matterbridge-iotas 1.1.6 → 1.2.1
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/CHANGELOG.md +14 -0
- package/dist/src/deviceFactory.d.ts +0 -6
- package/dist/src/deviceFactory.js +9 -7
- package/dist/src/deviceFactory.js.map +1 -1
- package/dist/src/devices/lock.js +34 -2
- package/dist/src/devices/lock.js.map +1 -1
- package/dist/src/devices/motionSwitch.d.ts +3 -0
- package/dist/src/devices/motionSwitch.js +29 -0
- package/dist/src/devices/motionSwitch.js.map +1 -0
- package/dist/src/devices/thermostat.d.ts +7 -1
- package/dist/src/devices/thermostat.js +70 -4
- package/dist/src/devices/thermostat.js.map +1 -1
- package/dist/test/devices/lock.test.js +70 -0
- package/dist/test/devices/lock.test.js.map +1 -1
- package/dist/test/devices/motionSwitch.test.d.ts +1 -0
- package/dist/test/devices/motionSwitch.test.js +64 -0
- package/dist/test/devices/motionSwitch.test.js.map +1 -0
- package/dist/test/devices/thermostat.test.js +54 -4
- package/dist/test/devices/thermostat.test.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.1](https://github.com/mezaugusto/matterbridge-iotas/compare/v1.2.0...v1.2.1) (2026-04-13)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* :bug: Fix child devices not working ([#22](https://github.com/mezaugusto/matterbridge-iotas/issues/22)) ([f315469](https://github.com/mezaugusto/matterbridge-iotas/commit/f3154695a0e32cc53b8dd61d10b110784e2413a4))
|
|
9
|
+
|
|
10
|
+
## [1.2.0](https://github.com/mezaugusto/matterbridge-iotas/compare/v1.1.6...v1.2.0) (2026-04-13)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* :sparkles: Extract motion sensor from motion lights ([#20](https://github.com/mezaugusto/matterbridge-iotas/issues/20)) ([729a094](https://github.com/mezaugusto/matterbridge-iotas/commit/729a094ae268b5e80b8399528908f3fd30f22149))
|
|
16
|
+
|
|
3
17
|
## [1.1.6](https://github.com/mezaugusto/matterbridge-iotas/compare/v1.1.5...v1.1.6) (2026-04-13)
|
|
4
18
|
|
|
5
19
|
|
|
@@ -1,9 +1,3 @@
|
|
|
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
1
|
import { type Device } from 'iotas-ts';
|
|
8
2
|
import type { DeviceFactoryContext, EndpointResult } from './devices/types.js';
|
|
9
3
|
/**
|
|
@@ -1,19 +1,21 @@
|
|
|
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
1
|
import { DeviceCategory, EventTypeName, FeatureCategory, isDeviceCategory } from 'iotas-ts';
|
|
8
2
|
import { createDimmableLight, createOnOffLight } from './devices/lights.js';
|
|
9
3
|
import { createOnOffOutlet } from './devices/outlet.js';
|
|
10
4
|
import { createDoorLock } from './devices/lock.js';
|
|
11
5
|
import { createThermostat } from './devices/thermostat.js';
|
|
12
6
|
import { createHumiditySensor, createOccupancySensor, createContactSensor } from './devices/sensors.js';
|
|
7
|
+
import { addOccupancyChild } from './devices/motionSwitch.js';
|
|
13
8
|
function handleSwitch(device, ctx) {
|
|
14
9
|
const isLight = device.features.some((f) => f.isLight);
|
|
15
10
|
return isLight ? createOnOffLight(device, ctx) : createOnOffOutlet(device, ctx);
|
|
16
11
|
}
|
|
12
|
+
function handleMotionSwitch(device, ctx) {
|
|
13
|
+
const result = handleSwitch(device, ctx);
|
|
14
|
+
if (!result) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return addOccupancyChild(device, result, ctx);
|
|
18
|
+
}
|
|
17
19
|
function handleDimmer(device, ctx) {
|
|
18
20
|
const hasLevel = device.features.some((f) => f.eventTypeName === EventTypeName.Level);
|
|
19
21
|
if (hasLevel) {
|
|
@@ -24,7 +26,7 @@ function handleDimmer(device, ctx) {
|
|
|
24
26
|
const categoryHandlers = new Map([
|
|
25
27
|
[DeviceCategory.Dimmer, handleDimmer],
|
|
26
28
|
[DeviceCategory.Switch, handleSwitch],
|
|
27
|
-
[DeviceCategory.MotionSwitch,
|
|
29
|
+
[DeviceCategory.MotionSwitch, handleMotionSwitch],
|
|
28
30
|
[DeviceCategory.Lock, createDoorLock],
|
|
29
31
|
[DeviceCategory.Thermostat, createThermostat],
|
|
30
32
|
[DeviceCategory.Door, createContactSensor],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deviceFactory.js","sourceRoot":"","sources":["../../src/deviceFactory.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"deviceFactory.js","sourceRoot":"","sources":["../../src/deviceFactory.ts"],"names":[],"mappings":"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"}
|
package/dist/src/devices/lock.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { doorLockDevice } from 'matterbridge';
|
|
2
2
|
import { DoorLock, PowerSource } from 'matterbridge/matter/clusters';
|
|
3
|
-
import { FeatureCategory, findFeatureByCategory, LOW_BATTERY_THRESHOLD } from 'iotas-ts';
|
|
3
|
+
import { FeatureCategory, findFeatureByCategory, autoRelockSeconds, isAutoRelockEnabled, isLockedAlarm, LOW_BATTERY_THRESHOLD, } from 'iotas-ts';
|
|
4
4
|
import { bridgedNode, createBridgedEndpoint, multiFeatureResult, requireFeature } from './helpers.js';
|
|
5
5
|
export function createDoorLock(device, ctx) {
|
|
6
6
|
const lockFeature = requireFeature(device, FeatureCategory.Lock, ctx, 'door lock');
|
|
@@ -9,8 +9,11 @@ export function createDoorLock(device, ctx) {
|
|
|
9
9
|
}
|
|
10
10
|
const isLocked = (lockFeature.value ?? 0) === 1;
|
|
11
11
|
const lockState = isLocked ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked;
|
|
12
|
+
const autoRelockFeature = findFeatureByCategory(device, FeatureCategory.AutoRelock);
|
|
13
|
+
const autoRelockTimeoutFeature = findFeatureByCategory(device, FeatureCategory.AutoRelockTimeout);
|
|
14
|
+
const autoRelockTime = autoRelockSeconds(autoRelockFeature?.value ?? 0, autoRelockTimeoutFeature?.value ?? 0);
|
|
12
15
|
const endpoint = createBridgedEndpoint([doorLockDevice, bridgedNode], device, ctx)
|
|
13
|
-
.createDefaultDoorLockClusterServer(lockState)
|
|
16
|
+
.createDefaultDoorLockClusterServer(lockState, DoorLock.LockType.DeadBolt, autoRelockTime)
|
|
14
17
|
.addRequiredClusterServers();
|
|
15
18
|
endpoint.addCommandHandler('lockDoor', () => {
|
|
16
19
|
ctx.onFeatureUpdate(lockFeature.id, 1);
|
|
@@ -20,6 +23,14 @@ export function createDoorLock(device, ctx) {
|
|
|
20
23
|
ctx.onFeatureUpdate(lockFeature.id, 0);
|
|
21
24
|
endpoint.setAttribute(DoorLock.Cluster.id, 'lockState', DoorLock.LockState.Unlocked);
|
|
22
25
|
});
|
|
26
|
+
if (autoRelockFeature && autoRelockTimeoutFeature) {
|
|
27
|
+
endpoint.subscribeAttribute(DoorLock.Cluster.id, 'autoRelockTime', (newValue) => {
|
|
28
|
+
ctx.onFeatureUpdate(autoRelockFeature.id, isAutoRelockEnabled(newValue));
|
|
29
|
+
if (newValue > 0) {
|
|
30
|
+
ctx.onFeatureUpdate(autoRelockTimeoutFeature.id, newValue);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
23
34
|
const handlers = new Map([
|
|
24
35
|
[
|
|
25
36
|
lockFeature.id,
|
|
@@ -39,6 +50,27 @@ export function createDoorLock(device, ctx) {
|
|
|
39
50
|
endpoint.setAttribute(PowerSource.Cluster.id, 'batChargeLevel', percent < LOW_BATTERY_THRESHOLD ? PowerSource.BatChargeLevel.Critical : PowerSource.BatChargeLevel.Ok);
|
|
40
51
|
});
|
|
41
52
|
}
|
|
53
|
+
if (autoRelockFeature && autoRelockTimeoutFeature) {
|
|
54
|
+
let lastEnabled = autoRelockFeature.value ?? 0;
|
|
55
|
+
let lastTimeout = autoRelockTimeoutFeature.value ?? 0;
|
|
56
|
+
handlers.set(autoRelockFeature.id, (value) => {
|
|
57
|
+
lastEnabled = value;
|
|
58
|
+
endpoint.setAttribute(DoorLock.Cluster.id, 'autoRelockTime', autoRelockSeconds(lastEnabled, lastTimeout));
|
|
59
|
+
});
|
|
60
|
+
handlers.set(autoRelockTimeoutFeature.id, (value) => {
|
|
61
|
+
lastTimeout = value;
|
|
62
|
+
endpoint.setAttribute(DoorLock.Cluster.id, 'autoRelockTime', autoRelockSeconds(lastEnabled, lastTimeout));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const doorLockStateFeatures = device.features.filter((f) => f.featureTypeCategory === FeatureCategory.DoorLockState && f.value !== undefined);
|
|
66
|
+
for (const dlsFeature of doorLockStateFeatures) {
|
|
67
|
+
handlers.set(dlsFeature.id, (value) => {
|
|
68
|
+
const locked = isLockedAlarm(value);
|
|
69
|
+
if (locked !== null) {
|
|
70
|
+
endpoint.setAttribute(DoorLock.Cluster.id, 'lockState', locked ? DoorLock.LockState.Locked : DoorLock.LockState.Unlocked);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
42
74
|
return multiFeatureResult(endpoint, handlers);
|
|
43
75
|
}
|
|
44
76
|
//# sourceMappingURL=lock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/devices/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,
|
|
1
|
+
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../../../src/devices/lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { occupancySensor } from 'matterbridge';
|
|
2
|
+
import { OccupancySensing } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { FeatureCategory, findFeatureByCategory } from 'iotas-ts';
|
|
4
|
+
export function addOccupancyChild(device, result, ctx) {
|
|
5
|
+
const motionFeature = findFeatureByCategory(device, FeatureCategory.Motion);
|
|
6
|
+
if (!motionFeature) {
|
|
7
|
+
ctx.log.debug(`Device ${device.name} has no motion feature, skipping occupancy child`);
|
|
8
|
+
return result;
|
|
9
|
+
}
|
|
10
|
+
const occupied = (motionFeature.value ?? 0) === 1;
|
|
11
|
+
const occupancyChild = result.endpoint
|
|
12
|
+
.addChildDeviceType('Occupancy', occupancySensor)
|
|
13
|
+
.createDefaultOccupancySensingClusterServer(occupied)
|
|
14
|
+
.addRequiredClusterServers();
|
|
15
|
+
const originalUpdate = result.updateAttribute.bind(result);
|
|
16
|
+
return {
|
|
17
|
+
endpoint: result.endpoint,
|
|
18
|
+
featureIds: [...result.featureIds, motionFeature.id],
|
|
19
|
+
updateAttribute(featureId, value) {
|
|
20
|
+
if (featureId === motionFeature.id) {
|
|
21
|
+
occupancyChild.setAttribute(OccupancySensing.Cluster.id, 'occupancy', { occupied: value === 1 });
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
originalUpdate(featureId, value);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=motionSwitch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motionSwitch.js","sourceRoot":"","sources":["../../../src/devices/motionSwitch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAe,MAAM,UAAU,CAAC;AAI/E,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,MAAsB,EAAE,GAAyB;IACjG,MAAM,aAAa,GAAG,qBAAqB,CAAC,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAE5E,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,MAAM,CAAC,IAAI,kDAAkD,CAAC,CAAC;QACvF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;IAElD,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ;SACnC,kBAAkB,CAAC,WAAW,EAAE,eAAe,CAAC;SAChD,0CAA0C,CAAC,QAAQ,CAAC;SACpD,yBAAyB,EAAE,CAAC;IAE/B,MAAM,cAAc,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE3D,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,EAAE,CAAC;QACpD,eAAe,CAAC,SAAS,EAAE,KAAK;YAC9B,IAAI,SAAS,KAAK,aAAa,CAAC,EAAE,EAAE,CAAC;gBACnC,cAAc,CAAC,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;YACnG,CAAC;iBAAM,CAAC;gBACN,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Thermostat } from 'matterbridge/matter/clusters';
|
|
1
|
+
import { FanControl, Thermostat } from 'matterbridge/matter/clusters';
|
|
2
2
|
import { type Device } from 'iotas-ts';
|
|
3
3
|
import type { DeviceFactoryContext, EndpointResult } from './types.js';
|
|
4
4
|
/**
|
|
@@ -6,4 +6,10 @@ import type { DeviceFactoryContext, EndpointResult } from './types.js';
|
|
|
6
6
|
* ThermostatMode enum values match IOTAS indices: 0=Off, 1=Heat, 2=Cool, 3=EmergencyHeat, 4=Auto
|
|
7
7
|
*/
|
|
8
8
|
export declare function iotasModeToSystemMode(iotasMode: number): Thermostat.SystemMode;
|
|
9
|
+
/**
|
|
10
|
+
* Map IOTAS FanMode to Matter FanControl.FanMode.
|
|
11
|
+
* IOTAS: 0=Auto Low, 1=On Low, 2=Circulate
|
|
12
|
+
* Matter: Off=0, Low=1, Medium=2, High=3, On=4, Auto=5
|
|
13
|
+
*/
|
|
14
|
+
export declare function iotasFanModeToMatter(iotasMode: number): FanControl.FanMode;
|
|
9
15
|
export declare function createThermostat(device: Device, ctx: DeviceFactoryContext): EndpointResult | null;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { thermostatDevice } from 'matterbridge';
|
|
2
|
-
import { Thermostat } from 'matterbridge/matter/clusters';
|
|
3
|
-
import { FeatureCategory, ThermostatMode, findFeatureByCategory, DEFAULT_CURRENT_TEMPERATURE_F, DEFAULT_HEAT_SETPOINT_F, DEFAULT_COOL_SETPOINT_F, } from 'iotas-ts';
|
|
4
|
-
import { bridgedNode, createBridgedEndpoint, fromMatterCentiCelsius, multiFeatureResult, requireFeature, toCelsius, toMatterCentiCelsius, } from './helpers.js';
|
|
1
|
+
import { fanDevice, humiditySensor, thermostatDevice } from 'matterbridge';
|
|
2
|
+
import { FanControl, RelativeHumidityMeasurement, Thermostat } from 'matterbridge/matter/clusters';
|
|
3
|
+
import { FeatureCategory, FanMode, ThermostatMode, findFeatureByCategory, DEFAULT_CURRENT_TEMPERATURE_F, DEFAULT_HEAT_SETPOINT_F, DEFAULT_COOL_SETPOINT_F, } from 'iotas-ts';
|
|
4
|
+
import { bridgedNode, createBridgedEndpoint, fromMatterCentiCelsius, multiFeatureResult, requireFeature, toCelsius, toMatterCentiCelsius, toMatterHumidity, } from './helpers.js';
|
|
5
5
|
/**
|
|
6
6
|
* Map IOTAS thermostat mode values to Matter SystemMode.
|
|
7
7
|
* ThermostatMode enum values match IOTAS indices: 0=Off, 1=Heat, 2=Cool, 3=EmergencyHeat, 4=Auto
|
|
@@ -35,11 +35,45 @@ function systemModeToIotasMode(systemMode) {
|
|
|
35
35
|
return ThermostatMode.Off;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Map IOTAS FanMode to Matter FanControl.FanMode.
|
|
40
|
+
* IOTAS: 0=Auto Low, 1=On Low, 2=Circulate
|
|
41
|
+
* Matter: Off=0, Low=1, Medium=2, High=3, On=4, Auto=5
|
|
42
|
+
*/
|
|
43
|
+
export function iotasFanModeToMatter(iotasMode) {
|
|
44
|
+
const mode = iotasMode;
|
|
45
|
+
switch (mode) {
|
|
46
|
+
case FanMode.AutoLow:
|
|
47
|
+
return FanControl.FanMode.Auto;
|
|
48
|
+
case FanMode.OnLow:
|
|
49
|
+
return FanControl.FanMode.Low;
|
|
50
|
+
case FanMode.Circulate:
|
|
51
|
+
return FanControl.FanMode.On;
|
|
52
|
+
default:
|
|
53
|
+
return FanControl.FanMode.Auto;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function matterFanModeToIotas(matterMode) {
|
|
57
|
+
switch (matterMode) {
|
|
58
|
+
case FanControl.FanMode.Auto:
|
|
59
|
+
return FanMode.AutoLow;
|
|
60
|
+
case FanControl.FanMode.Low:
|
|
61
|
+
return FanMode.OnLow;
|
|
62
|
+
case FanControl.FanMode.On:
|
|
63
|
+
case FanControl.FanMode.High:
|
|
64
|
+
case FanControl.FanMode.Medium:
|
|
65
|
+
return FanMode.Circulate;
|
|
66
|
+
default:
|
|
67
|
+
return FanMode.AutoLow;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
38
70
|
export function createThermostat(device, ctx) {
|
|
39
71
|
const tempFeature = requireFeature(device, FeatureCategory.CurrentTemperature, ctx, 'thermostat');
|
|
40
72
|
const modeFeature = findFeatureByCategory(device, FeatureCategory.ThermostatMode);
|
|
41
73
|
const heatSetpointFeature = findFeatureByCategory(device, FeatureCategory.HeatSetPoint);
|
|
42
74
|
const coolSetpointFeature = findFeatureByCategory(device, FeatureCategory.CoolSetPoint);
|
|
75
|
+
const humidityFeature = findFeatureByCategory(device, FeatureCategory.Humidity);
|
|
76
|
+
const fanModeFeature = findFeatureByCategory(device, FeatureCategory.FanMode);
|
|
43
77
|
if (!tempFeature) {
|
|
44
78
|
return null;
|
|
45
79
|
}
|
|
@@ -49,6 +83,22 @@ export function createThermostat(device, ctx) {
|
|
|
49
83
|
const endpoint = createBridgedEndpoint([thermostatDevice, bridgedNode], device, ctx)
|
|
50
84
|
.createDefaultThermostatClusterServer(currentTempC, heatSetpointC, coolSetpointC)
|
|
51
85
|
.addRequiredClusterServers();
|
|
86
|
+
let humidityChild;
|
|
87
|
+
if (humidityFeature) {
|
|
88
|
+
const humidity = toMatterHumidity(humidityFeature.value ?? 0);
|
|
89
|
+
humidityChild = endpoint
|
|
90
|
+
.addChildDeviceType('Humidity', humiditySensor)
|
|
91
|
+
.createDefaultRelativeHumidityMeasurementClusterServer(humidity)
|
|
92
|
+
.addRequiredClusterServers();
|
|
93
|
+
}
|
|
94
|
+
let fanChild;
|
|
95
|
+
if (fanModeFeature) {
|
|
96
|
+
const matterFanMode = iotasFanModeToMatter(fanModeFeature.value ?? 0);
|
|
97
|
+
fanChild = endpoint
|
|
98
|
+
.addChildDeviceType('Fan', fanDevice)
|
|
99
|
+
.createDefaultFanControlClusterServer(matterFanMode)
|
|
100
|
+
.addRequiredClusterServers();
|
|
101
|
+
}
|
|
52
102
|
if (modeFeature) {
|
|
53
103
|
endpoint.subscribeAttribute(Thermostat.Cluster.id, 'systemMode', (newValue) => {
|
|
54
104
|
const iotasMode = systemModeToIotasMode(newValue);
|
|
@@ -67,6 +117,12 @@ export function createThermostat(device, ctx) {
|
|
|
67
117
|
ctx.onFeatureUpdate(coolSetpointFeature.id, fahrenheit);
|
|
68
118
|
});
|
|
69
119
|
}
|
|
120
|
+
if (fanModeFeature && fanChild) {
|
|
121
|
+
fanChild.subscribeAttribute(FanControl.Cluster.id, 'fanMode', (newValue) => {
|
|
122
|
+
const iotasMode = matterFanModeToIotas(newValue);
|
|
123
|
+
ctx.onFeatureUpdate(fanModeFeature.id, iotasMode);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
70
126
|
const handlers = new Map([
|
|
71
127
|
[
|
|
72
128
|
tempFeature.id,
|
|
@@ -90,6 +146,16 @@ export function createThermostat(device, ctx) {
|
|
|
90
146
|
endpoint.setAttribute(Thermostat.Cluster.id, 'occupiedCoolingSetpoint', toMatterCentiCelsius(value));
|
|
91
147
|
});
|
|
92
148
|
}
|
|
149
|
+
if (humidityFeature && humidityChild) {
|
|
150
|
+
handlers.set(humidityFeature.id, (value) => {
|
|
151
|
+
humidityChild.setAttribute(RelativeHumidityMeasurement.Cluster.id, 'measuredValue', toMatterHumidity(value));
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (fanModeFeature && fanChild) {
|
|
155
|
+
handlers.set(fanModeFeature.id, (value) => {
|
|
156
|
+
fanChild.setAttribute(FanControl.Cluster.id, 'fanMode', iotasFanModeToMatter(value));
|
|
157
|
+
});
|
|
158
|
+
}
|
|
93
159
|
return multiFeatureResult(endpoint, handlers);
|
|
94
160
|
}
|
|
95
161
|
//# sourceMappingURL=thermostat.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thermostat.js","sourceRoot":"","sources":["../../../src/devices/thermostat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"thermostat.js","sourceRoot":"","sources":["../../../src/devices/thermostat.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,31 @@ describe('lock', () => {
|
|
|
23
23
|
const result = assertResult(createDoorLock(device, ctx));
|
|
24
24
|
assert.deepEqual(result.featureIds, [20, 21]);
|
|
25
25
|
});
|
|
26
|
+
it('should include auto_relock features when both present', () => {
|
|
27
|
+
const device = makeDevice({
|
|
28
|
+
category: 'lock',
|
|
29
|
+
features: [
|
|
30
|
+
makeFeature({ id: 20, featureTypeCategory: 'lock', value: 1 }),
|
|
31
|
+
makeFeature({ id: 22, featureTypeCategory: 'auto_relock', value: 1, featureTypeSettable: true }),
|
|
32
|
+
makeFeature({ id: 23, featureTypeCategory: 'auto_relock_timeout', value: 30, featureTypeSettable: true }),
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
const result = assertResult(createDoorLock(device, ctx));
|
|
36
|
+
assert.deepEqual(result.featureIds, [20, 22, 23]);
|
|
37
|
+
});
|
|
38
|
+
it('should include all features together', () => {
|
|
39
|
+
const device = makeDevice({
|
|
40
|
+
category: 'lock',
|
|
41
|
+
features: [
|
|
42
|
+
makeFeature({ id: 20, featureTypeCategory: 'lock', value: 1 }),
|
|
43
|
+
makeFeature({ id: 21, featureTypeCategory: 'battery', value: 33 }),
|
|
44
|
+
makeFeature({ id: 22, featureTypeCategory: 'auto_relock', value: 0, featureTypeSettable: true }),
|
|
45
|
+
makeFeature({ id: 23, featureTypeCategory: 'auto_relock_timeout', value: 30, featureTypeSettable: true }),
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
const result = assertResult(createDoorLock(device, ctx));
|
|
49
|
+
assert.deepEqual(result.featureIds, [20, 21, 22, 23]);
|
|
50
|
+
});
|
|
26
51
|
it('updateAttribute should not throw for lock and battery features', () => {
|
|
27
52
|
const device = makeDevice({
|
|
28
53
|
category: 'lock',
|
|
@@ -36,6 +61,51 @@ describe('lock', () => {
|
|
|
36
61
|
assert.doesNotThrow(() => suppressLogs(() => result.updateAttribute(21, 0.5)));
|
|
37
62
|
assert.doesNotThrow(() => suppressLogs(() => result.updateAttribute(999, 0)));
|
|
38
63
|
});
|
|
64
|
+
it('updateAttribute should not throw for auto_relock features', () => {
|
|
65
|
+
const device = makeDevice({
|
|
66
|
+
category: 'lock',
|
|
67
|
+
features: [
|
|
68
|
+
makeFeature({ id: 20, featureTypeCategory: 'lock', value: 1 }),
|
|
69
|
+
makeFeature({ id: 22, featureTypeCategory: 'auto_relock', value: 0, featureTypeSettable: true }),
|
|
70
|
+
makeFeature({ id: 23, featureTypeCategory: 'auto_relock_timeout', value: 30, featureTypeSettable: true }),
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
const result = assertResult(createDoorLock(device, ctx));
|
|
74
|
+
suppressLogs(() => {
|
|
75
|
+
assert.doesNotThrow(() => result.updateAttribute(22, 1)); // enable auto-relock
|
|
76
|
+
assert.doesNotThrow(() => result.updateAttribute(23, 60)); // change timeout
|
|
77
|
+
assert.doesNotThrow(() => result.updateAttribute(22, 0)); // disable auto-relock
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
it('should include door_lock_state features with defined values', () => {
|
|
81
|
+
const device = makeDevice({
|
|
82
|
+
category: 'lock',
|
|
83
|
+
features: [
|
|
84
|
+
makeFeature({ id: 20, featureTypeCategory: 'lock', value: 1 }),
|
|
85
|
+
makeFeature({ id: 24, featureTypeCategory: 'door_lock_state', value: undefined }),
|
|
86
|
+
makeFeature({ id: 25, featureTypeCategory: 'door_lock_state', value: 22 }),
|
|
87
|
+
],
|
|
88
|
+
});
|
|
89
|
+
const result = assertResult(createDoorLock(device, ctx));
|
|
90
|
+
// Only the feature with a defined value (id 25) should be tracked
|
|
91
|
+
assert.ok(result.featureIds.includes(25));
|
|
92
|
+
assert.ok(!result.featureIds.includes(24));
|
|
93
|
+
});
|
|
94
|
+
it('updateAttribute should not throw for door_lock_state', () => {
|
|
95
|
+
const device = makeDevice({
|
|
96
|
+
category: 'lock',
|
|
97
|
+
features: [
|
|
98
|
+
makeFeature({ id: 20, featureTypeCategory: 'lock', value: 1 }),
|
|
99
|
+
makeFeature({ id: 25, featureTypeCategory: 'door_lock_state', value: 22 }),
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
const result = assertResult(createDoorLock(device, ctx));
|
|
103
|
+
suppressLogs(() => {
|
|
104
|
+
assert.doesNotThrow(() => result.updateAttribute(25, 21)); // ManualLock
|
|
105
|
+
assert.doesNotThrow(() => result.updateAttribute(25, 22)); // ManualUnlock
|
|
106
|
+
assert.doesNotThrow(() => result.updateAttribute(25, 9)); // Jammed (unknown → no-op)
|
|
107
|
+
});
|
|
108
|
+
});
|
|
39
109
|
it('should return null when lock feature is missing', () => {
|
|
40
110
|
assert.equal(createDoorLock(makeDevice({ features: [] }), ctx), null);
|
|
41
111
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lock.test.js","sourceRoot":"","sources":["../../../test/devices/lock.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lock.test.js","sourceRoot":"","sources":["../../../test/devices/lock.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, it } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { assertResult, makeCtx, makeDevice, makeFeature, suppressLogs } from './helpers.js';
|
|
4
|
+
import { createEndpointForDevice } from '../../src/deviceFactory.js';
|
|
5
|
+
describe('addOccupancyChild', () => {
|
|
6
|
+
const ctx = makeCtx();
|
|
7
|
+
it('should add occupancy child when motion feature exists', () => {
|
|
8
|
+
const device = makeDevice({
|
|
9
|
+
category: 'motion_switch',
|
|
10
|
+
features: [
|
|
11
|
+
makeFeature({ id: 10, eventTypeName: 'OnOff', isLight: true, value: 1 }),
|
|
12
|
+
makeFeature({ id: 50, featureTypeCategory: 'motion', value: 0 }),
|
|
13
|
+
],
|
|
14
|
+
});
|
|
15
|
+
const result = assertResult(createEndpointForDevice(device, ctx));
|
|
16
|
+
assert.ok(result.featureIds.includes(10), 'should include onOff feature');
|
|
17
|
+
assert.ok(result.featureIds.includes(50), 'should include motion feature');
|
|
18
|
+
});
|
|
19
|
+
it('should work without motion feature (returns light only)', () => {
|
|
20
|
+
const device = makeDevice({
|
|
21
|
+
category: 'motion_switch',
|
|
22
|
+
features: [makeFeature({ id: 10, eventTypeName: 'OnOff', isLight: true, value: 0 })],
|
|
23
|
+
});
|
|
24
|
+
const result = assertResult(createEndpointForDevice(device, ctx));
|
|
25
|
+
assert.ok(result.featureIds.includes(10));
|
|
26
|
+
assert.ok(!result.featureIds.includes(50), 'should not include motion feature');
|
|
27
|
+
});
|
|
28
|
+
it('should create outlet with occupancy for non-light motion switch', () => {
|
|
29
|
+
const device = makeDevice({
|
|
30
|
+
category: 'motion_switch',
|
|
31
|
+
features: [
|
|
32
|
+
makeFeature({ id: 10, eventTypeName: 'OnOff', isLight: false, value: 0 }),
|
|
33
|
+
makeFeature({ id: 50, featureTypeCategory: 'motion', value: 1 }),
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
const result = assertResult(createEndpointForDevice(device, ctx));
|
|
37
|
+
assert.ok(result.featureIds.includes(10));
|
|
38
|
+
assert.ok(result.featureIds.includes(50));
|
|
39
|
+
});
|
|
40
|
+
it('should delegate non-motion updates to original handler', () => {
|
|
41
|
+
const device = makeDevice({
|
|
42
|
+
category: 'motion_switch',
|
|
43
|
+
features: [
|
|
44
|
+
makeFeature({ id: 10, eventTypeName: 'OnOff', isLight: true, value: 1 }),
|
|
45
|
+
makeFeature({ id: 50, featureTypeCategory: 'motion', value: 0 }),
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
const result = assertResult(createEndpointForDevice(device, ctx));
|
|
49
|
+
// updateAttribute for onOff should not throw (delegates to original)
|
|
50
|
+
suppressLogs(() => {
|
|
51
|
+
result.updateAttribute(10, 0);
|
|
52
|
+
result.updateAttribute(50, 1);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
it('should return null when switch has no OnOff feature', () => {
|
|
56
|
+
const device = makeDevice({
|
|
57
|
+
category: 'motion_switch',
|
|
58
|
+
features: [makeFeature({ id: 50, featureTypeCategory: 'motion', value: 0 })],
|
|
59
|
+
});
|
|
60
|
+
const result = createEndpointForDevice(device, ctx);
|
|
61
|
+
assert.equal(result, null);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=motionSwitch.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motionSwitch.test.js","sourceRoot":"","sources":["../../../test/devices/motionSwitch.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it } from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
|
-
import { Thermostat } from 'matterbridge/matter/clusters';
|
|
4
|
-
import { createThermostat, iotasModeToSystemMode } from '../../src/devices/thermostat.js';
|
|
3
|
+
import { FanControl, Thermostat } from 'matterbridge/matter/clusters';
|
|
4
|
+
import { createThermostat, iotasModeToSystemMode, iotasFanModeToMatter } from '../../src/devices/thermostat.js';
|
|
5
5
|
import { assertResult, makeCtx, makeDevice, makeFeature, suppressLogs } from './helpers.js';
|
|
6
6
|
describe('thermostat', () => {
|
|
7
7
|
const ctx = makeCtx();
|
|
@@ -26,6 +26,43 @@ describe('thermostat', () => {
|
|
|
26
26
|
const result = assertResult(createThermostat(device, ctx));
|
|
27
27
|
assert.deepEqual(result.featureIds, [30, 31, 32, 33]);
|
|
28
28
|
});
|
|
29
|
+
it('should include humidity when present', () => {
|
|
30
|
+
const device = makeDevice({
|
|
31
|
+
category: 'thermostat',
|
|
32
|
+
features: [
|
|
33
|
+
makeFeature({ id: 30, featureTypeCategory: 'current_temperature', value: 72 }),
|
|
34
|
+
makeFeature({ id: 34, featureTypeCategory: 'humidity', value: 45 }),
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
const result = assertResult(createThermostat(device, ctx));
|
|
38
|
+
assert.deepEqual(result.featureIds, [30, 34]);
|
|
39
|
+
});
|
|
40
|
+
it('should include fan mode when present', () => {
|
|
41
|
+
const device = makeDevice({
|
|
42
|
+
category: 'thermostat',
|
|
43
|
+
features: [
|
|
44
|
+
makeFeature({ id: 30, featureTypeCategory: 'current_temperature', value: 72 }),
|
|
45
|
+
makeFeature({ id: 35, featureTypeCategory: 'fan_mode', eventTypeName: 'FanMode', value: 0 }),
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
const result = assertResult(createThermostat(device, ctx));
|
|
49
|
+
assert.deepEqual(result.featureIds, [30, 35]);
|
|
50
|
+
});
|
|
51
|
+
it('should include all optional features together', () => {
|
|
52
|
+
const device = makeDevice({
|
|
53
|
+
category: 'thermostat',
|
|
54
|
+
features: [
|
|
55
|
+
makeFeature({ id: 30, featureTypeCategory: 'current_temperature', value: 72 }),
|
|
56
|
+
makeFeature({ id: 31, featureTypeCategory: 'thermostat_mode', value: 1 }),
|
|
57
|
+
makeFeature({ id: 32, featureTypeCategory: 'heat_set_point', value: 68 }),
|
|
58
|
+
makeFeature({ id: 33, featureTypeCategory: 'cool_set_point', value: 76 }),
|
|
59
|
+
makeFeature({ id: 34, featureTypeCategory: 'humidity', value: 45 }),
|
|
60
|
+
makeFeature({ id: 35, featureTypeCategory: 'fan_mode', eventTypeName: 'FanMode', value: 0 }),
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
const result = assertResult(createThermostat(device, ctx));
|
|
64
|
+
assert.deepEqual(result.featureIds, [30, 31, 32, 33, 34, 35]);
|
|
65
|
+
});
|
|
29
66
|
it('should return null when temperature feature is missing', () => {
|
|
30
67
|
assert.equal(createThermostat(makeDevice({ features: [] }), ctx), null);
|
|
31
68
|
});
|
|
@@ -37,16 +74,18 @@ describe('thermostat', () => {
|
|
|
37
74
|
makeFeature({ id: 31, featureTypeCategory: 'thermostat_mode', value: 1 }),
|
|
38
75
|
makeFeature({ id: 32, featureTypeCategory: 'heat_set_point', value: 68 }),
|
|
39
76
|
makeFeature({ id: 33, featureTypeCategory: 'cool_set_point', value: 76 }),
|
|
77
|
+
makeFeature({ id: 34, featureTypeCategory: 'humidity', value: 45 }),
|
|
78
|
+
makeFeature({ id: 35, featureTypeCategory: 'fan_mode', eventTypeName: 'FanMode', value: 0 }),
|
|
40
79
|
],
|
|
41
80
|
});
|
|
42
81
|
const result = assertResult(createThermostat(device, ctx));
|
|
43
|
-
// Should not throw for any tracked feature
|
|
44
82
|
suppressLogs(() => {
|
|
45
83
|
assert.doesNotThrow(() => result.updateAttribute(30, 75));
|
|
46
84
|
assert.doesNotThrow(() => result.updateAttribute(31, 2));
|
|
47
85
|
assert.doesNotThrow(() => result.updateAttribute(32, 70));
|
|
48
86
|
assert.doesNotThrow(() => result.updateAttribute(33, 78));
|
|
49
|
-
|
|
87
|
+
assert.doesNotThrow(() => result.updateAttribute(34, 50));
|
|
88
|
+
assert.doesNotThrow(() => result.updateAttribute(35, 1));
|
|
50
89
|
assert.doesNotThrow(() => result.updateAttribute(999, 0));
|
|
51
90
|
});
|
|
52
91
|
});
|
|
@@ -61,4 +100,15 @@ describe('iotasModeToSystemMode', () => {
|
|
|
61
100
|
assert.equal(iotasModeToSystemMode(99), Thermostat.SystemMode.Off);
|
|
62
101
|
});
|
|
63
102
|
});
|
|
103
|
+
describe('iotasFanModeToMatter', () => {
|
|
104
|
+
it('should map IOTAS fan modes to Matter FanMode', () => {
|
|
105
|
+
assert.equal(iotasFanModeToMatter(0), FanControl.FanMode.Auto); // Auto Low → Auto
|
|
106
|
+
assert.equal(iotasFanModeToMatter(1), FanControl.FanMode.Low); // On Low → Low
|
|
107
|
+
assert.equal(iotasFanModeToMatter(2), FanControl.FanMode.On); // Circulate → On
|
|
108
|
+
});
|
|
109
|
+
it('should default to Auto for unknown modes', () => {
|
|
110
|
+
assert.equal(iotasFanModeToMatter(99), FanControl.FanMode.Auto);
|
|
111
|
+
assert.equal(iotasFanModeToMatter(-1), FanControl.FanMode.Auto);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
64
114
|
//# sourceMappingURL=thermostat.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thermostat.test.js","sourceRoot":"","sources":["../../../test/devices/thermostat.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"thermostat.test.js","sourceRoot":"","sources":["../../../test/devices/thermostat.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge-iotas",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Matterbridge plugin for IOTAS smart home devices",
|
|
5
5
|
"author": "Augusto Meza <mezaugusto@proton.me>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"printWidth": 120
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"iotas-ts": "^1.
|
|
57
|
+
"iotas-ts": "^2.1.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@eslint/js": "^9.0.0",
|