@wms-js/lib 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/dist/command/ack-match.d.ts +5 -0
  4. package/dist/command/ack-match.js +9 -0
  5. package/dist/command/ack-match.js.map +1 -0
  6. package/dist/command/session.d.ts +23 -0
  7. package/dist/command/session.js +98 -0
  8. package/dist/command/session.js.map +1 -0
  9. package/dist/command/types.d.ts +14 -0
  10. package/dist/command/types.js +2 -0
  11. package/dist/command/types.js.map +1 -0
  12. package/dist/commands/name.d.ts +25 -0
  13. package/dist/commands/name.js +209 -0
  14. package/dist/commands/name.js.map +1 -0
  15. package/dist/controller.d.ts +26 -0
  16. package/dist/controller.js +108 -0
  17. package/dist/controller.js.map +1 -0
  18. package/dist/frame/errors.d.ts +4 -0
  19. package/dist/frame/errors.js +9 -0
  20. package/dist/frame/errors.js.map +1 -0
  21. package/dist/frame/parser.d.ts +13 -0
  22. package/dist/frame/parser.js +69 -0
  23. package/dist/frame/parser.js.map +1 -0
  24. package/dist/frame/serializer.d.ts +1 -0
  25. package/dist/frame/serializer.js +5 -0
  26. package/dist/frame/serializer.js.map +1 -0
  27. package/dist/index.d.ts +33 -0
  28. package/dist/index.js +22 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/logging/logger.d.ts +15 -0
  31. package/dist/logging/logger.js +60 -0
  32. package/dist/logging/logger.js.map +1 -0
  33. package/dist/network/events.d.ts +6 -0
  34. package/dist/network/events.js +24 -0
  35. package/dist/network/events.js.map +1 -0
  36. package/dist/network/manager.d.ts +36 -0
  37. package/dist/network/manager.js +281 -0
  38. package/dist/network/manager.js.map +1 -0
  39. package/dist/network/types.d.ts +35 -0
  40. package/dist/network/types.js +2 -0
  41. package/dist/network/types.js.map +1 -0
  42. package/dist/parsers/device-scan-response.d.ts +10 -0
  43. package/dist/parsers/device-scan-response.js +24 -0
  44. package/dist/parsers/device-scan-response.js.map +1 -0
  45. package/dist/parsers/device-scan.d.ts +6 -0
  46. package/dist/parsers/device-scan.js +14 -0
  47. package/dist/parsers/device-scan.js.map +1 -0
  48. package/dist/parsers/device-status.d.ts +14 -0
  49. package/dist/parsers/device-status.js +23 -0
  50. package/dist/parsers/device-status.js.map +1 -0
  51. package/dist/parsers/move-response.d.ts +8 -0
  52. package/dist/parsers/move-response.js +16 -0
  53. package/dist/parsers/move-response.js.map +1 -0
  54. package/dist/parsers/network-join.d.ts +8 -0
  55. package/dist/parsers/network-join.js +29 -0
  56. package/dist/parsers/network-join.js.map +1 -0
  57. package/dist/parsers/network-params.d.ts +7 -0
  58. package/dist/parsers/network-params.js +19 -0
  59. package/dist/parsers/network-params.js.map +1 -0
  60. package/dist/parsers/wave-request.d.ts +5 -0
  61. package/dist/parsers/wave-request.js +13 -0
  62. package/dist/parsers/wave-request.js.map +1 -0
  63. package/dist/parsers/wave-response.d.ts +6 -0
  64. package/dist/parsers/wave-response.js +14 -0
  65. package/dist/parsers/wave-response.js.map +1 -0
  66. package/dist/parsers/weather-station.d.ts +9 -0
  67. package/dist/parsers/weather-station.js +30 -0
  68. package/dist/parsers/weather-station.js.map +1 -0
  69. package/dist/routing/broadcast-router.d.ts +9 -0
  70. package/dist/routing/broadcast-router.js +40 -0
  71. package/dist/routing/broadcast-router.js.map +1 -0
  72. package/dist/serial/driver.d.ts +8 -0
  73. package/dist/serial/driver.js +2 -0
  74. package/dist/serial/driver.js.map +1 -0
  75. package/dist/testing/mock-serial.d.ts +22 -0
  76. package/dist/testing/mock-serial.js +62 -0
  77. package/dist/testing/mock-serial.js.map +1 -0
  78. package/package.json +29 -0
