Skip to content

Commit 0bc0fdd

Browse files
authored
fix(sensors): handle 0 values for subsensors (xZetsubou#653)
* Handle 0 values for sub sensors * none as default value for getattr * add qccdz category related: 658
1 parent 89e02df commit 0bc0fdd

File tree

8 files changed

+251
-3
lines changed

8 files changed

+251
-3
lines changed

custom_components/localtuya/core/ha_entities/base.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ class DPCode(StrEnum):
117117
ALARM_MESSAGE = "alarm_message"
118118
ALARM_RINGTONE = "alarm_ringtone"
119119
ALARM_SETTING = "alarm_setting"
120+
ALARM_SET_1 = "alarm_set_1"
121+
ALARM_SET_2 = "alarm_set_2"
120122
ALARM_STATE = "alarm_state"
121123
ALARM_SWITCH = "alarm_switch" # Alarm switch
122124
ALARM_TIME = "alarm_time" # Alarm time
@@ -138,7 +140,10 @@ class DPCode(StrEnum):
138140
AUTOMATIC_LOCK = "automatic_lock"
139141
AUTO_CLEAN = "auto_clean"
140142
AUTO_LOCK_TIME = "auto_lock_time"
143+
A_CURRENT = "A_Current"
144+
A_VOLTAGE = "A_Voltage"
141145
BACKLIGHT_SWITCH = "backlight_switch"
146+
BALANCE_ENERGY = "balance_energy"
142147
BASIC_ANTI_FLICKER = "basic_anti_flicker"
143148
BASIC_DEVICE_VOLUME = "basic_device_volume"
144149
BASIC_FLIP = "basic_flip"
@@ -170,6 +175,8 @@ class DPCode(StrEnum):
170175
BRIGHT_VALUE_3 = "bright_value_3"
171176
BRIGHT_VALUE_4 = "bright_value_4"
172177
BRIGHT_VALUE_V2 = "bright_value_v2"
178+
B_CURRENT = "B_Current"
179+
B_VOLTAGE = "B_Voltage"
173180
CALLPHONE = "callphone"
174181
CARD_BALANCE = "card_balance"
175182
CAT_WEIGHT = "cat_weight"
@@ -180,11 +187,13 @@ class DPCode(StrEnum):
180187
CHARGE_CARD_NO1 = "charge_card_no1"
181188
CHARGE_CARD_NO2 = "charge_card_no2"
182189
CHARGE_ELECTRIC_QUANTITY = "charge_electric_quantity"
190+
CHARGE_ENERGY_ONCE = "charge_energy_once"
183191
CHARGE_MONEY = "charge_money"
184192
CHARGE_PATTERN = "charge_pattern"
185193
CHARGE_POWER1 = "charge_power1"
186194
CHARGE_POWER2 = "charge_power2"
187195
CHARGE_STATE = "charge_state"
196+
CHARGINGOPERATION = "ChargingOperation"
188197
CHARGING_STATE = "charging_state"
189198
CHILDLOCK = "childlock"
190199
CHILD_LOCK = "child_lock" # Child lock
@@ -244,6 +253,7 @@ class DPCode(StrEnum):
244253
CP = "cp"
245254
CRUISE_MODE = "cruise_mode"
246255
CRY_DETECTION_SWITCH = "cry_detection_switch"
256+
CTIME = "Ctime"
247257
CUP_NUMBER = "cup_number" # NUmber of cups
248258
CURRENT_A = "current_a"
249259
CURRENT_A_CALIBRATION = "current_a_calibration"
@@ -260,19 +270,29 @@ class DPCode(StrEnum):
260270
CUR_VOLTAGE = "cur_voltage" # Actual voltage
261271
CUR_VOLTAGE1 = "cur_voltage1"
262272
CUR_VOLTAGE2 = "cur_voltage2"
273+
C_CURRENT = "C_Current"
263274
C_F = "c_f" # Temperature unit switching
275+
C_VOLTAGE = "C_Voltage"
264276
DATA = "data"
265277
DATA_IDENTIFICATION = "data_identification"
266278
DATA_OVERFLOW = "data_overflow"
267279
DAY_ENERGY = "day_energy"
268280
DECIBEL_SENSITIVITY = "decibel_sensitivity"
269281
DECIBEL_SWITCH = "decibel_switch"
282+
DEFINEDIS = "definedis"
270283
DEFROST = "defrost"
271284
DEHUMIDITY_SET_ENUM = "dehumidify_set_enum"
272285
DEHUMIDITY_SET_VALUE = "dehumidify_set_value"
286+
DELAYDIS = "DelayDis"
273287
DELAY_CLEAN_TIME = "delay_clean_time"
274288
DELAY_SET = "delay_set"
275289
DEODORIZATION_NUM = "deodorization_num"
290+
DEVICEKW = "DeviceKw"
291+
DEVICEKWH = "DeviceKwh"
292+
DEVICEMAXSETA = "DeviceMaxSetA"
293+
DEVICESTATE = "DeviceState"
294+
DEVICETEMP = "DeviceTemp"
295+
DEVICETEMP2 = "DeviceTemp2"
276296
DEVICE_NUMBER = "device_number"
277297
DEVICE_STATE1 = "device_state1"
278298
DEVICE_STATE2 = "device_state2"
@@ -456,6 +476,7 @@ class DPCode(StrEnum):
456476
OCPP_TLS = "ocpp_tls"
457477
OCPP_URL = "ocpp_url"
458478
ODU_FAN_SPEED = "odu_fan_speed"
479+
ONLINE_STATE = "online_state"
459480
OPEN_CLOSE = "open_close"
460481
OPPOSITE = "opposite"
461482
OPTIMUMSTART = "optimumstart"
@@ -474,6 +495,7 @@ class DPCode(StrEnum):
474495
PERCENT_STATE_2 = "percent_state_2"
475496
PERCENT_STATE_3 = "percent_state_3"
476497
PERCENT_STATE_4 = "percent_state_4"
498+
PHASEFLAG = "PhaseFlag"
477499
PHASE_A = "phase_a"
478500
PHASE_B = "phase_b"
479501
PHASE_C = "phase_c"
@@ -561,6 +583,7 @@ class DPCode(StrEnum):
561583
RESET_ROLL_BRUSH = "reset_roll_brush"
562584
RESIDUAL_ELECTRICITY = "residual_electricity"
563585
REVERSE_ENERGY_TOTAL = "reverse_energy_total"
586+
RFID = "RFID"
564587
ROLL_BRUSH = "roll_brush"
565588
RUNNING_FAN_SPEED = "running_fan_speed"
566589
SCENE_1 = "scene_1"
@@ -593,6 +616,14 @@ class DPCode(StrEnum):
593616
SENSOR_HUMIDITY = "sensor_humidity"
594617
SENSOR_LINE = "sensor_line"
595618
SENSOR_TEMPERATURE = "sensor_temperature"
619+
SET16A = "Set16A"
620+
SET32A = "Set32A"
621+
SET40A = "Set40A"
622+
SET50A = "Set50A"
623+
SET60A = "set60a"
624+
SET80A = "set80a"
625+
SETDEFINETIME = "SetDefineTime"
626+
SETDELAYTIME = "SetDelayTime"
596627
SETTING = "setting"
597628
SHAKE = "shake" # Oscillating
598629
SHOCK_STATE = "shock_state" # Vibration status
@@ -691,6 +722,7 @@ class DPCode(StrEnum):
691722
SYNC_REQUEST = "sync_request"
692723
SYNC_RESPONSE = "sync_response"
693724
SYSTEMMODE = "systemmode"
725+
SYSTEM_VERSION = "system_version"
694726
TBD = "tbd"
695727
TEMP = "temp" # Temperature setting
696728
TEMPACTIVATE = "tempactivate"

custom_components/localtuya/core/ha_entities/binary_sensors.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,9 @@ def localtuya_binarySensor(state_on="1"):
467467
condition_contains_any=["tilt", "true"],
468468
),
469469
),
470+
# EV Charcher
471+
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
472+
"qccdz": (*FAULT_SENSOR,),
470473
}
471474

