From 1fecaafcadb5c3e0d02e6840fb05407b933ddb06 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 6 Mar 2025 11:45:53 +0100 Subject: [PATCH 01/11] Aeotec Home Energy Meter Gen8 init --- .../zwave-electric-meter/fingerprints.yml | 30 + ...tec-home-energy-meter-gen8-1-phase-con.yml | 229 +++++ ...tec-home-energy-meter-gen8-1-phase-pro.yml | 23 + ...tec-home-energy-meter-gen8-2-phase-con.yml | 146 +++ ...tec-home-energy-meter-gen8-2-phase-pro.yml | 32 + ...tec-home-energy-meter-gen8-3-phase-con.yml | 187 ++++ ...tec-home-energy-meter-gen8-3-phase-pro.yml | 41 + ...aeotec-home-energy-meter-gen8-sald-con.yml | 16 + ...aeotec-home-energy-meter-gen8-sald-pro.yml | 16 + .../1-phase/init.lua | 195 ++++ .../2-phase/init.lua | 193 ++++ .../3-phase/init.lua | 197 ++++ .../aeotec-home-energy-meter-gen8/init.lua | 36 + .../zwave-electric-meter/src/init.lua | 22 +- .../zwave-electric-meter/src/preferences.lua | 95 ++ ..._aeotec_home_energy_meter_gen8_1_phase.lua | 627 ++++++++++++ ..._aeotec_home_energy_meter_gen8_2_phase.lua | 627 ++++++++++++ ..._aeotec_home_energy_meter_gen8_3_phase.lua | 955 ++++++++++++++++++ 18 files changed, 3666 insertions(+), 1 deletion(-) create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml create mode 100644 drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/preferences.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua create mode 100644 drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua diff --git a/drivers/SmartThings/zwave-electric-meter/fingerprints.yml b/drivers/SmartThings/zwave-electric-meter/fingerprints.yml index 7c32d646e3..65f9e6499b 100644 --- a/drivers/SmartThings/zwave-electric-meter/fingerprints.yml +++ b/drivers/SmartThings/zwave-electric-meter/fingerprints.yml @@ -35,6 +35,36 @@ zwaveManufacturer: productType: 0x0002 productId: 0x0001 deviceProfileName: base-electric-meter + - id: "0x0371/0x0003/0x0033" #HEM Gen8 1 Phase EU + deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + manufacturerId: 0x0371 + productType: 0x0003 + productId: 0x0033 + deviceProfileName: aeotec-home-energy-meter-gen8-1-phase-con + - id: "0x0371/0x0003/0x0034" # HEM Gen8 3 Phase EU + deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + manufacturerId: 0x0371 + productType: 0x0003 + productId: 0x0034 + deviceProfileName: aeotec-home-energy-meter-gen8-3-phase-con + - id: "0x0371/0x0103/0x002E" # HEM Gen8 2 Phase US + deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + manufacturerId: 0x0371 + productType: 0x0103 + productId: 0x002E + deviceProfileName: aeotec-home-energy-meter-gen8-2-phase-con + - id: "0x0371/0x0102/0x0033" # HEM Gen8 1 Phase AU + deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + manufacturerId: 0x0371 + productType: 0x0102 + productId: 0x0033 + deviceProfileName: aeotec-home-energy-meter-gen8-1-phase-con + - id: "0x0371/0x0102/0x0034" #HEM Gen8 3 Phase AU + deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + manufacturerId: 0x0371 + productType: 0x0102 + productId: 0x0034 + deviceProfileName: aeotec-home-energy-meter-gen8-3-phase-con zwaveGeneric: - id: "GenericEnergyMeter" deviceLabel: Energy Monitor diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml new file mode 100644 index 0000000000..b86c1d3e5e --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml @@ -0,0 +1,229 @@ +name: aeotec-home-energy-meter-gen8-1-phase-con +components: +- id: main + label: "Sum Consumption" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp1 + label: "Clamp 1" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +preferences: + - name: thresholdCheck + title: "3. Threshold Check Enable/Disable" + description: "Enable selective reporting only when power change reaches a certain threshold or percentage set in 4 -19 below. This is used to reduce network traffic." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 1 + - name: imWThresholdTotal + title: "4. Import W threshold (total)" + description: "Threshold change in import wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWThresholdPhaseA + title: "5. Import W threshold (Phase A)" + description: "Threshold change in import wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdTotal + title: "8. Export W threshold(total)" + description: "Threshold change in export wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdPhaseA + title: "9. Export W threshold (Phase A)" + description: "Threshold change in export wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWPctThresholdTotal + title: "12. Import W threshold (total)" + description: "Percentage change in import wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: imWPctThresholdPhaseA + title: "13. Import W threshold (Phase A)" + description: "Percentage change in import wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdTotal + title: "16. Export W threshold (total)" + description: "Percentage change in export wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdPhaseA + title: "17. Export W threshold (Phase A)" + description: "Percentage change in export wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: autoRootDeviceReport + title: "32. Auto report of root device" + description: "Enable automatic report of root device." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: set101to106default + title: "100. Set 101-106 to default" + description: "Set 101-106 to default." + preferenceType: integer + definition: + minimum: 0 + maximum: 1 + default: 0 + - name: autoReportList1im + title: "101. Auto Report list 1 (Import)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: enumeration + definition: + options: + '0x03030000': "Default: Watt and kWh" + '0x00000000': "No reports" + '0x01010000': "kWh only" + '0x02020000': "Watt only" + default: '0x03030000' + # - name: autoReportList2im + # title: "102. Auto Report list 2 (Import)" + # description: "Configure which report needs to be sent in Report group 2." + # preferenceType: enumeration + # definition: + # options: + + # default: 0x0C0C0000 + # - name: autoReportList3im + # title: "103. Auto Report list 3 (Import)" + # description: "Configure which report needs to be sent in Report group 3." + # preferenceType: enumeration + # definition: + # options: + + # default: 0xF0F00000 + # - name: autoReportList1ex + # title: "104. Auto Report list 1 (Export)" + # description: "Configure which report needs to be sent in Report group 1." + # preferenceType: enumeration + # definition: + # options: + + # default: 0x03030000 + # - name: autoReportList2ex + # title: "105. Auto Report list 2 (Export)" + # description: "Configure which report needs to be sent in Report group 2." + # preferenceType: enumeration + # definition: + # options: + + # default: 0x0C0C0000 + # - name: autoReportList3ex + # title: "106. Auto Report list 3 (Export)" + # description: "Configure which report needs to be sent in Report group 3." + # preferenceType: enumeration + # definition: + # options: + + # default: 0xF0F00000 + - name: set111to116default + title: "110. Set 111-116 to default" + description: "Set 111-116 to default." + preferenceType: integer + definition: + minimum: 0 + maximum: 1 + default: 0 + - name: autoListTime1im + title: "111. Auto list 1 Interval (Import)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: integer + definition: + minimum: 10 + maximum: 4294967295 + default: 3600 + - name: autoListTime2im + title: "112. Auto list 2 Interval (Import)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: integer + definition: + minimum: 10 + maximum: 4294967295 + default: 7200 + - name: autoListTime3im + title: "113. Auto list 3 Interval (Import)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: integer + definition: + minimum: 10 + maximum: 4294967295 + default: 7200 + - name: autoListTime1ex + title: "114. Auto list 1 Interval (Export)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: integer + definition: + minimum: 10 + maximum: 4294967295 + default: 3600 + - name: autoListTime2ex + title: "115. Auto list 2 Interval (Export)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: integer + definition: + minimum: 10 + maximum: 4294967295 + default: 7200 + - name: autoListTime3ex + title: "116. Auto list 3 Interval (Export)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: integer + definition: + minimum: 10 + maximum: 4294967295 + default: 7200 + - name: confiLock + title: "252. Config lock Enable/disable" + description: "Enable/disable to lock configuration parameters." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml new file mode 100644 index 0000000000..9bd5b538ab --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml @@ -0,0 +1,23 @@ +name: aeotec-home-energy-meter-gen8-1-phase-pro +components: +- id: main + label: "Sum Production" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp2 + label: "Clamp 1" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +preferences: \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml new file mode 100644 index 0000000000..77844355a7 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml @@ -0,0 +1,146 @@ +name: aeotec-home-energy-meter-gen8-2-phase-con +components: +- id: main + label: "Sum Consumption" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp1 + label: "Clamp 1" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp3 + label: "Clamp 2" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +preferences: + - name: thresholdCheck + title: "3. Threshold Check Enable/Disable" + description: "Enable selective reporting only when power change reaches a certain threshold or percentage set in 4 -19 below. This is used to reduce network traffic." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 1 + - name: imWThresholdTotal + title: "4. Import W threshold (total)" + description: "Threshold change in import wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWThresholdPhaseA + title: "5. Import W threshold (Phase A)" + description: "Threshold change in import wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWhresholdPhaseB + title: "6. Import W threshold (Phase B)" + description: "Threshold change in import wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWhresholdTotal + title: "8. Export W threshold(total)" + description: "Threshold change in export wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdPhaseA + title: "9. Export W threshold (Phase A)" + description: "Threshold change in export wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdPhaseB + title: "10. Export W threshold (Phase B)" + description: "Threshold change in export wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWPctThresholdTotal + title: "12. Import W threshold (total)" + description: "Percentage change in import wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: imWPctThresholdPhaseA + title: "13. Import W threshold (Phase A)" + description: "Percentage change in import wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: imWPctThresholdPhaseB + title: "14. Import W threshold (Phase B)." + description: "Percentage change in import wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdTotal + title: "16. Export W threshold (total)" + description: "Percentage change in export wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdPhaseA + title: "17. Export W threshold (Phase A)" + description: "Percentage change in export wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdPhaseB + title: "18. Export W threshold (Phase B)" + description: "Percentage change in export wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: autoRootDeviceReport + title: "32. Auto report of root device" + description: "Enable automatic report of root device." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml new file mode 100644 index 0000000000..8ac577ffbc --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml @@ -0,0 +1,32 @@ +name: aeotec-home-energy-meter-gen8-2-phase-pro +components: +- id: main + label: "Sum Production" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp2 + label: "Clamp 1" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp4 + label: "Clamp 2" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +preferences: \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml new file mode 100644 index 0000000000..c015b0acc2 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml @@ -0,0 +1,187 @@ +name: aeotec-home-energy-meter-gen8-3-phase-con +components: +- id: main + label: "Sum Consumption" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp1 + label: "Clamp 1" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp3 + label: "Clamp 2" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp5 + label: "Clamp 3" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +preferences: + - name: thresholdCheck + title: "3. Threshold Check Enable/Disable" + description: "Enable selective reporting only when power change reaches a certain threshold or percentage set in 4 -19 below. This is used to reduce network traffic." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 1 + - name: imWThresholdTotal + title: "4. Import W threshold (total)" + description: "Threshold change in import wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWThresholdPhaseA + title: "5. Import W threshold (Phase A)" + description: "Threshold change in import wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWhresholdPhaseB + title: "6. Import W threshold (Phase B)" + description: "Threshold change in import wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imtWThresholdPhaseC + title: "7. Import W threshold (Phase C)" + description: "Threshold change in import wattage to induce an automatic report (Phase C)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWhresholdTotal + title: "8. Export W threshold(total)" + description: "Threshold change in export wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdPhaseA + title: "9. Export W threshold (Phase A)" + description: "Threshold change in export wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdPhaseB + title: "10. Export W threshold (Phase B)" + description: "Threshold change in export wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: exWThresholdPhaseC + title: "11. Export W threshold (Phase C)" + description: "Threshold change in export wattage to induce an automatic report (Phase C)." + preferenceType: integer + definition: + minimum: 0 + maximum: 60000 + default: 50 + - name: imWPctThresholdTotal + title: "12. Import W threshold (total)" + description: "Percentage change in import wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: imWPctThresholdPhaseA + title: "13. Import W threshold (Phase A)" + description: "Percentage change in import wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: imWPctThresholdPhaseB + title: "14. Import W threshold (Phase B)" + description: "Percentage change in import wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: imWPctThresholdPhaseC + title: "15. Import W threshold (Phase C)" + description: "Percentage change in import wattage to induce an automatic report (Phase C)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdTotal + title: "16. Export W threshold (total)" + description: "Percentage change in export wattage to induce an automatic report (Whole HEM)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdPhaseA + title: "17. Export W threshold (Phase A)" + description: "Percentage change in export wattage to induce an automatic report (Phase A)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdPhaseB + title: "18. Export W threshold (Phase B)" + description: "Percentage change in export wattage to induce an automatic report (Phase B)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: exWPctThresholdPhaseC + title: "19. Export W threshold (Phase C)" + description: "Percentage change in export wattage to induce an automatic report (Phase C)." + preferenceType: integer + definition: + minimum: 0 + maximum: 100 + default: 20 + - name: autoRootDeviceReport + title: "32. Auto report of root device" + description: "Enable automatic report of root device." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml new file mode 100644 index 0000000000..9c124bff73 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml @@ -0,0 +1,41 @@ +name: aeotec-home-energy-meter-gen8-3-phase-pro +components: +- id: main + label: "Sum Production" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp2 + label: "Clamp 1" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp4 + label: "Clamp 2" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +- id: clamp6 + label: "Clamp 3" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + categories: + - name: CurbPowerMeter +preferences: \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml new file mode 100644 index 0000000000..616df69383 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml @@ -0,0 +1,16 @@ +name: aeotec-home-energy-meter-gen8-sald-con +components: +- id: main + label: "Settled Consumption" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + - id: powerConsumptionReport + version: 1 + categories: + - name: CurbPowerMeter +preferences: \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml new file mode 100644 index 0000000000..17225c2c73 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml @@ -0,0 +1,16 @@ +name: aeotec-home-energy-meter-gen8-sald-pro +components: +- id: main + label: "Settled Production" + capabilities: + - id: powerMeter + version: 1 + - id: energyMeter + version: 1 + - id: refresh + version: 1 + - id: powerConsumptionReport + version: 1 + categories: + - name: CurbPowerMeter +preferences: \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua new file mode 100644 index 0000000000..e77408feef --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -0,0 +1,195 @@ +local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass.Meter +local Meter = (require "st.zwave.CommandClass.Meter")({ version=6 }) +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" + +local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { + { mfr = 0x0371, prod = 0x0003, model = 0x0033 }, -- HEM Gen8 1 Phase EU + { mfr = 0x0371, prod = 0x0102, model = 0x002E } -- HEM Gen8 1 Phase AU +} + +local LAST_REPORT_TIME = "LAST_REPORT_TIME" +local POWER_UNIT_WATT = "W" +local ENERGY_UNIT_KWH = "kWh" + +local HEM8_DEVICES = { + { profile = 'aeotec-home-energy-meter-gen8-3-phase-con', name = 'Aeotec Home Energy Meter 8 Consumption', endpoints = { 1, 3 } }, + { profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2, 4 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 5 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 6 } } +} + +local function can_handle_aeotec_meter_gen8_1_phase(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS) do + if device:id_match(fingerprint.mfr, fingerprint.prod, fingerprint.model) then + return true + end + end + return false +end + +local function find_hem8_child_device_key_by_endpoint(endpoint) + for _, child in ipairs(HEM8_DEVICES) do + if child.endpoints then + for _, e in ipairs(child.endpoints) do + if e == endpoint then + return child.child_key + end + end + end + end +end + +local function emit_power_consumption_report_event(device, value, channel) + -- powerConsumptionReport report interval + local current_time = os.time() + local last_time = device:get_field(LAST_REPORT_TIME) or 0 + local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports + if current_time < next_time then + return + end + device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) + local raw_value = value.value * 1000 -- 'Wh' + + local delta_energy = 0.0 + local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, + capabilities.powerConsumptionReport.powerConsumption.NAME) + if current_power_consumption ~= nil then + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + end + device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ + energy = raw_value, + deltaEnergy = delta_energy + })) +end + +local function meter_report_handler(driver, device, cmd, zb_rx) + local endpoint = cmd.src_channel + + local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); + local child_device = device:get_child_by_parent_assigned_key(child_device_key) + + if child_device then + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + child_device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + + if endpoint == 5 then + -- powerConsumptionReport + emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) + end + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + child_device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end + else + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end + end +end + +local function do_refresh(self, device) + for _, d in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(d.endpoints) do + device:send(Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, {dst_channels = {endpoint}})) + device:send(Meter:Get({scale = Meter.scale.electric_meter.WATTS}, {dst_channels = {endpoint}})) + end + end +end + +local function component_to_endpoint(device, component_id) + local ep_num = component_id:match("clamp(%d)") + return { ep_num and tonumber(ep_num) } +end + +local function endpoint_to_component(device, ep) + local meter_comp = string.format("clamp%d", ep) + if device.profile.components[meter_comp] ~= nil then + return meter_comp + else + return "main" + end +end + +local device_init = function(self, device) + device:set_component_to_endpoint_fn(component_to_endpoint) + device:set_endpoint_to_component_fn(endpoint_to_component) +end + +local function device_added(driver, device) + if device.network_type == st_device.NETWORK_TYPE_ZWAVE and not (device.child_ids and utils.table_size(device.child_ids) ~= 0) then + for i, hem8_child in ipairs(HEM8_DEVICES) do + if(hem8_child["child_key"]) then + local name = hem8_child.name + local metadata = { + type = "EDGE_CHILD", + label = name, + profile = hem8_child.profile, + parent_device_id = device.id, + parent_assigned_child_key = hem8_child.child_key, + vendor_provided_label = name + } + driver:try_create_device(metadata) + end + end + end + do_refresh(self, device) +end + +local aeotec_home_energy_meter_gen8_1_phase = { + NAME = "Aeotec Home Energy Meter Gen8", + supported_capabilities = { + capabilities.powerConsumptionReport + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh + } + }, + zwave_handlers = { + [cc.METER] = { + [Meter.REPORT] = meter_report_handler + } + }, + lifecycle_handlers = { + added = device_added, + init = device_init + }, + can_handle = can_handle_aeotec_meter_gen8_1_phase +} + +return aeotec_home_energy_meter_gen8_1_phase diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua new file mode 100644 index 0000000000..4060863cfa --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua @@ -0,0 +1,193 @@ +local st_device = require "st.device" +local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass.Meter +local Meter = (require "st.zwave.CommandClass.Meter")({ version=6 }) +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" + +local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { + { mfr = 0x0371, prod = 0x0103, model = 0x002E } -- HEM Gen8 2 Phase US +} + +local LAST_REPORT_TIME = "LAST_REPORT_TIME" +local POWER_UNIT_WATT = "W" +local ENERGY_UNIT_KWH = "kWh" + +local HEM8_DEVICES = { + { profile = 'aeotec-home-energy-meter-gen8-3-phase-con', name = 'Aeotec Home Energy Meter 8 Consumption', endpoints = { 1, 3, 5 } }, + { profile = 'aeotec-home-energy-meter-gen8-2-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2, 4, 6 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 7 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 8 } } +} + +local function can_handle_aeotec_meter_gen8_2_phase(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS) do + if device:id_match(fingerprint.mfr, fingerprint.prod, fingerprint.model) then + return true + end + end + return false +end + +local function find_hem8_child_device_key_by_endpoint(endpoint) + for _, child in ipairs(HEM8_DEVICES) do + if child.endpoints then + for _, e in ipairs(child.endpoints) do + if e == endpoint then + return child.child_key + end + end + end + end +end + +local function emit_power_consumption_report_event(device, value, channel) + -- powerConsumptionReport report interval + local current_time = os.time() + local last_time = device:get_field(LAST_REPORT_TIME) or 0 + local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports + if current_time < next_time then + return + end + device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) + local raw_value = value.value * 1000 -- 'Wh' + + local delta_energy = 0.0 + local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, + capabilities.powerConsumptionReport.powerConsumption.NAME) + if current_power_consumption ~= nil then + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + end + device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ + energy = raw_value, + deltaEnergy = delta_energy + })) +end + +local function meter_report_handler(driver, device, cmd, zb_rx) + local endpoint = cmd.src_channel + + local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); + local child_device = device:get_child_by_parent_assigned_key(child_device_key) + + if child_device then + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + child_device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + + if endpoint == 7 then + -- powerConsumptionReport + emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) + end + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + child_device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end + else + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end + end + +end + +local function do_refresh(self, device) + for _, d in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(d.endpoints) do + device:send(Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, {dst_channels = {endpoint}})) + device:send(Meter:Get({scale = Meter.scale.electric_meter.WATTS}, {dst_channels = {endpoint}})) + end + end +end + +local function component_to_endpoint(device, component_id) + local ep_num = component_id:match("clamp(%d)") + return { ep_num and tonumber(ep_num) } +end +local function endpoint_to_component(device, ep) + local meter_comp = string.format("clamp%d", ep) + if device.profile.components[meter_comp] ~= nil then + return meter_comp + else + return "main" + end +end +local device_init = function(self, device) + device:set_component_to_endpoint_fn(component_to_endpoint) + device:set_endpoint_to_component_fn(endpoint_to_component) +end +local function device_added(driver, device) + if device.network_type == st_device.NETWORK_TYPE_ZWAVE and not (device.child_ids and utils.table_size(device.child_ids) ~= 0) then + for i, hem8_child in ipairs(HEM8_DEVICES) do + if(hem8_child["child_key"]) then + local name = hem8_child.name + local metadata = { + type = "EDGE_CHILD", + label = name, + profile = hem8_child.profile, + parent_device_id = device.id, + parent_assigned_child_key = hem8_child.child_key, + vendor_provided_label = name + } + driver:try_create_device(metadata) + end + end + end + do_refresh(self, device) +end + +local aeotec_home_energy_meter_gen8_2_phase = { + NAME = "Aeotec Home Energy Meter Gen8", + supported_capabilities = { + capabilities.powerConsumptionReport + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh + } + }, + zwave_handlers = { + [cc.METER] = { + [Meter.REPORT] = meter_report_handler + } + }, + lifecycle_handlers = { + added = device_added, + init = device_init + }, + can_handle = can_handle_aeotec_meter_gen8_2_phase +} + +return aeotec_home_energy_meter_gen8_2_phase diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua new file mode 100644 index 0000000000..89463a3f91 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua @@ -0,0 +1,197 @@ +local st_device = require "st.device" +local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass.Meter +local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) +--- @type st.zwave.CommandClass +local cc = require "st.zwave.CommandClass" +local zw = require "st.zwave" +local utils = require "st.utils" + +local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { + { mfr = 0x0371, prod = 0x0003, model = 0x0034 }, -- HEM Gen8 3 Phase EU + { mfr = 0x0371, prod = 0x0102, model = 0x0034 } -- HEM Gen8 3 Phase AU +} + +local LAST_REPORT_TIME = "LAST_REPORT_TIME" +local POWER_UNIT_WATT = "W" +local ENERGY_UNIT_KWH = "kWh" + +local HEM8_DEVICES = { + { profile = 'aeotec-home-energy-meter-gen8-3-phase-con', name = 'Aeotec Home Energy Meter 8 Consumption', endpoints = { 1, 3, 5, 7 } }, + { profile = 'aeotec-home-energy-meter-gen8-3-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2, 4, 6, 8 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 9 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 10 } } +} + +local function can_handle_aeotec_meter_gen8_3_phase(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS) do + if device:id_match(fingerprint.mfr, fingerprint.prod, fingerprint.model) then + return true + end + end + return false +end + +local function find_hem8_child_device_key_by_endpoint(endpoint) + for _, child in ipairs(HEM8_DEVICES) do + if child.endpoints then + for _, e in ipairs(child.endpoints) do + if e == endpoint then + return child.child_key + end + end + end + end +end + +local function emit_power_consumption_report_event(device, value, channel) + -- powerConsumptionReport report interval + local current_time = os.time() + local last_time = device:get_field(LAST_REPORT_TIME) or 0 + local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports + if current_time < next_time then + return + end + device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) + local raw_value = value.value * 1000 -- 'Wh' + + local delta_energy = 0.0 + local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, + capabilities.powerConsumptionReport.powerConsumption.NAME) + if current_power_consumption ~= nil then + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + end + device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ + energy = raw_value, + deltaEnergy = delta_energy + })) +end + +local function meter_report_handler(driver, device, cmd, zb_rx) + local endpoint = cmd.src_channel + local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); + local child_device = device:get_child_by_parent_assigned_key(child_device_key) + + if child_device then + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + child_device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + + if endpoint == 9 then + -- powerConsumptionReport + emit_power_consumption_report_event(child_device, { value = event_arguments.value }, endpoint) + end + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + child_device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end + else + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + device:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end + end +end + +local function do_refresh(self, device) + for _, d in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(d.endpoints) do + device:send(Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, {dst_channels = {endpoint}})) + device:send(Meter:Get({scale = Meter.scale.electric_meter.WATTS}, {dst_channels = {endpoint}})) + end + end +end + +local function component_to_endpoint(device, component_id) + local ep_num = component_id:match("clamp(%d)") + return { ep_num and tonumber(ep_num) } +end + +local function endpoint_to_component(device, ep) + local meter_comp = string.format("clamp%d", ep) + if device.profile.components[meter_comp] ~= nil then + return meter_comp + else + return "main" + end +end + +local device_init = function(self, device) + device:set_component_to_endpoint_fn(component_to_endpoint) + device:set_endpoint_to_component_fn(endpoint_to_component) +end + +local function device_added(driver, device) + if device.network_type == st_device.NETWORK_TYPE_ZWAVE and not (device.child_ids and utils.table_size(device.child_ids) ~= 0) then + for i, hem8_child in ipairs(HEM8_DEVICES) do + if(hem8_child["child_key"]) then + local name = hem8_child.name + local metadata = { + type = "EDGE_CHILD", + label = name, + profile = hem8_child.profile, + parent_device_id = device.id, + parent_assigned_child_key = hem8_child.child_key, + vendor_provided_label = name + } + driver:try_create_device(metadata) + end + end + end + do_refresh(self, device) +end + +local aeotec_home_energy_meter_gen8_3_phase = { + NAME = "Aeotec Home Energy Meter Gen8", + supported_capabilities = { + capabilities.powerConsumptionReport + }, + capability_handlers = { + [capabilities.refresh.ID] = { + [capabilities.refresh.commands.refresh.NAME] = do_refresh + } + }, + zwave_handlers = { + [cc.METER] = { + [Meter.REPORT] = meter_report_handler + } + }, + lifecycle_handlers = { + added = device_added, + init = device_init + }, + can_handle = can_handle_aeotec_meter_gen8_3_phase +} + +return aeotec_home_energy_meter_gen8_3_phase diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua new file mode 100644 index 0000000000..db11d13c71 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua @@ -0,0 +1,36 @@ +local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { + { mfr = 0x0371, prod = 0x0003, model = 0x0033 }, -- HEM Gen8 1 Phase EU + { mfr = 0x0371, prod = 0x0003, model = 0x0034 }, -- HEM Gen8 3 Phase EU + { mfr = 0x0371, prod = 0x0103, model = 0x002E }, -- HEM Gen8 2 Phase US + { mfr = 0x0371, prod = 0x0102, model = 0x002E }, -- HEM Gen8 1 Phase AU + { mfr = 0x0371, prod = 0x0102, model = 0x0034 }, -- HEM Gen8 3 Phase AU +} + +local function can_handle_aeotec_meter_gen8(opts, driver, device, ...) + for _, fingerprint in ipairs(AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS) do + if device:id_match(fingerprint.mfr, fingerprint.prod, fingerprint.model) then + local subdriver = require("aeotec-home-energy-meter-gen8") + return true, subdriver + end + end + return false +end + +local function device_added(driver, device) + device:refresh() +end + +local aeotec_home_energy_meter_gen8 = { + NAME = "Aeotec Home Energy Meter Gen8", + lifecycle_handlers = { + added = device_added + }, + can_handle = can_handle_aeotec_meter_gen8, + sub_drivers = { + require("aeotec-home-energy-meter-gen8/1-phase"), + require("aeotec-home-energy-meter-gen8/2-phase"), + require("aeotec-home-energy-meter-gen8/3-phase") + } +} + +return aeotec_home_energy_meter_gen8 diff --git a/drivers/SmartThings/zwave-electric-meter/src/init.lua b/drivers/SmartThings/zwave-electric-meter/src/init.lua index 2ef9f20281..7de46a079b 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/init.lua @@ -18,10 +18,28 @@ local defaults = require "st.zwave.defaults" --- @type st.zwave.Driver local ZwaveDriver = require "st.zwave.driver" +local preferencesMap = require "preferences" + local device_added = function (self, device) device:refresh() end +--- Handle preference changes +--- +--- @param driver st.zwave.Driver +--- @param device st.zwave.Device +--- @param event table +--- @param args +local function info_changed(driver, device, event, args) + local preferences = preferencesMap.get_device_parameters(device) + for id, value in pairs(device.preferences) do + if args.old_st_store.preferences[id] ~= value and preferences and preferences[id] then + local new_parameter_value = preferencesMap.to_numeric_value(device.preferences[id]) + device:send(Configuration:Set({ parameter_number = preferences[id].parameter_number, size = preferences[id].size, configuration_value = new_parameter_value })) + end + end +end + local driver_template = { supported_capabilities = { capabilities.powerMeter, @@ -29,12 +47,14 @@ local driver_template = { capabilities.refresh }, lifecycle_handlers = { + infoChanged = info_changed, added = device_added }, sub_drivers = { require("qubino-meter"), require("aeotec-gen5-meter"), - require("aeon-meter") + require("aeon-meter"), + require("aeotec-home-energy-meter-gen8") } } diff --git a/drivers/SmartThings/zwave-electric-meter/src/preferences.lua b/drivers/SmartThings/zwave-electric-meter/src/preferences.lua new file mode 100644 index 0000000000..9d1f5f3c6a --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/preferences.lua @@ -0,0 +1,95 @@ +local devices = { + AEOTEC_HOME_ENERGY_METER_GEN8_1_PHASE = { + MATCHING_MATRIX = { + mfrs = 0x0371, + product_types = {0x0003, 0x0102 }, + product_ids = 0x0033 + }, + PARAMETERS = { + thresholdCheck = {parameter_number = 3, size = 1}, + imWThresholdTotal = {parameter_number = 4, size = 2}, + imWThresholdPhaseA = {parameter_number = 5, size = 2}, + exWThresholdTotal = {parameter_number = 8, size = 2}, + exWThresholdPhaseA = {parameter_number = 9, size = 2}, + imtWPctThresholdTotal = {parameter_number = 12, size = 1}, + imWPctThresholdPhaseA = {parameter_number = 13, size = 1}, + exWPctThresholdTotal = {parameter_number = 16, size = 1}, + exWPctThresholdPhaseA = {parameter_number = 17, size = 1}, + autoRootDeviceReport = {parameter_number = 32, size = 1} + } + }, + AEOTEC_HOME_ENERGY_METER_GEN8_2_PHASE = { + MATCHING_MATRIX = { + mfrs = 0x0371, + product_types = 0x0103, + product_ids = 0x002E + }, + PARAMETERS = { + thresholdCheck = {parameter_number = 3, size = 1}, + imWThresholdTotal = {parameter_number = 4, size = 2}, + imWThresholdPhaseA = {parameter_number = 5, size = 2}, + imWThresholdPhaseB = {parameter_number = 6, size = 2}, + exWThresholdTotal = {parameter_number = 8, size = 2}, + exWThresholdPhaseA = {parameter_number = 9, size = 2}, + exWThresholdPhaseB = {parameter_number = 10, size = 2}, + imtWPctThresholdTotal = {parameter_number = 12, size = 1}, + imWPctThresholdPhaseA = {parameter_number = 13, size = 1}, + imWPctThresholdPhaseB = {parameter_number = 14, size = 1}, + exWPctThresholdTotal = {parameter_number = 16, size = 1}, + exWPctThresholdPhaseA = {parameter_number = 17, size = 1}, + exWPctThresholdPhaseB = {parameter_number = 18, size = 1}, + autoRootDeviceReport = {parameter_number = 32, size = 1} + } + }, + AEOTEC_HOME_ENERGY_METER_GEN8_3_PHASE = { + MATCHING_MATRIX = { + mfrs = 0x0371, + product_types = {0x0003, 0x0102}, + product_ids = 0x0034 + }, + PARAMETERS = { + thresholdCheck = {parameter_number = 3, size = 1}, + imWThresholdTotal = {parameter_number = 4, size = 2}, + imWThresholdPhaseA = {parameter_number = 5, size = 2}, + imWThresholdPhaseB = {parameter_number = 6, size = 2}, + imWThresholdPhaseC = {parameter_number = 7, size = 2}, + exWThresholdTotal = {parameter_number = 8, size = 2}, + exWThresholdPhaseA = {parameter_number = 9, size = 2}, + exWThresholdPhaseB = {parameter_number = 10, size = 2}, + exWThresholdPhaseC = {parameter_number = 11, size = 2}, + imtWPctThresholdTotal = {parameter_number = 12, size = 1}, + imWPctThresholdPhaseA = {parameter_number = 13, size = 1}, + imWPctThresholdPhaseB = {parameter_number = 14, size = 1}, + imWPctThresholdPhaseC = {parameter_number = 15, size = 1}, + exWPctThresholdTotal = {parameter_number = 16, size = 1}, + exWPctThresholdPhaseA = {parameter_number = 17, size = 1}, + exWPctThresholdPhaseB = {parameter_number = 18, size = 1}, + exWPctThresholdPhaseC = {parameter_number = 19, size = 1}, + autoRootDeviceReport = {parameter_number = 32, size = 1} + } + } +} + +local preferences = {} + +preferences.get_device_parameters = function(zw_device) + for _, device in pairs(devices) do + if zw_device:id_match( + device.MATCHING_MATRIX.mfrs, + device.MATCHING_MATRIX.product_types, + device.MATCHING_MATRIX.product_ids) then + return device.PARAMETERS + end + end + return nil +end + +preferences.to_numeric_value = function(new_value) + local numeric = tonumber(new_value) + if numeric == nil then -- in case the value is boolean + numeric = new_value and 1 or 0 + end + return numeric +end + +return preferences \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua new file mode 100644 index 0000000000..872410cc51 --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua @@ -0,0 +1,627 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local zw = require "st.zwave" +local zw_test_utils = require "integration_test.zwave_test_utils" +local Meter = (require "st.zwave.CommandClass.Meter")({version=3}) +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) +local t_utils = require "integration_test.utils" + +local AEOTEC_MFR_ID = 0x0371 +local AEOTEC_METER_PROD_TYPE = 0x0003 +local AEOTEC_METER_PROD_ID = 0x0033 + +local LAST_REPORT_TIME = "LAST_REPORT_TIME" + +local aeotec_meter_endpoints = { + { + command_classes = { + {value = zw.METER} + } + } +} + +local HEM8_CHILDS = { + { profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 5 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 6 } } +} + +local mock_parent = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-home-energy-meter-gen8-1-phase-con.yml"), + zwave_endpoints = aeotec_meter_endpoints, + zwave_manufacturer_id = AEOTEC_MFR_ID, + zwave_product_type = AEOTEC_METER_PROD_TYPE, + zwave_product_id = AEOTEC_METER_PROD_ID +}) + +local mock_child_prod = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_CHILDS[1].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_CHILDS[1].child_key +}) + +local mock_child_sald_con = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_CHILDS[2].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_CHILDS[2].child_key +}) + +local mock_child_sald_prod = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_CHILDS[3].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_CHILDS[3].child_key +}) + + +local function test_init() + test.mock_device.add_test_device(mock_parent) + test.mock_device.add_test_device(mock_child_prod) + test.mock_device.add_test_device(mock_child_sald_con) + test.mock_device.add_test_device(mock_child_sald_prod) +end + +test.set_test_init_function(test_init) + +test.register_message_test( + "Power meter report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ + scale = Meter.scale.electric_meter.WATTS, + meter_value = 27}) + )} + }, + { + channel = "capability", + direction = "send", + message = mock_parent:generate_test_message("main", capabilities.powerMeter.power({ value = 27, unit = "W" })) + } + } +) + +test.register_message_test( + "Energy meter report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5}) + )} + }, + { + channel = "capability", + direction = "send", + message = mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + } + } +) + +test.register_message_test( + "Device should be polled at inclusion", + { + { + channel = "device_lifecycle", + direction = "receive", + message = { mock_parent.id, "added" }, + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}) + ) + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}) + ) + }, + }, + { + inner_block_ordering = "relaxed" + } +) + +test.register_coroutine_test( + "Report consumption and power consumption report after 15 minutes", function() + -- set time to trigger power consumption report + local current_time = os.time() - 60 * 20 + mock_parent:set_field(LAST_REPORT_TIME, current_time) + + test.socket.zwave:__queue_receive( + { + mock_parent.id, + zw_test_utils.zwave_test_build_receive_command(Meter:Report( + { + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + })) + } + ) + + test.socket.capability:__expect_send( + mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + + test.socket.capability:__expect_send( + mock_parent:generate_test_message("main", + capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) + ) + end +) + +test.register_coroutine_test( + "Added lifecycle event should create children for parent device", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) + + for _, child in ipairs(HEM8_CHILDS) do + mock_parent:expect_device_create( + { + type = "EDGE_CHILD", + label = child.name, + profile = child.profile, + parent_device_id = mock_parent.id, + parent_assigned_child_key = child.child_key + } + ) + end + end +) + +test.register_coroutine_test( + "Handle preference: thresholdCheck (parameter 3) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + thresholdCheck = 0 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 3, + configuration_value = 0, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdTotal (parameter 4) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdTotal = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 4, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseA (parameter 5) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseA = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 5, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseB (parameter 6) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseB = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 6, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseC = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 7, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdTotal = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 8, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseA (parameter 9) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseA = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 9, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseB (parameter 10) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseB = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 10, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseC = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 11, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imtWPctThresholdTotal = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 12, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseA (parameter 13) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseA = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 13, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseB (parameter 14) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseB = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 14, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseC = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 15, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdTotal = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 16, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdPhaseA (parameter 17) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseA = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 17, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdPhaseB (parameter 18) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseB = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 18, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseC = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 19, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoRootDeviceReport = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 32, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.run_registered_tests() diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua new file mode 100644 index 0000000000..fb1f5c2a3d --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua @@ -0,0 +1,627 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local zw = require "st.zwave" +local zw_test_utils = require "integration_test.zwave_test_utils" +local Meter = (require "st.zwave.CommandClass.Meter")({version=3}) +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) +local t_utils = require "integration_test.utils" + +local AEOTEC_MFR_ID = 0x0371 +local AEOTEC_METER_PROD_TYPE = 0x0003 +local AEOTEC_METER_PROD_ID = 0x0033 + +local LAST_REPORT_TIME = "LAST_REPORT_TIME" + +local aeotec_meter_endpoints = { + { + command_classes = { + {value = zw.METER} + } + } +} + +local HEM8_CHILDS = { + { profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2, 4, 6 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 7 } }, + { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 8 } } +} + +local mock_parent = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition("aeotec-home-energy-meter-gen8-1-phase-con.yml"), + zwave_endpoints = aeotec_meter_endpoints, + zwave_manufacturer_id = AEOTEC_MFR_ID, + zwave_product_type = AEOTEC_METER_PROD_TYPE, + zwave_product_id = AEOTEC_METER_PROD_ID +}) + +local mock_child_prod = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_CHILDS[1].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_CHILDS[1].child_key +}) + +local mock_child_sald_con = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_CHILDS[2].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_CHILDS[2].child_key +}) + +local mock_child_sald_prod = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_CHILDS[3].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_CHILDS[3].child_key +}) + + +local function test_init() + test.mock_device.add_test_device(mock_parent) + test.mock_device.add_test_device(mock_child_prod) + test.mock_device.add_test_device(mock_child_sald_con) + test.mock_device.add_test_device(mock_child_sald_prod) +end + +test.set_test_init_function(test_init) + +test.register_message_test( + "Power meter report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ + scale = Meter.scale.electric_meter.WATTS, + meter_value = 27}) + )} + }, + { + channel = "capability", + direction = "send", + message = mock_parent:generate_test_message("main", capabilities.powerMeter.power({ value = 27, unit = "W" })) + } + } +) + +test.register_message_test( + "Energy meter report should be handled", + { + { + channel = "zwave", + direction = "receive", + message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5}) + )} + }, + { + channel = "capability", + direction = "send", + message = mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + } + } +) + +test.register_message_test( + "Device should be polled at inclusion", + { + { + channel = "device_lifecycle", + direction = "receive", + message = { mock_parent.id, "added" }, + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}) + ) + }, + { + channel = "zwave", + direction = "send", + message = zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}) + ) + }, + }, + { + inner_block_ordering = "relaxed" + } +) + +test.register_coroutine_test( + "Report consumption and power consumption report after 15 minutes", function() + -- set time to trigger power consumption report + local current_time = os.time() - 60 * 20 + mock_parent:set_field(LAST_REPORT_TIME, current_time) + + test.socket.zwave:__queue_receive( + { + mock_parent.id, + zw_test_utils.zwave_test_build_receive_command(Meter:Report( + { + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + })) + } + ) + + test.socket.capability:__expect_send( + mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + + test.socket.capability:__expect_send( + mock_parent:generate_test_message("main", + capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) + ) + end +) + +test.register_coroutine_test( + "Added lifecycle event should create children for parent device", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) + + for _, child in ipairs(HEM8_CHILDS) do + mock_parent:expect_device_create( + { + type = "EDGE_CHILD", + label = child.name, + profile = child.profile, + parent_device_id = mock_parent.id, + parent_assigned_child_key = child.child_key + } + ) + end + end +) + +test.register_coroutine_test( + "Handle preference: thresholdCheck (parameter 3) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + thresholdCheck = 0 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 3, + configuration_value = 0, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdTotal (parameter 4) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdTotal = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 4, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseA (parameter 5) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseA = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 5, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseB (parameter 6) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseB = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 6, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseC = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 7, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdTotal = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 8, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseA (parameter 9) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseA = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 9, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseB (parameter 10) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseB = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 10, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseC = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 11, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imtWPctThresholdTotal = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 12, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseA (parameter 13) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseA = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 13, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseB (parameter 14) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseB = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 14, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseC = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 15, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdTotal = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 16, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdPhaseA (parameter 17) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseA = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 17, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdPhaseB (parameter 18) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseB = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 18, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseC = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 19, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoRootDeviceReport = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 32, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.run_registered_tests() diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua new file mode 100644 index 0000000000..f927de899c --- /dev/null +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua @@ -0,0 +1,955 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + +local log = require "log" +local st_utils = require "st.utils" + +local test = require "integration_test" +local capabilities = require "st.capabilities" +local zw = require "st.zwave" +local zw_test_utils = require "integration_test.zwave_test_utils" +local Meter = (require "st.zwave.CommandClass.Meter")({version=4}) +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) +local t_utils = require "integration_test.utils" + +local AEOTEC_MFR_ID = 0x0371 +local AEOTEC_METER_PROD_TYPE = 0x0003 +local AEOTEC_METER_PROD_ID = 0x0034 + +local LAST_REPORT_TIME = "LAST_REPORT_TIME" + +local aeotec_meter_endpoints = { + { + command_classes = { + {value = zw.METER} + } + } +} + +local HEM8_DEVICES = { + { + profile = 'aeotec-home-energy-meter-gen8-3-phase-con', + name = 'Aeotec Home Energy Meter 8 Consumption', + endpoints = { 1, 3, 5, 7 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-3-phase-pro', + name = 'Aeotec Home Energy Meter 8 Production', + child_key = 'pro', + endpoints = { 2, 4, 6, 8 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-sald-con', + name = 'Aeotec Home Energy Meter 8 Settled Consumption', + child_key = 'sald-con', + endpoints = { 9 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-sald-pro', + name = 'Aeotec Home Energy Meter 8 Settled Production', + child_key = 'sald-pro', + endpoints = { 10 } + } +} + +local mock_parent = test.mock_device.build_test_zwave_device({ + profile = t_utils.get_profile_definition(HEM8_DEVICES[1].profile .. '.yml'), + zwave_endpoints = aeotec_meter_endpoints, + zwave_manufacturer_id = AEOTEC_MFR_ID, + zwave_product_type = AEOTEC_METER_PROD_TYPE, + zwave_product_id = AEOTEC_METER_PROD_ID +}) + +local mock_child_prod = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_DEVICES[2].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_DEVICES[2].child_key +}) + +local mock_child_sald_con = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_DEVICES[3].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_DEVICES[3].child_key +}) + +local mock_child_sald_prod = test.mock_device.build_test_child_device({ + profile = t_utils.get_profile_definition(HEM8_DEVICES[4].profile .. '.yml'), + parent_device_id = mock_parent.id, + parent_assigned_child_key = HEM8_DEVICES[4].child_key +}) + +local function test_init() + test.mock_device.add_test_device(mock_parent) + test.mock_device.add_test_device(mock_child_prod) + test.mock_device.add_test_device(mock_child_sald_con) + test.mock_device.add_test_device(mock_child_sald_prod) +end + +test.set_test_init_function(test_init) + +test.register_coroutine_test( + "Added lifecycle event should create children for parent device", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) + + for _, child in ipairs(HEM8_DEVICES) do + if(child["child_key"]) then + mock_parent:expect_device_create( + { + type = "EDGE_CHILD", + label = child.name, + profile = child.profile, + parent_device_id = mock_parent.id, + parent_assigned_child_key = child.child_key + } + ) + end + end + -- Refresh + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end + end +) + +-- test.register_coroutine_test( +-- "Power meter report should be handled", +-- function() +-- for _, device in ipairs(HEM8_DEVICES) do +-- for _, endpoint in ipairs(device.endpoints) do +-- local component = "main" +-- if endpoint ~= 7 and endpoint ~= 8 and endpoint ~= 9 and endpoint ~= 10 then +-- component = string.format("clamp%d", endpoint) +-- end +-- test.socket.zwave:__queue_receive({ +-- mock_parent.id, +-- Meter:Report({ +-- scale = Meter.scale.electric_meter.WATTS, +-- meter_value = 27 +-- }, { +-- encap = zw.ENCAP.AUTO, +-- src_channel = endpoint, +-- dst_channels = {0} +-- }) +-- }) +-- if(device["child_key"]) then +-- if(device["child_key"] == "pro") then +-- test.socket.capability:__expect_send( +-- mock_child_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) +-- ) +-- elseif (device["child_key"] == "sald-pro") then +-- test.socket.capability:__expect_send( +-- mock_child_sald_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) +-- ) +-- elseif (device["child_key"] == "sald-con") then +-- test.socket.capability:__expect_send( +-- mock_child_sald_con:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) +-- ) +-- end +-- else +-- test.socket.capability:__expect_send( +-- mock_parent:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) +-- ) +-- end +-- end +-- end +-- end +-- ) + +-- test.register_coroutine_test( +-- "Energy meter report should be handled", +-- function() +-- for _, device in ipairs(HEM8_DEVICES) do +-- for _, endpoint in ipairs(device.endpoints) do +-- local component = "main" +-- if endpoint ~= 7 and endpoint ~= 8 and endpoint ~= 9 and endpoint ~= 10 then +-- component = string.format("clamp%d", endpoint) +-- end +-- test.socket.zwave:__queue_receive({ +-- mock_parent.id, +-- Meter:Report({ +-- scale = Meter.scale.electric_meter.KILOWATT_HOURS, +-- meter_value = 5 +-- }, { +-- encap = zw.ENCAP.AUTO, +-- src_channel = endpoint, +-- dst_channels = {0} +-- }) +-- }) +-- if(device["child_key"]) then +-- if(device["child_key"] == "pro") then +-- test.socket.capability:__expect_send( +-- mock_child_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) +-- ) +-- elseif (device["child_key"] == "sald-pro") then +-- test.socket.capability:__expect_send( +-- mock_child_sald_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) +-- ) +-- elseif (device["child_key"] == "sald-con") then +-- test.socket.capability:__expect_send( +-- mock_child_sald_con:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) +-- ) +-- end +-- else +-- test.socket.capability:__expect_send( +-- mock_parent:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) +-- ) +-- end +-- end +-- end +-- end +-- ) + +-- test.register_coroutine_test( +-- "Report consumption and power consumption report after 15 minutes", function() +-- -- set time to trigger power consumption report +-- local current_time = os.time() - 60 * 20 +-- mock_child_sald_con:set_field(LAST_REPORT_TIME, current_time) + +-- test.socket.zwave:__queue_receive( +-- { +-- mock_child_sald_con.id, +-- zw_test_utils.zwave_test_build_receive_command(Meter:Report( +-- { +-- scale = Meter.scale.electric_meter.KILOWATT_HOURS, +-- meter_value = 5 +-- }, +-- { +-- encap = zw.ENCAP.AUTO, +-- src_channel = 9, +-- dst_channels = {0} +-- } +-- )) +-- } +-- ) + +-- test.socket.capability:__expect_send( +-- mock_child_sald_con:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) +-- ) + +-- test.socket.capability:__expect_send( +-- mock_child_sald_con:generate_test_message("main", +-- capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: thresholdCheck (parameter 3) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- thresholdCheck = 0 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 3, +-- configuration_value = 0, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWThresholdTotal (parameter 4) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWThresholdTotal = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 4, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWThresholdPhaseA (parameter 5) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWThresholdPhaseA = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 5, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWThresholdPhaseB (parameter 6) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWThresholdPhaseB = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 6, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWThresholdPhaseC = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 7, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWThresholdTotal = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 8, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWThresholdPhaseA (parameter 9) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWThresholdPhaseA = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 9, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWThresholdPhaseB (parameter 10) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWThresholdPhaseB = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 10, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWThresholdPhaseC = 3500 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 11, +-- configuration_value = 3500, +-- size = 2 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imtWPctThresholdTotal = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 12, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWPctThresholdPhaseA (parameter 13) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWPctThresholdPhaseA = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 13, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWPctThresholdPhaseB (parameter 14) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWPctThresholdPhaseB = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 14, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- imWPctThresholdPhaseC = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 15, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWPctThresholdTotal = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 16, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWPctThresholdPhaseA (parameter 17) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWPctThresholdPhaseA = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 17, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: exWPctThresholdPhaseB (parameter 18) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWPctThresholdPhaseB = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 18, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- exWPctThresholdPhaseC = 50 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 19, +-- configuration_value = 50, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", +-- function() +-- test.socket.device_lifecycle:__queue_receive( +-- mock_parent:generate_info_changed({ +-- preferences = { +-- autoRootDeviceReport = 1 +-- } +-- }) +-- ) + +-- test.socket.zwave:__expect_send( +-- zw_test_utils.zwave_test_build_send_command( +-- mock_parent, +-- Configuration:Set({ +-- parameter_number = 32, +-- configuration_value = 1, +-- size = 1 +-- }) +-- ) +-- ) +-- end +-- ) + +-- test.register_coroutine_test( +-- "Refresh sends commands to all components including base device", +-- function() +-- -- refresh commands for zwave devices do not have guaranteed ordering +-- test.socket.zwave:__set_channel_ordering("relaxed") + +-- -- {args={delta_time=0, meter_type="ELECTRIC_METER", meter_value=0.0, precision=3, rate_type="EXPORT", scale="WATTS", size=4}, cmd_class="METER", cmd_id="REPORT", dst_channels={0}, encap="S2_AUTH", payload="\x41\x74\x00\x00\x00\x00\x00\x00", src_channel=10, version=3} + +-- test.socket.capability:__queue_receive({ +-- mock_parent.id, +-- { capability = "refresh", component = "main", command = "refresh", args = {} } +-- }) + + -- test.socket.zwave:__expect_send( + -- zw_test_utils.zwave_test_build_send_command(mock_parent, Meter:Get({ + -- scale = Meter.scale.electric_meter.KILOWATT_HOURS + -- },{ + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {2} + -- })) + -- ) + + + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {0} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {0} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {1} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {1} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {2} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {2} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {3} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {3} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {4} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {4} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {5} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {5} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {6} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {6} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {7} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {7} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {8} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {8} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {9} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {9} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {10} + -- }) + -- )) + + -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + -- mock_parent, + -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, + -- { + -- encap = zw.ENCAP.AUTO, + -- src_channel = 0, + -- dst_channels = {10} + -- }) + -- )) + + -- test.socket.capability:__queue_receive({ + -- mock_parent.id, + -- { capability = "refresh", component = "main", command = "refresh", args = { } } + -- }) + +-- end +-- ) + +test.run_registered_tests() From 0b41971f0c152f83f86a24f482cf929419ab20cf Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 6 Mar 2025 13:16:37 +0100 Subject: [PATCH 02/11] Add missing Configuration import --- drivers/SmartThings/zwave-electric-meter/src/init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/SmartThings/zwave-electric-meter/src/init.lua b/drivers/SmartThings/zwave-electric-meter/src/init.lua index 7de46a079b..e751c133e9 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/init.lua @@ -17,6 +17,8 @@ local capabilities = require "st.capabilities" local defaults = require "st.zwave.defaults" --- @type st.zwave.Driver local ZwaveDriver = require "st.zwave.driver" +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({version=1}) local preferencesMap = require "preferences" From cdea1919dc306fd9d833576b934db7e2bdb78a4b Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 6 Mar 2025 13:17:02 +0100 Subject: [PATCH 03/11] add missing device import --- .../src/aeotec-home-energy-meter-gen8/1-phase/init.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua index e77408feef..0946ad161b 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -1,3 +1,4 @@ +local st_device = require "st.device" local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass.Meter local Meter = (require "st.zwave.CommandClass.Meter")({ version=6 }) From 082e122392a835397fd6f262e61f6ebd21065466 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 26 Mar 2025 16:11:13 +0100 Subject: [PATCH 04/11] fix review comments - add copyright to source files - add missing tests - fix typos - consolidated fingerprints - fix line indentations - rework meter_report_handler function --- .../zwave-electric-meter/fingerprints.yml | 24 +- ...tec-home-energy-meter-gen8-1-phase-con.yml | 124 -- ...tec-home-energy-meter-gen8-1-phase-pro.yml | 3 +- ...tec-home-energy-meter-gen8-2-phase-pro.yml | 3 +- ...tec-home-energy-meter-gen8-3-phase-pro.yml | 3 +- ...aeotec-home-energy-meter-gen8-sald-con.yml | 3 +- ...aeotec-home-energy-meter-gen8-sald-pro.yml | 3 +- .../1-phase/init.lua | 166 +- .../2-phase/init.lua | 159 +- .../3-phase/init.lua | 150 +- .../aeotec-home-energy-meter-gen8/init.lua | 14 + ..._aeotec_home_energy_meter_gen8_1_phase.lua | 506 +++--- ..._aeotec_home_energy_meter_gen8_2_phase.lua | 414 ++--- ..._aeotec_home_energy_meter_gen8_3_phase.lua | 1474 +++++++---------- 14 files changed, 1309 insertions(+), 1737 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/fingerprints.yml b/drivers/SmartThings/zwave-electric-meter/fingerprints.yml index 65f9e6499b..c580510daa 100644 --- a/drivers/SmartThings/zwave-electric-meter/fingerprints.yml +++ b/drivers/SmartThings/zwave-electric-meter/fingerprints.yml @@ -35,36 +35,22 @@ zwaveManufacturer: productType: 0x0002 productId: 0x0001 deviceProfileName: base-electric-meter - - id: "0x0371/0x0003/0x0033" #HEM Gen8 1 Phase EU - deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + - id: "0x0371/0x0003/0x0033" #HEM Gen8 1 Phase EU, AU + deviceLabel: Aeotec Home Energy Meter Gen8 Consumption manufacturerId: 0x0371 - productType: 0x0003 productId: 0x0033 deviceProfileName: aeotec-home-energy-meter-gen8-1-phase-con - - id: "0x0371/0x0003/0x0034" # HEM Gen8 3 Phase EU - deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + - id: "0x0371/0x0003/0x0034" # HEM Gen8 3 Phase EU, AU + deviceLabel: Aeotec Home Energy Meter Gen8 Consumption manufacturerId: 0x0371 - productType: 0x0003 productId: 0x0034 deviceProfileName: aeotec-home-energy-meter-gen8-3-phase-con - id: "0x0371/0x0103/0x002E" # HEM Gen8 2 Phase US - deviceLabel: Aeotec Home Engery Meter Gen8 Consumption + deviceLabel: Aeotec Home Energy Meter Gen8 Consumption manufacturerId: 0x0371 productType: 0x0103 productId: 0x002E deviceProfileName: aeotec-home-energy-meter-gen8-2-phase-con - - id: "0x0371/0x0102/0x0033" # HEM Gen8 1 Phase AU - deviceLabel: Aeotec Home Engery Meter Gen8 Consumption - manufacturerId: 0x0371 - productType: 0x0102 - productId: 0x0033 - deviceProfileName: aeotec-home-energy-meter-gen8-1-phase-con - - id: "0x0371/0x0102/0x0034" #HEM Gen8 3 Phase AU - deviceLabel: Aeotec Home Engery Meter Gen8 Consumption - manufacturerId: 0x0371 - productType: 0x0102 - productId: 0x0034 - deviceProfileName: aeotec-home-energy-meter-gen8-3-phase-con zwaveGeneric: - id: "GenericEnergyMeter" deviceLabel: Energy Monitor diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml index b86c1d3e5e..c53872b7ce 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml @@ -98,130 +98,6 @@ preferences: title: "32. Auto report of root device" description: "Enable automatic report of root device." preferenceType: enumeration - definition: - options: - 0: "Disable" - 1: "Enable" - default: 0 - - name: set101to106default - title: "100. Set 101-106 to default" - description: "Set 101-106 to default." - preferenceType: integer - definition: - minimum: 0 - maximum: 1 - default: 0 - - name: autoReportList1im - title: "101. Auto Report list 1 (Import)" - description: "Configure which report needs to be sent in Report group 1." - preferenceType: enumeration - definition: - options: - '0x03030000': "Default: Watt and kWh" - '0x00000000': "No reports" - '0x01010000': "kWh only" - '0x02020000': "Watt only" - default: '0x03030000' - # - name: autoReportList2im - # title: "102. Auto Report list 2 (Import)" - # description: "Configure which report needs to be sent in Report group 2." - # preferenceType: enumeration - # definition: - # options: - - # default: 0x0C0C0000 - # - name: autoReportList3im - # title: "103. Auto Report list 3 (Import)" - # description: "Configure which report needs to be sent in Report group 3." - # preferenceType: enumeration - # definition: - # options: - - # default: 0xF0F00000 - # - name: autoReportList1ex - # title: "104. Auto Report list 1 (Export)" - # description: "Configure which report needs to be sent in Report group 1." - # preferenceType: enumeration - # definition: - # options: - - # default: 0x03030000 - # - name: autoReportList2ex - # title: "105. Auto Report list 2 (Export)" - # description: "Configure which report needs to be sent in Report group 2." - # preferenceType: enumeration - # definition: - # options: - - # default: 0x0C0C0000 - # - name: autoReportList3ex - # title: "106. Auto Report list 3 (Export)" - # description: "Configure which report needs to be sent in Report group 3." - # preferenceType: enumeration - # definition: - # options: - - # default: 0xF0F00000 - - name: set111to116default - title: "110. Set 111-116 to default" - description: "Set 111-116 to default." - preferenceType: integer - definition: - minimum: 0 - maximum: 1 - default: 0 - - name: autoListTime1im - title: "111. Auto list 1 Interval (Import)" - description: "Set the interval time of sending report in Report group 1." - preferenceType: integer - definition: - minimum: 10 - maximum: 4294967295 - default: 3600 - - name: autoListTime2im - title: "112. Auto list 2 Interval (Import)" - description: "Set the interval time of sending report in Report group 2." - preferenceType: integer - definition: - minimum: 10 - maximum: 4294967295 - default: 7200 - - name: autoListTime3im - title: "113. Auto list 3 Interval (Import)" - description: "Set the interval time of sending report in Report group 3." - preferenceType: integer - definition: - minimum: 10 - maximum: 4294967295 - default: 7200 - - name: autoListTime1ex - title: "114. Auto list 1 Interval (Export)" - description: "Set the interval time of sending report in Report group 1." - preferenceType: integer - definition: - minimum: 10 - maximum: 4294967295 - default: 3600 - - name: autoListTime2ex - title: "115. Auto list 2 Interval (Export)" - description: "Set the interval time of sending report in Report group 2." - preferenceType: integer - definition: - minimum: 10 - maximum: 4294967295 - default: 7200 - - name: autoListTime3ex - title: "116. Auto list 3 Interval (Export)" - description: "Set the interval time of sending report in Report group 3." - preferenceType: integer - definition: - minimum: 10 - maximum: 4294967295 - default: 7200 - - name: confiLock - title: "252. Config lock Enable/disable" - description: "Enable/disable to lock configuration parameters." - preferenceType: enumeration definition: options: 0: "Disable" diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml index 9bd5b538ab..79b1eef8bc 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-pro.yml @@ -19,5 +19,4 @@ components: - id: energyMeter version: 1 categories: - - name: CurbPowerMeter -preferences: \ No newline at end of file + - name: CurbPowerMeter \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml index 8ac577ffbc..717a91aeef 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-pro.yml @@ -28,5 +28,4 @@ components: - id: energyMeter version: 1 categories: - - name: CurbPowerMeter -preferences: \ No newline at end of file + - name: CurbPowerMeter \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml index 9c124bff73..e877276a7b 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-pro.yml @@ -37,5 +37,4 @@ components: - id: energyMeter version: 1 categories: - - name: CurbPowerMeter -preferences: \ No newline at end of file + - name: CurbPowerMeter \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml index 616df69383..9b78fca82a 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-con.yml @@ -12,5 +12,4 @@ components: - id: powerConsumptionReport version: 1 categories: - - name: CurbPowerMeter -preferences: \ No newline at end of file + - name: CurbPowerMeter \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml index 17225c2c73..bd1f8cfebd 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml @@ -12,5 +12,4 @@ components: - id: powerConsumptionReport version: 1 categories: - - name: CurbPowerMeter -preferences: \ No newline at end of file + - name: CurbPowerMeter \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua index 0946ad161b..7cfbae4f56 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -1,13 +1,28 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + local st_device = require "st.device" local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass.Meter -local Meter = (require "st.zwave.CommandClass.Meter")({ version=6 }) +local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) --- @type st.zwave.CommandClass local cc = require "st.zwave.CommandClass" +local utils = require "st.utils" local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { - { mfr = 0x0371, prod = 0x0003, model = 0x0033 }, -- HEM Gen8 1 Phase EU - { mfr = 0x0371, prod = 0x0102, model = 0x002E } -- HEM Gen8 1 Phase AU + { mfr = 0x0371, prod = 0x0003, model = 0x0033 }, -- HEM Gen8 1 Phase EU + { mfr = 0x0371, prod = 0x0102, model = 0x002E } -- HEM Gen8 1 Phase AU } local LAST_REPORT_TIME = "LAST_REPORT_TIME" @@ -15,7 +30,7 @@ local POWER_UNIT_WATT = "W" local ENERGY_UNIT_KWH = "kWh" local HEM8_DEVICES = { - { profile = 'aeotec-home-energy-meter-gen8-3-phase-con', name = 'Aeotec Home Energy Meter 8 Consumption', endpoints = { 1, 3 } }, + { profile = 'aeotec-home-energy-meter-gen8-1-phase-con', name = 'Aeotec Home Energy Meter 8 Consumption', endpoints = { 1, 3 } }, { profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2, 4 } }, { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 5 } }, { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 6 } } @@ -31,96 +46,75 @@ local function can_handle_aeotec_meter_gen8_1_phase(opts, driver, device, ...) end local function find_hem8_child_device_key_by_endpoint(endpoint) - for _, child in ipairs(HEM8_DEVICES) do - if child.endpoints then - for _, e in ipairs(child.endpoints) do - if e == endpoint then - return child.child_key - end + for _, child in ipairs(HEM8_DEVICES) do + if child.endpoints then + for _, e in ipairs(child.endpoints) do + if e == endpoint then + return child.child_key end end end + end end local function emit_power_consumption_report_event(device, value, channel) - -- powerConsumptionReport report interval - local current_time = os.time() - local last_time = device:get_field(LAST_REPORT_TIME) or 0 - local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports - if current_time < next_time then - return - end - device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) - local raw_value = value.value * 1000 -- 'Wh' - - local delta_energy = 0.0 - local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, - capabilities.powerConsumptionReport.powerConsumption.NAME) - if current_power_consumption ~= nil then - delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) - end - device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ - energy = raw_value, - deltaEnergy = delta_energy - })) + -- powerConsumptionReport report interval + local current_time = os.time() + local last_time = device:get_field(LAST_REPORT_TIME) or 0 + local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports + if current_time < next_time then + return + end + device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) + local raw_value = value.value * 1000 -- 'Wh' + + local delta_energy = 0.0 + local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, capabilities.powerConsumptionReport.powerConsumption.NAME) + if current_power_consumption ~= nil then + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + end + device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ + energy = raw_value, + deltaEnergy = delta_energy + })) end local function meter_report_handler(driver, device, cmd, zb_rx) - local endpoint = cmd.src_channel - - local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); - local child_device = device:get_child_by_parent_assigned_key(child_device_key) - - if child_device then - if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then - local event_arguments = { - value = cmd.args.meter_value, - unit = ENERGY_UNIT_KWH - } - -- energyMeter - child_device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.energyMeter.energy(event_arguments) - ) - - if endpoint == 5 then - -- powerConsumptionReport - emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) - end - elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then - local event_arguments = { - value = cmd.args.meter_value, - unit = POWER_UNIT_WATT - } - -- powerMeter - child_device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.powerMeter.power(event_arguments) - ) - end - else - if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then - local event_arguments = { - value = cmd.args.meter_value, - unit = ENERGY_UNIT_KWH - } - -- energyMeter - device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.energyMeter.energy(event_arguments) - ) - elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then - local event_arguments = { - value = cmd.args.meter_value, - unit = POWER_UNIT_WATT - } - -- powerMeter - device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.powerMeter.power(event_arguments) - ) - end + local endpoint = cmd.src_channel + local device_to_emit_with = device + local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); + local child_device = device:get_child_by_parent_assigned_key(child_device_key) + + if(child_device) then + device_to_emit_with = child_device + end + + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + device_to_emit_with:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + + if endpoint == 5 then + -- powerConsumptionReport + emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) end + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + device_to_emit_with:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end end local function do_refresh(self, device) @@ -168,7 +162,7 @@ local function device_added(driver, device) end end end - do_refresh(self, device) + do_refresh(driver, device) end local aeotec_home_energy_meter_gen8_1_phase = { @@ -178,7 +172,7 @@ local aeotec_home_energy_meter_gen8_1_phase = { }, capability_handlers = { [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh + [capabilities.refresh.commands.refresh.NAME] = do_refresh } }, zwave_handlers = { diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua index 4060863cfa..fd6f316de1 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua @@ -1,9 +1,24 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + local st_device = require "st.device" local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass.Meter -local Meter = (require "st.zwave.CommandClass.Meter")({ version=6 }) +local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) --- @type st.zwave.CommandClass local cc = require "st.zwave.CommandClass" +local utils = require "st.utils" local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { { mfr = 0x0371, prod = 0x0103, model = 0x002E } -- HEM Gen8 2 Phase US @@ -30,97 +45,75 @@ local function can_handle_aeotec_meter_gen8_2_phase(opts, driver, device, ...) end local function find_hem8_child_device_key_by_endpoint(endpoint) - for _, child in ipairs(HEM8_DEVICES) do - if child.endpoints then - for _, e in ipairs(child.endpoints) do - if e == endpoint then - return child.child_key - end + for _, child in ipairs(HEM8_DEVICES) do + if child.endpoints then + for _, e in ipairs(child.endpoints) do + if e == endpoint then + return child.child_key end end end + end end local function emit_power_consumption_report_event(device, value, channel) - -- powerConsumptionReport report interval - local current_time = os.time() - local last_time = device:get_field(LAST_REPORT_TIME) or 0 - local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports - if current_time < next_time then - return - end - device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) - local raw_value = value.value * 1000 -- 'Wh' - - local delta_energy = 0.0 - local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, - capabilities.powerConsumptionReport.powerConsumption.NAME) - if current_power_consumption ~= nil then - delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) - end - device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ - energy = raw_value, - deltaEnergy = delta_energy - })) + -- powerConsumptionReport report interval + local current_time = os.time() + local last_time = device:get_field(LAST_REPORT_TIME) or 0 + local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports + if current_time < next_time then + return + end + device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) + local raw_value = value.value * 1000 -- 'Wh' + + local delta_energy = 0.0 + local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, capabilities.powerConsumptionReport.powerConsumption.NAME) + if current_power_consumption ~= nil then + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + end + device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ + energy = raw_value, + deltaEnergy = delta_energy + })) end local function meter_report_handler(driver, device, cmd, zb_rx) - local endpoint = cmd.src_channel - - local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); - local child_device = device:get_child_by_parent_assigned_key(child_device_key) - - if child_device then - if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then - local event_arguments = { - value = cmd.args.meter_value, - unit = ENERGY_UNIT_KWH - } - -- energyMeter - child_device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.energyMeter.energy(event_arguments) - ) - - if endpoint == 7 then - -- powerConsumptionReport - emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) - end - elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then - local event_arguments = { - value = cmd.args.meter_value, - unit = POWER_UNIT_WATT - } - -- powerMeter - child_device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.powerMeter.power(event_arguments) - ) - end - else - if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then - local event_arguments = { - value = cmd.args.meter_value, - unit = ENERGY_UNIT_KWH - } - -- energyMeter - device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.energyMeter.energy(event_arguments) - ) - elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then - local event_arguments = { - value = cmd.args.meter_value, - unit = POWER_UNIT_WATT - } - -- powerMeter - device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.powerMeter.power(event_arguments) - ) - end - end + local endpoint = cmd.src_channel + local device_to_emit_with = device + local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); + local child_device = device:get_child_by_parent_assigned_key(child_device_key) + if(child_device) then + device_to_emit_with = child_device + end + + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + device_to_emit_with:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + + if endpoint == 7 then + -- powerConsumptionReport + emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) + end + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + device_to_emit_with:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end end local function do_refresh(self, device) @@ -165,7 +158,7 @@ local function device_added(driver, device) end end end - do_refresh(self, device) + do_refresh(driver, device) end local aeotec_home_energy_meter_gen8_2_phase = { diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua index 89463a3f91..3858a0c924 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua @@ -1,15 +1,28 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + local st_device = require "st.device" local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass.Meter local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) --- @type st.zwave.CommandClass local cc = require "st.zwave.CommandClass" -local zw = require "st.zwave" local utils = require "st.utils" local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { - { mfr = 0x0371, prod = 0x0003, model = 0x0034 }, -- HEM Gen8 3 Phase EU - { mfr = 0x0371, prod = 0x0102, model = 0x0034 } -- HEM Gen8 3 Phase AU + { mfr = 0x0371, prod = 0x0003, model = 0x0034 }, -- HEM Gen8 3 Phase EU + { mfr = 0x0371, prod = 0x0102, model = 0x0034 } -- HEM Gen8 3 Phase AU } local LAST_REPORT_TIME = "LAST_REPORT_TIME" @@ -45,83 +58,64 @@ local function find_hem8_child_device_key_by_endpoint(endpoint) end local function emit_power_consumption_report_event(device, value, channel) - -- powerConsumptionReport report interval - local current_time = os.time() - local last_time = device:get_field(LAST_REPORT_TIME) or 0 - local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports - if current_time < next_time then - return - end - device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) - local raw_value = value.value * 1000 -- 'Wh' - - local delta_energy = 0.0 - local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, - capabilities.powerConsumptionReport.powerConsumption.NAME) - if current_power_consumption ~= nil then - delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) - end - device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ - energy = raw_value, - deltaEnergy = delta_energy - })) + -- powerConsumptionReport report interval + local current_time = os.time() + local last_time = device:get_field(LAST_REPORT_TIME) or 0 + local next_time = last_time + 60 * 15 -- 15 mins, the minimum interval allowed between reports + if current_time < next_time then + return + end + device:set_field(LAST_REPORT_TIME, current_time, { persist = true }) + local raw_value = value.value * 1000 -- 'Wh' + + local delta_energy = 0.0 + local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, + capabilities.powerConsumptionReport.powerConsumption.NAME) + if current_power_consumption ~= nil then + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + end + device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ + energy = raw_value, + deltaEnergy = delta_energy + })) end local function meter_report_handler(driver, device, cmd, zb_rx) - local endpoint = cmd.src_channel - local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); - local child_device = device:get_child_by_parent_assigned_key(child_device_key) - - if child_device then - if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then - local event_arguments = { - value = cmd.args.meter_value, - unit = ENERGY_UNIT_KWH - } - -- energyMeter - child_device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.energyMeter.energy(event_arguments) - ) - - if endpoint == 9 then - -- powerConsumptionReport - emit_power_consumption_report_event(child_device, { value = event_arguments.value }, endpoint) - end - elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then - local event_arguments = { - value = cmd.args.meter_value, - unit = POWER_UNIT_WATT - } - -- powerMeter - child_device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.powerMeter.power(event_arguments) - ) - end - else - if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then - local event_arguments = { - value = cmd.args.meter_value, - unit = ENERGY_UNIT_KWH - } - -- energyMeter - device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.energyMeter.energy(event_arguments) - ) - elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then - local event_arguments = { - value = cmd.args.meter_value, - unit = POWER_UNIT_WATT - } - -- powerMeter - device:emit_event_for_endpoint( - cmd.src_channel, - capabilities.powerMeter.power(event_arguments) - ) - end + local endpoint = cmd.src_channel + local device_to_emit_with = device + local child_device_key = find_hem8_child_device_key_by_endpoint(endpoint); + local child_device = device:get_child_by_parent_assigned_key(child_device_key) + + if(child_device) then + device_to_emit_with = child_device + end + + if cmd.args.scale == Meter.scale.electric_meter.KILOWATT_HOURS then + local event_arguments = { + value = cmd.args.meter_value, + unit = ENERGY_UNIT_KWH + } + -- energyMeter + device_to_emit_with:emit_event_for_endpoint( + cmd.src_channel, + capabilities.energyMeter.energy(event_arguments) + ) + + if endpoint == 9 then + -- powerConsumptionReport + emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) end + elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then + local event_arguments = { + value = cmd.args.meter_value, + unit = POWER_UNIT_WATT + } + -- powerMeter + device_to_emit_with:emit_event_for_endpoint( + cmd.src_channel, + capabilities.powerMeter.power(event_arguments) + ) + end end local function do_refresh(self, device) @@ -169,7 +163,7 @@ local function device_added(driver, device) end end end - do_refresh(self, device) + do_refresh(driver, device) end local aeotec_home_energy_meter_gen8_3_phase = { @@ -179,7 +173,7 @@ local aeotec_home_energy_meter_gen8_3_phase = { }, capability_handlers = { [capabilities.refresh.ID] = { - [capabilities.refresh.commands.refresh.NAME] = do_refresh + [capabilities.refresh.commands.refresh.NAME] = do_refresh } }, zwave_handlers = { diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua index db11d13c71..4506fda378 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua @@ -1,3 +1,17 @@ +-- Copyright 2022 SmartThings +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. + local AEOTEC_HOME_ENERGY_METER_GEN8_FINGERPRINTS = { { mfr = 0x0371, prod = 0x0003, model = 0x0033 }, -- HEM Gen8 1 Phase EU { mfr = 0x0371, prod = 0x0003, model = 0x0034 }, -- HEM Gen8 3 Phase EU diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua index 872410cc51..2e87841e5e 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua @@ -12,11 +12,12 @@ -- See the License for the specific language governing permissions and -- limitations under the License. +local st_utils = require "st.utils" local test = require "integration_test" local capabilities = require "st.capabilities" local zw = require "st.zwave" local zw_test_utils = require "integration_test.zwave_test_utils" -local Meter = (require "st.zwave.CommandClass.Meter")({version=3}) +local Meter = (require "st.zwave.CommandClass.Meter")({version=4}) local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) local t_utils = require "integration_test.utils" @@ -34,14 +35,34 @@ local aeotec_meter_endpoints = { } } -local HEM8_CHILDS = { - { profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2 } }, - { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 5 } }, - { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 6 } } +local HEM8_DEVICES = { + { + profile = 'aeotec-home-energy-meter-gen8-1-phase-con', + name = 'Aeotec Home Energy Meter 8 Consumption', + endpoints = { 1, 3 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', + name = 'Aeotec Home Energy Meter 8 Production', + child_key = 'pro', + endpoints = { 2, 4 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-sald-con', + name = 'Aeotec Home Energy Meter 8 Settled Consumption', + child_key = 'sald-con', + endpoints = { 5 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-sald-pro', + name = 'Aeotec Home Energy Meter 8 Settled Production', + child_key = 'sald-pro', + endpoints = { 6 } + } } local mock_parent = test.mock_device.build_test_zwave_device({ - profile = t_utils.get_profile_definition("aeotec-home-energy-meter-gen8-1-phase-con.yml"), + profile = t_utils.get_profile_definition(HEM8_DEVICES[1].profile .. '.yml'), zwave_endpoints = aeotec_meter_endpoints, zwave_manufacturer_id = AEOTEC_MFR_ID, zwave_product_type = AEOTEC_METER_PROD_TYPE, @@ -49,24 +70,23 @@ local mock_parent = test.mock_device.build_test_zwave_device({ }) local mock_child_prod = test.mock_device.build_test_child_device({ - profile = t_utils.get_profile_definition(HEM8_CHILDS[1].profile .. '.yml'), + profile = t_utils.get_profile_definition(HEM8_DEVICES[2].profile .. '.yml'), parent_device_id = mock_parent.id, - parent_assigned_child_key = HEM8_CHILDS[1].child_key + parent_assigned_child_key = HEM8_DEVICES[2].child_key }) local mock_child_sald_con = test.mock_device.build_test_child_device({ - profile = t_utils.get_profile_definition(HEM8_CHILDS[2].profile .. '.yml'), + profile = t_utils.get_profile_definition(HEM8_DEVICES[3].profile .. '.yml'), parent_device_id = mock_parent.id, - parent_assigned_child_key = HEM8_CHILDS[2].child_key + parent_assigned_child_key = HEM8_DEVICES[3].child_key }) local mock_child_sald_prod = test.mock_device.build_test_child_device({ - profile = t_utils.get_profile_definition(HEM8_CHILDS[3].profile .. '.yml'), + profile = t_utils.get_profile_definition(HEM8_DEVICES[4].profile .. '.yml'), parent_device_id = mock_parent.id, - parent_assigned_child_key = HEM8_CHILDS[3].child_key + parent_assigned_child_key = HEM8_DEVICES[4].child_key }) - local function test_init() test.mock_device.add_test_device(mock_parent) test.mock_device.add_test_device(mock_child_prod) @@ -76,122 +96,175 @@ end test.set_test_init_function(test_init) -test.register_message_test( - "Power meter report should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ - scale = Meter.scale.electric_meter.WATTS, - meter_value = 27}) - )} - }, - { - channel = "capability", - direction = "send", - message = mock_parent:generate_test_message("main", capabilities.powerMeter.power({ value = 27, unit = "W" })) - } - } +test.register_coroutine_test( + "Added lifecycle event should create children for parent device", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) + + for _, child in ipairs(HEM8_DEVICES) do + if(child["child_key"]) then + mock_parent:expect_device_create( + { + type = "EDGE_CHILD", + label = child.name, + profile = child.profile, + parent_device_id = mock_parent.id, + parent_assigned_child_key = child.child_key + } + ) + end + end + -- Refresh + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end + end ) -test.register_message_test( - "Energy meter report should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ - scale = Meter.scale.electric_meter.KILOWATT_HOURS, - meter_value = 5}) - )} - }, - { - channel = "capability", - direction = "send", - message = mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) - } - } +test.register_coroutine_test( + "Power meter report should be handled", + function() + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + local component = "main" + if endpoint ~= 3 and endpoint ~= 4 and endpoint ~= 5 and endpoint ~= 6 then + component = string.format("clamp%d", endpoint) + end + test.socket.zwave:__queue_receive({ + mock_parent.id, + Meter:Report({ + scale = Meter.scale.electric_meter.WATTS, + meter_value = 27 + }, { + encap = zw.ENCAP.AUTO, + src_channel = endpoint, + dst_channels = {0} + }) + }) + if(device["child_key"]) then + if(device["child_key"] == "pro") then + test.socket.capability:__expect_send( + mock_child_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + elseif (device["child_key"] == "sald-pro") then + test.socket.capability:__expect_send( + mock_child_sald_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + elseif (device["child_key"] == "sald-con") then + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + end + else + test.socket.capability:__expect_send( + mock_parent:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + end + end + end + end ) -test.register_message_test( - "Device should be polled at inclusion", - { - { - channel = "device_lifecycle", - direction = "receive", - message = { mock_parent.id, "added" }, - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_parent, - Meter:Get({scale = Meter.scale.electric_meter.WATTS}) - ) - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_parent, - Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}) - ) - }, - }, - { - inner_block_ordering = "relaxed" - } +test.register_coroutine_test( + "Energy meter report should be handled", + function() + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + local component = "main" + if endpoint ~= 3 and endpoint ~= 4 and endpoint ~= 5 and endpoint ~= 6 then + component = string.format("clamp%d", endpoint) + end + test.socket.zwave:__queue_receive({ + mock_parent.id, + Meter:Report({ + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + }, { + encap = zw.ENCAP.AUTO, + src_channel = endpoint, + dst_channels = {0} + }) + }) + if(device["child_key"]) then + if(device["child_key"] == "pro") then + test.socket.capability:__expect_send( + mock_child_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + elseif (device["child_key"] == "sald-pro") then + test.socket.capability:__expect_send( + mock_child_sald_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + elseif (device["child_key"] == "sald-con") then + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + end + else + test.socket.capability:__expect_send( + mock_parent:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + end + end + end + end ) test.register_coroutine_test( "Report consumption and power consumption report after 15 minutes", function() -- set time to trigger power consumption report local current_time = os.time() - 60 * 20 - mock_parent:set_field(LAST_REPORT_TIME, current_time) + mock_child_sald_con:set_field(LAST_REPORT_TIME, current_time) test.socket.zwave:__queue_receive( { - mock_parent.id, + mock_child_sald_con.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report( - { - scale = Meter.scale.electric_meter.KILOWATT_HOURS, - meter_value = 5 - })) + { + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + }, + { + encap = zw.ENCAP.AUTO, + src_channel = 5, + dst_channels = {0} + } + )) } ) test.socket.capability:__expect_send( - mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + mock_child_sald_con:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) ) test.socket.capability:__expect_send( - mock_parent:generate_test_message("main", + mock_child_sald_con:generate_test_message("main", capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) ) end ) -test.register_coroutine_test( - "Added lifecycle event should create children for parent device", - function() - test.socket.zwave:__set_channel_ordering("relaxed") - test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) - - for _, child in ipairs(HEM8_CHILDS) do - mock_parent:expect_device_create( - { - type = "EDGE_CHILD", - label = child.name, - profile = child.profile, - parent_device_id = mock_parent.id, - parent_assigned_child_key = child.child_key - } - ) - end - end -) - test.register_coroutine_test( "Handle preference: thresholdCheck (parameter 3) in infoChanged", function() @@ -264,54 +337,6 @@ test.register_coroutine_test( end ) -test.register_coroutine_test( - "Handle preference: imWThresholdPhaseB (parameter 6) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - imWThresholdPhaseB = 3500 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 6, - configuration_value = 3500, - size = 2 - }) - ) - ) - end -) - -test.register_coroutine_test( - "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - imWThresholdPhaseC = 3500 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 7, - configuration_value = 3500, - size = 2 - }) - ) - ) - end -) - test.register_coroutine_test( "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", function() @@ -360,54 +385,6 @@ test.register_coroutine_test( end ) -test.register_coroutine_test( - "Handle preference: exWThresholdPhaseB (parameter 10) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - exWThresholdPhaseB = 3500 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 10, - configuration_value = 3500, - size = 2 - }) - ) - ) - end -) - -test.register_coroutine_test( - "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - exWThresholdPhaseC = 3500 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 11, - configuration_value = 3500, - size = 2 - }) - ) - ) - end -) - test.register_coroutine_test( "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", function() @@ -456,54 +433,6 @@ test.register_coroutine_test( end ) -test.register_coroutine_test( - "Handle preference: imWPctThresholdPhaseB (parameter 14) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - imWPctThresholdPhaseB = 50 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 14, - configuration_value = 50, - size = 1 - }) - ) - ) - end -) - -test.register_coroutine_test( - "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - imWPctThresholdPhaseC = 50 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 15, - configuration_value = 50, - size = 1 - }) - ) - ) - end -) - test.register_coroutine_test( "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", function() @@ -553,12 +482,12 @@ test.register_coroutine_test( ) test.register_coroutine_test( - "Handle preference: exWPctThresholdPhaseB (parameter 18) in infoChanged", + "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", function() test.socket.device_lifecycle:__queue_receive( mock_parent:generate_info_changed({ preferences = { - exWPctThresholdPhaseB = 50 + autoRootDeviceReport = 1 } }) ) @@ -567,8 +496,8 @@ test.register_coroutine_test( zw_test_utils.zwave_test_build_send_command( mock_parent, Configuration:Set({ - parameter_number = 18, - configuration_value = 50, + parameter_number = 32, + configuration_value = 1, size = 1 }) ) @@ -577,51 +506,42 @@ test.register_coroutine_test( ) test.register_coroutine_test( - "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", + "Refresh sends commands to all components including base device", function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - exWPctThresholdPhaseC = 50 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 19, - configuration_value = 50, - size = 1 - }) - ) - ) - end -) + -- refresh commands for zwave devices do not have guaranteed ordering + test.socket.zwave:__set_channel_ordering("relaxed") + + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) -test.register_coroutine_test( - "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - autoRootDeviceReport = 1 - } - }) - ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 32, - configuration_value = 1, - size = 1 - }) - ) - ) + test.socket.capability:__queue_receive({ + mock_parent.id, + { capability = "refresh", component = "main", command = "refresh", args = { } } + }) end ) -test.run_registered_tests() +test.run_registered_tests() \ No newline at end of file diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua index fb1f5c2a3d..a2043e2b20 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua @@ -12,17 +12,18 @@ -- See the License for the specific language governing permissions and -- limitations under the License. +local st_utils = require "st.utils" local test = require "integration_test" local capabilities = require "st.capabilities" local zw = require "st.zwave" local zw_test_utils = require "integration_test.zwave_test_utils" -local Meter = (require "st.zwave.CommandClass.Meter")({version=3}) +local Meter = (require "st.zwave.CommandClass.Meter")({version=4}) local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) local t_utils = require "integration_test.utils" local AEOTEC_MFR_ID = 0x0371 -local AEOTEC_METER_PROD_TYPE = 0x0003 -local AEOTEC_METER_PROD_ID = 0x0033 +local AEOTEC_METER_PROD_TYPE = 0x0103 +local AEOTEC_METER_PROD_ID = 0x002E local LAST_REPORT_TIME = "LAST_REPORT_TIME" @@ -34,14 +35,34 @@ local aeotec_meter_endpoints = { } } -local HEM8_CHILDS = { - { profile = 'aeotec-home-energy-meter-gen8-1-phase-pro', name = 'Aeotec Home Energy Meter 8 Production', child_key = 'pro', endpoints = { 2, 4, 6 } }, - { profile = 'aeotec-home-energy-meter-gen8-sald-con', name = 'Aeotec Home Energy Meter 8 Settled Consumption', child_key = 'sald-con', endpoints = { 7 } }, - { profile = 'aeotec-home-energy-meter-gen8-sald-pro', name = 'Aeotec Home Energy Meter 8 Settled Production', child_key = 'sald-pro', endpoints = { 8 } } +local HEM8_DEVICES = { + { + profile = 'aeotec-home-energy-meter-gen8-2-phase-con', + name = 'Aeotec Home Energy Meter 8 Consumption', + endpoints = { 1, 3, 5 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-2-phase-pro', + name = 'Aeotec Home Energy Meter 8 Production', + child_key = 'pro', + endpoints = { 2, 4, 6 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-sald-con', + name = 'Aeotec Home Energy Meter 8 Settled Consumption', + child_key = 'sald-con', + endpoints = { 7 } + }, + { + profile = 'aeotec-home-energy-meter-gen8-sald-pro', + name = 'Aeotec Home Energy Meter 8 Settled Production', + child_key = 'sald-pro', + endpoints = { 8 } + } } local mock_parent = test.mock_device.build_test_zwave_device({ - profile = t_utils.get_profile_definition("aeotec-home-energy-meter-gen8-1-phase-con.yml"), + profile = t_utils.get_profile_definition(HEM8_DEVICES[1].profile .. '.yml'), zwave_endpoints = aeotec_meter_endpoints, zwave_manufacturer_id = AEOTEC_MFR_ID, zwave_product_type = AEOTEC_METER_PROD_TYPE, @@ -49,24 +70,23 @@ local mock_parent = test.mock_device.build_test_zwave_device({ }) local mock_child_prod = test.mock_device.build_test_child_device({ - profile = t_utils.get_profile_definition(HEM8_CHILDS[1].profile .. '.yml'), + profile = t_utils.get_profile_definition(HEM8_DEVICES[2].profile .. '.yml'), parent_device_id = mock_parent.id, - parent_assigned_child_key = HEM8_CHILDS[1].child_key + parent_assigned_child_key = HEM8_DEVICES[2].child_key }) local mock_child_sald_con = test.mock_device.build_test_child_device({ - profile = t_utils.get_profile_definition(HEM8_CHILDS[2].profile .. '.yml'), + profile = t_utils.get_profile_definition(HEM8_DEVICES[3].profile .. '.yml'), parent_device_id = mock_parent.id, - parent_assigned_child_key = HEM8_CHILDS[2].child_key + parent_assigned_child_key = HEM8_DEVICES[3].child_key }) local mock_child_sald_prod = test.mock_device.build_test_child_device({ - profile = t_utils.get_profile_definition(HEM8_CHILDS[3].profile .. '.yml'), + profile = t_utils.get_profile_definition(HEM8_DEVICES[4].profile .. '.yml'), parent_device_id = mock_parent.id, - parent_assigned_child_key = HEM8_CHILDS[3].child_key + parent_assigned_child_key = HEM8_DEVICES[4].child_key }) - local function test_init() test.mock_device.add_test_device(mock_parent) test.mock_device.add_test_device(mock_child_prod) @@ -76,122 +96,175 @@ end test.set_test_init_function(test_init) -test.register_message_test( - "Power meter report should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ - scale = Meter.scale.electric_meter.WATTS, - meter_value = 27}) - )} - }, - { - channel = "capability", - direction = "send", - message = mock_parent:generate_test_message("main", capabilities.powerMeter.power({ value = 27, unit = "W" })) - } - } +test.register_coroutine_test( + "Added lifecycle event should create children for parent device", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) + + for _, child in ipairs(HEM8_DEVICES) do + if(child["child_key"]) then + mock_parent:expect_device_create( + { + type = "EDGE_CHILD", + label = child.name, + profile = child.profile, + parent_device_id = mock_parent.id, + parent_assigned_child_key = child.child_key + } + ) + end + end + -- Refresh + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end + end ) -test.register_message_test( - "Energy meter report should be handled", - { - { - channel = "zwave", - direction = "receive", - message = { mock_parent.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report({ - scale = Meter.scale.electric_meter.KILOWATT_HOURS, - meter_value = 5}) - )} - }, - { - channel = "capability", - direction = "send", - message = mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) - } - } +test.register_coroutine_test( + "Power meter report should be handled", + function() + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + local component = "main" + if endpoint ~= 5 and endpoint ~= 6 and endpoint ~= 7 and endpoint ~= 8 then + component = string.format("clamp%d", endpoint) + end + test.socket.zwave:__queue_receive({ + mock_parent.id, + Meter:Report({ + scale = Meter.scale.electric_meter.WATTS, + meter_value = 27 + }, { + encap = zw.ENCAP.AUTO, + src_channel = endpoint, + dst_channels = {0} + }) + }) + if(device["child_key"]) then + if(device["child_key"] == "pro") then + test.socket.capability:__expect_send( + mock_child_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + elseif (device["child_key"] == "sald-pro") then + test.socket.capability:__expect_send( + mock_child_sald_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + elseif (device["child_key"] == "sald-con") then + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + end + else + test.socket.capability:__expect_send( + mock_parent:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + end + end + end + end ) -test.register_message_test( - "Device should be polled at inclusion", - { - { - channel = "device_lifecycle", - direction = "receive", - message = { mock_parent.id, "added" }, - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_parent, - Meter:Get({scale = Meter.scale.electric_meter.WATTS}) - ) - }, - { - channel = "zwave", - direction = "send", - message = zw_test_utils.zwave_test_build_send_command( - mock_parent, - Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}) - ) - }, - }, - { - inner_block_ordering = "relaxed" - } +test.register_coroutine_test( + "Energy meter report should be handled", + function() + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + local component = "main" + if endpoint ~= 5 and endpoint ~= 6 and endpoint ~= 7 and endpoint ~= 8 then + component = string.format("clamp%d", endpoint) + end + test.socket.zwave:__queue_receive({ + mock_parent.id, + Meter:Report({ + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + }, { + encap = zw.ENCAP.AUTO, + src_channel = endpoint, + dst_channels = {0} + }) + }) + if(device["child_key"]) then + if(device["child_key"] == "pro") then + test.socket.capability:__expect_send( + mock_child_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + elseif (device["child_key"] == "sald-pro") then + test.socket.capability:__expect_send( + mock_child_sald_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + elseif (device["child_key"] == "sald-con") then + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + end + else + test.socket.capability:__expect_send( + mock_parent:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + end + end + end + end ) test.register_coroutine_test( "Report consumption and power consumption report after 15 minutes", function() -- set time to trigger power consumption report local current_time = os.time() - 60 * 20 - mock_parent:set_field(LAST_REPORT_TIME, current_time) + mock_child_sald_con:set_field(LAST_REPORT_TIME, current_time) test.socket.zwave:__queue_receive( { - mock_parent.id, + mock_child_sald_con.id, zw_test_utils.zwave_test_build_receive_command(Meter:Report( - { - scale = Meter.scale.electric_meter.KILOWATT_HOURS, - meter_value = 5 - })) + { + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + }, + { + encap = zw.ENCAP.AUTO, + src_channel = 7, + dst_channels = {0} + } + )) } ) test.socket.capability:__expect_send( - mock_parent:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + mock_child_sald_con:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) ) test.socket.capability:__expect_send( - mock_parent:generate_test_message("main", + mock_child_sald_con:generate_test_message("main", capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) ) end ) -test.register_coroutine_test( - "Added lifecycle event should create children for parent device", - function() - test.socket.zwave:__set_channel_ordering("relaxed") - test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) - - for _, child in ipairs(HEM8_CHILDS) do - mock_parent:expect_device_create( - { - type = "EDGE_CHILD", - label = child.name, - profile = child.profile, - parent_device_id = mock_parent.id, - parent_assigned_child_key = child.child_key - } - ) - end - end -) - test.register_coroutine_test( "Handle preference: thresholdCheck (parameter 3) in infoChanged", function() @@ -288,30 +361,6 @@ test.register_coroutine_test( end ) -test.register_coroutine_test( - "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - imWThresholdPhaseC = 3500 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 7, - configuration_value = 3500, - size = 2 - }) - ) - ) - end -) - test.register_coroutine_test( "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", function() @@ -384,30 +433,6 @@ test.register_coroutine_test( end ) -test.register_coroutine_test( - "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - exWThresholdPhaseC = 3500 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 11, - configuration_value = 3500, - size = 2 - }) - ) - ) - end -) - test.register_coroutine_test( "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", function() @@ -480,30 +505,6 @@ test.register_coroutine_test( end ) -test.register_coroutine_test( - "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", - function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - imWPctThresholdPhaseC = 50 - } - }) - ) - - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 15, - configuration_value = 50, - size = 1 - }) - ) - ) - end -) - test.register_coroutine_test( "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", function() @@ -577,12 +578,12 @@ test.register_coroutine_test( ) test.register_coroutine_test( - "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", + "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", function() test.socket.device_lifecycle:__queue_receive( mock_parent:generate_info_changed({ preferences = { - exWPctThresholdPhaseC = 50 + autoRootDeviceReport = 1 } }) ) @@ -591,8 +592,8 @@ test.register_coroutine_test( zw_test_utils.zwave_test_build_send_command( mock_parent, Configuration:Set({ - parameter_number = 19, - configuration_value = 50, + parameter_number = 32, + configuration_value = 1, size = 1 }) ) @@ -601,26 +602,41 @@ test.register_coroutine_test( ) test.register_coroutine_test( - "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", + "Refresh sends commands to all components including base device", function() - test.socket.device_lifecycle:__queue_receive( - mock_parent:generate_info_changed({ - preferences = { - autoRootDeviceReport = 1 - } - }) - ) + -- refresh commands for zwave devices do not have guaranteed ordering + test.socket.zwave:__set_channel_ordering("relaxed") + + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Configuration:Set({ - parameter_number = 32, - configuration_value = 1, - size = 1 - }) - ) - ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end + + test.socket.capability:__queue_receive({ + mock_parent.id, + { capability = "refresh", component = "main", command = "refresh", args = { } } + }) end ) diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua index f927de899c..250bb23b98 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua @@ -12,9 +12,7 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -local log = require "log" local st_utils = require "st.utils" - local test = require "integration_test" local capabilities = require "st.capabilities" local zw = require "st.zwave" @@ -99,857 +97,643 @@ end test.set_test_init_function(test_init) test.register_coroutine_test( - "Added lifecycle event should create children for parent device", - function() - test.socket.zwave:__set_channel_ordering("relaxed") - test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) - - for _, child in ipairs(HEM8_DEVICES) do - if(child["child_key"]) then - mock_parent:expect_device_create( - { - type = "EDGE_CHILD", - label = child.name, - profile = child.profile, - parent_device_id = mock_parent.id, - parent_assigned_child_key = child.child_key - } + "Added lifecycle event should create children for parent device", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "added" }) + + for _, child in ipairs(HEM8_DEVICES) do + if(child["child_key"]) then + mock_parent:expect_device_create( + { + type = "EDGE_CHILD", + label = child.name, + profile = child.profile, + parent_device_id = mock_parent.id, + parent_assigned_child_key = child.child_key + } + ) + end + end + -- Refresh + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end + end +) + +test.register_coroutine_test( + "Power meter report should be handled", + function() + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + local component = "main" + if endpoint ~= 7 and endpoint ~= 8 and endpoint ~= 9 and endpoint ~= 10 then + component = string.format("clamp%d", endpoint) + end + test.socket.zwave:__queue_receive({ + mock_parent.id, + Meter:Report({ + scale = Meter.scale.electric_meter.WATTS, + meter_value = 27 + }, { + encap = zw.ENCAP.AUTO, + src_channel = endpoint, + dst_channels = {0} + }) + }) + if(device["child_key"]) then + if(device["child_key"] == "pro") then + test.socket.capability:__expect_send( + mock_child_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + elseif (device["child_key"] == "sald-pro") then + test.socket.capability:__expect_send( + mock_child_sald_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + elseif (device["child_key"] == "sald-con") then + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) ) end + else + test.socket.capability:__expect_send( + mock_parent:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) + ) + end end - -- Refresh - for _, device in ipairs(HEM8_DEVICES) do - for _, endpoint in ipairs(device.endpoints) do - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { - encap = zw.ENCAP.AUTO, - src_channel = 0, - dst_channels = { endpoint } - }) + end + end +) + +test.register_coroutine_test( + "Energy meter report should be handled", + function() + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + local component = "main" + if endpoint ~= 7 and endpoint ~= 8 and endpoint ~= 9 and endpoint ~= 10 then + component = string.format("clamp%d", endpoint) + end + test.socket.zwave:__queue_receive({ + mock_parent.id, + Meter:Report({ + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + }, { + encap = zw.ENCAP.AUTO, + src_channel = endpoint, + dst_channels = {0} + }) + }) + if(device["child_key"]) then + if(device["child_key"] == "pro") then + test.socket.capability:__expect_send( + mock_child_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) ) - ) - test.socket.zwave:__expect_send( - zw_test_utils.zwave_test_build_send_command( - mock_parent, - Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { - encap = zw.ENCAP.AUTO, - src_channel = 0, - dst_channels = { endpoint } - }) + elseif (device["child_key"] == "sald-pro") then + test.socket.capability:__expect_send( + mock_child_sald_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + elseif (device["child_key"] == "sald-con") then + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) ) + end + else + test.socket.capability:__expect_send( + mock_parent:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) ) end end end + end +) + +test.register_coroutine_test( + "Report consumption and power consumption report after 15 minutes", function() + -- set time to trigger power consumption report + local current_time = os.time() - 60 * 20 + mock_child_sald_con:set_field(LAST_REPORT_TIME, current_time) + + test.socket.zwave:__queue_receive( + { + mock_child_sald_con.id, + zw_test_utils.zwave_test_build_receive_command(Meter:Report( + { + scale = Meter.scale.electric_meter.KILOWATT_HOURS, + meter_value = 5 + }, + { + encap = zw.ENCAP.AUTO, + src_channel = 9, + dst_channels = {0} + } + )) + } + ) + + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) + ) + + test.socket.capability:__expect_send( + mock_child_sald_con:generate_test_message("main", + capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) + ) + end +) + +test.register_coroutine_test( + "Handle preference: thresholdCheck (parameter 3) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + thresholdCheck = 0 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 3, + configuration_value = 0, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdTotal (parameter 4) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdTotal = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 4, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseA (parameter 5) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseA = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 5, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseB (parameter 6) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseB = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 6, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWThresholdPhaseC = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 7, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdTotal = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 8, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseA (parameter 9) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseA = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 9, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseB (parameter 10) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseB = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 10, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWThresholdPhaseC = 3500 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 11, + configuration_value = 3500, + size = 2 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imtWPctThresholdTotal = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 12, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseA (parameter 13) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseA = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 13, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseB (parameter 14) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseB = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 14, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + imWPctThresholdPhaseC = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 15, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdTotal = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 16, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdPhaseA (parameter 17) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseA = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 17, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: exWPctThresholdPhaseB (parameter 18) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseB = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 18, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + exWPctThresholdPhaseC = 50 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 19, + configuration_value = 50, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoRootDeviceReport = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 32, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Refresh sends commands to all components including base device", + function() + -- refresh commands for zwave devices do not have guaranteed ordering + test.socket.zwave:__set_channel_ordering("relaxed") + + for _, device in ipairs(HEM8_DEVICES) do + for _, endpoint in ipairs(device.endpoints) do + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.WATTS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, { + encap = zw.ENCAP.AUTO, + src_channel = 0, + dst_channels = { endpoint } + }) + ) + ) + end + end + + test.socket.capability:__queue_receive({ + mock_parent.id, + { capability = "refresh", component = "main", command = "refresh", args = { } } + }) + end ) --- test.register_coroutine_test( --- "Power meter report should be handled", --- function() --- for _, device in ipairs(HEM8_DEVICES) do --- for _, endpoint in ipairs(device.endpoints) do --- local component = "main" --- if endpoint ~= 7 and endpoint ~= 8 and endpoint ~= 9 and endpoint ~= 10 then --- component = string.format("clamp%d", endpoint) --- end --- test.socket.zwave:__queue_receive({ --- mock_parent.id, --- Meter:Report({ --- scale = Meter.scale.electric_meter.WATTS, --- meter_value = 27 --- }, { --- encap = zw.ENCAP.AUTO, --- src_channel = endpoint, --- dst_channels = {0} --- }) --- }) --- if(device["child_key"]) then --- if(device["child_key"] == "pro") then --- test.socket.capability:__expect_send( --- mock_child_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) --- ) --- elseif (device["child_key"] == "sald-pro") then --- test.socket.capability:__expect_send( --- mock_child_sald_prod:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) --- ) --- elseif (device["child_key"] == "sald-con") then --- test.socket.capability:__expect_send( --- mock_child_sald_con:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) --- ) --- end --- else --- test.socket.capability:__expect_send( --- mock_parent:generate_test_message(component, capabilities.powerMeter.power({ value = 27, unit = "W" })) --- ) --- end --- end --- end --- end --- ) - --- test.register_coroutine_test( --- "Energy meter report should be handled", --- function() --- for _, device in ipairs(HEM8_DEVICES) do --- for _, endpoint in ipairs(device.endpoints) do --- local component = "main" --- if endpoint ~= 7 and endpoint ~= 8 and endpoint ~= 9 and endpoint ~= 10 then --- component = string.format("clamp%d", endpoint) --- end --- test.socket.zwave:__queue_receive({ --- mock_parent.id, --- Meter:Report({ --- scale = Meter.scale.electric_meter.KILOWATT_HOURS, --- meter_value = 5 --- }, { --- encap = zw.ENCAP.AUTO, --- src_channel = endpoint, --- dst_channels = {0} --- }) --- }) --- if(device["child_key"]) then --- if(device["child_key"] == "pro") then --- test.socket.capability:__expect_send( --- mock_child_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) --- ) --- elseif (device["child_key"] == "sald-pro") then --- test.socket.capability:__expect_send( --- mock_child_sald_prod:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) --- ) --- elseif (device["child_key"] == "sald-con") then --- test.socket.capability:__expect_send( --- mock_child_sald_con:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) --- ) --- end --- else --- test.socket.capability:__expect_send( --- mock_parent:generate_test_message(component, capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) --- ) --- end --- end --- end --- end --- ) - --- test.register_coroutine_test( --- "Report consumption and power consumption report after 15 minutes", function() --- -- set time to trigger power consumption report --- local current_time = os.time() - 60 * 20 --- mock_child_sald_con:set_field(LAST_REPORT_TIME, current_time) - --- test.socket.zwave:__queue_receive( --- { --- mock_child_sald_con.id, --- zw_test_utils.zwave_test_build_receive_command(Meter:Report( --- { --- scale = Meter.scale.electric_meter.KILOWATT_HOURS, --- meter_value = 5 --- }, --- { --- encap = zw.ENCAP.AUTO, --- src_channel = 9, --- dst_channels = {0} --- } --- )) --- } --- ) - --- test.socket.capability:__expect_send( --- mock_child_sald_con:generate_test_message("main", capabilities.energyMeter.energy({ value = 5, unit = "kWh" })) --- ) - --- test.socket.capability:__expect_send( --- mock_child_sald_con:generate_test_message("main", --- capabilities.powerConsumptionReport.powerConsumption({ deltaEnergy = 0.0, energy = 5000 })) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: thresholdCheck (parameter 3) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- thresholdCheck = 0 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 3, --- configuration_value = 0, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWThresholdTotal (parameter 4) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWThresholdTotal = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 4, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWThresholdPhaseA (parameter 5) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWThresholdPhaseA = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 5, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWThresholdPhaseB (parameter 6) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWThresholdPhaseB = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 6, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWThresholdPhaseC (parameter 7) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWThresholdPhaseC = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 7, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWThresholdTotal (parameter 8) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWThresholdTotal = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 8, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWThresholdPhaseA (parameter 9) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWThresholdPhaseA = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 9, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWThresholdPhaseB (parameter 10) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWThresholdPhaseB = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 10, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWThresholdPhaseC (parameter 11) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWThresholdPhaseC = 3500 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 11, --- configuration_value = 3500, --- size = 2 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imtWPctThresholdTotal (parameter 12) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imtWPctThresholdTotal = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 12, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWPctThresholdPhaseA (parameter 13) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWPctThresholdPhaseA = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 13, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWPctThresholdPhaseB (parameter 14) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWPctThresholdPhaseB = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 14, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: imWPctThresholdPhaseC (parameter 15) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- imWPctThresholdPhaseC = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 15, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWPctThresholdTotal (parameter 16) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWPctThresholdTotal = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 16, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWPctThresholdPhaseA (parameter 17) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWPctThresholdPhaseA = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 17, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: exWPctThresholdPhaseB (parameter 18) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWPctThresholdPhaseB = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 18, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: thresholdCheck (exWPctThresholdPhaseC 19) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- exWPctThresholdPhaseC = 50 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 19, --- configuration_value = 50, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Handle preference: autoRootDeviceReport (parameter 32) in infoChanged", --- function() --- test.socket.device_lifecycle:__queue_receive( --- mock_parent:generate_info_changed({ --- preferences = { --- autoRootDeviceReport = 1 --- } --- }) --- ) - --- test.socket.zwave:__expect_send( --- zw_test_utils.zwave_test_build_send_command( --- mock_parent, --- Configuration:Set({ --- parameter_number = 32, --- configuration_value = 1, --- size = 1 --- }) --- ) --- ) --- end --- ) - --- test.register_coroutine_test( --- "Refresh sends commands to all components including base device", --- function() --- -- refresh commands for zwave devices do not have guaranteed ordering --- test.socket.zwave:__set_channel_ordering("relaxed") - --- -- {args={delta_time=0, meter_type="ELECTRIC_METER", meter_value=0.0, precision=3, rate_type="EXPORT", scale="WATTS", size=4}, cmd_class="METER", cmd_id="REPORT", dst_channels={0}, encap="S2_AUTH", payload="\x41\x74\x00\x00\x00\x00\x00\x00", src_channel=10, version=3} - --- test.socket.capability:__queue_receive({ --- mock_parent.id, --- { capability = "refresh", component = "main", command = "refresh", args = {} } --- }) - - -- test.socket.zwave:__expect_send( - -- zw_test_utils.zwave_test_build_send_command(mock_parent, Meter:Get({ - -- scale = Meter.scale.electric_meter.KILOWATT_HOURS - -- },{ - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {2} - -- })) - -- ) - - - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {0} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {0} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {1} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {1} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {2} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {2} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {3} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {3} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {4} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {4} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {5} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {5} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {6} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {6} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {7} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {7} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {8} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {8} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {9} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {9} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.KILOWATT_HOURS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {10} - -- }) - -- )) - - -- test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( - -- mock_parent, - -- Meter:Get({scale = Meter.scale.electric_meter.WATTS}, - -- { - -- encap = zw.ENCAP.AUTO, - -- src_channel = 0, - -- dst_channels = {10} - -- }) - -- )) - - -- test.socket.capability:__queue_receive({ - -- mock_parent.id, - -- { capability = "refresh", component = "main", command = "refresh", args = { } } - -- }) - --- end --- ) - -test.run_registered_tests() +test.run_registered_tests() \ No newline at end of file From c8b93bad56311358be325209e54c9cc8ec065cea Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Mon, 31 Mar 2025 09:13:59 +0200 Subject: [PATCH 05/11] remove unused imports --- .../src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua | 1 - .../src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua | 1 - .../src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua | 1 - 3 files changed, 3 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua index 2e87841e5e..88debaa87a 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua @@ -12,7 +12,6 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -local st_utils = require "st.utils" local test = require "integration_test" local capabilities = require "st.capabilities" local zw = require "st.zwave" diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua index a2043e2b20..b4702117eb 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua @@ -12,7 +12,6 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -local st_utils = require "st.utils" local test = require "integration_test" local capabilities = require "st.capabilities" local zw = require "st.zwave" diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua index 250bb23b98..a16b4e49cb 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua @@ -12,7 +12,6 @@ -- See the License for the specific language governing permissions and -- limitations under the License. -local st_utils = require "st.utils" local test = require "integration_test" local capabilities = require "st.capabilities" local zw = require "st.zwave" From ba4f6d48429aea082a483451b71f3c24c9e2fcc9 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Wed, 2 Apr 2025 15:53:27 +0200 Subject: [PATCH 06/11] update copyright year --- .../src/aeotec-home-energy-meter-gen8/1-phase/init.lua | 2 +- .../src/aeotec-home-energy-meter-gen8/2-phase/init.lua | 2 +- .../src/aeotec-home-energy-meter-gen8/3-phase/init.lua | 2 +- .../src/aeotec-home-energy-meter-gen8/init.lua | 2 +- .../src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua | 2 +- .../src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua | 2 +- .../src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua index 7cfbae4f56..68f416b643 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua index fd6f316de1..97568bc32a 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua index 3858a0c924..32be752ca8 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua index 4506fda378..767f0d7d8f 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/init.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua index 88debaa87a..5d8e4922a4 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua index b4702117eb..27d6d171d8 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua index a16b4e49cb..63264b92af 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua @@ -1,4 +1,4 @@ --- Copyright 2022 SmartThings +-- Copyright 2025 SmartThings -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. From f6aa78f93693a755820fbf64047f78de29984a4c Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 24 Apr 2025 11:52:56 +0200 Subject: [PATCH 07/11] remove powerConsumptionReport capability from production child device profile --- .../profiles/aeotec-home-energy-meter-gen8-sald-pro.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml index bd1f8cfebd..1ff680ec76 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-sald-pro.yml @@ -9,7 +9,5 @@ components: version: 1 - id: refresh version: 1 - - id: powerConsumptionReport - version: 1 categories: - name: CurbPowerMeter \ No newline at end of file From 7498e285d9ba1f0e13af3294b8374ae4dae0cd3c Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 24 Apr 2025 11:54:40 +0200 Subject: [PATCH 08/11] add missing Parameters --- ...tec-home-energy-meter-gen8-1-phase-con.yml | 125 +++++- ...tec-home-energy-meter-gen8-2-phase-con.yml | 125 +++++- ...tec-home-energy-meter-gen8-3-phase-con.yml | 125 +++++- .../zwave-electric-meter/src/preferences.lua | 51 ++- ..._aeotec_home_energy_meter_gen8_1_phase.lua | 360 ++++++++++++++++++ ..._aeotec_home_energy_meter_gen8_2_phase.lua | 360 ++++++++++++++++++ ..._aeotec_home_energy_meter_gen8_3_phase.lua | 360 ++++++++++++++++++ 7 files changed, 1500 insertions(+), 6 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml index c53872b7ce..2069a96bc2 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-1-phase-con.yml @@ -47,7 +47,7 @@ preferences: maximum: 60000 default: 50 - name: exWThresholdTotal - title: "8. Export W threshold(total)" + title: "8. Export W threshold (total)" description: "Threshold change in export wattage to induce an automatic report (Whole HEM)." preferenceType: integer definition: @@ -98,6 +98,129 @@ preferences: title: "32. Auto report of root device" description: "Enable automatic report of root device." preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: defaultReport + title: "100. Set 101-106 to default" + description: "Set 101-106 to default." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: autoReportImp1 + title: "101. Auto Report list 1 (Import)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 50528256 + - name: autoReportImp2 + title: "102. Auto Report list 2 (Import)" + description: "Configure which report needs to be sent in Report group 2." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 202113024 + - name: autoReportImp3 + title: "103. Auto Report list 3 (Import)" + description: "Configure which report needs to be sent in Report group 3." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 4042260480 + - name: autoReportExp1 + title: "104. Auto Report list 1 (Export)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 50528256 + - name: autoReportExp2 + title: "105. Auto Report list 2 (Export)" + description: "Configure which report needs to be sent in Report group 2." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 202113024 + - name: autoReportExp3 + title: "106. Auto Report list 3 (Export)" + description: "Configure which report needs to be sent in Report group 3." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 4042260480 + - name: defaultTime + title: "110. Set 111-116 to default" + description: "Set 111-116 to default." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: autoTimeImp1 + title: "111. Automatic time list 1 (Import)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeImp2 + title: "112. Automatic time list 2 (Import)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeImp3 + title: "113. Automatic time list 3 (Import)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeExp1 + title: "114. Automatic time list 1 (Export)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeExp2 + title: "115. Automatic time list 2 (Export)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 7200 + - name: autoTimeExp3 + title: "116. Automatic time list 3 (Export)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 7200 + - name: lockConfig + title: "252. Enable/disable lock config" + description: "Enable/disable to lock configuration parameters." + preferenceType: enumeration definition: options: 0: "Disable" diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml index 77844355a7..147f4709e9 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-2-phase-con.yml @@ -64,7 +64,7 @@ preferences: maximum: 60000 default: 50 - name: exWhresholdTotal - title: "8. Export W threshold(total)" + title: "8. Export W threshold (total)" description: "Threshold change in export wattage to induce an automatic report (Whole HEM)." preferenceType: integer definition: @@ -139,6 +139,129 @@ preferences: title: "32. Auto report of root device" description: "Enable automatic report of root device." preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: defaultReport + title: "100. Set 101-106 to default" + description: "Set 101-106 to default." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: autoReportImp1 + title: "101. Auto Report list 1 (Import)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 50529024 + - name: autoReportImp2 + title: "102. Auto Report list 2 (Import)" + description: "Configure which report needs to be sent in Report group 2." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 202116096 + - name: autoReportImp3 + title: "103. Auto Report list 3 (Import)" + description: "Configure which report needs to be sent in Report group 3." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 4042321920 + - name: autoReportExp1 + title: "104. Auto Report list 1 (Export)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 50529024 + - name: autoReportExp2 + title: "105. Auto Report list 2 (Export)" + description: "Configure which report needs to be sent in Report group 2." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 202116096 + - name: autoReportExp3 + title: "106. Auto Report list 3 (Export)" + description: "Configure which report needs to be sent in Report group 3." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 4042321920 + - name: defaultTime + title: "110. Set 111-116 to default" + description: "Set 111-116 to default." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: autoTimeImp1 + title: "111. Automatic time list 1 (Import)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeImp2 + title: "112. Automatic time list 2 (Import)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeImp3 + title: "113. Automatic time list 3 (Import)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeExp1 + title: "114. Automatic time list 1 (Export)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeExp2 + title: "115. Automatic time list 2 (Export)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 7200 + - name: autoTimeExp3 + title: "116. Automatic time list 3 (Export)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 7200 + - name: lockConfig + title: "252. Enable/disable lock config" + description: "Enable/disable to lock configuration parameters." + preferenceType: enumeration definition: options: 0: "Disable" diff --git a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml index c015b0acc2..682e05860e 100644 --- a/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml +++ b/drivers/SmartThings/zwave-electric-meter/profiles/aeotec-home-energy-meter-gen8-3-phase-con.yml @@ -81,7 +81,7 @@ preferences: maximum: 60000 default: 50 - name: exWhresholdTotal - title: "8. Export W threshold(total)" + title: "8. Export W threshold (total)" description: "Threshold change in export wattage to induce an automatic report (Whole HEM)." preferenceType: integer definition: @@ -180,6 +180,129 @@ preferences: title: "32. Auto report of root device" description: "Enable automatic report of root device." preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: defaultReport + title: "100. Set 101-106 to default" + description: "Set 101-106 to default." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: autoReportImp1 + title: "101. Auto Report list 1 (Import)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 50529027 + - name: autoReportImp2 + title: "102. Auto Report list 2 (Import)" + description: "Configure which report needs to be sent in Report group 2." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 202116108 + - name: autoReportImp3 + title: "103. Auto Report list 3 (Import)" + description: "Configure which report needs to be sent in Report group 3." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 4042322160 + - name: autoReportExp1 + title: "104. Auto Report list 1 (Export)" + description: "Configure which report needs to be sent in Report group 1." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 50529027 + - name: autoReportExp2 + title: "105. Auto Report list 2 (Export)" + description: "Configure which report needs to be sent in Report group 2." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 202116108 + - name: autoReportExp3 + title: "106. Auto Report list 3 (Export)" + description: "Configure which report needs to be sent in Report group 3." + preferenceType: number + definition: + min: 0 + max: 4294967295 + default: 4042322160 + - name: defaultTime + title: "110. Set 111-116 to default" + description: "Set 111-116 to default." + preferenceType: enumeration + definition: + options: + 0: "Disable" + 1: "Enable" + default: 0 + - name: autoTimeImp1 + title: "111. Automatic time list 1 (Import)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeImp2 + title: "112. Automatic time list 2 (Import)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeImp3 + title: "113. Automatic time list 3 (Import)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeExp1 + title: "114. Automatic time list 1 (Export)" + description: "Set the interval time of sending report in Report group 1." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 3600 + - name: autoTimeExp2 + title: "115. Automatic time list 2 (Export)" + description: "Set the interval time of sending report in Report group 2." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 7200 + - name: autoTimeExp3 + title: "116. Automatic time list 3 (Export)" + description: "Set the interval time of sending report in Report group 3." + preferenceType: number + definition: + min: 10 + max: 4294967295 + default: 7200 + - name: lockConfig + title: "252. Enable/disable lock config" + description: "Enable/disable to lock configuration parameters." + preferenceType: enumeration definition: options: 0: "Disable" diff --git a/drivers/SmartThings/zwave-electric-meter/src/preferences.lua b/drivers/SmartThings/zwave-electric-meter/src/preferences.lua index 9d1f5f3c6a..3340f7e284 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/preferences.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/preferences.lua @@ -15,7 +15,22 @@ local devices = { imWPctThresholdPhaseA = {parameter_number = 13, size = 1}, exWPctThresholdTotal = {parameter_number = 16, size = 1}, exWPctThresholdPhaseA = {parameter_number = 17, size = 1}, - autoRootDeviceReport = {parameter_number = 32, size = 1} + autoRootDeviceReport = {parameter_number = 32, size = 1}, + defaultReport = {parameter_number = 100, size = 1}, + autoReportImp1 = {parameter_number = 101, size = 4}, + autoReportImp2 = {parameter_number = 102, size = 4}, + autoReportImp3 = {parameter_number = 103, size = 4}, + autoReportExp1 = {parameter_number = 104, size = 4}, + autoReportExp2 = {parameter_number = 105, size = 4}, + autoReportExp3 = {parameter_number = 106, size = 4}, + defaultTime = {parameter_number = 110, size = 1}, + autoTimeImp1 = {parameter_number = 111, size = 4}, + autoTimeImp2 = {parameter_number = 112, size = 4}, + autoTimeImp3 = {parameter_number = 113, size = 4}, + autoTimeExp1 = {parameter_number = 114, size = 4}, + autoTimeExp2 = {parameter_number = 115, size = 4}, + autoTimeExp3 = {parameter_number = 116, size = 4}, + lockConfig = {parameter_number = 252, size = 1} } }, AEOTEC_HOME_ENERGY_METER_GEN8_2_PHASE = { @@ -38,7 +53,22 @@ local devices = { exWPctThresholdTotal = {parameter_number = 16, size = 1}, exWPctThresholdPhaseA = {parameter_number = 17, size = 1}, exWPctThresholdPhaseB = {parameter_number = 18, size = 1}, - autoRootDeviceReport = {parameter_number = 32, size = 1} + autoRootDeviceReport = {parameter_number = 32, size = 1}, + defaultReport = {parameter_number = 100, size = 1}, + autoReportImp1 = {parameter_number = 101, size = 4}, + autoReportImp2 = {parameter_number = 102, size = 4}, + autoReportImp3 = {parameter_number = 103, size = 4}, + autoReportExp1 = {parameter_number = 104, size = 4}, + autoReportExp2 = {parameter_number = 105, size = 4}, + autoReportExp3 = {parameter_number = 106, size = 4}, + defaultTime = {parameter_number = 110, size = 1}, + autoTimeImp1 = {parameter_number = 111, size = 4}, + autoTimeImp2 = {parameter_number = 112, size = 4}, + autoTimeImp3 = {parameter_number = 113, size = 4}, + autoTimeExp1 = {parameter_number = 114, size = 4}, + autoTimeExp2 = {parameter_number = 115, size = 4}, + autoTimeExp3 = {parameter_number = 116, size = 4}, + lockConfig = {parameter_number = 252, size = 1} } }, AEOTEC_HOME_ENERGY_METER_GEN8_3_PHASE = { @@ -65,7 +95,22 @@ local devices = { exWPctThresholdPhaseA = {parameter_number = 17, size = 1}, exWPctThresholdPhaseB = {parameter_number = 18, size = 1}, exWPctThresholdPhaseC = {parameter_number = 19, size = 1}, - autoRootDeviceReport = {parameter_number = 32, size = 1} + autoRootDeviceReport = {parameter_number = 32, size = 1}, + defaultReport = {parameter_number = 100, size = 1}, + autoReportImp1 = {parameter_number = 101, size = 4}, + autoReportImp2 = {parameter_number = 102, size = 4}, + autoReportImp3 = {parameter_number = 103, size = 4}, + autoReportExp1 = {parameter_number = 104, size = 4}, + autoReportExp2 = {parameter_number = 105, size = 4}, + autoReportExp3 = {parameter_number = 106, size = 4}, + defaultTime = {parameter_number = 110, size = 1}, + autoTimeImp1 = {parameter_number = 111, size = 4}, + autoTimeImp2 = {parameter_number = 112, size = 4}, + autoTimeImp3 = {parameter_number = 113, size = 4}, + autoTimeExp1 = {parameter_number = 114, size = 4}, + autoTimeExp2 = {parameter_number = 115, size = 4}, + autoTimeExp3 = {parameter_number = 116, size = 4}, + lockConfig = {parameter_number = 252, size = 1} } } } diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua index 5d8e4922a4..0c009a7c9d 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua @@ -504,6 +504,366 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Handle preference: defaultReport (parameter 100) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + defaultReport = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 100, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp1 (parameter 101) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 101, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp2 (parameter 102) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp2 = 2021161 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 102, + configuration_value = 2021161, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp3 (parameter 103) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp3 = 40423221 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 103, + configuration_value = 40423221, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp1 (parameter 104) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp1 = 505290 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 104, + configuration_value = 505290, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp2 (parameter 105) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp2 = 2021161 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 105, + configuration_value = 2021161, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp3 (parameter 106) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp3 = 40423221 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 106, + configuration_value = 40423221, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: defaultTime (parameter 110) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + defaultTime = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 110, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp1 (parameter 111) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 111, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp2 (parameter 112) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp2 = 7200 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 112, + configuration_value = 7200, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp3 (parameter 113) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp3 = 7200 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 113, + configuration_value = 7200, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp1 (parameter 114) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 114, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp2 (parameter 115) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp2 = 3600 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 115, + configuration_value = 3600, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp3 (parameter 116) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp3 = 3600 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 116, + configuration_value = 3600, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: lockConfig (parameter 252) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + lockConfig = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 252, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + test.register_coroutine_test( "Refresh sends commands to all components including base device", function() diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua index 27d6d171d8..b852f4609d 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua @@ -600,6 +600,366 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Handle preference: defaultReport (parameter 100) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + defaultReport = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 100, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp1 (parameter 101) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 101, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp2 (parameter 102) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp2 = 2021161 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 102, + configuration_value = 2021161, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp3 (parameter 103) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp3 = 40423221 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 103, + configuration_value = 40423221, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp1 (parameter 104) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp1 = 505290 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 104, + configuration_value = 505290, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp2 (parameter 105) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp2 = 2021161 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 105, + configuration_value = 2021161, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp3 (parameter 106) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp3 = 40423221 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 106, + configuration_value = 40423221, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: defaultTime (parameter 110) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + defaultTime = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 110, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp1 (parameter 111) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 111, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp2 (parameter 112) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp2 = 7200 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 112, + configuration_value = 7200, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp3 (parameter 113) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp3 = 7200 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 113, + configuration_value = 7200, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp1 (parameter 114) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 114, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp2 (parameter 115) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp2 = 3600 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 115, + configuration_value = 3600, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp3 (parameter 116) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp3 = 3600 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 116, + configuration_value = 3600, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: lockConfig (parameter 252) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + lockConfig = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 252, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + test.register_coroutine_test( "Refresh sends commands to all components including base device", function() diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua index 63264b92af..377af2bd8c 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua @@ -696,6 +696,366 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Handle preference: defaultReport (parameter 100) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + defaultReport = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 100, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp1 (parameter 101) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 101, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp2 (parameter 102) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp2 = 2021161 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 102, + configuration_value = 2021161, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportImp3 (parameter 103) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportImp3 = 40423221 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 103, + configuration_value = 40423221, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp1 (parameter 104) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp1 = 505290 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 104, + configuration_value = 505290, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp2 (parameter 105) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp2 = 2021161 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 105, + configuration_value = 2021161, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoReportExp3 (parameter 106) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoReportExp3 = 40423221 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 106, + configuration_value = 40423221, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: defaultTime (parameter 110) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + defaultTime = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 110, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp1 (parameter 111) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 111, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp2 (parameter 112) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp2 = 7200 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 112, + configuration_value = 7200, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeImp3 (parameter 113) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeImp3 = 7200 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 113, + configuration_value = 7200, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp1 (parameter 114) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp1 = 300 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 114, + configuration_value = 300, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp2 (parameter 115) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp2 = 3600 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 115, + configuration_value = 3600, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: autoTimeExp3 (parameter 116) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + autoTimeExp3 = 3600 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 116, + configuration_value = 3600, + size = 4 + }) + ) + ) + end +) + +test.register_coroutine_test( + "Handle preference: lockConfig (parameter 252) in infoChanged", + function() + test.socket.device_lifecycle:__queue_receive( + mock_parent:generate_info_changed({ + preferences = { + lockConfig = 1 + } + }) + ) + + test.socket.zwave:__expect_send( + zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({ + parameter_number = 252, + configuration_value = 1, + size = 1 + }) + ) + ) + end +) + test.register_coroutine_test( "Refresh sends commands to all components including base device", function() From d88a31f487f2737e746b7e61e23eea7838e15db9 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 24 Apr 2025 11:56:55 +0200 Subject: [PATCH 09/11] change deivce for power consumption report in meter report handler --- .../src/aeotec-home-energy-meter-gen8/1-phase/init.lua | 2 +- .../src/aeotec-home-energy-meter-gen8/2-phase/init.lua | 2 +- .../src/aeotec-home-energy-meter-gen8/3-phase/init.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua index 68f416b643..f4e26fecd2 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -102,7 +102,7 @@ local function meter_report_handler(driver, device, cmd, zb_rx) if endpoint == 5 then -- powerConsumptionReport - emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) + emit_power_consumption_report_event(device_to_emit_with, { value = event_arguments.value }, endpoint) end elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then local event_arguments = { diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua index 97568bc32a..cfd706d3ab 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua @@ -101,7 +101,7 @@ local function meter_report_handler(driver, device, cmd, zb_rx) if endpoint == 7 then -- powerConsumptionReport - emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) + emit_power_consumption_report_event(device_to_emit_with, { value = event_arguments.value }, endpoint) end elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then local event_arguments = { diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua index 32be752ca8..6f20a28e3d 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua @@ -103,7 +103,7 @@ local function meter_report_handler(driver, device, cmd, zb_rx) if endpoint == 9 then -- powerConsumptionReport - emit_power_consumption_report_event(device, { value = event_arguments.value }, endpoint) + emit_power_consumption_report_event(device_to_emit_with, { value = event_arguments.value }, endpoint) end elseif cmd.args.scale == Meter.scale.electric_meter.WATTS then local event_arguments = { From d614139780452670a6c7887e7aef6227f2bd394a Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 24 Apr 2025 11:58:42 +0200 Subject: [PATCH 10/11] add doConfigure lifecycle - add test for doConfigure lifecycle --- .../1-phase/init.lua | 7 ++++++ .../2-phase/init.lua | 9 +++++++ .../3-phase/init.lua | 9 +++++++ ..._aeotec_home_energy_meter_gen8_1_phase.lua | 22 +++++++++++++++++ ..._aeotec_home_energy_meter_gen8_2_phase.lua | 22 +++++++++++++++++ ..._aeotec_home_energy_meter_gen8_3_phase.lua | 24 ++++++++++++++++++- 6 files changed, 92 insertions(+), 1 deletion(-) diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua index f4e26fecd2..2b1369de29 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -165,6 +165,12 @@ local function device_added(driver, device) do_refresh(driver, device) end +local do_configure = function (self, device) + device:send(Configuration:Set({parameter_number = 111, configuration_value = 300, size = 4})) -- ...every 5 min + device:send(Configuration:Set({parameter_number = 112, configuration_value = 300, size = 4})) -- ...every 5 min + device:send(Configuration:Set({parameter_number = 113, configuration_value = 300, size = 4})) -- ...every 5 min +end + local aeotec_home_energy_meter_gen8_1_phase = { NAME = "Aeotec Home Energy Meter Gen8", supported_capabilities = { @@ -181,6 +187,7 @@ local aeotec_home_energy_meter_gen8_1_phase = { } }, lifecycle_handlers = { + doConfigure = do_configure, added = device_added, init = device_init }, diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua index cfd706d3ab..00770b6a75 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/2-phase/init.lua @@ -14,6 +14,8 @@ local st_device = require "st.device" local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=1 }) --- @type st.zwave.CommandClass.Meter local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) --- @type st.zwave.CommandClass @@ -161,6 +163,12 @@ local function device_added(driver, device) do_refresh(driver, device) end +local do_configure = function (self, device) + device:send(Configuration:Set({parameter_number = 111, configuration_value = 300, size = 4})) -- ...every 5 min + device:send(Configuration:Set({parameter_number = 112, configuration_value = 300, size = 4})) -- ...every 5 min + device:send(Configuration:Set({parameter_number = 113, configuration_value = 300, size = 4})) -- ...every 5 min +end + local aeotec_home_energy_meter_gen8_2_phase = { NAME = "Aeotec Home Energy Meter Gen8", supported_capabilities = { @@ -177,6 +185,7 @@ local aeotec_home_energy_meter_gen8_2_phase = { } }, lifecycle_handlers = { + doConfigure = do_configure, added = device_added, init = device_init }, diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua index 6f20a28e3d..f6c37a1bf9 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua @@ -14,6 +14,8 @@ local st_device = require "st.device" local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=1 }) --- @type st.zwave.CommandClass.Meter local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) --- @type st.zwave.CommandClass @@ -166,6 +168,12 @@ local function device_added(driver, device) do_refresh(driver, device) end +local do_configure = function (self, device) + device:send(Configuration:Set({parameter_number = 111, configuration_value = 300, size = 4})) -- ...every 5 min + device:send(Configuration:Set({parameter_number = 112, configuration_value = 300, size = 4})) -- ...every 5 min + device:send(Configuration:Set({parameter_number = 113, configuration_value = 300, size = 4})) -- ...every 5 min +end + local aeotec_home_energy_meter_gen8_3_phase = { NAME = "Aeotec Home Energy Meter Gen8", supported_capabilities = { @@ -182,6 +190,7 @@ local aeotec_home_energy_meter_gen8_3_phase = { } }, lifecycle_handlers = { + doConfigure = do_configure, added = device_added, init = device_init }, diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua index 0c009a7c9d..09a98701d6 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_1_phase.lua @@ -142,6 +142,28 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Configure should configure all necessary attributes", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "doConfigure" }) + + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 111, size = 4, configuration_value = 300}) + )) + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 112, size = 4, configuration_value = 300}) + )) + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 113, size = 4, configuration_value = 300}) + )) + mock_parent:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + test.register_coroutine_test( "Power meter report should be handled", function() diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua index b852f4609d..a0d7a227bd 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_2_phase.lua @@ -142,6 +142,28 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Configure should configure all necessary attributes", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "doConfigure" }) + + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 111, size = 4, configuration_value = 300}) + )) + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 112, size = 4, configuration_value = 300}) + )) + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 113, size = 4, configuration_value = 300}) + )) + mock_parent:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + test.register_coroutine_test( "Power meter report should be handled", function() diff --git a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua index 377af2bd8c..a267d6b75a 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/test/test_aeotec_home_energy_meter_gen8_3_phase.lua @@ -17,7 +17,7 @@ local capabilities = require "st.capabilities" local zw = require "st.zwave" local zw_test_utils = require "integration_test.zwave_test_utils" local Meter = (require "st.zwave.CommandClass.Meter")({version=4}) -local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=4 }) +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=1 }) local t_utils = require "integration_test.utils" local AEOTEC_MFR_ID = 0x0371 @@ -142,6 +142,28 @@ test.register_coroutine_test( end ) +test.register_coroutine_test( + "Configure should configure all necessary attributes", + function() + test.socket.zwave:__set_channel_ordering("relaxed") + test.socket.device_lifecycle:__queue_receive({ mock_parent.id, "doConfigure" }) + + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 111, size = 4, configuration_value = 300}) + )) + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 112, size = 4, configuration_value = 300}) + )) + test.socket.zwave:__expect_send(zw_test_utils.zwave_test_build_send_command( + mock_parent, + Configuration:Set({parameter_number = 113, size = 4, configuration_value = 300}) + )) + mock_parent:expect_metadata_update({ provisioning_state = "PROVISIONED" }) + end +) + test.register_coroutine_test( "Power meter report should be handled", function() From e368cad8b68437453c84cb7307e1e50a2eb76895 Mon Sep 17 00:00:00 2001 From: mh-zwave Date: Thu, 24 Apr 2025 12:02:03 +0200 Subject: [PATCH 11/11] fix line indentation --- .../src/aeotec-home-energy-meter-gen8/1-phase/init.lua | 6 ++++-- .../src/aeotec-home-energy-meter-gen8/3-phase/init.lua | 9 ++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua index 2b1369de29..05be152d65 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/1-phase/init.lua @@ -14,6 +14,8 @@ local st_device = require "st.device" local capabilities = require "st.capabilities" +--- @type st.zwave.CommandClass.Configuration +local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=1 }) --- @type st.zwave.CommandClass.Meter local Meter = (require "st.zwave.CommandClass.Meter")({ version=4 }) --- @type st.zwave.CommandClass @@ -74,8 +76,8 @@ local function emit_power_consumption_report_event(device, value, channel) delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) end device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ - energy = raw_value, - deltaEnergy = delta_energy + energy = raw_value, + deltaEnergy = delta_energy })) end diff --git a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua index f6c37a1bf9..c7a5c6884e 100644 --- a/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua +++ b/drivers/SmartThings/zwave-electric-meter/src/aeotec-home-energy-meter-gen8/3-phase/init.lua @@ -11,7 +11,6 @@ -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. - local st_device = require "st.device" local capabilities = require "st.capabilities" --- @type st.zwave.CommandClass.Configuration @@ -72,13 +71,13 @@ local function emit_power_consumption_report_event(device, value, channel) local delta_energy = 0.0 local current_power_consumption = device:get_latest_state('main', capabilities.powerConsumptionReport.ID, - capabilities.powerConsumptionReport.powerConsumption.NAME) + capabilities.powerConsumptionReport.powerConsumption.NAME) if current_power_consumption ~= nil then - delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) + delta_energy = math.max(raw_value - current_power_consumption.energy, 0.0) end device:emit_event_for_endpoint(channel, capabilities.powerConsumptionReport.powerConsumption({ - energy = raw_value, - deltaEnergy = delta_energy + energy = raw_value, + deltaEnergy = delta_energy })) end