@ecobridge.xyz/devicemanager 3.0.2

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 (137) hide show
  1. package/.gitea/workflows/default_nottags.yaml +66 -0
  2. package/.gitea/workflows/default_tags.yaml +124 -0
  3. package/.vscode/launch.json +11 -0
  4. package/.vscode/settings.json +26 -0
  5. package/changelog.md +91 -0
  6. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  7. package/dist_ts/00_commitinfo_data.js +9 -0
  8. package/dist_ts/device/device.classes.device.d.ts +205 -0
  9. package/dist_ts/device/device.classes.device.js +344 -0
  10. package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
  11. package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
  12. package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
  13. package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
  14. package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
  15. package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
  16. package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
  17. package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
  18. package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
  19. package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
  20. package/dist_ts/factories/index.d.ts +190 -0
  21. package/dist_ts/factories/index.js +350 -0
  22. package/dist_ts/features/feature.abstract.d.ts +118 -0
  23. package/dist_ts/features/feature.abstract.js +172 -0
  24. package/dist_ts/features/feature.camera.d.ts +95 -0
  25. package/dist_ts/features/feature.camera.js +162 -0
  26. package/dist_ts/features/feature.climate.d.ts +174 -0
  27. package/dist_ts/features/feature.climate.js +328 -0
  28. package/dist_ts/features/feature.cover.d.ts +121 -0
  29. package/dist_ts/features/feature.cover.js +217 -0
  30. package/dist_ts/features/feature.fan.d.ts +127 -0
  31. package/dist_ts/features/feature.fan.js +235 -0
  32. package/dist_ts/features/feature.light.d.ts +156 -0
  33. package/dist_ts/features/feature.light.js +296 -0
  34. package/dist_ts/features/feature.lock.d.ts +103 -0
  35. package/dist_ts/features/feature.lock.js +170 -0
  36. package/dist_ts/features/feature.playback.d.ts +98 -0
  37. package/dist_ts/features/feature.playback.js +191 -0
  38. package/dist_ts/features/feature.power.d.ts +79 -0
  39. package/dist_ts/features/feature.power.js +173 -0
  40. package/dist_ts/features/feature.print.d.ts +78 -0
  41. package/dist_ts/features/feature.print.js +226 -0
  42. package/dist_ts/features/feature.scan.d.ts +79 -0
  43. package/dist_ts/features/feature.scan.js +315 -0
  44. package/dist_ts/features/feature.sensor.d.ts +95 -0
  45. package/dist_ts/features/feature.sensor.js +147 -0
  46. package/dist_ts/features/feature.snmp.d.ts +88 -0
  47. package/dist_ts/features/feature.snmp.js +175 -0
  48. package/dist_ts/features/feature.switch.d.ts +75 -0
  49. package/dist_ts/features/feature.switch.js +126 -0
  50. package/dist_ts/features/feature.volume.d.ts +104 -0
  51. package/dist_ts/features/feature.volume.js +186 -0
  52. package/dist_ts/features/index.d.ts +19 -0
  53. package/dist_ts/features/index.js +23 -0
  54. package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
  55. package/dist_ts/helpers/helpers.iprange.js +151 -0
  56. package/dist_ts/helpers/helpers.retry.d.ts +25 -0
  57. package/dist_ts/helpers/helpers.retry.js +69 -0
  58. package/dist_ts/index.d.ts +15 -0
  59. package/dist_ts/index.js +40 -0
  60. package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
  61. package/dist_ts/interfaces/feature.interfaces.js +6 -0
  62. package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
  63. package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
  64. package/dist_ts/interfaces/index.d.ts +330 -0
  65. package/dist_ts/interfaces/index.js +16 -0
  66. package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
  67. package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
  68. package/dist_ts/paths.d.ts +1 -0
  69. package/dist_ts/paths.js +3 -0
  70. package/dist_ts/plugins.d.ts +23 -0
  71. package/dist_ts/plugins.js +30 -0
  72. package/dist_ts/protocols/index.d.ts +12 -0
  73. package/dist_ts/protocols/index.js +21 -0
  74. package/dist_ts/protocols/protocol.escl.d.ts +58 -0
  75. package/dist_ts/protocols/protocol.escl.js +364 -0
  76. package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
  77. package/dist_ts/protocols/protocol.homeassistant.js +611 -0
  78. package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
  79. package/dist_ts/protocols/protocol.ipp.js +284 -0
  80. package/dist_ts/protocols/protocol.nut.d.ts +160 -0
  81. package/dist_ts/protocols/protocol.nut.js +364 -0
  82. package/dist_ts/protocols/protocol.sane.d.ts +104 -0
  83. package/dist_ts/protocols/protocol.sane.js +597 -0
  84. package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
  85. package/dist_ts/protocols/protocol.snmp.js +333 -0
  86. package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
  87. package/dist_ts/protocols/protocol.upnp.js +442 -0
  88. package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
  89. package/dist_ts/protocols/protocol.upssnmp.js +263 -0
  90. package/npmextra.json +24 -0
  91. package/package.json +39 -0
  92. package/readme.hints.md +115 -0
  93. package/readme.md +624 -0
  94. package/test/test.ts +261 -0
  95. package/ts/00_commitinfo_data.ts +8 -0
  96. package/ts/device/device.classes.device.ts +454 -0
  97. package/ts/devicemanager.classes.devicemanager.ts +1219 -0
  98. package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
  99. package/ts/discovery/discovery.classes.mdns.ts +347 -0
  100. package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
  101. package/ts/discovery/discovery.classes.ssdp.ts +357 -0
  102. package/ts/factories/index.ts +696 -0
  103. package/ts/features/feature.abstract.ts +251 -0
  104. package/ts/features/feature.camera.ts +214 -0
  105. package/ts/features/feature.climate.ts +407 -0
  106. package/ts/features/feature.cover.ts +278 -0
  107. package/ts/features/feature.fan.ts +296 -0
  108. package/ts/features/feature.light.ts +369 -0
  109. package/ts/features/feature.lock.ts +223 -0
  110. package/ts/features/feature.playback.ts +246 -0
  111. package/ts/features/feature.power.ts +231 -0
  112. package/ts/features/feature.print.ts +297 -0
  113. package/ts/features/feature.scan.ts +370 -0
  114. package/ts/features/feature.sensor.ts +202 -0
  115. package/ts/features/feature.snmp.ts +235 -0
  116. package/ts/features/feature.switch.ts +170 -0
  117. package/ts/features/feature.volume.ts +256 -0
  118. package/ts/features/index.ts +25 -0
  119. package/ts/helpers/helpers.iprange.ts +172 -0
  120. package/ts/helpers/helpers.retry.ts +100 -0
  121. package/ts/index.ts +165 -0
  122. package/ts/interfaces/feature.interfaces.ts +359 -0
  123. package/ts/interfaces/homeassistant.interfaces.ts +666 -0
  124. package/ts/interfaces/index.ts +421 -0
  125. package/ts/interfaces/smarthome.interfaces.ts +421 -0
  126. package/ts/paths.ts +5 -0
  127. package/ts/plugins.ts +41 -0
  128. package/ts/protocols/index.ts +59 -0
  129. package/ts/protocols/protocol.escl.ts +439 -0
  130. package/ts/protocols/protocol.homeassistant.ts +737 -0
  131. package/ts/protocols/protocol.ipp.ts +329 -0
  132. package/ts/protocols/protocol.nut.ts +471 -0
  133. package/ts/protocols/protocol.sane.ts +694 -0
  134. package/ts/protocols/protocol.snmp.ts +439 -0
  135. package/ts/protocols/protocol.upnp.ts +627 -0
  136. package/ts/protocols/protocol.upssnmp.ts +377 -0
  137. package/tsconfig.json +12 -0
