Skip to content

Commit cab31b2

Browse files
authored
fix!: General fixes (#25)
2 parents a92d76e + 74c6a33 commit cab31b2

12 files changed

+2858
-807
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@ dist
133133
*.save
134134
/temp
135135
/data-temp
136+
temp_*

package-lock.json

+120-98
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "zigbee-on-host",
3-
"version": "0.1.7",
3+
"version": "0.1.8",
44
"description": "ZigBee stack designed to run on a host and communicate with a radio co-processor (RCP)",
55
"engines": {
66
"node": ">=20.17.0"
@@ -35,7 +35,7 @@
3535
"homepage": "https://github.com/Nerivec/zigbee-on-host#readme",
3636
"devDependencies": {
3737
"@biomejs/biome": "1.9.4",
38-
"@types/node": "^22.13.11",
38+
"@types/node": "^22.13.13",
3939
"@vitest/coverage-v8": "^3.0.9",
4040
"serialport": "^13.0.0",
4141
"typescript": "^5.8.2",

src/dev/minimal-adapter.ts

+58-58
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,34 @@ type PortOptions = {
3636
*/
3737
export class MinimalAdapter {
3838
public readonly driver: OTRCPDriver;
39-
private readonly portOptions: PortOptions;
40-
private serialPort?: SerialPort;
41-
private socketPort?: Socket;
39+
readonly #portOptions: PortOptions;
40+
#serialPort?: SerialPort;
41+
#socketPort?: Socket;
4242
/** True when serial/socket is currently closing */
43-
private closing: boolean;
43+
#closing: boolean;
4444

45-
private wiresharkSeqNum: number;
46-
private wiresharkPort: number;
47-
private wiresharkAddress: string;
48-
private readonly wiresharkSocket: DgramSocket;
45+
#wiresharkSeqNum: number;
46+
#wiresharkPort: number;
47+
#wiresharkAddress: string;
48+
readonly #wiresharkSocket: DgramSocket;
4949

5050
constructor(portOptions: PortOptions, streamRawConfig: StreamRawConfig, netParams: NetworkParameters, sendMACToZEP: boolean) {
51-
this.wiresharkSeqNum = 0; // start at 1
52-
this.wiresharkSocket = createSocket("udp4");
53-
this.wiresharkPort = process.env.WIRESHARK_ZEP_PORT ? Number.parseInt(process.env.WIRESHARK_ZEP_PORT) : DEFAULT_ZEP_UDP_PORT;
54-
this.wiresharkAddress = process.env.WIRESHARK_ADDRESS ? process.env.WIRESHARK_ADDRESS : DEFAULT_WIRESHARK_IP;
55-
this.wiresharkSocket.bind(this.wiresharkPort);
51+
this.#wiresharkSeqNum = 0; // start at 1
52+
this.#wiresharkSocket = createSocket("udp4");
53+
this.#wiresharkPort = process.env.WIRESHARK_ZEP_PORT ? Number.parseInt(process.env.WIRESHARK_ZEP_PORT) : DEFAULT_ZEP_UDP_PORT;
54+
this.#wiresharkAddress = process.env.WIRESHARK_ADDRESS ? process.env.WIRESHARK_ADDRESS : DEFAULT_WIRESHARK_IP;
55+
this.#wiresharkSocket.bind(this.#wiresharkPort);
5656

5757
this.driver = new OTRCPDriver(streamRawConfig, netParams, ".", sendMACToZEP);
5858

59-
this.portOptions = portOptions;
60-
this.closing = false;
59+
this.#portOptions = portOptions;
60+
this.#closing = false;
6161

6262
if (sendMACToZEP) {
6363
this.driver.on("macFrame", (payload, rssi) => {
6464
const wsZEPFrame = createWiresharkZEPFrame(this.driver.netParams.channel, 1, 0, rssi ?? 0, this.nextWiresharkSeqNum(), payload);
6565

66-
this.wiresharkSocket.send(wsZEPFrame, this.wiresharkPort, this.wiresharkAddress);
66+
this.#wiresharkSocket.send(wsZEPFrame, this.#wiresharkPort, this.#wiresharkAddress);
6767
});
6868
}
6969

@@ -75,21 +75,21 @@ export class MinimalAdapter {
7575
* Check if port is valid, open, and not closing.
7676
*/
7777
get portOpen(): boolean {
78-
if (this.closing) {
78+
if (this.#closing) {
7979
return false;
8080
}
8181

82-
if (isTcpPath(this.portOptions.path!)) {
83-
return this.socketPort ? !this.socketPort.closed : false;
82+
if (isTcpPath(this.#portOptions.path!)) {
83+
return this.#socketPort ? !this.#socketPort.closed : false;
8484
}
8585

86-
return this.serialPort ? this.serialPort.isOpen : false;
86+
return this.#serialPort ? this.#serialPort.isOpen : false;
8787
}
8888

8989
private nextWiresharkSeqNum(): number {
90-
this.wiresharkSeqNum = (this.wiresharkSeqNum + 1) & 0xffffffff;
90+
this.#wiresharkSeqNum = (this.#wiresharkSeqNum + 1) & 0xffffffff;
9191

92-
return this.wiresharkSeqNum + 1;
92+
return this.#wiresharkSeqNum + 1;
9393
}
9494

9595
/**
@@ -98,19 +98,19 @@ export class MinimalAdapter {
9898
public async initPort(): Promise<void> {
9999
await this.closePort(); // will do nothing if nothing's open
100100

101-
if (isTcpPath(this.portOptions.path!)) {
102-
const pathUrl = new URL(this.portOptions.path!);
101+
if (isTcpPath(this.#portOptions.path!)) {
102+
const pathUrl = new URL(this.#portOptions.path!);
103103
const hostname = pathUrl.hostname;
104104
const port = Number.parseInt(pathUrl.port, 10);
105105

106106
logger.debug(() => `Opening TCP socket with ${hostname}:${port}`, NS);
107107

108-
this.socketPort = new Socket();
108+
this.#socketPort = new Socket();
109109

110-
this.socketPort.setNoDelay(true);
111-
this.socketPort.setKeepAlive(true, 15000);
112-
this.driver.writer.pipe(this.socketPort);
113-
this.socketPort.pipe(this.driver.parser);
110+
this.#socketPort.setNoDelay(true);
111+
this.#socketPort.setKeepAlive(true, 15000);
112+
this.driver.writer.pipe(this.#socketPort);
113+
this.#socketPort.pipe(this.driver.parser);
114114
this.driver.parser.on("data", this.driver.onFrame.bind(this.driver));
115115

116116
return await new Promise((resolve, reject): void => {
@@ -120,27 +120,27 @@ export class MinimalAdapter {
120120
reject(err);
121121
};
122122

123-
this.socketPort!.on("connect", () => {
123+
this.#socketPort!.on("connect", () => {
124124
logger.debug(() => "Socket connected", NS);
125125
});
126-
this.socketPort!.on("ready", (): void => {
126+
this.#socketPort!.on("ready", (): void => {
127127
logger.info("Socket ready", NS);
128-
this.socketPort!.removeListener("error", openError);
129-
this.socketPort!.once("close", this.onPortClose.bind(this));
130-
this.socketPort!.on("error", this.onPortError.bind(this));
128+
this.#socketPort!.removeListener("error", openError);
129+
this.#socketPort!.once("close", this.onPortClose.bind(this));
130+
this.#socketPort!.on("error", this.onPortError.bind(this));
131131

132132
resolve();
133133
});
134-
this.socketPort!.once("error", openError);
134+
this.#socketPort!.once("error", openError);
135135

136-
this.socketPort!.connect(port, hostname);
136+
this.#socketPort!.connect(port, hostname);
137137
});
138138
}
139139

140140
const serialOpts = {
141-
path: this.portOptions.path!,
142-
baudRate: typeof this.portOptions.baudRate === "number" ? this.portOptions.baudRate : 115200,
143-
rtscts: typeof this.portOptions.rtscts === "boolean" ? this.portOptions.rtscts : false,
141+
path: this.#portOptions.path!,
142+
baudRate: typeof this.#portOptions.baudRate === "number" ? this.#portOptions.baudRate : 115200,
143+
rtscts: typeof this.#portOptions.rtscts === "boolean" ? this.#portOptions.rtscts : false,
144144
autoOpen: false,
145145
parity: "none" as const,
146146
stopBits: 1 as const,
@@ -156,21 +156,21 @@ export class MinimalAdapter {
156156
}
157157

158158
logger.debug(() => `Opening serial port with [path=${serialOpts.path} baudRate=${serialOpts.baudRate} rtscts=${serialOpts.rtscts}]`, NS);
159-
this.serialPort = new SerialPort(serialOpts);
159+
this.#serialPort = new SerialPort(serialOpts);
160160

161-
this.driver.writer.pipe(this.serialPort);
162-
this.serialPort.pipe(this.driver.parser);
161+
this.driver.writer.pipe(this.#serialPort);
162+
this.#serialPort.pipe(this.driver.parser);
163163
this.driver.parser.on("data", this.driver.onFrame.bind(this.driver));
164164

165165
try {
166166
await new Promise<void>((resolve, reject): void => {
167-
this.serialPort!.open((err) => (err ? reject(err) : resolve()));
167+
this.#serialPort!.open((err) => (err ? reject(err) : resolve()));
168168
});
169169

170170
logger.info("Serial port opened", NS);
171171

172-
this.serialPort.once("close", this.onPortClose.bind(this));
173-
this.serialPort.on("error", this.onPortError.bind(this));
172+
this.#serialPort.once("close", this.onPortClose.bind(this));
173+
this.#serialPort.on("error", this.onPortError.bind(this));
174174
} catch (error) {
175175
await this.stop();
176176

@@ -207,11 +207,11 @@ export class MinimalAdapter {
207207
throw new Error("Invalid call to start");
208208
}
209209

210-
if (this.serialPort) {
210+
if (this.#serialPort) {
211211
// try clearing read/write buffers
212212
try {
213213
await new Promise<void>((resolve, reject): void => {
214-
this.serialPort!.flush((err) => (err ? reject(err) : resolve()));
214+
this.#serialPort!.flush((err) => (err ? reject(err) : resolve()));
215215
});
216216
} catch (err) {
217217
logger.error(`Error while flushing serial port before start: ${err}`, NS);
@@ -231,35 +231,35 @@ export class MinimalAdapter {
231231
}
232232

233233
public async stop(): Promise<void> {
234-
this.closing = true;
234+
this.#closing = true;
235235

236236
await this.driver.stop();
237-
this.wiresharkSocket.close();
237+
this.#wiresharkSocket.close();
238238
await this.closePort();
239239
}
240240

241241
public async closePort(): Promise<void> {
242-
if (this.serialPort?.isOpen) {
242+
if (this.#serialPort?.isOpen) {
243243
try {
244244
await new Promise<void>((resolve, reject): void => {
245-
this.serialPort!.flush((err) => (err ? reject(err) : resolve()));
245+
this.#serialPort!.flush((err) => (err ? reject(err) : resolve()));
246246
});
247247

248248
await new Promise<void>((resolve, reject): void => {
249-
this.serialPort!.close((err) => (err ? reject(err) : resolve()));
249+
this.#serialPort!.close((err) => (err ? reject(err) : resolve()));
250250
});
251251
} catch (err) {
252252
logger.error(`Failed to close serial port ${err}.`, NS);
253253
}
254254

255-
this.serialPort.removeAllListeners();
255+
this.#serialPort.removeAllListeners();
256256

257-
this.serialPort = undefined;
258-
} else if (this.socketPort != null && !this.socketPort.closed) {
259-
this.socketPort.destroy();
260-
this.socketPort.removeAllListeners();
257+
this.#serialPort = undefined;
258+
} else if (this.#socketPort != null && !this.#socketPort.closed) {
259+
this.#socketPort.destroy();
260+
this.#socketPort.removeAllListeners();
261261

262-
this.socketPort = undefined;
262+
this.#socketPort = undefined;
263263
}
264264
}
265265

src/dev/z2mdata-to-zohsave.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -195,11 +195,19 @@ async function convert(dataPath: string): Promise<void> {
195195
driver.deviceTable.set(BigInt(device.ieeeAddr), {
196196
address16: device.nwkAddr,
197197
// this could be... wrong, devices not always use this properly
198-
rxOnWhenIdle: device.type === "Router" && device.powerSource !== "Battery",
198+
capabilities: {
199+
alternatePANCoordinator: false,
200+
deviceType: device.type === "Router" ? 0x01 : 0x00,
201+
powerSource: device.powerSource !== "Unknown" && device.powerSource !== "Battery" ? 0x01 : 0x00,
202+
rxOnWhenIdle: device.type === "Router" && device.powerSource !== "Unknown" && device.powerSource !== "Battery",
203+
securityCapability: false,
204+
allocateAddress: true,
205+
},
199206
// technically not correct, but reasonable expectation
200207
authorized: device.interviewCompleted === true,
201208
// add support for not knowing this in driver (re-evaluation)
202209
neighbor: backupDevice?.is_child !== true,
210+
recentLQAs: [],
203211
});
204212
}
205213

0 commit comments

Comments
 (0)