Skip to content

Commit bbd02c4

Browse files
Matter: Add PM10 sensors (#2354)
Co-authored-by: Pierre-Gilles Leymarie <[email protected]>
1 parent abbe0c6 commit bbd02c4

File tree

11 files changed

+112
-0
lines changed

11 files changed

+112
-0
lines changed

front/src/components/boxs/device-in-room/device-features/sensor-value/BadgeNumberDeviceValue.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const BADGE_CATEGORIES = {
6363
[DEVICE_FEATURE_CATEGORIES.CO2_SENSOR]: value => colorLowAsGreen(value, 600, 1200),
6464
[DEVICE_FEATURE_CATEGORIES.VOC_SENSOR]: value => colorLowAsGreen(value, 250, 2000),
6565
[DEVICE_FEATURE_CATEGORIES.VOC_INDEX_SENSOR]: value => getVocIndexColor(value),
66+
[DEVICE_FEATURE_CATEGORIES.PM10_SENSOR]: value => colorLowAsGreen(value, 30, 50),
6667
[DEVICE_FEATURE_CATEGORIES.PM25_SENSOR]: value => colorLowAsGreen(value, 15, 25),
6768
[DEVICE_FEATURE_CATEGORIES.FORMALDEHYD_SENSOR]: value => colorLowAsGreen(value, 50, 120),
6869
[DEVICE_FEATURE_CATEGORIES.AIRQUALITY_SENSOR]: value => getAqiColor(value),

front/src/config/i18n/de.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3378,6 +3378,10 @@
33783378
"shortCategoryName": "PM2.5-Sensor",
33793379
"decimal": "PM2.5 (Dezimal)"
33803380
},
3381+
"pm10-sensor": {
3382+
"shortCategoryName": "PM10-Sensor",
3383+
"decimal": "PM10 (Dezimal)"
3384+
},
33813385
"formaldehyd-sensor": {
33823386
"shortCategoryName": "Formaldehyd-Sensor",
33833387
"decimal": "Formaldehyd (Dezimal)"

front/src/config/i18n/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3378,6 +3378,10 @@
33783378
"shortCategoryName": "PM2.5 sensor",
33793379
"decimal": "PM2.5 (decimal)"
33803380
},
3381+
"pm10-sensor": {
3382+
"shortCategoryName": "PM10 sensor",
3383+
"decimal": "PM10 (decimal)"
3384+
},
33813385
"formaldehyd-sensor": {
33823386
"shortCategoryName": "Formaldehyd sensor",
33833387
"decimal": "Formaldehyd (decimal)"

front/src/config/i18n/fr.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3378,6 +3378,10 @@
33783378
"shortCategoryName": "Capteur de PM2.5",
33793379
"decimal": "PM2.5 (Décimale)"
33803380
},
3381+
"pm10-sensor": {
3382+
"shortCategoryName": "Capteur de PM10",
3383+
"decimal": "PM10 (Décimale)"
3384+
},
33813385
"formaldehyd-sensor": {
33823386
"shortCategoryName": "Capteur Formaldéhyde",
33833387
"decimal": "Formaldéhyde (Décimale)"

front/src/utils/consts.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ export const DeviceFeatureCategoriesIcon = {
260260
[DEVICE_FEATURE_CATEGORIES.PM25_SENSOR]: {
261261
[DEVICE_FEATURE_TYPES.SENSOR.DECIMAL]: 'bar-chart-2'
262262
},
263+
[DEVICE_FEATURE_CATEGORIES.PM10_SENSOR]: {
264+
[DEVICE_FEATURE_TYPES.SENSOR.DECIMAL]: 'bar-chart-2'
265+
},
263266
[DEVICE_FEATURE_CATEGORIES.FORMALDEHYD_SENSOR]: {
264267
[DEVICE_FEATURE_TYPES.SENSOR.DECIMAL]: 'bar-chart-2'
265268
},

server/services/matter/lib/matter.listenToStateChange.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
RelativeHumidityMeasurement,
1010
Thermostat,
1111
Pm25ConcentrationMeasurement,
12+
Pm10ConcentrationMeasurement,
1213
// eslint-disable-next-line import/no-unresolved
1314
} = require('@matter/main/clusters');
1415

@@ -189,6 +190,22 @@ async function listenToStateChange(nodeId, devicePath, device) {
189190
});
190191
}
191192

193+
const pm10ConcentrationMeasurement = device.clusterClients.get(Pm10ConcentrationMeasurement.Complete.id);
194+
if (pm10ConcentrationMeasurement && !this.stateChangeListeners.has(pm10ConcentrationMeasurement)) {
195+
logger.debug(
196+
`Matter: Adding state change listener for Pm10ConcentrationMeasurement cluster ${pm10ConcentrationMeasurement.name}`,
197+
);
198+
this.stateChangeListeners.add(pm10ConcentrationMeasurement);
199+
// Subscribe to Pm10ConcentrationMeasurement attribute changes
200+
pm10ConcentrationMeasurement.addMeasuredValueAttributeListener((value) => {
201+
logger.debug(`Matter: Pm10ConcentrationMeasurement attribute changed to ${value}`);
202+
this.gladys.event.emit(EVENTS.DEVICE.NEW_STATE, {
203+
device_feature_external_id: `matter:${nodeId}:${devicePath}:${Pm10ConcentrationMeasurement.Complete.id}`,
204+
state: value,
205+
});
206+
});
207+
}
208+
192209
const thermostat = device.clusterClients.get(Thermostat.Complete.id);
193210
if (thermostat && !this.stateChangeListeners.has(thermostat)) {
194211
logger.debug(`Matter: Adding state change listener for Thermostat cluster ${thermostat.name}`);

server/services/matter/utils/convertToGladysDevice.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
RelativeHumidityMeasurement,
1010
Thermostat,
1111
Pm25ConcentrationMeasurement,
12+
Pm10ConcentrationMeasurement,
1213
// eslint-disable-next-line import/no-unresolved
1314
} = require('@matter/main/clusters');
1415
const Promise = require('bluebird');
@@ -221,6 +222,18 @@ async function convertToGladysDevice(serviceId, nodeId, device, nodeDetailDevice
221222
min: 0,
222223
max: 1500,
223224
});
225+
} else if (clusterIndex === Pm10ConcentrationMeasurement.Complete.id) {
226+
gladysDevice.features.push({
227+
...commonNewFeature,
228+
category: DEVICE_FEATURE_CATEGORIES.PM10_SENSOR,
229+
type: DEVICE_FEATURE_TYPES.SENSOR.DECIMAL,
230+
read_only: true,
231+
has_feedback: true,
232+
unit: DEVICE_FEATURE_UNITS.MICROGRAM_PER_CUBIC_METER,
233+
external_id: `matter:${nodeId}:${devicePath}:${clusterIndex}`,
234+
min: 0,
235+
max: 1500,
236+
});
224237
}
225238
});
226239
}

