diff --git a/.homeycompose/flow/actions/send_command_boolean.json b/.homeycompose/flow/actions/send_command_boolean.json index 4f4d8f08..6c93d45c 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 6ef6e0cf..6d40296c 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 2bb55b1e..3387a426 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 f812febb..657709d9 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 dcb3a68d..56f959d5 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 462219ef..fe1219fd 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 d578786b..6963729d 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 5f5b3701..367e9d71 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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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 753e9fdc..2cad655e 100644 --- a/app.json +++ b/app.json @@ -438,7 +438,7 @@ "name": "device", "type": "device", "filter": { - "driver_id": "button|camera|circuit_breaker|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|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|dehumidifier|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": "button|camera|circuit_breaker|dehumidifier|dimmer|doorbell|fan|garage_door|heater|humidifier|irrigator|light|other|sensor_climate|sensor_co2|sensor_contact|sensor_human|sensor_motion|sensor_smoke|siren|socket|thermostat|window_coverings" }, "title": { "en": "Device" @@ -2616,6 +2616,127 @@ } ] }, + { + "id": "humidifier_onoff.spray_true", + "title": { + "en": "Turn spray on" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=onoff.spray" + } + ] + }, + { + "id": "humidifier_onoff.spray_false", + "title": { + "en": "Turn spray off" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=onoff.spray" + } + ] + }, + { + "id": "humidifier_onoff.light_true", + "title": { + "en": "Turn light on" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=onoff.light" + } + ] + }, + { + "id": "humidifier_onoff.light_false", + "title": { + "en": "Turn light off" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=onoff.light" + } + ] + }, + { + "id": "humidifier_night_mode", + "title": { + "en": "Set night mode" + }, + "titleFormatted": { + "en": "Set night mode to [[value]]" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=night_mode" + }, + { + "name": "value", + "type": "checkbox", + "title": { + "en": "Value" + } + } + ] + }, + { + "id": "humidifier_enum.spray_mode", + "title": { + "en": "Set spray mode" + }, + "titleFormatted": { + "en": "Set spray mode to [[value]]" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=enum.spray_mode" + }, + { + "name": "value", + "type": "autocomplete", + "title": { + "en": "Value" + } + } + ] + }, + { + "id": "humidifier_enum.spray_level", + "title": { + "en": "Set spray level" + }, + "titleFormatted": { + "en": "Set spray level to [[value]]" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=enum.spraylevel" + }, + { + "name": "value", + "type": "autocomplete", + "title": { + "en": "Value" + } + } + ] + }, { "id": "infrared_remote_press", "title": { @@ -3256,6 +3377,32 @@ } ] }, + { + "id": "humidifier_onoff.spray_is_true", + "title": { + "en": "Spray is !{{on|off}}" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=onoff.spray" + } + ] + }, + { + "id": "humidifier_onoff.light_is_true", + "title": { + "en": "Light is !{{on|off}}" + }, + "args": [ + { + "type": "device", + "name": "device", + "filter": "driver_id=humidifier&capabilities=onoff.light" + } + ] + }, { "id": "irrigator_rain_sensor_is_true", "title": { @@ -5057,6 +5204,190 @@ } ] }, + { + "capabilities": [ + "onoff", + "measure_humidity", + "target_humidity" + ], + "connectivity": [ + "cloud" + ], + "platforms": [ + "local", + "cloud" + ], + "images": { + "small": "/drivers/humidifier/assets/images/small.png", + "large": "/drivers/humidifier/assets/images/large.png", + "xlarge": "/drivers/humidifier/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": "humidifier", + "name": { + "en": "Humidifier", + "nl": "Luchtbevochtiger" + }, + "capabilitiesOptions": { + "onoff.spray": { + "title": { + "en": "Spray" + } + }, + "onoff.light": { + "title": { + "en": "Light" + } + }, + "enum.fog_mode": { + "title": { + "en": "Fog Mode" + }, + "values": [ + { + "id": "large", + "title": "Large" + }, + { + "id": "middle", + "title": "Middle" + }, + { + "id": "small", + "title": "Small" + }, + { + "id": "interval", + "title": "Interval" + }, + { + "id": "continuous", + "title": "Continuous" + } + ] + }, + "enum.spray_mode": { + "title": { + "en": "Spray Mode" + }, + "values": [ + { + "id": "auto", + "title": "Auto" + }, + { + "id": "health", + "title": "Health" + }, + { + "id": "baby", + "title": "Baby" + }, + { + "id": "sleep", + "title": "Sleep" + }, + { + "id": "humidity", + "title": "Humidity" + }, + { + "id": "work", + "title": "Work" + } + ] + }, + "enum.spray_level": { + "title": { + "en": "Spray Level" + }, + "values": [ + { + "id": "level_1", + "title": "1" + }, + { + "id": "level_2", + "title": "2" + }, + { + "id": "level_3", + "title": "3" + }, + { + "id": "level_4", + "title": "4" + }, + { + "id": "level_5", + "title": "5" + }, + { + "id": "level_6", + "title": "6" + }, + { + "id": "level_7", + "title": "7" + }, + { + "id": "level_8", + "title": "8" + }, + { + "id": "level_9", + "title": "9" + }, + { + "id": "level_10", + "title": "10" + } + ] + } + }, + "id": "humidifier", + "settings": [ + { + "id": "deviceSpecification", + "type": "label", + "label": { + "en": "Device Specification" + }, + "hint": { + "en": "The Tuya specification of this device" + }, + "value": "" + } + ] + }, { "capabilities": [ "on_button", diff --git a/drivers/humidifier/TuyaHumidifierConstants.ts b/drivers/humidifier/TuyaHumidifierConstants.ts new file mode 100644 index 00000000..e5bdbc57 --- /dev/null +++ b/drivers/humidifier/TuyaHumidifierConstants.ts @@ -0,0 +1,24 @@ +export const HUMIDIFIER_CAPABILITY_MAPPING = { + switch: 'onoff', + switch_spray: 'onoff.spray', + temp_set: 'target_temperature', + humidity_set: 'target_humidity', + sleep: 'night_mode', + temp_current: 'measure_temperature', + humidity_current: 'measure_humidity', + mode: 'enum.fog_mode', + spray_mode: 'enum.spray_mode', + level: 'enum.spray_level', + level_current: 'measure_content_volume', +} as const; + +export const HUMIDIFIER_CAPABILITIES = { + read_write: ['switch', 'switch_spray', 'mode', 'spray_mode', 'level', 'temp_set', 'humidity_set', 'sleep'], + read_only: ['temp_current', 'humidity_current', 'level_current'], +} as const; + +export const HUMIDIFIER_FLOWS = { + onoff: ['onoff.spray'], + boolean: ['night_mode'], + enum: ['enum.spray_mode', 'enum.spray_level'], +} as const; diff --git a/drivers/humidifier/assets/icon.svg b/drivers/humidifier/assets/icon.svg new file mode 100644 index 00000000..ab61ab30 --- /dev/null +++ b/drivers/humidifier/assets/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/drivers/humidifier/assets/images/large.png b/drivers/humidifier/assets/images/large.png new file mode 100644 index 00000000..9adf7510 Binary files /dev/null and b/drivers/humidifier/assets/images/large.png differ diff --git a/drivers/humidifier/assets/images/small.png b/drivers/humidifier/assets/images/small.png new file mode 100644 index 00000000..52ae995f Binary files /dev/null and b/drivers/humidifier/assets/images/small.png differ diff --git a/drivers/humidifier/assets/images/xlarge.png b/drivers/humidifier/assets/images/xlarge.png new file mode 100644 index 00000000..dfd5159d Binary files /dev/null and b/drivers/humidifier/assets/images/xlarge.png differ diff --git a/drivers/humidifier/device.ts b/drivers/humidifier/device.ts new file mode 100644 index 00000000..564369c8 --- /dev/null +++ b/drivers/humidifier/device.ts @@ -0,0 +1,38 @@ +import TuyaOAuth2Device from '../../lib/TuyaOAuth2Device'; +import { TuyaStatus } from '../../types/TuyaTypes'; +import { HUMIDIFIER_CAPABILITIES, HUMIDIFIER_CAPABILITY_MAPPING } from './TuyaHumidifierConstants'; +import { constIncludes, getFromMap } from '../../lib/TuyaOAuth2Util'; + +module.exports = class TuyaOAuth2DeviceHumidifier extends TuyaOAuth2Device { + async onOAuth2Init(): Promise { + await super.onOAuth2Init(); + + for (const tuyaCapability of HUMIDIFIER_CAPABILITIES.read_write) { + const homeyCapability = getFromMap(HUMIDIFIER_CAPABILITY_MAPPING, tuyaCapability); + if (homeyCapability && this.hasCapability(homeyCapability)) { + this.registerCapabilityListener(homeyCapability, value => + this.sendCommand({ + code: tuyaCapability, + value: value, + }), + ); + } + } + } + + async onTuyaStatus(status: TuyaStatus, changed: string[]): Promise { + await super.onTuyaStatus(status, changed); + + for (const tuyaCapability in status) { + const value = status[tuyaCapability]; + const homeyCapability = getFromMap(HUMIDIFIER_CAPABILITY_MAPPING, tuyaCapability); + + if ( + constIncludes(HUMIDIFIER_CAPABILITIES.read_write, tuyaCapability) || + constIncludes(HUMIDIFIER_CAPABILITIES.read_only, tuyaCapability) + ) { + await this.safeSetCapabilityValue(homeyCapability, value); + } + } + } +}; diff --git a/drivers/humidifier/driver.compose.json b/drivers/humidifier/driver.compose.json new file mode 100644 index 00000000..130ee027 --- /dev/null +++ b/drivers/humidifier/driver.compose.json @@ -0,0 +1,126 @@ +{ + "$extends": "tuya", + "class": "humidifier", + "name": { + "en": "Humidifier", + "nl": "Luchtbevochtiger" + }, + "capabilities": ["onoff", "measure_humidity", "target_humidity"], + "capabilitiesOptions": { + "onoff.spray": { + "title": { + "en": "Spray" + } + }, + "onoff.light": { + "title": { + "en": "Light" + } + }, + "enum.fog_mode": { + "title": { + "en": "Fog Mode" + }, + "values": [ + { + "id": "large", + "title": "Large" + }, + { + "id": "middle", + "title": "Middle" + }, + { + "id": "small", + "title": "Small" + }, + { + "id": "interval", + "title": "Interval" + }, + { + "id": "continuous", + "title": "Continuous" + } + ] + }, + "enum.spray_mode": { + "title": { + "en": "Spray Mode" + }, + "values": [ + { + "id": "auto", + "title": "Auto" + }, + { + "id": "health", + "title": "Health" + }, + { + "id": "baby", + "title": "Baby" + }, + { + "id": "sleep", + "title": "Sleep" + }, + { + "id": "humidity", + "title": "Humidity" + }, + { + "id": "work", + "title": "Work" + } + ] + }, + "enum.spray_level": { + "title": { + "en": "Spray Level" + }, + "values": [ + { + "id": "level_1", + "title": "1" + }, + { + "id": "level_2", + "title": "2" + }, + { + "id": "level_3", + "title": "3" + }, + { + "id": "level_4", + "title": "4" + }, + { + "id": "level_5", + "title": "5" + }, + { + "id": "level_6", + "title": "6" + }, + { + "id": "level_7", + "title": "7" + }, + { + "id": "level_8", + "title": "8" + }, + { + "id": "level_9", + "title": "9" + }, + { + "id": "level_10", + "title": "10" + } + ] + } + } +} diff --git a/drivers/humidifier/driver.flow.compose.json b/drivers/humidifier/driver.flow.compose.json new file mode 100644 index 00000000..fd646153 --- /dev/null +++ b/drivers/humidifier/driver.flow.compose.json @@ -0,0 +1,100 @@ +{ + "actions": [ + { + "id": "humidifier_onoff.spray_true", + "$filter": "capabilities=onoff.spray", + "title": { + "en": "Turn spray on" + } + }, + { + "id": "humidifier_onoff.spray_false", + "$filter": "capabilities=onoff.spray", + "title": { + "en": "Turn spray off" + } + }, + { + "id": "humidifier_onoff.light_true", + "$filter": "capabilities=onoff.light", + "title": { + "en": "Turn light on" + } + }, + { + "id": "humidifier_onoff.light_false", + "$filter": "capabilities=onoff.light", + "title": { + "en": "Turn light off" + } + }, + { + "id": "humidifier_night_mode", + "$filter": "capabilities=night_mode", + "title": { + "en": "Set night mode" + }, + "titleFormatted": { + "en": "Set night mode to [[value]]" + }, + "args": [ + { + "name": "value", + "type": "checkbox", + "title": { "en": "Value" } + } + ] + }, + { + "id": "humidifier_enum.spray_mode", + "$filter": "capabilities=enum.spray_mode", + "title": { + "en": "Set spray mode" + }, + "titleFormatted": { + "en": "Set spray mode to [[value]]" + }, + "args": [ + { + "name": "value", + "type": "autocomplete", + "title": { "en": "Value" } + } + ] + }, + { + "id": "humidifier_enum.spray_level", + "$filter": "capabilities=enum.spraylevel", + "title": { + "en": "Set spray level" + }, + "titleFormatted": { + "en": "Set spray level to [[value]]" + }, + "args": [ + { + "name": "value", + "type": "autocomplete", + "title": { "en": "Value" } + } + ] + } + ], + "conditions": [ + { + "id": "humidifier_onoff.spray_is_true", + "$filter": "capabilities=onoff.spray", + "title": { + "en": "Spray is !{{on|off}}" + } + }, + { + "id": "humidifier_onoff.light_is_true", + "$filter": "capabilities=onoff.light", + "title": { + "en": "Light is !{{on|off}}" + } + } + ], + "triggers": [] +} diff --git a/drivers/humidifier/driver.settings.compose.json b/drivers/humidifier/driver.settings.compose.json new file mode 100644 index 00000000..dceebc0d --- /dev/null +++ b/drivers/humidifier/driver.settings.compose.json @@ -0,0 +1,5 @@ +[ + { + "$extends": "deviceSpecification" + } +] diff --git a/drivers/humidifier/driver.ts b/drivers/humidifier/driver.ts new file mode 100644 index 00000000..6d11269c --- /dev/null +++ b/drivers/humidifier/driver.ts @@ -0,0 +1,100 @@ +import { DEVICE_CATEGORIES } from '../../lib/TuyaOAuth2Constants'; +import TuyaOAuth2Driver, { ListDeviceProperties } from '../../lib/TuyaOAuth2Driver'; +import { + type TuyaDeviceDataPointResponse, + TuyaDeviceResponse, + TuyaDeviceSpecificationResponse, +} from '../../types/TuyaApiTypes'; +import { getFromMap } from '../../lib/TuyaOAuth2Util'; +import { HUMIDIFIER_CAPABILITY_MAPPING, HUMIDIFIER_FLOWS } from './TuyaHumidifierConstants'; +import driver_compose from './driver.compose.json'; +import { StandardDeviceFlowArgs, StandardFlowArgs } from '../../types/TuyaTypes'; + +module.exports = class TuyaOAuth2DriverHumidifier extends TuyaOAuth2Driver { + TUYA_DEVICE_CATEGORIES = [DEVICE_CATEGORIES.SMALL_HOME_APPLIANCES.HUMIDIFIER] as const; + + async onInit(): Promise { + await super.onInit(); + + // onoff + for (const homeyCapability of HUMIDIFIER_FLOWS.onoff) { + this.homey.flow + .getActionCard(`humidifier_${homeyCapability}_true`) + .registerRunListener((args: StandardDeviceFlowArgs) => + args.device.triggerCapabilityListener(homeyCapability, true), + ); + this.homey.flow + .getActionCard(`humidifier_${homeyCapability}_false`) + .registerRunListener((args: StandardDeviceFlowArgs) => + args.device.triggerCapabilityListener(homeyCapability, false), + ); + this.homey.flow + .getConditionCard(`humidifier_${homeyCapability}_is_true`) + .registerRunListener((args: StandardDeviceFlowArgs) => args.device.getCapabilityValue(homeyCapability)); + } + + // boolean + for (const homeyCapability of HUMIDIFIER_FLOWS.boolean) { + this.homey.flow + .getActionCard(`humidifier_${homeyCapability}`) + .registerRunListener((args: StandardFlowArgs) => + args.device.triggerCapabilityListener(homeyCapability, args.value), + ); + } + + // enum + for (const homeyCapability of HUMIDIFIER_FLOWS.enum) { + this.addEnumActionFlowHandler(homeyCapability, `humidifier_${homeyCapability}`); + } + } + + 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(HUMIDIFIER_CAPABILITY_MAPPING, tuyaCapability); + + if (homeyCapability) { + props.store.tuya_capabilities.push(tuyaCapability); + props.capabilities.push(homeyCapability); + } + } + + // Defaults enum values + props.capabilitiesOptions = { ...props.capabilitiesOptions, ...driver_compose.capabilitiesOptions }; + + if (!specifications || !specifications.status) { + return props; + } + + for (const statusSpecification of specifications.status) { + const tuyaCapability = statusSpecification.code; + const values = JSON.parse(statusSpecification.values); + const homeyCapability = getFromMap(HUMIDIFIER_CAPABILITY_MAPPING, tuyaCapability); + + if ( + ['mode', 'spray_mode', 'level'].includes(tuyaCapability) && + homeyCapability && + Array.isArray(values.range) && + values.range.length > 0 + ) { + props.capabilitiesOptions[homeyCapability] = { + values: values.range.map((value: string) => { + const title = value.charAt(0).toUpperCase() + value.slice(1); + return { + id: value, + title: title, + }; + }), + }; + } + } + + return props; + } +}; diff --git a/drivers/humidifier/pair/welcome.assets/chevron-right.png b/drivers/humidifier/pair/welcome.assets/chevron-right.png new file mode 100644 index 00000000..d7331b23 Binary files /dev/null and b/drivers/humidifier/pair/welcome.assets/chevron-right.png differ diff --git a/drivers/humidifier/pair/welcome.assets/logos.png b/drivers/humidifier/pair/welcome.assets/logos.png new file mode 100644 index 00000000..faefa496 Binary files /dev/null and b/drivers/humidifier/pair/welcome.assets/logos.png differ diff --git a/drivers/humidifier/pair/welcome.html b/drivers/humidifier/pair/welcome.html new file mode 100644 index 00000000..14a7e06e --- /dev/null +++ b/drivers/humidifier/pair/welcome.html @@ -0,0 +1,60 @@ + + +

+ +

+ +

+ +

+ + + + +

+ +

+ +