Bläddra i källkod

Add another smart switch type with more advanced features.

This switch is already detected as SmartplugV2, but has additional info attached, some of which is useful:
 - calibration info (report as attributes only)
 - energy reporting (report as new sensor) - caveat is it seems to reset every time it successfully sends data to the server, so never really changes.
 - initial mode selection (make available as select)
 - fault reporting (make available as a binary sensor, and attribute with fault code)

Issue #72
Jason Rumney 4 år sedan
förälder
incheckning
6e707fdd11

+ 116 - 0
custom_components/tuya_local/devices/smartplugv2_energy.yaml

@@ -0,0 +1,116 @@
+name: Advanced Energy Monitoring Smart Plug
+primary_entity:
+  entity: switch
+  class: outlet
+  dps:
+    - id: 1
+      type: boolean
+      name: switch
+    - id: 21
+      type: integer
+      name: test_bit
+    - id: 22
+      type: integer
+      name: voltage_calibration
+    - id: 23
+      type: integer
+      name: current_calibration
+    - id: 24
+      type: integer
+      name: power_calibration
+    - id: 25
+      type: integer
+      name: energy_calibration
+    - id: 26
+      type: bitfield
+      name: fault_code
+    - id: 41
+      type: string
+      name: cycle_timer
+    - id: 42
+      type: string
+      name: random_timer
+    - id: 46
+      type: boolean
+      name: unknown_46
+secondary_entities:
+  - entity: number
+    category: config
+    name: Timer
+    dps:
+      - id: 9
+        type: integer
+        name: value
+        range:
+          min: 0
+          max: 1440
+  - entity: sensor
+    category: diagnostic
+    class: energy
+    name: Energy
+    dps:
+      - id: 17
+        name: sensor
+        type: integer
+        unit: Wh
+        class: total_increasing
+  - entity: sensor
+    category: diagnostic
+    class: current
+    name: Current
+    dps:
+      - id: 18
+        name: sensor
+        type: integer
+        class: measurement
+        unit: mA
+  - entity: sensor
+    category: diagnostic
+    class: power
+    name: Power
+    dps:
+      - id: 19
+        name: sensor
+        type: integer
+        class: measurement
+        unit: W
+        mapping:
+          - scale: 10
+  - entity: sensor
+    category: diagnostic
+    class: voltage
+    name: Voltage
+    dps:
+      - id: 20
+        name: sensor
+        type: integer
+        class: measurement
+        unit: V
+        mapping:
+          - scale: 10
+  - entity: binary_sensor
+    class: problem
+    category: disagnostic
+    name: Error
+    dps:
+      - id: 26
+        type: bitfield
+        name: sensor
+        mapping:
+          - dps_val: 0
+            value: false
+          - value: true
+  - entity: select
+    category: config
+    name: Initial State
+    dps:
+      - id: 38
+        type: string
+        name: option
+        mapping:
+          - dps_val: "on"
+            value: "On"
+          - dps_val: "off"
+            value: "Off"
+          - dps_val: memory
+            value: "Last State"

+ 19 - 0
tests/const.py

@@ -80,6 +80,25 @@ KOGAN_SOCKET_PAYLOAD2 = {
     "20": 2300,
 }
 
