Skip to content
This repository was archived by the owner on Nov 15, 2025. It is now read-only.

Commit f1603a3

Browse files
authored
Merge pull request #17 from RobinBol/fix/disable-entity-state-parsing
Fix/disable entity state parsing
2 parents 98b2dee + 0c635ed commit f1603a3

5 files changed

Lines changed: 125 additions & 154 deletions

File tree

.homeychangelog.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,8 @@
2525
},
2626
"1.1.3": {
2727
"en": "Fixes an issue that could cause the app to crash in rare circumstances."
28+
},
29+
"1.1.4": {
30+
"en": "Made parsing events from EP less CPU intensive."
2831
}
2932
}

.homeycompose/app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "io.everythingsmart",
3-
"version": "1.1.3",
3+
"version": "1.1.4",
44
"compatibility": ">=5.0.0",
55
"sdk": 3,
66
"platforms": ["local"],

app.json

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,21 @@
11
{
22
"_comment": "This file is generated. Please edit .homeycompose/app.json instead.",
33
"id": "io.everythingsmart",
4-
"version": "1.1.3",
4+
"version": "1.1.4",
55
"compatibility": ">=5.0.0",
66
"sdk": 3,
7-
"platforms": [
8-
"local"
9-
],
7+
"platforms": ["local"],
108
"name": {
119
"en": "Everything Smart"
1210
},
1311
"tags": {
14-
"en": [
15-
"everything",
16-
"presence",
17-
"everythingsmart",
18-
"mmwave"
19-
]
12+
"en": ["everything", "presence", "everythingsmart", "mmwave"]
2013
},
2114
"brandColor": "#5621F5",
2215
"description": {
2316
"en": "Building a Better Smart Home"
2417
},
25-
"category": [
26-
"security"
27-
],
18+
"category": ["security"],
2819
"permissions": [],
2920
"images": {
3021
"small": "/assets/images/small.png",
@@ -56,16 +47,9 @@
5647
"en": "Everything Presence Lite"
5748
},
5849
"class": "sensor",
59-
"capabilities": [
60-
"measure_luminance",
61-
"alarm_motion"
62-
],
63-
"platforms": [
64-
"local"
65-
],
66-
"connectivity": [
67-
"lan"
68-
],
50+
"capabilities": ["measure_luminance", "alarm_motion"],
51+
"platforms": ["local"],
52+
"connectivity": ["lan"],
6953
"discovery": "everything-presence-lite",
7054
"images": {
7155
"small": "/drivers/everything-presence-lite/assets/images/small.jpg",
@@ -297,12 +281,8 @@
297281
}
298282
}
299283
},
300-
"platforms": [
301-
"local"
302-
],
303-
"connectivity": [
304-
"lan"
305-
],
284+
"platforms": ["local"],
285+
"connectivity": ["lan"],
306286
"discovery": "everything-presence-one",
307287
"images": {
308288
"small": "/drivers/everything-presence-one/assets/images/small.jpg",
@@ -682,4 +662,4 @@
682662
]
683663
}
684664
}
685-
}
665+
}

drivers/everything-presence-lite/device.ts

Lines changed: 44 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -430,9 +430,13 @@ class EverythingPresenceLiteDevice extends Homey.Device {
430430
}
431431

432432
// Subscribe to entity events
433-
entity.on(`state`, (state: unknown) =>
434-
this.onEntityState(parseEntityResult.data.config.objectId, state)
435-
);
433+
entity.on(`state`, (state: unknown) => {
434+
try {
435+
this.onEntityState(parseEntityResult.data.config.objectId, state);
436+
} catch (err) {
437+
this.debugEntity('Failed to handle entity state event', err);
438+
}
439+
});
436440
}
437441

