matterbridge-iotas 1.0.2 → 1.1.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/dist/src/deviceFactory.d.ts +12 -0
- package/dist/src/deviceFactory.js +65 -0
- package/dist/src/deviceFactory.js.map +1 -0
- package/dist/src/devices/helpers.d.ts +18 -0
- package/dist/src/devices/helpers.js +91 -0
- package/dist/src/devices/helpers.js.map +1 -0
- package/dist/src/devices/lights.d.ts +4 -0
- package/dist/src/devices/lights.js +71 -0
- package/dist/src/devices/lights.js.map +1 -0
- package/dist/src/devices/lock.d.ts +3 -0
- package/dist/src/devices/lock.js +44 -0
- package/dist/src/devices/lock.js.map +1 -0
- package/dist/src/devices/outlet.d.ts +3 -0
- package/dist/src/devices/outlet.js +6 -0
- package/dist/src/devices/outlet.js.map +1 -0
- package/dist/src/devices/sensors.d.ts +5 -0
- package/dist/src/devices/sensors.js +44 -0
- package/dist/src/devices/sensors.js.map +1 -0
- package/dist/src/devices/thermostat.d.ts +9 -0
- package/dist/src/devices/thermostat.js +95 -0
- package/dist/src/devices/thermostat.js.map +1 -0
- package/dist/src/devices/types.d.ts +26 -0
- package/dist/src/devices/types.js +5 -0
- package/dist/src/devices/types.js.map +1 -0
- package/dist/src/module.d.ts +24 -0
- package/dist/src/module.js +121 -0
- package/dist/src/module.js.map +1 -0
- package/dist/test/deviceFactory.test.d.ts +1 -0
- package/dist/test/deviceFactory.test.js +168 -0
- package/dist/test/deviceFactory.test.js.map +1 -0
- package/dist/test/devices/helpers.d.ts +18 -0
- package/dist/test/devices/helpers.js +70 -0
- package/dist/test/devices/helpers.js.map +1 -0
- package/dist/test/devices/lights.test.d.ts +1 -0
- package/dist/test/devices/lights.test.js +49 -0
- package/dist/test/devices/lights.test.js.map +1 -0
- package/dist/test/devices/lock.test.d.ts +1 -0
- package/dist/test/devices/lock.test.js +43 -0
- package/dist/test/devices/lock.test.js.map +1 -0
- package/dist/test/devices/outlet.test.d.ts +1 -0
- package/dist/test/devices/outlet.test.js +18 -0
- package/dist/test/devices/outlet.test.js.map +1 -0
- package/dist/test/devices/sensors.test.d.ts +1 -0
- package/dist/test/devices/sensors.test.js +44 -0
- package/dist/test/devices/sensors.test.js.map +1 -0
- package/dist/test/devices/thermostat.test.d.ts +1 -0
- package/dist/test/devices/thermostat.test.js +64 -0
- package/dist/test/devices/thermostat.test.js.map +1 -0
- package/dist/test/module.test.d.ts +1 -0
- package/dist/test/module.test.js +88 -0
- package/dist/test/module.test.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Factory - Router that maps IOTAS device categories to factory functions.
|
|
3
|
+
*
|
|
4
|
+
* Individual device factories live in src/devices/.
|
|
5
|
+
* This module provides createEndpointForDevice (the router).
|
|
6
|
+
*/
|
|
7
|
+
import { type Device } from 'iotas-ts';
|
|
8
|
+
import type { DeviceFactoryContext, EndpointResult } from './devices/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Main factory function - creates appropriate endpoint based on device category.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createEndpointForDevice(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Factory - Router that maps IOTAS device categories to factory functions.
|
|
3
|
+
*
|
|
4
|
+
* Individual device factories live in src/devices/.
|
|
5
|
+
* This module provides createEndpointForDevice (the router).
|
|
6
|
+
*/
|
|
7
|
+
import { DeviceCategory, EventTypeName, FeatureCategory, isDeviceCategory } from 'iotas-ts';
|
|
8
|
+
import { createDimmableLight, createOnOffLight } from './devices/lights.js';
|
|
9
|
+
import { createOnOffOutlet } from './devices/outlet.js';
|
|
10
|
+
import { createDoorLock } from './devices/lock.js';
|
|
11
|
+
import { createThermostat } from './devices/thermostat.js';
|
|
12
|
+
import { createHumiditySensor, createOccupancySensor, createContactSensor } from './devices/sensors.js';
|
|
13
|
+
function handleSwitch(device, ctx) {
|
|
14
|
+
const isLight = device.features.some((f) => f.isLight);
|
|
15
|
+
return isLight ? createOnOffLight(device, ctx) : createOnOffOutlet(device, ctx);
|
|
16
|
+
}
|
|
17
|
+
function handleDimmer(device, ctx) {
|
|
18
|
+
const hasLevel = device.features.some((f) => f.eventTypeName === EventTypeName.Level);
|
|
19
|
+
if (hasLevel) {
|
|
20
|
+
return createDimmableLight(device, ctx);
|
|
21
|
+
}
|
|
22
|
+
return handleSwitch(device, ctx);
|
|
23
|
+
}
|
|
24
|
+
const categoryHandlers = new Map([
|
|
25
|
+
[DeviceCategory.Dimmer, handleDimmer],
|
|
26
|
+
[DeviceCategory.Switch, handleSwitch],
|
|
27
|
+
[DeviceCategory.MotionSwitch, handleSwitch],
|
|
28
|
+
[DeviceCategory.Lock, createDoorLock],
|
|
29
|
+
[DeviceCategory.Thermostat, createThermostat],
|
|
30
|
+
[DeviceCategory.Door, createContactSensor],
|
|
31
|
+
]);
|
|
32
|
+
/**
|
|
33
|
+
* Feature-based fallbacks for unknown categories.
|
|
34
|
+
*
|
|
35
|
+
* Precedence is defined by array order (first match wins):
|
|
36
|
+
* 1) humidity
|
|
37
|
+
* 2) motion
|
|
38
|
+
*/
|
|
39
|
+
const featureFallbacks = [
|
|
40
|
+
{ category: FeatureCategory.Humidity, handler: createHumiditySensor },
|
|
41
|
+
{ category: FeatureCategory.Motion, handler: createOccupancySensor },
|
|
42
|
+
];
|
|
43
|
+
/**
|
|
44
|
+
* Main factory function - creates appropriate endpoint based on device category.
|
|
45
|
+
*/
|
|
46
|
+
export function createEndpointForDevice(device, ctx) {
|
|
47
|
+
if (!device.paired) {
|
|
48
|
+
ctx.log.debug(`Skipping unpaired device: ${device.name}`);
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (isDeviceCategory(device.category)) {
|
|
52
|
+
const handler = categoryHandlers.get(device.category);
|
|
53
|
+
if (handler) {
|
|
54
|
+
return handler(device, ctx);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
for (const { category, handler: fallbackHandler } of featureFallbacks) {
|
|
58
|
+
if (device.features.some((f) => f.featureTypeCategory === category)) {
|
|
59
|
+
return fallbackHandler(device, ctx);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
ctx.log.warn(`Unsupported device category: ${device.category} for device ${device.name}`);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=deviceFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceFactory.js","sourceRoot":"","sources":["../../src/deviceFactory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { bridgedNode, MatterbridgeEndpoint } from 'matterbridge';
|
|
2
|
+
import type { DeviceTypeDefinition } from 'matterbridge';
|
|
3
|
+
import type { Device } from 'iotas-ts';
|
|
4
|
+
import { type FeatureCategory } from 'iotas-ts';
|
|
5
|
+
import type { DeviceFactoryContext, EndpointResult } from './types.js';
|
|
6
|
+
export { bridgedNode };
|
|
7
|
+
export declare function requireFeature(device: Device, category: FeatureCategory, ctx: DeviceFactoryContext, label: string): import("iotas-ts").Feature | null;
|
|
8
|
+
export declare function createBridgedEndpoint(deviceTypes: [DeviceTypeDefinition, ...DeviceTypeDefinition[]], device: Device, ctx: DeviceFactoryContext): MatterbridgeEndpoint;
|
|
9
|
+
export declare function toMatterLevel(iotasLevel: number): number;
|
|
10
|
+
export declare function fromMatterLevel(matterLevel: number): number;
|
|
11
|
+
export declare function toMatterHumidity(iotasHumidity: number): number;
|
|
12
|
+
export declare function toCelsius(fahrenheit: number): number;
|
|
13
|
+
export declare function toMatterCentiCelsius(fahrenheit: number): number;
|
|
14
|
+
export declare function fromMatterCentiCelsius(centiCelsius: number): number;
|
|
15
|
+
export declare function addOnOffHandlers(endpoint: MatterbridgeEndpoint, featureId: number, ctx: DeviceFactoryContext): void;
|
|
16
|
+
export declare function multiFeatureResult(endpoint: MatterbridgeEndpoint, handlers: Map<number, (value: number) => void>): EndpointResult;
|
|
17
|
+
export declare function singleFeatureResult(endpoint: MatterbridgeEndpoint, featureId: number, onUpdate: (value: number) => void): EndpointResult;
|
|
18
|
+
export declare function createSimpleOnOffDevice(deviceType: DeviceTypeDefinition, device: Device, ctx: DeviceFactoryContext, label: string): EndpointResult | null;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { bridgedNode, MatterbridgeEndpoint } from 'matterbridge';
|
|
2
|
+
import { OnOff } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { findFeatureByCategory, findFeatureByEventType, getManufacturer, getModel, getSerialNumber, Temperature, } from 'iotas-ts';
|
|
4
|
+
import { EventTypeName } from 'iotas-ts';
|
|
5
|
+
import { VENDOR_ID } from './types.js';
|
|
6
|
+
export { bridgedNode };
|
|
7
|
+
function makeDeviceId(device) {
|
|
8
|
+
return `iotas-${device.id}`;
|
|
9
|
+
}
|
|
10
|
+
export function requireFeature(device, category, ctx, label) {
|
|
11
|
+
const feature = findFeatureByCategory(device, category);
|
|
12
|
+
if (!feature) {
|
|
13
|
+
ctx.log.warn(`Device ${device.name} missing ${category} feature for ${label}`);
|
|
14
|
+
}
|
|
15
|
+
return feature ?? null;
|
|
16
|
+
}
|
|
17
|
+
function requireFeatureByEventType(device, eventTypeName, ctx, label) {
|
|
18
|
+
const feature = findFeatureByEventType(device, eventTypeName);
|
|
19
|
+
if (!feature) {
|
|
20
|
+
ctx.log.warn(`Device ${device.name} missing ${eventTypeName} feature for ${label}`);
|
|
21
|
+
}
|
|
22
|
+
return feature ?? null;
|
|
23
|
+
}
|
|
24
|
+
export function createBridgedEndpoint(deviceTypes, device, ctx) {
|
|
25
|
+
return new MatterbridgeEndpoint(deviceTypes, { id: makeDeviceId(device) }, ctx.debug)
|
|
26
|
+
.createDefaultIdentifyClusterServer()
|
|
27
|
+
.createDefaultBridgedDeviceBasicInformationClusterServer(device.name, getSerialNumber(device), VENDOR_ID, getManufacturer(device), getModel(device));
|
|
28
|
+
}
|
|
29
|
+
export function toMatterLevel(iotasLevel) {
|
|
30
|
+
return Math.round(iotasLevel * 254);
|
|
31
|
+
}
|
|
32
|
+
export function fromMatterLevel(matterLevel) {
|
|
33
|
+
return matterLevel / 254;
|
|
34
|
+
}
|
|
35
|
+
export function toMatterHumidity(iotasHumidity) {
|
|
36
|
+
return Math.round(iotasHumidity * 10000);
|
|
37
|
+
}
|
|
38
|
+
export function toCelsius(fahrenheit) {
|
|
39
|
+
return Temperature.toCelsius(fahrenheit);
|
|
40
|
+
}
|
|
41
|
+
export function toMatterCentiCelsius(fahrenheit) {
|
|
42
|
+
return Math.round(Temperature.toCelsius(fahrenheit) * 100);
|
|
43
|
+
}
|
|
44
|
+
export function fromMatterCentiCelsius(centiCelsius) {
|
|
45
|
+
return Temperature.toFahrenheit(centiCelsius / 100);
|
|
46
|
+
}
|
|
47
|
+
export function addOnOffHandlers(endpoint, featureId, ctx) {
|
|
48
|
+
endpoint.addCommandHandler('on', () => {
|
|
49
|
+
ctx.onFeatureUpdate(featureId, 1);
|
|
50
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', true);
|
|
51
|
+
});
|
|
52
|
+
endpoint.addCommandHandler('off', () => {
|
|
53
|
+
ctx.onFeatureUpdate(featureId, 0);
|
|
54
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', false);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export function multiFeatureResult(endpoint, handlers) {
|
|
58
|
+
return {
|
|
59
|
+
endpoint,
|
|
60
|
+
featureIds: [...handlers.keys()],
|
|
61
|
+
updateAttribute(featureId, value) {
|
|
62
|
+
handlers.get(featureId)?.(value);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function singleFeatureResult(endpoint, featureId, onUpdate) {
|
|
67
|
+
return {
|
|
68
|
+
endpoint,
|
|
69
|
+
featureIds: [featureId],
|
|
70
|
+
updateAttribute(fid, value) {
|
|
71
|
+
if (fid === featureId) {
|
|
72
|
+
onUpdate(value);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function createSimpleOnOffDevice(deviceType, device, ctx, label) {
|
|
78
|
+
const onOffFeature = requireFeatureByEventType(device, EventTypeName.OnOff, ctx, label);
|
|
79
|
+
if (!onOffFeature) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const isOn = (onOffFeature.value ?? 0) === 1;
|
|
83
|
+
const endpoint = createBridgedEndpoint([deviceType, bridgedNode], device, ctx)
|
|
84
|
+
.createDefaultOnOffClusterServer(isOn)
|
|
85
|
+
.addRequiredClusterServers();
|
|
86
|
+
addOnOffHandlers(endpoint, onOffFeature.id, ctx);
|
|
87
|
+
return singleFeatureResult(endpoint, onOffFeature.id, (value) => {
|
|
88
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', value === 1);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/devices/helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Device } from 'iotas-ts';
|
|
2
|
+
import type { DeviceFactoryContext, EndpointResult } from './types.js';
|
|
3
|
+
export declare function createDimmableLight(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
4
|
+
export declare function createOnOffLight(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { dimmableLight, onOffLight } from 'matterbridge';
|
|
2
|
+
import { LevelControl, OnOff } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { EventTypeName, findFeatureByEventType } from 'iotas-ts';
|
|
4
|
+
import { addOnOffHandlers, bridgedNode, createBridgedEndpoint, createSimpleOnOffDevice, fromMatterLevel, multiFeatureResult, singleFeatureResult, toMatterLevel, } from './helpers.js';
|
|
5
|
+
function createStandardDimmableLight(device, ctx, onOffFeature, levelFeature, level) {
|
|
6
|
+
const isOn = (onOffFeature.value ?? 0) === 1;
|
|
7
|
+
const endpoint = createBridgedEndpoint([dimmableLight, bridgedNode], device, ctx)
|
|
8
|
+
.createDefaultOnOffClusterServer(isOn)
|
|
9
|
+
.createDefaultLevelControlClusterServer(level)
|
|
10
|
+
.addRequiredClusterServers();
|
|
11
|
+
addOnOffHandlers(endpoint, onOffFeature.id, ctx);
|
|
12
|
+
endpoint.addCommandHandler('moveToLevel', ({ request }) => {
|
|
13
|
+
const matterLevel = request.level;
|
|
14
|
+
const iotasLevel = fromMatterLevel(matterLevel);
|
|
15
|
+
ctx.onFeatureUpdate(levelFeature.id, iotasLevel);
|
|
16
|
+
endpoint.setAttribute(LevelControl.Cluster.id, 'currentLevel', matterLevel);
|
|
17
|
+
});
|
|
18
|
+
return multiFeatureResult(endpoint, new Map([
|
|
19
|
+
[onOffFeature.id, (value) => endpoint.setAttribute(OnOff.Cluster.id, 'onOff', value === 1)],
|
|
20
|
+
[
|
|
21
|
+
levelFeature.id,
|
|
22
|
+
(value) => endpoint.setAttribute(LevelControl.Cluster.id, 'currentLevel', toMatterLevel(value)),
|
|
23
|
+
],
|
|
24
|
+
]));
|
|
25
|
+
}
|
|
26
|
+
function createLevelOnlyDimmableLight(device, ctx, levelFeature, level) {
|
|
27
|
+
const isOn = (levelFeature.value ?? 0) > 0;
|
|
28
|
+
const endpoint = createBridgedEndpoint([dimmableLight, bridgedNode], device, ctx)
|
|
29
|
+
.createDefaultOnOffClusterServer(isOn)
|
|
30
|
+
.createDefaultLevelControlClusterServer(level)
|
|
31
|
+
.addRequiredClusterServers();
|
|
32
|
+
// On/off synthesized from level — send level value to the single IOTAS feature
|
|
33
|
+
endpoint.addCommandHandler('on', () => {
|
|
34
|
+
ctx.onFeatureUpdate(levelFeature.id, 1);
|
|
35
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', true);
|
|
36
|
+
endpoint.setAttribute(LevelControl.Cluster.id, 'currentLevel', 254);
|
|
37
|
+
});
|
|
38
|
+
endpoint.addCommandHandler('off', () => {
|
|
39
|
+
ctx.onFeatureUpdate(levelFeature.id, 0);
|
|
40
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', false);
|
|
41
|
+
endpoint.setAttribute(LevelControl.Cluster.id, 'currentLevel', 0);
|
|
42
|
+
});
|
|
43
|
+
endpoint.addCommandHandler('moveToLevel', ({ request }) => {
|
|
44
|
+
const matterLevel = request.level;
|
|
45
|
+
const iotasLevel = fromMatterLevel(matterLevel);
|
|
46
|
+
ctx.onFeatureUpdate(levelFeature.id, iotasLevel);
|
|
47
|
+
endpoint.setAttribute(LevelControl.Cluster.id, 'currentLevel', matterLevel);
|
|
48
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', matterLevel > 0);
|
|
49
|
+
});
|
|
50
|
+
return singleFeatureResult(endpoint, levelFeature.id, (value) => {
|
|
51
|
+
endpoint.setAttribute(LevelControl.Cluster.id, 'currentLevel', toMatterLevel(value));
|
|
52
|
+
endpoint.setAttribute(OnOff.Cluster.id, 'onOff', value > 0);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
export function createDimmableLight(device, ctx) {
|
|
56
|
+
const onOffFeature = findFeatureByEventType(device, EventTypeName.OnOff);
|
|
57
|
+
const levelFeature = findFeatureByEventType(device, EventTypeName.Level);
|
|
58
|
+
if (!levelFeature) {
|
|
59
|
+
ctx.log.warn(`Device ${device.name} missing Level feature for dimmable light`);
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const level = toMatterLevel(levelFeature.value ?? 0);
|
|
63
|
+
if (onOffFeature) {
|
|
64
|
+
return createStandardDimmableLight(device, ctx, onOffFeature, levelFeature, level);
|
|
65
|
+
}
|
|
66
|
+
return createLevelOnlyDimmableLight(device, ctx, levelFeature, level);
|
|
67
|
+
}
|
|
68
|
+
export function createOnOffLight(device, ctx) {
|
|
69
|
+
return createSimpleOnOffDevice(onOffLight, device, ctx, 'light');
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=lights.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lights.js","sourceRoot":"","sources":["../../../src/devices/lights.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { doorLockDevice } from 'matterbridge';
|
|
2
|
+
import { DoorLock, PowerSource } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { FeatureCategory, findFeatureByCategory } from 'iotas-ts';
|
|
4
|
+
import { bridgedNode, createBridgedEndpoint, multiFeatureResult, requireFeature } from './helpers.js';
|
|
5
|
+
export function createDoorLock(device, ctx) {
|
|
6
|
+
const lockFeature = requireFeature(device, FeatureCategory.Lock, ctx, 'door lock');
|
|
7
|
+
if (!lockFeature) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const isLocked = (lockFeature.value ?? 0) === 1;
|
|
11
|
+
const lockState = isLocked ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked;
|
|
12
|
+
const endpoint = createBridgedEndpoint([doorLockDevice, bridgedNode], device, ctx)
|
|
13
|
+
.createDefaultDoorLockClusterServer(lockState)
|
|
14
|
+
.addRequiredClusterServers();
|
|
15
|
+
endpoint.addCommandHandler('lockDoor', () => {
|
|
16
|
+
ctx.onFeatureUpdate(lockFeature.id, 1);
|
|
17
|
+
endpoint.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Locked);
|
|
18
|
+
});
|
|
19
|
+
endpoint.addCommandHandler('unlockDoor', () => {
|
|
20
|
+
ctx.onFeatureUpdate(lockFeature.id, 0);
|
|
21
|
+
endpoint.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Unlocked);
|
|
22
|
+
});
|
|
23
|
+
const handlers = new Map([
|
|
24
|
+
[
|
|
25
|
+
lockFeature.id,
|
|
26
|
+
(value) => {
|
|
27
|
+
endpoint.setAttribute(DoorLock.Cluster.id, 'lockState', value === 1 ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked);
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
]);
|
|
31
|
+
const batteryFeature = findFeatureByCategory(device, FeatureCategory.Battery);
|
|
32
|
+
if (batteryFeature) {
|
|
33
|
+
const batteryPercent = Math.min(Math.round(batteryFeature.value ?? 0), 100);
|
|
34
|
+
const matterPercent = batteryPercent * 2; // Matter uses 0-200 (0.5% steps)
|
|
35
|
+
endpoint.createDefaultPowerSourceReplaceableBatteryClusterServer(matterPercent, batteryPercent < 20 ? PowerSource.BatChargeLevel.Critical : PowerSource.BatChargeLevel.Ok, batteryPercent * 30, 'CR123A', 1, PowerSource.BatReplaceability.UserReplaceable);
|
|
36
|
+
handlers.set(batteryFeature.id, (value) => {
|
|
37
|
+
const percent = Math.min(Math.round(value), 100);
|
|
38
|
+
endpoint.setAttribute(PowerSource.Cluster.id, 'batPercentRemaining', percent * 2);
|
|
39
|
+
endpoint.setAttribute(PowerSource.Cluster.id, 'batChargeLevel', percent < 20 ? PowerSource.BatChargeLevel.Critical : PowerSource.BatChargeLevel.Ok);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return multiFeatureResult(endpoint, handlers);
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/devices/lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"outlet.js","sourceRoot":"","sources":["../../../src/devices/outlet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAK3C,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,GAAyB;IACzE,OAAO,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Device } from 'iotas-ts';
|
|
2
|
+
import type { DeviceFactoryContext, EndpointResult } from './types.js';
|
|
3
|
+
export declare function createHumiditySensor(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
4
|
+
export declare function createOccupancySensor(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
5
|
+
export declare function createContactSensor(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { contactSensor, humiditySensor, occupancySensor } from 'matterbridge';
|
|
2
|
+
import { BooleanState, OccupancySensing, RelativeHumidityMeasurement } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { FeatureCategory } from 'iotas-ts';
|
|
4
|
+
import { bridgedNode, createBridgedEndpoint, requireFeature, singleFeatureResult, toMatterHumidity, } from './helpers.js';
|
|
5
|
+
export function createHumiditySensor(device, ctx) {
|
|
6
|
+
const humidityFeature = requireFeature(device, FeatureCategory.Humidity, ctx, 'humidity sensor');
|
|
7
|
+
if (!humidityFeature) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const humidity = toMatterHumidity(humidityFeature.value ?? 0);
|
|
11
|
+
const endpoint = createBridgedEndpoint([humiditySensor, bridgedNode], device, ctx)
|
|
12
|
+
.createDefaultRelativeHumidityMeasurementClusterServer(humidity)
|
|
13
|
+
.addRequiredClusterServers();
|
|
14
|
+
return singleFeatureResult(endpoint, humidityFeature.id, (value) => {
|
|
15
|
+
endpoint.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', toMatterHumidity(value));
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function createOccupancySensor(device, ctx) {
|
|
19
|
+
const motionFeature = requireFeature(device, FeatureCategory.Motion, ctx, 'occupancy sensor');
|
|
20
|
+
if (!motionFeature) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const occupied = (motionFeature.value ?? 0) === 1;
|
|
24
|
+
const endpoint = createBridgedEndpoint([occupancySensor, bridgedNode], device, ctx)
|
|
25
|
+
.createDefaultOccupancySensingClusterServer(occupied)
|
|
26
|
+
.addRequiredClusterServers();
|
|
27
|
+
return singleFeatureResult(endpoint, motionFeature.id, (value) => {
|
|
28
|
+
endpoint.setAttribute(OccupancySensing.Cluster.id, 'occupancy', { occupied: value === 1 });
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function createContactSensor(device, ctx) {
|
|
32
|
+
const doorFeature = requireFeature(device, FeatureCategory.DoorState, ctx, 'contact sensor');
|
|
33
|
+
if (!doorFeature) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const contactState = (doorFeature.value ?? 0) === 1;
|
|
37
|
+
const endpoint = createBridgedEndpoint([contactSensor, bridgedNode], device, ctx)
|
|
38
|
+
.createDefaultBooleanStateClusterServer(contactState)
|
|
39
|
+
.addRequiredClusterServers();
|
|
40
|
+
return singleFeatureResult(endpoint, doorFeature.id, (value) => {
|
|
41
|
+
endpoint.setAttribute(BooleanState.Cluster.id, 'stateValue', value === 1);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=sensors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sensors.js","sourceRoot":"","sources":["../../../src/devices/sensors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Thermostat } from 'matterbridge/matter/clusters';
|
|
2
|
+
import { type Device } from 'iotas-ts';
|
|
3
|
+
import type { DeviceFactoryContext, EndpointResult } from './types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Map IOTAS thermostat mode values to Matter SystemMode.
|
|
6
|
+
* ThermostatMode enum values match IOTAS indices: 0=Off, 1=Heat, 2=Cool, 3=EmergencyHeat, 4=Auto
|
|
7
|
+
*/
|
|
8
|
+
export declare function iotasModeToSystemMode(iotasMode: number): Thermostat.SystemMode;
|
|
9
|
+
export declare function createThermostat(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { thermostatDevice } from 'matterbridge';
|
|
2
|
+
import { Thermostat } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { FeatureCategory, ThermostatMode, findFeatureByCategory } from 'iotas-ts';
|
|
4
|
+
import { bridgedNode, createBridgedEndpoint, fromMatterCentiCelsius, multiFeatureResult, requireFeature, toCelsius, toMatterCentiCelsius, } from './helpers.js';
|
|
5
|
+
/**
|
|
6
|
+
* Map IOTAS thermostat mode values to Matter SystemMode.
|
|
7
|
+
* ThermostatMode enum values match IOTAS indices: 0=Off, 1=Heat, 2=Cool, 3=EmergencyHeat, 4=Auto
|
|
8
|
+
*/
|
|
9
|
+
export function iotasModeToSystemMode(iotasMode) {
|
|
10
|
+
const mode = iotasMode;
|
|
11
|
+
switch (mode) {
|
|
12
|
+
case ThermostatMode.Heat:
|
|
13
|
+
return Thermostat.SystemMode.Heat;
|
|
14
|
+
case ThermostatMode.Cool:
|
|
15
|
+
return Thermostat.SystemMode.Cool;
|
|
16
|
+
case ThermostatMode.EmergencyHeat:
|
|
17
|
+
return Thermostat.SystemMode.EmergencyHeat;
|
|
18
|
+
case ThermostatMode.Auto:
|
|
19
|
+
return Thermostat.SystemMode.Auto;
|
|
20
|
+
default:
|
|
21
|
+
return Thermostat.SystemMode.Off;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function systemModeToIotasMode(systemMode) {
|
|
25
|
+
switch (systemMode) {
|
|
26
|
+
case Thermostat.SystemMode.Heat:
|
|
27
|
+
return ThermostatMode.Heat;
|
|
28
|
+
case Thermostat.SystemMode.Cool:
|
|
29
|
+
return ThermostatMode.Cool;
|
|
30
|
+
case Thermostat.SystemMode.EmergencyHeat:
|
|
31
|
+
return ThermostatMode.EmergencyHeat;
|
|
32
|
+
case Thermostat.SystemMode.Auto:
|
|
33
|
+
return ThermostatMode.Auto;
|
|
34
|
+
default:
|
|
35
|
+
return ThermostatMode.Off;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function createThermostat(device, ctx) {
|
|
39
|
+
const tempFeature = requireFeature(device, FeatureCategory.CurrentTemperature, ctx, 'thermostat');
|
|
40
|
+
const modeFeature = findFeatureByCategory(device, FeatureCategory.ThermostatMode);
|
|
41
|
+
const heatSetpointFeature = findFeatureByCategory(device, FeatureCategory.HeatSetPoint);
|
|
42
|
+
const coolSetpointFeature = findFeatureByCategory(device, FeatureCategory.CoolSetPoint);
|
|
43
|
+
if (!tempFeature) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const currentTempC = toCelsius(tempFeature.value ?? 70);
|
|
47
|
+
const heatSetpointC = toCelsius(heatSetpointFeature?.value ?? 68);
|
|
48
|
+
const coolSetpointC = toCelsius(coolSetpointFeature?.value ?? 76);
|
|
49
|
+
const endpoint = createBridgedEndpoint([thermostatDevice, bridgedNode], device, ctx)
|
|
50
|
+
.createDefaultThermostatClusterServer(currentTempC, heatSetpointC, coolSetpointC)
|
|
51
|
+
.addRequiredClusterServers();
|
|
52
|
+
if (modeFeature) {
|
|
53
|
+
endpoint.subscribeAttribute(Thermostat.Cluster.id, 'systemMode', (newValue) => {
|
|
54
|
+
const iotasMode = systemModeToIotasMode(newValue);
|
|
55
|
+
ctx.onFeatureUpdate(modeFeature.id, iotasMode);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (heatSetpointFeature) {
|
|
59
|
+
endpoint.subscribeAttribute(Thermostat.Cluster.id, 'occupiedHeatingSetpoint', (newValue) => {
|
|
60
|
+
const fahrenheit = fromMatterCentiCelsius(newValue);
|
|
61
|
+
ctx.onFeatureUpdate(heatSetpointFeature.id, fahrenheit);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (coolSetpointFeature) {
|
|
65
|
+
endpoint.subscribeAttribute(Thermostat.Cluster.id, 'occupiedCoolingSetpoint', (newValue) => {
|
|
66
|
+
const fahrenheit = fromMatterCentiCelsius(newValue);
|
|
67
|
+
ctx.onFeatureUpdate(coolSetpointFeature.id, fahrenheit);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
const handlers = new Map([
|
|
71
|
+
[
|
|
72
|
+
tempFeature.id,
|
|
73
|
+
(value) => {
|
|
74
|
+
endpoint.setAttribute(Thermostat.Cluster.id, 'localTemperature', toMatterCentiCelsius(value));
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
]);
|
|
78
|
+
if (modeFeature) {
|
|
79
|
+
handlers.set(modeFeature.id, (value) => {
|
|
80
|
+
endpoint.setAttribute(Thermostat.Cluster.id, 'systemMode', iotasModeToSystemMode(value));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (heatSetpointFeature) {
|
|
84
|
+
handlers.set(heatSetpointFeature.id, (value) => {
|
|
85
|
+
endpoint.setAttribute(Thermostat.Cluster.id, 'occupiedHeatingSetpoint', toMatterCentiCelsius(value));
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (coolSetpointFeature) {
|
|
89
|
+
handlers.set(coolSetpointFeature.id, (value) => {
|
|
90
|
+
endpoint.setAttribute(Thermostat.Cluster.id, 'occupiedCoolingSetpoint', toMatterCentiCelsius(value));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return multiFeatureResult(endpoint, handlers);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=thermostat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thermostat.js","sourceRoot":"","sources":["../../../src/devices/thermostat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for device factories.
|
|
3
|
+
*/
|
|
4
|
+
import type { MatterbridgeEndpoint } from 'matterbridge';
|
|
5
|
+
import type { AnsiLogger } from 'matterbridge/logger';
|
|
6
|
+
export declare const VENDOR_ID = 65521;
|
|
7
|
+
/**
|
|
8
|
+
* Context for device creation, containing references to platform resources.
|
|
9
|
+
*/
|
|
10
|
+
export interface DeviceFactoryContext {
|
|
11
|
+
log: AnsiLogger;
|
|
12
|
+
debug: boolean;
|
|
13
|
+
onFeatureUpdate: (featureId: number, value: number) => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Result of creating an endpoint.
|
|
17
|
+
*
|
|
18
|
+
* Self-contained: includes the endpoint, the feature IDs it tracks,
|
|
19
|
+
* and a callback to push IOTAS value changes to Matter attributes.
|
|
20
|
+
* All per-device-kind logic is co-located in the factory that builds this.
|
|
21
|
+
*/
|
|
22
|
+
export interface EndpointResult {
|
|
23
|
+
endpoint: MatterbridgeEndpoint;
|
|
24
|
+
featureIds: number[];
|
|
25
|
+
updateAttribute: (featureId: number, value: number) => void;
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/devices/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { MatterbridgeDynamicPlatform, PlatformConfig, PlatformMatterbridge } from 'matterbridge';
|
|
2
|
+
import { AnsiLogger } from 'matterbridge/logger';
|
|
3
|
+
import { FeatureCache, IotasClient } from 'iotas-ts';
|
|
4
|
+
import type { SnapshotFilter } from 'iotas-ts';
|
|
5
|
+
export interface IotasPluginConfig extends PlatformConfig {
|
|
6
|
+
username: string;
|
|
7
|
+
password: string;
|
|
8
|
+
unit?: string;
|
|
9
|
+
pollingInterval?: number;
|
|
10
|
+
}
|
|
11
|
+
export default function initializePlugin(matterbridge: PlatformMatterbridge, log: AnsiLogger, config: PlatformConfig): IotasPlatform;
|
|
12
|
+
export declare class IotasPlatform extends MatterbridgeDynamicPlatform {
|
|
13
|
+
iotasClient: IotasClient;
|
|
14
|
+
featureCache: FeatureCache;
|
|
15
|
+
pollingInterval: number;
|
|
16
|
+
private deviceMap;
|
|
17
|
+
constructor(matterbridge: PlatformMatterbridge, log: AnsiLogger, config: IotasPluginConfig);
|
|
18
|
+
createSnapshotFilter(): SnapshotFilter | undefined;
|
|
19
|
+
onStart(reason?: string): Promise<void>;
|
|
20
|
+
onConfigure(): Promise<void>;
|
|
21
|
+
onShutdown(reason?: string): Promise<void>;
|
|
22
|
+
private discoverDevices;
|
|
23
|
+
private refreshStates;
|
|
24
|
+
}
|