Skip to content

Commit af30f61

Browse files
committed
Add contact sensor state option for garage doors
1 parent 665a7bb commit af30f61

5 files changed

Lines changed: 58 additions & 4 deletions

File tree

ADVANCED_OPTIONS.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Before configuring, you may need to:
2020
- `category` - **optional**: Device category code. See [SUPPORTED_DEVICES.md](./SUPPORTED_DEVICES.md). Also you can use `hidden` to hide the device, product, or scene. **⚠️Overriding this property may lead to unexpected behaviors and exceptions, so please remove the accessory cache after making changes.**
2121
- `unbridged` - **optional**: Unbridge accessories. Defaults to `false`.
2222
- `adaptiveLighting` - **optional**: Adaptive Lighting. Defaults to `false`. Not all light device support this feature, please use it on demand.
23+
- `garageDoorUseContactSensorForState` - **optional**: For garage door controllers. When `true`, `CurrentDoorState` and `TargetDoorState` reads use `doorcontact_state` only, while set commands still use `switch_1`. Defaults to `false`.
2324
- `schema` - **optional**: An array of schema overriding config objects, used for describing datapoint (DP). When your device has non-standard DP, you need to transform them manually with configuration. Each element in the schema array is described as follows:
2425
- `code` - **required**: DP code.
2526
- `newCode` - **optional**: New DP code.
@@ -94,6 +95,22 @@ An example of hide camera's floodlight (`floodlight_switch`):
9495
}
9596
```
9697

98+
### Use garage door contact sensor for state
99+
100+
Some `ckmkzq` garage door controllers keep `switch_1` as `true`, which can make HomeKit show the door as stuck Opening or Closing. Enable this per-device option to read the door state from `doorcontact_state`, while commands are still sent to `switch_1`.
101+
102+
```js
103+
{
104+
"options": {
105+
// ...
106+
"deviceOverrides": [{
107+
"id": "{device_id}",
108+
"garageDoorUseContactSensorForState": true
109+
}]
110+
}
111+
}
112+
```
113+
97114

98115
### Offline as off
99116

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ Before you can configure, you must go to the [Tuya IoT Platform](https://iot.tuy
107107
#### Advanced options
108108
See [ADVANCED_OPTIONS.md](./ADVANCED_OPTIONS.md)
109109

110+
Garage door controllers that keep `switch_1=true` can opt in to contact-sensor-only state reads with `garageDoorUseContactSensorForState` in `options.deviceOverrides`. This keeps commands on `switch_1`, but reads HomeKit state from `doorcontact_state`.
111+
110112

111113
## Limitations
112114
- **⚠️Don't forget to extend the API trial period every 6 months. Maybe you can set up a reminder in calendar.**

config.schema.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@
140140
"functionBody": "return (model.options && model.options.deviceOverrides);"
141141
}
142142
},
143+
"garageDoorUseContactSensorForState": {
144+
"title": "Use Contact Sensor For Garage Door State",
145+
"description": "For garage door controllers only. Derive CurrentDoorState and TargetDoorState reads from doorcontact_state instead of switch_1.",
146+
"type": "boolean",
147+
"condition": {
148+
"functionBody": "return (model.options && model.options.deviceOverrides);"
149+
}
150+
},
143151
"schema": {
144152
"title": "Schema Overriding Configs",
145153
"type": "array",
@@ -425,6 +433,9 @@
425433
{
426434
"key": "options.deviceOverrides[].unbridged"
427435
},
436+
{
437+
"key": "options.deviceOverrides[].garageDoorUseContactSensorForState"
438+
},
428439
{
429440
"key": "options.deviceOverrides[].schema",
430441
"add": "Add New Schema",

src/accessory/GarageDoorAccessory.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,41 @@ export default class GarageDoorAccessory extends BaseAccessory {
1212
}
1313

1414
configureServices() {
15-
1615
this.configureCurrentDoorState();
1716
this.configureTargetDoorState();
1817
}
1918

20-
2119
mainService() {
2220
return this.accessory.getService(this.Service.GarageDoorOpener)
2321
|| this.accessory.addService(this.Service.GarageDoorOpener);
2422
}
2523

24+
useContactSensorForState() {
25+
return this.platform.getDeviceConfig(this.device)?.garageDoorUseContactSensorForState === true;
26+
}
27+
2628
configureCurrentDoorState() {
2729
const { OPEN, CLOSED, OPENING, CLOSING, STOPPED } = this.Characteristic.CurrentDoorState;
2830
this.mainService().getCharacteristic(this.Characteristic.CurrentDoorState)
2931
.onGet(() => {
3032
const currentSchema = this.getSchema(...SCHEMA_CODE.CURRENT_DOOR_STATE);
31-
const targetSchema = this.getSchema(...SCHEMA_CODE.TARGET_DOOR_STATE);
32-
if (!currentSchema || !targetSchema) {
33+
if (!currentSchema) {
3334
return STOPPED;
3435
}
3536

3637
const currentStatus = this.getStatus(currentSchema.code)!;
38+
39+
if (this.useContactSensorForState()) {
40+
return currentStatus.value === false ? CLOSED : OPEN;
41+
}
42+
43+
const targetSchema = this.getSchema(...SCHEMA_CODE.TARGET_DOOR_STATE);
44+
if (!targetSchema) {
45+
return STOPPED;
46+
}
47+
3748
const targetStatus = this.getStatus(targetSchema.code)!;
49+
3850
if (currentStatus.value === true && targetStatus.value === true) {
3951
return OPEN;
4052
} else if (currentStatus.value === false && targetStatus.value === false) {
@@ -58,6 +70,17 @@ export default class GarageDoorAccessory extends BaseAccessory {
5870
const { OPEN, CLOSED } = this.Characteristic.TargetDoorState;
5971
this.mainService().getCharacteristic(this.Characteristic.TargetDoorState)
6072
.onGet(() => {
73+
if (this.useContactSensorForState()) {
74+
const currentSchema = this.getSchema(...SCHEMA_CODE.CURRENT_DOOR_STATE);
75+
76+
if (!currentSchema) {
77+
return CLOSED;
78+
}
79+
80+
const currentStatus = this.getStatus(currentSchema.code)!;
81+
return currentStatus.value === false ? CLOSED : OPEN;
82+
}
83+
6184
const status = this.getStatus(schema.code)!;
6285
return status.value as boolean ? OPEN : CLOSED;
6386
})

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface TuyaPlatformDeviceConfig {
1717
schema?: Array<TuyaPlatformDeviceSchemaConfig>;
1818
unbridged?: boolean;
1919
adaptiveLighting?: boolean;
20+
garageDoorUseContactSensorForState?: boolean;
2021
}
2122

2223
export interface TuyaPlatformServiceInformationConfig {

0 commit comments

Comments
 (0)