diff --git a/CODEOWNERS b/CODEOWNERS index 97bd8089e8d23..086a34e101001 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -337,6 +337,7 @@ /bundles/org.openhab.binding.sensebox/ @hakan42 /bundles/org.openhab.binding.sensibo/ @seime /bundles/org.openhab.binding.sensorcommunity/ @weymann +/bundles/org.openhab.binding.senseenergy/ @jsjames /bundles/org.openhab.binding.serial/ @MikeJMajor /bundles/org.openhab.binding.serialbutton/ @kaikreuzer /bundles/org.openhab.binding.shelly/ @markus7017 diff --git a/bundles/org.openhab.binding.senseenergy/README.md b/bundles/org.openhab.binding.senseenergy/README.md index c8b3e5f8456e3..93cdf8051fc3d 100644 --- a/bundles/org.openhab.binding.senseenergy/README.md +++ b/bundles/org.openhab.binding.senseenergy/README.md @@ -2,26 +2,25 @@ This binding supports the Sense Energy monitor (sense.com) which can be used to provide accurate energy usage statistics in the home. In addition to providing real-time and historical energy production and usage data, Sense also uses machine learning to predict specific device usage in the home. -This binding will interface with the Sense cloud and web-socket and provide to openHAB real-time energy use statistics at both the whole house, but also exposes the per device usage. -Note, the binding currently assumes (and is tested) that the monitor is installed in a solar enabled configuration. -Is someone has a device in a different configuration I would welcome the feedback and would be able to add support to the binding. +This binding interfaces with the Sense cloud and local monitor to provide openHAB real-time energy updates for the whole house and any known devices. +Note, the binding currently assumes (and the configuration tested) that the monitor is installed in a solar enabled configuration. +If you have a device in a different configuration I would welcome the feedback and would be able to add support to the binding. -Sense also allows smart plugs and other devices to provide real-time usage to Sense allowing Sense to incorporate accurate usage data into your data. -This binding supports emulation of the smart plugs so data from openHAB can be sent to Sense. -Here are several examples of how this can be used: +Sense also allows smart plugs and other devices to provide real-time usage allowing Sense to incorporate accurate usage statistics into your data. +This binding also supports creation of virtual proxy devices in openHAB which can send to Sense any energy usage for openHAB aware devices. +Here are several examples of how a virtual proxy device can be used. -- A pool pump configured in openHAB where the actual power is known can be communicated to Sense. -- A switch or dimmer controlling a light can be used to notify the lights power when on (or dimmed to a certain level) to Sense. +- A pool pump known in openHAB can update its power when on to Sense +- A switch or dimmer where the power is known can get send to Sense when on. - A fan / scene represented as a String can be used to notify Sense of the power usage when a particualar scene is on. -Using the openHAB follow profile with the channel(s) of the proxy device is an easy way to link these proxy devices to your openHAB setup. +Using the openHAB follow profile with the channel(s) of the proxy device is an easy way to link these proxy devices to your openHAB setup. (see examples) This binding builds off the following works in understanding the Sense API. https://github.com/scottbonline/sense https://github.com/cbpowell/SenseLink/ - ## Supported Things | Thing | id | Type | Description | @@ -33,14 +32,16 @@ https://github.com/cbpowell/SenseLink/ ## Discovery -Once the cloud-connector has been created and initialized, the monitor(s) associated with the account will be auto-discovered. Virtual devices are created manually attached to the monitor bridge. +Initial configurtion involes creating a cloud-connector device with the email and password for the Sense cloud account. +Once the cloud-connector has been created and initialized, the monitor(s) associated with the account will be auto-discovered. +Virtual proxy devices are created manually attached to the monitor bridge. ## Thing Configuration ### Sense Energy Cloud Connector The cloud connector is configured with the email and password for your Sense Energy cloud account. -At present, the binding does not support multi-factor authentication which can be disabled via the Sense app settings on your phone. +At present, the binding does not support multi-factor authentication which should be disabled via the Sense app settings. | Name | Type | Description | Default | Required | Advanced | |-----------------|---------|---------------------------------------|---------|----------|----------| @@ -49,15 +50,19 @@ At present, the binding does not support multi-factor authentication which can b ### Sense Monitor Device -The monitor will be auto-discovered after the could-connector bridge goes online. The only configuration parameter is the id, however, this is not available via the Sense app or sense.com. If supporting textual configuration, you will have to monitor the log in order to see the id for your monitor device. +The monitor will be auto-discovered after the could-connector bridge goes online. +The only configuration parameter is the id, however, this is not available via the Sense app or sense.com. +If supporting textual configuration, you can monitor the openhab.log in order to see the id for your monitor device. | Name | Type | Description | Default | Required | Advanced | |-----------------|---------|---------------------------------------|---------|----------|----------| | id | integer | ID for the monitor device | N/A | yes | no | -### Virtual Device Emulation +### Virtual Proxy Device Emulation -Virtual devices can be created in order to notify Sense of specific power usage of devices in your home. These emulate a TP-Link Kasa HS110 smart plug so you can report actual power usage of any real or virutal device from openHAB. In order to use, you need to enable "TP-Link HS110/HS300 Smart Plug" in the Sense app. +Virtual proxy devices can be created in order to notify Sense of specific power usage of devices in your home. +These emulate a TP-Link Kasa HS110 smart plug and will report to Sense the power usage based on on the configuration of the proxy device and the state. +In order to use, you need to enable "TP-Link HS110/HS300 Smart Plug" in the Sense app. | Name | Type | Description | Default | Required | Advanced | |-----------------|--------- |--------------------------------------- |---------|----------|----------| @@ -67,19 +72,21 @@ Virtual devices can be created in order to notify Sense of specific power usage #### Power Levels -The power levels will be a list of power levels representing different states of the device. +The power levels is a list representing different power levels or states of the device. Here are several examples of how this can be configured: | powerLevel parameter | Description | Example Device | |------------------ |------------------------|--------------------- | -| 10 W | The device is a simple ON/OFF switch or Dimmer with 0 W in the OFF or 0% state, and 10 W in the full ON or 100% state. For a dimmer, the power will be linearly interpolated over the full range [0 W, 10 W] | Light | -| 800 mW,10 W | The device is a simple ON/OFF switch or Dimmer with 800 mW in the OFF or 0% state, and 10 W in the full ON or 100% state. For a dimmer, the power will be linearly interpolated over the full range [800 mW, 10 W] | TV which standby power > 0 W | +| 10 W | The device is a simple ON/OFF switch or Dimmer with 0 W in the OFF or 0% state, and 10 W in the full ON or 100% state. For a dimmer, the power will be linearly interpolated over the full range [0 W, 10 W] depending on current dim level. | Light | +| 800 mW,10 W | The device is a simple ON/OFF switch or Dimmer with 800 mW in the OFF or 0% state, and 10 W in the full ON or 100% state. For a dimmer, the power will be linearly interpolated over the full range [800 mW, 10 W] depending on current dim level. | TV which standby power > 0 W | | 0 W,1 W,3 W,8 W, 15 W | A device which has non-linear power usage at different dim levels. This configuration would use 0 W at 0%, 1 W at 25%, 3 W at 50%, 8 W at 75% and 15 W at the full 100%. Other levels are linearly interpolated within the bounding points of the sub-range. | Dimmable light with non-linear usage profile | -| OFF=0 W,LOW=200 W,HIGH=400 W | A device with several power states with different power levels in each state. | A fan with OFF, LOW, HIGH states | +| OFF=0 W,LOW=200 W,HIGH=400 W | A device with several power states with different power levels in state represented by a String. | A fan with OFF, LOW, HIGH states | #### MAC -Each proxy device must be configured with a MAC address. In a typical configuration, one should leave this field blank and the binding will automatically create a randomized MAC address to be used. +Each proxy device must be configured with a MAC address. +The virtual device creates a random MAC address which is used in identification of the device to Sense. +Note, if configuring via the textual interace, it is important to provide the MAC field, otherwise a different MAC address will be randomized whenever openHAB restarts and the proxy device will appear as a new additional device to Sense. ## Channels @@ -89,9 +96,9 @@ There are no channels associated with the cloud-connector bridge. ### Monitor -The monitor channels are organized into two groups. +The monitor channels are organized into multiple groups. -#### General +#### General Channel Group | Channel | id | Type | Read/Write | Description | |---------- |-------- |-------- |-------- |--------------- | @@ -104,9 +111,11 @@ The monitor channels are organized into two groups. | Leg 1 Power | leg-1-power | Number:Power | R | Power detected by the first Sense clamp (only present when not in solar mode). | | Leg 2 Power | leg-2-power | Number:Power | R | Power detected by the second Sense clamp (only present when not in solar mode). | -#### Discovered Devices +#### Discovered Devices, Self-Reporting Devices and Proxy Devices Channel Groups -Every discovered device will have the following channels. +- Discovered devices are those which Sense has discovered using their algorithms. +- Self-reporting devices are any devices which report their power usage to Sense (i.e. energy reporting smart plugs). +- Proxy devices are any virtual proxy devices set up in openHAB where this binding reports their power usage. | Channel | id | Type | Read/Write | Advanced | Description | |---------- |-------- |-------- |-------- |--------------- |--------- | @@ -116,13 +125,14 @@ Every discovered device will have the following channels. ### Proxy Device Each proxy device has several channels that can be used to notify Sense of the current power usage for the device. +These can either attached to an openHAB item, or, can be used with the system:follow profile to follow the state of another channel (see example). | Channel | id | Type | Read/Write | Description | |---------- |-------- |-------- |-------- |--------------- | -| Power Level | vdevice-power | Number:Power | W | Sets a specific absolute real-time power usage for the device. | -| Device Switch | vdevice-switch | Switch | W | Sets the power level to either the ON or OFF defined in the powerLevels parameter. | -| Device Dimmer | vdevice-dimmer | Dimmer | W | Sets the power level to an interpolated value based on the powerLevels parameter. | -| Device State | vdevice-state | String | W | Sets the power level to the state sepecifice in the powerLevels parameter. | +| Power Level | proxy-device-power | Number:Power | W | Sets a specific absolute real-time power usage for the device. | +| Device Switch | proxy-device-switch | Switch | W | Sets the power level to either the ON or OFF defined in the powerLevels parameter. | +| Device Dimmer | proxy-device-dimmer | Dimmer | W | Sets the power level to an interpolated value based on the powerLevels parameter. | +| Device State | proxy-device-state | String | W | Sets the power level to the state sepecifice in the powerLevels parameter. | ## Full Example @@ -154,11 +164,11 @@ Number:Power Sense_AlwaysOn_Power "Always-On Power" Number:Power Sense_PoolPump_Power "Pool Pump Power" { channel="senseenergy:monitor:cloud:monitor1:discovered-devices#Z0sBBkO1-device-power" } Number:Power Sense_Other_Power "Other Power" { channel="senseenergy:monitor:cloud:monitor1:discovered-devices#unknown-device-power" } -// Virtual device "follow" channels. These should be the actually controlling items for your device. -Switch LightSwitch "Light Switch" { channel="senseenergy:proxy-device:cloud:monitor1:light:vdevice-switch"[profile="system:follow"] } -Dimmer LightDimmer "Light Dimmer" { channel="senseenergy:proxy-device:cloud:monitor1:light:vdevice-dimmer"[profile="system:follow"] } -Number:Power PoolPump_Power "Pool Pump Power" { channel="senseenergy:proxy-device:cloud:monitor1:light:vdevice-power"[profile="system:follow"] } -String Fan_State "Fan State" { channel="senseenergy:proxy-device:cloud:monitor1:light:vdevice-state"[profile="system:follow"] } +// Virtual proxy device "follow" channels. These should be the actually controlling items for your device. +Switch LightSwitch "Light Switch" { channel="senseenergy:proxy-device:cloud:monitor1:light:proxy-device-switch"[profile="system:follow"] } +Dimmer LightDimmer "Light Dimmer" { channel="senseenergy:proxy-device:cloud:monitor1:light:proxy-device-dimmer"[profile="system:follow"] } +Number:Power PoolPump_Power "Pool Pump Power" { channel="senseenergy:proxy-device:cloud:monitor1:light:proxy-device-power"[profile="system:follow"] } +String Fan_State "Fan State" { channel="senseenergy:proxy-device:cloud:monitor1:light:proxy-device-state"[profile="system:follow"] } ``` ### Rules @@ -167,15 +177,16 @@ String Fan_State "Fan State" rule "Sense Energy Discovered Device OnOff" when Channel 'senseenergy:monitor:cloud:monitor1:discovered-devices#XXXX-trigger' triggered or - Channel 'senseenergy:monitor:cloud:monitor1:discovered-devices#YYYY-trigger' triggered + Channel 'senseenergy:monitor:cloud:monitor1:self-reporting-devices#YYYY-trigger' triggered or + Channel 'senseenergy:monitor:cloud:monitor1:proxy-devices#ZZZZ-trigger' triggered then - logInfo("SenseEnergy", "Sense Energy Discovered Device Triggered", "Message: {}", receivedEvent) + logInfo("SenseEnergy", "Sense Energy device turned ON/OFF - Event: {}", receivedEvent) end ``` ### Rule Actions -The binding also supports querying of trend totals over for different periods of time. +The binding also supports querying of trend totals over a periods of time. #### Map queryEnergyTrend(String scale, Instant datetime) @@ -224,9 +235,9 @@ end ## Special notes -- For proxy device to work, the openHAB must be on the same sub-net as the Sense monitor and be able to received broadcast Datagram packets on port 9999. While the binding has not been tested in a Docker configuration, there are some potential issues with being able to receive on port 9999 (see https://github.com/cbpowell/SenseLink/). -- The Sense Energy Monitor can be configured in two different modes depending on whether the secondary current monitor is either attaced to the Solar circuit of another circuit in your house. Unfortunately, the JSON format from the API is different depending on the mode and currently the binding has only been tested and will work in the Solar mode to-date. If there are others wanting to use the setup in the other mode, I would be interested in enabling support for the other mode in the binding with assistance in receiving examples of the JSON format. +For proxy device to work, openHAB must be on the same sub-net as the Sense monitor and be able to receive broadcast Datagram packets on port 9999. +While the binding has not been tested in a Docker configuration, there are some potential issues with being able to receive on port 9999 (see https://github.com/cbpowell/SenseLink/). -##TODO -code review -test authorization +The Sense Energy Monitor can be configured in two different modes depending on whether the secondary current monitor is either attaced to the Solar circuit of another circuit in your house. +Unfortunately, the JSON format from the API is different depending on the mode and currently the binding has only been tested and will work in the Solar mode. +If there are others wanting to use the setup in a different mode, I would be interested in enabling support. diff --git a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/api/SenseEnergyDatagram.java b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/api/SenseEnergyDatagram.java index 6dc128cf1fe03..474bbf1da9fc0 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/api/SenseEnergyDatagram.java +++ b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/api/SenseEnergyDatagram.java @@ -42,7 +42,7 @@ public class SenseEnergyDatagram { private final Logger logger = LoggerFactory.getLogger(SenseEnergyDatagram.class); - static private final int BUFFERSIZE = 1024; + private static final int BUFFERSIZE = 1024; private @Nullable DatagramSocket datagramSocket; private @Nullable SenseEnergyDatagramListener packetListener; @@ -124,11 +124,11 @@ public void run() { while (connected) { try { localSocket.receive(packet); - } catch (IOException exception) { - logger.debug("Exception during packet read - {}", exception.getMessage()); + } catch (IOException e) { + logger.debug("Exception during packet read - {}", e.getMessage()); try { Thread.sleep(100); // allow CPU to breath - } catch (InterruptedException e) { + } catch (InterruptedException ie) { Thread.currentThread().interrupt(); } break; @@ -162,7 +162,6 @@ public void run() { public void sendResponse(SocketAddress socketAddress, SenseEnergyDatagramGetSysInfo getSysInfo, SenseEnergyDatagramGetRealtime getRealtime) throws IOException { - String jsonResponse = String.format("{\"emeter\":{\"get_realtime\":%s},\"system\":{\"get_sysinfo\":%s}}", gson.toJson(getRealtime), gson.toJson(getSysInfo)); diff --git a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyBridgeHandler.java b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyBridgeHandler.java index 5f2200eae66d4..ca937c9dae7df 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyBridgeHandler.java +++ b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyBridgeHandler.java @@ -14,7 +14,6 @@ import static org.openhab.binding.senseenergy.internal.SenseEnergyBindingConstants.HEARTBEAT_MINUTES; import static org.openhab.binding.senseenergy.internal.SenseEnergyBindingConstants.MONITOR_THING_TYPE; -import static org.openhab.binding.senseenergy.internal.SenseEnergyBindingConstants.PROXY_DEVICE_THING_TYPE; import java.util.Collection; import java.util.Collections; @@ -172,17 +171,6 @@ public SenseEnergyMonitorHandler getMonitorHandler(long id) { .orElse(null); // } - @Nullable - public SenseEnergyProxyDeviceHandler getProxyDeviceByMAC(String macAddress) { - return getThing().getThings().stream() // - .filter(t -> t.getThingTypeUID().equals(PROXY_DEVICE_THING_TYPE)) // - .map(t -> (SenseEnergyProxyDeviceHandler) t.getHandler()) // - .filter(Objects::nonNull) // - .filter(h -> h.getMAC().equals(macAddress)) // - .findFirst() // - .orElse(null); - } - /* * rediscover the monitors again to add any back to inbox */ diff --git a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyMonitorHandler.java b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyMonitorHandler.java index 53cf05bd99d69..7f95d170925f0 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyMonitorHandler.java +++ b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyMonitorHandler.java @@ -108,11 +108,11 @@ public class SenseEnergyMonitorHandler extends BaseBridgeHandler implements SenseEnergyWebSocketListener, SenseEnergyDatagramListener { private final Logger logger = LoggerFactory.getLogger(SenseEnergyMonitorHandler.class); - static final private int MAX_RESPONSES_PER_REQUEST = 5; - static final private int SENSE_DATAGRAM_BCAST_PORT = 9999; + private static final int MAX_RESPONSES_PER_REQUEST = 5; + private static final int SENSE_DATAGRAM_BCAST_PORT = 9999; - static final private String CHANNEL_PROPERTY_ID = "sense-id"; - static final private String CHANNEL_PROPERTY_LABEL = "sense-label"; + private static final String CHANNEL_PROPERTY_ID = "sense-id"; + private static final String CHANNEL_PROPERTY_LABEL = "sense-label"; private long id; @Nullable @@ -370,12 +370,7 @@ private DeviceType deduceDeviceType(SenseEnergyApiDevice apiDevice) { return DeviceType.DISCOVERED_DEVICE; } - SenseEnergyBridgeHandler bridgeHandler = getBridgeHandler(); - if (bridgeHandler == null) { - throw new IllegalStateException("Bridge handler is not available"); - } - - SenseEnergyProxyDeviceHandler proxyHandler = bridgeHandler.getProxyDeviceByMAC(apiDevice.tags.deviceID); + SenseEnergyProxyDeviceHandler proxyHandler = getProxyDeviceByMAC(apiDevice.tags.deviceID); return (proxyHandler != null) ? DeviceType.PROXY_DEVICE : DeviceType.SELF_REPORTING_DEVICE; } @@ -547,7 +542,6 @@ public void updateChannel(String channelGroup, String channel, float value, Unit * @param thingStatus */ public void childStatusChange(SenseEnergyProxyDeviceHandler proxyDeviceHandler, ThingStatus thingStatus) { - if (thingStatus == ThingStatus.ONLINE && getThing().getStatus() != ThingStatus.ONLINE) { throw new IllegalStateException("Child should never go ONLINE w/o the bridge being online"); } @@ -690,14 +684,14 @@ public void updateDiscoveredDevicesStatus(SenseEnergyWebSocketDevice[] devices) reconcileDiscoveredDeviceChannels(null); } + DeviceType deviceType = senseDevicesType.getOrDefault(device.id, DeviceType.DISCOVERED_DEVICE); + // Send trigger if device just turned on if (!this.devicesOn.contains(device.id)) { - DeviceType deviceType = senseDevicesType.getOrDefault(device.id, DeviceType.DISCOVERED_DEVICE); triggerChannel(makeDeviceChannelUID(deviceType, device.id, CHANNEL_DEVICE_TRIGGER), "ON"); logger.trace("Discovered device turned on: {}({})", device.name, device.id); } - DeviceType deviceType = senseDevicesType.getOrDefault(device.id, DeviceType.DISCOVERED_DEVICE); ChannelUID channelUID = makeDeviceChannelUID(deviceType, device.id, CHANNEL_DEVICE_POWER); if (isLinked(channelUID)) { updateState(channelUID, new QuantityType<>(device.w, Units.WATT)); @@ -715,4 +709,15 @@ public void updateDiscoveredDevicesStatus(SenseEnergyWebSocketDevice[] devices) } this.devicesOn = updateDevicesOn; } + + @Nullable + public SenseEnergyProxyDeviceHandler getProxyDeviceByMAC(String macAddress) { + return getThing().getThings().stream() // + .filter(t -> t.getThingTypeUID().equals(PROXY_DEVICE_THING_TYPE)) // + .map(t -> (SenseEnergyProxyDeviceHandler) t.getHandler()) // + .filter(Objects::nonNull) // + .filter(h -> h.getMAC().equals(macAddress)) // + .findFirst() // + .orElse(null); + } } diff --git a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyProxyDeviceHandler.java b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyProxyDeviceHandler.java index e53c0ab0192a5..57025621a3cd2 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyProxyDeviceHandler.java +++ b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/SenseEnergyProxyDeviceHandler.java @@ -19,6 +19,7 @@ import static org.openhab.binding.senseenergy.internal.SenseEnergyBindingConstants.CONFIG_PARAMETER_MAC; import static org.openhab.binding.senseenergy.internal.SenseEnergyBindingConstants.CONFIG_PARAMETER_POWER_LEVELS; +import java.util.Arrays; import java.util.HexFormat; import java.util.Map; import java.util.Objects; @@ -59,11 +60,11 @@ public class SenseEnergyProxyDeviceHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(SenseEnergyProxyDeviceHandler.class); - static final private byte[] OUI = new byte[] { 0x53, 0x75, 0x31 }; - static final private String PROXY_DEVICE_SW_VERSION = "1.2.5 Build 171206 Rel.085954"; - static final private String PROXY_DEVICE_HW_VERSION = "1.0"; - static final private String PROXY_DEVICE_TYPE = "IOT.SMARTPLUGSWITCH"; - static final private String PROXY_DEVICE_MODEL = "HS110(US)"; + private static final byte[] OUI = new byte[] { 0x53, 0x75, 0x31 }; + private static final String PROXY_DEVICE_SW_VERSION = "1.2.5 Build 171206 Rel.085954"; + private static final String PROXY_DEVICE_HW_VERSION = "1.0"; + private static final String PROXY_DEVICE_TYPE = "IOT.SMARTPLUGSWITCH"; + private static final String PROXY_DEVICE_MODEL = "HS110(US)"; private SenseEnergyProxyDeviceConfiguration config = new SenseEnergyProxyDeviceConfiguration(); @@ -87,7 +88,7 @@ public void initialize() { byte[] mac = randomizeMAC(OUI); String macAddress = HexFormat.of().withDelimiter(":").formatHex(mac).toUpperCase(); - logger.trace("Spoof MAC address: {}", macAddress); + logger.debug("Spoof MAC address: {}", macAddress); selfConfigurationChange = true; c = this.editConfiguration(); @@ -293,10 +294,9 @@ public byte[] randomizeMAC(byte @Nullable [] oui) { } if (oui != null) { - for (int i = 0; i < oui.length; i++) { - macAddress[i] = oui[i]; - } + macAddress = Arrays.copyOf(oui, oui.length); } + return macAddress; } diff --git a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/helpers/SenseEnergyPowerLevels.java b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/helpers/SenseEnergyPowerLevels.java index d5ce1e6d290c7..f66d5142ded5e 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/helpers/SenseEnergyPowerLevels.java +++ b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/internal/handler/helpers/SenseEnergyPowerLevels.java @@ -99,8 +99,9 @@ public String toString() { @Nullable public QuantityType getLevel(int level) { int numNodes = powerValueLevels.size(); - if (numNodes == 0) + if (numNodes == 0) { return null; + } Point2D.Float p0 = new Point2D.Float(0, 0); Point2D.Float p1 = new Point2D.Float(100, getPowerFloatValue(numNodes - 1)); // if only one node, value is set diff --git a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/utils/TpLinkEncryption.java b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/utils/TpLinkEncryption.java index 7f779d96095fe..6550b12425813 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/utils/TpLinkEncryption.java +++ b/bundles/org.openhab.binding.senseenergy/src/main/java/org/openhab/binding/senseenergy/utils/TpLinkEncryption.java @@ -23,10 +23,9 @@ */ @NonNullByDefault public class TpLinkEncryption { - static final private int STARTKEY = 0xAB; - - static public byte[] encrypt(String unencrypted) { + private static final int STARTKEY = 0xAB; + public static byte[] encrypt(String unencrypted) { try { return encrypt(unencrypted.getBytes("UTF-8"), unencrypted.length()); } catch (UnsupportedEncodingException e) { @@ -34,7 +33,7 @@ static public byte[] encrypt(String unencrypted) { } } - static public byte[] encrypt(byte[] unencrypted, int l) { + public static byte[] encrypt(byte[] unencrypted, int l) { int length = (l == 0) ? unencrypted.length : l; int key = STARTKEY; @@ -48,7 +47,7 @@ static public byte[] encrypt(byte[] unencrypted, int l) { return encrypted; } - static public byte[] decrypt(byte[] crypted, int l) { + public static byte[] decrypt(byte[] crypted, int l) { int key = STARTKEY; int a; diff --git a/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/i18n/senseenergy.properties b/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/i18n/senseenergy.properties index 0c2f44015a92d..99a7f9803eaea 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/i18n/senseenergy.properties +++ b/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/i18n/senseenergy.properties @@ -1,3 +1,83 @@ -# FIXME: please add all English translations to this file so the texts can be translated using Crowdin -# FIXME: to generate the content of this file run: mvn i18n:generate-default-translations -# FIXME: see also: https://www.openhab.org/docs/developer/utils/i18n.html +# add-on + +addon.senseenergy.name = SenseEnergy Binding +addon.senseenergy.description = This is the binding for Sense energy monitor (sense.com). + +# thing types + +thing-type.senseenergy.cloud-connector.label = Sense Energy Cloud Connector +thing-type.senseenergy.cloud-connector.description = The Sense Home cloud connector establishes connection to the Sense cloud API and services. +thing-type.senseenergy.monitor.label = Sense Energy Monitor +thing-type.senseenergy.monitor.description = Sense energy monitor instance. +thing-type.senseenergy.proxy-device.label = Proxy Device +thing-type.senseenergy.proxy-device.description = A proxy device to notifiy the sense monitor of real-time power draw. All channels are "one-way" in that they only report their settings to Sense. + +# thing types config + +thing-type.config.senseenergy.cloud-connector.email.label = Email +thing-type.config.senseenergy.cloud-connector.email.description = Sense account email address +thing-type.config.senseenergy.cloud-connector.password.label = Password +thing-type.config.senseenergy.cloud-connector.password.description = Sense account password +thing-type.config.senseenergy.monitor.id.label = ID +thing-type.config.senseenergy.monitor.id.description = Device ID (only known from the openHAB log or when devices is discovered). +thing-type.config.senseenergy.proxy-device.macAddress.label = Spoof'd MAC Address +thing-type.config.senseenergy.proxy-device.macAddress.description = A spoof'ed MAC address for this proxy device. +thing-type.config.senseenergy.proxy-device.powerLevels.label = Power Levels +thing-type.config.senseenergy.proxy-device.powerLevels.description = Power levels for different states. Examples: "5W" (static full ON power), ".2W, 5W" (for static power range), "OFF=.2W, LOW=2W, HIGH=5W" (for static power in different states), ".2,2W,2.5W,3W" (for non-linear dimmer rage". +thing-type.config.senseenergy.proxy-device.senseName.label = Sense Name +thing-type.config.senseenergy.proxy-device.senseName.description = Name of device to be used by Sense. +thing-type.config.senseenergy.proxy-device.voltage.label = Voltage +thing-type.config.senseenergy.proxy-device.voltage.description = Supply voltage for device. + +# channel group types + +channel-group-type.senseenergy.discovered-devices.label = Discovered Devices +channel-group-type.senseenergy.discovered-devices.description = Sense discovered devices +channel-group-type.senseenergy.general.label = General Information +channel-group-type.senseenergy.general.description = General information about the monitor +channel-group-type.senseenergy.proxy-devices.label = Proxy Devices +channel-group-type.senseenergy.proxy-devices.description = Proxy devices configured in openHAB which report their power +channel-group-type.senseenergy.self-reporting-devices.label = Self-Reporting Devices +channel-group-type.senseenergy.self-reporting-devices.description = Devices that self report their power to Sense + +# channel types + +channel-type.senseenergy.device-power.label = Power +channel-type.senseenergy.device-power.description = Power draw of discovered device. +channel-type.senseenergy.device-trigger.label = On Off Trigger +channel-type.senseenergy.device-trigger.description = Triggered when the discovered device turns ON and OFF. +channel-type.senseenergy.devices-updated-trigger.label = Discovered Devices Updated +channel-type.senseenergy.devices-updated-trigger.description = Triggered when the discovered device list has been updated +channel-type.senseenergy.frequency.label = Frequency +channel-type.senseenergy.frequency.description = Electrical frequency detected by Sense. +channel-type.senseenergy.grid-power.label = Grid Power +channel-type.senseenergy.grid-power.description = Power consumed from the grid (negative if supplying power to grid) +channel-type.senseenergy.leg-1-power.label = Leg 1 Power +channel-type.senseenergy.leg-1-power.description = Power detected by the first Sense clamp. +channel-type.senseenergy.leg-2-power.label = Leg 2 Power +channel-type.senseenergy.leg-2-power.description = Power detected by the second Sense clamp. +channel-type.senseenergy.main-power.label = Main Power +channel-type.senseenergy.main-power.description = Power detected by the main Sense clamp. +channel-type.senseenergy.potential-1.label = Potential 1 +channel-type.senseenergy.potential-1.description = Potential measured on first 120V branch. +channel-type.senseenergy.potential-2.label = Potential 2 +channel-type.senseenergy.potential-2.description = Potential measured on second 120V branch. +channel-type.senseenergy.proxy-device-dimmer.label = Device Dimmer +channel-type.senseenergy.proxy-device-dimmer.description = Dimmer to notify the current power. This will report to sense an interpolated value based on the specified levels. +channel-type.senseenergy.proxy-device-power.label = Power Level +channel-type.senseenergy.proxy-device-power.description = Realtime power to send to Sense. Note, if you are using the Switch, Dimmer or State channels, it is not necessary to use this channel. +channel-type.senseenergy.proxy-device-state.label = Device State +channel-type.senseenergy.proxy-device-state.description = Current device state. This will report to sense the specified power based on the device state. +channel-type.senseenergy.proxy-device-switch.label = Device Switch +channel-type.senseenergy.proxy-device-switch.description = OnOff switch to notify when device is On/Off. This will report to sense the full ON or full OFF values specified. +channel-type.senseenergy.solar-power.label = Solar Power +channel-type.senseenergy.solar-power.description = Power detected by the solar Sense clamp. + +# thing status messages +offline.configuration-error.bridge-missing = Sense Cloud Connector bridge must be online + +# api error conditions +api.invalid-user-credentials = Invalid user credentials, please check configuration +api.response-fail = API response fail +api.response-invalid = API response invalid +api.rate-limit-exceeded = API rate limit exceeded diff --git a/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/thing/monitor.xml b/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/thing/monitor.xml index 7231fbba4633b..219b370685ee2 100644 --- a/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/thing/monitor.xml +++ b/bundles/org.openhab.binding.senseenergy/src/main/resources/OH-INF/thing/monitor.xml @@ -81,49 +81,49 @@ - Number:ElectricPotential + Number:ElectricPotential Potential measured on first 120V branch. - Number:ElectricPotential + Number:ElectricPotential Potential measured on second 120V branch. - Number:Power + Number:Power Power detected by the first Sense clamp. - Number:Power + Number:Power Power detected by the second Sense clamp. - Number:Power + Number:Power Power detected by the main Sense clamp. - Number:Power + Number:Power Power detected by the solar Sense clamp. - Number:Power + Number:Power Power consumed from the grid (negative if supplying power to grid) @@ -136,7 +136,7 @@ - Number:Power + Number:Power Power draw of discovered device. @@ -155,7 +155,7 @@ - Number:Frequency + Number:Frequency Electrical frequency detected by Sense.