Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ It can also be used in NodeJS to connect to MeshCore Companion devices over TCP/
- Web Browser
- BLE: [WebBleConnection()](./src/connection/web_ble_connection.js)
- USB/Serial: [WebSerialConnection()](./src/connection/web_serial_connection.js)
- WebSocket: [WebSocketConnection()](./src/connection/websocket_connection.js)
- NodeJS
- TCP/WiFi: [TCPConnection("host", "port")](./src/connection/tcp_connection.js)
- USB/Serial: [NodeJSSerialConnection("/dev/ttyUSB0")](./src/connection/nodejs_serial_connection.js)
Expand Down
13 changes: 11 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
<button v-if="!connection" @click="askForBleDevice" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Connect (BLE)
</button>
<button v-if="!connection" @click="askForWebSocketDevice" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Connect (WebSocket)
</button>
<button v-if="connection" @click="disconnect" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
Disconnect
</button>
Expand All @@ -55,7 +58,7 @@

<!-- actions -->
<div class="border bg-gray-50 rounded shadow">
<div class="p-3 space-x-1">
<div class="p-3 space-x-1 space-y-1">
<button @click="getSelfInfo" class="border border-gray-500 px-2 bg-gray-100 hover:bg-gray-200 rounded">
AppStart
</button>
Expand Down Expand Up @@ -198,6 +201,7 @@
import Constants from "./src/constants.js";
import WebSerialConnection from "./src/connection/web_serial_connection.js";
import WebBleConnection from "./src/connection/web_ble_connection.js";
import WebSocketConnection from "./src/connection/websocket_connection.js";
import BufferUtils from "./src/buffer_utils.js";
Vue.createApp({
data() {
Expand Down Expand Up @@ -228,6 +232,11 @@
// this.connection.on("tx", (data) => console.log("tx", data));
// this.connection.on("rx", (data) => console.log("rx", data));
},
async askForWebSocketDevice() {
this.connection = await WebSocketConnection.open();
this.connection.on("connected", () => this.onConnected());
this.connection.on("disconnected", () => this.onDisconnected());
},
async disconnect() {
if(this.connection){
await this.connection.close();
Expand Down Expand Up @@ -390,7 +399,7 @@
console.log("syncNextMessage", message);

// check if contact message
if(message.contactMessage){
if(message!= null && message.contactMessage){

// check if from cli contact
if(this.cliContact && BufferUtils.areBuffersEqual(message.contactMessage.pubKeyPrefix, this.cliContact.publicKey.subarray(0, 6))){
Expand Down
59 changes: 49 additions & 10 deletions src/connection/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class Connection extends EventEmitter {
data.writeByte(Constants.CommandCodes.AppStart);
data.writeByte(1); // appVer
data.writeBytes(new Uint8Array(6)); // reserved
data.writeString("test"); // appName
data.writeString("test client"); // appName
await this.sendToRadioFrame(data.toBytes());
}

Expand Down Expand Up @@ -334,6 +334,10 @@ class Connection extends EventEmitter {
this.onContactMsgRecvResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.ChannelMsgRecv){
this.onChannelMsgRecvResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.ContactMsgRecv3){
this.onContactMsgRecvResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.ChannelMsgRecv3){
this.onChannelMsgRecvResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.ContactsStart){
this.onContactsStartResponse(bufferReader);
} else if(responseCode === Constants.ResponseCodes.Contact){
Expand Down Expand Up @@ -635,23 +639,50 @@ class Connection extends EventEmitter {
}

onContactMsgRecvResponse(bufferReader) {
this.emit(Constants.ResponseCodes.ContactMsgRecv, {

if (Constants.SupportedCompanionProtocolVersion >= 3) {
this.emit(Constants.ResponseCodes.ContactMsgRecv3, {
snr: bufferReader.readByte() / 4.0,
reserved1: bufferReader.readByte(),
reserved2: bufferReader.readByte(),
pubKeyPrefix: bufferReader.readBytes(6),
pathLen: bufferReader.readByte(),
txtType: bufferReader.readByte(),
senderTimestamp: bufferReader.readUInt32LE(),
text: bufferReader.readString(),
});
}

onChannelMsgRecvResponse(bufferReader) {
this.emit(Constants.ResponseCodes.ChannelMsgRecv, {
channelIdx: bufferReader.readInt8(), // reserved (0 for now, ie. 'public')
pathLen: bufferReader.readByte(), // 0xFF if was sent direct, otherwise hop count for flood-mode
});
} else {
this.emit(Constants.ResponseCodes.ContactMsgRecv, {
pubKeyPrefix: bufferReader.readBytes(6),
pathLen: bufferReader.readByte(),
txtType: bufferReader.readByte(),
senderTimestamp: bufferReader.readUInt32LE(),
text: bufferReader.readString(),
});
});
}
}

onChannelMsgRecvResponse(bufferReader) {
if (Constants.SupportedCompanionProtocolVersion >= 3) {
this.emit(Constants.ResponseCodes.ChannelMsgRecv3, {
snr: bufferReader.readByte() / 4.0,
reserved1: bufferReader.readByte(),
reserved2: bufferReader.readByte(),
channelIdx: bufferReader.readInt8(), // reserved (0 for now, ie. 'public')
pathLen: bufferReader.readByte(), // 0xFF if was sent direct, otherwise hop count for flood-mode
txtType: bufferReader.readByte(),
senderTimestamp: bufferReader.readUInt32LE(),
text: bufferReader.readString(),
});
} else {
this.emit(Constants.ResponseCodes.ChannelMsgRecv, {
channelIdx: bufferReader.readInt8(), // reserved (0 for now, ie. 'public')
pathLen: bufferReader.readByte(), // 0xFF if was sent direct, otherwise hop count for flood-mode
txtType: bufferReader.readByte(),
senderTimestamp: bufferReader.readUInt32LE(),
text: bufferReader.readString(),
});
}
}

getSelfInfo(timeoutMillis = null) {
Expand Down Expand Up @@ -963,6 +994,8 @@ class Connection extends EventEmitter {
const onContactMessageReceived = (message) => {
this.off(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
this.off(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
this.off(Constants.ResponseCodes.ContactMsgRecv3, onContactMessageReceived);
this.off(Constants.ResponseCodes.ChannelMsgRecv3, onChannelMessageReceived);
this.off(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
resolve({
contactMessage: message,
Expand All @@ -973,6 +1006,8 @@ class Connection extends EventEmitter {
const onChannelMessageReceived = (message) => {
this.off(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
this.off(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
this.off(Constants.ResponseCodes.ContactMsgRecv3, onContactMessageReceived);
this.off(Constants.ResponseCodes.ChannelMsgRecv3, onChannelMessageReceived);
this.off(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
resolve({
channelMessage: message,
Expand All @@ -983,13 +1018,17 @@ class Connection extends EventEmitter {
const onNoMoreMessagesReceived = () => {
this.off(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
this.off(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
this.off(Constants.ResponseCodes.ContactMsgRecv3, onContactMessageReceived);
this.off(Constants.ResponseCodes.ChannelMsgRecv3, onChannelMessageReceived);
this.off(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);
resolve(null);
}

// listen for events
this.once(Constants.ResponseCodes.ContactMsgRecv, onContactMessageReceived);
this.once(Constants.ResponseCodes.ChannelMsgRecv, onChannelMessageReceived);
this.once(Constants.ResponseCodes.ContactMsgRecv3, onContactMessageReceived);
this.once(Constants.ResponseCodes.ChannelMsgRecv3, onChannelMessageReceived);
this.once(Constants.ResponseCodes.NoMoreMessages, onNoMoreMessagesReceived);

// sync next message from device
Expand Down
73 changes: 73 additions & 0 deletions src/connection/websocket_connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import Connection from "./connection.js";

// Easy way to test this is to run `websocat -s 5000`

class WebSocketConnection extends Connection {

constructor(url) {
super();

let self = this
this.isClosing = false

let socket = new WebSocket(url)
socket.onopen = (event) => {
//console.log("connected")
this.onConnected();
}
socket.onerror = function(error) {
//console.log(error);
self.isClosing = true
self.onDisconnected();
}
socket.onmessage = async function(event) {
//console.log('got message', event.data)
let buf = await event.data.arrayBuffer();
self.onFrameReceived(buf);
}
socket.onclose = function() {
if (!self.isClosing) {
self.onDisconnected();
}
}
this.socket = socket
}

static async open() {

// ensure browser supports web bluetooth
let url = prompt("Enter WebSocket URL", "ws://127.0.0.1:5000")
if (url.startsWith("ws://") || url.startsWith("wss://")) {
} else {
url = "ws://" + url
}

return new WebSocketConnection(url);
}

async close() {
try {
this.isClosing = true
this.socket.close()
} catch(e) {
//console.log("close error", e)
// ignore error when disconnecting
}
}

async write(bytes) {
try {
this.socket.send(bytes)
} catch(e) {
console.log("failed to write to ble device", e);
}
}

async sendToRadioFrame(frame) {
this.emit("tx", frame);
await this.write(frame);
}

}

export default WebSocketConnection;
4 changes: 3 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Constants {

static SupportedCompanionProtocolVersion = 1;
static SupportedCompanionProtocolVersion = 3;

static SerialFrameTypes = {
Incoming: 0x3e, // ">"
Expand Down Expand Up @@ -71,6 +71,8 @@ class Constants {
DeviceInfo: 13,
PrivateKey: 14,
Disabled: 15,
ContactMsgRecv3: 16,
ChannelMsgRecv3: 17,
ChannelInfo: 18,
SignStart: 19,
Signature: 20,
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import SerialConnection from "./connection/serial_connection.js";
import NodeJSSerialConnection from "./connection/nodejs_serial_connection.js";
import WebSerialConnection from "./connection/web_serial_connection.js";
import TCPConnection from "./connection/tcp_connection.js";
import WebSocketConnection from "./connection/websocket_connection.js";
import Constants from "./constants.js";
import Advert from "./advert.js";
import Packet from "./packet.js";
Expand All @@ -17,6 +18,7 @@ export {
NodeJSSerialConnection,
WebSerialConnection,
TCPConnection,
WebSocketConnection,
Constants,
Advert,
Packet,
Expand Down