+SMARTSWITCH_ENERGY_PAYLOAD = {
+    "1": True,
+    "9": 0,
+    "17": 100,
+    "18": 2368,
+    "19": 4866,
+    "20": 2148,
+    "21": 1,
+    "22": 628,
+    "23": 30636,
+    "24": 17426,
+    "25": 2400,
+    "26": 0,
+    "38": "memory",
+    "41": "",
+    "42": "",
+    "46": False,
+}
+
 KOGAN_SOCKET_CLEAR_PAYLOAD = {
     "2": None,
     "4": None,

+ 133 - 0
tests/devices/test_smartplugv2_energy.py

@@ -0,0 +1,133 @@
+"""Tests for the switch entity."""
+from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.const import (
+    DEVICE_CLASS_CURRENT,
+    DEVICE_CLASS_ENERGY,
+    DEVICE_CLASS_POWER,
+    DEVICE_CLASS_VOLTAGE,
+    ELECTRIC_CURRENT_MILLIAMPERE,
+    ELECTRIC_POTENTIAL_VOLT,
+    ENERGY_WATT_HOUR,
+    POWER_WATT,
+)
+
+from ..const import SMARTSWITCH_ENERGY_PAYLOAD
+from ..mixins.binary_sensor import BasicBinarySensorTests
+from ..mixins.number import BasicNumberTests
+from ..mixins.select import BasicSelectTests
+from ..mixins.sensor import MultiSensorTests
+from ..mixins.switch import BasicSwitchTests
+from .base_device_tests import TuyaDeviceTestCase
+
+SWITCH_DPS = "1"
+TIMER_DPS = "9"
+ENERGY_DPS = "17"
+CURRENT_DPS = "18"
+POWER_DPS = "19"
+VOLTAGE_DPS = "20"
+TEST_DPS = "21"
+CALIBV_DPS = "22"
+CALIBI_DPS = "23"
+CALIBP_DPS = "24"
+CALIBE_DPS = "25"
+ERROR_DPS = "26"
+INITIAL_DPS = "38"
+CYCLE_DPS = "41"
+RANDOM_DPS = "42"
+UNKNOWN46_DPS = "46"
+
+
+class TestSwitchV2Energy(
+    BasicBinarySensorTests,
+    BasicNumberTests,
+    BasicSelectTests,
+    MultiSensorTests,
+    BasicSwitchTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("smartplugv2_energy.yaml", SMARTSWITCH_ENERGY_PAYLOAD)
+        self.setUpBasicSwitch(
+            SWITCH_DPS,
+            self.entities.get("switch"),
+            device_class=DEVICE_CLASS_OUTLET,
+        )
+        self.setUpBasicBinarySensor(
+            ERROR_DPS,
+            self.entities.get("binary_sensor_error"),
+            device_class=DEVICE_CLASS_PROBLEM,
+            testdata=(1, 0),
+        )
+        self.setUpBasicNumber(TIMER_DPS, self.entities.get("number_timer"), max=1440)
+        self.setUpBasicSelect(
+            INITIAL_DPS,
+            self.entities.get("select_initial_state"),
+            {
+                "on": "On",
+                "off": "Off",
+                "memory": "Last State",
+            },
+        )
+        self.setUpMultiSensors(
+            [
+                {
+                    "name": "sensor_energy",
+                    "dps": ENERGY_DPS,
+                    "unit": ENERGY_WATT_HOUR,
+                    "device_class": DEVICE_CLASS_ENERGY,
+                    "state_class": "total_increasing",
+                },
+                {
+                    "name": "sensor_voltage",
+                    "dps": VOLTAGE_DPS,
+                    "unit": ELECTRIC_POTENTIAL_VOLT,
+                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "state_class": "measurement",
+                    "testdata": (2300, 230.0),
+                },
+                {
+                    "name": "sensor_current",
+                    "dps": CURRENT_DPS,
+                    "unit": ELECTRIC_CURRENT_MILLIAMPERE,
+                    "device_class": DEVICE_CLASS_CURRENT,
+                    "state_class": "measurement",
+                },
+                {
+                    "name": "sensor_power",
+                    "dps": POWER_DPS,
+                    "unit": POWER_WATT,
+                    "device_class": DEVICE_CLASS_POWER,
+                    "state_class": "measurement",
+                    "testdata": (1234, 123.4),
+                },
+            ]
+        )
+
+    def test_basic_switch_state_attributes(self):
+        self.dps[TEST_DPS] = 21
+        self.dps[CALIBV_DPS] = 22
+        self.dps[CALIBI_DPS] = 23
+        self.dps[CALIBP_DPS] = 24
+        self.dps[CALIBE_DPS] = 25
+        self.dps[ERROR_DPS] = 26
+        self.dps[CYCLE_DPS] = "1A2B"
+        self.dps[RANDOM_DPS] = "3C4D"
+        self.dps[UNKNOWN46_DPS] = True
+
+        self.assertDictEqual(
+            self.basicSwitch.device_state_attributes,
+            {
+                "test_bit": 21,
+                "voltage_calibration": 22,
+                "current_calibration": 23,
+                "power_calibration": 24,
+                "energy_calibration": 25,
+                "fault_code": 26,
+                "cycle_timer": "1A2B",
+                "random_timer": "3C4D",
+                "unknown_46": True,
+            },
+        )