diff --git a/.homeycompose/flow/actions/send_command_boolean.json b/.homeycompose/flow/actions/send_command_boolean.json index 2f17f9f6..ee4989ac 100644 --- a/.homeycompose/flow/actions/send_command_boolean.json +++ b/.homeycompose/flow/actions/send_command_boolean.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/actions/send_command_json.json b/.homeycompose/flow/actions/send_command_json.json index 02788c80..ae9c1dde 100644 --- a/.homeycompose/flow/actions/send_command_json.json +++ b/.homeycompose/flow/actions/send_command_json.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/actions/send_command_number.json b/.homeycompose/flow/actions/send_command_number.json index 1384993d..377c0b6b 100644 --- a/.homeycompose/flow/actions/send_command_number.json +++ b/.homeycompose/flow/actions/send_command_number.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/actions/send_command_string.json b/.homeycompose/flow/actions/send_command_string.json index 67d35084..e82d667d 100644 --- a/.homeycompose/flow/actions/send_command_string.json +++ b/.homeycompose/flow/actions/send_command_string.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/triggers/receive_status_boolean.json b/.homeycompose/flow/triggers/receive_status_boolean.json index 330accc9..eb410170 100644 --- a/.homeycompose/flow/triggers/receive_status_boolean.json +++ b/.homeycompose/flow/triggers/receive_status_boolean.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/triggers/receive_status_json.json b/.homeycompose/flow/triggers/receive_status_json.json index 5336552c..3fecaaff 100644 --- a/.homeycompose/flow/triggers/receive_status_json.json +++ b/.homeycompose/flow/triggers/receive_status_json.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/triggers/receive_status_number.json b/.homeycompose/flow/triggers/receive_status_number.json index 95bd861b..264f975f 100644 --- a/.homeycompose/flow/triggers/receive_status_number.json +++ b/.homeycompose/flow/triggers/receive_status_number.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/.homeycompose/flow/triggers/receive_status_string.json b/.homeycompose/flow/triggers/receive_status_string.json index 9b035bcc..3cc71b37 100644 --- a/.homeycompose/flow/triggers/receive_status_string.json +++ b/.homeycompose/flow/triggers/receive_status_string.json @@ -13,7 +13,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" diff --git a/app.json b/app.json index 2d853a39..7a41ddbb 100644 --- a/app.json +++ b/app.json @@ -438,7 +438,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -479,7 +479,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -520,7 +520,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -561,7 +561,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -1349,7 +1349,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -1387,7 +1387,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -1425,7 +1425,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -1463,7 +1463,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" + "driver_id": "airco|button|camera|circuit_breaker|dimmer|doorbell|fan|garage_door|heater|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -1708,6 +1708,29 @@ ], "id": "trigger_scene" }, + { + "id": "airco_set_child_lock", + "title": { + "en": "Set child lock" + }, + "titleFormatted": { + "en": "Set child lock [[value]]" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=airco&capabilities=child_lock" + }, + { + "name": "value", + "type": "checkbox", + "title": { + "en": "Value" + } + } + ] + }, { "id": "camera_cruise_switch", "title": { @@ -3182,6 +3205,221 @@ ] }, "drivers": [ + { + "capabilities": [ + "onoff", + "target_temperature", + "measure_temperature" + ], + "connectivity": [ + "cloud" + ], + "platforms": [ + "local", + "cloud" + ], + "images": { + "small": "/drivers/airco/assets/images/small.png", + "large": "/drivers/airco/assets/images/large.png", + "xlarge": "/drivers/airco/assets/images/xlarge.png" + }, + "pair": [ + { + "id": "welcome", + "navigation": { + "next": "login_oauth2" + } + }, + { + "id": "login_oauth2", + "template": "login_oauth2" + }, + { + "id": "list_devices", + "template": "list_devices", + "navigation": { + "next": "add_devices" + } + }, + { + "id": "add_devices", + "template": "add_devices" + } + ], + "repair": [ + { + "id": "login_oauth2", + "template": "login_oauth2" + } + ], + "class": "airconditioning", + "name": { + "en": "Air Conditioning", + "nl": "Airconditioning" + }, + "id": "airco", + "settings": [ + { + "id": "deviceSpecification", + "type": "label", + "label": { + "en": "Device Specification" + }, + "hint": { + "en": "The Tuya specification of this device" + }, + "value": "" + }, + { + "id": "temp_set_scaling", + "type": "dropdown", + "label": { + "en": "Target Temperature Scale" + }, + "hint": { + "en": "By how much the temperature targeted by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + }, + { + "id": "temp_current_scaling", + "type": "dropdown", + "label": { + "en": "Measured Temperature Scale" + }, + "hint": { + "en": "By how much the temperature measured by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + }, + { + "id": "humidity_set_scaling", + "type": "dropdown", + "label": { + "en": "Target Humidity Scale" + }, + "hint": { + "en": "By how much the humidity targeted by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + }, + { + "id": "humidity_current_scaling", + "type": "dropdown", + "label": { + "en": "Measured Humidity Scale" + }, + "hint": { + "en": "By how much the humidity measured by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + } + ] + }, { "capabilities": [ "measure_battery" diff --git a/drivers/airco/TuyaAircoConstants.ts b/drivers/airco/TuyaAircoConstants.ts new file mode 100644 index 00000000..91e64282 --- /dev/null +++ b/drivers/airco/TuyaAircoConstants.ts @@ -0,0 +1,15 @@ +export const AIRCO_CAPABILITIES_MAPPING = { + switch: 'onoff', + temp_set: 'target_temperature', + temp_current: 'measure_temperature', + humidity_set: 'target_humidity', + humidity_current: 'measure_humidity', + lock: 'child_lock', +} as const; + +export type HomeySocketSettings = { + temp_set_scaling: '0' | '1' | '2' | '3'; + temp_current_scaling: '0' | '1' | '2' | '3'; + humidity_set_scaling: '0' | '1' | '2' | '3'; + humidity_current_scaling: '0' | '1' | '2' | '3'; +}; diff --git a/drivers/airco/assets/icon.svg b/drivers/airco/assets/icon.svg new file mode 100644 index 00000000..fe205c11 --- /dev/null +++ b/drivers/airco/assets/icon.svg @@ -0,0 +1 @@ + diff --git a/drivers/airco/assets/images/large.png b/drivers/airco/assets/images/large.png new file mode 100644 index 00000000..a59b42a1 Binary files /dev/null and b/drivers/airco/assets/images/large.png differ diff --git a/drivers/airco/assets/images/small.png b/drivers/airco/assets/images/small.png new file mode 100644 index 00000000..971a7449 Binary files /dev/null and b/drivers/airco/assets/images/small.png differ diff --git a/drivers/airco/assets/images/xlarge.png b/drivers/airco/assets/images/xlarge.png new file mode 100644 index 00000000..c49bfa99 Binary files /dev/null and b/drivers/airco/assets/images/xlarge.png differ diff --git a/drivers/airco/device.ts b/drivers/airco/device.ts new file mode 100644 index 00000000..ee4e4065 --- /dev/null +++ b/drivers/airco/device.ts @@ -0,0 +1,86 @@ +import TuyaOAuth2Device from '../../lib/TuyaOAuth2Device'; +import { TuyaStatus } from '../../types/TuyaTypes'; + +module.exports = class TuyaOAuth2DeviceAirco extends TuyaOAuth2Device { + async onOAuth2Init(): Promise { + await super.onOAuth2Init(); + + if (this.hasCapability('onoff')) { + this.registerCapabilityListener('onoff', value => this.onOffCapabilityListener(value)); + } + + if (this.hasCapability('target_temperature')) { + this.registerCapabilityListener('target_temperature', value => this.targetTemperatureCapabilityListener(value)); + } + + if (this.hasCapability('target_humidity')) { + this.registerCapabilityListener('target_humidity', value => this.targetHumidityCapabilityListener(value)); + } + + if (this.hasCapability('child_lock')) { + this.registerCapabilityListener('child_lock', value => this.childLockCapabilityListener(value)); + } + } + + async onTuyaStatus(status: TuyaStatus, changedStatusCodes: string[]): Promise { + await super.onTuyaStatus(status, changedStatusCodes); + + if (typeof status['switch'] === 'boolean') { + this.setCapabilityValue('onoff', status['switch']).catch(this.error); + } + + if (typeof status['temp_current'] === 'number') { + const scaling = 10.0 ** Number.parseInt(this.getSetting('temp_current_scaling') ?? '0', 10); + this.setCapabilityValue('measure_temperature', status['temp_current'] / scaling).catch(this.error); + } + + if (typeof status['temp_set'] === 'number') { + const scaling = 10.0 ** Number.parseInt(this.getSetting('temp_set_scaling') ?? '0', 10); + this.setCapabilityValue('target_temperature', status['temp_set'] / scaling).catch(this.error); + } + + if (typeof status['humidity_current'] === 'number') { + const scaling = 10.0 ** Number.parseInt(this.getSetting('temp_current_scaling') ?? '0', 10); + this.setCapabilityValue('measure_humidity', status['humidity_current'] / scaling).catch(this.error); + } + + if (typeof status['humidity_set'] === 'number') { + const scaling = 10.0 ** Number.parseInt(this.getSetting('temp_set_scaling') ?? '0', 10); + this.setCapabilityValue('target_humidity', status['humidity_set'] / scaling).catch(this.error); + } + + if (typeof status['lock'] === 'boolean') { + this.setCapabilityValue('child_lock', status['lock']).catch(this.error); + } + } + + async onOffCapabilityListener(value: boolean): Promise { + await this.sendCommand({ + code: 'switch', + value: value, + }); + } + + async targetTemperatureCapabilityListener(value: number): Promise { + const scaling = 10.0 ** Number.parseInt(this.getSetting('temp_set_scaling') ?? '0', 10); + await this.sendCommand({ + code: 'temp_set', + value: value * scaling, + }); + } + + async targetHumidityCapabilityListener(value: number): Promise { + const scaling = 10.0 ** Number.parseInt(this.getSetting('humidity_set_scaling') ?? '0', 10); + await this.sendCommand({ + code: 'humidity_set', + value: value * scaling, + }); + } + + async childLockCapabilityListener(value: boolean): Promise { + await this.sendCommand({ + code: 'lock', + value: value, + }); + } +}; diff --git a/drivers/airco/driver.compose.json b/drivers/airco/driver.compose.json new file mode 100644 index 00000000..f9632cc9 --- /dev/null +++ b/drivers/airco/driver.compose.json @@ -0,0 +1,9 @@ +{ + "$extends": "tuya", + "class": "airconditioning", + "name": { + "en": "Air Conditioning", + "nl": "Airconditioning" + }, + "capabilities": ["onoff", "target_temperature", "measure_temperature"] +} diff --git a/drivers/airco/driver.flow.compose.json b/drivers/airco/driver.flow.compose.json new file mode 100644 index 00000000..aca8e586 --- /dev/null +++ b/drivers/airco/driver.flow.compose.json @@ -0,0 +1,23 @@ +{ + "actions": [ + { + "id": "airco_set_child_lock", + "$filter": "capabilities=child_lock", + "title": { + "en": "Set child lock" + }, + "titleFormatted": { + "en": "Set child lock [[value]]" + }, + "args": [ + { + "name": "value", + "type": "checkbox", + "title": { "en": "Value" } + } + ] + } + ], + "conditions": [], + "triggers": [] +} diff --git a/drivers/airco/driver.settings.compose.json b/drivers/airco/driver.settings.compose.json new file mode 100644 index 00000000..5b7b96e2 --- /dev/null +++ b/drivers/airco/driver.settings.compose.json @@ -0,0 +1,154 @@ +[ + { + "$extends": "deviceSpecification" + }, + { + "id": "temp_set_scaling", + "type": "dropdown", + "label": { + "en": "Target Temperature Scale" + }, + "hint": { + "en": "By how much the temperature targeted by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + }, + { + "id": "temp_current_scaling", + "type": "dropdown", + "label": { + "en": "Measured Temperature Scale" + }, + "hint": { + "en": "By how much the temperature measured by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + }, + + { + "id": "humidity_set_scaling", + "type": "dropdown", + "label": { + "en": "Target Humidity Scale" + }, + "hint": { + "en": "By how much the humidity targeted by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + }, + { + "id": "humidity_current_scaling", + "type": "dropdown", + "label": { + "en": "Measured Humidity Scale" + }, + "hint": { + "en": "By how much the humidity measured by the device is scaled." + }, + "value": "0", + "values": [ + { + "id": "0", + "label": { + "en": "1" + } + }, + { + "id": "1", + "label": { + "en": "1/10" + } + }, + { + "id": "2", + "label": { + "en": "1/100" + } + }, + { + "id": "3", + "label": { + "en": "1/1000" + } + } + ] + } +] diff --git a/drivers/airco/driver.ts b/drivers/airco/driver.ts new file mode 100644 index 00000000..eafd6fc9 --- /dev/null +++ b/drivers/airco/driver.ts @@ -0,0 +1,83 @@ +import { DEVICE_CATEGORIES } from '../../lib/TuyaOAuth2Constants'; +import type TuyaOAuth2Device from '../../lib/TuyaOAuth2Device'; +import TuyaOAuth2Driver, { ListDeviceProperties } from '../../lib/TuyaOAuth2Driver'; +import { getFromMap } from '../../lib/TuyaOAuth2Util'; +import { + type TuyaDeviceDataPointResponse, + TuyaDeviceResponse, + TuyaDeviceSpecificationResponse, +} from '../../types/TuyaApiTypes'; +import { AIRCO_CAPABILITIES_MAPPING } from './TuyaAircoConstants'; + +type DeviceArgs = { device: TuyaOAuth2Device }; +type ValueArgs = { value: unknown }; + +module.exports = class TuyaOAuth2DriverAirco extends TuyaOAuth2Driver { + TUYA_DEVICE_CATEGORIES = [DEVICE_CATEGORIES.LARGE_HOME_APPLIANCES.AIR_CONDITIONER] as const; + + async onInit(): Promise { + await super.onInit(); + + this.homey.flow.getActionCard('heater_set_child_lock').registerRunListener(async (args: DeviceArgs & ValueArgs) => { + await args.device.triggerCapabilityListener('child_lock', args.value); + }); + } + + onTuyaPairListDeviceProperties( + device: TuyaDeviceResponse, + specifications?: TuyaDeviceSpecificationResponse, + dataPoints?: TuyaDeviceDataPointResponse, + ): ListDeviceProperties { + const props = super.onTuyaPairListDeviceProperties(device, specifications, dataPoints); + + for (const status of device.status) { + const tuyaCapability = status.code; + + const homeyCapability = getFromMap(AIRCO_CAPABILITIES_MAPPING, tuyaCapability); + if (homeyCapability) { + props.store.tuya_capabilities.push(tuyaCapability); + props.capabilities.push(homeyCapability); + } + } + + if (!specifications || !specifications.status) { + return props; + } + + for (const spec of specifications.status) { + const tuyaCapability = spec.code; + const values = JSON.parse(spec.values); + + if (tuyaCapability === 'temp_set') { + const scaleExp = values.scale ?? 0; + const scale = 10 ** scaleExp; + + props.capabilitiesOptions['target_temperature'] = { + step: values.step / scale, + min: values.min / scale, + max: values.max / scale, + }; + } + + if (tuyaCapability === 'humidity_set') { + const scaleExp = values.scale ?? 0; + const scale = 10 ** scaleExp; + + props.capabilitiesOptions['target_humidity'] = { + step: values.step / scale, + min: values.min / scale, + max: values.max / scale, + }; + } + + if (['temp_set', 'temp_current', 'humidity_set', 'humidity_current'].includes(tuyaCapability)) { + if ([0, 1, 2, 3].includes(values.scale)) { + props.settings[`${tuyaCapability}_scaling`] = `${values.scale}`; + } else { + this.error(`Unsupported ${tuyaCapability} scale:`, values.scale); + } + } + } + return props; + } +}; diff --git a/drivers/airco/pair/welcome.assets/chevron-right.png b/drivers/airco/pair/welcome.assets/chevron-right.png new file mode 100644 index 00000000..d7331b23 Binary files /dev/null and b/drivers/airco/pair/welcome.assets/chevron-right.png differ diff --git a/drivers/airco/pair/welcome.assets/logos.png b/drivers/airco/pair/welcome.assets/logos.png new file mode 100644 index 00000000..faefa496 Binary files /dev/null and b/drivers/airco/pair/welcome.assets/logos.png differ diff --git a/drivers/airco/pair/welcome.html b/drivers/airco/pair/welcome.html new file mode 100644 index 00000000..14a7e06e --- /dev/null +++ b/drivers/airco/pair/welcome.html @@ -0,0 +1,60 @@ + + +

+ +

+ +

+ +

+ + + + +

+ +

+ +