Add java part of plug-in for HomeWizard SmartPlug support

This commit is contained in:
Björn Rennfanz
2017-12-09 21:15:18 +01:00
parent b9437d42e8
commit d337546da7
9 changed files with 505 additions and 4 deletions

View File

@@ -209,6 +209,7 @@ public class BridgeSettings extends BackupHandler {
theBridgeSettings.setHassconfigured(theBridgeSettings.isValidHass());
theBridgeSettings.setDomoticzconfigured(theBridgeSettings.isValidDomoticz());
theBridgeSettings.setSomfyconfigured(theBridgeSettings.isValidSomfy());
theBridgeSettings.setHomeWizardConfigured(theBridgeSettings.isValidHomeWizard());
// Lifx is either configured or not, so it does not need an update.
if(serverPortOverride != null)
theBridgeSettings.setServerPort(serverPortOverride);

View File

@@ -93,7 +93,9 @@ public class BridgeSettingsDescriptor {
@SerializedName("securityData")
@Expose
private String securityData;
@SerializedName("homewizardaddress")
@Expose
private IpList homewizardaddress;
private boolean settingsChanged;
private boolean veraconfigured;
@@ -107,7 +109,8 @@ public class BridgeSettingsDescriptor {
private boolean domoticzconfigured;
private boolean somfyconfigured;
private boolean lifxconfigured;
private boolean homewizardconfigured;
// Deprecated settings
private String haltoken;
private boolean upnpstrict;
@@ -127,7 +130,7 @@ public class BridgeSettingsDescriptor {
this.mqttconfigured = false;
this.hassconfigured = false;
this.domoticzconfigured = false;
this.somfyconfigured = false;
this.homewizardconfigured = false;
this.lifxconfigured = false;
this.farenheit = true;
this.securityData = null;
@@ -188,6 +191,9 @@ public class BridgeSettingsDescriptor {
public IpList getSomfyAddress() {
return somfyaddress;
}
public IpList getHomeWizardAddress() {
return homewizardaddress;
}
public void setVeraAddress(IpList veraAddress) {
this.veraaddress = veraAddress;
}
@@ -197,6 +203,9 @@ public class BridgeSettingsDescriptor {
public void setSomfyAddress(IpList somfyAddress) {
this.somfyaddress = somfyAddress;
}
public void setHomeWizardAddress(IpList homewizardaddress) {
this.homewizardaddress = homewizardaddress;
}
public IpList getHarmonyAddress() {
return harmonyaddress;
}
@@ -236,6 +245,9 @@ public class BridgeSettingsDescriptor {
public boolean isSomfyconfigured() {
return somfyconfigured;
}
public boolean isHomeWizardConfigured() {
return homewizardconfigured;
}
public void setVeraconfigured(boolean veraconfigured) {
this.veraconfigured = veraconfigured;
}
@@ -245,6 +257,9 @@ public class BridgeSettingsDescriptor {
public void setSomfyconfigured(boolean somfyconfigured) {
this.somfyconfigured = somfyconfigured;
}
public void setHomeWizardConfigured(boolean homewizardconfigured) {
this.homewizardconfigured = homewizardconfigured;
}
public boolean isHarmonyconfigured() {
return harmonyconfigured;
}
@@ -492,4 +507,14 @@ public class BridgeSettingsDescriptor {
this.setSettingsChanged(true);
}
}
public Boolean isValidHomeWizard() {
if(this.getHomeWizardAddress() == null || this.getHomeWizardAddress().getDevices().size() <= 0)
return false;
List<NamedIP> devicesList = this.getHomeWizardAddress().getDevices();
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
return false;
return true;
}
}

View File

@@ -22,6 +22,7 @@ public class DeviceMapTypes {
public final static String[] EXEC_DEVICE_COMPAT = { "exec", "Execute Script/Program"};
public final static String[] CMD_DEVICE = { "cmdDevice", "Execute Command/Script/Program"};
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
public final static String[] HOMEWIZARD_DEVICE = { "homewizardDevice", "HomeWizard Device"};
public final static String[] TCP_DEVICE = { "tcpDevice", "TCP Device"};
public final static String[] TCP_DEVICE_COMPAT = { "TCP", "TCP Device"};
public final static String[] UDP_DEVICE = { "udpDevice", "UDP Device"};
@@ -48,6 +49,7 @@ public class DeviceMapTypes {
deviceMapTypes.add(HARMONY_ACTIVITY);
deviceMapTypes.add(HARMONY_BUTTON);
deviceMapTypes.add(HASS_DEVICE);
deviceMapTypes.add(HOMEWIZARD_DEVICE);
deviceMapTypes.add(HTTP_DEVICE);
deviceMapTypes.add(HUE_DEVICE);
deviceMapTypes.add(LIFX_DEVICE);

View File

@@ -14,6 +14,7 @@ import com.bwssystems.HABridge.plugins.exec.CommandHome;
import com.bwssystems.HABridge.plugins.hal.HalHome;
import com.bwssystems.HABridge.plugins.harmony.HarmonyHome;
import com.bwssystems.HABridge.plugins.hass.HassHome;
import com.bwssystems.HABridge.plugins.homewizard.HomeWizardHome;
import com.bwssystems.HABridge.plugins.http.HTTPHome;
import com.bwssystems.HABridge.plugins.hue.HueHome;
import com.bwssystems.HABridge.plugins.lifx.LifxHome;
@@ -68,6 +69,10 @@ public class HomeManager {
aHome = new HassHome(bridgeSettings);
resourceList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex], aHome);
// Setup the HomeWizard configuration if available
aHome = new HomeWizardHome(bridgeSettings);
resourceList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome);
homeList.put(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex], aHome);
//setup the command execution Home
aHome = new CommandHome(bridgeSettings);
homeList.put(DeviceMapTypes.EXEC_DEVICE_COMPAT[DeviceMapTypes.typeIndex], aHome);
@@ -96,7 +101,7 @@ public class HomeManager {
aHome = new FibaroHome(bridgeSettings);
resourceList.put(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex], aHome);
resourceList.put(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex], aHome);
//setup the Domoticz configuration if available
//setup the Domoticz configuration if available
aHome = new DomoticzHome(bridgeSettings);
homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
resourceList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);

View File

@@ -291,6 +291,12 @@ public class DeviceResource {
return homeManager.findResource(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HASS_DEVICE[DeviceMapTypes.typeIndex]);
}, new JsonTransformer());
get (API_CONTEXT + "/homewizard/devices", "application/json", (request, response) -> {
log.debug("Get HomeWizard Clients");
response.status(HttpStatus.SC_OK);
return homeManager.findResource(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]);
}, new JsonTransformer());
get (API_CONTEXT + "/domoticz/devices", "application/json", (request, response) -> {
log.debug("Get Domoticz Clients");
response.status(HttpStatus.SC_OK);

View File

@@ -0,0 +1,151 @@
package com.bwssystems.HABridge.plugins.homewizard;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.BridgeSettings;
import com.bwssystems.HABridge.DeviceMapTypes;
import com.bwssystems.HABridge.Home;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.CallItem;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.hue.ColorData;
import com.bwssystems.HABridge.hue.MultiCommandUtil;
/**
* Control HomeWizard devices over HomeWizard Cloud
*
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
*
*/
public class HomeWizardHome implements Home {
private static final Logger log = LoggerFactory.getLogger(HomeWizardHome.class);
private Map<String, HomeWizzardSmartPlugInfo> plugGateways;
private Boolean validHomeWizard;
private boolean closed;
public HomeWizardHome(BridgeSettings bridgeSettings) {
super();
closed = true;
createHome(bridgeSettings);
closed = false;
}
@Override
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
String responseString = null;
if (!validHomeWizard) {
log.warn("Should not get here, no HomeWizard smart plug available");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Should not get here, no HomeWizard smart plug available\", \"parameter\": \"/lights/"
+ lightId + "state\"}}]";
} else {
if (anItem.getType() != null && anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex])) {
log.debug("Executing HUE api request to change activity to HomeWizard smart plug: " + anItem.getItem().toString());
String jsonToPost = anItem.getItem().toString();
HomeWizzardSmartPlugInfo homeWizzardHandler = getHomeWizzardHandler(device.getTargetDevice());
if(homeWizzardHandler == null) {
log.warn("Should not get here, no HomeWizard smart plug configured");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Should not get here, no HomeWizard smart plug configured\", \"parameter\": \"/lights/"
+ lightId + "state\"}}]";
} else {
try {
homeWizzardHandler.execApply(jsonToPost);
} catch (Exception e) {
log.warn("Error posting request to HomeWizard smart plug");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Error posting request to HomeWizard smart plug\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
}
}
}
}
return responseString;
}
public HomeWizzardSmartPlugInfo getHomeWizzardHandler(String plugName) {
return plugGateways.get(plugName);
}
public List<HomeWizardSmartPlugDevice> getDevices() {
log.debug("consolidating devices for plug gateways");
Iterator<String> keys = plugGateways.keySet().iterator();
ArrayList<HomeWizardSmartPlugDevice> deviceList = new ArrayList<>();
while(keys.hasNext())
{
String key = keys.next();
for(HomeWizardSmartPlugDevice device : plugGateways.get(key).getDevices())
deviceList.add(device);
}
return deviceList;
}
@Override
public Object getItems(String type) {
if (validHomeWizard)
{
if (type.equalsIgnoreCase(DeviceMapTypes.HOMEWIZARD_DEVICE[DeviceMapTypes.typeIndex]))
{
return getDevices();
}
}
return null;
}
@Override
public Home createHome(BridgeSettings bridgeSettings) {
validHomeWizard = bridgeSettings.getBridgeSettingsDescriptor().isValidHomeWizard();
log.info("HomeWizard Home created. " + (validHomeWizard ? "" : "No HomeWizard gateways configured."));
if (validHomeWizard)
{
plugGateways = new HashMap<>();
Iterator<NamedIP> gatewaysList = bridgeSettings.getBridgeSettingsDescriptor().getHomeWizardAddress().getDevices().iterator();
while(gatewaysList.hasNext()) {
NamedIP gateway = gatewaysList.next();
plugGateways.put(gateway.getName(), new HomeWizzardSmartPlugInfo(gateway, gateway.getName()));
}
}
return this;
}
@Override
public void closeHome() {
log.debug("Closing Home.");
if(closed) {
log.debug("Home is already closed....");
return;
}
plugGateways = null;
closed = true;
}
}

