]> git.basschouten.com Git - openhab-addons.git/commitdiff
[mecmeter] Initial contribution of mecmeter binding (#9075)
authorKai Kreuzer <kai@openhab.org>
Sun, 28 Mar 2021 09:20:21 +0000 (11:20 +0200)
committerGitHub <noreply@github.com>
Sun, 28 Mar 2021 09:20:21 +0000 (11:20 +0200)
* Initial contribution of mecmeter binding

Also-by: Klaus Berger <klaus.berger@verbund.com>
Also-by: Florian Pazour <florian.pazour@verbund.com>
Signed-off-by: Kai Kreuzer <kai@openhab.org>
* addressed review feedback

Signed-off-by: Kai Kreuzer <kai@openhab.org>
* added codeowners entry

Signed-off-by: Kai Kreuzer <kai@openhab.org>
* addressed review comments

Signed-off-by: Kai Kreuzer <kai@openhab.org>
15 files changed:
CODEOWNERS
bom/openhab-addons/pom.xml
bundles/org.openhab.binding.mecmeter/NOTICE [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/README.MD [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/pom.xml [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/MecMeterBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/MecMeterDeviceConfiguration.java [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/handler/MecMeterHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/MecMeterHandlerFactory.java [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/discovery/MecMeterDiscoveryParticipant.java [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/dto/MecMeterResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/resources/OH-INF/binding/binding.xml [new file with mode: 0644]
bundles/org.openhab.binding.mecmeter/src/main/resources/OH-INF/thing/thing-types.xml [new file with mode: 0644]
bundles/pom.xml

index 41e5ecba69f28044d34223b74e9c8b6ea0eec38e..122c664046cb404511674068a432ccacc7adfeed 100644 (file)
 /bundles/org.openhab.binding.mail/ @openhab/add-ons-maintainers
 /bundles/org.openhab.binding.max/ @marcelrv
 /bundles/org.openhab.binding.mcp23017/ @aogorek
+/bundles/org.openhab.binding.mecmeter/ @kaikreuzer
 /bundles/org.openhab.binding.melcloud/ @lucacalcaterra @paulianttila @thewiep
 /bundles/org.openhab.binding.meteoalerte/ @clinique
 /bundles/org.openhab.binding.meteoblue/ @9037568
index 1b0f7a7afa26eaa10a6e83e84ce9d37861b30791..4eaa9f9befd40045f12f03d6e1a5636c68fde391 100644 (file)
       <artifactId>org.openhab.binding.mcp23017</artifactId>
       <version>${project.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.openhab.addons.bundles</groupId>
+      <artifactId>org.openhab.binding.mecmeter</artifactId>
+      <version>${project.version}</version>
+    </dependency>
     <dependency>
       <groupId>org.openhab.addons.bundles</groupId>
       <artifactId>org.openhab.binding.melcloud</artifactId>
diff --git a/bundles/org.openhab.binding.mecmeter/NOTICE b/bundles/org.openhab.binding.mecmeter/NOTICE
new file mode 100644 (file)
index 0000000..38d625e
--- /dev/null
@@ -0,0 +1,13 @@
+This content is produced and maintained by the openHAB project.
+
+* Project home: https://www.openhab.org
+
+== Declared Project Licenses
+
+This program and the accompanying materials are made available under the terms
+of the Eclipse Public License 2.0 which is available at
+https://www.eclipse.org/legal/epl-2.0/.
+
+== Source Code
+
+https://github.com/openhab/openhab-addons
diff --git a/bundles/org.openhab.binding.mecmeter/README.MD b/bundles/org.openhab.binding.mecmeter/README.MD
new file mode 100644 (file)
index 0000000..aa8f2f8
--- /dev/null
@@ -0,0 +1,247 @@
+# MecMeter Binding
+
+This binding reads data from MEC power meter for providing electrical information for the electric circuit.
+
+To use this binding the meter must be installed, initialized and connected to the same network as openHAB. 
+
+## Supported Things
+
+The mecMeter is supported with firmware version starting from 2.0.0.
+There is exactly one supported thing type `meter`, which represents the electric meter.
+Its unique ID is the serial number.
+
+## Discovery
+
+MecMeters are automatically discovered via mDNS. 
+The IP of the Power Meter is automatically set and can be changed manually if needed.
+The default update interval is set to 5 seconds. Intervals from 1 to 300 seconds can be set manually.
+
+## Thing Configuration
+
+The thing has a few configuration parameters:  
+
+| Parameter       | Description                                                           |
+|-----------------|-----------------------------------------------------------------------|
+| password        | User-defined password during initializing the Power Meter. Mandatory. |
+| ip              | The IP address of the meter. Mandatory.                               |
+| refreshInterval | Refresh interval in second. Optional, the default value is 5 seconds. |
+
+       
+## Channels
+
+The meter has the following channels: 
+
+| Channel Type ID                                              | Item Type                | Label                             | Description                              |
+|--------------------------------------------------------------|--------------------------|-----------------------------------|------------------------------------------|
+| general_group#frequency                                      | Number:Frequency         | Main Frequency                    | Frequency in Hertz                       |
+| general_group#temperature                                    | Number:Temperature       | Internal Temperature              | Internal Temperature of the energy meter |
+| general_group#op_time                                        | Number:Time              | Time in Operation                 | Time in Operation                        |
+| voltage_group#voltage_phase1                                 | Number:ElectricPotential | Voltage P1                        | Voltage in Volt                          |
+| voltage_group#voltage_phase2                                 | Number:ElectricPotential | Voltage P2                        | Voltage in Volt                          |
+| voltage_group#voltage_phase3                                 | Number:ElectricPotential | Voltage P3                        | Voltage in Volt                          |
+| voltage_group#avg_phase_phase_voltage                        | Number:ElectricPotential | Average Phase – Phase Voltage     | Average Phase – Phase Voltage in Volt    |
+| voltage_group#avg_neutral_phase_voltage                      | Number:ElectricPotential | Average Voltage                   | Average N – Phase Voltage in Volt        |
+| current_group#current_allphase                               | Number:ElectricCurrent   | Current                           | Current in Ampere                        |
+| current_group#current_phase1                                 | Number:ElectricCurrent   | Current P1                        | Current in Ampere                        |
+| current_group#current_phase2                                 | Number:ElectricCurrent   | Current P2                        | Current in Ampere                        |
+| current_group#current_phase3                                 | Number:ElectricCurrent   | Current P3                        | Current in Ampere                        |
+| angle_group#phase_angle_currvolt_phase1                      | Number:Angle             | Current P1                        | Angle Current to Voltage in Degree       |
+| angle_group#phase_angle_currvolt_phase2                      | Number:Angle             | Current P2                        | Angle Current to Voltage in Degree       |
+| angle_group#phase_angle_currvolt_phase3                      | Number:Angle             | Current P3                        | Angle Current to Voltage in Degree       |
+| angle_group#phase_angle_phase1-3                             | Number:Angle             | Angle Voltage to Voltage          | Angle Voltage to Voltage in Degree       |
+| angle_group#phase_angle_phase2-3                             | Number:Angle             | Angle Voltage to Voltage          | Angle Voltage to Voltage in Degree       |
+| activepower_group#activepower_allphase                       | Number:Power             | Active Power                      | Active power consumed                    |
+| activepower_group#activepower_phase1                         | Number:Power             | Active Power P1                   | Active power consumed                    |
+| activepower_group#activepower_phase2                         | Number:Power             | Active Power P2                   | Active power consumed                    |
+| activepower_group#activepower_phase3                         | Number:Power             | Active Power P3                   | Active power consumed                    |
+| activefundpower_group#activefundpower_allphase               | Number:Power             | Active Fundamental Power          | Active fundamental power                 |
+| activefundpower_group#activefundpower_phase1                 | Number:Power             | Active Fund Power P1              | Active fundamental power                 |
+| activefundpower_group#activefundpower_phase2                 | Number:Power             | Active Fund Power P2              | Active fundamental power                 |
+| activefundpower_group#activefundpower_phase3                 | Number:Power             | Active Fund Power P3              | Active fundamental power                 |
+| activeharmpower_group#activeharmpower_allphase               | Number:Power             | Active Harmonic Power             | Active harmonic power                    |
+| activeharmpower_group#activeharmpower_phase1                 | Number:Power             | Active Harm Power P1              | Active harmonic power                    |
+| activeharmpower_group#activeharmpower_phase2                 | Number:Power             | Active Harm Power P2              | Active harmonic power                    |
+| activeharmpower_group#activeharmpower_phase3                 | Number:Power             | Active Harm Power P3              | Active harmonic power                    |
+| reactivepower_group#reactivepower_allphase                   | Number:Power             | Reactive Power                    | Reactive power consumed                  |
+| reactivepower_group#reactivepower_phase1                     | Number:Power             | Reactive Power P1                 | Reactive power consumed                  |
+| reactivepower_group#reactivepower_phase2                     | Number:Power             | Reactive Power P2                 | Reactive power consumed                  |
+| reactivepower_group#reactivepower_phase3                     | Number:Power             | Reactive Power P3                 | Reactive power consumed                  |
+| powerfactor_group#powerFactor_allphase                       | Number:Dimensionless     | Power Factor                      | Power Factor                             |
+| powerfactor_group#powerFactor_phase1                         | Number:Dimensionless     | Power Factor P1                   | Power Factor                             |
+| powerfactor_group#powerFactor_phase2                         | Number:Dimensionless     | Power Factor P2                   | Power Factor                             |
+| powerfactor_group#powerFactor_phase3                         | Number:Dimensionless     | Power Factor P3                   | Power Factor                             |
+| apppower_group#apppower_allphase                             | Number:Power             | Apparent Power                    | Apparent power consumed                  |
+| apppower_group#apppower_phase1                               | Number:Power             | Apparent Power P1                 | Apparent power consumed                  |
+| apppower_group#apppower_phase2                               | Number:Power             | Apparent Power P2                 | Apparent power consumed                  |
+| apppower_group#apppower_phase3                               | Number:Power             | Apparent Power P3                 | Apparent power consumed                  |
+| fwd_active_energy_group#fwd_active_energy_allphase           | Number:Energy            | Forward Active Energy             | Forward Active Energy in kWh             |
+| fwd_active_energy_group#fwd_active_energy_phase1             | Number:Energy            | Fwd Active Energy P1              | Forward Active Energy in kWh             |
+| fwd_active_energy_group#fwd_active_energy_phase2             | Number:Energy            | Fwd Active Energy P2              | Forward Active Energy in kWh             |
+| fwd_active_energy_group#fwd_active_energy_phase3             | Number:Energy            | Fwd Active Energy P3              | Forward Active Energy in kWh             |
+| fwd_active_fund_energy_group#fwd_active_fund_energy_allphase | Number:Energy            | Forward Active Fundamental Energy | Forward Active Fundamental Energy in kWh |
+| fwd_active_fund_energy_group#fwd_active_fund_energy_phase1   | Number:Energy            | Fwd Active Fund Energy P1         | Forward Active Fundamental Energy in kWh |
+| fwd_active_fund_energy_group#fwd_active_fund_energy_phase2   | Number:Energy            | Fwd Active Fund Energy P2         | Forward Active Fundamental Energy in kWh |
+| fwd_active_fund_energy_group#fwd_active_fund_energy_phase3   | Number:Energy            | Fwd Active Fund Energy P3         | Forward Active Fundamental Energy in kWh |
+| fwd_active_harm_energy_group#fwd_active_harm_energy_allphase | Number:Energy            | Forward Active Harmonic Energy    | Forward Active Harmonic Energy in kWh    |
+| fwd_active_harm_energy_group#fwd_active_harm_energy_phase1   | Number:Energy            | Fwd Active Harm Energy P1         | Forward Active Harmonic Energy in kWh    |
+| fwd_active_harm_energy_group#fwd_active_harm_energy_phase2   | Number:Energy            | Fwd Active Harm Energy P2         | Forward Active Harmonic Energy in kWh    |
+| fwd_active_harm_energy_group#fwd_active_harm_energy_phase3   | Number:Energy            | Fwd Active Harm Energy P3         | Forward Active Harmonic Energy in kWh    |
+| fwd_reactive_energy_group#fwd_reactive_energy_allphase       | Number:Energy            | Forward Reactive Energy           | Forward Reactive Energy in VArh          |
+| fwd_reactive_energy_group#fwd_reactive_energy_phase1         | Number:Energy            | Fwd Reactive Energy P1            | Forward Reactive Energy in VArh          |
+| fwd_reactive_energy_group#fwd_reactive_energy_phase2         | Number:Energy            | Fwd Reactive Energy P2            | Forward Reactive Energy in VArh          |
+| fwd_reactive_energy_group#fwd_reactive_energy_phase3         | Number:Energy            | Fwd Reactive Energy P3            | Forward Reactive Energy in VArh          |
+| rev_active_energy_group#rev_active_energy_allphase           | Number:Energy            | Reverse Active Energy             | Reverse Active Energy in kWh             |
+| rev_active_energy_group#rev_active_energy_phase1             | Number:Energy            | Rev Active Energy P1              | Reverse Active Energy in kWh             |
+| rev_active_energy_group#rev_active_energy_phase2             | Number:Energy            | Rev Active Energy P2              | Reverse Active Energy in kWh             |
+| rev_active_energy_group#rev_active_energy_phase3             | Number:Energy            | Rev Active Energy P3              | Reverse Active Energy in kWh             |
+| rev_active_fund_energy_group#rev_active_fund_energy_allphase | Number:Energy            | Reverse Active Fundamental Energy | Reverse Active Fundamental Energy in kWh |
+| rev_active_fund_energy_group#rev_active_fund_energy_phase1   | Number:Energy            | Rev Active Fund Energy P1         | Reverse Active Fundamental Energy in kWh |
+| rev_active_fund_energy_group#rev_active_fund_energy_phase2   | Number:Energy            | Rev Active Fund Energy P2         | Reverse Active Fundamental Energy in kWh |
+| rev_active_fund_energy_group#rev_active_fund_energy_phase3   | Number:Energy            | Rev Active Fund Energy P3         | Reverse Active Fundamental Energy in kWh |
+| rev_active_harm_energy_group#rev_active_harm_energy_allphase | Number:Energy            | Reverse Active Harmonic Energy    | Reverse Active Harmonic Energy in kWh    |
+| rev_active_harm_energy_group#rev_active_harm_energy_phase1   | Number:Energy            | Rev Active Harm Energy P1         | Reverse Active Harmonic Energy in kWh    |
+| rev_active_harm_energy_group#rev_active_harm_energy_phase2   | Number:Energy            | Rev Active Harm Energy P2         | Reverse Active Harmonic Energy in kWh    |
+| rev_active_harm_energy_group#rev_active_harm_energy_phase3   | Number:Energy            | Rev Active Harm Energy P3         | Reverse Active Harmonic Energy in kWh    |
+| rev_reactive_energy_group#rev_reactive_energy_allphase       | Number:Energy            | Reverse Reactive Energy           | Reverse Reactive Energy in VArh          |
+| rev_reactive_energy_group#rev_reactive_energy_phase1         | Number:Energy            | Rev Reactive Energy P1            | Reverse Reactive Energy in VArh          |
+| rev_reactive_energy_group#rev_reactive_energy_phase2         | Number:Energy            | Rev Reactive Energy P2            | Reverse Reactive Energy in VArh          |
+| rev_reactive_energy_group#rev_reactive_energy_phase3         | Number:Energy            | Rev Reactive Energy P3            | Reverse Reactive Energy in VArh          |
+| app_energy_group#appenergy_consumption_allphase              | Number:Energy            | Apparent Energy Consumption       | Apparent Energy Consumption in VArh      |
+| app_energy_group#appenergy_consumption_phase1                | Number:Energy            | Apparent Energy P1                | Apparent Energy Consumption in VArh      |
+| app_energy_group#appenergy_consumption_phase2                | Number:Energy            | Apparent Energy P2                | Apparent Energy Consumption in VArh      |
+| app_energy_group#appenergy_consumption_phase3                | Number:Energy            | Apparent Energy P3                | Apparent Energy Consumption in VArh      |
+
+## Full Example
+
+### mecmeter.things
+
+```
+mecmeter:meter:1 [ password="Test1234", ip="192.168.1.16", refreshInterval="10" ]
+```
+
+### mecmeter.items
+
+```
+Number:Frequency    MainFrequency           { channel="mecmeter:meter:1:general_group#frequency" }
+Number:Temperature  InternalTemperature     { channel="mecmeter:meter:1:general_group#temperature" }
+Number:Time         TimeinOperation         { channel="mecmeter:meter:1:general_group#op_time" }
+
+Number:Power ActivePower { channel="mecmeter:meter:1:activepower_group#activepower_allphase" }
+Number:Power ActivePowerP1 { channel="mecmeter:meter:1:activepower_group#activepower_phase1" }
+Number:Power ActivePowerP2 { channel="mecmeter:meter:1:activepower_group#activepower_phase2" }
+Number:Power ActivePowerP3 { channel="mecmeter:meter:1:activepower_group#activepower_phase3" }
+
+Number:ElectricPotential VoltageP1 { channel="mecmeter:meter:1:voltage_group#voltage_phase1" }
+Number:ElectricPotential VoltageP2 { channel="mecmeter:meter:1:voltage_group#voltage_phase2" }
+Number:ElectricPotential VoltageP3 { channel="mecmeter:meter:1:voltage_group#voltage_phase3" }
+Number:ElectricPotential AveragePhasePhaseVoltage { channel="mecmeter:meter:1:voltage_group#avg_phase_phase_voltage" }
+Number:ElectricPotential AverageVoltage { channel="mecmeter:meter:1:voltage_group#avg_neutral_phase_voltage" }
+
+Number:ElectricCurrent Current { channel="mecmeter:meter:1:current_group#current_allphase" }
+Number:ElectricCurrent Current_Group_Current_Phase1 { channel="mecmeter:meter:1:current_group#current_phase1" }
+Number:ElectricCurrent Current_Group_Current_Phase2 { channel="mecmeter:meter:1:current_group#current_phase2" }
+Number:ElectricCurrent Current_Group_Current_Phase3 { channel="mecmeter:meter:1:current_group#current_phase3" }
+
+Number:Power ActiveFundamentalPower { channel="mecmeter:meter:1:activefundpower_group#activefundpower_allphase" }
+Number:Power ActiveFundPowerP1 { channel="mecmeter:meter:1:activefundpower_group#activefundpower_phase1" }
+Number:Power ActiveFundPowerP2 { channel="mecmeter:meter:1:activefundpower_group#activefundpower_phase2" }
+Number:Power ActiveFundPowerP3 { channel="mecmeter:meter:1:activefundpower_group#activefundpower_phase3" }
+
+Number:Power ActiveHarmonicPower { channel="mecmeter:meter:1:activeharmpower_group#activeharmpower_allphase" }
+Number:Power ActiveHarmPowerP1 { channel="mecmeter:meter:1:activeharmpower_group#activeharmpower_phase1" }
+Number:Power ActiveHarmPowerP2 { channel="mecmeter:meter:1:activeharmpower_group#activeharmpower_phase2" }
+Number:Power ActiveHarmPowerP3 { channel="mecmeter:meter:1:activeharmpower_group#activeharmpower_phase3" }
+
+Number:Angle Angle_Group_Phase_Angle_Currvolt_Phase1 { channel="mecmeter:meter:1:angle_group#phase_angle_currvolt_phase1" }
+Number:Angle Angle_Group_Phase_Angle_Currvolt_Phase2 { channel="mecmeter:meter:1:angle_group#phase_angle_currvolt_phase2" }
+Number:Angle Angle_Group_Phase_Angle_Currvolt_Phase3 { channel="mecmeter:meter:1:angle_group#phase_angle_currvolt_phase3" }
+Number:Angle Angle_Group_Phase_Angle_Phase13 { channel="mecmeter:meter:1:angle_group#phase_angle_phase1-3" }
+Number:Angle Angle_Group_Phase_Angle_Phase23 { channel="mecmeter:meter:1:angle_group#phase_angle_phase2-3" }
+
+Number:Energy ApparentEnergyConsumption { channel="mecmeter:meter:1:app_energy_group#appenergy_consumption_allphase" }
+Number:Energy ApparentEnergyP1 { channel="mecmeter:meter:1:app_energy_group#appenergy_consumption_phase1" }
+Number:Energy ApparentEnergyP2 { channel="mecmeter:meter:1:app_energy_group#appenergy_consumption_phase2" }
+Number:Energy ApparentEnergyP3 { channel="mecmeter:meter:1:app_energy_group#appenergy_consumption_phase3" }
+
+Number:Power ApparentPower { channel="mecmeter:meter:1:apppower_group#apppower_allphase" }
+Number:Power ApparentPowerP1 { channel="mecmeter:meter:1:apppower_group#apppower_phase1" }
+Number:Power ApparentPowerP2 { channel="mecmeter:meter:1:apppower_group#apppower_phase2" }
+Number:Power ApparentPowerP3 { channel="mecmeter:meter:1:apppower_group#apppower_phase3" }
+
+Number:Energy ForwardActiveEnergy { channel="mecmeter:meter:1:fwd_active_energy_group#fwd_active_energy_allphase" }
+Number:Energy ForwardActiveFundamentalEnergy { channel="mecmeter:meter:1:fwd_active_fund_energy_group#fwd_active_fund_energy_allphase" }
+Number:Energy ForwardActiveHarmonicEnergy { channel="mecmeter:meter:1:fwd_active_harm_energy_group#fwd_active_harm_energy_allphase" }
+Number:Energy ForwardReactiveEnergy { channel="mecmeter:meter:1:fwd_reactive_energy_group#fwd_reactive_energy_allphase" }
+
+Number:Energy FwdActiveEnergyP1 { channel="mecmeter:meter:1:fwd_active_energy_group#fwd_active_energy_phase1" }
+Number:Energy FwdActiveEnergyP2 { channel="mecmeter:meter:1:fwd_active_energy_group#fwd_active_energy_phase2" }
+Number:Energy FwdActiveEnergyP3 { channel="mecmeter:meter:1:fwd_active_energy_group#fwd_active_energy_phase3" }
+
+Number:Energy FwdActiveFundEnergyP1 { channel="mecmeter:meter:1:fwd_active_fund_energy_group#fwd_active_fund_energy_phase1" }
+Number:Energy FwdActiveFundEnergyP2 { channel="mecmeter:meter:1:fwd_active_fund_energy_group#fwd_active_fund_energy_phase2" }
+Number:Energy FwdActiveFundEnergyP3 { channel="mecmeter:meter:1:fwd_active_fund_energy_group#fwd_active_fund_energy_phase3" }
+
+Number:Energy FwdActiveHarmEnergyP1 { channel="mecmeter:meter:1:fwd_active_harm_energy_group#fwd_active_harm_energy_phase1" }
+Number:Energy FwdActiveHarmEnergyP2 { channel="mecmeter:meter:1:fwd_active_harm_energy_group#fwd_active_harm_energy_phase2" }
+Number:Energy FwdActiveHarmEnergyP3 { channel="mecmeter:meter:1:fwd_active_harm_energy_group#fwd_active_harm_energy_phase3" }
+
+Number:Energy FwdReactiveEnergyP1 { channel="mecmeter:meter:1:fwd_reactive_energy_group#fwd_reactive_energy_phase1" }
+Number:Energy FwdReactiveEnergyP2 { channel="mecmeter:meter:1:fwd_reactive_energy_group#fwd_reactive_energy_phase2" }
+Number:Energy FwdReactiveEnergyP3 { channel="mecmeter:meter:1:fwd_reactive_energy_group#fwd_reactive_energy_phase3" }
+
+Number:Energy PowerFactor { channel="mecmeter:meter:1:powerfactor_group#powerFactor_allphase" }
+Number:Energy PowerFactorP1 { channel="mecmeter:meter:1:powerfactor_group#powerFactor_phase1" }
+Number:Energy PowerFactorP2 { channel="mecmeter:meter:1:powerfactor_group#powerFactor_phase2" }
+Number:Energy PowerFactorP3 { channel="mecmeter:meter:1:powerfactor_group#powerFactor_phase3" }
+
+Number:Power ReactivePower { channel="mecmeter:meter:1:reactivepower_group#reactivepower_allphase" }
+Number:Power ReactivePowerP1 { channel="mecmeter:meter:1:reactivepower_group#reactivepower_phase1" }
+Number:Power ReactivePowerP2 { channel="mecmeter:meter:1:reactivepower_group#reactivepower_phase2" }
+Number:Power ReactivePowerP3 { channel="mecmeter:meter:1:reactivepower_group#reactivepower_phase3" }
+
+Number:Energy ReverseActiveEnergy { channel="mecmeter:meter:1:rev_active_energy_group#rev_active_energy_allphase" }
+Number:Energy RevActiveEnergyP1 { channel="mecmeter:meter:1:rev_active_energy_group#rev_active_energy_phase1" }
+Number:Energy RevActiveEnergyP2 { channel="mecmeter:meter:1:rev_active_energy_group#rev_active_energy_phase2" }
+Number:Energy RevActiveEnergyP3 { channel="mecmeter:meter:1:rev_active_energy_group#rev_active_energy_phase3" }
+
+Number:Energy ReverseActiveFundamentalEnergy { channel="mecmeter:meter:1:rev_active_fund_energy_group#rev_active_fund_energy_allphase" }
+Number:Energy RevActiveFundEnergyP1 { channel="mecmeter:meter:1:rev_active_fund_energy_group#rev_active_fund_energy_phase1" }
+Number:Energy RevActiveFundEnergyP2 { channel="mecmeter:meter:1:rev_active_fund_energy_group#rev_active_fund_energy_phase2" }
+Number:Energy RevActiveFundEnergyP3 { channel="mecmeter:meter:1:rev_active_fund_energy_group#rev_active_fund_energy_phase3" }
+
+Number:Energy ReverseActiveHarmonicEnergy { channel="mecmeter:meter:1:rev_active_harm_energy_group#rev_active_harm_energy_allphase" }
+Number:Energy RevActiveHarmEnergyP1 { channel="mecmeter:meter:1:rev_active_harm_energy_group#rev_active_harm_energy_phase1" }
+Number:Energy RevActiveHarmEnergyP2 { channel="mecmeter:meter:1:rev_active_harm_energy_group#rev_active_harm_energy_phase2" }
+Number:Energy RevActiveHarmEnergyP3 { channel="mecmeter:meter:1:rev_active_harm_energy_group#rev_active_harm_energy_phase3" }
+
+Number:Energy ReverseReactiveEnergy { channel="mecmeter:meter:1:rev_reactive_energy_group#rev_reactive_energy_allphase" }
+Number:Energy RevReactiveEnergyP1 { channel="mecmeter:meter:1:rev_reactive_energy_group#rev_reactive_energy_phase1" }
+Number:Energy RevReactiveEnergyP2 { channel="mecmeter:meter:1:rev_reactive_energy_group#rev_reactive_energy_phase2" }
+Number:Energy RevReactiveEnergyP3 { channel="mecmeter:meter:1:rev_reactive_energy_group#rev_reactive_energy_phase3" }
+```
+
+### mecmeter.sitemap
+
+```
+sitemap mecmeter label="MecMeter"
+{
+    Frame label="General" {
+            Text item=MainFrequency
+            Text item=InternalTemperature
+    }
+
+    Frame label="Power" {
+        Text item=ActivePower
+        Text item=ActivePowerP1
+        Text item=ActivePowerP2
+        Text item=ActivePowerP3
+    }
+
+    Frame label="Electric Potential" {
+        Text item=VoltageP1
+        Text item=VoltageP2
+        Text item=VoltageP3
+    }
+    
+}
+```
diff --git a/bundles/org.openhab.binding.mecmeter/pom.xml b/bundles/org.openhab.binding.mecmeter/pom.xml
new file mode 100644 (file)
index 0000000..3f454ba
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.openhab.addons.bundles</groupId>
+    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+    <version>3.1.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.binding.mecmeter</artifactId>
+
+  <name>openHAB Add-ons :: Bundles :: mecMeter Binding</name>
+
+</project>
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/feature/feature.xml b/bundles/org.openhab.binding.mecmeter/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..2ddad66
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.mecmeter-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
+       <repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
+
+       <feature name="openhab-binding-mecmeter" description="mecMeter Binding" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.mecmeter/${project.version}</bundle>
+       </feature>
+</features>
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/MecMeterBindingConstants.java b/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/MecMeterBindingConstants.java
new file mode 100644 (file)
index 0000000..b594cf4
--- /dev/null
@@ -0,0 +1,210 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mecmeter;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link MecMeterBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Florian Pazour - Initial contribution
+ * @author Klaus Berger - Initial contribution
+ */
+@NonNullByDefault
+public class MecMeterBindingConstants {
+
+    private static final String BINDING_ID = "mecmeter";
+
+    // List of all Thing Type UIDs
+    public static final ThingTypeUID THING_TYPE_METER = new ThingTypeUID(BINDING_ID, "meter");
+
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_METER);
+
+    /*
+     * List of all Groups
+     */
+    public static final String GENERAL_GROUP = "general_group";
+    public static final String VOLTAGE_GROUP = "voltage_group";
+    public static final String CURRENT_GROUP = "current_group";
+    public static final String ANGLE_GROUP = "angle_group";
+
+    public static final String ACTIVE_POWER_GROUP = "activepower_group";
+    public static final String ACTIVE_FUND_POWER_GROUP = "activefundpower_group";
+    public static final String POWER_FACTOR_GROUP = "powerfactor_group";
+    public static final String ACTIVE_HARM_POWER_GROUP = "activeharmpower_group";
+    public static final String REACTIVE_POWER_GROUP = "reactivepower_group";
+
+    public static final String APP_POWER_GROUP = "apppower_group";
+
+    public static final String FWD_ACTIVE_ENERGY_GROUP = "fwd_active_energy_group";
+    public static final String FWD_ACTIVE_FUND_ENERGY_GROUP = "fwd_active_fund_energy_group";
+    public static final String FWD_ACTIVE_HARM_ENERGY_GROUP = "fwd_active_harm_energy_group";
+    public static final String FWD_REACTIVE_ENERGY_GROUP = "fwd_reactive_energy_group";
+
+    public static final String REV_ACTIVE_ENERGY_GROUP = "rev_active_energy_group";
+    public static final String REV_ACTIVE_FUND_ENERGY_GROUP = "rev_active_fund_energy_group";
+    public static final String REV_ACTIVE_HARM_ENERGY_GROUP = "rev_active_harm_energy_group";
+    public static final String REV_REACTIVE_ENERGY_GROUP = "rev_reactive_energy_group";
+
+    public static final String APP_ENERGY_GROUP = "app_energy_group";
+
+    /*
+     * List of all Channels
+     */
+    // General Channels
+    public static final String FREQUENCY = GENERAL_GROUP + "#" + "frequency";
+    public static final String TEMPERATURE = GENERAL_GROUP + "#" + "temperature";
+    public static final String OPERATIONAL_TIME = GENERAL_GROUP + "#" + "op_time";
+
+    // Voltage Channels
+    public static final String VOLTAGE_PHASE_1 = VOLTAGE_GROUP + "#" + "voltage_phase1";
+    public static final String VOLTAGE_PHASE_2 = VOLTAGE_GROUP + "#" + "voltage_phase2";
+    public static final String VOLTAGE_PHASE_3 = VOLTAGE_GROUP + "#" + "voltage_phase3";
+
+    public static final String VOLTAGE_PHASE_3_TO_PHASE_2 = VOLTAGE_GROUP + "#" + "voltage_phase3-2";
+    public static final String VOLTAGE_PHASE_2_TO_PHASE_1 = VOLTAGE_GROUP + "#" + "voltage_phase2-1";
+    public static final String VOLTAGE_PHASE_1_TO_PHASE_3 = VOLTAGE_GROUP + "#" + "voltage_phase1-3";
+
+    public static final String AVERAGE_VOLTAGE_PHASE_2_PHASE = VOLTAGE_GROUP + "#" + "avg_phase_phase_voltage";
+    public static final String AVERAGE_VOLTAGE_NEUTRAL_2_PHASE = VOLTAGE_GROUP + "#" + "avg_neutral_phase_voltage";
+
+    // Current Channels
+    public static final String CURRENT_PHASE_1 = CURRENT_GROUP + "#" + "current_phase1";
+    public static final String CURRENT_PHASE_2 = CURRENT_GROUP + "#" + "current_phase2";
+    public static final String CURRENT_PHASE_3 = CURRENT_GROUP + "#" + "current_phase3";
+    public static final String CURRENT_SUM = CURRENT_GROUP + "#" + "current_allphase";
+
+    // Angle Channels
+    public static final String PHASE_ANGLE_TO_CURRENT_PHASE_1 = ANGLE_GROUP + "#" + "phase_angle_currvolt_phase1";
+    public static final String PHASE_ANGLE_TO_CURRENT_PHASE_2 = ANGLE_GROUP + "#" + "phase_angle_currvolt_phase2";
+    public static final String PHASE_ANGLE_TO_CURRENT_PHASE_3 = ANGLE_GROUP + "#" + "phase_angle_currvolt_phase3";
+
+    public static final String PHASE_ANGLE_PHASE_1_3 = ANGLE_GROUP + "#" + "phase_angle_phase1-3";
+    public static final String PHASE_ANGLE_PHASE_2_3 = ANGLE_GROUP + "#" + "phase_angle_phase2-3";
+
+    // Power Channels
+    public static final String ACTIVE_POWER_PHASE_1 = ACTIVE_POWER_GROUP + "#" + "activepower_phase1";
+    public static final String ACTIVE_POWER_PHASE_2 = ACTIVE_POWER_GROUP + "#" + "activepower_phase2";
+    public static final String ACTIVE_POWER_PHASE_3 = ACTIVE_POWER_GROUP + "#" + "activepower_phase3";
+    public static final String ACTIVE_POWER_SUM = ACTIVE_POWER_GROUP + "#" + "activepower_allphase";
+
+    public static final String ACTIVE_FUND_POWER_PHASE_1 = ACTIVE_FUND_POWER_GROUP + "#" + "activefundpower_phase1";
+    public static final String ACTIVE_FUND_POWER_PHASE_2 = ACTIVE_FUND_POWER_GROUP + "#" + "activefundpower_phase2";
+    public static final String ACTIVE_FUND_POWER_PHASE_3 = ACTIVE_FUND_POWER_GROUP + "#" + "activefundpower_phase3";
+    public static final String ACTIVE_FUND_POWER_ALL = ACTIVE_FUND_POWER_GROUP + "#" + "activefundpower_allphase";
+
+    public static final String POWER_FACTOR_PHASE_1 = POWER_FACTOR_GROUP + "#" + "powerFactor_phase1";
+    public static final String POWER_FACTOR_PHASE_2 = POWER_FACTOR_GROUP + "#" + "powerFactor_phase2";
+    public static final String POWER_FACTOR_PHASE_3 = POWER_FACTOR_GROUP + "#" + "powerFactor_phase3";
+    public static final String POWER_FACTOR_ALL = POWER_FACTOR_GROUP + "#" + "powerFactor_allphase";
+
+    public static final String ACTIVE_HARM_POWER_PHASE_1 = ACTIVE_HARM_POWER_GROUP + "#" + "activeharmpower_phase1";
+    public static final String ACTIVE_HARM_POWER_PHASE_2 = ACTIVE_HARM_POWER_GROUP + "#" + "activeharmpower_phase2";
+    public static final String ACTIVE_HARM_POWER_PHASE_3 = ACTIVE_HARM_POWER_GROUP + "#" + "activeharmpower_phase3";
+    public static final String ACTIVE_HARM_POWER_ALL = ACTIVE_HARM_POWER_GROUP + "#" + "activeharmpower_allphase";
+
+    public static final String REACTIVE_POWER_PHASE_1 = REACTIVE_POWER_GROUP + "#" + "reactivepower_phase1";
+    public static final String REACTIVE_POWER_PHASE_2 = REACTIVE_POWER_GROUP + "#" + "reactivepower_phase2";
+    public static final String REACTIVE_POWER_PHASE_3 = REACTIVE_POWER_GROUP + "#" + "reactivepower_phase3";
+    public static final String REACTIVE_POWER_ALL = REACTIVE_POWER_GROUP + "#" + "reactivepower_allphase";
+
+    public static final String APP_POWER_PHASE_1 = APP_POWER_GROUP + "#" + "apppower_phase1";
+    public static final String APP_POWER_PHASE_2 = APP_POWER_GROUP + "#" + "apppower_phase2";
+    public static final String APP_POWER_PHASE_3 = APP_POWER_GROUP + "#" + "apppower_phase3";
+    public static final String APP_POWER_ALL = APP_POWER_GROUP + "#" + "apppower_allphase";
+
+    // Forward Energy Channels
+    public static final String FORWARD_ACTIVE_ENERGY_PHASE_1 = FWD_ACTIVE_ENERGY_GROUP + "#"
+            + "fwd_active_energy_phase1";
+    public static final String FORWARD_ACTIVE_ENERGY_PHASE_2 = FWD_ACTIVE_ENERGY_GROUP + "#"
+            + "fwd_active_energy_phase2";
+    public static final String FORWARD_ACTIVE_ENERGY_PHASE_3 = FWD_ACTIVE_ENERGY_GROUP + "#"
+            + "fwd_active_energy_phase3";
+    public static final String FORWARD_ACTIVE_ENERGY_ALL = FWD_ACTIVE_ENERGY_GROUP + "#" + "fwd_active_energy_allphase";
+
+    public static final String FORWARD_ACTIVE_FUND_ENERGY_PHASE_1 = FWD_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "fwd_active_fund_energy_phase1";
+    public static final String FORWARD_ACTIVE_FUND_ENERGY_PHASE_2 = FWD_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "fwd_active_fund_energy_phase2";
+    public static final String FORWARD_ACTIVE_FUND_ENERGY_PHASE_3 = FWD_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "fwd_active_fund_energy_phase3";
+    public static final String FORWARD_ACTIVE_FUND_ENERGY_ALL = FWD_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "fwd_active_fund_energy_allphase";
+
+    public static final String FORWARD_ACTIVE_HARM_ENERGY_PHASE_1 = FWD_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "fwd_active_harm_energy_phase1";
+    public static final String FORWARD_ACTIVE_HARM_ENERGY_PHASE_2 = FWD_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "fwd_active_harm_energy_phase2";
+    public static final String FORWARD_ACTIVE_HARM_ENERGY_PHASE_3 = FWD_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "fwd_active_harm_energy_phase3";
+    public static final String FORWARD_ACTIVE_HARM_ENERGY_ALL = FWD_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "fwd_active_harm_energy_allphase";
+
+    public static final String FORWARD_REACTIVE_ENERGY_PHASE_1 = FWD_REACTIVE_ENERGY_GROUP + "#"
+            + "fwd_reactive_energy_phase1";
+    public static final String FORWARD_REACTIVE_ENERGY_PHASE_2 = FWD_REACTIVE_ENERGY_GROUP + "#"
+            + "fwd_reactive_energy_phase2";
+    public static final String FORWARD_REACTIVE_ENERGY_PHASE_3 = FWD_REACTIVE_ENERGY_GROUP + "#"
+            + "fwd_reactive_energy_phase3";
+    public static final String FORWARD_REACTIVE_ENERGY_ALL = FWD_REACTIVE_ENERGY_GROUP + "#"
+            + "fwd_reactive_energy_allphase";
+
+    // Reverse Energy Channels
+    public static final String REVERSE_ACTIVE_ENERGY_PHASE_1 = REV_ACTIVE_ENERGY_GROUP + "#"
+            + "rev_active_energy_phase1";
+    public static final String REVERSE_ACTIVE_ENERGY_PHASE_2 = REV_ACTIVE_ENERGY_GROUP + "#"
+            + "rev_active_energy_phase2";
+    public static final String REVERSE_ACTIVE_ENERGY_PHASE_3 = REV_ACTIVE_ENERGY_GROUP + "#"
+            + "rev_active_energy_phase3";
+    public static final String REVERSE_ACTIVE_ENERGY_ALL = REV_ACTIVE_ENERGY_GROUP + "#" + "rev_active_energy_allphase";
+
+    public static final String REVERSE_ACTIVE_FUND_ENERGY_PHASE_1 = REV_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "rev_active_fund_energy_phase1";
+    public static final String REVERSE_ACTIVE_FUND_ENERGY_PHASE_2 = REV_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "rev_active_fund_energy_phase2";
+    public static final String REVERSE_ACTIVE_FUND_ENERGY_PHASE_3 = REV_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "rev_active_fund_energy_phase3";
+    public static final String REVERSE_ACTIVE_FUND_ENERGY_ALL = REV_ACTIVE_FUND_ENERGY_GROUP + "#"
+            + "rev_active_fund_energy_allphase";
+
+    public static final String REVERSE_ACTIVE_HARM_ENERGY_PHASE_1 = REV_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "rev_active_harm_energy_phase1";
+    public static final String REVERSE_ACTIVE_HARM_ENERGY_PHASE_2 = REV_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "rev_active_harm_energy_phase2";
+    public static final String REVERSE_ACTIVE_HARM_ENERGY_PHASE_3 = REV_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "rev_active_harm_energy_phase3";
+    public static final String REVERSE_ACTIVE_HARM_ENERGY_ALL = REV_ACTIVE_HARM_ENERGY_GROUP + "#"
+            + "rev_active_harm_energy_allphase";
+
+    public static final String REVERSE_REACTIVE_ENERGY_PHASE_1 = REV_REACTIVE_ENERGY_GROUP + "#"
+            + "rev_reactive_energy_phase1";
+    public static final String REVERSE_REACTIVE_ENERGY_PHASE_2 = REV_REACTIVE_ENERGY_GROUP + "#"
+            + "rev_reactive_energy_phase2";
+    public static final String REVERSE_REACTIVE_ENERGY_PHASE_3 = REV_REACTIVE_ENERGY_GROUP + "#"
+            + "rev_reactive_energy_phase3";
+    public static final String REVERSE_REACTIVE_ENERGY_ALL = REV_REACTIVE_ENERGY_GROUP + "#"
+            + "rev_reactive_energy_allphase";
+
+    // Apparent Energy Channels
+    public static final String APP_ENERGY_PHASE_1 = APP_ENERGY_GROUP + "#" + "appenergy_consumption_phase1";
+    public static final String APP_ENERGY_PHASE_2 = APP_ENERGY_GROUP + "#" + "appenergy_consumption_phase2";
+    public static final String APP_ENERGY_PHASE_3 = APP_ENERGY_GROUP + "#" + "appenergy_consumption_phase3";
+    public static final String APP_ENERGY_ALL = APP_ENERGY_GROUP + "#" + "appenergy_consumption_allphase";
+
+    // list of all URLs
+    public static final String POWERMETER_DATA_URL = "http://%IP%/wizard/public/api/measurements";
+}
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/MecMeterDeviceConfiguration.java b/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/MecMeterDeviceConfiguration.java
new file mode 100644 (file)
index 0000000..605a167
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mecmeter;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link MecMeterDeviceConfiguration} is the class used to match the
+ * thing configuration.
+ *
+ * @author Florian Pazour - Initial contribution
+ * @author Klaus Berger - Initial contribution
+ */
+@NonNullByDefault
+public class MecMeterDeviceConfiguration {
+    public String ip = "";
+    public String password = "12345";
+    public int refreshInterval = 5;
+
+    public String getIp() {
+        return ip;
+    }
+
+    public void setIp(String inetaddress) {
+        ip = inetaddress;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String pw) {
+        password = pw;
+    }
+
+    public int getRefreshInterval() {
+        return refreshInterval;
+    }
+
+    public void setRefreshInterval(int ri) {
+        refreshInterval = ri;
+    }
+
+    public @Nullable String isValid() {
+        if (ip.isBlank()) {
+            return "Missing IP";
+        }
+        if (password.isBlank()) {
+            return "Password is missing";
+        }
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/handler/MecMeterHandler.java b/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/handler/MecMeterHandler.java
new file mode 100644 (file)
index 0000000..c66aa98
--- /dev/null
@@ -0,0 +1,408 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mecmeter.handler;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.http.HttpHeader;
+import org.eclipse.jetty.http.HttpMethod;
+import org.openhab.binding.mecmeter.MecMeterBindingConstants;
+import org.openhab.binding.mecmeter.MecMeterDeviceConfiguration;
+import org.openhab.binding.mecmeter.internal.dto.MecMeterResponse;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.Units;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.binding.BaseThingHandler;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.State;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonSyntaxException;
+
+/**
+ * The {@link MecMeterHandler} is responsible for handling commands, which are
+ * sent to one of the channels.
+ *
+ * @author Florian Pazour - Initial contribution
+ * @author Klaus Berger - Initial contribution
+ * @author Kai Kreuzer - Refactoring for openHAB 3
+ */
+@NonNullByDefault
+public class MecMeterHandler extends BaseThingHandler {
+
+    private static final int API_TIMEOUT = 5000; // set on 5000ms - not specified in datasheet
+
+    private static final String USERNAME = "admin";
+
+    private final Logger logger = LoggerFactory.getLogger(MecMeterHandler.class);
+
+    private Gson gson = new Gson();
+
+    private final HttpClient httpClient;
+
+    private @Nullable ScheduledFuture<?> pollFuture;
+
+    private @Nullable MecMeterResponse powerMeterResponse;
+
+    public MecMeterHandler(Thing thing, HttpClient httpClient) {
+        super(thing);
+        this.httpClient = httpClient;
+    }
+
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        if (command instanceof RefreshType) {
+            updateChannel(channelUID.getId());
+        } else {
+            logger.debug("Received unsupported command {}.", command);
+        }
+    }
+
+    /**
+     * function which is called to refresh the data
+     */
+    public void refresh() {
+        updateData();
+        updateChannels();
+    }
+
+    @Override
+    public void dispose() {
+        super.dispose();
+        logger.debug("removing thing..");
+        if (pollFuture != null) {
+            pollFuture.cancel(true);
+        }
+    }
+
+    @Override
+    public void initialize() {
+        MecMeterDeviceConfiguration config = getConfig().as(MecMeterDeviceConfiguration.class);
+        String configCheck = config.isValid();
+
+        if (configCheck != null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, configCheck);
+            return;
+        }
+        updateStatus(ThingStatus.UNKNOWN);
+
+        if (pollFuture != null) {
+            pollFuture.cancel(false);
+        }
+        pollFuture = scheduler.scheduleWithFixedDelay(() -> {
+            refresh();
+        }, 0, config.refreshInterval, TimeUnit.SECONDS);
+    }
+
+    /**
+     * Get new data
+     * Function to save Response of the powermeter
+     */
+    private void updateData() {
+        powerMeterResponse = getRealtimeData();
+    }
+
+    /**
+     * Get new realtime data over the network
+     *
+     * @return MecMeterResponse class where json values "are saved"
+     */
+    private @Nullable MecMeterResponse getRealtimeData() {
+        MecMeterResponse result = null;
+        boolean resultOk = false;
+        String errorMsg = null;
+
+        MecMeterDeviceConfiguration config = getConfig().as(MecMeterDeviceConfiguration.class);
+
+        try {
+            String basicAuthentication = "Basic " + Base64.getEncoder()
+                    .encodeToString(new String(USERNAME + ":" + config.password).getBytes(StandardCharsets.ISO_8859_1));
+
+            String location = MecMeterBindingConstants.POWERMETER_DATA_URL.replace("%IP%", config.ip.strip());
+
+            ContentResponse response = httpClient.newRequest(location).method(HttpMethod.GET)
+                    .header(HttpHeader.AUTHORIZATION, basicAuthentication).timeout(API_TIMEOUT, TimeUnit.MILLISECONDS)
+                    .send();
+            if (response.getStatus() != 200) {
+                errorMsg = "Reading meter did not succeed: " + response.getReason();
+                logger.error("Request to meter failed: HTTP {}: {}", response.getStatus(), response.getReason());
+            } else {
+                result = gson.fromJson(response.getContentAsString(), MecMeterResponse.class);
+                if (result == null) {
+                    errorMsg = "no data returned";
+                    logger.error("no data returned from meter at {}", location);
+                } else {
+                    resultOk = true;
+                }
+            }
+        } catch (JsonSyntaxException e) {
+            errorMsg = "Configuration is incorrect";
+            logger.error("Error running power meter request: {}", e.getMessage());
+        } catch (IllegalStateException e) {
+            errorMsg = "Connection failed";
+            logger.error("Error running powermeter request: {}", e.getMessage());
+        } catch (InterruptedException e) {
+            logger.debug("Http request has been interrupted: {}", e.getMessage());
+        } catch (TimeoutException e) {
+            logger.debug("Http request ran into a timeout: {}", e.getMessage());
+            errorMsg = "Connection to power meter timed out.";
+        } catch (ExecutionException e) {
+            logger.debug("Http request did not succeed: {}", e.getMessage());
+            errorMsg = "Connection problem: " + e.getMessage();
+        }
+
+        // Update the thing status
+        if (resultOk) {
+            updateStatus(ThingStatus.ONLINE);
+        } else {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg);
+        }
+
+        return resultOk ? result : null;
+    }
+
+    /**
+     * Update all Channels
+     */
+    protected void updateChannels() {
+        for (Channel channel : getThing().getChannels()) {
+            updateChannel(channel.getUID().getId());
+        }
+    }
+
+    /**
+     * Update the channel state
+     *
+     * @param channelId the id identifying the channel to be updated
+     */
+    protected void updateChannel(String channelId) {
+        if (!isLinked(channelId)) {
+            return;
+        }
+        State state = getState(channelId);
+        if (state != null) {
+            updateState(channelId, state);
+        }
+    }
+
+    /**
+     * Get the state of a given channel
+     *
+     * @param channelId the id identifying the channel to be updated
+     * @return state of the channel
+     */
+    protected @Nullable State getState(String channelId) {
+        MecMeterResponse response = powerMeterResponse;
+        if (response == null) {
+            return null;
+        } else {
+            switch (channelId) {
+                /* General */
+                case MecMeterBindingConstants.FREQUENCY:
+                    return new QuantityType<>(response.getFrequency(), Units.HERTZ);
+                case MecMeterBindingConstants.TEMPERATURE:
+                    return new QuantityType<>(response.getTemperature(), SIUnits.CELSIUS);
+                case MecMeterBindingConstants.OPERATIONAL_TIME:
+                    return new QuantityType<>(response.getOperationalTime() / 1000, Units.SECOND);
+
+                /* Voltage */
+                case MecMeterBindingConstants.VOLTAGE_PHASE_1:
+                    return new QuantityType<>(response.getVoltagePhase1(), Units.VOLT);
+                case MecMeterBindingConstants.VOLTAGE_PHASE_2:
+                    return new QuantityType<>(response.getVoltagePhase2(), Units.VOLT);
+                case MecMeterBindingConstants.VOLTAGE_PHASE_3:
+                    return new QuantityType<>(response.getVoltagePhase3(), Units.VOLT);
+                case MecMeterBindingConstants.VOLTAGE_PHASE_3_TO_PHASE_2:
+                    return new QuantityType<>(response.getVoltagePhase3ToPhase2(), Units.VOLT);
+                case MecMeterBindingConstants.VOLTAGE_PHASE_2_TO_PHASE_1:
+                    return new QuantityType<>(response.getVoltagePhase2ToPhase1(), Units.VOLT);
+                case MecMeterBindingConstants.VOLTAGE_PHASE_1_TO_PHASE_3:
+                    return new QuantityType<>(response.getVoltagePhase1ToPhase3(), Units.VOLT);
+                case MecMeterBindingConstants.AVERAGE_VOLTAGE_PHASE_2_PHASE:
+                    return new QuantityType<>(response.getAverageVoltagePhaseToPhase(), Units.VOLT);
+                case MecMeterBindingConstants.AVERAGE_VOLTAGE_NEUTRAL_2_PHASE:
+                    return new QuantityType<>(response.getAverageVoltageNeutralToPhase(), Units.VOLT);
+
+                /* Current */
+                case MecMeterBindingConstants.CURRENT_PHASE_1:
+                    return new QuantityType<>(response.getCurrentPhase1(), Units.AMPERE);
+                case MecMeterBindingConstants.CURRENT_PHASE_2:
+                    return new QuantityType<>(response.getCurrentPhase2(), Units.AMPERE);
+                case MecMeterBindingConstants.CURRENT_PHASE_3:
+                    return new QuantityType<>(response.getCurrentPhase3(), Units.AMPERE);
+                case MecMeterBindingConstants.CURRENT_SUM:
+                    return new QuantityType<>(response.getCurrentSum(), Units.AMPERE);
+
+                /* Angles */
+                case MecMeterBindingConstants.PHASE_ANGLE_TO_CURRENT_PHASE_1:
+                    return new QuantityType<>(response.getPhaseAngleCurrentToVoltagePhase1(), Units.DEGREE_ANGLE);
+                case MecMeterBindingConstants.PHASE_ANGLE_TO_CURRENT_PHASE_2:
+                    return new QuantityType<>(response.getPhaseAngleCurrentToVoltagePhase2(), Units.DEGREE_ANGLE);
+                case MecMeterBindingConstants.PHASE_ANGLE_TO_CURRENT_PHASE_3:
+                    return new QuantityType<>(response.getPhaseAngleCurrentToVoltagePhase3(), Units.DEGREE_ANGLE);
+                case MecMeterBindingConstants.PHASE_ANGLE_PHASE_1_3:
+                    return new QuantityType<>(response.getPhaseAnglePhase1To3(), Units.DEGREE_ANGLE);
+                case MecMeterBindingConstants.PHASE_ANGLE_PHASE_2_3:
+                    return new QuantityType<>(response.getPhaseAnglePhase2To3(), Units.DEGREE_ANGLE);
+
+                /* Power */
+                case MecMeterBindingConstants.ACTIVE_POWER_PHASE_1:
+                    return new QuantityType<>(response.getActivePowerPhase1(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_POWER_PHASE_2:
+                    return new QuantityType<>(response.getActivePowerPhase2(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_POWER_PHASE_3:
+                    return new QuantityType<>(response.getActivePowerPhase3(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_POWER_SUM:
+                    return new QuantityType<>(response.getActivePowerSum(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_FUND_POWER_PHASE_1:
+                    return new QuantityType<>(response.getActiveFundamentalPowerPhase1(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_FUND_POWER_PHASE_2:
+                    return new QuantityType<>(response.getActiveFundamentalPowerPhase2(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_FUND_POWER_PHASE_3:
+                    return new QuantityType<>(response.getActiveFundamentalPowerPhase3(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_FUND_POWER_ALL:
+                    return new QuantityType<>(response.getActiveFundamentalPowerSum(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_HARM_POWER_PHASE_1:
+                    return new QuantityType<>(response.getActiveHarmonicPowerPhase1(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_HARM_POWER_PHASE_2:
+                    return new QuantityType<>(response.getActiveHarmonicPowerPhase2(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_HARM_POWER_PHASE_3:
+                    return new QuantityType<>(response.getActiveHarmonicPowerPhase3(), Units.WATT);
+                case MecMeterBindingConstants.ACTIVE_HARM_POWER_ALL:
+                    return new QuantityType<>(response.getActiveHarmonicPowerSum(), Units.WATT);
+                case MecMeterBindingConstants.REACTIVE_POWER_PHASE_1:
+                    return new QuantityType<>(response.getReactivePowerPhase1(), Units.VAR);
+                case MecMeterBindingConstants.REACTIVE_POWER_PHASE_2:
+                    return new QuantityType<>(response.getReactivePowerPhase2(), Units.VAR);
+                case MecMeterBindingConstants.REACTIVE_POWER_PHASE_3:
+                    return new QuantityType<>(response.getReactivePowerPhase3(), Units.VAR);
+                case MecMeterBindingConstants.REACTIVE_POWER_ALL:
+                    return new QuantityType<>(response.getReactivePowerSum(), Units.VAR);
+                case MecMeterBindingConstants.APP_POWER_PHASE_1:
+                    return new QuantityType<>(response.getApparentPowerPhase1(), Units.VOLT_AMPERE);
+                case MecMeterBindingConstants.APP_POWER_PHASE_2:
+                    return new QuantityType<>(response.getApparentPowerPhase2(), Units.VOLT_AMPERE);
+                case MecMeterBindingConstants.APP_POWER_PHASE_3:
+                    return new QuantityType<>(response.getApparentPowerPhase3(), Units.VOLT_AMPERE);
+                case MecMeterBindingConstants.APP_POWER_ALL:
+                    return new QuantityType<>(response.getApparentPowerSum(), Units.VOLT_AMPERE);
+
+                /* Forward Energy */
+                case MecMeterBindingConstants.FORWARD_ACTIVE_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getForwardActiveEnergyPhase1(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getForwardActiveEnergyPhase2(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getForwardActiveEnergyPhase3(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_ENERGY_ALL:
+                    return new QuantityType<>(response.getForwardActiveEnergySum(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_FUND_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getForwardActiveFundamentalEnergyPhase1(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_FUND_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getForwardActiveFundamentalEnergyPhase2(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_FUND_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getForwardActiveFundamentalEnergyPhase3(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_FUND_ENERGY_ALL:
+                    return new QuantityType<>(response.getForwardActiveFundamentalEnergySum(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_HARM_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getForwardActiveHarmonicEnergyPhase1(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_HARM_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getForwardActiveHarmonicEnergyPhase2(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_HARM_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getForwardActiveHarmonicEnergyPhase3(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_ACTIVE_HARM_ENERGY_ALL:
+                    return new QuantityType<>(response.getForwardActiveHarmonicEnergySum(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.FORWARD_REACTIVE_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getForwardReactiveEnergyPhase1(), Units.VAR_HOUR);
+                case MecMeterBindingConstants.FORWARD_REACTIVE_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getForwardReactiveEnergyPhase2(), Units.VAR_HOUR);
+                case MecMeterBindingConstants.FORWARD_REACTIVE_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getForwardReactiveEnergyPhase3(), Units.VAR_HOUR);
+                case MecMeterBindingConstants.FORWARD_REACTIVE_ENERGY_ALL:
+                    return new QuantityType<>(response.getForwardReactiveEnergySum(), Units.VAR_HOUR);
+
+                /* Reverse Energy */
+                case MecMeterBindingConstants.REVERSE_ACTIVE_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getReverseActiveEnergyPhase1(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getReverseActiveEnergyPhase2(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getReverseActiveEnergyPhase3(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_ENERGY_ALL:
+                    return new QuantityType<>(response.getReverseActiveEnergySum(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_FUND_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getReverseActiveFundamentalEnergyPhase1(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_FUND_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getReverseActiveFundamentalEnergyPhase2(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_FUND_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getReverseActiveFundamentalEnergyPhase3(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_FUND_ENERGY_ALL:
+                    return new QuantityType<>(response.getReverseActiveFundamentalEnergySum(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_HARM_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getReverseActiveHarmonicEnergyPhase1(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_HARM_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getReverseActiveHarmonicEnergyPhase2(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_HARM_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getReverseActiveHarmonicEnergyPhase3(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_ACTIVE_HARM_ENERGY_ALL:
+                    return new QuantityType<>(response.getReverseActiveHarmonicEnergySum(), Units.KILOWATT_HOUR);
+                case MecMeterBindingConstants.REVERSE_REACTIVE_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getReverseReactiveEnergyPhase1(), Units.VAR_HOUR);
+                case MecMeterBindingConstants.REVERSE_REACTIVE_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getReverseReactiveEnergyPhase2(), Units.VAR_HOUR);
+                case MecMeterBindingConstants.REVERSE_REACTIVE_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getReverseReactiveEnergyPhase3(), Units.VAR_HOUR);
+                case MecMeterBindingConstants.REVERSE_REACTIVE_ENERGY_ALL:
+                    return new QuantityType<>(response.getReverseReactiveEnergySum(), Units.VAR_HOUR);
+
+                /* Apparent Energy */
+                case MecMeterBindingConstants.APP_ENERGY_PHASE_1:
+                    return new QuantityType<>(response.getApparentEnergyConsumptionPhase1(), Units.VOLT_AMPERE_HOUR);
+                case MecMeterBindingConstants.APP_ENERGY_PHASE_2:
+                    return new QuantityType<>(response.getApparentEnergyConsumptionPhase2(), Units.VOLT_AMPERE_HOUR);
+                case MecMeterBindingConstants.APP_ENERGY_PHASE_3:
+                    return new QuantityType<>(response.getApparentEnergyConsumptionPhase3(), Units.VOLT_AMPERE_HOUR);
+                case MecMeterBindingConstants.APP_ENERGY_ALL:
+                    return new QuantityType<>(response.getApparentEnergyConsumptionSum(), Units.VOLT_AMPERE_HOUR);
+
+                /* Power Factor */
+                case MecMeterBindingConstants.POWER_FACTOR_PHASE_1:
+                    return new QuantityType<>(response.getPowerFactorPhase1(), Units.ONE);
+                case MecMeterBindingConstants.POWER_FACTOR_PHASE_2:
+                    return new QuantityType<>(response.getPowerFactorPhase2(), Units.ONE);
+                case MecMeterBindingConstants.POWER_FACTOR_PHASE_3:
+                    return new QuantityType<>(response.getPowerFactorPhase3(), Units.ONE);
+                case MecMeterBindingConstants.POWER_FACTOR_ALL:
+                    return new QuantityType<>(response.getPowerFactorSum(), Units.ONE);
+            }
+        }
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/MecMeterHandlerFactory.java b/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/MecMeterHandlerFactory.java
new file mode 100644 (file)
index 0000000..f26fca1
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mecmeter.internal;
+
+import static org.openhab.binding.mecmeter.MecMeterBindingConstants.THING_TYPE_METER;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.jetty.client.HttpClient;
+import org.openhab.binding.mecmeter.MecMeterBindingConstants;
+import org.openhab.binding.mecmeter.handler.MecMeterHandler;
+import org.openhab.core.io.net.http.HttpClientFactory;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.binding.BaseThingHandlerFactory;
+import org.openhab.core.thing.binding.ThingHandler;
+import org.openhab.core.thing.binding.ThingHandlerFactory;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+/**
+ * The {@link MecMeterHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Florian Pazour - Initial contribution
+ * @author Klaus Berger - Initial contribution
+ * @author Kai Kreuzer - Refactoring for openHAB 3
+ */
+@NonNullByDefault
+@Component(service = ThingHandlerFactory.class, configurationPid = "binding.mecmeter")
+public class MecMeterHandlerFactory extends BaseThingHandlerFactory {
+
+    private final HttpClient httpClient;
+
+    @Activate
+    public MecMeterHandlerFactory(@Reference HttpClientFactory httpClientFactory) {
+        httpClient = httpClientFactory.getCommonHttpClient();
+    }
+
+    @Override
+    public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+        return MecMeterBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
+    }
+
+    @Override
+    protected @Nullable ThingHandler createHandler(Thing thing) {
+        ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+
+        if (thingTypeUID.equals(THING_TYPE_METER)) {
+            return new MecMeterHandler(thing, httpClient);
+        }
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/discovery/MecMeterDiscoveryParticipant.java b/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/discovery/MecMeterDiscoveryParticipant.java
new file mode 100644 (file)
index 0000000..b6b6762
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mecmeter.internal.discovery;
+
+import static org.openhab.binding.mecmeter.MecMeterBindingConstants.THING_TYPE_METER;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.jmdns.ServiceInfo;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.mecmeter.MecMeterBindingConstants;
+import org.openhab.core.config.discovery.DiscoveryResult;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingTypeUID;
+import org.openhab.core.thing.ThingUID;
+import org.osgi.service.component.annotations.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link MecMeterDiscoveryParticipant} is responsible for discovering devices, which are
+ * sent to inbox.
+ *
+ * @author Florian Pazour - Initial contribution
+ * @author Klaus Berger - Initial contribution
+ * @author Kai Kreuzer - Refactoring for openHAB 3
+ */
+@NonNullByDefault
+@Component(service = MDNSDiscoveryParticipant.class)
+public class MecMeterDiscoveryParticipant implements MDNSDiscoveryParticipant {
+
+    private Logger logger = LoggerFactory.getLogger(MecMeterDiscoveryParticipant.class);
+    private static final String SERVICE_TYPE = "_http._tcp.local.";
+
+    /**
+     * Match the serial number, vendor and model of the discovered PowerMeter.
+     * Input is like "vpmAA11BB33CC55"
+     */
+    private static final Pattern MECMETER_PATTERN = Pattern
+            .compile("^(vpm|mec)[A-F0-9]{12}\\._http\\._tcp\\.local\\.$");
+
+    @Override
+    public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
+        return MecMeterBindingConstants.SUPPORTED_THING_TYPES_UIDS;
+    }
+
+    @Override
+    public String getServiceType() {
+        return SERVICE_TYPE;
+    }
+
+    @Override
+    public @Nullable DiscoveryResult createResult(ServiceInfo service) {
+        String qualifiedName = service.getQualifiedName();
+        logger.debug("Device found: {}", qualifiedName);
+        ThingUID uid = getThingUID(service);
+        if (uid == null) {
+            return null;
+        }
+
+        String serial = qualifiedName.substring(3, 15);
+        String vendor = "MEC";
+
+        InetAddress ip = getIpAddress(service);
+        if (ip == null) {
+            return null;
+        }
+        String inetAddress = ip.toString().substring(1);
+
+        Map<String, Object> properties = new HashMap<>(3);
+        properties.put(Thing.PROPERTY_SERIAL_NUMBER, serial);
+        properties.put(Thing.PROPERTY_VENDOR, vendor);
+        properties.put("ip", inetAddress);
+
+        String label = "MEC Power Meter";
+        return DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(label)
+                .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER).build();
+    }
+
+    private @Nullable InetAddress getIpAddress(ServiceInfo service) {
+        if (service.getInet4Addresses().length > 0) {
+            return service.getInet4Addresses()[0];
+        } else {
+            return null;
+        }
+    }
+
+    @Override
+    public @Nullable ThingUID getThingUID(ServiceInfo service) {
+        Matcher matcher = MECMETER_PATTERN.matcher(service.getQualifiedName());
+        if (matcher.matches()) {
+            String serial = service.getQualifiedName().substring(3, 15); // Qualified Name like "mecABCDEF123456", we
+                                                                         // want "ABCDEF123456"
+            return new ThingUID(THING_TYPE_METER, serial);
+        } else {
+            logger.debug("The discovered device is not supported, ignoring it.");
+        }
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/dto/MecMeterResponse.java b/bundles/org.openhab.binding.mecmeter/src/main/java/org/openhab/binding/mecmeter/internal/dto/MecMeterResponse.java
new file mode 100644 (file)
index 0000000..bcd0427
--- /dev/null
@@ -0,0 +1,856 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mecmeter.internal.dto;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link MecMeterResponse} is responsible for storing
+ * the "data" node of the JSON response
+ *
+ * @author Florian Pazour - Initial contribution
+ * @author Klaus Berger - Initial contribution
+ * @author Kai Kreuzer - Refactoring for openHAB 3
+ */
+public class MecMeterResponse {
+    /* General */
+    @SerializedName("F")
+    private float frequency;
+    @SerializedName("T")
+    private float temperature;
+    @SerializedName("TIME")
+    private long operationalTime;
+
+    /* Voltage */
+    @SerializedName("VA")
+    private float voltagePhase1;
+    @SerializedName("VB")
+    private float voltagePhase2;
+    @SerializedName("VC")
+    private float voltagePhase3;
+    @SerializedName("VCB")
+    private float voltagePhase3ToPhase2;
+    @SerializedName("VBA")
+    private float voltagePhase2ToPhase1;
+    @SerializedName("VAC")
+    private float voltagePhase1ToPhase3;
+    @SerializedName("VPT")
+    private float averageVoltagePhaseToPhase;
+    @SerializedName("VT")
+    private float averageVoltageNeutralToPhase;
+
+    /* Current */
+    @SerializedName("IA")
+    private float currentPhase1;
+    @SerializedName("IB")
+    private float currentPhase2;
+    @SerializedName("IC")
+    private float currentPhase3;
+    @SerializedName("IN")
+    private float currentSum;
+
+    /* Angles */
+    @SerializedName("IAA")
+    private float phaseAngleCurrentToVoltagePhase1;
+    @SerializedName("IAB")
+    private float phaseAngleCurrentToVoltagePhase2;
+    @SerializedName("IAC")
+    private float phaseAngleCurrentToVoltagePhase3;
+    @SerializedName("UAA")
+    private float phaseAnglePhase1To3;
+    @SerializedName("UAB")
+    private float phaseAnglePhase2To3;
+
+    /* Power */
+    @SerializedName("PA")
+    private float activePowerPhase1;
+    @SerializedName("PB")
+    private float activePowerPhase2;
+    @SerializedName("PC")
+    private float activePowerPhase3;
+    @SerializedName("PT")
+    private float activePowerSum;
+
+    @SerializedName("PAF")
+    private float activeFundamentalPowerPhase1;
+    @SerializedName("PBF")
+    private float activeFundamentalPowerPhase2;
+    @SerializedName("PCF")
+    private float activeFundamentalPowerPhase3;
+    @SerializedName("PTF")
+    private float activeFundamentalPowerSum;
+
+    @SerializedName("PFA")
+    private float powerFactorPhase1;
+    @SerializedName("PFB")
+    private float powerFactorPhase2;
+    @SerializedName("PFC")
+    private float powerFactorPhase3;
+    @SerializedName("PFT")
+    private float powerFactorSum;
+
+    @SerializedName("PAH")
+    private float activeHarmonicPowerPhase1;
+    @SerializedName("PBH")
+    private float activeHarmonicPowerPhase2;
+    @SerializedName("PCH")
+    private float activeHarmonicPowerPhase3;
+    @SerializedName("PTH")
+    private float activeHarmonicPowerSum;
+
+    @SerializedName("QA")
+    private float reactivePowerPhase1;
+    @SerializedName("QB")
+    private float reactivePowerPhase2;
+    @SerializedName("QC")
+    private float reactivePowerPhase3;
+    @SerializedName("QT")
+    private float reactivePowerSum;
+
+    @SerializedName("SA")
+    private float apparentPowerPhase1;
+    @SerializedName("SB")
+    private float apparentPowerPhase2;
+    @SerializedName("SC")
+    private float apparentPowerPhase3;
+    @SerializedName("ST")
+    private float apparentPowerSum;
+
+    /* Forward Energy */
+    @SerializedName("EFAA")
+    private float forwardActiveEnergyPhase1;
+    @SerializedName("EFAB")
+    private float forwardActiveEnergyPhase2;
+    @SerializedName("EFAC")
+    private float forwardActiveEnergyPhase3;
+    @SerializedName("EFAT")
+    private float forwardActiveEnergySum;
+
+    @SerializedName("EFAF")
+    private float forwardActiveFundamentalEnergyPhase1;
+    @SerializedName("EFBF")
+    private float forwardActiveFundamentalEnergyPhase2;
+    @SerializedName("EFCF")
+    private float forwardActiveFundamentalEnergyPhase3;
+    @SerializedName("EFTF")
+    private float forwardActiveFundamentalEnergySum;
+
+    @SerializedName("EFAH")
+    private float forwardActiveHarmonicEnergyPhase1;
+    @SerializedName("EFBH")
+    private float forwardActiveHarmonicEnergyPhase2;
+    @SerializedName("EFCH")
+    private float forwardActiveHarmonicEnergyPhase3;
+    @SerializedName("EFTH")
+    private float forwardActiveHarmonicEnergySum;
+
+    @SerializedName("EFRA")
+    private float forwardReactiveEnergyPhase1;
+    @SerializedName("EFRB")
+    private float forwardReactiveEnergyPhase2;
+    @SerializedName("EFRC")
+    private float forwardReactiveEnergyPhase3;
+    @SerializedName("EFRT")
+    private float forwardReactiveEnergySum;
+
+    /* Reverse Energy */
+    @SerializedName("ERAA")
+    private float reverseActiveEnergyPhase1;
+    @SerializedName("ERAB")
+    private float reverseActiveEnergyPhase2;
+    @SerializedName("ERAC")
+    private float reverseActiveEnergyPhase3;
+    @SerializedName("ERAT")
+    private float reverseActiveEnergySum;
+
+    @SerializedName("ERAF")
+    private float reverseActiveFundamentalEnergyPhase1;
+    @SerializedName("ERBF")
+    private float reverseActiveFundamentalEnergyPhase2;
+    @SerializedName("ERCF")
+    private float reverseActiveFundamentalEnergyPhase3;
+    @SerializedName("ERTF")
+    private float reverseActiveFundamentalEnergySum;
+
+    @SerializedName("ERAH")
+    private float reverseActiveHarmonicEnergyPhase1;
+    @SerializedName("ERBH")
+    private float reverseActiveHarmonicEnergyPhase2;
+    @SerializedName("ERCH")
+    private float reverseActiveHarmonicEnergyPhase3;
+    @SerializedName("ERTH")
+    private float reverseActiveHarmonicEnergySum;
+
+    @SerializedName("ERRA")
+    private float reverseReactiveEnergyPhase1;
+    @SerializedName("ERRB")
+    private float reverseReactiveEnergyPhase2;
+    @SerializedName("ERRC")
+    private float reverseReactiveEnergyPhase3;
+    @SerializedName("ERRT")
+    private float reverseReactiveEnergySum;
+
+    /* apparent Energy */
+    @SerializedName("ESA")
+    private float apparentEnergyConsumptionPhase1;
+    @SerializedName("ESB")
+    private float apparentEnergyConsumptionPhase2;
+    @SerializedName("ESC")
+    private float apparentEnergyConsumptionPhase3;
+    @SerializedName("EST")
+    private float apparentEnergyConsumptionSum;
+
+    /* Constants */
+    private static final int KILO = 1000;
+
+    /* Getters and Setters */
+    public float getFrequency() {
+        return frequency;
+    }
+
+    public void setFrequency(float frequency) {
+        this.frequency = frequency;
+    }
+
+    public float getTemperature() {
+        return temperature;
+    }
+
+    public void setTemperature(float temperature) {
+        this.temperature = temperature;
+    }
+
+    public long getOperationalTime() {
+        return operationalTime;
+    }
+
+    public void setOperationalTime(long operationalTime) {
+        this.operationalTime = operationalTime;
+    }
+
+    public float getVoltagePhase1() {
+        return voltagePhase1;
+    }
+
+    public void setVoltagePhase1(float voltagePhase1) {
+        this.voltagePhase1 = voltagePhase1;
+    }
+
+    public float getVoltagePhase2() {
+        return voltagePhase2;
+    }
+
+    public void setVoltagePhase2(float voltagePhase2) {
+        this.voltagePhase2 = voltagePhase2;
+    }
+
+    public float getVoltagePhase3() {
+        return voltagePhase3;
+    }
+
+    public void setVoltagePhase3(float voltagePhase3) {
+        this.voltagePhase3 = voltagePhase3;
+    }
+
+    public float getVoltagePhase3ToPhase2() {
+        return voltagePhase3ToPhase2;
+    }
+
+    public void setVoltagePhase3ToPhase2(float voltagePhase3ToPhase2) {
+        this.voltagePhase3ToPhase2 = voltagePhase3ToPhase2;
+    }
+
+    public float getVoltagePhase2ToPhase1() {
+        return voltagePhase2ToPhase1;
+    }
+
+    public void setVoltagePhase2ToPhase1(float voltagePhase2ToPhase1) {
+        this.voltagePhase2ToPhase1 = voltagePhase2ToPhase1;
+    }
+
+    public float getVoltagePhase1ToPhase3() {
+        return voltagePhase1ToPhase3;
+    }
+
+    public void setVoltagePhase1ToPhase3(float voltagePhase1ToPhase3) {
+        this.voltagePhase1ToPhase3 = voltagePhase1ToPhase3;
+    }
+
+    public float getAverageVoltagePhaseToPhase() {
+        return averageVoltagePhaseToPhase;
+    }
+
+    public void setAverageVoltagePhaseToPhase(float averageVoltagePhaseToPhase) {
+        this.averageVoltagePhaseToPhase = averageVoltagePhaseToPhase;
+    }
+
+    public float getAverageVoltageNeutralToPhase() {
+        return averageVoltageNeutralToPhase;
+    }
+
+    public void setAverageVoltageNeutralToPhase(float averageVoltageNeutralToPhase) {
+        this.averageVoltageNeutralToPhase = averageVoltageNeutralToPhase;
+    }
+
+    public float getCurrentPhase1() {
+        return currentPhase1;
+    }
+
+    public void setCurrentPhase1(float currentPhase1) {
+        this.currentPhase1 = currentPhase1;
+    }
+
+    public float getCurrentPhase2() {
+        return currentPhase2;
+    }
+
+    public void setCurrentPhase2(float currentPhase2) {
+        this.currentPhase2 = currentPhase2;
+    }
+
+    public float getCurrentPhase3() {
+        return currentPhase3;
+    }
+
+    public void setCurrentPhase3(float currentPhase3) {
+        this.currentPhase3 = currentPhase3;
+    }
+
+    public float getCurrentSum() {
+        return currentSum;
+    }
+
+    public void setCurrentSum(float currentSum) {
+        this.currentSum = currentSum;
+    }
+
+    public float getPhaseAngleCurrentToVoltagePhase1() {
+        return phaseAngleCurrentToVoltagePhase1;
+    }
+
+    public void setPhaseAngleCurrentToVoltagePhase1(float phaseAngleCurrentToVoltagePhase1) {
+        this.phaseAngleCurrentToVoltagePhase1 = phaseAngleCurrentToVoltagePhase1;
+    }
+
+    public float getPhaseAngleCurrentToVoltagePhase2() {
+        return phaseAngleCurrentToVoltagePhase2;
+    }
+
+    public void setPhaseAngleCurrentToVoltagePhase2(float phaseAngleCurrentToVoltagePhase2) {
+        this.phaseAngleCurrentToVoltagePhase2 = phaseAngleCurrentToVoltagePhase2;
+    }
+
+    public float getPhaseAngleCurrentToVoltagePhase3() {
+        return phaseAngleCurrentToVoltagePhase3;
+    }
+
+    public void setPhaseAngleCurrentToVoltagePhase3(float phaseAngleCurrentToVoltagePhase3) {
+        this.phaseAngleCurrentToVoltagePhase3 = phaseAngleCurrentToVoltagePhase3;
+    }
+
+    public float getPhaseAnglePhase1To3() {
+        return phaseAnglePhase1To3;
+    }
+
+    public void setPhaseAnglePhase1To3(float phaseAnglePhase1To3) {
+        this.phaseAnglePhase1To3 = phaseAnglePhase1To3;
+    }
+
+    public float getPhaseAnglePhase2To3() {
+        return phaseAnglePhase2To3;
+    }
+
+    public void setPhaseAnglePhase2To3(float phaseAnglePhase2To3) {
+        this.phaseAnglePhase2To3 = phaseAnglePhase2To3;
+    }
+
+    public float getActivePowerPhase1() {
+        return activePowerPhase1;
+    }
+
+    public void setActivePowerPhase1(float activePowerPhase1) {
+        this.activePowerPhase1 = activePowerPhase1;
+    }
+
+    public float getActivePowerPhase2() {
+        return activePowerPhase2;
+    }
+
+    public void setActivePowerPhase2(float activePowerPhase2) {
+        this.activePowerPhase2 = activePowerPhase2;
+    }
+
+    public float getActivePowerPhase3() {
+        return activePowerPhase3;
+    }
+
+    public void setActivePowerPhase3(float activePowerPhase3) {
+        this.activePowerPhase3 = activePowerPhase3;
+    }
+
+    public float getActivePowerSum() {
+        return activePowerSum;
+    }
+
+    public void setActivePowerSum(float activePowerSum) {
+        this.activePowerSum = activePowerSum;
+    }
+
+    public float getActiveFundamentalPowerPhase1() {
+        return activeFundamentalPowerPhase1;
+    }
+
+    public void setActiveFundamentalPowerPhase1(float activeFundamentalPowerPhase1) {
+        this.activeFundamentalPowerPhase1 = activeFundamentalPowerPhase1;
+    }
+
+    public float getPowerFactorPhase1() {
+        return powerFactorPhase1;
+    }
+
+    public void setPowerFactorPhase1(float powerFactorPhase1) {
+        this.powerFactorPhase1 = powerFactorPhase1;
+    }
+
+    public float getPowerFactorPhase2() {
+        return powerFactorPhase2;
+    }
+
+    public void setPowerFactorPhase2(float powerFactorPhase2) {
+        this.powerFactorPhase2 = powerFactorPhase2;
+    }
+
+    public float getPowerFactorPhase3() {
+        return powerFactorPhase3;
+    }
+
+    public void setPowerFactorPhase3(float powerFactorPhase3) {
+        this.powerFactorPhase3 = powerFactorPhase3;
+    }
+
+    public float getPowerFactorSum() {
+        return powerFactorSum;
+    }
+
+    public void setPowerFactorSum(float powerFactorSum) {
+        this.powerFactorSum = powerFactorSum;
+    }
+
+    public float getActiveFundamentalPowerPhase2() {
+        return activeFundamentalPowerPhase2;
+    }
+
+    public void setActiveFundamentalPowerPhase2(float activeFundamentalPowerPhase2) {
+        this.activeFundamentalPowerPhase2 = activeFundamentalPowerPhase2;
+    }
+
+    public float getActiveFundamentalPowerPhase3() {
+        return activeFundamentalPowerPhase3;
+    }
+
+    public void setActiveFundamentalPowerPhase3(float activeFundamentalPowerPhase3) {
+        this.activeFundamentalPowerPhase3 = activeFundamentalPowerPhase3;
+    }
+
+    public float getActiveFundamentalPowerSum() {
+        return activeFundamentalPowerSum;
+    }
+
+    public void setActiveFundamentalPowerSum(float activeFundamentalPowerSum) {
+        this.activeFundamentalPowerSum = activeFundamentalPowerSum;
+    }
+
+    public float getActiveHarmonicPowerPhase1() {
+        return activeHarmonicPowerPhase1;
+    }
+
+    public void setActiveHarmonicPowerPhase1(float activeHarmonicPowerPhase1) {
+        this.activeHarmonicPowerPhase1 = activeHarmonicPowerPhase1;
+    }
+
+    public float getActiveHarmonicPowerPhase2() {
+        return activeHarmonicPowerPhase2;
+    }
+
+    public void setActiveHarmonicPowerPhase2(float activeHarmonicPowerPhase2) {
+        this.activeHarmonicPowerPhase2 = activeHarmonicPowerPhase2;
+    }
+
+    public float getActiveHarmonicPowerPhase3() {
+        return activeHarmonicPowerPhase3;
+    }
+
+    public void setActiveHarmonicPowerPhase3(float activeHarmonicPowerPhase3) {
+        this.activeHarmonicPowerPhase3 = activeHarmonicPowerPhase3;
+    }
+
+    public float getActiveHarmonicPowerSum() {
+        return activeHarmonicPowerSum;
+    }
+
+    public void setActiveHarmonicPowerSum(float activeHarmonicPowerSum) {
+        this.activeHarmonicPowerSum = activeHarmonicPowerSum;
+    }
+
+    public float getReactivePowerPhase1() {
+        return reactivePowerPhase1;
+    }
+
+    public void setReactivePowerPhase1(float reactivePowerPhase1) {
+        this.reactivePowerPhase1 = reactivePowerPhase1;
+    }
+
+    public float getReactivePowerPhase2() {
+        return reactivePowerPhase2;
+    }
+
+    public void setReactivePowerPhase2(float reactivePowerPhase2) {
+        this.reactivePowerPhase2 = reactivePowerPhase2;
+    }
+
+    public float getReactivePowerPhase3() {
+        return reactivePowerPhase3;
+    }
+
+    public void setReactivePowerPhase3(float reactivePowerPhase3) {
+        this.reactivePowerPhase3 = reactivePowerPhase3;
+    }
+
+    public float getReactivePowerSum() {
+        return reactivePowerSum;
+    }
+
+    public void setReactivePowerSum(float reactivePowerSum) {
+        this.reactivePowerSum = reactivePowerSum;
+    }
+
+    public float getApparentPowerPhase1() {
+        return apparentPowerPhase1;
+    }
+
+    public void setApparentPowerPhase1(float apparentPowerPhase1) {
+        this.apparentPowerPhase1 = apparentPowerPhase1;
+    }
+
+    public float getApparentPowerPhase2() {
+        return apparentPowerPhase2;
+    }
+
+    public void setApparentPowerPhase2(float apparentPowerPhase2) {
+        this.apparentPowerPhase2 = apparentPowerPhase2;
+    }
+
+    public float getApparentPowerPhase3() {
+        return apparentPowerPhase3;
+    }
+
+    public void setApparentPowerPhase3(float apparentPowerPhase3) {
+        this.apparentPowerPhase3 = apparentPowerPhase3;
+    }
+
+    public float getApparentPowerSum() {
+        return apparentPowerSum;
+    }
+
+    public void setApparentPowerSum(float apparentPowerSum) {
+        this.apparentPowerSum = apparentPowerSum;
+    }
+
+    public float getForwardActiveEnergyPhase1() {
+        return forwardActiveEnergyPhase1 / KILO;
+    }
+
+    public void setForwardActiveEnergyPhase1(float forwardActiveEnergyPhase1) {
+        this.forwardActiveEnergyPhase1 = forwardActiveEnergyPhase1;
+    }
+
+    public float getForwardActiveEnergyPhase2() {
+        return forwardActiveEnergyPhase2 / KILO;
+    }
+
+    public void setForwardActiveEnergyPhase2(float forwardActiveEnergyPhase2) {
+        this.forwardActiveEnergyPhase2 = forwardActiveEnergyPhase2;
+    }
+
+    public float getForwardActiveEnergyPhase3() {
+        return forwardActiveEnergyPhase3 / KILO;
+    }
+
+    public void setForwardActiveEnergyPhase3(float forwardActiveEnergyPhase3) {
+        this.forwardActiveEnergyPhase3 = forwardActiveEnergyPhase3;
+    }
+
+    public float getForwardActiveEnergySum() {
+        return forwardActiveEnergySum / KILO;
+    }
+
+    public void setForwardActiveEnergySum(float forwardActiveEnergySum) {
+        this.forwardActiveEnergySum = forwardActiveEnergySum;
+    }
+
+    public float getForwardActiveFundamentalEnergyPhase1() {
+        return forwardActiveFundamentalEnergyPhase1 / KILO;
+    }
+
+    public void setForwardActiveFundamentalEnergyPhase1(float forwardActiveFundamentalEnergyPhase1) {
+        this.forwardActiveFundamentalEnergyPhase1 = forwardActiveFundamentalEnergyPhase1;
+    }
+
+    public float getForwardActiveFundamentalEnergyPhase2() {
+        return forwardActiveFundamentalEnergyPhase2 / KILO;
+    }
+
+    public void setForwardActiveFundamentalEnergyPhase2(float forwardActiveFundamentalEnergyPhase2) {
+        this.forwardActiveFundamentalEnergyPhase2 = forwardActiveFundamentalEnergyPhase2;
+    }
+
+    public float getForwardActiveFundamentalEnergyPhase3() {
+        return forwardActiveFundamentalEnergyPhase3 / KILO;
+    }
+
+    public void setForwardActiveFundamentalEnergyPhase3(float forwardActiveFundamentalEnergyPhase3) {
+        this.forwardActiveFundamentalEnergyPhase3 = forwardActiveFundamentalEnergyPhase3;
+    }
+
+    public float getForwardActiveFundamentalEnergySum() {
+        return forwardActiveFundamentalEnergySum / KILO;
+    }
+
+    public void setForwardActiveFundamentalEnergySum(float forwardActiveFundamentalEnergySum) {
+        this.forwardActiveFundamentalEnergySum = forwardActiveFundamentalEnergySum;
+    }
+
+    public float getForwardActiveHarmonicEnergyPhase1() {
+        return forwardActiveHarmonicEnergyPhase1 / KILO;
+    }
+
+    public void setForwardActiveHarmonicEnergyPhase1(float forwardActiveHarmonicEnergyPhase1) {
+        this.forwardActiveHarmonicEnergyPhase1 = forwardActiveHarmonicEnergyPhase1;
+    }
+
+    public float getForwardActiveHarmonicEnergyPhase2() {
+        return forwardActiveHarmonicEnergyPhase2 / KILO;
+    }
+
+    public void setForwardActiveHarmonicEnergyPhase2(float forwardActiveHarmonicEnergyPhase2) {
+        this.forwardActiveHarmonicEnergyPhase2 = forwardActiveHarmonicEnergyPhase2;
+    }
+
+    public float getForwardActiveHarmonicEnergyPhase3() {
+        return forwardActiveHarmonicEnergyPhase3 / KILO;
+    }
+
+    public void setForwardActiveHarmonicEnergyPhase3(float forwardActiveHarmonicEnergyPhase3) {
+        this.forwardActiveHarmonicEnergyPhase3 = forwardActiveHarmonicEnergyPhase3;
+    }
+
+    public float getForwardActiveHarmonicEnergySum() {
+        return forwardActiveHarmonicEnergySum / KILO;
+    }
+
+    public void setForwardActiveHarmonicEnergySum(float forwardActiveHarmonicEnergySum) {
+        this.forwardActiveHarmonicEnergySum = forwardActiveHarmonicEnergySum;
+    }
+
+    public float getForwardReactiveEnergyPhase1() {
+        return forwardReactiveEnergyPhase1;
+    }
+
+    public void setForwardReactiveEnergyPhase1(float forwardReactiveEnergyPhase1) {
+        this.forwardReactiveEnergyPhase1 = forwardReactiveEnergyPhase1;
+    }
+
+    public float getForwardReactiveEnergyPhase2() {
+        return forwardReactiveEnergyPhase2;
+    }
+
+    public void setForwardReactiveEnergyPhase2(float forwardReactiveEnergyPhase2) {
+        this.forwardReactiveEnergyPhase2 = forwardReactiveEnergyPhase2;
+    }
+
+    public float getForwardReactiveEnergyPhase3() {
+        return forwardReactiveEnergyPhase3;
+    }
+
+    public void setForwardReactiveEnergyPhase3(float forwardReactiveEnergyPhase3) {
+        this.forwardReactiveEnergyPhase3 = forwardReactiveEnergyPhase3;
+    }
+
+    public float getForwardReactiveEnergySum() {
+        return forwardReactiveEnergySum;
+    }
+
+    public void setForwardReactiveEnergySum(float forwardReactiveEnergySum) {
+        this.forwardReactiveEnergySum = forwardReactiveEnergySum;
+    }
+
+    public float getReverseActiveEnergyPhase1() {
+        return reverseActiveEnergyPhase1 / KILO;
+    }
+
+    public void setReverseActiveEnergyPhase1(float reverseActiveEnergyPhase1) {
+        this.reverseActiveEnergyPhase1 = reverseActiveEnergyPhase1;
+    }
+
+    public float getReverseActiveEnergyPhase2() {
+        return reverseActiveEnergyPhase2 / KILO;
+    }
+
+    public void setReverseActiveEnergyPhase2(float reverseActiveEnergyPhase2) {
+        this.reverseActiveEnergyPhase2 = reverseActiveEnergyPhase2;
+    }
+
+    public float getReverseActiveEnergyPhase3() {
+        return reverseActiveEnergyPhase3 / KILO;
+    }
+
+    public void setReverseActiveEnergyPhase3(float reverseActiveEnergyPhase3) {
+        this.reverseActiveEnergyPhase3 = reverseActiveEnergyPhase3;
+    }
+
+    public float getReverseActiveEnergySum() {
+        return reverseActiveEnergySum / KILO;
+    }
+
+    public void setReverseActiveEnergySum(float reverseActiveEnergySum) {
+        this.reverseActiveEnergySum = reverseActiveEnergySum;
+    }
+
+    public float getReverseActiveFundamentalEnergyPhase1() {
+        return reverseActiveFundamentalEnergyPhase1 / KILO;
+    }
+
+    public void setReverseActiveFundamentalEnergyPhase1(float reverseActiveFundamentalEnergyPhase1) {
+        this.reverseActiveFundamentalEnergyPhase1 = reverseActiveFundamentalEnergyPhase1;
+    }
+
+    public float getReverseActiveFundamentalEnergyPhase2() {
+        return reverseActiveFundamentalEnergyPhase2 / KILO;
+    }
+
+    public void setReverseActiveFundamentalEnergyPhase2(float reverseActiveFundamentalEnergyPhase2) {
+        this.reverseActiveFundamentalEnergyPhase2 = reverseActiveFundamentalEnergyPhase2;
+    }
+
+    public float getReverseActiveFundamentalEnergyPhase3() {
+        return reverseActiveFundamentalEnergyPhase3 / KILO;
+    }
+
+    public void setReverseActiveFundamentalEnergyPhase3(float reverseActiveFundamentalEnergyPhase3) {
+        this.reverseActiveFundamentalEnergyPhase3 = reverseActiveFundamentalEnergyPhase3;
+    }
+
+    public float getReverseActiveFundamentalEnergySum() {
+        return reverseActiveFundamentalEnergySum / KILO;
+    }
+
+    public void setReverseActiveFundamentalEnergySum(float reverseActiveFundamentalEnergySum) {
+        this.reverseActiveFundamentalEnergySum = reverseActiveFundamentalEnergySum;
+    }
+
+    public float getReverseActiveHarmonicEnergyPhase1() {
+        return reverseActiveHarmonicEnergyPhase1 / KILO;
+    }
+
+    public void setReverseActiveHarmonicEnergyPhase1(float reverseActiveHarmonicEnergyPhase1) {
+        this.reverseActiveHarmonicEnergyPhase1 = reverseActiveHarmonicEnergyPhase1;
+    }
+
+    public float getReverseActiveHarmonicEnergyPhase2() {
+        return reverseActiveHarmonicEnergyPhase2 / KILO;
+    }
+
+    public void setReverseActiveHarmonicEnergyPhase2(float reverseActiveHarmonicEnergyPhase2) {
+        this.reverseActiveHarmonicEnergyPhase2 = reverseActiveHarmonicEnergyPhase2;
+    }
+
+    public float getReverseActiveHarmonicEnergyPhase3() {
+        return reverseActiveHarmonicEnergyPhase3 / KILO;
+    }
+
+    public void setReverseActiveHarmonicEnergyPhase3(float reverseActiveHarmonicEnergyPhase3) {
+        this.reverseActiveHarmonicEnergyPhase3 = reverseActiveHarmonicEnergyPhase3;
+    }
+
+    public float getReverseActiveHarmonicEnergySum() {
+        return reverseActiveHarmonicEnergySum / KILO;
+    }
+
+    public void setReverseActiveHarmonicEnergySum(float reverseActiveHarmonicEnergySum) {
+        this.reverseActiveHarmonicEnergySum = reverseActiveHarmonicEnergySum;
+    }
+
+    public float getReverseReactiveEnergyPhase1() {
+        return reverseReactiveEnergyPhase1;
+    }
+
+    public void setReverseReactiveEnergyPhase1(float reverseReactiveEnergyPhase1) {
+        this.reverseReactiveEnergyPhase1 = reverseReactiveEnergyPhase1;
+    }
+
+    public float getReverseReactiveEnergyPhase2() {
+        return reverseReactiveEnergyPhase2;
+    }
+
+    public void setReverseReactiveEnergyPhase2(float reverseReactiveEnergyPhase2) {
+        this.reverseReactiveEnergyPhase2 = reverseReactiveEnergyPhase2;
+    }
+
+    public float getReverseReactiveEnergyPhase3() {
+        return reverseReactiveEnergyPhase3;
+    }
+
+    public void setReverseReactiveEnergyPhase3(float reverseReactiveEnergyPhase3) {
+        this.reverseReactiveEnergyPhase3 = reverseReactiveEnergyPhase3;
+    }
+
+    public float getReverseReactiveEnergySum() {
+        return reverseReactiveEnergySum;
+    }
+
+    public void setReverseReactiveEnergySum(float reverseReactiveEnergySum) {
+        this.reverseReactiveEnergySum = reverseReactiveEnergySum;
+    }
+
+    public float getApparentEnergyConsumptionPhase1() {
+        return apparentEnergyConsumptionPhase1;
+    }
+
+    public void setApparentEnergyConsumptionPhase1(float apparentEnergyConsumptionPhase1) {
+        this.apparentEnergyConsumptionPhase1 = apparentEnergyConsumptionPhase1;
+    }
+
+    public float getApparentEnergyConsumptionPhase2() {
+        return apparentEnergyConsumptionPhase2;
+    }
+
+    public void setApparentEnergyConsumptionPhase2(float apparentEnergyConsumptionPhase2) {
+        this.apparentEnergyConsumptionPhase2 = apparentEnergyConsumptionPhase2;
+    }
+
+    public float getApparentEnergyConsumptionPhase3() {
+        return apparentEnergyConsumptionPhase3;
+    }
+
+    public void setApparentEnergyConsumptionPhase3(float apparentEnergyConsumptionPhase3) {
+        this.apparentEnergyConsumptionPhase3 = apparentEnergyConsumptionPhase3;
+    }
+
+    public float getApparentEnergyConsumptionSum() {
+        return apparentEnergyConsumptionSum;
+    }
+
+    public void setApparentEnergyConsumptionSum(float apparentEnergyConsumptionSum) {
+        this.apparentEnergyConsumptionSum = apparentEnergyConsumptionSum;
+    }
+}
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.mecmeter/src/main/resources/OH-INF/binding/binding.xml
new file mode 100644 (file)
index 0000000..b55da22
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<binding:binding id="mecmeter" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
+
+       <name>mecMeter Binding</name>
+       <description>This is the binding for the din-rail power meter from MEC.</description>
+
+</binding:binding>
diff --git a/bundles/org.openhab.binding.mecmeter/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mecmeter/src/main/resources/OH-INF/thing/thing-types.xml
new file mode 100644 (file)
index 0000000..064ee8a
--- /dev/null
@@ -0,0 +1,561 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="mecmeter"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <thing-type id="meter">
+               <label>mecMeter</label>
+               <description>Power Meter from MEC</description>
+
+               <channel-groups>
+                       <channel-group id="general_group" typeId="general_group"/>
+                       <channel-group id="voltage_group" typeId="voltage_group"/>
+                       <channel-group id="current_group" typeId="current_group"/>
+                       <channel-group id="angle_group" typeId="angle_group"/>
+
+                       <channel-group id="activepower_group" typeId="activepower_group"/>
+                       <channel-group id="activefundpower_group" typeId="activefundpower_group"/>
+                       <channel-group id="activeharmpower_group" typeId="activeharmpower_group"/>
+                       <channel-group id="reactivepower_group" typeId="reactivepower_group"/>
+                       <channel-group id="powerfactor_group" typeId="powerfactor_group"/>
+
+                       <channel-group id="apppower_group" typeId="apppower_group"/>
+
+                       <channel-group id="fwd_active_energy_group" typeId="fwd_active_energy_group"/>
+                       <channel-group id="fwd_active_fund_energy_group" typeId="fwd_active_fund_energy_group"/>
+                       <channel-group id="fwd_active_harm_energy_group" typeId="fwd_active_harm_energy_group"/>
+                       <channel-group id="fwd_reactive_energy_group" typeId="fwd_reactive_energy_group"/>
+
+                       <channel-group id="rev_active_energy_group" typeId="rev_active_energy_group"/>
+                       <channel-group id="rev_active_fund_energy_group" typeId="rev_active_fund_energy_group"/>
+                       <channel-group id="rev_active_harm_energy_group" typeId="rev_active_harm_energy_group"/>
+                       <channel-group id="rev_reactive_energy_group" typeId="rev_reactive_energy_group"/>
+
+                       <channel-group id="app_energy_group" typeId="app_energy_group"/>
+               </channel-groups>
+
+               <config-description>
+                       <parameter name="password" type="text" required="true">
+                               <label>Password</label>
+                               <description>Enter the password</description>
+                               <context>password</context>
+                       </parameter>
+                       <parameter name="ip" type="text" required="true">
+                               <label>IP</label>
+                               <description>The IP address of the mecMeter</description>
+                               <context>network-address</context>
+                       </parameter>
+                       <parameter name="refreshInterval" type="integer" min="1" max="300" step="1" unit="s" required="false">
+                               <label>Refresh Interval</label>
+                               <default>5</default>
+                               <description>Refresh interval in seconds, default 5 seconds, range 1 to 300 seconds</description>
+                       </parameter>
+               </config-description>
+       </thing-type>
+
+       <!-- Definition of all Channel Groups -->
+       <channel-group-type id="general_group">
+               <label>General Channels</label>
+               <description>General Channels</description>
+               <channels>
+                       <channel id="frequency" typeId="frequency"/>
+                       <channel id="temperature" typeId="temperature"/>
+                       <channel id="op_time" typeId="op_time"/>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="voltage_group">
+               <label>Voltage</label>
+               <channels>
+                       <channel id="voltage_phase1" typeId="voltage">
+                               <label>Voltage P1</label>
+                       </channel>
+                       <channel id="voltage_phase2" typeId="voltage">
+                               <label>Voltage P2</label>
+                       </channel>
+                       <channel id="voltage_phase3" typeId="voltage">
+                               <label>Voltage P3</label>
+                       </channel>
+                       <channel id="avg_phase_phase_voltage" typeId="avg_phase_phase_voltage"/>
+                       <channel id="avg_neutral_phase_voltage" typeId="avg_neutral_phase_voltage"/>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="current_group">
+               <label>Current</label>
+               <channels>
+                       <channel id="current_allphase" typeId="current"/>
+                       <channel id="current_phase1" typeId="current">
+                               <label>Current P1</label>
+                       </channel>
+                       <channel id="current_phase2" typeId="current">
+                               <label>Current P2</label>
+                       </channel>
+                       <channel id="current_phase3" typeId="current">
+                               <label>Current P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="angle_group">
+               <label>Angles</label>
+               <channels>
+                       <channel id="phase_angle_currvolt_phase1" typeId="phase_angle_currvolt">
+                               <label>Angle Current to P1</label>
+                       </channel>
+                       <channel id="phase_angle_currvolt_phase2" typeId="phase_angle_currvolt">
+                               <label>Angle Current to P2</label>
+                       </channel>
+                       <channel id="phase_angle_currvolt_phase3" typeId="phase_angle_currvolt">
+                               <label>Angle Current to P3</label>
+                       </channel>
+
+                       <channel id="phase_angle_phase1-3" typeId="phase_angle"/>
+                       <channel id="phase_angle_phase2-3" typeId="phase_angle"/>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="activepower_group">
+               <label>Active Power</label>
+               <channels>
+                       <channel id="activepower_allphase" typeId="activepower"/>
+                       <channel id="activepower_phase1" typeId="activepower">
+                               <label>Active Power P1</label>
+                       </channel>
+                       <channel id="activepower_phase2" typeId="activepower">
+                               <label>Active Power P2</label>
+                       </channel>
+                       <channel id="activepower_phase3" typeId="activepower">
+                               <label>Active Power P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="activefundpower_group">
+               <label>Active Fund Power</label>
+               <channels>
+                       <channel id="activefundpower_allphase" typeId="activefundpower"/>
+                       <channel id="activefundpower_phase1" typeId="activefundpower">
+                               <label>Active Fund Power P1</label>
+                       </channel>
+                       <channel id="activefundpower_phase2" typeId="activefundpower">
+                               <label>Active Fund Power P2</label>
+                       </channel>
+                       <channel id="activefundpower_phase3" typeId="activefundpower">
+                               <label>Active Fund Power P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="activeharmpower_group">
+               <label>Active Harm Power</label>
+               <channels>
+                       <channel id="activeharmpower_allphase" typeId="activeharmpower"/>
+                       <channel id="activeharmpower_phase1" typeId="activeharmpower">
+                               <label>Active Harm Power P1</label>
+                       </channel>
+                       <channel id="activeharmpower_phase2" typeId="activeharmpower">
+                               <label>Active Harm Power P2</label>
+                       </channel>
+                       <channel id="activeharmpower_phase3" typeId="activeharmpower">
+                               <label>Active Harm Power P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="reactivepower_group">
+               <label>Reactive Power</label>
+               <channels>
+                       <channel id="reactivepower_allphase" typeId="reactivepower"/>
+                       <channel id="reactivepower_phase1" typeId="reactivepower">
+                               <label>Reactive Power P1</label>
+                       </channel>
+                       <channel id="reactivepower_phase2" typeId="reactivepower">
+                               <label>Reactive Power P2</label>
+                       </channel>
+                       <channel id="reactivepower_phase3" typeId="reactivepower">
+                               <label>Reactive Power P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="apppower_group">
+               <label>Apparent Power</label>
+               <channels>
+                       <channel id="apppower_allphase" typeId="apppower"/>
+                       <channel id="apppower_phase1" typeId="apppower">
+                               <label>Apparent Power P1</label>
+                       </channel>
+                       <channel id="apppower_phase2" typeId="apppower">
+                               <label>Apparent Power P2</label>
+                       </channel>
+                       <channel id="apppower_phase3" typeId="apppower">
+                               <label>Apparent Power P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="fwd_active_energy_group">
+               <label>Fwd Active Energy</label>
+               <channels>
+                       <channel id="fwd_active_energy_allphase" typeId="fwd_active_energy_all"/>
+                       <channel id="fwd_active_energy_phase1" typeId="fwd_active_energy">
+                               <label>Fwd Active Energy P1</label>
+                       </channel>
+                       <channel id="fwd_active_energy_phase2" typeId="fwd_active_energy">
+                               <label>Fwd Active Energy P2</label>
+                       </channel>
+                       <channel id="fwd_active_energy_phase3" typeId="fwd_active_energy">
+                               <label>Fwd Active Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="fwd_active_fund_energy_group">
+               <label>Fwd Active Fund Energy</label>
+               <channels>
+                       <channel id="fwd_active_fund_energy_allphase" typeId="fwd_active_fund_energy"/>
+                       <channel id="fwd_active_fund_energy_phase1" typeId="fwd_active_fund_energy">
+                               <label>Fwd Active Fund Energy P1</label>
+                       </channel>
+                       <channel id="fwd_active_fund_energy_phase2" typeId="fwd_active_fund_energy">
+                               <label>Fwd Active Fund Energy P2</label>
+                       </channel>
+                       <channel id="fwd_active_fund_energy_phase3" typeId="fwd_active_fund_energy">
+                               <label>Fwd Active Fund Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="fwd_active_harm_energy_group">
+               <label>Fwd Active Harm Energy</label>
+               <channels>
+                       <channel id="fwd_active_harm_energy_allphase" typeId="fwd_active_harm_energy"/>
+                       <channel id="fwd_active_harm_energy_phase1" typeId="fwd_active_harm_energy">
+                               <label>Fwd Active Harm Energy P1</label>
+                       </channel>
+                       <channel id="fwd_active_harm_energy_phase2" typeId="fwd_active_harm_energy">
+                               <label>Fwd Active Harm Energy P2</label>
+                       </channel>
+                       <channel id="fwd_active_harm_energy_phase3" typeId="fwd_active_harm_energy">
+                               <label>Fwd Active Harm Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="fwd_reactive_energy_group">
+               <label>Fwd Reactive Energy</label>
+               <channels>
+                       <channel id="fwd_reactive_energy_allphase" typeId="fwd_reactive_energy"/>
+                       <channel id="fwd_reactive_energy_phase1" typeId="fwd_reactive_energy">
+                               <label>Fwd Reactive Energy P1</label>
+                       </channel>
+                       <channel id="fwd_reactive_energy_phase2" typeId="fwd_reactive_energy">
+                               <label>Fwd Reactive Energy P2</label>
+                       </channel>
+                       <channel id="fwd_reactive_energy_phase3" typeId="fwd_reactive_energy">
+                               <label>Fwd Reactive Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="rev_active_energy_group">
+               <label>Rev Active Energy</label>
+               <channels>
+                       <channel id="rev_active_energy_allphase" typeId="rev_active_energy_all"/>
+                       <channel id="rev_active_energy_phase1" typeId="rev_active_energy">
+                               <label>Rev Active Energy P1</label>
+                       </channel>
+                       <channel id="rev_active_energy_phase2" typeId="rev_active_energy">
+                               <label>Rev Active Energy P2</label>
+                       </channel>
+                       <channel id="rev_active_energy_phase3" typeId="rev_active_energy">
+                               <label>Rev Active Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="rev_active_fund_energy_group">
+               <label>Rev Active Fund Energy</label>
+               <channels>
+                       <channel id="rev_active_fund_energy_allphase" typeId="rev_active_fund_energy"/>
+                       <channel id="rev_active_fund_energy_phase1" typeId="rev_active_fund_energy">
+                               <label>Rev Active Fund Energy P1</label>
+                       </channel>
+                       <channel id="rev_active_fund_energy_phase2" typeId="rev_active_fund_energy">
+                               <label>Rev Active Fund Energy P2</label>
+                       </channel>
+                       <channel id="rev_active_fund_energy_phase3" typeId="rev_active_fund_energy">
+                               <label>Rev Active Fund Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="rev_active_harm_energy_group">
+               <label>Rev Active Harm Energy</label>
+               <channels>
+                       <channel id="rev_active_harm_energy_allphase" typeId="rev_active_harm_energy"/>
+                       <channel id="rev_active_harm_energy_phase1" typeId="rev_active_harm_energy">
+                               <label>Rev Active Harm Energy P1</label>
+                       </channel>
+                       <channel id="rev_active_harm_energy_phase2" typeId="rev_active_harm_energy">
+                               <label>Rev Active Harm Energy P2</label>
+                       </channel>
+                       <channel id="rev_active_harm_energy_phase3" typeId="rev_active_harm_energy">
+                               <label>Rev Active Harm Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="rev_reactive_energy_group">
+               <label>Rev Reactive Energy</label>
+               <channels>
+                       <channel id="rev_reactive_energy_allphase" typeId="rev_reactive_energy"/>
+                       <channel id="rev_reactive_energy_phase1" typeId="rev_reactive_energy">
+                               <label>Rev Reactive Energy P1</label>
+                       </channel>
+                       <channel id="rev_reactive_energy_phase2" typeId="rev_reactive_energy">
+                               <label>Rev Reactive Energy P2</label>
+                       </channel>
+                       <channel id="rev_reactive_energy_phase3" typeId="rev_reactive_energy">
+                               <label>Rev Reactive Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="app_energy_group">
+               <label>Apparent Energy</label>
+               <channels>
+                       <channel id="appenergy_consumption_allphase" typeId="appenergy_consumption"/>
+                       <channel id="appenergy_consumption_phase1" typeId="appenergy_consumption">
+                               <label>Apparent Energy P1</label>
+                       </channel>
+                       <channel id="appenergy_consumption_phase2" typeId="appenergy_consumption">
+                               <label>Apparent Energy P2</label>
+                       </channel>
+                       <channel id="appenergy_consumption_phase3" typeId="appenergy_consumption">
+                               <label>Apparent Energy P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <channel-group-type id="powerfactor_group">
+               <label>Power Factor</label>
+               <channels>
+                       <channel id="powerFactor_allphase" typeId="powerFactor"/>
+                       <channel id="powerFactor_phase1" typeId="powerFactor">
+                               <label>Power Factor P1</label>
+                       </channel>
+                       <channel id="powerFactor_phase2" typeId="powerFactor">
+                               <label>Power Factor P2</label>
+                       </channel>
+                       <channel id="powerFactor_phase3" typeId="powerFactor">
+                               <label>Power Factor P3</label>
+                       </channel>
+               </channels>
+       </channel-group-type>
+
+       <!-- definition of channels types -->
+       <!-- General -->
+       <channel-type id="frequency">
+               <item-type>Number:Frequency</item-type>
+               <label>Main Frequency</label>
+               <description>Frequency in Hertz</description>
+               <state pattern="%.2f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="temperature" advanced="true">
+               <item-type>Number:Temperature</item-type>
+               <label>Internal Temperature</label>
+               <description>Internal Temperature of the energy meter</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="op_time" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Time in Operation</label>
+               <description>Time in Operation</description>
+               <state pattern="%d %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Voltage -->
+       <channel-type id="avg_neutral_phase_voltage">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Average Voltage</label>
+               <description>Average N – Phase Voltage in Volt</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="voltage" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Voltage</label>
+               <description>Voltage in Volt</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="avg_phase_phase_voltage" advanced="true">
+               <item-type>Number:ElectricPotential</item-type>
+               <label>Average Phase – Phase Voltage</label>
+               <description>Average Phase – Phase Voltage in Volt</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Current -->
+       <channel-type id="current" advanced="true">
+               <item-type>Number:ElectricCurrent</item-type>
+               <label>Current</label>
+               <description>Current in Ampere</description>
+               <state pattern="%.2f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Angles -->
+       <channel-type id="phase_angle_currvolt" advanced="true">
+               <item-type>Number:Angle</item-type>
+               <label>Angle Current to Voltage</label>
+               <description>Angle Current to Voltage in Degree</description>
+               <state pattern="%.1f °" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="phase_angle" advanced="true">
+               <item-type>Number:Angle</item-type>
+               <label>Angle Voltage to Voltage</label>
+               <description>Angle Voltage to Voltage in Degree</description>
+               <state pattern="%.1f °" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Power -->
+       <channel-type id="activepower">
+               <item-type>Number:Power</item-type>
+               <label>Active Power</label>
+               <description>Active power consumed</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="activefundpower" advanced="true">
+               <item-type>Number:Power</item-type>
+               <label>Active Fundamental Power</label>
+               <description>Active fundamental power</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="activeharmpower" advanced="true">
+               <item-type>Number:Power</item-type>
+               <label>Active Harmonic Power</label>
+               <description>Active harmonic power</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="reactivepower" advanced="true">
+               <item-type>Number:Power</item-type>
+               <label>Reactive Power</label>
+               <description>Reactive power consumed</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="apppower" advanced="true">
+               <item-type>Number:Power</item-type>
+               <label>Apparent Power</label>
+               <description>Apparent power consumed</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Forward Energy -->
+       <channel-type id="fwd_active_energy_all">
+               <item-type>Number:Energy</item-type>
+               <label>Forward Active Energy</label>
+               <description>Forward Active Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="fwd_active_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Forward Active Energy</label>
+               <description>Forward Active Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="fwd_active_energy_allphase">
+               <item-type>Number:Energy</item-type>
+               <label>Forward Active Energy</label>
+               <description>Forward Active Energy all phase in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="fwd_active_fund_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Forward Active Fund. Energy</label>
+               <description>Forward Active Fundamental Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="fwd_active_harm_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Forward Active Harm. Energy</label>
+               <description>Forward Active Harmonic Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="fwd_reactive_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Forward Reactive Energy</label>
+               <description>Forward Reactive Energy in VArh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Reverse Energy -->
+       <channel-type id="rev_active_energy_all">
+               <item-type>Number:Energy</item-type>
+               <label>Reverse Active Energy</label>
+               <description>Reverse Active Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+       <channel-type id="rev_active_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Reverse Active Energy</label>
+               <description>Reverse Active Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="rev_active_fund_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Reverse Active Fund. Energy</label>
+               <description>Reverse Active Fundamental Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="rev_active_harm_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Reverse Active Harm. Energy</label>
+               <description>Reverse Active Harmonic Energy in kWh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <channel-type id="rev_reactive_energy" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Reverse Reactive Energy</label>
+               <description>Reverse Reactive Energy in VArh</description>
+               <category>Energy</category>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Apparent Energy -->
+       <channel-type id="appenergy_consumption" advanced="true">
+               <item-type>Number:Energy</item-type>
+               <label>Apparent Energy Consumption</label>
+               <description>Apparent Energy Consumption in VArh</description>
+               <state pattern="%.1f %unit%" readOnly="true"></state>
+       </channel-type>
+
+       <!-- Power Factor -->
+       <channel-type id="powerFactor" advanced="true">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Power Factor</label>
+               <description>Power Factor</description>
+               <state pattern="%.1f" readOnly="true"></state>
+       </channel-type>
+</thing:thing-descriptions>
index 3c6b37c4875a2c0973893b22ed60a92516d702ef..aef3e7d41dcd39bd81d0ef513cf803cdc986e6c0 100644 (file)
     <module>org.openhab.binding.mail</module>
     <module>org.openhab.binding.max</module>
     <module>org.openhab.binding.mcp23017</module>
+    <module>org.openhab.binding.mecmeter</module>
     <module>org.openhab.binding.melcloud</module>
     <module>org.openhab.binding.meteoalerte</module>
     <module>org.openhab.binding.meteoblue</module>