438442
/**
@@ -442,17 +446,8 @@ class EverythingPresenceLiteDevice extends Homey.Device {
442446
* @param state
443447
*/
444448
onEntityState(entityId: string, state: unknown) {
445-
const parseResult = entityStateSchema.safeParse(state);
446-
if (!parseResult.success) {
447-
this.debugEntity(
448-
`Got invalid entity state for entityId ${entityId}, error:`,
449-
parseResult.error,
450-
state
451-
);
452-
return;
453-
}
454-
455-
const parsedState = parseResult.data;
449+
// Skip parsing which may cause CPU spikes
450+
const parsedState = state as z.infer<typeof entityStateSchema>;
456451

457452
// Get entity
458453
const entity = this.entities.get(entityId)?.data;
@@ -471,21 +466,21 @@ class EverythingPresenceLiteDevice extends Homey.Device {
471466

472467
switch (entity.config.deviceClass) {
473468
case 'illuminance':
474-
// Throw when state is not a number
475-
z.number().parse(parsedState.state);
476-
this.debugEntity(`Capability: measure_luminance: state event`, parsedState.state);
477-
this.setCapabilityValue('measure_luminance', parsedState.state).catch((err) =>
478-
this.debugEntity('Failed to set measure_luminance capability value', err)
479-
);
469+
if (typeof parsedState?.state === 'number') {
470+
this.debugEntity(`Capability: measure_luminance: state event`, parsedState?.state);
471+
this.setCapabilityValue('measure_luminance', parsedState?.state).catch((err) =>
472+
this.debugEntity('Failed to set measure_luminance capability value', err)
473+
);
474+
}
480475
break;
481476
case 'occupancy':
482-
// Throw when state is not a boolean
483-
z.boolean().parse(parsedState.state);
484-
if (includesBinarySensorOccupancy(entity)) {
485-
this.debugEntity(`Capability: alarm_motion: state event`, parsedState.state);
486-
this.setCapabilityValue('alarm_motion', parsedState.state).catch((err) =>
487-
this.debugEntity('Failed to set alarm_motion capability value', err)
488-
);
477+
if (typeof parsedState?.state === 'boolean') {
478+
if (includesBinarySensorOccupancy(entity)) {
479+
this.debugEntity(`Capability: alarm_motion: state event`, parsedState?.state);
480+
this.setCapabilityValue('alarm_motion', parsedState?.state).catch((err) =>
481+
this.debugEntity('Failed to set alarm_motion capability value', err)
482+
);
483+
}
489484
}
490485
break;
491486
default:
@@ -495,31 +490,30 @@ class EverythingPresenceLiteDevice extends Homey.Device {
495490
// Read and update settings
496491
switch (entity.config.objectId) {
497492
case DRIVER_SETTINGS.MMWAVE_DISTANCE:
498-
// Throw when state is not a number
499-
z.number().parse(parsedState.state);
500-
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState.state);
501-
this.setSettings({
502-
[entity.config.objectId]: parsedState.state
503-
}).catch((err) =>
504-
this.debugEntity(
505-
`Failed to set setting ${entity.config.objectId} to value: ${parsedState.state}, reason:`,
506-
err
507-
)
508-
);
493+
if (typeof parsedState?.state === 'number') {
494+
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState?.state);
495+
this.setSettings({
496+
[entity.config.objectId]: parsedState?.state
497+
}).catch((err) =>
498+
this.debugEntity(
499+
`Failed to set setting ${entity.config.objectId} to value: ${parsedState?.state}, reason:`,
500+
err
501+
)
502+
);
503+
}
509504
break;
510505
case DRIVER_SETTINGS.ESP_32_LED:
511-
// Throw when state is not a boolean
512-
z.boolean().parse(parsedState.state);
513-
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState.state);
514-
this.setSettings({
515-
[entity.config.objectId]: parsedState.state
516-
}).catch((err) =>
517-
this.debugEntity(
518-
`Failed to set setting ${entity.config.objectId} to value: ${parsedState.state}, reason:`,
519-
err
520-
)
521-
);
522-
506+
if (typeof parsedState?.state === 'boolean') {
507+
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState?.state);
508+
this.setSettings({
509+
[entity.config.objectId]: parsedState?.state
510+
}).catch((err) =>
511+
this.debugEntity(
512+
`Failed to set setting ${entity.config.objectId} to value: ${parsedState?.state}, reason:`,
513+
err
514+
)
515+
);
516+
}
523517
break;
524518
default:
525519
this.debugEntity('Unknown setting:', entity.config.objectId);

drivers/everything-presence-one/device.ts

Lines changed: 67 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -440,9 +440,13 @@ class EverythingPresenceOneDevice extends Homey.Device {
440440
}
441441

442442
// Subscribe to entity events
443-
entity.on(`state`, (state: unknown) =>
444-
this.onEntityState(parseEntityResult.data.config.objectId, state)
445-
);
443+
entity.on(`state`, (state: unknown) => {
444+
try {
445+
this.onEntityState(parseEntityResult.data.config.objectId, state);
446+
} catch (err) {
447+
this.debugEntity('Failed to handle entity state event', err);
448+
}
449+
});
446450
}
447451

448452
/**
@@ -452,17 +456,8 @@ class EverythingPresenceOneDevice extends Homey.Device {
452456
* @param state
453457
*/
454458
onEntityState(entityId: string, state: unknown) {
455-
const parseResult = entityStateSchema.safeParse(state);
456-
if (!parseResult.success) {
457-
this.debugEntity(
458-
`Got invalid entity state for entityId ${entityId}, error:`,
459-
parseResult.error,
460-
state
461-
);
462-
return;
463-
}
464-
465-
const parsedState = parseResult.data;
459+
// Skip parsing which may cause CPU spikes
460+
const parsedState = state as z.infer<typeof entityStateSchema>;
466461

467462
// Get entity
468463
const entity = this.entities.get(entityId)?.data;
@@ -479,50 +474,50 @@ class EverythingPresenceOneDevice extends Homey.Device {
479474

480475
switch (entity.config.deviceClass) {
481476
case 'temperature':
482-
// Throw when state is not a number
483-
z.number().parse(parsedState.state);
484-
this.debugEntity(`Capability: measure_temperature: state event`, parsedState.state);
485-
this.setCapabilityValue('measure_temperature', parsedState.state).catch((err) =>
486-
this.debugEntity('Failed to set measure_temperature capability value', err)
487-
);
477+
if (typeof parsedState?.state === 'number') {
478+
this.debugEntity(`Capability: measure_temperature: state event`, parsedState?.state);
479+
this.setCapabilityValue('measure_temperature', parsedState?.state).catch((err) =>
480+
this.debugEntity('Failed to set measure_temperature capability value', err)
481+
);
482+
}
488483
break;
489484
case 'humidity':
490-
// Throw when state is not a number
491-
z.number().parse(parsedState.state);
492-
this.debugEntity(`Capability: measure_humidity: state event`, parsedState.state);
493-
this.setCapabilityValue('measure_humidity', parsedState.state).catch((err) =>
494-
this.debugEntity('Failed to set measure_humidity capability value', err)
495-
);
485+
if (typeof parsedState?.state === 'number') {
486+
this.debugEntity(`Capability: measure_humidity: state event`, parsedState?.state);
487+
this.setCapabilityValue('measure_humidity', parsedState?.state).catch((err) =>
488+
this.debugEntity('Failed to set measure_humidity capability value', err)
489+
);
490+
}
496491
break;
497492
case 'illuminance':
498-
// Throw when state is not a number
499-
z.number().parse(parsedState.state);
500-
this.debugEntity(`Capability: measure_luminance: state event`, parsedState.state);
501-
this.setCapabilityValue('measure_luminance', parsedState.state).catch((err) =>
502-
this.debugEntity('Failed to set measure_luminance capability value', err)
503-
);
493+
if (typeof parsedState?.state === 'number') {
494+
this.debugEntity(`Capability: measure_luminance: state event`, parsedState?.state);
495+
this.setCapabilityValue('measure_luminance', parsedState?.state).catch((err) =>
496+
this.debugEntity('Failed to set measure_luminance capability value', err)
497+
);
498+
}
504499
break;
505500
case 'motion':
506-
// Throw when state is not a boolean
507-
z.boolean().parse(parsedState.state);
508-
this.debugEntity(`Capability: alarm_motion.pir: state event`, parsedState.state);
509-
this.setCapabilityValue('alarm_motion.pir', parsedState.state).catch((err) =>
510-
this.debugEntity('Failed to set alarm_motion.pir capability value', err)
511-
);
501+
if (typeof parsedState?.state === 'boolean') {
502+
this.debugEntity(`Capability: alarm_motion.pir: state event`, parsedState?.state);
503+
this.setCapabilityValue('alarm_motion.pir', parsedState?.state).catch((err) =>
504+
this.debugEntity('Failed to set alarm_motion.pir capability value', err)
505+
);
506+
}
512507
break;
513508
case 'occupancy':
514-
// Throw when state is not a boolean
515-
z.boolean().parse(parsedState.state);
516-
if (includesBinarySensorMMWave(entity)) {
517-
this.debugEntity(`Capability: alarm_motion.mmwave: state event`, parsedState.state);
518-
this.setCapabilityValue('alarm_motion.mmwave', parsedState.state).catch((err) =>
519-
this.debugEntity('Failed to set alarm_motion.mmwave capability value', err)
520-
);
521-
} else if (includesBinarySensorOccupancy(entity)) {
522-
this.debugEntity(`Capability: alarm_motion: state event`, parsedState.state);
523-
this.setCapabilityValue('alarm_motion', parsedState.state).catch((err) =>
524-
this.debugEntity('Failed to set alarm_motion capability value', err)
525-
);
509+
if (typeof parsedState?.state === 'boolean') {
510+
if (includesBinarySensorMMWave(entity)) {
511+
this.debugEntity(`Capability: alarm_motion.mmwave: state event`, parsedState?.state);
512+
this.setCapabilityValue('alarm_motion.mmwave', parsedState?.state).catch((err) =>
513+
this.debugEntity('Failed to set alarm_motion.mmwave capability value', err)
514+
);
515+
} else if (includesBinarySensorOccupancy(entity)) {
516+
this.debugEntity(`Capability: alarm_motion: state event`, parsedState?.state);
517+
this.setCapabilityValue('alarm_motion', parsedState?.state).catch((err) =>
518+
this.debugEntity('Failed to set alarm_motion capability value', err)
519+
);
520+
}
526521
}
527522
break;
528523
default:
@@ -535,32 +530,31 @@ class EverythingPresenceOneDevice extends Homey.Device {
535530
case DRIVER_SETTINGS.MMWAVE_ON_LATENCY:
536531
case DRIVER_SETTINGS.MMWAVE_OFF_LATENCY:
537532
case DRIVER_SETTINGS.MMWAVE_DISTANCE:
538-
// Throw when state is not a number
539-
z.number().parse(parsedState.state);
540-
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState.state);
541-
this.setSettings({
542-
[entity.config.objectId]: parsedState.state
543-
}).catch((err) =>
544-
this.debugEntity(
545-
`Failed to set setting ${entity.config.objectId} to value: ${parsedState.state}, reason:`,
546-
err
547-
)
548-
);
533+
if (typeof parsedState?.state === 'number') {
534+
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState?.state);
535+
this.setSettings({
536+
[entity.config.objectId]: parsedState?.state
537+
}).catch((err) =>
538+
this.debugEntity(
539+
`Failed to set setting ${entity.config.objectId} to value: ${parsedState?.state}, reason:`,
540+
err
541+
)
542+
);
543+
}
549544
break;
550545
case DRIVER_SETTINGS.MMWAVE_LED:
551546
case DRIVER_SETTINGS.ESP_32_STATUS_LED:
552-
// Throw when state is not a boolean
553-
z.boolean().parse(parsedState.state);
554-
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState.state);
555-
this.setSettings({
556-
[entity.config.objectId]: parsedState.state
557-
}).catch((err) =>
558-
this.debugEntity(
559-
`Failed to set setting ${entity.config.objectId} to value: ${parsedState.state}, reason:`,
560-
err
561-
)
562-
);
563-
547+
if (typeof parsedState?.state === 'boolean') {
548+
this.debugEntity(`Setting: ${entity.config.objectId}: state event`, parsedState?.state);
549+
this.setSettings({
550+
[entity.config.objectId]: parsedState?.state
551+
}).catch((err) =>
552+
this.debugEntity(
553+
`Failed to set setting ${entity.config.objectId} to value: ${parsedState?.state}, reason:`,
554+
err
555+
)
556+
);
557+
}
564558
break;
565559
default:
566560
this.debugEntity('Unknown setting:', entity.config.objectId);

0 commit comments

Comments
 (0)