@@ -0,0 +1,263 @@
1
+ import { SnmpProtocol, SNMP_OIDS } from '../protocols/index.js';
2
+ /**
3
+ * Extended UPS-MIB OIDs (RFC 1628)
4
+ */
5
+ export const UPS_SNMP_OIDS = {
6
+ // Identity
7
+ upsIdentManufacturer: '1.3.6.1.2.1.33.1.1.1.0',
8
+ upsIdentModel: '1.3.6.1.2.1.33.1.1.2.0',
9
+ upsIdentUPSSoftwareVersion: '1.3.6.1.2.1.33.1.1.3.0',
10
+ upsIdentAgentSoftwareVersion: '1.3.6.1.2.1.33.1.1.4.0',
11
+ upsIdentName: '1.3.6.1.2.1.33.1.1.5.0',
12
+ upsIdentAttachedDevices: '1.3.6.1.2.1.33.1.1.6.0',
13
+ // Battery group
14
+ upsBatteryStatus: '1.3.6.1.2.1.33.1.2.1.0',
15
+ upsSecondsOnBattery: '1.3.6.1.2.1.33.1.2.2.0',
16
+ upsEstimatedMinutesRemaining: '1.3.6.1.2.1.33.1.2.3.0',
17
+ upsEstimatedChargeRemaining: '1.3.6.1.2.1.33.1.2.4.0',
18
+ upsBatteryVoltage: '1.3.6.1.2.1.33.1.2.5.0',
19
+ upsBatteryCurrent: '1.3.6.1.2.1.33.1.2.6.0',
20
+ upsBatteryTemperature: '1.3.6.1.2.1.33.1.2.7.0',
21
+ // Input group
22
+ upsInputLineBads: '1.3.6.1.2.1.33.1.3.1.0',
23
+ upsInputNumLines: '1.3.6.1.2.1.33.1.3.2.0',
24
+ upsInputLineIndex: '1.3.6.1.2.1.33.1.3.3.1.1',
25
+ upsInputFrequency: '1.3.6.1.2.1.33.1.3.3.1.2',
26
+ upsInputVoltage: '1.3.6.1.2.1.33.1.3.3.1.3',
27
+ upsInputCurrent: '1.3.6.1.2.1.33.1.3.3.1.4',
28
+ upsInputTruePower: '1.3.6.1.2.1.33.1.3.3.1.5',
29
+ // Output group
30
+ upsOutputSource: '1.3.6.1.2.1.33.1.4.1.0',
31
+ upsOutputFrequency: '1.3.6.1.2.1.33.1.4.2.0',
32
+ upsOutputNumLines: '1.3.6.1.2.1.33.1.4.3.0',
33
+ upsOutputLineIndex: '1.3.6.1.2.1.33.1.4.4.1.1',
34
+ upsOutputVoltage: '1.3.6.1.2.1.33.1.4.4.1.2',
35
+ upsOutputCurrent: '1.3.6.1.2.1.33.1.4.4.1.3',
36
+ upsOutputPower: '1.3.6.1.2.1.33.1.4.4.1.4',
37
+ upsOutputPercentLoad: '1.3.6.1.2.1.33.1.4.4.1.5',
38
+ // Bypass group
39
+ upsBypassFrequency: '1.3.6.1.2.1.33.1.5.1.0',
40
+ upsBypassNumLines: '1.3.6.1.2.1.33.1.5.2.0',
41
+ // Alarm group
42
+ upsAlarmsPresent: '1.3.6.1.2.1.33.1.6.1.0',
43
+ // Test group
44
+ upsTestId: '1.3.6.1.2.1.33.1.7.1.0',
45
+ upsTestSpinLock: '1.3.6.1.2.1.33.1.7.2.0',
46
+ upsTestResultsSummary: '1.3.6.1.2.1.33.1.7.3.0',
47
+ upsTestResultsDetail: '1.3.6.1.2.1.33.1.7.4.0',
48
+ upsTestStartTime: '1.3.6.1.2.1.33.1.7.5.0',
49
+ upsTestElapsedTime: '1.3.6.1.2.1.33.1.7.6.0',
50
+ // Control group
51
+ upsShutdownType: '1.3.6.1.2.1.33.1.8.1.0',
52
+ upsShutdownAfterDelay: '1.3.6.1.2.1.33.1.8.2.0',
53
+ upsStartupAfterDelay: '1.3.6.1.2.1.33.1.8.3.0',
54
+ upsRebootWithDuration: '1.3.6.1.2.1.33.1.8.4.0',
55
+ upsAutoRestart: '1.3.6.1.2.1.33.1.8.5.0',
56
+ // Config group
57
+ upsConfigInputVoltage: '1.3.6.1.2.1.33.1.9.1.0',
58
+ upsConfigInputFreq: '1.3.6.1.2.1.33.1.9.2.0',
59
+ upsConfigOutputVoltage: '1.3.6.1.2.1.33.1.9.3.0',
60
+ upsConfigOutputFreq: '1.3.6.1.2.1.33.1.9.4.0',
61
+ upsConfigOutputVA: '1.3.6.1.2.1.33.1.9.5.0',
62
+ upsConfigOutputPower: '1.3.6.1.2.1.33.1.9.6.0',
63
+ upsConfigLowBattTime: '1.3.6.1.2.1.33.1.9.7.0',
64
+ upsConfigAudibleStatus: '1.3.6.1.2.1.33.1.9.8.0',
65
+ upsConfigLowVoltageTransferPoint: '1.3.6.1.2.1.33.1.9.9.0',
66
+ upsConfigHighVoltageTransferPoint: '1.3.6.1.2.1.33.1.9.10.0',
67
+ };
68
+ /**
69
+ * UPS SNMP handler for querying UPS devices via SNMP
70
+ */
71
+ export class UpsSnmpHandler {
72
+ protocol;
73
+ constructor(address, options) {
74
+ this.protocol = new SnmpProtocol(address, options);
75
+ }
76
+ /**
77
+ * Close SNMP session
78
+ */
79
+ close() {
80
+ this.protocol.close();
81
+ }
82
+ /**
83
+ * Get UPS identity information
84
+ */
85
+ async getIdentity() {
86
+ const varbinds = await this.protocol.getMultiple([
87
+ UPS_SNMP_OIDS.upsIdentManufacturer,
88
+ UPS_SNMP_OIDS.upsIdentModel,
89
+ UPS_SNMP_OIDS.upsIdentUPSSoftwareVersion,
90
+ UPS_SNMP_OIDS.upsIdentName,
91
+ ]);
92
+ const getValue = (oid) => {
93
+ const vb = varbinds.find((v) => v.oid === oid);
94
+ return String(vb?.value || '');
95
+ };
96
+ return {
97
+ manufacturer: getValue(UPS_SNMP_OIDS.upsIdentManufacturer),
98
+ model: getValue(UPS_SNMP_OIDS.upsIdentModel),
99
+ softwareVersion: getValue(UPS_SNMP_OIDS.upsIdentUPSSoftwareVersion),
100
+ name: getValue(UPS_SNMP_OIDS.upsIdentName),
101
+ };
102
+ }
103
+ /**
104
+ * Get battery status
105
+ */
106
+ async getBatteryStatus() {
107
+ const varbinds = await this.protocol.getMultiple([
108
+ UPS_SNMP_OIDS.upsBatteryStatus,
109
+ UPS_SNMP_OIDS.upsSecondsOnBattery,
110
+ UPS_SNMP_OIDS.upsEstimatedMinutesRemaining,
111
+ UPS_SNMP_OIDS.upsEstimatedChargeRemaining,
112
+ UPS_SNMP_OIDS.upsBatteryVoltage,
113
+ UPS_SNMP_OIDS.upsBatteryTemperature,
114
+ ]);
115
+ const getValue = (oid) => {
116
+ const vb = varbinds.find((v) => v.oid === oid);
117
+ return Number(vb?.value || 0);
118
+ };
119
+ const statusMap = {
120
+ 1: 'unknown',
121
+ 2: 'batteryNormal',
122
+ 3: 'batteryLow',
123
+ 4: 'batteryDepleted',
124
+ };
125
+ return {
126
+ status: statusMap[getValue(UPS_SNMP_OIDS.upsBatteryStatus)] || 'unknown',
127
+ secondsOnBattery: getValue(UPS_SNMP_OIDS.upsSecondsOnBattery),
128
+ estimatedMinutesRemaining: getValue(UPS_SNMP_OIDS.upsEstimatedMinutesRemaining),
129
+ estimatedChargeRemaining: getValue(UPS_SNMP_OIDS.upsEstimatedChargeRemaining),
130
+ voltage: getValue(UPS_SNMP_OIDS.upsBatteryVoltage) / 10, // Typically in 0.1V units
131
+ temperature: getValue(UPS_SNMP_OIDS.upsBatteryTemperature),
132
+ };
133
+ }
134
+ /**
135
+ * Get input status
136
+ */
137
+ async getInputStatus() {
138
+ const varbinds = await this.protocol.getMultiple([
139
+ UPS_SNMP_OIDS.upsInputFrequency + '.1', // Line 1
140
+ UPS_SNMP_OIDS.upsInputVoltage + '.1', // Line 1
141
+ UPS_SNMP_OIDS.upsInputLineBads,
142
+ ]);
143
+ const getValue = (oid) => {
144
+ const vb = varbinds.find((v) => v.oid === oid);
145
+ return Number(vb?.value || 0);
146
+ };
147
+ return {
148
+ frequency: getValue(UPS_SNMP_OIDS.upsInputFrequency + '.1') / 10, // 0.1 Hz units
149
+ voltage: getValue(UPS_SNMP_OIDS.upsInputVoltage + '.1'),
150
+ lineBads: getValue(UPS_SNMP_OIDS.upsInputLineBads),
151
+ };
152
+ }
153
+ /**
154
+ * Get output status
155
+ */
156
+ async getOutputStatus() {
157
+ const varbinds = await this.protocol.getMultiple([
158
+ UPS_SNMP_OIDS.upsOutputSource,
159
+ UPS_SNMP_OIDS.upsOutputFrequency,
160
+ UPS_SNMP_OIDS.upsOutputVoltage + '.1', // Line 1
161
+ UPS_SNMP_OIDS.upsOutputCurrent + '.1', // Line 1
162
+ UPS_SNMP_OIDS.upsOutputPower + '.1', // Line 1
163
+ UPS_SNMP_OIDS.upsOutputPercentLoad + '.1', // Line 1
164
+ ]);
165
+ const getValue = (oid) => {
166
+ const vb = varbinds.find((v) => v.oid === oid);
167
+ return Number(vb?.value || 0);
168
+ };
169
+ const sourceMap = {
170
+ 1: 'other',
171
+ 2: 'none',
172
+ 3: 'normal',
173
+ 4: 'bypass',
174
+ 5: 'battery',
175
+ 6: 'booster',
176
+ 7: 'reducer',
177
+ };
178
+ return {
179
+ source: sourceMap[getValue(UPS_SNMP_OIDS.upsOutputSource)] || 'other',
180
+ frequency: getValue(UPS_SNMP_OIDS.upsOutputFrequency) / 10, // 0.1 Hz units
181
+ voltage: getValue(UPS_SNMP_OIDS.upsOutputVoltage + '.1'),
182
+ current: getValue(UPS_SNMP_OIDS.upsOutputCurrent + '.1') / 10, // 0.1 A units
183
+ power: getValue(UPS_SNMP_OIDS.upsOutputPower + '.1'),
184
+ percentLoad: getValue(UPS_SNMP_OIDS.upsOutputPercentLoad + '.1'),
185
+ };
186
+ }
187
+ /**
188
+ * Get full UPS status
189
+ */
190
+ async getFullStatus() {
191
+ const [battery, input, output] = await Promise.all([
192
+ this.getBatteryStatus(),
193
+ this.getInputStatus(),
194
+ this.getOutputStatus(),
195
+ ]);
196
+ // Get alarms separately
197
+ let alarmsPresent = 0;
198
+ try {
199
+ const alarmVb = await this.protocol.get(UPS_SNMP_OIDS.upsAlarmsPresent);
200
+ alarmsPresent = Number(alarmVb.value || 0);
201
+ }
202
+ catch {
203
+ // Ignore alarm fetch errors
204
+ }
205
+ return {
206
+ batteryStatus: battery.status,
207
+ secondsOnBattery: battery.secondsOnBattery,
208
+ estimatedMinutesRemaining: battery.estimatedMinutesRemaining,
209
+ estimatedChargeRemaining: battery.estimatedChargeRemaining,
210
+ batteryVoltage: battery.voltage,
211
+ batteryTemperature: battery.temperature,
212
+ outputSource: output.source,
213
+ outputFrequency: output.frequency,
214
+ outputVoltage: output.voltage,
215
+ outputCurrent: output.current,
216
+ outputPower: output.power,
217
+ outputPercentLoad: output.percentLoad,
218
+ inputFrequency: input.frequency,
219
+ inputVoltage: input.voltage,
220
+ alarmsPresent,
221
+ };
222
+ }
223
+ /**
224
+ * Check if UPS-MIB is supported on device
225
+ */
226
+ async isUpsDevice() {
227
+ try {
228
+ const vb = await this.protocol.get(UPS_SNMP_OIDS.upsBatteryStatus);
229
+ return vb.value !== null && vb.value !== undefined;
230
+ }
231
+ catch {
232
+ return false;
233
+ }
234
+ }
235
+ /**
236
+ * Get configuration info
237
+ */
238
+ async getConfiguration() {
239
+ const varbinds = await this.protocol.getMultiple([
240
+ UPS_SNMP_OIDS.upsConfigInputVoltage,
241
+ UPS_SNMP_OIDS.upsConfigInputFreq,
242
+ UPS_SNMP_OIDS.upsConfigOutputVoltage,
243
+ UPS_SNMP_OIDS.upsConfigOutputFreq,
244
+ UPS_SNMP_OIDS.upsConfigOutputVA,
245
+ UPS_SNMP_OIDS.upsConfigOutputPower,
246
+ UPS_SNMP_OIDS.upsConfigLowBattTime,
247
+ ]);
248
+ const getValue = (oid) => {
249
+ const vb = varbinds.find((v) => v.oid === oid);
250
+ return Number(vb?.value || 0);
251
+ };
252
+ return {
253
+ inputVoltage: getValue(UPS_SNMP_OIDS.upsConfigInputVoltage),
254
+ inputFrequency: getValue(UPS_SNMP_OIDS.upsConfigInputFreq) / 10,
255
+ outputVoltage: getValue(UPS_SNMP_OIDS.upsConfigOutputVoltage),
256
+ outputFrequency: getValue(UPS_SNMP_OIDS.upsConfigOutputFreq) / 10,
257
+ outputVA: getValue(UPS_SNMP_OIDS.upsConfigOutputVA),
258
+ outputPower: getValue(UPS_SNMP_OIDS.upsConfigOutputPower),
259
+ lowBatteryTime: getValue(UPS_SNMP_OIDS.upsConfigLowBattTime),
260
+ };
261
+ }
262
+ }
263
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wudXBzc25tcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3Byb3RvY29scy9wcm90b2NvbC51cHNzbm1wLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFxQixNQUFNLHVCQUF1QixDQUFDO0FBRW5GOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHO0lBQzNCLFdBQVc7SUFDWCxvQkFBb0IsRUFBRSx3QkFBd0I7SUFDOUMsYUFBYSxFQUFFLHdCQUF3QjtJQUN2QywwQkFBMEIsRUFBRSx3QkFBd0I7SUFDcEQsNEJBQTRCLEVBQUUsd0JBQXdCO0lBQ3RELFlBQVksRUFBRSx3QkFBd0I7SUFDdEMsdUJBQXVCLEVBQUUsd0JBQXdCO0lBRWpELGdCQUFnQjtJQUNoQixnQkFBZ0IsRUFBRSx3QkFBd0I7SUFDMUMsbUJBQW1CLEVBQUUsd0JBQXdCO0lBQzdDLDRCQUE0QixFQUFFLHdCQUF3QjtJQUN0RCwyQkFBMkIsRUFBRSx3QkFBd0I7SUFDckQsaUJBQWlCLEVBQUUsd0JBQXdCO0lBQzNDLGlCQUFpQixFQUFFLHdCQUF3QjtJQUMzQyxxQkFBcUIsRUFBRSx3QkFBd0I7SUFFL0MsY0FBYztJQUNkLGdCQUFnQixFQUFFLHdCQUF3QjtJQUMxQyxnQkFBZ0IsRUFBRSx3QkFBd0I7SUFDMUMsaUJBQWlCLEVBQUUsMEJBQTBCO0lBQzdDLGlCQUFpQixFQUFFLDBCQUEwQjtJQUM3QyxlQUFlLEVBQUUsMEJBQTBCO0lBQzNDLGVBQWUsRUFBRSwwQkFBMEI7SUFDM0MsaUJBQWlCLEVBQUUsMEJBQTBCO0lBRTdDLGVBQWU7SUFDZixlQUFlLEVBQUUsd0JBQXdCO0lBQ3pDLGtCQUFrQixFQUFFLHdCQUF3QjtJQUM1QyxpQkFBaUIsRUFBRSx3QkFBd0I7SUFDM0Msa0JBQWtCLEVBQUUsMEJBQTBCO0lBQzlDLGdCQUFnQixFQUFFLDBCQUEwQjtJQUM1QyxnQkFBZ0Is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
package/npmextra.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "@git.zone/cli": {
3
+ "projectType": "npm",
4
+ "module": {
5
+ "githost": "code.foss.global",
6
+ "gitscope": "ecobridge.xyz",
7
+ "gitrepo": "devicemanager",
8
+ "description": "a device manager for talking to devices on network and over usb",
9
+ "npmPackagename": "@ecobridge.xyz/devicemanager",
10
+ "license": "MIT",
11
+ "projectDomain": "ecobridge.xyz"
12
+ },
13
+ "release": {
14
+ "accessLevel": "public",
15
+ "registries": [
16
+ "https://verdaccio.lossless.digital",
17
+ "https://registry.npmjs.org"
18
+ ]
19
+ }
20
+ },
21
+ "@ship.zone/szci": {
22
+ "npmGlobalTools": []
23
+ }
24
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@ecobridge.xyz/devicemanager",
3
+ "version": "3.0.2",
4
+ "private": false,
5
+ "description": "a device manager for talking to devices on network and over usb",
6
+ "main": "dist_ts/index.js",
7
+ "typings": "dist_ts/index.d.ts",
8
+ "type": "module",
9
+ "author": "Task Venture Capital GmbH",
10
+ "license": "MIT",
11
+ "scripts": {
12
+ "test": "(tstest test/ --verbose)",
13
+ "build": "(tsbuild --web --allowimplicitany)",
14
+ "buildDocs": "(tsdoc)"
15
+ },
16
+ "devDependencies": {
17
+ "@git.zone/tsbuild": "^4.1.0",
18
+ "@git.zone/tsrun": "^2.0.0",
19
+ "@git.zone/tstest": "^3.1.3",
20
+ "@types/node": "^25.0.3",
21
+ "@types/ws": "^8.18.1"
22
+ },
23
+ "dependencies": {
24
+ "@push.rocks/smartdelay": "^3.0.5",
25
+ "@push.rocks/smartevent": "^2.0.5",
26
+ "@push.rocks/smartnetwork": "^4.4.0",
27
+ "@push.rocks/smartpath": "^6.0.0",
28
+ "@push.rocks/smartpromise": "^4.2.3",
29
+ "@push.rocks/smartrequest": "^5.0.1",
30
+ "@push.rocks/smartxml": "^2.0.0",
31
+ "bonjour-service": "^1.3.0",
32
+ "castv2-client": "^1.2.0",
33
+ "ipp": "^2.0.1",
34
+ "net-snmp": "^3.26.0",
35
+ "node-ssdp": "^4.0.1",
36
+ "sonos": "^1.14.2",
37
+ "ws": "^8.19.0"
38
+ }
39
+ }
@@ -0,0 +1,115 @@
1
+ # Device Manager - Implementation Notes
2
+
3
+ ## Architecture Overview
4
+
5
+ The device manager uses a **UniversalDevice** architecture with composable features.
6
+
7
+ ### Key Concepts
8
+
9
+ - **UniversalDevice**: A single device class that can have multiple features attached
10
+ - **Features**: Composable capabilities (scan, print, playback, volume, power, snmp, smart home, etc.)
11
+ - **Protocols**: Low-level protocol implementations (eSCL, SANE, IPP, SNMP, NUT, UPnP, Home Assistant)
12
+
13
+ ## Key Files
14
+
15
+ ### Core (`ts/`)
16
+ - `devicemanager.classes.devicemanager.ts` - Main DeviceManager class with discovery and device registry
17
+ - `device/device.classes.device.ts` - UniversalDevice class with feature management
18
+
19
+ ### Features (`ts/features/`)
20
+ - `feature.abstract.ts` - Base Feature class with connection management and retry logic
21
+ - `feature.scan.ts` - Scanning via eSCL/SANE protocols
22
+ - `feature.print.ts` - Printing via IPP protocol
23
+ - `feature.playback.ts` - Media playback (Sonos, AirPlay, Chromecast, DLNA)
24
+ - `feature.volume.ts` - Volume control (separate from playback)
25
+ - `feature.power.ts` - UPS/power monitoring via NUT/SNMP
26
+ - `feature.snmp.ts` - SNMP queries
27
+ - `feature.light.ts` - Smart light control
28
+ - `feature.switch.ts` - Smart switch control
29
+ - `feature.sensor.ts` - Smart sensors
30
+ - `feature.climate.ts` - Climate/HVAC control
31
+ - `feature.cover.ts` - Blinds, garage doors
32
+ - `feature.lock.ts` - Smart locks
33
+ - `feature.fan.ts` - Fan control
34
+ - `feature.camera.ts` - Camera control
35
+
36
+ ### Protocols (`ts/protocols/`)
37
+ - `protocol.escl.ts` - eSCL/AirScan scanner protocol
38
+ - `protocol.sane.ts` - SANE network scanner protocol
39
+ - `protocol.ipp.ts` - IPP printer protocol
40
+ - `protocol.snmp.ts` - SNMP queries
41
+ - `protocol.nut.ts` - Network UPS Tools protocol
42
+ - `protocol.upnp.ts` - UPnP/SOAP client
43
+ - `protocol.upssnmp.ts` - UPS-specific SNMP
44
+ - `protocol.homeassistant.ts` - Home Assistant WebSocket API
45
+
46
+ ### Discovery (`ts/discovery/`)
47
+ - `discovery.classes.mdns.ts` - mDNS discovery (Bonjour)
48
+ - `discovery.classes.ssdp.ts` - SSDP/UPnP discovery
49
+ - `discovery.classes.networkscanner.ts` - Active network scanning
50
+ - `discovery.classes.homeassistant.ts` - Home Assistant instance discovery
51
+
52
+ ### Factories (`ts/factories/`)
53
+ - `index.ts` - Device factory functions for creating pre-configured devices:
54
+ - `createScanner`, `createPrinter`, `createSpeaker`, `createDlnaRenderer`
55
+ - `createSnmpDevice`, `createUpsDevice`
56
+ - Smart home: `createSmartLight`, `createSmartSwitch`, `createSmartSensor`, etc.
57
+
58
+ ### Interfaces (`ts/interfaces/`)
59
+ - `feature.interfaces.ts` - All feature-related types and interfaces
60
+ - `smarthome.interfaces.ts` - Smart home specific interfaces
61
+ - `homeassistant.interfaces.ts` - Home Assistant API types
62
+ - `index.ts` - Re-exports all interfaces
63
+
64
+ ## Feature Types
65
+
66
+ ```typescript
67
+ type TFeatureType =
68
+ | 'scan' | 'print' | 'fax' | 'copy'
69
+ | 'playback' | 'volume' | 'power' | 'snmp'
70
+ | 'dlna-render' | 'dlna-serve'
71
+ | 'light' | 'climate' | 'sensor' | 'camera'
72
+ | 'cover' | 'switch' | 'lock' | 'fan';
73
+ ```
74
+
75
+ ## DeviceManager API
76
+
77
+ ```typescript
78
+ // Query by features
79
+ dm.getDevices(); // All devices
80
+ dm.getDevices({ hasFeature: 'scan' }); // Devices with scan feature
81
+ dm.getDevices({ name: 'Brother' }); // Devices matching name
82
+ dm.getDevicesWithFeatures(['scan', 'print']); // Devices with ALL features
83
+ dm.getDevicesWithAnyFeature(['playback', 'volume']); // Devices with ANY feature
84
+
85
+ // Select (throws if not found)
86
+ dm.selectDevice({ address: '192.168.1.100' });
87
+
88
+ // Discovery
89
+ dm.discoverScanners('192.168.1.0/24');
90
+ dm.discoverPrinters('192.168.1.0/24');
91
+ dm.scanNetwork({ ipRange: '...', probeEscl: true, ... });
92
+ dm.startDiscovery(); // mDNS/SSDP
93
+ dm.stopDiscovery();
94
+ ```
95
+
96
+ ## UniversalDevice API
97
+
98
+ ```typescript
99
+ // Feature access
100
+ device.hasFeature('scan');
101
+ device.getFeature<ScanFeature>('scan'); // Returns undefined if not found
102
+ device.selectFeature<ScanFeature>('scan'); // Throws if not found
103
+ device.getFeatureTypes(); // ['scan', 'print', ...]
104
+
105
+ // Connection
106
+ await device.connect(); // Connect all features
107
+ await device.disconnect(); // Disconnect all features
108
+ ```
109
+
110
+ ## Testing Notes
111
+
112
+ - Test files use `@git.zone/tstest` with tap-based assertions
113
+ - Import `expect` from `@git.zone/tstest/tapbundle`
114
+ - Tests are in `test/` directory
115
+ - Run with `pnpm test` or `tstest test/test.some.ts --verbose`