472475
BINARY_SENSORS["cl"] = FAULT_SENSOR

custom_components/localtuya/core/ha_entities/buttons.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@
216216
entity_category=EntityCategory.CONFIG,
217217
),
218218
),
219+
# EV Charcher
220+
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
221+
"qccdz": (
222+
LocalTuyaEntity(
223+
id=DPCode.CLEAR_ENERGY,
224+
name="Clear Energy",
225+
icon="mdi:lightning-bolt-circle",
226+
entity_category=EntityCategory.CONFIG,
227+
),
228+
),
219229
}
220230

221231
# Wireless Switch # also can come as knob switch.

custom_components/localtuya/core/ha_entities/numbers.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,58 @@ def localtuya_numbers(_min, _max, _step=1, _scale=1, unit=None) -> dict:
823823
entity_category=EntityCategory.CONFIG,
824824
),
825825
),
826+
# EV Charcher
827+
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
828+
"qccdz": (
829+
LocalTuyaEntity(
830+
id=DPCode.SETDELAYTIME,
831+
name="Set Delay time",
832+
custom_configs=localtuya_numbers(0, 15, unit=UnitOfTime.HOURS),
833+
entity_category=EntityCategory.CONFIG,
834+
),
835+
LocalTuyaEntity(
836+
id=DPCode.SETDEFINETIME,
837+
name="Set Define time",
838+
custom_configs=localtuya_numbers(0, 15, unit=UnitOfTime.HOURS),
839+
entity_category=EntityCategory.CONFIG,
840+
),
841+
LocalTuyaEntity(
842+
id=DPCode.SET16A,
843+
name="Set 16A",
844+
custom_configs=localtuya_numbers(8, 16, unit=UnitOfElectricCurrent.AMPERE),
845+
entity_category=EntityCategory.CONFIG,
846+
),
847+
LocalTuyaEntity(
848+
id=DPCode.SET32A,
849+
name="Set 32A",
850+
custom_configs=localtuya_numbers(8, 32, unit=UnitOfElectricCurrent.AMPERE),
851+
entity_category=EntityCategory.CONFIG,
852+
),
853+
LocalTuyaEntity(
854+
id=DPCode.SET40A,
855+
name="Set 400A",
856+
custom_configs=localtuya_numbers(12, 40, unit=UnitOfElectricCurrent.AMPERE),
857+
entity_category=EntityCategory.CONFIG,
858+
),
859+
LocalTuyaEntity(
860+
id=DPCode.SET50A,
861+
name="Set 50A",
862+
custom_configs=localtuya_numbers(12, 50, unit=UnitOfElectricCurrent.AMPERE),
863+
entity_category=EntityCategory.CONFIG,
864+
),
865+
LocalTuyaEntity(
866+
id=DPCode.SET60A,
867+
name="Set 60A",
868+
custom_configs=localtuya_numbers(6, 80, unit=UnitOfElectricCurrent.AMPERE),
869+
entity_category=EntityCategory.CONFIG,
870+
),
871+
LocalTuyaEntity(
872+
id=DPCode.SET80A,
873+
name="Set 80A",
874+
custom_configs=localtuya_numbers(24, 80, unit=UnitOfElectricCurrent.AMPERE),
875+
entity_category=EntityCategory.CONFIG,
876+
),
877+
),
826878
# Generic products, EV Charger
827879
# https://support.tuya.com/en/help/_detail/K9g77zfmlnwal
828880
"qt": (

custom_components/localtuya/core/ha_entities/selects.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,44 @@ def localtuya_selector(options):
440440
),
441441
),
442442
),
443+
# EV Charcher
444+
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
445+
"qccdz": (
446+
LocalTuyaEntity(
447+
id=DPCode.WORK_MODE,
448+
name="Mode",
449+
icon="mdi:cog",
450+
custom_configs=localtuya_selector(
451+
{
452+
"charge_now": "NOW",
453+
"charge_pct": "PCT",
454+
"charge_energy": "Energy",
455+
"charge_schedule": "Schedule",
456+
}
457+
),
458+
),
459+
LocalTuyaEntity(
460+
id=DPCode.ONLINE_STATE,
461+
name="Online state",
462+
icon="mdi:cog",
463+
custom_configs=localtuya_selector(
464+
{"online": "online", "offline": "offline"}
465+
),
466+
),
467+
LocalTuyaEntity(
468+
id=DPCode.CHARGINGOPERATION,
469+
name="Charge State",
470+
icon="mdi:cog",
471+
custom_configs=localtuya_selector(
472+
{
473+
"OpenCharging": "Open charging",
474+
"CloseCharging": "Close charging",
475+
"WaitOperation": "Wait for operation",
476+
}
477+
),
478+
entity_category=EntityCategory.CONFIG,
479+
),
480+
),
443481
# Heater
444482
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
445483
"qn": (

custom_components/localtuya/core/ha_entities/sensors.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,111 @@ def localtuya_sensor(unit_of_measurement=None, scale_factor: float = 1) -> dict:
726726
),
727727
*BATTERY_SENSORS,
728728
),
729+
# EV Charcher
730+
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
731+
"qccdz": (
732+
LocalTuyaEntity(
733+
id=DPCode.WORK_STATE,
734+
name="Work state",
735+
),
736+
LocalTuyaEntity(
737+
id=DPCode.DEVICESTATE,
738+
name="Device state",
739+
entity_category=EntityCategory.DIAGNOSTIC,
740+
),
741+
LocalTuyaEntity(
742+
id=DPCode.PHASEFLAG,
743+
name="Phase Flag",
744+
entity_category=EntityCategory.DIAGNOSTIC,
745+
),
746+
LocalTuyaEntity(
747+
id=DPCode.DEVICEMAXSETA,
748+
name="Max Set Ampere",
749+
entity_category=EntityCategory.DIAGNOSTIC,
750+
),
751+
LocalTuyaEntity(
752+
id=DPCode.DEVICEMAXSETA,
753+
name="Max Set Ampere",
754+
entity_category=EntityCategory.DIAGNOSTIC,
755+
),
756+
LocalTuyaEntity(
757+
id=DPCode.DEVICETEMP,
758+
name="Device Temperature",
759+
device_class=SensorDeviceClass.TEMPERATURE,
760+
state_class=SensorStateClass.MEASUREMENT,
761+
custom_configs=localtuya_sensor(UnitOfTemperature.CELSIUS, 0.1),
762+
),
763+
LocalTuyaEntity(
764+
id=DPCode.BALANCE_ENERGY,
765+
name="Energy Balance",
766+
device_class=SensorDeviceClass.ENERGY,
767+
state_class=SensorStateClass.TOTAL,
768+
custom_configs=localtuya_sensor(UnitOfEnergy.KILO_WATT_HOUR, 0.001),
769+
),
770+
LocalTuyaEntity(
771+
id=DPCode.CHARGE_ENERGY_ONCE,
772+
name="Energy charge",
773+
device_class=SensorDeviceClass.ENERGY,
774+
state_class=SensorStateClass.TOTAL,
775+
custom_configs=localtuya_sensor(UnitOfEnergy.KILO_WATT_HOUR, 0.01),
776+
),
777+
LocalTuyaEntity(
778+
id=DPCode.DEVICEKW,
779+
name="Device kW",
780+
device_class=SensorDeviceClass.POWER,
781+
state_class=SensorStateClass.MEASUREMENT,
782+
custom_configs=localtuya_sensor(UnitOfPower.KILO_WATT, 0.1),
783+
),
784+
LocalTuyaEntity(
785+
id=DPCode.DEVICEKW,
786+
name="Device kWh",
787+
device_class=SensorDeviceClass.ENERGY,
788+
state_class=SensorStateClass.TOTAL,
789+
custom_configs=localtuya_sensor(UnitOfEnergy.KILO_WATT_HOUR, 0.01),
790+
),
791+
LocalTuyaEntity(
792+
id=DPCode.A_VOLTAGE,
793+
name="Voltage A",
794+
device_class=SensorDeviceClass.VOLTAGE,
795+
state_class=SensorStateClass.MEASUREMENT,
796+
custom_configs=localtuya_sensor(UnitOfElectricPotential.VOLT, 0.1),
797+
),
798+
LocalTuyaEntity(
799+
id=DPCode.B_VOLTAGE,
800+
name="Voltage B",
801+
device_class=SensorDeviceClass.VOLTAGE,
802+
state_class=SensorStateClass.MEASUREMENT,
803+
custom_configs=localtuya_sensor(UnitOfElectricPotential.VOLT, 0.1),
804+
),
805+
LocalTuyaEntity(
806+
id=DPCode.C_VOLTAGE,
807+
name="Voltage C",
808+
device_class=SensorDeviceClass.VOLTAGE,
809+
state_class=SensorStateClass.MEASUREMENT,
810+
custom_configs=localtuya_sensor(UnitOfElectricPotential.VOLT, 0.1),
811+
),
812+
LocalTuyaEntity(
813+
id=DPCode.A_CURRENT,
814+
name="Current A",
815+
device_class=SensorDeviceClass.VOLTAGE,
816+
state_class=SensorStateClass.MEASUREMENT,
817+
custom_configs=localtuya_sensor(UnitOfElectricPotential.VOLT, 0.01),
818+
),
819+
LocalTuyaEntity(
820+
id=DPCode.B_CURRENT,
821+
name="Current B",
822+
device_class=SensorDeviceClass.VOLTAGE,
823+
state_class=SensorStateClass.MEASUREMENT,
824+
custom_configs=localtuya_sensor(UnitOfElectricPotential.VOLT, 0.01),
825+
),
826+
LocalTuyaEntity(
827+
id=DPCode.C_CURRENT,
828+
name="Current C",
829+
device_class=SensorDeviceClass.VOLTAGE,
830+
state_class=SensorStateClass.MEASUREMENT,
831+
custom_configs=localtuya_sensor(UnitOfElectricPotential.VOLT, 0.01),
832+
),
833+
),
729834
# Heater
730835
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
731836
"qn": (

custom_components/localtuya/core/ha_entities/switches.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,13 @@
494494
icon="mdi:human-greeting",
495495
),
496496
),
497+
# EV Charcher
498+
# https://developer.tuya.com/en/docs/iot/categoryqn?id=Kaiuz18kih0sm
499+
"qccdz": (
500+
LocalTuyaEntity(
501+
id=DPCode.SWITCH,
502+
),
503+
),
497504
# Unknown product with switch capabilities
498505
# Fond in some diffusers, plugs and PIR flood lights
499506
# Not documented

custom_components/localtuya/sensor.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,11 @@ def status_updated(self):
101101
if not self._has_sub_entities:
102102
self.hass.add_job(self.__create_sub_sensors())
103103

104-
if (sub_sensor := getattr(self, "_attr_sub_sensor", None)) and (
105-
sub_state := self.decode_base64(state).get(sub_sensor)
104+
if None not in (
105+
sub_sensor := getattr(self, "_attr_sub_sensor", None),
106+
sub_sensor_state := self.decode_base64(state).get(sub_sensor),
106107
):
107-
self._state = sub_state
108+
self._state = sub_sensor_state
108109
else:
109110
self._state = state
110111
else:

0 commit comments

Comments
 (0)