mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[HomeWizard] Add support for Energy Socket and Watermeter products (#13495)
Also-by: Leo Siepel <leosiepel@gmail.com> Signed-off-by: Daniël van Os <daniel@supercell.nl> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
6a98dd4615
commit
d34e01956d
@ -1,22 +1,42 @@
|
||||
# HomeWizard Binding
|
||||
|
||||
The HomeWizard binding retrieves measurements from the HomeWizard Wi-Fi P1 meter.
|
||||
The meter itself is attached to a DSMR Smart Meter and reads out the telegrams, which it will forward to cloud storage.
|
||||
However, recently HomeWizard also added an interface that can be queried locally.
|
||||
The HomeWizard binding provides access to several HomeWizard devices by using the local API of those devices.
|
||||
|
||||
This binding uses that local interface to make the measurements available.
|
||||
## Installation
|
||||
|
||||
There are two important points of attention: the local API of each device must be enabled and a fixed address must be configured for the devices.
|
||||
|
||||
### Local API
|
||||
|
||||
The local API of a device can be enabled from the HomeWizard app.
|
||||
Go to Settings in the app, then Meters and select the device you want to enable.
|
||||
On this page enable the local API.
|
||||
|
||||
### Fixed Address
|
||||
|
||||
The devices support mDNS discovery but the binding does not support that yet.
|
||||
As a result the devices should be reachable through a hostname or a fixed IP address.
|
||||
Since the devices themselves have no option to set a fixed IP address you will need a different solution, for instance having your router hand out an IP address based upon the MAC address of the devices.
|
||||
|
||||
## Supported Things
|
||||
|
||||
The binding provides the P1 Meter thing.
|
||||
The binding offers three Things, providing support for the P1 meter, the Watermeter and the Energy Socket.
|
||||
|
||||
| Thing | Device | Description |
|
||||
|---------------|---------------------|---------------------------------------------------------------------------------------------------|
|
||||
| p1_wifi_meter | Wi-Fi P1 Meter | Reads total and current energy usage and total gas usage. |
|
||||
| energy_socket | Wi-Fi Energy Socket | Reads total and current energy usage. Controls power switch, lock and ring brightness. |
|
||||
| watermeter | Wi-Fi Watermeter | Reads total and current water usage. |
|
||||
|
||||
The HomeWizard kWh meters are not yet officially supported, but they can probably be added as as 'p1_wifi_meter'. However, this has not been tested.
|
||||
|
||||
## Discovery
|
||||
|
||||
Auto discovery is not available for this binding.
|
||||
Auto discovery is not yet available for this binding.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The P1 Meter thing can be configured through the web interface.
|
||||
All devices can be configured through the web interface.
|
||||
|
||||
| Parameter | Required | Default | Description |
|
||||
|--------------|----------|---------|---------------------------------------------------------------------------------------------------|
|
||||
@ -26,28 +46,37 @@ The P1 Meter thing can be configured through the web interface.
|
||||
Note that update rate of the P1 Meter itself depends on the frequency of the telegrams it receives from the Smart Meter.
|
||||
For DSMR5 meters this is generally once per second, for older versions the frequency is much lower.
|
||||
|
||||
Example of configuration through a .thing file:
|
||||
|
||||
```java
|
||||
Thing homewizard:p1_wifi_meter:my_meter [ ipAddress="192.178.1.67", refreshDelay=5 ]
|
||||
```
|
||||
|
||||
## Channels
|
||||
|
||||
| Channel ID | Item Type | Description |
|
||||
|------------------------|---------------|--------------------------------------------------------------------------------------------|
|
||||
| total_energy_import_t1 | Number:Energy | The most recently reported total imported energy in kWh by counter 1. |
|
||||
| total_energy_import_t2 | Number:Energy | The most recently reported total imported energy in kWh by counter 2. |
|
||||
| total_energy_export_t1 | Number:Energy | The most recently reported total exported energy in kWh by counter 1. |
|
||||
| total_energy_export_t2 | Number:Energy | The most recently reported total exported energy in kWh by counter 2. |
|
||||
| active_power | Number:Power | The current net total power in W. It will be below 0 if power is currently being exported. |
|
||||
| active_power_l1 | Number:Power | The current net total power in W for phase 1. |
|
||||
| active_power_l2 | Number:Power | The current net total power in W for phase 2. |
|
||||
| active_power_l3 | Number:Power | The current net total power in W for phase 3. |
|
||||
| total_gas | Number:Volume | The most recently reported total imported gas in m^3. |
|
||||
| gas_timestamp | DateTime | The time stamp of the total_gas measurement. |
|
||||
| Channel ID | Item Type | Description |Available|
|
||||
|------------------------|---------------------------|--------------------------------------------------------------------------------------------|---------|
|
||||
| total_energy_import_t1 | Number:Energy | The most recently reported total imported energy in kWh by counter 1. | P,E |
|
||||
| total_energy_import_t2 | Number:Energy | The most recently reported total imported energy in kWh by counter 2. | P |
|
||||
| total_energy_export_t1 | Number:Energy | The most recently reported total exported energy in kWh by counter 1. | P,E |
|
||||
| total_energy_export_t2 | Number:Energy | The most recently reported total exported energy in kWh by counter 2. | P |
|
||||
| active_power | Number:Power | The current net total power in W. It will be below 0 if power is currently being exported. | P,E |
|
||||
| active_power_l1 | Number:Power | The current net total power in W for phase 1. | P |
|
||||
| active_power_l2 | Number:Power | The current net total power in W for phase 2. | P |
|
||||
| active_power_l3 | Number:Power | The current net total power in W for phase 3. | P |
|
||||
| total_gas | Number:Volume | The most recently reported total imported gas in m^3. | P |
|
||||
| gas_timestamp | DateTime | The time stamp of the total_gas measurement. | P |
|
||||
| total_water | Number:Volume | Total water used. | W |
|
||||
| current_water | Number:VolumetricFlowRate | Current water usage. | W |
|
||||
| power_switch | Switch | Controls the power switch of the socket. | E |
|
||||
| power_lock | Switch | Controls the lock of the power switch (un/locking both the API and the physical button) | E |
|
||||
| ring_brightness | Number:Dimensionless | Controls the brightness of the ring on the socket | E |
|
||||
|
||||
Example of configuration through a .items file:
|
||||
## Full Example
|
||||
|
||||
### `homewizard.things` Example
|
||||
|
||||
```java
|
||||
Thing homewizard:p1_wifi_meter:my_p1 [ ipAddress="192.178.1.67", refreshDelay=5 ]
|
||||
Thing homewizard:energy_socket:my_socket [ ipAddress="192.178.1.61", refreshDelay=5 ]
|
||||
Thing homewizard:watermeter:my_water [ ipAddress="192.178.1.27", refreshDelay=15 ]
|
||||
```
|
||||
|
||||
### `homewizard.items` Example
|
||||
|
||||
```java
|
||||
Number:Energy Energy_Import_T1 "Imported Energy T1 [%.0f kWh]" {channel="homewizard:p1_wifi_meter:my_meter:total_energy_import_t1" }
|
||||
|
@ -17,13 +17,13 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Class that provides storage for the json object obtained from the P1 meter API
|
||||
* Class that provides storage for the json objects obtained from HomeWizard devices.
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class P1Payload {
|
||||
public class DataPayload {
|
||||
private int smrVersion = 0;
|
||||
private String meterModel = "";
|
||||
private String wifiSsid = "";
|
||||
@ -45,6 +45,11 @@ public class P1Payload {
|
||||
private double totalGasM3;
|
||||
private long gasTimestamp = 0;
|
||||
|
||||
@SerializedName("total_liter_m3")
|
||||
private double totalWaterM3;
|
||||
@SerializedName("active_liter_lpm")
|
||||
private double currentWaterLPM;
|
||||
|
||||
/**
|
||||
* Getter for the smart meter version
|
||||
*
|
||||
@ -297,15 +302,53 @@ public class P1Payload {
|
||||
this.gasTimestamp = gasTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the total imported water volume
|
||||
*
|
||||
* @return total imported water volume
|
||||
*/
|
||||
public double getTotalWaterM3() {
|
||||
return totalWaterM3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the total imported water volume
|
||||
*
|
||||
* @param totalWaterM3 total imported water volume
|
||||
*/
|
||||
public void setTotalWaterM3(double totalWaterM3) {
|
||||
this.totalWaterM3 = totalWaterM3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the current water flow
|
||||
*
|
||||
* @return current water flow
|
||||
*/
|
||||
public double getCurrentWaterLPM() {
|
||||
return currentWaterLPM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the current water flow
|
||||
*
|
||||
* @param currentWaterLPM current water flow
|
||||
*/
|
||||
public void setCurrentWaterLPM(double currentWaterLPM) {
|
||||
this.currentWaterLPM = currentWaterLPM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"""
|
||||
P1 [version: %d model: %s ssid: %s signal: %d\
|
||||
imp1: %f imp2: %f exp1: %f exp2: %f active: %f active1: %f active2: %f active3: %f gas: %f timestamp: %.0f]\
|
||||
Data [smrVersion: %d meterModel: %s wifiSsid: %s wifiStrength: %d"
|
||||
totalEnergyImportT1Kwh: %f totalEnergyImportT2Kwh: %f totalEnergyExportT1Kwh: %f totalEnergyExportT2Kwh: %f"
|
||||
activePowerW: %f activePowerL1W: %f activePowerL2W: %f activePowerL3W: %f totalGasM3: %f gasTimestamp: %.0f"
|
||||
totalWaterM3: %f currentWaterLPM: %f]
|
||||
""",
|
||||
smrVersion, meterModel, wifiSsid, wifiStrength, totalEnergyImportT1Kwh, totalEnergyImportT2Kwh,
|
||||
totalEnergyExportT1Kwh, totalEnergyExportT2Kwh, activePowerW, activePowerL1W, activePowerL2W,
|
||||
activePowerL3W, totalGasM3, gasTimestamp);
|
||||
activePowerL3W, totalGasM3, gasTimestamp, totalWaterM3, currentWaterLPM);
|
||||
}
|
||||
}
|
@ -27,7 +27,9 @@ public class HomeWizardBindingConstants {
|
||||
private static final String BINDING_ID = "homewizard";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_P1_WIFI_METER = new ThingTypeUID(BINDING_ID, "p1_wifi_meter");
|
||||
public static final ThingTypeUID THING_TYPE_P1_METER = new ThingTypeUID(BINDING_ID, "p1_wifi_meter");
|
||||
public static final ThingTypeUID THING_TYPE_ENERGY_SOCKET = new ThingTypeUID(BINDING_ID, "energy_socket");
|
||||
public static final ThingTypeUID THING_TYPE_WATERMETER = new ThingTypeUID(BINDING_ID, "watermeter");
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String CHANNEL_ENERGY_IMPORT_T1 = "total_energy_import_t1";
|
||||
@ -40,6 +42,12 @@ public class HomeWizardBindingConstants {
|
||||
public static final String CHANNEL_ACTIVE_POWER_L3 = "active_power_l3";
|
||||
public static final String CHANNEL_TOTAL_GAS = "total_gas";
|
||||
public static final String CHANNEL_GAS_TIMESTAMP = "gas_timestamp";
|
||||
public static final String CHANNEL_TOTAL_WATER = "total_water";
|
||||
public static final String CHANNEL_CURRENT_WATER = "current_water";
|
||||
|
||||
public static final String CHANNEL_POWER_SWITCH = "power_switch";
|
||||
public static final String CHANNEL_POWER_LOCK = "power_lock";
|
||||
public static final String CHANNEL_RING_BRIGHTNESS = "ring_brightness";
|
||||
|
||||
public static final String PROPERTY_METER_MODEL = "meterModel";
|
||||
public static final String PROPERTY_METER_VERSION = "meterVersion";
|
||||
|
@ -23,7 +23,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
public class HomeWizardConfiguration {
|
||||
|
||||
/**
|
||||
* IP Address or host for the P1 Meter
|
||||
* IP Address or host for a HomeWizard device.
|
||||
*/
|
||||
public String ipAddress = "";
|
||||
|
||||
|
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.homewizard.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
/**
|
||||
* The {@link HomeWizardDeviceHandler} is a base class for all
|
||||
* HomeWizard devices. It provides configuration and polling of
|
||||
* data from a device. It also processes common data.
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class HomeWizardDeviceHandler extends BaseThingHandler {
|
||||
|
||||
protected final Logger logger = LoggerFactory.getLogger(HomeWizardDeviceHandler.class);
|
||||
protected final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.create();
|
||||
|
||||
private HomeWizardConfiguration config = new HomeWizardConfiguration();
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
protected String apiURL = "";
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param thing The thing to handle
|
||||
*/
|
||||
public HomeWizardDeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a host has been specified start polling it
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
config = getConfigAs(HomeWizardConfiguration.class);
|
||||
if (configure()) {
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::pollingCode, 0, config.refreshDelay, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the current configuration
|
||||
*
|
||||
* @return true if the configuration is ok to start polling, false otherwise
|
||||
*/
|
||||
private boolean configure() {
|
||||
if (config.ipAddress.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Missing ipAddress/host configuration");
|
||||
return false;
|
||||
} else {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
apiURL = String.format("http://%s/api/v1/", config.ipAddress.trim());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dispose: stop the poller
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
var job = pollingJob;
|
||||
if (job != null) {
|
||||
job.cancel(true);
|
||||
}
|
||||
pollingJob = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device specific handling of the returned data payload.
|
||||
*
|
||||
* @param payload The data parsed from the data Json file
|
||||
*/
|
||||
abstract protected void handleDataPayload(DataPayload payload);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected void pollData() {
|
||||
final String dataResult;
|
||||
|
||||
try {
|
||||
dataResult = HttpUtil.executeUrl("GET", apiURL + "data", 30000);
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Unable to query device data: %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataResult.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Device returned empty data");
|
||||
return;
|
||||
}
|
||||
|
||||
DataPayload dataPayload = gson.fromJson(dataResult, DataPayload.class);
|
||||
if (dataPayload == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Unable to parse data response from device");
|
||||
return;
|
||||
}
|
||||
|
||||
if ("".equals(dataPayload.getWifiSsid())) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Results from API are empty");
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
handleDataPayload(dataPayload);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual polling loop
|
||||
*/
|
||||
protected void pollingCode() {
|
||||
pollData();
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.homewizard.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
|
||||
/**
|
||||
* The {@link HomeWizardEnergySocketHandler} implements functionality to handle a HomeWizard EnergySocket.
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HomeWizardEnergySocketHandler extends HomeWizardStatefulDeviceHandler {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param thing The thing to handle
|
||||
*/
|
||||
public HomeWizardEnergySocketHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a brightness value (0..255) to a percentage.
|
||||
*
|
||||
* @param brightness The brightness to convert.
|
||||
* @return brightness percentage
|
||||
*/
|
||||
private int brightnessToPercentage(int brightness) {
|
||||
return (int) (100.0 * brightness / 255.0 + 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a percentage to a brightness value (0..255)
|
||||
*
|
||||
* @param percentage The percentage to convert.
|
||||
* @return brightness value
|
||||
*/
|
||||
private int percentageToBrightness(String percentage) {
|
||||
return (int) (Double.valueOf(percentage) * 255.0 / 100.0 + 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incoming commands.
|
||||
*
|
||||
* Power on/off, Power lock/unlock and Ring brightness are supported.
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
// For now I prefer not updating immediately above firing a full update request for each channel
|
||||
return;
|
||||
}
|
||||
|
||||
StatePayload result = null;
|
||||
|
||||
/*
|
||||
* The returned payloads below only contain the modified value, so each has it's own
|
||||
* call to updateState instead of just calling handleStatePayload() with the returned
|
||||
* payload.
|
||||
*/
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
case HomeWizardBindingConstants.CHANNEL_RING_BRIGHTNESS: {
|
||||
result = sendStateCommand(
|
||||
String.format("{\"brightness\": %d}", percentageToBrightness(command.toFullString())));
|
||||
if (result != null) {
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_RING_BRIGHTNESS,
|
||||
new PercentType(brightnessToPercentage(result.getBrightness())));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HomeWizardBindingConstants.CHANNEL_POWER_SWITCH: {
|
||||
boolean onOff = command.equals(OnOffType.ON);
|
||||
result = sendStateCommand(String.format("{\"power_on\": %b}", onOff));
|
||||
if (result != null) {
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_POWER_SWITCH, OnOffType.from(result.getPowerOn()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HomeWizardBindingConstants.CHANNEL_POWER_LOCK: {
|
||||
boolean onOff = command.equals(OnOffType.ON);
|
||||
result = sendStateCommand(String.format("{\"switch_lock\": %b}", onOff));
|
||||
if (result != null) {
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_POWER_LOCK, OnOffType.from(result.getSwitchLock()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logger.warn("Should handle {} {}", channelUID.getIdWithoutGroup(), command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Device specific handling of the returned payload.
|
||||
*
|
||||
* @param payload The data parsed from the Json file
|
||||
*/
|
||||
@Override
|
||||
protected void handleDataPayload(DataPayload payload) {
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_ENERGY_IMPORT_T1,
|
||||
new QuantityType<>(payload.getTotalEnergyImportT1Kwh(), Units.KILOWATT_HOUR));
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_ENERGY_EXPORT_T1,
|
||||
new QuantityType<>(payload.getTotalEnergyExportT1Kwh(), Units.KILOWATT_HOUR));
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_ACTIVE_POWER,
|
||||
new QuantityType<>(payload.getActivePowerW(), Units.WATT));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleStatePayload(StatePayload payload) {
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_POWER_SWITCH, OnOffType.from(payload.getPowerOn()));
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_POWER_LOCK, OnOffType.from(payload.getSwitchLock()));
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_RING_BRIGHTNESS,
|
||||
new PercentType(brightnessToPercentage(payload.getBrightness())));
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.homewizard.internal;
|
||||
|
||||
import static org.openhab.binding.homewizard.internal.HomeWizardBindingConstants.THING_TYPE_P1_WIFI_METER;
|
||||
import static org.openhab.binding.homewizard.internal.HomeWizardBindingConstants.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@ -35,7 +35,8 @@ import org.osgi.service.component.annotations.Component;
|
||||
@Component(configurationPid = "binding.homewizard", service = ThingHandlerFactory.class)
|
||||
public class HomeWizardHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_P1_WIFI_METER);
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_P1_METER,
|
||||
THING_TYPE_ENERGY_SOCKET, THING_TYPE_WATERMETER);
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
@ -46,8 +47,16 @@ public class HomeWizardHandlerFactory extends BaseThingHandlerFactory {
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_P1_WIFI_METER.equals(thingTypeUID)) {
|
||||
return new HomeWizardHandler(thing);
|
||||
if (THING_TYPE_P1_METER.equals(thingTypeUID)) {
|
||||
return new HomeWizardP1MeterHandler(thing);
|
||||
}
|
||||
|
||||
if (THING_TYPE_ENERGY_SOCKET.equals(thingTypeUID)) {
|
||||
return new HomeWizardEnergySocketHandler(thing);
|
||||
}
|
||||
|
||||
if (THING_TYPE_WATERMETER.equals(thingTypeUID)) {
|
||||
return new HomeWizardWaterMeterHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -12,50 +12,27 @@
|
||||
*/
|
||||
package org.openhab.binding.homewizard.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
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.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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
/**
|
||||
* The {@link HomeWizardHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
* The {@link HomeWizardP1MeterHandler} implements functionality to handle a HomeWizard P1 Meter.
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HomeWizardHandler extends BaseThingHandler {
|
||||
public class HomeWizardP1MeterHandler extends HomeWizardDeviceHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(HomeWizardHandler.class);
|
||||
private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.create();
|
||||
|
||||
private HomeWizardConfiguration config = new HomeWizardConfiguration();
|
||||
private @Nullable ScheduledFuture<?> pollingJob;
|
||||
|
||||
private String apiURL = "";
|
||||
private String meterModel = "";
|
||||
private int meterVersion = 0;
|
||||
|
||||
@ -64,7 +41,7 @@ public class HomeWizardHandler extends BaseThingHandler {
|
||||
*
|
||||
* @param thing The thing to handle
|
||||
*/
|
||||
public HomeWizardHandler(Thing thing) {
|
||||
public HomeWizardP1MeterHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@ -76,79 +53,12 @@ public class HomeWizardHandler extends BaseThingHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* If a host has been specified start polling it
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
config = getConfigAs(HomeWizardConfiguration.class);
|
||||
if (configure()) {
|
||||
pollingJob = scheduler.scheduleWithFixedDelay(this::pollingCode, 0, config.refreshDelay, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the current configuration
|
||||
* Device specific handling of the returned payload.
|
||||
*
|
||||
* @return true if the configuration is ok to start polling, false otherwise
|
||||
*/
|
||||
private boolean configure() {
|
||||
if (config.ipAddress.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Missing ipAddress/host configuration");
|
||||
return false;
|
||||
} else {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
apiURL = String.format("http://%s/api/v1/data", config.ipAddress.trim());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dispose: stop the poller
|
||||
* @param payload The data parsed from the Json file
|
||||
*/
|
||||
@Override
|
||||
public void dispose() {
|
||||
var job = pollingJob;
|
||||
if (job != null) {
|
||||
job.cancel(true);
|
||||
}
|
||||
pollingJob = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual polling loop
|
||||
*/
|
||||
private void pollingCode() {
|
||||
final String result;
|
||||
|
||||
try {
|
||||
result = HttpUtil.executeUrl("GET", apiURL, 30000);
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Unable to query P1 Meter: %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"P1 Meter API returned empty status");
|
||||
return;
|
||||
}
|
||||
|
||||
P1Payload payload = gson.fromJson(result, P1Payload.class);
|
||||
if (payload == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Unable to parse response from P1 meter");
|
||||
return;
|
||||
}
|
||||
|
||||
if ("".equals(payload.getMeterModel())) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Results from API are empty");
|
||||
return;
|
||||
}
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
|
||||
protected void handleDataPayload(DataPayload payload) {
|
||||
if (!meterModel.equals(payload.getMeterModel())) {
|
||||
meterModel = payload.getMeterModel();
|
||||
updateProperty(HomeWizardBindingConstants.PROPERTY_METER_MODEL, meterModel);
|
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.homewizard.internal;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
|
||||
/**
|
||||
* The {@link HomeWizardStatefulDeviceHandler} extends the base class
|
||||
* to provide support for devices that also have a 'state' interface.
|
||||
* This interface can be used to query and control the state of a device.
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public abstract class HomeWizardStatefulDeviceHandler extends HomeWizardDeviceHandler {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param thing The thing to handle
|
||||
*/
|
||||
public HomeWizardStatefulDeviceHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Device specific handling of the returned state payload.
|
||||
*
|
||||
* @param payload The data parsed from the state Json file
|
||||
*/
|
||||
abstract protected void handleStatePayload(StatePayload payload);
|
||||
|
||||
protected void pollState() {
|
||||
final String stateResult;
|
||||
|
||||
try {
|
||||
stateResult = HttpUtil.executeUrl("GET", apiURL + "state", 30000);
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
String.format("Unable to query device state: %s", e.getMessage()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (stateResult.trim().isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Device returned empty state");
|
||||
return;
|
||||
}
|
||||
|
||||
StatePayload statePayload = gson.fromJson(stateResult, StatePayload.class);
|
||||
if (statePayload == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Unable to parse state response from device");
|
||||
return;
|
||||
}
|
||||
|
||||
handleStatePayload(statePayload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the state interface of the device.
|
||||
*
|
||||
* @param command The command to send.
|
||||
*/
|
||||
protected @Nullable StatePayload sendStateCommand(String command) {
|
||||
try (InputStream is = new ByteArrayInputStream(command.getBytes())) {
|
||||
String updatedState = HttpUtil.executeUrl("PUT", apiURL + "state", is, "application/json", 30000);
|
||||
return gson.fromJson(updatedState, StatePayload.class);
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to send command {} to {}", command, apiURL + "state");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This overrides the original polling loop by including a request for the current state..
|
||||
*/
|
||||
@Override
|
||||
protected void pollingCode() {
|
||||
pollData();
|
||||
pollState();
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.homewizard.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
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.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
|
||||
/**
|
||||
* The {@link HomeWizardWaterMeterHandler} implements functionality to handle a HomeWizard Watermeter.
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class HomeWizardWaterMeterHandler extends HomeWizardDeviceHandler {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param thing The thing to handle
|
||||
*/
|
||||
public HomeWizardWaterMeterHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not listening to any commands.
|
||||
*/
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Device specific handling of the returned payload.
|
||||
*
|
||||
* @param payload The data parsed from the Json file
|
||||
*/
|
||||
@Override
|
||||
protected void handleDataPayload(DataPayload payload) {
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_CURRENT_WATER,
|
||||
new QuantityType<>(payload.getCurrentWaterLPM(), Units.LITRE_PER_MINUTE));
|
||||
updateState(HomeWizardBindingConstants.CHANNEL_TOTAL_WATER,
|
||||
new QuantityType<>(payload.getTotalWaterM3(), SIUnits.CUBIC_METRE));
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 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.homewizard.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Class that provides storage for the json object obtained from the HomeWizard device State API
|
||||
*
|
||||
* @author Daniël van Os - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class StatePayload {
|
||||
@SerializedName("power_on")
|
||||
private boolean powerOn;
|
||||
@SerializedName("switch_lock")
|
||||
private boolean switchLock;
|
||||
private int brightness = 0;
|
||||
|
||||
/**
|
||||
* Getter for the power_on field
|
||||
*
|
||||
* @return true if the device is currently on, false if it is off
|
||||
*/
|
||||
public boolean getPowerOn() {
|
||||
return powerOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the power_on field
|
||||
*
|
||||
* @param powerOn true to turn the device on, false to turn it off
|
||||
*/
|
||||
public void setPowerOn(boolean powerOn) {
|
||||
this.powerOn = powerOn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the switch_lock field
|
||||
*
|
||||
* @return true if the device currently locked, false if it is not
|
||||
*/
|
||||
public boolean getSwitchLock() {
|
||||
return switchLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the power_on field
|
||||
*
|
||||
* @param switchLock true to lock the device, false to unlock it
|
||||
*/
|
||||
public void setSwitchLock(boolean switchLock) {
|
||||
this.switchLock = switchLock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for the ring brightness
|
||||
*
|
||||
* @return ring brightness percentage
|
||||
*/
|
||||
public int getBrightness() {
|
||||
return brightness;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the ring brightness
|
||||
*
|
||||
* @param brightness ring brightness
|
||||
*/
|
||||
public void setBrightness(int brightness) {
|
||||
this.brightness = brightness;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("State [power_on: %b switch_lock: %b brightness: %d]", powerOn, switchLock, brightness);
|
||||
}
|
||||
}
|
@ -5,15 +5,27 @@ addon.homewizard.description = This binding provides access to the data provided
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.homewizard.energy_socket.label = HomeWizard Energysocket
|
||||
thing-type.homewizard.energy_socket.description = This thing provides the measurement data that is available through the http interface of a HomeWizard Energysocket.
|
||||
thing-type.homewizard.p1_wifi_meter.label = HomeWizard Wi-Fi P1 Meter
|
||||
thing-type.homewizard.p1_wifi_meter.description = This thing provides the measurement data that is available through the http interface of the HomeWizard Wi-Fi P1 Meter.
|
||||
thing-type.homewizard.watermeter.label = HomeWizard Wi-Fi Watermeter
|
||||
thing-type.homewizard.watermeter.description = This thing provides the measurement data that is available through the http interface of a HomeWizard Watermeter.
|
||||
|
||||
# thing types config
|
||||
|
||||
thing-type.config.homewizard.energy_socket.ipAddress.label = Network Address
|
||||
thing-type.config.homewizard.energy_socket.ipAddress.description = The IP or host name of the Energysocket.
|
||||
thing-type.config.homewizard.energy_socket.refreshDelay.label = Refresh Interval
|
||||
thing-type.config.homewizard.energy_socket.refreshDelay.description = The refresh interval in seconds for polling the Energysocket.
|
||||
thing-type.config.homewizard.p1_wifi_meter.ipAddress.label = Network Address
|
||||
thing-type.config.homewizard.p1_wifi_meter.ipAddress.description = The IP or host name of the P1 Meter.
|
||||
thing-type.config.homewizard.p1_wifi_meter.refreshDelay.label = Refresh Interval
|
||||
thing-type.config.homewizard.p1_wifi_meter.refreshDelay.description = The refresh interval in seconds for polling the P1 Meter.
|
||||
thing-type.config.homewizard.watermeter.ipAddress.label = Network Address
|
||||
thing-type.config.homewizard.watermeter.ipAddress.description = The IP or host name of the Watermeter.
|
||||
thing-type.config.homewizard.watermeter.refreshDelay.label = Refresh Interval
|
||||
thing-type.config.homewizard.watermeter.refreshDelay.description = The refresh interval in seconds for polling the Watermeter.
|
||||
|
||||
# channel types
|
||||
|
||||
@ -25,8 +37,16 @@ channel-type.homewizard.active_power_l2.label = Current Phase 2 Net Power
|
||||
channel-type.homewizard.active_power_l2.description = This channel provides the current net phase 2 power in W. It will be below 0 if power is currently being exported. It will be 0 for single phase systems.
|
||||
channel-type.homewizard.active_power_l3.label = Current Phase 3 Net Power
|
||||
channel-type.homewizard.active_power_l3.description = This channel provides the current net phase 3 power in W. It will be below 0 if power is currently being exported. It will be 0 for single phase systems.
|
||||
channel-type.homewizard.current_water.label = Current Water Rate
|
||||
channel-type.homewizard.current_water.description = This channel provides the most recently reported current water usage in liters per minute.
|
||||
channel-type.homewizard.gas_timestamp.label = Gas Update Time Stamp
|
||||
channel-type.homewizard.gas_timestamp.description = This channel provides the time stamp of the total_gas measurement.
|
||||
channel-type.homewizard.power_lock.label = Power Lock
|
||||
channel-type.homewizard.power_lock.description = This channel provides access to the power lock of the Energysocket
|
||||
channel-type.homewizard.power_switch.label = Power Switch
|
||||
channel-type.homewizard.power_switch.description = This channel provides access to the power switch of the Energysocket
|
||||
channel-type.homewizard.ring_brightness.label = Ring Brightness
|
||||
channel-type.homewizard.ring_brightness.description = This channel provides access to the brightness of the ring of the Energysocket
|
||||
channel-type.homewizard.total_energy_export_t1.label = Total Exported Energy Counter 1
|
||||
channel-type.homewizard.total_energy_export_t1.description = This channel provides the most recently reported total exported energy in kWh by counter 1, most commonly used for export during the night or weekend.
|
||||
channel-type.homewizard.total_energy_export_t2.label = Total Exported Energy Counter 2
|
||||
@ -37,3 +57,5 @@ channel-type.homewizard.total_energy_import_t2.label = Total Imported Energy Cou
|
||||
channel-type.homewizard.total_energy_import_t2.description = This channel provides the most recently reported total imported energy in kWh by counter 2, most commonly used for import during the day.
|
||||
channel-type.homewizard.total_gas.label = Total Imported Gas
|
||||
channel-type.homewizard.total_gas.description = This channel provides the most recently reported total imported gas in m^3. It does not get updated as frequently as the data in the other channels, the gas_timestamp channel provides the time stamp of the most recent update.
|
||||
channel-type.homewizard.total_water.label = Total Imported Water
|
||||
channel-type.homewizard.total_water.description = This channel provides the most recently reported total imported water in m^3.
|
||||
|
@ -4,6 +4,7 @@
|
||||
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="p1_wifi_meter">
|
||||
<label>HomeWizard Wi-Fi P1 Meter</label>
|
||||
<description>This thing provides the measurement data that is available through the http interface of the HomeWizard
|
||||
@ -41,6 +42,62 @@
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="energy_socket">
|
||||
<label>HomeWizard Energysocket</label>
|
||||
<description>This thing provides the measurement data that is available through the http interface of a HomeWizard
|
||||
Energysocket.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="total_energy_import_t1" typeId="total_energy_import_t1"/>
|
||||
<channel id="total_energy_export_t1" typeId="total_energy_export_t1"/>
|
||||
<channel id="active_power" typeId="active_power"/>
|
||||
|
||||
<channel id="power_switch" typeId="power_switch"/>
|
||||
<channel id="power_lock" typeId="power_lock"/>
|
||||
<channel id="ring_brightness" typeId="ring_brightness"/>
|
||||
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>The IP or host name of the Energysocket.</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="refreshDelay" type="integer" min="1" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>The refresh interval in seconds for polling the Energysocket.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="watermeter">
|
||||
<label>HomeWizard Wi-Fi Watermeter</label>
|
||||
<description>This thing provides the measurement data that is available through the http interface of a HomeWizard
|
||||
Watermeter.</description>
|
||||
|
||||
<channels>
|
||||
<channel id="total_water" typeId="total_water"/>
|
||||
<channel id="current_water" typeId="current_water"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>The IP or host name of the Watermeter.</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="refreshDelay" type="integer" min="1" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>The refresh interval in seconds for polling the Watermeter.</description>
|
||||
<default>5</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="total_energy_import_t1">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Total Imported Energy Counter 1</label>
|
||||
@ -129,4 +186,47 @@
|
||||
</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="total_water">
|
||||
<item-type>Number:Volume</item-type>
|
||||
<label>Total Imported Water</label>
|
||||
<description>
|
||||
This channel provides the most recently reported total imported water in m^3.
|
||||
</description>
|
||||
<state readOnly="true" pattern="%.3f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="current_water">
|
||||
<item-type>Number:VolumetricFlowRate</item-type>
|
||||
<label>Current Water Rate</label>
|
||||
<description>
|
||||
This channel provides the most recently reported current water usage in liters per minute.
|
||||
</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="power_switch">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Power Switch</label>
|
||||
<description>
|
||||
This channel provides access to the power switch of the Energysocket
|
||||
</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="power_lock">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Power Lock</label>
|
||||
<description>
|
||||
This channel provides access to the power lock of the Energysocket
|
||||
</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ring_brightness">
|
||||
<item-type unitHint="%">Number:Dimensionless</item-type>
|
||||
<label>Ring Brightness</label>
|
||||
<description>
|
||||
This channel provides access to the brightness of the ring of the Energysocket
|
||||
</description>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
Loading…
Reference in New Issue
Block a user