server/services/zigbee2mqtt/exposes/numericType.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,6 +908,15 @@ module.exports = {
908908
max: 999,
909909
},
910910
},
911+
pm10: {
912+
feature: {
913+
category: DEVICE_FEATURE_CATEGORIES.PM10_SENSOR,
914+
type: DEVICE_FEATURE_TYPES.SENSOR.DECIMAL,
915+
unit: DEVICE_FEATURE_UNITS.MICROGRAM_PER_CUBIC_METER,
916+
min: 0,
917+
max: 999,
918+
},
919+
},
911920
formaldehyd: {
912921
feature: {
913922
category: DEVICE_FEATURE_CATEGORIES.FORMALDEHYD_SENSOR,

server/test/services/matter/lib/listenToStateChange.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
RelativeHumidityMeasurement,
1010
Thermostat,
1111
Pm25ConcentrationMeasurement,
12+
Pm10ConcentrationMeasurement,
1213
// eslint-disable-next-line import/no-unresolved
1314
} = require('@matter/main/clusters');
1415

@@ -193,6 +194,23 @@ describe('Matter.listenToStateChange', () => {
193194
state: 100,
194195
});
195196
});
197+
it('should listen to state change (Pm10ConcentrationMeasurement)', async () => {
198+
const clusterClients = new Map();
199+
clusterClients.set(Pm10ConcentrationMeasurement.Complete.id, {
200+
addMeasuredValueAttributeListener: (callback) => {
201+
callback(100);
202+
},
203+
});
204+
const device = {
205+
number: 1,
206+
clusterClients,
207+
};
208+
await matterHandler.listenToStateChange(1234n, '1', device);
209+
assert.calledWith(gladys.event.emit, EVENTS.DEVICE.NEW_STATE, {
210+
device_feature_external_id: 'matter:1234:1:1069',
211+
state: 100,
212+
});
213+
});
196214
it('should listen to state change (Thermostat heating)', async () => {
197215
const clusterClients = new Map();
198216
clusterClients.set(Thermostat.Complete.id, {

server/test/services/matter/lib/matter.init.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const {
22
Pm25ConcentrationMeasurement,
3+
Pm10ConcentrationMeasurement,
34
// eslint-disable-next-line import/no-unresolved
45
} = require('@matter/main/clusters');
56

@@ -171,6 +172,18 @@ describe('Matter.init', () => {
171172
addMeasuredValueAttributeListener: fake.returns(null),
172173
});
173174

175+
// PM10 concentration measurement
176+
clusterClients.set(Pm10ConcentrationMeasurement.Complete.id, {
177+
id: Pm10ConcentrationMeasurement.Complete.id,
178+
name: 'Pm10ConcentrationMeasurement',
179+
endpointId: 1,
180+
attributes: {
181+
measuredValue: {},
182+
},
183+
commands: {},
184+
addMeasuredValueAttributeListener: fake.returns(null),
185+
});
186+
174187
// Mock commissioning controller
175188
commissioningController = {
176189
start: fake.resolves(null),
@@ -405,6 +418,18 @@ describe('Matter.init', () => {
405418
type: 'decimal',
406419
unit: 'microgram-per-cubic-meter',
407420
},
421+
{
422+
category: 'pm10-sensor',
423+
external_id: 'matter:12345:1:1069',
424+
has_feedback: true,
425+
max: 1500,
426+
min: 0,
427+
name: 'Pm10ConcentrationMeasurement - 1',
428+
read_only: true,
429+
selector: matterHandler.devices[0].features[12].selector,
430+
type: 'decimal',
431+
unit: 'microgram-per-cubic-meter',
432+
},
408433
],
409434
params: [],
410435
},
@@ -555,6 +580,18 @@ describe('Matter.init', () => {
555580
type: 'decimal',
556581
unit: 'microgram-per-cubic-meter',
557582
},
583+
{
584+
category: 'pm10-sensor',
585+
external_id: 'matter:12345:1:child_endpoint:2:1069',
586+
has_feedback: true,
587+
max: 1500,
588+
min: 0,
589+
name: 'Pm10ConcentrationMeasurement - 1',
590+
read_only: true,
591+
selector: matterHandler.devices[1].features[12].selector,
592+
type: 'decimal',
593+
unit: 'microgram-per-cubic-meter',
594+
},
558595
],
559596
params: [],
560597
},

0 commit comments

Comments
 (0)