Skip to content

Commit

Permalink
bus
Browse files Browse the repository at this point in the history
  • Loading branch information
milesstoetzner authored Sep 21, 2023
1 parent 2d15876 commit e7f7e8f
Show file tree
Hide file tree
Showing 22 changed files with 398 additions and 76 deletions.
54 changes: 47 additions & 7 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
[![Release](https://github.com/milesstoetzner/stoetzms-can2x/actions/workflows/release.yaml/badge.svg)](https://github.com/milesstoetzner/stoetzms-can2x/actions/workflows/release.yaml)
[![Codacy Quality Badge](https://app.codacy.com/project/badge/Grade/8b0bd18dbdc844e4947b21b4e7bb5d9f)](https://app.codacy.com/gh/milesstoetzner/stoetzms-can2x/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[![Codacy Coverage Badge](https://app.codacy.com/project/badge/Coverage/8b0bd18dbdc844e4947b21b4e7bb5d9f)](https://app.codacy.com/gh/milesstoetzner/stoetzms-can2x/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](https://vintner.opentosca.org/code-of-conduct)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-blue.svg)](https://vintner.opentosca.org/code-of-conduct)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Platforms](https://img.shields.io/badge/Platforms-Linux-blue.svg)](https://vintner.opentosca.org)
[![npm](https://img.shields.io/badge/npm-can2x-blue)](https://www.npmjs.com/package/can2x)

`can2x` is a simple utility for connecting a CAN bus bidirectional with another CAN bus over the network using common web protocols, such as HTTP, MQTT, Socket.IO, and WebSockets.
`can2x` is a simple utility for connecting a CAN bus bidirectional with one or multiple CAN busses over the network using common web protocols, such as HTTP, MQTT, Socket.IO, and WebSockets.

## Overview

Expand All @@ -20,6 +20,7 @@ A source, such as a CAN bus in a first computing environment, forwards the CAN m
This target then acts as a source and forwards the CAN message to another target, such as a CAN bus connected to the second computing environment.
It is also possible to have a arbitrary long chains of different of such bridges.
Also, most bridges are bidirectional, thus, CAN message are also bridged backward.
In addition, `can2x bus` is able to connect multiple `can2x bridges`.

## Installation

Expand Down Expand Up @@ -81,15 +82,15 @@ can2x bridge start --source can --target socketio --target-endpoint http://<TARG

Then, on the source host, send a message to the vCAN.

```
```shell
sudo apt-get update -y
sudo apt-get install can-utils -y
cansend can2x 01a#11223344AABBCCDD
```

On the target host, we can observe the CAN message.

```
```shell
can2x 01A [8] 11 22 33 44 AA BB CC DD
```

Expand All @@ -102,7 +103,7 @@ can2x 01A [8] 11 22 33 44 AA BB CC DD

The following command starts a can2x bridge.

```
```shell
can2x bridge start [options]
```

Expand Down Expand Up @@ -130,11 +131,29 @@ The following options are supported.
| `--target-file` | string | none | false | |
| `--target-bidirectional` | boolean | `true` | false | |

### Bus Start

The following command starts a can2x bus.

```shell
can2x bus start [options]
```

The following options are supported.

| Option | Type | Default | Required | Description |
|-----------|--------------|--------------|----------|-------------|
| `--bus` | `socketio` | `socketio` | false | |
| `--port` | number | `3000` | false | |
| `--host` | string | `localhost` | false | |
| `--event` | string | `can2x` | false | |


### vCAN Start

The following command starts a vCAN using SocketCAN.

```
```shell
can2x vcan start [options]
```

Expand All @@ -148,7 +167,7 @@ The following options are supported.

The following command stops a vCAN using SocketCAN.

```
```shell
can2x vcan stop [options]
```

Expand Down Expand Up @@ -316,6 +335,23 @@ The following options are supported.
| `--target-endpoint` | string | none | true | |
| `--target-bidirectional` | boolean | `true` | false | |


## Busses

`can2x` supports the following busses.

### Socket.IO

`can2x` supports a `socketio` bridge, i.e., `--bus socketio`.
The following options are supported.

| Option | Type | Default | Required | Description |
|-----------|--------------|--------------|----------|-------------|
| `--port` | number | `3000` | false | |
| `--host` | string | `localhost` | false | |
| `--event` | string | `can2x` | false | |


## Limitations

- security aspects, such as encryption, authentication, and authorization, are not supported
Expand Down Expand Up @@ -345,6 +381,10 @@ license-checker --production --summary --onlyAllow "MIT;Apache-2.0;Python-2.0;BS
└─ Python-2.0: 1
```

## Keywords

http, mqtt, can, bridge, ws, websocket, socketio, vcan, can2http, can2mqtt, can2socketio, can2x, can2ws, virtual

## Acknowledgements

This project is s partially funded by the [German Federal Ministry for Economic Affairs and Climate Action (BMWK)](https://www.bmwk.de/Navigation/EN/Home/home.html) as part of the [Software-Defined Car (SofDCar)](https://sofdcar.de) project (19S21002).
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# can2x

`can2x` is a simple utility for connecting a CAN bus bidirectional with another CAN bus over the network using common web protocols, such as HTTP, MQTT, Socket.IO, and WebSockets.
`can2x` is a simple utility for connecting a CAN bus bidirectional with one or multiple CAN busses over the network using common web protocols, such as HTTP, MQTT, Socket.IO, and WebSockets.
Please check out our [repository](https://github.com/milesstoetzner/stoetzms-can2x).
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "can2x",
"version": "0.1.6",
"description": "can2x is a simple utility for connecting a CAN bus bidirectional with another CAN bus over the network using common web protocols, such as HTTP, MQTT, Socket.IO, and WebSockets.",
"description": "can2x is a simple utility for connecting a CAN bus bidirectional with one or multiple CAN busses over the network using common web protocols, such as HTTP, MQTT, Socket.IO, and WebSockets.",
"repository": "https://github.com/milesstoetzner/can2x",
"homepage": "https://can2x.stoetz.ms",
"author": {
Expand All @@ -23,7 +23,8 @@
"can2mqtt",
"can2socketio",
"can2x",
"can2ws"
"can2ws",
"virtual"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
17 changes: 17 additions & 0 deletions src/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {startBus} from '#/actions/start-bus'
import {startVCAN} from '#/actions/start-vcan'
import {stopVCAN} from '#/actions/stop-vcan'
import {startBridge} from './start-bridge'

export default {
bridge: {
start: startBridge,
},
bus: {
start: startBus,
},
vcan: {
start: startVCAN,
stop: stopVCAN,
},
}
20 changes: 0 additions & 20 deletions src/core/actions.ts → src/actions/start-bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {SocketIOTarget} from '#/target/socketio'
import {WSTarget} from '#/target/ws'
import * as assert from '#assert'
import {Bridge} from '#core/bridge'
import {VCAN, VCANOptions} from '#core/vcan'
import std from '#std'

export type BridgeOptions = {
Expand Down Expand Up @@ -50,25 +49,6 @@ export async function startBridge(options: BridgeOptions) {
await bridge.start()
return bridge
}

export async function startVCAN(options: VCANOptions) {
std.log('can2x vcan create', {options})

std.log('creating vcan')
const vcan = new VCAN(options)
await vcan.start()
return vcan
}

export async function stopVCAN(options: VCANOptions) {
std.log('can2x vcan delete', {options})

std.log('deleting vcan')
const vcan = new VCAN(options)
await vcan.stop()
return vcan
}

function createSource(options: BridgeOptions) {
if (options.source === 'can')
return new CANSource({
Expand Down
31 changes: 31 additions & 0 deletions src/actions/start-bus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {SocketIOBus} from '#/bus/socketio'
import std from '#std'

export type BusOptions = {
bus?: string
port?: number
host?: string
event?: string
}

export async function startBus(options: BusOptions) {
std.log('can2x bus', {options})

const bus = createBus(options)

std.log('starting bus')
await bus.start()
await bus.ready()
return bus
}

function createBus(options: BusOptions) {
if (options.bus === 'socketio')
return new SocketIOBus({
port: options.port ? Number(options.port) : 3000,
host: options.host ?? 'localhost',
event: options.event ?? 'can2x',
})

throw new Error(`Bus of type "${options.bus}" unknown`)
}
11 changes: 11 additions & 0 deletions src/actions/start-vcan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {VCAN, VCANOptions} from '#core/vcan'
import std from '#std'

export async function startVCAN(options: VCANOptions) {
std.log('can2x vcan create', {options})

std.log('creating vcan')
const vcan = new VCAN(options)
await vcan.start()
return vcan
}
11 changes: 11 additions & 0 deletions src/actions/stop-vcan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {VCAN, VCANOptions} from '#core/vcan'
import std from '#std'

export async function stopVCAN(options: VCANOptions) {
std.log('can2x vcan delete', {options})

std.log('deleting vcan')
const vcan = new VCAN(options)
await vcan.stop()
return vcan
}
17 changes: 17 additions & 0 deletions src/bus/bus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import * as utils from '#utils'

export default abstract class Bus {
protected readyPromise

protected constructor() {
this.readyPromise = utils.createDecomposedPromise()
}

abstract start(): Promise<void>

abstract stop(): Promise<void>

async ready() {
return this.readyPromise.promise
}
}
65 changes: 65 additions & 0 deletions src/bus/socketio.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Bus from '#/bus/bus'
import * as check from '#check'
import {JSONMessage} from '#core/message'
import std from '#std'
import http from 'http'
import SocketIO from 'socket.io'

export type SocketIOBusOptions = {
port: number
host: string
event: string
}

export class SocketIOBus extends Bus {
io?: SocketIO.Server
server?: http.Server
options: SocketIOBusOptions

constructor(options: SocketIOBusOptions) {
super()
this.options = options
}

async start() {
std.log('starting socketio bus')

this.server = http.createServer()

this.io = new SocketIO.Server(this.server)
this.io.on('connection', socket => {
std.log(`socketio client connected`, {id: socket.id})

socket.on(this.options.event, (message: JSONMessage) => {
std.log('socketio source received', {message})
socket.broadcast.emit(this.options.event, message)
})
})

this.server.listen({port: this.options.port, host: this.options.host}, () => {
std.log(`socketio bus running on "http://${this.options.host}:${this.options.port}"`)
this.readyPromise.resolve()
})

this.server.on('error', error => {
std.log('socketio bus error', {error})
})
}

async stop() {
std.log('stopping socketio bus')
await this.stopServer()
std.log('socketio bus stopped')
}

private async stopServer() {
if (check.isUndefined(this.server)) return std.log('socketio http server not defined')
const server = this.server
return new Promise<void>(resolve => {
server.close(error => {
if (check.isDefined(error)) std.log(error)
return resolve()
})
})
}
}
Loading

0 comments on commit e7f7e8f

Please sign in to comment.