@@ -0,0 +1,10 @@
1
+ export declare function getDeviceTypeName(code: string): string;
2
+ export interface DeviceScanResponse {
3
+ serialNumber: string;
4
+ panId: string;
5
+ deviceType: string;
6
+ deviceTypeName: string;
7
+ unknown: string;
8
+ raw: string;
9
+ }
10
+ export declare function deviceScanResponseMatcher(frame: string): DeviceScanResponse | null;
@@ -0,0 +1,24 @@
1
+ const DEVICE_TYPE_NAMES = {
2
+ "25": "Shade",
3
+ };
4
+ export function getDeviceTypeName(code) {
5
+ return DEVICE_TYPE_NAMES[code] ?? "Unknown";
6
+ }
7
+ export function deviceScanResponseMatcher(frame) {
8
+ if (frame.length < 57)
9
+ return null;
10
+ if (frame[0] !== "r")
11
+ return null;
12
+ if (frame.slice(7, 11) !== "7021")
13
+ return null;
14
+ const deviceType = frame.slice(15, 17);
15
+ return {
16
+ serialNumber: frame.slice(1, 7),
17
+ panId: frame.slice(11, 15),
18
+ deviceType,
19
+ deviceTypeName: getDeviceTypeName(deviceType),
20
+ unknown: frame.slice(17, 57),
21
+ raw: frame,
22
+ };
23
+ }
24
+ //# sourceMappingURL=device-scan-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-scan-response.js","sourceRoot":"","sources":["../../src/parsers/device-scan-response.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAA2B;IAChD,IAAI,EAAE,OAAO;CACd,CAAA;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,iBAAiB,CAAC,IAAI,CAAC,IAAI,SAAS,CAAA;AAC7C,CAAC;AAWD,MAAM,UAAU,yBAAyB,CAAC,KAAa;IACrD,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC1B,UAAU;QACV,cAAc,EAAE,iBAAiB,CAAC,UAAU,CAAC;QAC7C,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC5B,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface DeviceScanQuery {
2
+ serialNumber: string;
3
+ panId: string;
4
+ raw: string;
5
+ }
6
+ export declare function deviceScanMatcher(frame: string): DeviceScanQuery | null;
@@ -0,0 +1,14 @@
1
+ export function deviceScanMatcher(frame) {
2
+ if (frame.length < 17)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "7020")
7
+ return null;
8
+ return {
9
+ serialNumber: frame.slice(1, 7),
10
+ panId: frame.slice(11, 15),
11
+ raw: frame,
12
+ };
13
+ }
14
+ //# sourceMappingURL=device-scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-scan.js","sourceRoot":"","sources":["../../src/parsers/device-scan.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC1B,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ export type DeviceDirection = "opening" | "closing" | "stopped";
2
+ export interface DeviceStatus {
3
+ serialNumber: string;
4
+ deviceType: string;
5
+ deviceTypeName: string;
6
+ position: number;
7
+ inclination: number;
8
+ valance1: number;
9
+ valance2: number;
10
+ moving: boolean;
11
+ direction: DeviceDirection;
12
+ raw: string;
13
+ }
14
+ export declare function deviceStatusMatcher(frame: string): DeviceStatus | null;
@@ -0,0 +1,23 @@
1
+ import { getDeviceTypeName } from "./device-scan-response.js";
2
+ export function deviceStatusMatcher(frame) {
3
+ if (frame.length < 29)
4
+ return null;
5
+ if (frame[0] !== "r")
6
+ return null;
7
+ if (frame.slice(7, 11) !== "8011")
8
+ return null;
9
+ const deviceType = frame.slice(17, 19);
10
+ return {
11
+ serialNumber: frame.slice(1, 7),
12
+ deviceType,
13
+ deviceTypeName: getDeviceTypeName(deviceType),
14
+ position: Math.round(parseInt(frame.slice(19, 21), 16) / 2),
15
+ inclination: parseInt(frame.slice(21, 23), 16) - 127,
16
+ valance1: parseInt(frame.slice(23, 25), 16),
17
+ valance2: parseInt(frame.slice(25, 27), 16),
18
+ moving: frame.slice(27, 29) === "01",
19
+ direction: "stopped",
20
+ raw: frame,
21
+ };
22
+ }
23
+ //# sourceMappingURL=device-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-status.js","sourceRoot":"","sources":["../../src/parsers/device-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAiB7D,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtC,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,UAAU;QACV,cAAc,EAAE,iBAAiB,CAAC,UAAU,CAAC;QAC7C,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QAC3D,WAAW,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;QACpD,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI;QACpC,SAAS,EAAE,SAAS;QACpB,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface MoveResponse {
2
+ serialNumber: string;
3
+ subCommand: number;
4
+ previousPosition: number;
5
+ previousInclination: number;
6
+ raw: string;
7
+ }
8
+ export declare function moveResponseMatcher(frame: string): MoveResponse | null;
@@ -0,0 +1,16 @@
1
+ export function moveResponseMatcher(frame) {
2
+ if (frame.length < 25)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "7071")
7
+ return null;
8
+ return {
9
+ serialNumber: frame.slice(1, 7),
10
+ subCommand: parseInt(frame.slice(17, 19), 16) & 0x03,
11
+ previousPosition: Math.round(parseInt(frame.slice(21, 23), 16) / 2),
12
+ previousInclination: parseInt(frame.slice(23, 25), 16) - 127,
13
+ raw: frame,
14
+ };
15
+ }
16
+ //# sourceMappingURL=move-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"move-response.js","sourceRoot":"","sources":["../../src/parsers/move-response.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI;QACpD,gBAAgB,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACnE,mBAAmB,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG;QAC5D,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export interface NetworkJoinMessage {
2
+ serialNumber: string;
3
+ panId: string;
4
+ key: string;
5
+ channel: number;
6
+ raw: string;
7
+ }
8
+ export declare function networkJoinMatcher(frame: string): NetworkJoinMessage | null;
@@ -0,0 +1,29 @@
1
+ export function networkJoinMatcher(frame) {
2
+ if (frame.length < 51)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "5018")
7
+ return null;
8
+ if (frame.slice(47, 49) !== "FF")
9
+ return null;
10
+ const channelHex = frame.slice(49, 51);
11
+ const channel = Number.parseInt(channelHex, 16);
12
+ if (Number.isNaN(channel) || channel < 11 || channel > 26)
13
+ return null;
14
+ return {
15
+ serialNumber: frame.slice(1, 7),
16
+ panId: frame.slice(11, 15),
17
+ key: decodeKey(frame.slice(15, 47)),
18
+ channel,
19
+ raw: frame,
20
+ };
21
+ }
22
+ function decodeKey(hex) {
23
+ let out = "";
24
+ for (let i = hex.length - 2; i >= 0; i -= 2) {
25
+ out += hex.slice(i, i + 2);
26
+ }
27
+ return out;
28
+ }
29
+ //# sourceMappingURL=network-join.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-join.js","sourceRoot":"","sources":["../../src/parsers/network-join.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAC9C,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAE7C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAE/C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAEtE,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC1B,GAAG,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACnC,OAAO;QACP,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,IAAI,GAAG,GAAG,EAAE,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;IAC5B,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface NetworkParamsMessage {
2
+ serialNumber: string;
3
+ panId: string;
4
+ channel: number;
5
+ raw: string;
6
+ }
7
+ export declare function networkParamsMatcher(frame: string): NetworkParamsMessage | null;
@@ -0,0 +1,19 @@
1
+ export function networkParamsMatcher(frame) {
2
+ if (frame.length < 21)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "5060")
7
+ return null;
8
+ const channelHex = frame.slice(17, 19);
9
+ const channel = Number.parseInt(channelHex, 16);
10
+ if (Number.isNaN(channel) || channel < 11 || channel > 26)
11
+ return null;
12
+ return {
13
+ serialNumber: frame.slice(1, 7),
14
+ panId: frame.slice(11, 15),
15
+ channel,
16
+ raw: frame,
17
+ };
18
+ }
19
+ //# sourceMappingURL=network-params.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-params.js","sourceRoot":"","sources":["../../src/parsers/network-params.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAA;IAE/C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAEtE,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QAC1B,OAAO;QACP,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface WaveRequest {
2
+ serialNumber: string;
3
+ raw: string;
4
+ }
5
+ export declare function waveRequestMatcher(frame: string): WaveRequest | null;
@@ -0,0 +1,13 @@
1
+ export function waveRequestMatcher(frame) {
2
+ if (frame.length < 11)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "7050")
7
+ return null;
8
+ return {
9
+ serialNumber: frame.slice(1, 7),
10
+ raw: frame,
11
+ };
12
+ }
13
+ //# sourceMappingURL=wave-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wave-request.js","sourceRoot":"","sources":["../../src/parsers/wave-request.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface WaveResponse {
2
+ serialNumber: string;
3
+ code: string;
4
+ raw: string;
5
+ }
6
+ export declare function waveResponseMatcher(frame: string): WaveResponse | null;
@@ -0,0 +1,14 @@
1
+ export function waveResponseMatcher(frame) {
2
+ if (frame.length < 15)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "50AC")
7
+ return null;
8
+ return {
9
+ serialNumber: frame.slice(1, 7),
10
+ code: frame.slice(11, 15),
11
+ raw: frame,
12
+ };
13
+ }
14
+ //# sourceMappingURL=wave-response.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wave-response.js","sourceRoot":"","sources":["../../src/parsers/wave-response.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;QACzB,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface WeatherStationMessage {
2
+ serialNumber: string;
3
+ windSpeed: number;
4
+ temperature: number | null;
5
+ rain: boolean;
6
+ illuminance: number | null;
7
+ raw: string;
8
+ }
9
+ export declare function weatherStationMatcher(frame: string): WeatherStationMessage | null;
@@ -0,0 +1,30 @@
1
+ export function weatherStationMatcher(frame) {
2
+ if (frame.length < 31)
3
+ return null;
4
+ if (frame[0] !== "r")
5
+ return null;
6
+ if (frame.slice(7, 11) !== "7080")
7
+ return null;
8
+ const ww = parseInt(frame.slice(13, 15), 16);
9
+ const l1 = parseInt(frame.slice(15, 17), 16);
10
+ const l2 = parseInt(frame.slice(23, 25), 16);
11
+ const rain = frame.slice(25, 27) === "C8";
12
+ const tRaw = parseInt(frame.slice(29, 31), 16);
13
+ const temperature = Number.isFinite(tRaw) ? +(tRaw / 2 - 35).toFixed(1) : null;
14
+ const illuminance = (() => {
15
+ if (!Number.isFinite(l1) || !Number.isFinite(l2))
16
+ return null;
17
+ if (l1 === 0)
18
+ return l2 * 2;
19
+ return l1 * l2 * 2;
20
+ })();
21
+ return {
22
+ serialNumber: frame.slice(1, 7),
23
+ windSpeed: ww,
24
+ temperature,
25
+ rain,
26
+ illuminance,
27
+ raw: frame,
28
+ };
29
+ }
30
+ //# sourceMappingURL=weather-station.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weather-station.js","sourceRoot":"","sources":["../../src/parsers/weather-station.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,IAAI,CAAA;IAClC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAA;IACjC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAE9C,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;IAC5C,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;IAC5C,MAAM,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,CAAA;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;IAC9C,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9E,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;QACxB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,OAAO,IAAI,CAAA;QAC7D,IAAI,EAAE,KAAK,CAAC;YAAE,OAAO,EAAE,GAAG,CAAC,CAAA;QAC3B,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC,CAAC,EAAE,CAAA;IAEJ,OAAO;QACL,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,SAAS,EAAE,EAAE;QACb,WAAW;QACX,IAAI;QACJ,WAAW;QACX,GAAG,EAAE,KAAK;KACX,CAAA;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { type RadioController } from "../controller.js";
2
+ export declare class BroadcastRouter {
3
+ private radio;
4
+ private entries;
5
+ private unsubBroadcast;
6
+ constructor(radio: RadioController);
7
+ on<T>(matcher: (frame: string) => T | null, handler: (msg: T) => void): () => void;
8
+ private dispatch;
9
+ }
@@ -0,0 +1,40 @@
1
+ export class BroadcastRouter {
2
+ radio;
3
+ entries = [];
4
+ unsubBroadcast = null;
5
+ constructor(radio) {
6
+ this.radio = radio;
7
+ }
8
+ on(matcher, handler) {
9
+ const entry = {
10
+ matcher: matcher,
11
+ handler: handler,
12
+ };
13
+ this.entries.push(entry);
14
+ if (this.unsubBroadcast === null) {
15
+ this.unsubBroadcast = this.radio.onBroadcast((frame) => {
16
+ this.dispatch(frame);
17
+ });
18
+ }
19
+ return () => {
20
+ const idx = this.entries.indexOf(entry);
21
+ if (idx !== -1) {
22
+ this.entries.splice(idx, 1);
23
+ }
24
+ if (this.entries.length === 0 && this.unsubBroadcast !== null) {
25
+ this.unsubBroadcast();
26
+ this.unsubBroadcast = null;
27
+ }
28
+ };
29
+ }
30
+ dispatch(frame) {
31
+ for (const entry of this.entries) {
32
+ const result = entry.matcher(frame);
33
+ if (result !== null) {
34
+ entry.handler(result);
35
+ return;
36
+ }
37
+ }
38
+ }
39
+ }
40
+ //# sourceMappingURL=broadcast-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"broadcast-router.js","sourceRoot":"","sources":["../../src/routing/broadcast-router.ts"],"names":[],"mappings":"AAOA,MAAM,OAAO,eAAe;IAClB,KAAK,CAAiB;IACtB,OAAO,GAAoB,EAAE,CAAA;IAC7B,cAAc,GAAwB,IAAI,CAAA;IAElD,YAAY,KAAsB;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IAED,EAAE,CAAI,OAAoC,EAAE,OAAyB;QACnE,MAAM,KAAK,GAAkB;YAC3B,OAAO,EAAE,OAAqC;YAC9C,OAAO,EAAE,OAAiC;SAC3C,CAAA;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAExB,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;YACjC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE;gBACrD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC,CAAC,CAAA;QACJ,CAAC;QAED,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACvC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;YAC7B,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;gBAC9D,IAAI,CAAC,cAAc,EAAE,CAAA;gBACrB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;YAC5B,CAAC;QACH,CAAC,CAAA;IACH,CAAC;IAEO,QAAQ,CAAC,KAAa;QAC5B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YACnC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;gBACrB,OAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ export interface SerialDriver {
2
+ open(path: string): Promise<void>;
3
+ close(): Promise<void>;
4
+ write(data: Uint8Array): Promise<void>;
5
+ onData(handler: (data: Uint8Array) => void): () => void;
6
+ onError(handler: (error: Error) => void): () => void;
7
+ onClose(handler: () => void): () => void;
8
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/serial/driver.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { type SerialDriver } from "../serial/driver.js";
2
+ export declare class MockSerialDriver implements SerialDriver {
3
+ private dataHandlers;
4
+ private errorHandlers;
5
+ private closeHandlers;
6
+ private _isOpen;
7
+ private _writes;
8
+ private _path;
9
+ get isOpen(): boolean;
10
+ get path(): string;
11
+ open(path: string): Promise<void>;
12
+ close(): Promise<void>;
13
+ write(data: Uint8Array): Promise<void>;
14
+ onData(handler: (data: Uint8Array) => void): () => void;
15
+ onError(handler: (error: Error) => void): () => void;
16
+ onClose(handler: () => void): () => void;
17
+ simulateData(data: Uint8Array): void;
18
+ simulateError(error: Error): void;
19
+ simulateClose(): void;
20
+ getWrites(): Uint8Array[];
21
+ clearWrites(): void;
22
+ }
@@ -0,0 +1,62 @@
1
+ export class MockSerialDriver {
2
+ dataHandlers = new Set();
3
+ errorHandlers = new Set();
4
+ closeHandlers = new Set();
5
+ _isOpen = false;
6
+ _writes = [];
7
+ _path = "";
8
+ get isOpen() {
9
+ return this._isOpen;
10
+ }
11
+ get path() {
12
+ return this._path;
13
+ }
14
+ async open(path) {
15
+ this._path = path;
16
+ this._isOpen = true;
17
+ }
18
+ async close() {
19
+ this._isOpen = false;
20
+ this._writes = [];
21
+ this.dataHandlers.clear();
22
+ this.errorHandlers.clear();
23
+ this.closeHandlers.clear();
24
+ }
25
+ async write(data) {
26
+ this._writes.push(data);
27
+ }
28
+ onData(handler) {
29
+ this.dataHandlers.add(handler);
30
+ return () => { this.dataHandlers.delete(handler); };
31
+ }
32
+ onError(handler) {
33
+ this.errorHandlers.add(handler);
34
+ return () => { this.errorHandlers.delete(handler); };
35
+ }
36
+ onClose(handler) {
37
+ this.closeHandlers.add(handler);
38
+ return () => { this.closeHandlers.delete(handler); };
39
+ }
40
+ simulateData(data) {
41
+ for (const handler of this.dataHandlers) {
42
+ handler(data);
43
+ }
44
+ }
45
+ simulateError(error) {
46
+ for (const handler of this.errorHandlers) {
47
+ handler(error);
48
+ }
49
+ }
50
+ simulateClose() {
51
+ for (const handler of this.closeHandlers) {
52
+ handler();
53
+ }
54
+ }
55
+ getWrites() {
56
+ return [...this._writes];
57
+ }
58
+ clearWrites() {
59
+ this._writes = [];
60
+ }
61
+ }
62
+ //# sourceMappingURL=mock-serial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-serial.js","sourceRoot":"","sources":["../../src/testing/mock-serial.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,gBAAgB;IACnB,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAA;IACpD,aAAa,GAAG,IAAI,GAAG,EAA0B,CAAA;IACjD,aAAa,GAAG,IAAI,GAAG,EAAc,CAAA;IACrC,OAAO,GAAG,KAAK,CAAA;IACf,OAAO,GAAiB,EAAE,CAAA;IAC1B,KAAK,GAAG,EAAE,CAAA;IAElB,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QACjB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;IACrB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;QACjB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAA;QACzB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAA;QAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,IAAgB;QAC1B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzB,CAAC;IAED,MAAM,CAAC,OAAmC;QACxC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAC9B,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC,CAAA;IACpD,CAAC;IAED,OAAO,CAAC,OAA+B;QACrC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAC/B,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,OAAO,CAAC,OAAmB;QACzB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAC/B,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA,CAAC,CAAC,CAAA;IACrD,CAAC;IAED,YAAY,CAAC,IAAgB;QAC3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACxC,OAAO,CAAC,IAAI,CAAC,CAAA;QACf,CAAC;IACH,CAAC;IAED,aAAa,CAAC,KAAY;QACxB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB,CAAC;IACH,CAAC;IAED,aAAa;QACX,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACzC,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED,SAAS;QACP,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAA;IAC1B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;IACnB,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@wms-js/lib",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./src/index.ts",
9
+ "import": "./src/index.ts"
10
+ },
11
+ "./*": "./src/*"
12
+ },
13
+ "files": [
14
+ "dist",
15
+ "package.json",
16
+ "README.md",
17
+ "LICENSE"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "prepublishOnly": "tsc"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "25.9.3"
28
+ }
29
+ }