Browse Source

Add node-transport lib (#703)

* feat: add node transport

* updated readme

* Update packages/transport-node/README.md

Co-authored-by: Copilot <[email protected]>

---------

Co-authored-by: Copilot <[email protected]>
pull/705/head
Dan Ditomaso 11 months ago
committed by GitHub
parent
commit
66b839742a
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      .gitignore
  2. 1
      deno.json
  3. 28
      packages/transport-node/README.md
  4. 8
      packages/transport-node/deno.json
  5. 1
      packages/transport-node/mod.ts
  6. 77
      packages/transport-node/src/transport.ts

1
.gitignore

@ -6,3 +6,4 @@ stats.html
dev-dist
__screenshots__*
*.diff
npm/

1
deno.json

@ -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"

28
packages/transport-node/README.md

@ -0,0 +1,28 @@
# @meshtastic/transport-node
[![JSR](https://jsr.io/badges/@meshtastic/transport-node)](https://jsr.io/@meshtastic/transport-node)
[![CI](https://img.shields.io/github/actions/workflow/status/meshtastic/js/ci.yml?branch=master&label=actions&logo=github&color=yellow)](https://github.com/meshtastic/js/actions/workflows/ci.yml)
[![CLA assistant](https://cla-assistant.io/readme/badge/meshtastic/meshtastic.js)](https://cla-assistant.io/meshtastic/meshtastic.js)
[![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/)
[![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](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
![Alt](https://repobeats.axiom.co/api/embed/5330641586e92a2ec84676fedb98f6d4a7b25d69.svg "Repobeats analytics image")

8
packages/transport-node/deno.json

@ -0,0 +1,8 @@
{
"name": "@meshtastic/transport-node",
"version": "0.0.1",
"description": "NodeJS-specific transport layer for Meshtastic web applications.",
"exports": {
".": "./mod.ts"
}
}

1
packages/transport-node/mod.ts

@ -0,0 +1 @@
export { TransportNode } from "./src/transport.ts";

77
packages/transport-node/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;
}
}
Loading…
Cancel
Save