Add node-transport lib (#703)
* feat: add node transport * updated readme * Update packages/transport-node/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
+2
-1
@@ -5,4 +5,5 @@ stats.html
|
||||
.vite
|
||||
dev-dist
|
||||
__screenshots__*
|
||||
*.diff
|
||||
*.diff
|
||||
npm/
|
||||
@@ -3,6 +3,7 @@
|
||||
"./packages/web",
|
||||
"./packages/core",
|
||||
"./packages/transport-deno",
|
||||
"./packages/transport-node",
|
||||
"./packages/transport-http",
|
||||
"./packages/transport-web-bluetooth",
|
||||
"./packages/transport-web-serial"
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# @meshtastic/transport-node
|
||||
|
||||
[](https://jsr.io/@meshtastic/transport-node)
|
||||
[](https://github.com/meshtastic/js/actions/workflows/ci.yml)
|
||||
[](https://cla-assistant.io/meshtastic/meshtastic.js)
|
||||
[](https://opencollective.com/meshtastic/)
|
||||
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
||||
|
||||
## Overview
|
||||
|
||||
`@meshtastic/transport-node` Provides TCP transport (Node) for Meshtastic
|
||||
devices. Installation instructions are available at
|
||||
[JSR](https://jsr.io/@meshtastic/transport-node)
|
||||
[NPM](https://www.npmjs.com/package/@meshtastic/transport-node)
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { MeshDevice } from "@meshtastic/core";
|
||||
import { TransportNode } from "@meshtastic/transport-node";
|
||||
|
||||
const transport = await TransportNode.create("10.10.0.57");
|
||||
const device = new MeshDevice(transport);
|
||||
```
|
||||
|
||||
## Stats
|
||||
|
||||

|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "@meshtastic/transport-node",
|
||||
"version": "0.0.1",
|
||||
"description": "NodeJS-specific transport layer for Meshtastic web applications.",
|
||||
"exports": {
|
||||
".": "./mod.ts"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { TransportNode } from "./src/transport.ts";
|
||||
@@ -0,0 +1,77 @@
|
||||
import { Utils } from "@meshtastic/core";
|
||||
import type { Types } from "@meshtastic/core";
|
||||
import { Socket } from "node:net";
|
||||
import { Readable, Writable } from "node:stream";
|
||||
|
||||
export class TransportNode implements Types.Transport {
|
||||
private readonly _toDevice: WritableStream<Uint8Array>;
|
||||
private readonly _fromDevice: ReadableStream<Types.DeviceOutput>;
|
||||
|
||||
/**
|
||||
* Creates and connects a new TransportNode instance.
|
||||
* @param hostname - The IP address or hostname of the Meshtastic device.
|
||||
* @param port - The port number for the TCP connection (defaults to 4403).
|
||||
* @returns A promise that resolves with a connected TransportNode instance.
|
||||
*/
|
||||
public static create(hostname: string, port = 4403): Promise<TransportNode> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const socket = new Socket();
|
||||
|
||||
const onError = (err: Error) => {
|
||||
socket.destroy();
|
||||
reject(err);
|
||||
};
|
||||
|
||||
socket.once("error", onError);
|
||||
|
||||
socket.connect(port, hostname, () => {
|
||||
socket.removeListener("error", onError);
|
||||
resolve(new TransportNode(socket));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new TransportNode.
|
||||
* @param connection - An active Node.js net.Socket connection.
|
||||
*/
|
||||
constructor(connection: Socket) {
|
||||
connection.on("error", (err) => {
|
||||
console.error("Socket connection error:", err);
|
||||
});
|
||||
|
||||
const fromDeviceSource = Readable.toWeb(connection) as ReadableStream<
|
||||
Uint8Array
|
||||
>;
|
||||
this._fromDevice = fromDeviceSource.pipeThrough(Utils.fromDeviceStream());
|
||||
|
||||
// Stream for data going FROM the application TO the Meshtastic device.
|
||||
const toDeviceTransform = new TransformStream<Uint8Array, Uint8Array>();
|
||||
this._toDevice = toDeviceTransform.writable;
|
||||
|
||||
// The readable end of the transform is then piped to the Node.js socket.
|
||||
// A similar assertion is needed here because `Writable.toWeb` also returns
|
||||
// a generically typed stream (`WritableStream<any>`).
|
||||
toDeviceTransform.readable.pipeTo(
|
||||
Writable.toWeb(connection) as WritableStream<Uint8Array>,
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error("Error piping data to socket:", err);
|
||||
connection.destroy(err as Error);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The WritableStream to send data to the Meshtastic device.
|
||||
*/
|
||||
public get toDevice(): WritableStream<Uint8Array> {
|
||||
return this._toDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ReadableStream to receive data from the Meshtastic device.
|
||||
*/
|
||||
public get fromDevice(): ReadableStream<Types.DeviceOutput> {
|
||||
return this._fromDevice;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user