@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.
- package/.gitea/workflows/default_nottags.yaml +66 -0
- package/.gitea/workflows/default_tags.yaml +124 -0
- package/.vscode/launch.json +11 -0
- package/.vscode/settings.json +26 -0
- package/changelog.md +91 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/device/device.classes.device.d.ts +205 -0
- package/dist_ts/device/device.classes.device.js +344 -0
- package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
- package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
- package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
- package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
- package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
- package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
- package/dist_ts/factories/index.d.ts +190 -0
- package/dist_ts/factories/index.js +350 -0
- package/dist_ts/features/feature.abstract.d.ts +118 -0
- package/dist_ts/features/feature.abstract.js +172 -0
- package/dist_ts/features/feature.camera.d.ts +95 -0
- package/dist_ts/features/feature.camera.js +162 -0
- package/dist_ts/features/feature.climate.d.ts +174 -0
- package/dist_ts/features/feature.climate.js +328 -0
- package/dist_ts/features/feature.cover.d.ts +121 -0
- package/dist_ts/features/feature.cover.js +217 -0
- package/dist_ts/features/feature.fan.d.ts +127 -0
- package/dist_ts/features/feature.fan.js +235 -0
- package/dist_ts/features/feature.light.d.ts +156 -0
- package/dist_ts/features/feature.light.js +296 -0
- package/dist_ts/features/feature.lock.d.ts +103 -0
- package/dist_ts/features/feature.lock.js +170 -0
- package/dist_ts/features/feature.playback.d.ts +98 -0
- package/dist_ts/features/feature.playback.js +191 -0
- package/dist_ts/features/feature.power.d.ts +79 -0
- package/dist_ts/features/feature.power.js +173 -0
- package/dist_ts/features/feature.print.d.ts +78 -0
- package/dist_ts/features/feature.print.js +226 -0
- package/dist_ts/features/feature.scan.d.ts +79 -0
- package/dist_ts/features/feature.scan.js +315 -0
- package/dist_ts/features/feature.sensor.d.ts +95 -0
- package/dist_ts/features/feature.sensor.js +147 -0
- package/dist_ts/features/feature.snmp.d.ts +88 -0
- package/dist_ts/features/feature.snmp.js +175 -0
- package/dist_ts/features/feature.switch.d.ts +75 -0
- package/dist_ts/features/feature.switch.js +126 -0
- package/dist_ts/features/feature.volume.d.ts +104 -0
- package/dist_ts/features/feature.volume.js +186 -0
- package/dist_ts/features/index.d.ts +19 -0
- package/dist_ts/features/index.js +23 -0
- package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
- package/dist_ts/helpers/helpers.iprange.js +151 -0
- package/dist_ts/helpers/helpers.retry.d.ts +25 -0
- package/dist_ts/helpers/helpers.retry.js +69 -0
- package/dist_ts/index.d.ts +15 -0
- package/dist_ts/index.js +40 -0
- package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
- package/dist_ts/interfaces/feature.interfaces.js +6 -0
- package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
- package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
- package/dist_ts/interfaces/index.d.ts +330 -0
- package/dist_ts/interfaces/index.js +16 -0
- package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
- package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
- package/dist_ts/paths.d.ts +1 -0
- package/dist_ts/paths.js +3 -0
- package/dist_ts/plugins.d.ts +23 -0
- package/dist_ts/plugins.js +30 -0
- package/dist_ts/protocols/index.d.ts +12 -0
- package/dist_ts/protocols/index.js +21 -0
- package/dist_ts/protocols/protocol.escl.d.ts +58 -0
- package/dist_ts/protocols/protocol.escl.js +364 -0
- package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
- package/dist_ts/protocols/protocol.homeassistant.js +611 -0
- package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
- package/dist_ts/protocols/protocol.ipp.js +284 -0
- package/dist_ts/protocols/protocol.nut.d.ts +160 -0
- package/dist_ts/protocols/protocol.nut.js +364 -0
- package/dist_ts/protocols/protocol.sane.d.ts +104 -0
- package/dist_ts/protocols/protocol.sane.js +597 -0
- package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
- package/dist_ts/protocols/protocol.snmp.js +333 -0
- package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
- package/dist_ts/protocols/protocol.upnp.js +442 -0
- package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
- package/dist_ts/protocols/protocol.upssnmp.js +263 -0
- package/npmextra.json +24 -0
- package/package.json +39 -0
- package/readme.hints.md +115 -0
- package/readme.md +624 -0
- package/test/test.ts +261 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/device/device.classes.device.ts +454 -0
- package/ts/devicemanager.classes.devicemanager.ts +1219 -0
- package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
- package/ts/discovery/discovery.classes.mdns.ts +347 -0
- package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
- package/ts/discovery/discovery.classes.ssdp.ts +357 -0
- package/ts/factories/index.ts +696 -0
- package/ts/features/feature.abstract.ts +251 -0
- package/ts/features/feature.camera.ts +214 -0
- package/ts/features/feature.climate.ts +407 -0
- package/ts/features/feature.cover.ts +278 -0
- package/ts/features/feature.fan.ts +296 -0
- package/ts/features/feature.light.ts +369 -0
- package/ts/features/feature.lock.ts +223 -0
- package/ts/features/feature.playback.ts +246 -0
- package/ts/features/feature.power.ts +231 -0
- package/ts/features/feature.print.ts +297 -0
- package/ts/features/feature.scan.ts +370 -0
- package/ts/features/feature.sensor.ts +202 -0
- package/ts/features/feature.snmp.ts +235 -0
- package/ts/features/feature.switch.ts +170 -0
- package/ts/features/feature.volume.ts +256 -0
- package/ts/features/index.ts +25 -0
- package/ts/helpers/helpers.iprange.ts +172 -0
- package/ts/helpers/helpers.retry.ts +100 -0
- package/ts/index.ts +165 -0
- package/ts/interfaces/feature.interfaces.ts +359 -0
- package/ts/interfaces/homeassistant.interfaces.ts +666 -0
- package/ts/interfaces/index.ts +421 -0
- package/ts/interfaces/smarthome.interfaces.ts +421 -0
- package/ts/paths.ts +5 -0
- package/ts/plugins.ts +41 -0
- package/ts/protocols/index.ts +59 -0
- package/ts/protocols/protocol.escl.ts +439 -0
- package/ts/protocols/protocol.homeassistant.ts +737 -0
- package/ts/protocols/protocol.ipp.ts +329 -0
- package/ts/protocols/protocol.nut.ts +471 -0
- package/ts/protocols/protocol.sane.ts +694 -0
- package/ts/protocols/protocol.snmp.ts +439 -0
- package/ts/protocols/protocol.upnp.ts +627 -0
- package/ts/protocols/protocol.upssnmp.ts +377 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensor Feature
|
|
3
|
+
* Provides read-only state for sensors (temperature, humidity, power, etc.)
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
import type { TSensorProtocol, TSensorDeviceClass, TSensorStateClass, ISensorCapabilities, ISensorState, ISensorFeatureInfo, ISensorProtocolClient } from '../interfaces/smarthome.interfaces.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating a SensorFeature
|
|
10
|
+
*/
|
|
11
|
+
export interface ISensorFeatureOptions extends IFeatureOptions {
|
|
12
|
+
/** Protocol type */
|
|
13
|
+
protocol: TSensorProtocol;
|
|
14
|
+
/** Entity ID (for Home Assistant) */
|
|
15
|
+
entityId: string;
|
|
16
|
+
/** Protocol client for reading sensor state */
|
|
17
|
+
protocolClient: ISensorProtocolClient;
|
|
18
|
+
/** Device class (temperature, humidity, etc.) */
|
|
19
|
+
deviceClass?: TSensorDeviceClass;
|
|
20
|
+
/** State class (measurement, total, etc.) */
|
|
21
|
+
stateClass?: TSensorStateClass;
|
|
22
|
+
/** Unit of measurement */
|
|
23
|
+
unit?: string;
|
|
24
|
+
/** Precision (decimal places) */
|
|
25
|
+
precision?: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Sensor Feature - read-only state values
|
|
29
|
+
*
|
|
30
|
+
* Protocol-agnostic: works with Home Assistant, MQTT, SNMP, etc.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const sensor = device.getFeature<SensorFeature>('sensor');
|
|
35
|
+
* if (sensor) {
|
|
36
|
+
* await sensor.refreshState();
|
|
37
|
+
* console.log(`Temperature: ${sensor.value} ${sensor.unit}`);
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class SensorFeature extends Feature {
|
|
42
|
+
readonly type: "sensor";
|
|
43
|
+
readonly protocol: TSensorProtocol;
|
|
44
|
+
/** Entity ID (e.g., "sensor.living_room_temperature") */
|
|
45
|
+
readonly entityId: string;
|
|
46
|
+
/** Capabilities */
|
|
47
|
+
readonly capabilities: ISensorCapabilities;
|
|
48
|
+
/** Current state */
|
|
49
|
+
protected _value: string | number | boolean;
|
|
50
|
+
protected _numericValue?: number;
|
|
51
|
+
protected _unit?: string;
|
|
52
|
+
protected _lastUpdated: Date;
|
|
53
|
+
/** Protocol client for reading sensor state */
|
|
54
|
+
private protocolClient;
|
|
55
|
+
constructor(device: TDeviceReference, port: number, options: ISensorFeatureOptions);
|
|
56
|
+
/**
|
|
57
|
+
* Get current value (cached)
|
|
58
|
+
*/
|
|
59
|
+
get value(): string | number | boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get numeric value if available (cached)
|
|
62
|
+
*/
|
|
63
|
+
get numericValue(): number | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Get unit of measurement
|
|
66
|
+
*/
|
|
67
|
+
get unit(): string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Get device class
|
|
70
|
+
*/
|
|
71
|
+
get deviceClass(): TSensorDeviceClass | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Get state class
|
|
74
|
+
*/
|
|
75
|
+
get stateClass(): TSensorStateClass | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* Get last updated timestamp
|
|
78
|
+
*/
|
|
79
|
+
get lastUpdated(): Date;
|
|
80
|
+
protected doConnect(): Promise<void>;
|
|
81
|
+
protected doDisconnect(): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Refresh state from the device
|
|
84
|
+
*/
|
|
85
|
+
refreshState(): Promise<ISensorState>;
|
|
86
|
+
/**
|
|
87
|
+
* Update state from external source (e.g., state change event)
|
|
88
|
+
*/
|
|
89
|
+
updateState(state: ISensorState): void;
|
|
90
|
+
/**
|
|
91
|
+
* Internal state update
|
|
92
|
+
*/
|
|
93
|
+
private updateStateInternal;
|
|
94
|
+
getFeatureInfo(): ISensorFeatureInfo;
|
|
95
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sensor Feature
|
|
3
|
+
* Provides read-only state for sensors (temperature, humidity, power, etc.)
|
|
4
|
+
*/
|
|
5
|
+
import { Feature } from './feature.abstract.js';
|
|
6
|
+
/**
|
|
7
|
+
* Sensor Feature - read-only state values
|
|
8
|
+
*
|
|
9
|
+
* Protocol-agnostic: works with Home Assistant, MQTT, SNMP, etc.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const sensor = device.getFeature<SensorFeature>('sensor');
|
|
14
|
+
* if (sensor) {
|
|
15
|
+
* await sensor.refreshState();
|
|
16
|
+
* console.log(`Temperature: ${sensor.value} ${sensor.unit}`);
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export class SensorFeature extends Feature {
|
|
21
|
+
type = 'sensor';
|
|
22
|
+
protocol;
|
|
23
|
+
/** Entity ID (e.g., "sensor.living_room_temperature") */
|
|
24
|
+
entityId;
|
|
25
|
+
/** Capabilities */
|
|
26
|
+
capabilities;
|
|
27
|
+
/** Current state */
|
|
28
|
+
_value = '';
|
|
29
|
+
_numericValue;
|
|
30
|
+
_unit;
|
|
31
|
+
_lastUpdated = new Date();
|
|
32
|
+
/** Protocol client for reading sensor state */
|
|
33
|
+
protocolClient;
|
|
34
|
+
constructor(device, port, options) {
|
|
35
|
+
super(device, port, options);
|
|
36
|
+
this.protocol = options.protocol;
|
|
37
|
+
this.entityId = options.entityId;
|
|
38
|
+
this.protocolClient = options.protocolClient;
|
|
39
|
+
this.capabilities = {
|
|
40
|
+
deviceClass: options.deviceClass,
|
|
41
|
+
stateClass: options.stateClass,
|
|
42
|
+
unit: options.unit,
|
|
43
|
+
precision: options.precision,
|
|
44
|
+
};
|
|
45
|
+
this._unit = options.unit;
|
|
46
|
+
}
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Properties
|
|
49
|
+
// ============================================================================
|
|
50
|
+
/**
|
|
51
|
+
* Get current value (cached)
|
|
52
|
+
*/
|
|
53
|
+
get value() {
|
|
54
|
+
return this._value;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get numeric value if available (cached)
|
|
58
|
+
*/
|
|
59
|
+
get numericValue() {
|
|
60
|
+
return this._numericValue;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get unit of measurement
|
|
64
|
+
*/
|
|
65
|
+
get unit() {
|
|
66
|
+
return this._unit;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get device class
|
|
70
|
+
*/
|
|
71
|
+
get deviceClass() {
|
|
72
|
+
return this.capabilities.deviceClass;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get state class
|
|
76
|
+
*/
|
|
77
|
+
get stateClass() {
|
|
78
|
+
return this.capabilities.stateClass;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get last updated timestamp
|
|
82
|
+
*/
|
|
83
|
+
get lastUpdated() {
|
|
84
|
+
return this._lastUpdated;
|
|
85
|
+
}
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// Connection
|
|
88
|
+
// ============================================================================
|
|
89
|
+
async doConnect() {
|
|
90
|
+
// Fetch initial state
|
|
91
|
+
try {
|
|
92
|
+
const state = await this.protocolClient.getState(this.entityId);
|
|
93
|
+
this.updateStateInternal(state);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Ignore errors fetching initial state
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async doDisconnect() {
|
|
100
|
+
// Nothing to disconnect
|
|
101
|
+
}
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Sensor Reading
|
|
104
|
+
// ============================================================================
|
|
105
|
+
/**
|
|
106
|
+
* Refresh state from the device
|
|
107
|
+
*/
|
|
108
|
+
async refreshState() {
|
|
109
|
+
const state = await this.protocolClient.getState(this.entityId);
|
|
110
|
+
this.updateStateInternal(state);
|
|
111
|
+
return state;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Update state from external source (e.g., state change event)
|
|
115
|
+
*/
|
|
116
|
+
updateState(state) {
|
|
117
|
+
this.updateStateInternal(state);
|
|
118
|
+
this.emit('state:changed', state);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Internal state update
|
|
122
|
+
*/
|
|
123
|
+
updateStateInternal(state) {
|
|
124
|
+
this._value = state.value;
|
|
125
|
+
this._numericValue = state.numericValue;
|
|
126
|
+
this._unit = state.unit || this._unit;
|
|
127
|
+
this._lastUpdated = state.lastUpdated;
|
|
128
|
+
}
|
|
129
|
+
// ============================================================================
|
|
130
|
+
// Feature Info
|
|
131
|
+
// ============================================================================
|
|
132
|
+
getFeatureInfo() {
|
|
133
|
+
return {
|
|
134
|
+
...this.getBaseFeatureInfo(),
|
|
135
|
+
type: 'sensor',
|
|
136
|
+
protocol: this.protocol,
|
|
137
|
+
capabilities: this.capabilities,
|
|
138
|
+
currentState: {
|
|
139
|
+
value: this._value,
|
|
140
|
+
numericValue: this._numericValue,
|
|
141
|
+
unit: this._unit,
|
|
142
|
+
lastUpdated: this._lastUpdated,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS5zZW5zb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9mZWF0dXJlcy9mZWF0dXJlLnNlbnNvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsT0FBTyxFQUF5QixNQUFNLHVCQUF1QixDQUFDO0FBZ0N2RTs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxPQUFPLGFBQWMsU0FBUSxPQUFPO0lBQ3hCLElBQUksR0FBRyxRQUFpQixDQUFDO0lBQ3pCLFFBQVEsQ0FBa0I7SUFFMUMseURBQXlEO0lBQ3pDLFFBQVEsQ0FBUztJQUVqQyxtQkFBbUI7SUFDSCxZQUFZLENBQXNCO0lBRWxELG9CQUFvQjtJQUNWLE1BQU0sR0FBOEIsRUFBRSxDQUFDO0lBQ3ZDLGFBQWEsQ0FBVTtJQUN2QixLQUFLLENBQVU7SUFDZixZQUFZLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUUxQywrQ0FBK0M7SUFDdkMsY0FBYyxDQUF3QjtJQUU5QyxZQUNFLE1BQXdCLEVBQ3hCLElBQVksRUFDWixPQUE4QjtRQUU5QixLQUFLLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7UUFDakMsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxjQUFjLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQztRQUM3QyxJQUFJLENBQUMsWUFBWSxHQUFHO1lBQ2xCLFdBQVcsRUFBRSxPQUFPLENBQUMsV0FBVztZQUNoQyxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVU7WUFDOUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1lBQ2xCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztTQUM3QixDQUFDO1FBQ0YsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMs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
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SNMP Feature
|
|
3
|
+
* Provides SNMP query capability for network management
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { TSnmpVersion, ISnmpVarbind, ISnmpFeatureInfo, IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
/**
|
|
8
|
+
* Options for creating an SnmpFeature
|
|
9
|
+
*/
|
|
10
|
+
export interface ISnmpFeatureOptions extends IFeatureOptions {
|
|
11
|
+
version?: TSnmpVersion;
|
|
12
|
+
community?: string;
|
|
13
|
+
username?: string;
|
|
14
|
+
authProtocol?: 'md5' | 'sha';
|
|
15
|
+
authKey?: string;
|
|
16
|
+
privProtocol?: 'des' | 'aes';
|
|
17
|
+
privKey?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* SNMP Feature - provides SNMP query capability
|
|
21
|
+
*
|
|
22
|
+
* Allows querying devices via SNMP for monitoring and management.
|
|
23
|
+
* Many network devices (printers, switches, UPS) support SNMP.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* const snmp = device.getFeature<SnmpFeature>('snmp');
|
|
28
|
+
* if (snmp) {
|
|
29
|
+
* const sysDescr = await snmp.get('1.3.6.1.2.1.1.1.0');
|
|
30
|
+
* console.log(`System: ${sysDescr.value}`);
|
|
31
|
+
*
|
|
32
|
+
* const interfaces = await snmp.walk('1.3.6.1.2.1.2.2.1');
|
|
33
|
+
* console.log(`Found ${interfaces.length} interface entries`);
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare class SnmpFeature extends Feature {
|
|
38
|
+
readonly type: "snmp";
|
|
39
|
+
readonly protocol = "snmp";
|
|
40
|
+
readonly version: TSnmpVersion;
|
|
41
|
+
readonly community: string;
|
|
42
|
+
sysDescr?: string;
|
|
43
|
+
sysObjectId?: string;
|
|
44
|
+
sysName?: string;
|
|
45
|
+
sysLocation?: string;
|
|
46
|
+
sysContact?: string;
|
|
47
|
+
sysUpTime?: number;
|
|
48
|
+
constructor(device: TDeviceReference, port: number, options?: ISnmpFeatureOptions);
|
|
49
|
+
protected doConnect(): Promise<void>;
|
|
50
|
+
protected doDisconnect(): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Get a single OID value
|
|
53
|
+
*/
|
|
54
|
+
get(oid: string): Promise<ISnmpVarbind>;
|
|
55
|
+
/**
|
|
56
|
+
* Get multiple OID values
|
|
57
|
+
*/
|
|
58
|
+
getMultiple(oids: string[]): Promise<ISnmpVarbind[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Get next OID in MIB tree
|
|
61
|
+
*/
|
|
62
|
+
getNext(oid: string): Promise<ISnmpVarbind>;
|
|
63
|
+
/**
|
|
64
|
+
* Walk a subtree of the MIB
|
|
65
|
+
*/
|
|
66
|
+
walk(baseOid: string): Promise<ISnmpVarbind[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Bulk get (SNMPv2c/v3)
|
|
69
|
+
*/
|
|
70
|
+
getBulk(oids: string[], nonRepeaters?: number, maxRepetitions?: number): Promise<ISnmpVarbind[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Set an OID value
|
|
73
|
+
*/
|
|
74
|
+
set(oid: string, type: number, value: unknown): Promise<ISnmpVarbind>;
|
|
75
|
+
/**
|
|
76
|
+
* Get all system info OIDs
|
|
77
|
+
*/
|
|
78
|
+
getSystemInfo(): Promise<{
|
|
79
|
+
sysDescr?: string;
|
|
80
|
+
sysObjectId?: string;
|
|
81
|
+
sysName?: string;
|
|
82
|
+
sysLocation?: string;
|
|
83
|
+
sysContact?: string;
|
|
84
|
+
sysUpTime?: number;
|
|
85
|
+
}>;
|
|
86
|
+
getFeatureInfo(): ISnmpFeatureInfo;
|
|
87
|
+
static fromDiscovery(device: TDeviceReference, port: number, metadata: Record<string, unknown>): SnmpFeature;
|
|
88
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SNMP Feature
|
|
3
|
+
* Provides SNMP query capability for network management
|
|
4
|
+
*/
|
|
5
|
+
import { Feature } from './feature.abstract.js';
|
|
6
|
+
/**
|
|
7
|
+
* SNMP Feature - provides SNMP query capability
|
|
8
|
+
*
|
|
9
|
+
* Allows querying devices via SNMP for monitoring and management.
|
|
10
|
+
* Many network devices (printers, switches, UPS) support SNMP.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const snmp = device.getFeature<SnmpFeature>('snmp');
|
|
15
|
+
* if (snmp) {
|
|
16
|
+
* const sysDescr = await snmp.get('1.3.6.1.2.1.1.1.0');
|
|
17
|
+
* console.log(`System: ${sysDescr.value}`);
|
|
18
|
+
*
|
|
19
|
+
* const interfaces = await snmp.walk('1.3.6.1.2.1.2.2.1');
|
|
20
|
+
* console.log(`Found ${interfaces.length} interface entries`);
|
|
21
|
+
* }
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class SnmpFeature extends Feature {
|
|
25
|
+
type = 'snmp';
|
|
26
|
+
protocol = 'snmp';
|
|
27
|
+
// Configuration
|
|
28
|
+
version;
|
|
29
|
+
community;
|
|
30
|
+
// System info (populated after connect)
|
|
31
|
+
sysDescr;
|
|
32
|
+
sysObjectId;
|
|
33
|
+
sysName;
|
|
34
|
+
sysLocation;
|
|
35
|
+
sysContact;
|
|
36
|
+
sysUpTime;
|
|
37
|
+
constructor(device, port, options) {
|
|
38
|
+
super(device, port ?? 161, options);
|
|
39
|
+
this.version = options?.version ?? 'v2c';
|
|
40
|
+
this.community = options?.community ?? 'public';
|
|
41
|
+
}
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Connection
|
|
44
|
+
// ============================================================================
|
|
45
|
+
async doConnect() {
|
|
46
|
+
// Test connection by getting system description
|
|
47
|
+
try {
|
|
48
|
+
const result = await this.get('1.3.6.1.2.1.1.1.0'); // sysDescr
|
|
49
|
+
if (result) {
|
|
50
|
+
this.sysDescr = String(result.value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// Connection test failed
|
|
55
|
+
throw new Error('SNMP connection failed');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async doDisconnect() {
|
|
59
|
+
// SNMP is connectionless, nothing to disconnect
|
|
60
|
+
}
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// SNMP Operations
|
|
63
|
+
// ============================================================================
|
|
64
|
+
/**
|
|
65
|
+
* Get a single OID value
|
|
66
|
+
*/
|
|
67
|
+
async get(oid) {
|
|
68
|
+
// This would use the SNMP library to perform the query
|
|
69
|
+
// Placeholder implementation
|
|
70
|
+
return {
|
|
71
|
+
oid,
|
|
72
|
+
type: 0,
|
|
73
|
+
value: null,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get multiple OID values
|
|
78
|
+
*/
|
|
79
|
+
async getMultiple(oids) {
|
|
80
|
+
const results = [];
|
|
81
|
+
for (const oid of oids) {
|
|
82
|
+
results.push(await this.get(oid));
|
|
83
|
+
}
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get next OID in MIB tree
|
|
88
|
+
*/
|
|
89
|
+
async getNext(oid) {
|
|
90
|
+
// Placeholder
|
|
91
|
+
return {
|
|
92
|
+
oid,
|
|
93
|
+
type: 0,
|
|
94
|
+
value: null,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Walk a subtree of the MIB
|
|
99
|
+
*/
|
|
100
|
+
async walk(baseOid) {
|
|
101
|
+
const results = [];
|
|
102
|
+
// This would iterate through the MIB tree using getNext
|
|
103
|
+
return results;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Bulk get (SNMPv2c/v3)
|
|
107
|
+
*/
|
|
108
|
+
async getBulk(oids, nonRepeaters = 0, maxRepetitions = 10) {
|
|
109
|
+
if (this.version === 'v1') {
|
|
110
|
+
throw new Error('getBulk not supported in SNMPv1');
|
|
111
|
+
}
|
|
112
|
+
// Placeholder
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Set an OID value
|
|
117
|
+
*/
|
|
118
|
+
async set(oid, type, value) {
|
|
119
|
+
// Placeholder
|
|
120
|
+
return {
|
|
121
|
+
oid,
|
|
122
|
+
type,
|
|
123
|
+
value,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// System Info
|
|
128
|
+
// ============================================================================
|
|
129
|
+
/**
|
|
130
|
+
* Get all system info OIDs
|
|
131
|
+
*/
|
|
132
|
+
async getSystemInfo() {
|
|
133
|
+
const oids = [
|
|
134
|
+
'1.3.6.1.2.1.1.1.0', // sysDescr
|
|
135
|
+
'1.3.6.1.2.1.1.2.0', // sysObjectID
|
|
136
|
+
'1.3.6.1.2.1.1.3.0', // sysUpTime
|
|
137
|
+
'1.3.6.1.2.1.1.4.0', // sysContact
|
|
138
|
+
'1.3.6.1.2.1.1.5.0', // sysName
|
|
139
|
+
'1.3.6.1.2.1.1.6.0', // sysLocation
|
|
140
|
+
];
|
|
141
|
+
const results = await this.getMultiple(oids);
|
|
142
|
+
return {
|
|
143
|
+
sysDescr: results[0]?.value,
|
|
144
|
+
sysObjectId: results[1]?.value,
|
|
145
|
+
sysUpTime: results[2]?.value,
|
|
146
|
+
sysContact: results[3]?.value,
|
|
147
|
+
sysName: results[4]?.value,
|
|
148
|
+
sysLocation: results[5]?.value,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
// ============================================================================
|
|
152
|
+
// Serialization
|
|
153
|
+
// ============================================================================
|
|
154
|
+
getFeatureInfo() {
|
|
155
|
+
return {
|
|
156
|
+
...this.getBaseFeatureInfo(),
|
|
157
|
+
type: 'snmp',
|
|
158
|
+
version: this.version,
|
|
159
|
+
community: this.version !== 'v3' ? this.community : undefined,
|
|
160
|
+
sysDescr: this.sysDescr,
|
|
161
|
+
sysName: this.sysName,
|
|
162
|
+
sysLocation: this.sysLocation,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Static Factory
|
|
167
|
+
// ============================================================================
|
|
168
|
+
static fromDiscovery(device, port, metadata) {
|
|
169
|
+
return new SnmpFeature(device, port ?? 161, {
|
|
170
|
+
version: metadata.version ?? 'v2c',
|
|
171
|
+
community: metadata.community ?? 'public',
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS5zbm1wLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZmVhdHVyZXMvZmVhdHVyZS5zbm1wLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFBRSxPQUFPLEVBQXlCLE1BQU0sdUJBQXVCLENBQUM7QUFzQnZFOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sT0FBTyxXQUFZLFNBQVEsT0FBTztJQUN0QixJQUFJLEdBQUcsTUFBZSxDQUFDO0lBQ3ZCLFFBQVEsR0FBRyxNQUFNLENBQUM7SUFFbEMsZ0JBQWdCO0lBQ0EsT0FBTyxDQUFlO0lBQ3RCLFNBQVMsQ0FBUztJQUVsQyx3Q0FBd0M7SUFDakMsUUFBUSxDQUFVO0lBQ2xCLFdBQVcsQ0FBVTtJQUNyQixPQUFPLENBQVU7SUFDakIsV0FBVyxDQUFVO0lBQ3JCLFVBQVUsQ0FBVTtJQUNwQixTQUFTLENBQVU7SUFFMUIsWUFDRSxNQUF3QixFQUN4QixJQUFZLEVBQ1osT0FBNkI7UUFFN0IsS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLElBQUksR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxFQUFFLE9BQU8sSUFBSSxLQUFLLENBQUM7UUFDekMsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLEVBQUUsU0FBUyxJQUFJLFFBQVEsQ0FBQztJQUNsRCxDQUFDO0lBRUQsK0VBQStFO0lBQy9FLGFBQWE7SUFDYiwrRUFBK0U7SUFFckUsS0FBSyxDQUFDLFNBQVM7UUFDdkIsZ0RBQWdEO1FBQ2hELElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUMsV0FBVztZQUMvRCxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFL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
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch Feature
|
|
3
|
+
* Provides binary on/off control for smart switches, outlets, etc.
|
|
4
|
+
*/
|
|
5
|
+
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
6
|
+
import type { IFeatureOptions } from '../interfaces/feature.interfaces.js';
|
|
7
|
+
import type { TSwitchProtocol, ISwitchCapabilities, ISwitchState, ISwitchFeatureInfo, ISwitchProtocolClient } from '../interfaces/smarthome.interfaces.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for creating a SwitchFeature
|
|
10
|
+
*/
|
|
11
|
+
export interface ISwitchFeatureOptions extends IFeatureOptions {
|
|
12
|
+
/** Protocol type */
|
|
13
|
+
protocol: TSwitchProtocol;
|
|
14
|
+
/** Entity ID (for Home Assistant) */
|
|
15
|
+
entityId: string;
|
|
16
|
+
/** Protocol client for controlling the switch */
|
|
17
|
+
protocolClient: ISwitchProtocolClient;
|
|
18
|
+
/** Device class */
|
|
19
|
+
deviceClass?: 'outlet' | 'switch';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Switch Feature - binary on/off control
|
|
23
|
+
*
|
|
24
|
+
* Protocol-agnostic: works with Home Assistant, MQTT, Tasmota, Tuya, etc.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const sw = device.getFeature<SwitchFeature>('switch');
|
|
29
|
+
* if (sw) {
|
|
30
|
+
* await sw.turnOn();
|
|
31
|
+
* await sw.toggle();
|
|
32
|
+
* console.log(`Switch is ${sw.isOn ? 'on' : 'off'}`);
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class SwitchFeature extends Feature {
|
|
37
|
+
readonly type: "switch";
|
|
38
|
+
readonly protocol: TSwitchProtocol;
|
|
39
|
+
/** Entity ID (e.g., "switch.living_room") */
|
|
40
|
+
readonly entityId: string;
|
|
41
|
+
/** Capabilities */
|
|
42
|
+
readonly capabilities: ISwitchCapabilities;
|
|
43
|
+
/** Current state */
|
|
44
|
+
protected _isOn: boolean;
|
|
45
|
+
/** Protocol client for controlling the switch */
|
|
46
|
+
private protocolClient;
|
|
47
|
+
constructor(device: TDeviceReference, port: number, options: ISwitchFeatureOptions);
|
|
48
|
+
/**
|
|
49
|
+
* Get current on/off state (cached)
|
|
50
|
+
*/
|
|
51
|
+
get isOn(): boolean;
|
|
52
|
+
protected doConnect(): Promise<void>;
|
|
53
|
+
protected doDisconnect(): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Turn on the switch
|
|
56
|
+
*/
|
|
57
|
+
turnOn(): Promise<void>;
|
|
58
|
+
/**
|
|
59
|
+
* Turn off the switch
|
|
60
|
+
*/
|
|
61
|
+
turnOff(): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Toggle the switch
|
|
64
|
+
*/
|
|
65
|
+
toggle(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Refresh state from the device
|
|
68
|
+
*/
|
|
69
|
+
refreshState(): Promise<ISwitchState>;
|
|
70
|
+
/**
|
|
71
|
+
* Update state from external source (e.g., state change event)
|
|
72
|
+
*/
|
|
73
|
+
updateState(state: ISwitchState): void;
|
|
74
|
+
getFeatureInfo(): ISwitchFeatureInfo;
|
|
75
|
+
}
|