Execute oxfmt (#1166)
Ran pnpm oxfmt . This should get the web repo aligned so that we can better enforce oxfmt going forward.
This commit is contained in:
@@ -18,7 +18,14 @@ describe("MeshClient.progress", () => {
|
||||
expect(client.progress.value.phase).toBe("configuring");
|
||||
expect(client.progress.value).toEqual({
|
||||
phase: "configuring",
|
||||
received: { config: 0, modules: 0, channels: 0, nodes: 0, myInfo: false, metadata: false },
|
||||
received: {
|
||||
config: 0,
|
||||
modules: 0,
|
||||
channels: 0,
|
||||
nodes: 0,
|
||||
myInfo: false,
|
||||
metadata: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,14 +34,25 @@ describe("MeshClient.progress", () => {
|
||||
const client = new MeshClient({ transport });
|
||||
void client.configure();
|
||||
|
||||
client.events.onConfigPacket.dispatch(create(Protobuf.Config.ConfigSchema, {}));
|
||||
client.events.onConfigPacket.dispatch(create(Protobuf.Config.ConfigSchema, {}));
|
||||
client.events.onChannelPacket.dispatch(create(Protobuf.Channel.ChannelSchema, {}));
|
||||
client.events.onNodeInfoPacket.dispatch(create(Protobuf.Mesh.NodeInfoSchema, {}));
|
||||
client.events.onMyNodeInfo.dispatch(create(Protobuf.Mesh.MyNodeInfoSchema, {}));
|
||||
client.events.onConfigPacket.dispatch(
|
||||
create(Protobuf.Config.ConfigSchema, {}),
|
||||
);
|
||||
client.events.onConfigPacket.dispatch(
|
||||
create(Protobuf.Config.ConfigSchema, {}),
|
||||
);
|
||||
client.events.onChannelPacket.dispatch(
|
||||
create(Protobuf.Channel.ChannelSchema, {}),
|
||||
);
|
||||
client.events.onNodeInfoPacket.dispatch(
|
||||
create(Protobuf.Mesh.NodeInfoSchema, {}),
|
||||
);
|
||||
client.events.onMyNodeInfo.dispatch(
|
||||
create(Protobuf.Mesh.MyNodeInfoSchema, {}),
|
||||
);
|
||||
|
||||
const cur = client.progress.value;
|
||||
if (cur.phase !== "configuring") throw new Error("expected configuring phase");
|
||||
if (cur.phase !== "configuring")
|
||||
throw new Error("expected configuring phase");
|
||||
expect(cur.received.config).toBe(2);
|
||||
expect(cur.received.channels).toBe(1);
|
||||
expect(cur.received.nodes).toBe(1);
|
||||
@@ -46,7 +64,9 @@ describe("MeshClient.progress", () => {
|
||||
const { transport } = createFakeTransport();
|
||||
const client = new MeshClient({ transport });
|
||||
void client.configure();
|
||||
client.events.onConfigPacket.dispatch(create(Protobuf.Config.ConfigSchema, {}));
|
||||
client.events.onConfigPacket.dispatch(
|
||||
create(Protobuf.Config.ConfigSchema, {}),
|
||||
);
|
||||
client.events.onConfigComplete.dispatch(0);
|
||||
|
||||
const cur = client.progress.value;
|
||||
@@ -59,7 +79,9 @@ describe("MeshClient.progress", () => {
|
||||
const { transport } = createFakeTransport();
|
||||
const client = new MeshClient({ transport });
|
||||
// not calling configure() — phase is idle
|
||||
client.events.onConfigPacket.dispatch(create(Protobuf.Config.ConfigSchema, {}));
|
||||
client.events.onConfigPacket.dispatch(
|
||||
create(Protobuf.Config.ConfigSchema, {}),
|
||||
);
|
||||
expect(client.progress.value.phase).toBe("idle");
|
||||
});
|
||||
|
||||
@@ -67,12 +89,21 @@ describe("MeshClient.progress", () => {
|
||||
const { transport } = createFakeTransport();
|
||||
const client = new MeshClient({ transport });
|
||||
void client.configure();
|
||||
client.events.onConfigPacket.dispatch(create(Protobuf.Config.ConfigSchema, {}));
|
||||
client.events.onConfigPacket.dispatch(
|
||||
create(Protobuf.Config.ConfigSchema, {}),
|
||||
);
|
||||
client.events.onConfigComplete.dispatch(0);
|
||||
void client.configure();
|
||||
expect(client.progress.value).toEqual({
|
||||
phase: "configuring",
|
||||
received: { config: 0, modules: 0, channels: 0, nodes: 0, myInfo: false, metadata: false },
|
||||
received: {
|
||||
config: 0,
|
||||
modules: 0,
|
||||
channels: 0,
|
||||
nodes: 0,
|
||||
myInfo: false,
|
||||
metadata: false,
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,12 @@ import { Queue } from "../queue/Queue.ts";
|
||||
import { createStore, type ReadonlySignal } from "../signals/createStore.ts";
|
||||
import type { Transport } from "../transport/Transport.ts";
|
||||
import { DeviceStatusEnum } from "../transport/Transport.ts";
|
||||
import { ChannelNumber, type Destination, Emitter, type PacketMetadata } from "../types.ts";
|
||||
import {
|
||||
ChannelNumber,
|
||||
type Destination,
|
||||
Emitter,
|
||||
type PacketMetadata,
|
||||
} from "../types.ts";
|
||||
import { Xmodem } from "../xmodem/Xmodem.ts";
|
||||
import { ChatClient } from "../../features/chat/index.ts";
|
||||
import { ChannelsClient } from "../../features/channels/index.ts";
|
||||
@@ -101,7 +106,9 @@ export class MeshClient {
|
||||
* sends `configCompleteId`.
|
||||
*/
|
||||
public readonly progress: ReadonlySignal<ConnectionProgress>;
|
||||
private readonly progressStore = createStore<ConnectionProgress>({ phase: "idle" });
|
||||
private readonly progressStore = createStore<ConnectionProgress>({
|
||||
phase: "idle",
|
||||
});
|
||||
|
||||
private _heartbeatIntervalId: ReturnType<typeof setInterval> | undefined;
|
||||
|
||||
@@ -153,7 +160,10 @@ export class MeshClient {
|
||||
}
|
||||
|
||||
public configure(): Promise<number> {
|
||||
this.log.debug(Emitter[Emitter.Configure], "⚙️ Requesting device configuration");
|
||||
this.log.debug(
|
||||
Emitter[Emitter.Configure],
|
||||
"⚙️ Requesting device configuration",
|
||||
);
|
||||
this.updateDeviceStatus(DeviceStatusEnum.DeviceConfiguring);
|
||||
this.progressStore.write.value = {
|
||||
phase: "configuring",
|
||||
@@ -164,12 +174,14 @@ export class MeshClient {
|
||||
payloadVariant: { case: "wantConfigId", value: this.configId },
|
||||
});
|
||||
|
||||
return this.sendRaw(toBinary(Protobuf.Mesh.ToRadioSchema, toRadio)).catch((e) => {
|
||||
if (this.device.status.value === DeviceStatusEnum.DeviceDisconnected) {
|
||||
throw new Error("Device connection lost");
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
return this.sendRaw(toBinary(Protobuf.Mesh.ToRadioSchema, toRadio)).catch(
|
||||
(e) => {
|
||||
if (this.device.status.value === DeviceStatusEnum.DeviceDisconnected) {
|
||||
throw new Error("Device connection lost");
|
||||
}
|
||||
throw e;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,7 +198,10 @@ export class MeshClient {
|
||||
if (cur.phase !== "configuring") return;
|
||||
const next: ConnectionProgressCounters = {
|
||||
...cur.received,
|
||||
[field]: typeof cur.received[field] === "number" ? cur.received[field] + 1 : true,
|
||||
[field]:
|
||||
typeof cur.received[field] === "number"
|
||||
? cur.received[field] + 1
|
||||
: true,
|
||||
} as ConnectionProgressCounters;
|
||||
this.progressStore.write.value = { phase: "configuring", received: next };
|
||||
};
|
||||
@@ -200,7 +215,8 @@ export class MeshClient {
|
||||
|
||||
this.events.onConfigComplete.subscribe(() => {
|
||||
const cur = this.progressStore.read.value;
|
||||
const received = cur.phase === "configuring" ? cur.received : { ...EMPTY_COUNTERS };
|
||||
const received =
|
||||
cur.phase === "configuring" ? cur.received : { ...EMPTY_COUNTERS };
|
||||
this.progressStore.write.value = { phase: "configured", received };
|
||||
});
|
||||
}
|
||||
@@ -219,7 +235,10 @@ export class MeshClient {
|
||||
}
|
||||
this._heartbeatIntervalId = setInterval(() => {
|
||||
this.heartbeat().catch((err: Error) => {
|
||||
this.log.error(Emitter[Emitter.Ping], `⚠️ Unable to send heartbeat: ${err.message}`);
|
||||
this.log.error(
|
||||
Emitter[Emitter.Ping],
|
||||
`⚠️ Unable to send heartbeat: ${err.message}`,
|
||||
);
|
||||
});
|
||||
}, interval);
|
||||
}
|
||||
@@ -286,10 +305,16 @@ export class MeshClient {
|
||||
meshPacket.rxTime = Math.trunc(Date.now() / 1000);
|
||||
this.events.onMeshPacket.dispatch(meshPacket);
|
||||
}
|
||||
return await this.sendRaw(toBinary(Protobuf.Mesh.ToRadioSchema, toRadioMessage), meshPacket.id);
|
||||
return await this.sendRaw(
|
||||
toBinary(Protobuf.Mesh.ToRadioSchema, toRadioMessage),
|
||||
meshPacket.id,
|
||||
);
|
||||
}
|
||||
|
||||
public async sendRaw(toRadio: Uint8Array, id: number = generatePacketId()): Promise<number> {
|
||||
public async sendRaw(
|
||||
toRadio: Uint8Array,
|
||||
id: number = generatePacketId(),
|
||||
): Promise<number> {
|
||||
if (toRadio.length > 512) {
|
||||
throw new PacketTooLargeError(toRadio.length);
|
||||
}
|
||||
|
||||
@@ -11,66 +11,110 @@ import type { LogEventPacket, PacketMetadata } from "../types.ts";
|
||||
*/
|
||||
export class EventBus {
|
||||
public readonly onLogEvent = new SimpleEventDispatcher<LogEventPacket>();
|
||||
public readonly onFromRadio = new SimpleEventDispatcher<Protobuf.Mesh.FromRadio>();
|
||||
public readonly onMeshPacket = new SimpleEventDispatcher<Protobuf.Mesh.MeshPacket>();
|
||||
public readonly onMyNodeInfo = new SimpleEventDispatcher<Protobuf.Mesh.MyNodeInfo>();
|
||||
public readonly onNodeInfoPacket = new SimpleEventDispatcher<Protobuf.Mesh.NodeInfo>();
|
||||
public readonly onChannelPacket = new SimpleEventDispatcher<Protobuf.Channel.Channel>();
|
||||
public readonly onConfigPacket = new SimpleEventDispatcher<Protobuf.Config.Config>();
|
||||
public readonly onFromRadio =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.FromRadio>();
|
||||
public readonly onMeshPacket =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.MeshPacket>();
|
||||
public readonly onMyNodeInfo =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.MyNodeInfo>();
|
||||
public readonly onNodeInfoPacket =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.NodeInfo>();
|
||||
public readonly onChannelPacket =
|
||||
new SimpleEventDispatcher<Protobuf.Channel.Channel>();
|
||||
public readonly onConfigPacket =
|
||||
new SimpleEventDispatcher<Protobuf.Config.Config>();
|
||||
public readonly onModuleConfigPacket =
|
||||
new SimpleEventDispatcher<Protobuf.ModuleConfig.ModuleConfig>();
|
||||
public readonly onAtakPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onMessagePacket = new SimpleEventDispatcher<PacketMetadata<string>>();
|
||||
public readonly onAtakPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onMessagePacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<string>
|
||||
>();
|
||||
public readonly onRemoteHardwarePacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.RemoteHardware.HardwareMessage>
|
||||
>();
|
||||
public readonly onPositionPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.Position>
|
||||
>();
|
||||
public readonly onUserPacket = new SimpleEventDispatcher<PacketMetadata<Protobuf.Mesh.User>>();
|
||||
public readonly onUserPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.User>
|
||||
>();
|
||||
public readonly onRoutingPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.Routing>
|
||||
>();
|
||||
public readonly onDeviceMetadataPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.DeviceMetadata>
|
||||
>();
|
||||
public readonly onCannedMessageModulePacket = new SimpleEventDispatcher<PacketMetadata<string>>();
|
||||
public readonly onCannedMessageModulePacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<string>
|
||||
>();
|
||||
public readonly onWaypointPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.Waypoint>
|
||||
>();
|
||||
public readonly onAudioPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onDetectionSensorPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onPingPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onIpTunnelPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onAudioPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onDetectionSensorPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onPingPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onIpTunnelPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onPaxcounterPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.PaxCount.Paxcount>
|
||||
>();
|
||||
public readonly onSerialPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onStoreForwardPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onRangeTestPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onSerialPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onStoreForwardPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onRangeTestPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onTelemetryPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Telemetry.Telemetry>
|
||||
>();
|
||||
public readonly onZpsPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onSimulatorPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onZpsPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onSimulatorPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onTraceRoutePacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.RouteDiscovery>
|
||||
>();
|
||||
public readonly onNeighborInfoPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Protobuf.Mesh.NeighborInfo>
|
||||
>();
|
||||
public readonly onAtakPluginPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onMapReportPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onPrivatePacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onAtakForwarderPacket = new SimpleEventDispatcher<PacketMetadata<Uint8Array>>();
|
||||
public readonly onAtakPluginPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onMapReportPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onPrivatePacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onAtakForwarderPacket = new SimpleEventDispatcher<
|
||||
PacketMetadata<Uint8Array>
|
||||
>();
|
||||
public readonly onClientNotificationPacket =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.ClientNotification>();
|
||||
public readonly onDeviceStatus = new SimpleEventDispatcher<DeviceStatusEnum>();
|
||||
public readonly onLogRecord = new SimpleEventDispatcher<Protobuf.Mesh.LogRecord>();
|
||||
public readonly onDeviceStatus =
|
||||
new SimpleEventDispatcher<DeviceStatusEnum>();
|
||||
public readonly onLogRecord =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.LogRecord>();
|
||||
public readonly onMeshHeartbeat = new SimpleEventDispatcher<Date>();
|
||||
public readonly onDeviceDebugLog = new SimpleEventDispatcher<Uint8Array>();
|
||||
public readonly onPendingSettingsChange = new SimpleEventDispatcher<boolean>();
|
||||
public readonly onQueueStatus = new SimpleEventDispatcher<Protobuf.Mesh.QueueStatus>();
|
||||
public readonly onPendingSettingsChange =
|
||||
new SimpleEventDispatcher<boolean>();
|
||||
public readonly onQueueStatus =
|
||||
new SimpleEventDispatcher<Protobuf.Mesh.QueueStatus>();
|
||||
public readonly onConfigComplete = new SimpleEventDispatcher<number>();
|
||||
public readonly onRebooted = new SimpleEventDispatcher<void>();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Logger } from "tslog";
|
||||
|
||||
const prettyLogTemplate = "{{hh}}:{{MM}}:{{ss}}:{{ms}}\t{{logLevelName}}\t[{{name}}]\t";
|
||||
const prettyLogTemplate =
|
||||
"{{hh}}:{{MM}}:{{ss}}:{{ms}}\t{{logLevelName}}\t[{{name}}]\t";
|
||||
|
||||
/**
|
||||
* Minimum log level. Default is `info` (3). Lifts to `debug` (2) when:
|
||||
@@ -15,8 +16,11 @@ function defaultMinLevel(): number {
|
||||
try {
|
||||
if (
|
||||
typeof globalThis !== "undefined" &&
|
||||
typeof (globalThis as { localStorage?: Storage }).localStorage !== "undefined" &&
|
||||
(globalThis as { localStorage: Storage }).localStorage.getItem("mesh-debug") === "1"
|
||||
typeof (globalThis as { localStorage?: Storage }).localStorage !==
|
||||
"undefined" &&
|
||||
(globalThis as { localStorage: Storage }).localStorage.getItem(
|
||||
"mesh-debug",
|
||||
) === "1"
|
||||
) {
|
||||
return 2;
|
||||
}
|
||||
@@ -25,15 +29,18 @@ function defaultMinLevel(): number {
|
||||
}
|
||||
if (
|
||||
typeof globalThis !== "undefined" &&
|
||||
(globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env
|
||||
?.MESH_DEBUG === "1"
|
||||
(globalThis as { process?: { env?: Record<string, string | undefined> } })
|
||||
.process?.env?.MESH_DEBUG === "1"
|
||||
) {
|
||||
return 2;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
export function createLogger(name: string, options?: { minLevel?: number }): Logger<unknown> {
|
||||
export function createLogger(
|
||||
name: string,
|
||||
options?: { minLevel?: number },
|
||||
): Logger<unknown> {
|
||||
return new Logger({
|
||||
name,
|
||||
prettyLogTemplate,
|
||||
|
||||
@@ -48,9 +48,16 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
case "packet": {
|
||||
let decodedMessage: Protobuf.Mesh.FromRadio;
|
||||
try {
|
||||
decodedMessage = fromBinary(Protobuf.Mesh.FromRadioSchema, chunk.data);
|
||||
decodedMessage = fromBinary(
|
||||
Protobuf.Mesh.FromRadioSchema,
|
||||
chunk.data,
|
||||
);
|
||||
} catch (e) {
|
||||
sink.log.error(Emitter[Emitter.HandleFromRadio], "⚠️ Received undecodable packet", e);
|
||||
sink.log.error(
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
"⚠️ Received undecodable packet",
|
||||
e,
|
||||
);
|
||||
break;
|
||||
}
|
||||
sink.events.onFromRadio.dispatch(decodedMessage);
|
||||
@@ -69,7 +76,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
break;
|
||||
}
|
||||
case "myInfo": {
|
||||
sink.events.onMyNodeInfo.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onMyNodeInfo.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
sink.log.info(
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
"📱 Received Node info for this device",
|
||||
@@ -81,7 +90,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
`📱 Received Node Info packet for node: ${decodedMessage.payloadVariant.value.num}`,
|
||||
);
|
||||
sink.events.onNodeInfoPacket.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onNodeInfoPacket.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
|
||||
if (decodedMessage.payloadVariant.value.position) {
|
||||
sink.events.onPositionPacket.dispatch({
|
||||
@@ -120,12 +131,19 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
"⚠️ Received Config packet of variant: UNK",
|
||||
);
|
||||
}
|
||||
sink.events.onConfigPacket.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onConfigPacket.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "logRecord": {
|
||||
sink.log.trace(Emitter[Emitter.HandleFromRadio], "Received onLogRecord");
|
||||
sink.events.onLogRecord.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.log.trace(
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
"Received onLogRecord",
|
||||
);
|
||||
sink.events.onLogRecord.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "configCompleteId": {
|
||||
@@ -133,7 +151,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
`⚙️ Received config complete id: ${decodedMessage.payloadVariant.value}`,
|
||||
);
|
||||
sink.events.onConfigComplete.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onConfigComplete.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
if (decodedMessage.payloadVariant.value === sink.configId) {
|
||||
sink.log.info(
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
@@ -162,7 +182,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
"⚠️ Received Module Config packet of variant: UNK",
|
||||
);
|
||||
}
|
||||
sink.events.onModuleConfigPacket.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onModuleConfigPacket.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "channel": {
|
||||
@@ -170,7 +192,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
`🔐 Received Channel: ${decodedMessage.payloadVariant.value.index}`,
|
||||
);
|
||||
sink.events.onChannelPacket.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onChannelPacket.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "queueStatus": {
|
||||
@@ -178,7 +202,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
`🚧 Received Queue Status: ${decodedMessage.payloadVariant.value}`,
|
||||
);
|
||||
sink.events.onQueueStatus.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onQueueStatus.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "xmodemPacket": {
|
||||
@@ -187,15 +213,19 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
}
|
||||
case "metadata": {
|
||||
if (
|
||||
Number.parseFloat(decodedMessage.payloadVariant.value.firmwareVersion) <
|
||||
Constants.minFwVer
|
||||
Number.parseFloat(
|
||||
decodedMessage.payloadVariant.value.firmwareVersion,
|
||||
) < Constants.minFwVer
|
||||
) {
|
||||
sink.log.fatal(
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
`Device firmware outdated. Min supported: ${Constants.minFwVer} got: ${decodedMessage.payloadVariant.value.firmwareVersion}`,
|
||||
);
|
||||
}
|
||||
sink.log.debug(Emitter[Emitter.GetMetadata], "🏷️ Received metadata packet");
|
||||
sink.log.debug(
|
||||
Emitter[Emitter.GetMetadata],
|
||||
"🏷️ Received metadata packet",
|
||||
);
|
||||
sink.events.onDeviceMetadataPacket.dispatch({
|
||||
id: decodedMessage.id,
|
||||
rxTime: new Date(),
|
||||
@@ -215,7 +245,9 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
Emitter[Emitter.HandleFromRadio],
|
||||
`📣 Received ClientNotification: ${decodedMessage.payloadVariant.value.message}`,
|
||||
);
|
||||
sink.events.onClientNotificationPacket.dispatch(decodedMessage.payloadVariant.value);
|
||||
sink.events.onClientNotificationPacket.dispatch(
|
||||
decodedMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -230,7 +262,10 @@ export const decodePacket = (sink: PacketSink): WritableStream<DeviceOutput> =>
|
||||
},
|
||||
});
|
||||
|
||||
function handleMeshPacket(sink: PacketSink, meshPacket: Protobuf.Mesh.MeshPacket): void {
|
||||
function handleMeshPacket(
|
||||
sink: PacketSink,
|
||||
meshPacket: Protobuf.Mesh.MeshPacket,
|
||||
): void {
|
||||
sink.events.onMeshPacket.dispatch(meshPacket);
|
||||
if (meshPacket.from !== sink.myNodeNum) {
|
||||
sink.events.onMeshHeartbeat.dispatch(new Date());
|
||||
@@ -283,7 +318,10 @@ function handleDecodedPacket(
|
||||
case Protobuf.Portnums.PortNum.REMOTE_HARDWARE_APP: {
|
||||
sink.events.onRemoteHardwarePacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: fromBinary(Protobuf.RemoteHardware.HardwareMessageSchema, dataPacket.payload),
|
||||
data: fromBinary(
|
||||
Protobuf.RemoteHardware.HardwareMessageSchema,
|
||||
dataPacket.payload,
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -302,11 +340,19 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.ROUTING_APP: {
|
||||
const routingPacket = fromBinary(Protobuf.Mesh.RoutingSchema, dataPacket.payload);
|
||||
sink.events.onRoutingPacket.dispatch({ ...packetMetadata, data: routingPacket });
|
||||
const routingPacket = fromBinary(
|
||||
Protobuf.Mesh.RoutingSchema,
|
||||
dataPacket.payload,
|
||||
);
|
||||
sink.events.onRoutingPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: routingPacket,
|
||||
});
|
||||
switch (routingPacket.variant.case) {
|
||||
case "errorReason": {
|
||||
if (routingPacket.variant.value === Protobuf.Mesh.Routing_Error.NONE) {
|
||||
if (
|
||||
routingPacket.variant.value === Protobuf.Mesh.Routing_Error.NONE
|
||||
) {
|
||||
sink.queue.processAck(dataPacket.requestId);
|
||||
} else {
|
||||
sink.queue.processError({
|
||||
@@ -325,10 +371,15 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.ADMIN_APP: {
|
||||
const adminMessage = fromBinary(Protobuf.Admin.AdminMessageSchema, dataPacket.payload);
|
||||
const adminMessage = fromBinary(
|
||||
Protobuf.Admin.AdminMessageSchema,
|
||||
dataPacket.payload,
|
||||
);
|
||||
switch (adminMessage.payloadVariant.case) {
|
||||
case "getChannelResponse": {
|
||||
sink.events.onChannelPacket.dispatch(adminMessage.payloadVariant.value);
|
||||
sink.events.onChannelPacket.dispatch(
|
||||
adminMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "getOwnerResponse": {
|
||||
@@ -339,11 +390,15 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case "getConfigResponse": {
|
||||
sink.events.onConfigPacket.dispatch(adminMessage.payloadVariant.value);
|
||||
sink.events.onConfigPacket.dispatch(
|
||||
adminMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "getModuleConfigResponse": {
|
||||
sink.events.onModuleConfigPacket.dispatch(adminMessage.payloadVariant.value);
|
||||
sink.events.onModuleConfigPacket.dispatch(
|
||||
adminMessage.payloadVariant.value,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "getDeviceMetadataResponse": {
|
||||
@@ -388,7 +443,10 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.AUDIO_APP: {
|
||||
sink.events.onAudioPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onAudioPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.DETECTION_SENSOR_APP: {
|
||||
@@ -399,11 +457,17 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.REPLY_APP: {
|
||||
sink.events.onPingPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onPingPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.IP_TUNNEL_APP: {
|
||||
sink.events.onIpTunnelPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onIpTunnelPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.PAXCOUNTER_APP: {
|
||||
@@ -414,36 +478,57 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.SERIAL_APP: {
|
||||
sink.events.onSerialPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onSerialPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.STORE_FORWARD_APP: {
|
||||
sink.events.onStoreForwardPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onStoreForwardPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.RANGE_TEST_APP: {
|
||||
sink.events.onRangeTestPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onRangeTestPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.TELEMETRY_APP: {
|
||||
sink.events.onTelemetryPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: fromBinary(Protobuf.Telemetry.TelemetrySchema, dataPacket.payload),
|
||||
data: fromBinary(
|
||||
Protobuf.Telemetry.TelemetrySchema,
|
||||
dataPacket.payload,
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.ZPS_APP: {
|
||||
sink.events.onZpsPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onZpsPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.SIMULATOR_APP: {
|
||||
sink.events.onSimulatorPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onSimulatorPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.TRACEROUTE_APP: {
|
||||
sink.events.onTraceRoutePacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: fromBinary(Protobuf.Mesh.RouteDiscoverySchema, dataPacket.payload),
|
||||
data: fromBinary(
|
||||
Protobuf.Mesh.RouteDiscoverySchema,
|
||||
dataPacket.payload,
|
||||
),
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -455,19 +540,31 @@ function handleDecodedPacket(
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.ATAK_PLUGIN: {
|
||||
sink.events.onAtakPluginPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onAtakPluginPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.MAP_REPORT_APP: {
|
||||
sink.events.onMapReportPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onMapReportPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.PRIVATE_APP: {
|
||||
sink.events.onPrivatePacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onPrivatePacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Protobuf.Portnums.PortNum.ATAK_FORWARDER: {
|
||||
sink.events.onAtakForwarderPacket.dispatch({ ...packetMetadata, data: dataPacket.payload });
|
||||
sink.events.onAtakForwarderPacket.dispatch({
|
||||
...packetMetadata,
|
||||
data: dataPacket.payload,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -4,7 +4,10 @@ import type { DeviceOutput } from "../transport/Transport.ts";
|
||||
* Transforms a raw byte stream from the device into typed DeviceOutput chunks
|
||||
* by parsing the 0x94 0xC3 framing header and length prefix.
|
||||
*/
|
||||
export const fromDeviceStream: () => TransformStream<Uint8Array, DeviceOutput> = () => {
|
||||
export const fromDeviceStream: () => TransformStream<
|
||||
Uint8Array,
|
||||
DeviceOutput
|
||||
> = () => {
|
||||
let byteBuffer = new Uint8Array([]);
|
||||
const textDecoder = new TextDecoder();
|
||||
return new TransformStream<Uint8Array, DeviceOutput>({
|
||||
@@ -26,11 +29,18 @@ export const fromDeviceStream: () => TransformStream<Uint8Array, DeviceOutput> =
|
||||
const msb = byteBuffer[2];
|
||||
const lsb = byteBuffer[3];
|
||||
|
||||
if (msb !== undefined && lsb !== undefined && byteBuffer.length >= 4 + (msb << 8) + lsb) {
|
||||
if (
|
||||
msb !== undefined &&
|
||||
lsb !== undefined &&
|
||||
byteBuffer.length >= 4 + (msb << 8) + lsb
|
||||
) {
|
||||
const packet = byteBuffer.subarray(4, 4 + (msb << 8) + lsb);
|
||||
|
||||
const malformedDetectorIndex = packet.indexOf(0x94);
|
||||
if (malformedDetectorIndex !== -1 && packet[malformedDetectorIndex + 1] === 0xc3) {
|
||||
if (
|
||||
malformedDetectorIndex !== -1 &&
|
||||
packet[malformedDetectorIndex + 1] === 0xc3
|
||||
) {
|
||||
console.warn(
|
||||
`⚠️ Malformed packet found, discarding: ${byteBuffer
|
||||
.subarray(0, malformedDetectorIndex - 1)
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
/**
|
||||
* Pads outbound packets with the 0x94 0xC3 framing header and length prefix.
|
||||
*/
|
||||
export const toDeviceStream: () => TransformStream<Uint8Array, Uint8Array> = () => {
|
||||
export const toDeviceStream: () => TransformStream<
|
||||
Uint8Array,
|
||||
Uint8Array
|
||||
> = () => {
|
||||
return new TransformStream<Uint8Array, Uint8Array>({
|
||||
transform(chunk: Uint8Array, controller): void {
|
||||
const bufLen = chunk.length;
|
||||
const header = new Uint8Array([0x94, 0xc3, (bufLen >> 8) & 0xff, bufLen & 0xff]);
|
||||
const header = new Uint8Array([
|
||||
0x94,
|
||||
0xc3,
|
||||
(bufLen >> 8) & 0xff,
|
||||
bufLen & 0xff,
|
||||
]);
|
||||
controller.enqueue(new Uint8Array([...header, ...chunk]));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -53,7 +53,9 @@ export class Queue {
|
||||
return;
|
||||
}
|
||||
|
||||
console.warn(`Packet ${item.id} of type ${decoded.payloadVariant.case} timed out`);
|
||||
console.warn(
|
||||
`Packet ${item.id} of type ${decoded.payloadVariant.case} timed out`,
|
||||
);
|
||||
|
||||
reject({
|
||||
id: item.id,
|
||||
@@ -79,7 +81,9 @@ export class Queue {
|
||||
}
|
||||
|
||||
public processError(e: PacketError): void {
|
||||
console.error(`Error received for packet ${e.id}: ${Protobuf.Mesh.Routing_Error[e.error]}`);
|
||||
console.error(
|
||||
`Error received for packet ${e.id}: ${Protobuf.Mesh.Routing_Error[e.error]}`,
|
||||
);
|
||||
this.errorNotifier.dispatch(e);
|
||||
}
|
||||
|
||||
@@ -91,7 +95,9 @@ export class Queue {
|
||||
return queueItem.promise;
|
||||
}
|
||||
|
||||
public async processQueue(outputStream: WritableStream<Uint8Array>): Promise<void> {
|
||||
public async processQueue(
|
||||
outputStream: WritableStream<Uint8Array>,
|
||||
): Promise<void> {
|
||||
if (this.lock) {
|
||||
return;
|
||||
}
|
||||
@@ -109,7 +115,10 @@ export class Queue {
|
||||
item.sent = true;
|
||||
} catch (error) {
|
||||
const err = error as { code?: string };
|
||||
if (err?.code === "ECONNRESET" || err?.code === "ERR_INVALID_STATE") {
|
||||
if (
|
||||
err?.code === "ECONNRESET" ||
|
||||
err?.code === "ERR_INVALID_STATE"
|
||||
) {
|
||||
writer.releaseLock();
|
||||
this.lock = false;
|
||||
throw error;
|
||||
|
||||
@@ -41,7 +41,9 @@ describe("MeshRegistry", () => {
|
||||
const reg = new MeshRegistry();
|
||||
const { transport } = createFakeTransport();
|
||||
reg.create(1, { transport });
|
||||
expect(() => reg.create(1, { transport: createFakeTransport().transport })).toThrow();
|
||||
expect(() =>
|
||||
reg.create(1, { transport: createFakeTransport().transport }),
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
it("remove disconnects the client and falls back to another active id", async () => {
|
||||
|
||||
@@ -113,9 +113,11 @@ export class MeshRegistry {
|
||||
}
|
||||
|
||||
private snapshot(): void {
|
||||
this.backing.value = Array.from(this.clients.entries()).map(([id, client]) => ({
|
||||
id,
|
||||
client,
|
||||
}));
|
||||
this.backing.value = Array.from(this.clients.entries()).map(
|
||||
([id, client]) => ({
|
||||
id,
|
||||
client,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,12 +21,17 @@ export interface ReadonlySignal<T> {
|
||||
* is invoked asynchronously on every change. Returns both the writable signal
|
||||
* (for slice-internal use) and the readable facade (for external consumption).
|
||||
*/
|
||||
export function createStore<T>(initial: T): { write: Signal<T>; read: ReadonlySignal<T> } {
|
||||
export function createStore<T>(initial: T): {
|
||||
write: Signal<T>;
|
||||
read: ReadonlySignal<T>;
|
||||
} {
|
||||
const write = signal(initial);
|
||||
return { write, read: toReadonly(write) };
|
||||
}
|
||||
|
||||
export function toReadonly<T>(s: Signal<T> | PreactReadonlySignal<T>): ReadonlySignal<T> {
|
||||
export function toReadonly<T>(
|
||||
s: Signal<T> | PreactReadonlySignal<T>,
|
||||
): ReadonlySignal<T> {
|
||||
return {
|
||||
get value() {
|
||||
return s.value;
|
||||
|
||||
@@ -13,8 +13,12 @@ export interface FakeTransportHandle {
|
||||
close(): Promise<void>;
|
||||
}
|
||||
|
||||
type MyNodeInfoInit = Parameters<typeof create<typeof Protobuf.Mesh.MyNodeInfoSchema>>[1];
|
||||
type NodeInfoInit = Parameters<typeof create<typeof Protobuf.Mesh.NodeInfoSchema>>[1];
|
||||
type MyNodeInfoInit = Parameters<
|
||||
typeof create<typeof Protobuf.Mesh.MyNodeInfoSchema>
|
||||
>[1];
|
||||
type NodeInfoInit = Parameters<
|
||||
typeof create<typeof Protobuf.Mesh.NodeInfoSchema>
|
||||
>[1];
|
||||
|
||||
export interface FakeResponder {
|
||||
withMyNodeInfo(info: MyNodeInfoInit & { myNodeNum: number }): void;
|
||||
@@ -31,7 +35,9 @@ export interface FakeResponder {
|
||||
*/
|
||||
export function createFakeTransport(): FakeTransportHandle {
|
||||
const sent: Uint8Array[] = [];
|
||||
let fromDeviceController: ReadableStreamDefaultController<Uint8Array> | undefined;
|
||||
let fromDeviceController:
|
||||
| ReadableStreamDefaultController<Uint8Array>
|
||||
| undefined;
|
||||
|
||||
const fromDeviceRaw = new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
export { createFakeTransport } from "./createFakeTransport.ts";
|
||||
export type { FakeResponder, FakeTransportHandle } from "./createFakeTransport.ts";
|
||||
export type {
|
||||
FakeResponder,
|
||||
FakeTransportHandle,
|
||||
} from "./createFakeTransport.ts";
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import type * as Protobuf from "@meshtastic/protobufs";
|
||||
|
||||
export type { DeviceOutput, HttpRetryConfig, Transport } from "./transport/Transport.ts";
|
||||
export type {
|
||||
DeviceOutput,
|
||||
HttpRetryConfig,
|
||||
Transport,
|
||||
} from "./transport/Transport.ts";
|
||||
export { DeviceStatusEnum } from "./transport/Transport.ts";
|
||||
|
||||
export interface QueueItem {
|
||||
|
||||
@@ -72,7 +72,11 @@ export class Xmodem {
|
||||
this.rxBuffer[this.counter] = packet.buffer;
|
||||
return this.sendCommand(Protobuf.Xmodem.XModem_Control.ACK);
|
||||
}
|
||||
return await this.sendCommand(Protobuf.Xmodem.XModem_Control.NAK, undefined, packet.seq);
|
||||
return await this.sendCommand(
|
||||
Protobuf.Xmodem.XModem_Control.NAK,
|
||||
undefined,
|
||||
packet.seq,
|
||||
);
|
||||
}
|
||||
case Protobuf.Xmodem.XModem_Control.STX: {
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user