View File

@@ -0,0 +1,47 @@
package com.bwssystems.HABridge.plugins.homewizard;
/**
* Control HomeWizard devices over HomeWizard Cloud
*
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
*
*/
public class HomeWizardSmartPlugDevice {
private String name;
private String gateway;
private String id;
private String typeName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGateway() {
return gateway;
}
public void setGateway(String gateway) {
this.gateway = gateway;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTypeName() {
return this.typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
}

View File

@@ -0,0 +1,215 @@
package com.bwssystems.HABridge.plugins.homewizard;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.plugins.homewizard.json.Device;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import us.monoid.json.JSONException;
import us.monoid.json.JSONObject;
/**
* Control HomeWizard devices over HomeWizard Cloud
*
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
*
*/
public class HomeWizzardSmartPlugInfo {
private static final Logger log = LoggerFactory.getLogger(HomeWizardHome.class);
private static final String HOMEWIZARD_LOGIN_URL = "https://cloud.homewizard.com/account/login";
private static final String HOMEWIZARD_API_URL = "https://plug.homewizard.com/plugs";
private static final String EMPTY_STRING = "";
private final String cloudAuth;
private final Gson gson;
private String cloudSessionId;
private String cloudPlugName;
private String cloudPlugId;
public HomeWizzardSmartPlugInfo(NamedIP gateway, String name) {
super();
cloudAuth = "Basic " + new String(Base64.encodeBase64((gateway.getUsername() + ":" + DigestUtils.sha1Hex(gateway.getPassword())).getBytes()));
cloudPlugName = name;
gson = new Gson();
}
public boolean login()
{
try
{
URL url = new URL(HOMEWIZARD_LOGIN_URL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", cloudAuth);
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
connection.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder buffer = new StringBuilder();
String line;
while((line = br.readLine()) != null)
{
buffer.append(line).append("\n");
}
br.close();
// Get session id from result JSON
JSONObject json = new JSONObject(buffer.toString());
cloudSessionId = json.get("session").toString();
}
catch(IOException | JSONException e)
{
log.warn("Error while login to cloud service ", e);
return false;
}
return true;
}
private String requestJson(String request)
{
String result = null;
// Check login was successful
if (login()) {
// Request JSON from Cloud service
try
{
URL url = new URL(HOMEWIZARD_API_URL + request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("X-Session-Token", cloudSessionId);
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
connection.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder buffer = new StringBuilder();
String line;
while((line = br.readLine()) != null)
{
buffer.append(line).append("\n");
}
br.close();
result = buffer.toString();
result = StringUtils.strip(result, "[]");
}
catch(IOException e)
{
log.warn("Error while get json request: {} ", request, e);
}
}
return result;
}
private boolean sendAction(String request, String action)
{
// Check login was successful
if (login()) {
// Post action into Cloud service
try
{
URL url = new URL(HOMEWIZARD_API_URL + request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("X-Session-Token", cloudSessionId);
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
JsonObject actionJson = new JsonObject();
actionJson.addProperty("action", action);
OutputStream os = connection.getOutputStream();
os.write(actionJson.toString().getBytes("UTF-8"));
os.close();
}
catch(IOException e)
{
log.warn("Error while post json action: {} ", request, e);
return false;
}
}
else
{
return false;
}
return true;
}
public List<HomeWizardSmartPlugDevice> getDevices()
{
List<HomeWizardSmartPlugDevice> homewizardDevices = new ArrayList<>();
try {
String result = requestJson(EMPTY_STRING);
JSONObject resultJson = new JSONObject(result);
cloudPlugId = resultJson.getString("id");
String all_devices_json = resultJson.get("devices").toString();
Device[] devices = gson.fromJson(all_devices_json, Device[].class);
// Fix names from JSON
for (Device device : devices) {
device.setTypeName(StringUtils.capitalize(device.getTypeName().replace("_", " ")));
homewizardDevices.add(mapDeviceToHomeWizardSmartPlugDevice(device));
}
}
catch(JSONException e) {
log.warn("Error while get devices from cloud service ", e);
}
log.info("Found: " + homewizardDevices.size() + " devices");
return homewizardDevices;
}
public void execApply(String jsonToPost) {
try
{
JSONObject resultJson = new JSONObject(jsonToPost);
String deviceId = resultJson.getString("deviceid");
String action = resultJson.getString("action");
sendAction("/" + cloudPlugId + "/devices/" + deviceId + "/action", action);
}
catch(JSONException e) {
log.warn("Error while get devices from cloud service ", e);
}
}
protected HomeWizardSmartPlugDevice mapDeviceToHomeWizardSmartPlugDevice(Device device) {
HomeWizardSmartPlugDevice homewizardDevice = new HomeWizardSmartPlugDevice();
homewizardDevice.setId(device.getId());
homewizardDevice.setGateway(cloudPlugName);
homewizardDevice.setName(device.getName());
homewizardDevice.setTypeName(device.getTypeName());
return homewizardDevice;
}
}

View File

@@ -0,0 +1,49 @@
package com.bwssystems.HABridge.plugins.homewizard.json;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
/**
* Control HomeWizard devices over HomeWizard Cloud
*
* @author Björn Rennfanz (bjoern@fam-rennfanz.de)
*
*/
public class Device {
@SerializedName("id")
@Expose
private String id;
@SerializedName("name")
@Expose
private String name;
@SerializedName("typeName")
@Expose
private String typeName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTypeName() {
return this.typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
}