added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
32
bundles/org.openhab.binding.energenie/.classpath
Normal file
32
bundles/org.openhab.binding.energenie/.classpath
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.energenie/.project
Normal file
23
bundles/org.openhab.binding.energenie/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.energenie</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
bundles/org.openhab.binding.energenie/NOTICE
Normal file
13
bundles/org.openhab.binding.energenie/NOTICE
Normal file
@@ -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
|
||||
95
bundles/org.openhab.binding.energenie/README.md
Normal file
95
bundles/org.openhab.binding.energenie/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Gembird energenie Binding
|
||||
|
||||
This binding integrates the Gembird energenie range of power extenders by using the Energenie Data Exchange Protocol and power reading devices through HTTP interface.
|
||||
|
||||
|
||||
## Supported Things
|
||||
|
||||
The Binding supports PM2-LAN, PMS-LAN, PMS2-LAN or PMS-WLAN power extenders as well as PWM-LAN power measurement devices.
|
||||
|
||||
## Discovery
|
||||
|
||||
Gembird energenie devices don't support autodiscovery.
|
||||
All Things need to be created manually either in PaperUI or within Things files.
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
The Binding does not need any specific configuration
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The device requires the IP-address and a password as a configuration value in order for the binding to know where to access it and to login to the device.
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|------------------------------------------------------|
|
||||
| host | IP-Address of energenie device |
|
||||
| password | Password to access energenie device, defaults to "1" |
|
||||
|
||||
## Channels
|
||||
|
||||
The following channels are supported by PM2-LAN, PMS-LAN, PMS2-LAN or PMS-WLAN devices
|
||||
|
||||
| channel | type | description |
|
||||
|----------|--------|----------------------------------------------------|
|
||||
| socket1 | Switch | This is the control channel for the first socket |
|
||||
| socket2 | Switch | This is the control channel for the second socket |
|
||||
| socket3 | Switch | This is the control channel for the third socket |
|
||||
| socket4 | Switch | This is the control channel for the fourth socket |
|
||||
|
||||
PWM-LAN devices support the following channels
|
||||
|
||||
| channel | type | description |
|
||||
|----------|--------------------------|------------------------------------------|
|
||||
| voltage | Number:ElectricPotential | Channel for output voltage measurement |
|
||||
| current | Number:ElectricCurrent | Channel for output current measurement |
|
||||
| power | Number:Power | Channel for output power measurement |
|
||||
| energy | Number:Energy | channel for output energy measurement |
|
||||
|
||||
## Full Example
|
||||
|
||||
Things
|
||||
|
||||
```
|
||||
Thing energenie:pm2lan:pm2lan [ host="xxx.xxx.xxx.xxx", password="your password" ]
|
||||
Thing energenie:pmslan:pmslan [ host="xxx.xxx.xxx.xxx", password="your password" ]
|
||||
Thing energenie:pms2lan:pms2lan [ host="xxx.xxx.xxx.xxx", password="your password" ]
|
||||
Thing energenie:pmswlan:pmswlan [ host="xxx.xxx.xxx.xxx", password="your password" ]
|
||||
Thing energenie:pwmlan:pwmlan [ host="xxx.xxx.xxx.xxx", password="your password" ]
|
||||
```
|
||||
|
||||
Items
|
||||
|
||||
```
|
||||
//Power extenders
|
||||
Switch Socket1 { channel="energenie:pm2lan:pm2lan:socket1" }
|
||||
Switch Socket2 { channel="energenie:pm2lan:pm2lan:socket2" }
|
||||
Switch Socket3 { channel="energenie:pm2lan:pm2lan:socket3" }
|
||||
Switch Socket4 { channel="energenie:pm2lan:pm2lan:socket4" }
|
||||
|
||||
//Power measurement
|
||||
Number Voltage { channel="energenie:pwmlan:pwmlan:voltage" }
|
||||
Number Current { channel="energenie:pwmlan:pwmlan:current" }
|
||||
Number Power { channel="energenie:pwmlan:pwmlan:power" }
|
||||
Number Energy { channel="energenie:pwmlan:pwmlan:energy" }
|
||||
```
|
||||
|
||||
Sitemap
|
||||
|
||||
```
|
||||
sitemap energenie label="Energenie Devices"
|
||||
{
|
||||
Frame {
|
||||
// Power extenders
|
||||
Switch item=Socket1
|
||||
Switch item=Socket2
|
||||
Switch item=Socket3
|
||||
Switch item=Socket4
|
||||
|
||||
// Power measurement
|
||||
Number item=Voltage
|
||||
Number item=Current
|
||||
Number item=Power
|
||||
Number item=Energy
|
||||
}
|
||||
}
|
||||
```
|
||||
17
bundles/org.openhab.binding.energenie/pom.xml
Normal file
17
bundles/org.openhab.binding.energenie/pom.xml
Normal file
@@ -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/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.energenie</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: Energenie Binding</name>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.energenie-${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-energenie" description="Energenie Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.energenie/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link EnergenieBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnergenieBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "energenie";
|
||||
|
||||
public static final int TCP_PORT = 5000;
|
||||
|
||||
public static final int STATCRYP_LEN = 4;
|
||||
public static final int CTRLCRYP_LEN = 4;
|
||||
public static final int KEY_LEN = 8;
|
||||
public static final int TASK_LEN = 4;
|
||||
public static final int SOLUTION_LEN = 4;
|
||||
|
||||
public static final String STATE_ON = "0x11";
|
||||
public static final String STATE_ON_NO_VOLTAGE = "0x12";
|
||||
public static final String STATE_OFF = "0x22";
|
||||
public static final String STATE_OFF_NO_VOLTAGE = "0x21";
|
||||
|
||||
public static final String V21_STATE_ON = "0x41";
|
||||
public static final String V21_STATE_OFF = "0x82";
|
||||
|
||||
public static final String WLAN_STATE_ON = "0x51";
|
||||
public static final String WLAN_STATE_OFF = "0x92";
|
||||
|
||||
public static final byte SWITCH_ON = 0x01;
|
||||
public static final byte SWITCH_OFF = 0x02;
|
||||
public static final byte DONT_SWITCH = 0x04;
|
||||
|
||||
public static final int SOCKET_COUNT = 4; // AC power sockets, not network ones
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_PM2LAN = new ThingTypeUID(BINDING_ID, "pm2lan");
|
||||
public static final ThingTypeUID THING_TYPE_PMSLAN = new ThingTypeUID(BINDING_ID, "pmslan");
|
||||
public static final ThingTypeUID THING_TYPE_PMS2LAN = new ThingTypeUID(BINDING_ID, "pms2lan");
|
||||
public static final ThingTypeUID THING_TYPE_PMSWLAN = new ThingTypeUID(BINDING_ID, "pmswlan");
|
||||
public static final ThingTypeUID THING_TYPE_PWMLAN = new ThingTypeUID(BINDING_ID, "pwmlan");
|
||||
|
||||
// List of all Channel ids
|
||||
public static final Pattern CHANNEL_SOCKET = Pattern.compile("socket(\\d)");
|
||||
|
||||
public static final String VOLTAGE = "voltage";
|
||||
public static final String CURRENT = "current";
|
||||
public static final String POWER = "power";
|
||||
public static final String ENERGY = "energy";
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
|
||||
Stream.of(THING_TYPE_PM2LAN, THING_TYPE_PMSLAN, THING_TYPE_PMS2LAN, THING_TYPE_PMSLAN, THING_TYPE_PWMLAN)
|
||||
.collect(Collectors.toSet()));
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal;
|
||||
|
||||
import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.energenie.internal.handler.EnergenieHandler;
|
||||
import org.openhab.binding.energenie.internal.handler.EnergeniePWMHandler;
|
||||
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.Component;
|
||||
|
||||
/**
|
||||
* The {@link EnergenieHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.energenie", service = ThingHandlerFactory.class)
|
||||
public class EnergenieHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = EnergenieBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (THING_TYPE_PMSLAN.equals(thingTypeUID)) {
|
||||
return new EnergenieHandler(thing, EnergenieProtocolEnum.V20);
|
||||
} else if (THING_TYPE_PM2LAN.equals(thingTypeUID)) {
|
||||
return new EnergenieHandler(thing, EnergenieProtocolEnum.V20);
|
||||
} else if (THING_TYPE_PMS2LAN.equals(thingTypeUID)) {
|
||||
return new EnergenieHandler(thing, EnergenieProtocolEnum.V21);
|
||||
} else if (THING_TYPE_PMSWLAN.equals(thingTypeUID)) {
|
||||
return new EnergenieHandler(thing, EnergenieProtocolEnum.WLAN);
|
||||
} else if (THING_TYPE_PWMLAN.equals(thingTypeUID)) {
|
||||
return new EnergeniePWMHandler(thing);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal;
|
||||
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EnergeniePWMStateEnum} contains informations for parsing the readState() result.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public enum EnergeniePWMStateEnum {
|
||||
VOLTAGE("var V = ", 9, 20, 10, SmartHomeUnits.VOLT),
|
||||
CURRENT("var V = ", 9, 20, 100, SmartHomeUnits.AMPERE),
|
||||
POWER("var P=", 6, 20, 466, SmartHomeUnits.WATT),
|
||||
ENERGY("var E=", 6, 20, 25600, SmartHomeUnits.WATT_HOUR);
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EnergeniePWMStateEnum.class);
|
||||
|
||||
private final String stateResponseSearch;
|
||||
private final int start;
|
||||
private final int stop;
|
||||
private final int divisor;
|
||||
private final Unit<?> unit;
|
||||
|
||||
private EnergeniePWMStateEnum(final String stateResponseSearch, final int start, final int stop, final int divisor,
|
||||
final Unit<?> unit) {
|
||||
this.stateResponseSearch = stateResponseSearch;
|
||||
this.start = start;
|
||||
this.stop = stop;
|
||||
this.divisor = divisor;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public String getStateResponseSearch() {
|
||||
return stateResponseSearch;
|
||||
}
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public int getStop() {
|
||||
return stop;
|
||||
}
|
||||
|
||||
public int getDivisor() {
|
||||
return divisor;
|
||||
}
|
||||
|
||||
public State readState(final String loginResponseString) {
|
||||
final int findState = loginResponseString.lastIndexOf(stateResponseSearch);
|
||||
|
||||
if (findState > 0) {
|
||||
logger.trace("searchstring {} found at position {}", stateResponseSearch, findState);
|
||||
final String slicedResponseTmp = loginResponseString.substring(findState + start, findState + stop);
|
||||
logger.trace("transformed state response = {}", slicedResponseTmp);
|
||||
final String[] slicedResponse = slicedResponseTmp.split(";");
|
||||
logger.trace("transformed state response = {} - {}", slicedResponse[0], slicedResponse[1]);
|
||||
final double value;
|
||||
try {
|
||||
value = Double.parseDouble(slicedResponse[0]) / divisor;
|
||||
return QuantityType.valueOf(value, unit);
|
||||
} catch (NumberFormatException e) {
|
||||
logger.debug("Could not Parse State", e);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
} else {
|
||||
logger.trace("searchstring '{} not found", stateResponseSearch);
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal;
|
||||
|
||||
import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link EnergenieProtocolEnum} contains informations for parsing the readState() result.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public enum EnergenieProtocolEnum {
|
||||
V20(STATE_ON),
|
||||
V21(V21_STATE_ON),
|
||||
WLAN(WLAN_STATE_ON);
|
||||
|
||||
private final String statusOn;
|
||||
|
||||
private EnergenieProtocolEnum(String statusOn) {
|
||||
this.statusOn = statusOn;
|
||||
}
|
||||
|
||||
public String getStatusOn() {
|
||||
return statusOn;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal.config;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link EnergenieConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnergenieConfiguration {
|
||||
/**
|
||||
* The default refresh interval in Seconds.
|
||||
*/
|
||||
public static final int DEFAULT_REFRESH_INTERVAL = 60;
|
||||
|
||||
public String host = "";
|
||||
public String password = "";
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal.handler;
|
||||
|
||||
import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.energenie.internal.EnergenieProtocolEnum;
|
||||
import org.openhab.binding.energenie.internal.config.EnergenieConfiguration;
|
||||
import org.openhab.core.cache.ExpiringCache;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
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.thing.util.ThingHandlerHelper;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EnergenieHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnergenieHandler extends BaseThingHandler {
|
||||
|
||||
private static final String CHANNEL_SOCKET_PREFIX = "socket";
|
||||
private final Logger logger = LoggerFactory.getLogger(EnergenieHandler.class);
|
||||
|
||||
/**
|
||||
* Use cache for refresh command to not update again when call is made within 4 seconds of previous call.
|
||||
*/
|
||||
private final ExpiringCache<Boolean> refreshCache = new ExpiringCache<>(Duration.ofSeconds(5), this::refreshState);
|
||||
private final String statusOn;
|
||||
|
||||
private @Nullable EnergenieSocket energenieSocket;
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
private int refreshInterval;
|
||||
private @Nullable String host;
|
||||
|
||||
public EnergenieHandler(final Thing thing, final EnergenieProtocolEnum protocol) {
|
||||
super(thing);
|
||||
this.statusOn = protocol.getStatusOn();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(final ChannelUID channelUID, final Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
refreshCache.getValue();
|
||||
} else if (command instanceof OnOffType) {
|
||||
final byte[] ctrl = { DONT_SWITCH, DONT_SWITCH, DONT_SWITCH, DONT_SWITCH };
|
||||
final Matcher matcher = CHANNEL_SOCKET.matcher(channelUID.getId());
|
||||
|
||||
try {
|
||||
boolean found = false;
|
||||
|
||||
if (matcher.find()) {
|
||||
final int index = Integer.parseInt(matcher.group(1)) - 1;
|
||||
|
||||
if (index >= 0 && index < SOCKET_COUNT) {
|
||||
ctrl[index] = OnOffType.ON.equals(command) ? SWITCH_ON : SWITCH_OFF;
|
||||
stateUpdate(energenieSocket.sendCommand(ctrl));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
logger.debug("Invalid channel id {}, should be value between 1 and {}", channelUID, SOCKET_COUNT);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE);
|
||||
logger.debug("Couldn't get I/O for the connection to: {}:{}.", host, TCP_PORT, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
final EnergenieConfiguration config = getConfigAs(EnergenieConfiguration.class);
|
||||
|
||||
if (!config.host.isEmpty() && !config.password.isEmpty()) {
|
||||
refreshInterval = EnergenieConfiguration.DEFAULT_REFRESH_INTERVAL;
|
||||
host = config.host;
|
||||
logger.debug("Initializing EnergenieHandler for Host '{}'", config.host);
|
||||
energenieSocket = new EnergenieSocket(config.host, config.password);
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::refreshState, 6, refreshInterval, TimeUnit.SECONDS);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Can not access device , IP-Address or password not set");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("EnergenieHandler disposed.");
|
||||
final ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
this.refreshJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean refreshState() {
|
||||
final EnergenieSocket socket = this.energenieSocket;
|
||||
|
||||
if (socket != null) {
|
||||
try {
|
||||
stateUpdate(socket.retrieveStatus());
|
||||
if (thing.getStatus() != ThingStatus.ONLINE && ThingHandlerHelper.isHandlerInitialized(thing)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
return true;
|
||||
} catch (final UnknownHostException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Can't find host: " + e.getMessage());
|
||||
} catch (final IOException e) {
|
||||
logger.debug("Couldn't get I/O for the connection to: {}:{}.", host, TCP_PORT, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Couldn't get I/O for the connection");
|
||||
} catch (final RuntimeException e) {
|
||||
logger.debug("Unexpected error", e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, e.getMessage());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void stateUpdate(final byte[] status) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
final String socket = CHANNEL_SOCKET_PREFIX + (i + 1);
|
||||
final String stringStatus = String.format("0x%02x", status[i]);
|
||||
updateState(socket, OnOffType.from(stringStatus.equals(statusOn)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal.handler;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
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.binding.energenie.internal.EnergeniePWMStateEnum;
|
||||
import org.openhab.binding.energenie.internal.config.EnergenieConfiguration;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
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.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link EnergeniePWMHandler} is responsible for reading states and update PWM channels.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
public class EnergeniePWMHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EnergeniePWMHandler.class);
|
||||
|
||||
private static final int HTTP_TIMEOUT_MILLISECONDS = 6000;
|
||||
|
||||
private String host = "";
|
||||
private String password = "";
|
||||
private int refreshInterval;
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
public EnergeniePWMHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
scheduler.execute(this::getState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
EnergenieConfiguration config = getConfigAs(EnergenieConfiguration.class);
|
||||
|
||||
if (!config.host.isEmpty() && !config.password.isEmpty()) {
|
||||
host = config.host;
|
||||
password = config.password;
|
||||
refreshInterval = EnergenieConfiguration.DEFAULT_REFRESH_INTERVAL;
|
||||
logger.debug("Initializing EnergeniePWMHandler for Host '{}'", host);
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
onUpdate();
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Can not access device , IP-Address or password not set");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("EnergeniePWMHandler disposed.");
|
||||
final ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
|
||||
if (refreshJob != null) {
|
||||
refreshJob.cancel(true);
|
||||
this.refreshJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void getState() {
|
||||
String url = "http://" + host + "/login.html";
|
||||
String urlParameters = "pw=" + password;
|
||||
InputStream urlContent = new ByteArrayInputStream(urlParameters.getBytes(StandardCharsets.UTF_8));
|
||||
String loginResponseString = null;
|
||||
|
||||
try {
|
||||
logger.trace("sending 'POST' request to URL : {}", url);
|
||||
loginResponseString = HttpUtil.executeUrl("POST", url, urlContent, "TEXT/PLAIN", HTTP_TIMEOUT_MILLISECONDS);
|
||||
|
||||
if (loginResponseString != null) {
|
||||
updateState("voltage", EnergeniePWMStateEnum.VOLTAGE.readState(loginResponseString));
|
||||
updateState("current", EnergeniePWMStateEnum.CURRENT.readState(loginResponseString));
|
||||
updateState("power", EnergeniePWMStateEnum.POWER.readState(loginResponseString));
|
||||
updateState("energy", EnergeniePWMStateEnum.ENERGY.readState(loginResponseString));
|
||||
try {
|
||||
HttpUtil.executeUrl("POST", url, HTTP_TIMEOUT_MILLISECONDS);
|
||||
logger.trace("logout from ip {}", host);
|
||||
} catch (IOException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"failed to logout: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.debug("energenie: failed to login to {} with ip {}", thing.getUID(), host, e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void onUpdate() {
|
||||
ScheduledFuture<?> refreshJob = this.refreshJob;
|
||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
||||
this.refreshJob = scheduler.scheduleWithFixedDelay(this::getState, 5, refreshInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.energenie.internal.handler;
|
||||
|
||||
import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Class handling the Socket connections.
|
||||
*
|
||||
* @author Hans-Jörg Merk - Initial contribution
|
||||
* @author Hilbrand Bouwkamp - Moved Socket to it's own class
|
||||
*/
|
||||
@NonNullByDefault
|
||||
class EnergenieSocket {
|
||||
|
||||
private static final int SOCKET_TIMEOUT_MILLISECONDS = 1500;
|
||||
private static final byte[] MESSAGE = { 0x11 };
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EnergenieSocket.class);
|
||||
private final String host;
|
||||
private final byte[] key;
|
||||
|
||||
public EnergenieSocket(final String host, final String password) {
|
||||
this.host = host;
|
||||
this.key = getKey(password);
|
||||
}
|
||||
|
||||
private static byte[] getKey(final String password) {
|
||||
final int passwordLength = password.length();
|
||||
String passwordString = password;
|
||||
for (int i = 0; i < (8 - passwordLength); i++) {
|
||||
passwordString = passwordString + " ";
|
||||
}
|
||||
return passwordString.getBytes();
|
||||
}
|
||||
|
||||
public synchronized byte[] sendCommand(final byte[] ctrl) throws IOException {
|
||||
try (final TaskSocket taskSocket = authorize()) {
|
||||
final OutputStream output = taskSocket.socket.getOutputStream();
|
||||
final DataInputStream input = new DataInputStream(taskSocket.socket.getInputStream());
|
||||
|
||||
if (output == null) {
|
||||
throw new IOException("No connection");
|
||||
} else {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Control message send to EG (int) '{}' (hex)'{}'", ctrl, HexUtils.bytesToHex(ctrl));
|
||||
}
|
||||
output.write(encryptControls(ctrl, taskSocket.task));
|
||||
output.flush();
|
||||
readStatus(input, taskSocket);
|
||||
return updateStatus(taskSocket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized byte[] retrieveStatus() throws IOException {
|
||||
try (final TaskSocket taskSocket = authorize()) {
|
||||
return updateStatus(taskSocket);
|
||||
}
|
||||
}
|
||||
|
||||
private TaskSocket authorize() throws IOException {
|
||||
final TaskSocket taskSocket = new TaskSocket();
|
||||
final OutputStream output = taskSocket.socket.getOutputStream();
|
||||
final DataInputStream input = new DataInputStream(taskSocket.socket.getInputStream());
|
||||
if (output == null) {
|
||||
throw new IOException("No connection");
|
||||
}
|
||||
output.write(MESSAGE);
|
||||
output.flush();
|
||||
logger.trace("Start Condition '{}' send to EG", MESSAGE);
|
||||
input.readFully(taskSocket.task);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("EG responded with task (int) '{}' (hex) '{}'", taskSocket.task,
|
||||
HexUtils.bytesToHex(taskSocket.task));
|
||||
}
|
||||
final byte[] solutionMessage = calculateSolution(taskSocket.task);
|
||||
|
||||
output.write(solutionMessage);
|
||||
output.flush();
|
||||
logger.trace("Solution '{}' send to EG", solutionMessage);
|
||||
readStatus(input, taskSocket);
|
||||
return taskSocket;
|
||||
}
|
||||
|
||||
private void readStatus(final DataInputStream input, final TaskSocket taskSocket) throws IOException {
|
||||
input.readFully(taskSocket.statcryp);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("EG responded with statcryp (int) '{}' (hex) '{}'", taskSocket.statcryp,
|
||||
HexUtils.bytesToHex(taskSocket.statcryp));
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] updateStatus(final TaskSocket taskSocket) throws IOException {
|
||||
final byte[] status = decryptStatus(taskSocket);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("EG responded with status (int) '{}' (hex) '{}'", status, HexUtils.bytesToHex(status));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
private byte[] calculateSolution(final byte[] task) {
|
||||
final int[] uIntTask = new int[4];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
uIntTask[i] = Byte.toUnsignedInt(task[i]);
|
||||
}
|
||||
final int solutionLoword = (((uIntTask[0] ^ key[2]) * key[0]) ^ (key[6] | (key[4] << 8)) ^ uIntTask[2]);
|
||||
final byte[] loword = ByteBuffer.allocate(4).putInt(solutionLoword).array();
|
||||
|
||||
final int solutionHiword = (((uIntTask[1] ^ key[3]) * key[1]) ^ (key[7] | (key[5] << 8)) ^ uIntTask[3]);
|
||||
final byte[] hiword = ByteBuffer.allocate(4).putInt(solutionHiword).array();
|
||||
final byte[] solution = new byte[SOLUTION_LEN];
|
||||
|
||||
solution[0] = loword[3];
|
||||
solution[1] = loword[2];
|
||||
solution[2] = hiword[3];
|
||||
solution[3] = hiword[2];
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
private byte[] decryptStatus(final TaskSocket taskSocket) {
|
||||
final byte[] status = new byte[4];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
status[i] = (byte) ((((taskSocket.statcryp[3 - i] - key[1]) ^ key[0]) - taskSocket.task[3])
|
||||
^ taskSocket.task[2]);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
private byte[] encryptControls(final byte[] controls, final byte[] task) {
|
||||
final byte[] ctrlcryp = new byte[CTRLCRYP_LEN];
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ctrlcryp[i] = (byte) ((((controls[3 - i] ^ task[2]) + task[3]) ^ key[0]) + key[1]);
|
||||
}
|
||||
return ctrlcryp;
|
||||
}
|
||||
|
||||
private class TaskSocket implements Closeable {
|
||||
final Socket socket;
|
||||
final byte[] task = new byte[TASK_LEN];
|
||||
final byte[] statcryp = new byte[STATCRYP_LEN];
|
||||
|
||||
public TaskSocket() throws UnknownHostException, IOException {
|
||||
socket = new Socket(host, TCP_PORT);
|
||||
socket.setSoTimeout(SOCKET_TIMEOUT_MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="energenie" 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>Energenie Binding</name>
|
||||
<description>This is the binding for Energenie.</description>
|
||||
<author>Hans-Jörg Merk</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
<config-description uri="thing-type:energenie:config">
|
||||
<parameter name="host" type="text" required="true">
|
||||
<label>IP-Address</label>
|
||||
<description>The IP address of this device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
<parameter name="password" type="text" required="true">
|
||||
<label>Password</label>
|
||||
<description>The password of this device</description>
|
||||
<default>1</default>
|
||||
<context>password</context>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</config-description:config-descriptions>
|
||||
@@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="energenie"
|
||||
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="pm2lan">
|
||||
<label>EG-PM2-LAN</label>
|
||||
<description>Energenie programmable power strip with LAN interface</description>
|
||||
|
||||
<channels>
|
||||
<channel id="socket1" typeId="socket1"/>
|
||||
<channel id="socket2" typeId="socket2"/>
|
||||
<channel id="socket3" typeId="socket3"/>
|
||||
<channel id="socket4" typeId="socket4"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:energenie:config"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pmslan">
|
||||
<label>EG-PMS-LAN</label>
|
||||
<description>Energenie programmable power strip with LAN interface</description>
|
||||
|
||||
<channels>
|
||||
<channel id="socket1" typeId="socket1"/>
|
||||
<channel id="socket2" typeId="socket2"/>
|
||||
<channel id="socket3" typeId="socket3"/>
|
||||
<channel id="socket4" typeId="socket4"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:energenie:config"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pms2lan">
|
||||
<label>EG-PMS2-LAN</label>
|
||||
<description>Energenie programmable power strip with LAN interface</description>
|
||||
|
||||
<channels>
|
||||
<channel id="socket1" typeId="socket1"/>
|
||||
<channel id="socket2" typeId="socket2"/>
|
||||
<channel id="socket3" typeId="socket3"/>
|
||||
<channel id="socket4" typeId="socket4"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:energenie:config"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pmswlan">
|
||||
<label>EG-PMS-WLAN</label>
|
||||
<description>Energenie programmable power strip with WLAN interface</description>
|
||||
|
||||
<channels>
|
||||
<channel id="socket1" typeId="socket1"/>
|
||||
<channel id="socket2" typeId="socket2"/>
|
||||
<channel id="socket3" typeId="socket3"/>
|
||||
<channel id="socket4" typeId="socket4"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:energenie:config"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pwmlan">
|
||||
<label>EGM-PWM-LAN</label>
|
||||
<description>Energenie energy meter with LAN interface</description>
|
||||
|
||||
<channels>
|
||||
<channel id="voltage" typeId="voltage"/>
|
||||
<channel id="current" typeId="current"/>
|
||||
<channel id="power" typeId="power"/>
|
||||
<channel id="energy" typeId="energy"/>
|
||||
</channels>
|
||||
|
||||
<config-description-ref uri="thing-type:energenie:config"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
<channel-type id="socket1">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Socket 1 State</label>
|
||||
<description>Channel representing the state of socket 1</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="socket2">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Socket 2 State</label>
|
||||
<description>Channel representing the state of socket 2</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="socket3">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Socket 3 State</label>
|
||||
<description>Channel representing the state of socket 3</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="socket4">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Socket 4 State</label>
|
||||
<description>Channel representing the state of socket 4</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="voltage">
|
||||
<item-type>Number:ElectricPotential</item-type>
|
||||
<label>Voltage</label>
|
||||
<description>Channel representing the voltage</description>
|
||||
<state pattern="%.0f %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="current">
|
||||
<item-type>Number:ElectricCurrent</item-type>
|
||||
<label>Current</label>
|
||||
<description>Channel representing the current</description>
|
||||
<state pattern="%.1f %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="power">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>Power</label>
|
||||
<description>Channel representing the power consumption</description>
|
||||
<state pattern="%.0f %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="energy">
|
||||
<item-type>Number:Energy</item-type>
|
||||
<label>Energy</label>
|
||||
<description>Channel representing the energy consumption</description>
|
||||
<state pattern="%.0f %unit%" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user