Skip to content

Commit

Permalink
Reimplement ContactSensorAccessory and LeakSensorAccessory
Browse files Browse the repository at this point in the history
  • Loading branch information
0x5e committed Oct 22, 2022
1 parent d7faba0 commit e39a736
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 14 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
- Fix access_token undefined error. (https://github.com/tuya/tuya-homebridge/issues/298#issuecomment-1278238870 by @Azukovskij )

### Accessory category specific
- Rewrite `BaseAccessory`, `SwitchAccessory`, `OutletAccessory`, `LightAccessory`, reduce about 50% code size. Now writing a accessory class is much more simple.
- Rewrite `BaseAccessory`, `SwitchAccessory`, `OutletAccessory`, `LightAccessory`, `ContactSensorAccessory`, `LeakSensorAccessory` reduce about 50% code size. Now writing a accessory class is much more simple.
- Legacy accessory codes moved to `src/accessory/legacy/` folder.
- [Light] Add `debounce` and command send queue, more stable during frequent operations on different characteristics.
- [Light] Fix wrong color temperature map. (https://github.com/tuya/tuya-homebridge/issues/136 by @XiaoTonyLuo and https://github.com/tuya/tuya-homebridge/pull/135 by @levidhuyvetter)
- [LeakSensor] Add CO Detector support (`cobj`).

### Known issue
- `LightAccessory` may not work properly, espasially on work mode change. need more test and feedbacks.
Expand Down
2 changes: 1 addition & 1 deletion SUPPORTED_DEVICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ Most category code is pinyin abbreviation of Chinese name.
| Pressure Sensor | 压力传感器 | ylcg | | |
| Emergency Button | 紧急按钮 | sos | | |
| PM2.5 Detector | PM2.5传感器 | pm25 | | |
| CO Detector | CO报警传感器 | cobj | | |
| CO Detector | CO报警传感器 | cobj | Leak Sensor | |
| CO2 Detector | CO2报警传感器 | co2bj | | |
| Multi-functional Sensor | 多功能传感器 | dgnbj | | |
| Methane Detector | 甲烷报警传感器 | jwbj | Leak Sensor ||
Expand Down
7 changes: 5 additions & 2 deletions src/accessory/AccessoryFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import BaseAccessory from './BaseAccessory';
import LightAccessory from './LightAccessory';
import OutletAccessory from './OutletAccessory';
import SwitchAccessory from './SwitchAccessory';
import ContactSensorAccessory from './ContactSensorAccessory';
import LeakSensorAccessory from './LeakSensorAccessory';

import LegacyAccessoryFactory from './LegacyAccessoryFactory';

Expand Down Expand Up @@ -54,11 +56,12 @@ export default class AccessoryFactory {
// TODO WindowCoveringAccessory
break;
case 'mcs':
// TODO ContactSensorAccessory
handler = new ContactSensorAccessory(platform, accessory);
break;
case 'rqbj':
case 'cobj':
case 'jwbj':
// TODO LeakSensorAccessory
handler = new LeakSensorAccessory(platform, accessory);
break;
}

Expand Down
33 changes: 33 additions & 0 deletions src/accessory/ContactSensorAccessory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { PlatformAccessory } from 'homebridge';
import { TuyaPlatform } from '../platform';
import BaseAccessory from './BaseAccessory';

export default class ContaceSensor extends BaseAccessory {

constructor(platform: TuyaPlatform, accessory: PlatformAccessory) {
super(platform, accessory);

const service = this.accessory.getService(this.Service.ContactSensor)
|| this.accessory.addService(this.Service.ContactSensor);

service.getCharacteristic(this.Characteristic.ContactSensorState)
.onGet(() => {
const status = this.device.getDeviceStatus('doorcontact_state');
return status!.value ?
this.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED:
this.Characteristic.ContactSensorState.CONTACT_DETECTED;
});

if (this.device.getDeviceStatus('battery_percentage')) {
service.getCharacteristic(this.Characteristic.StatusLowBattery)
.onGet(() => {
const status = this.device.getDeviceStatus('battery_percentage');
return (status && status!.value <= 20) ?
this.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW :
this.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
});
}

}

}
42 changes: 42 additions & 0 deletions src/accessory/LeakSensorAccessory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { PlatformAccessory } from 'homebridge';
import { TuyaPlatform } from '../platform';
import BaseAccessory from './BaseAccessory';

export default class LeakSensor extends BaseAccessory {

constructor(platform: TuyaPlatform, accessory: PlatformAccessory) {
super(platform, accessory);

const service = this.accessory.getService(this.Service.LeakSensor)
|| this.accessory.addService(this.Service.LeakSensor);

service.getCharacteristic(this.Characteristic.LeakDetected)
.onGet(() => {
const gas = this.device.getDeviceStatus('gas_sensor_status')
|| this.device.getDeviceStatus('gas_sensor_state');
const ch4 = this.device.getDeviceStatus('ch4_sensor_state');
const co = this.device.getDeviceStatus('co_status')
|| this.device.getDeviceStatus('co_state');

if ((gas && (gas.value === 'alarm' || gas.value === '1'))
|| (ch4 && ch4.value === 'alarm')
|| (co && (co.value === 'alarm' || co.value === '1'))) {
return this.Characteristic.LeakDetected.LEAK_DETECTED;
} else {
return this.Characteristic.LeakDetected.LEAK_NOT_DETECTED;
}
});

if (this.device.getDeviceStatus('battery_percentage')) {
service.getCharacteristic(this.Characteristic.StatusLowBattery)
.onGet(() => {
const status = this.device.getDeviceStatus('battery_percentage');
return (status && status!.value <= 20) ?
this.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW :
this.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
});
}

}

}
9 changes: 0 additions & 9 deletions src/accessory/LegacyAccessoryFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import SmokeSensorAccessory from './legacy/smokesensor_accessory';
import HeaterAccessory from './legacy/heater_accessory';
import GarageDoorAccessory from './legacy/garagedoor_accessory';
import WindowCoveringAccessory from './legacy/window_covering_accessory';
import ContactSensorAccessory from './legacy/contactsensor_accessory';
import LeakSensorAccessory from './legacy/leak_sensor_accessory';

class LegacyAccessoryWrapper {

Expand Down Expand Up @@ -61,13 +59,6 @@ export default class LegacyAccessoryFactory {
case 'cl':
handler = new WindowCoveringAccessory(platform, accessory, device);
break;
case 'mcs':
handler = new ContactSensorAccessory(platform, accessory, device);
break;
case 'rqbj':
case 'jwbj':
handler = new LeakSensorAccessory(platform, accessory, device);
break;
}

if (handler) {
Expand Down
7 changes: 6 additions & 1 deletion src/device/TuyaDeviceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ export default class TuyaDeviceManager extends EventEmitter {
const device = new TuyaDevice(res.result);

res = await this.getDeviceFunctions(deviceID);
device.functions = res.success ? res.result['functions'] : [];
if (res.success) {
device.functions = res.result['functions'];
} else {
this.log.warn(`Get device functions failed. code=${res.code}, msg=${res.msg}`);
device.functions = [];
}

const oldDevice = this.getDevice(deviceID);
if (oldDevice) {
Expand Down

0 comments on commit e39a736

Please sign in to comment.