diff --git a/pom.xml b/pom.xml index 2bc19ed..76577d9 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.bwssystems.HABridge ha-bridge - 1.1.0f + 1.1.0g jar HA Bridge diff --git a/src/main/java/com/bwssystems/HABridge/HABridge.java b/src/main/java/com/bwssystems/HABridge/HABridge.java index c2b1b59..5b3e7f3 100644 --- a/src/main/java/com/bwssystems/HABridge/HABridge.java +++ b/src/main/java/com/bwssystems/HABridge/HABridge.java @@ -12,7 +12,7 @@ import com.bwssystems.HABridge.devicemanagmeent.*; import com.bwssystems.HABridge.hue.HueMulator; import com.bwssystems.HABridge.upnp.UpnpListener; import com.bwssystems.HABridge.upnp.UpnpSettingsResource; -import com.bwssystems.harmony.HarmonyServer; +import com.bwssystems.harmony.HarmonyHome; import com.google.gson.Gson; public class HABridge { @@ -35,7 +35,7 @@ public class HABridge { public static void main(String[] args) { Logger log = LoggerFactory.getLogger(HABridge.class); DeviceResource theResources; - HarmonyServer myHarmonyServer; + HarmonyHome harmonyHome; HueMulator theHueMulator; UpnpSettingsResource theSettingResponder; UpnpListener theUpnpListener; @@ -89,16 +89,11 @@ public class HABridge { // sparkjava config directive to set html static file location for Jetty staticFileLocation("/public"); //setup the harmony connection if available - try { - myHarmonyServer = HarmonyServer.setup(bridgeSettings); - } catch (Exception e) { - log.error("Cannot get harmony client setup, Exiting with message: " + e.getMessage(), e); - return; - } + harmonyHome = new HarmonyHome(bridgeSettings); // setup the class to handle the resource setup rest api - theResources = new DeviceResource(bridgeSettings, theVersion, myHarmonyServer.getMyHarmony()); + theResources = new DeviceResource(bridgeSettings, theVersion, harmonyHome); // setup the class to handle the hue emulator rest api - theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), myHarmonyServer.getMyHarmony()); + theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), harmonyHome); theHueMulator.setupServer(); // setup the class to handle the upnp response rest api theSettingResponder = new UpnpSettingsResource(bridgeSettings); diff --git a/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java b/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java index ab34eeb..cb26eea 100644 --- a/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java +++ b/src/main/java/com/bwssystems/HABridge/dao/DeviceDescriptor.java @@ -8,6 +8,7 @@ public class DeviceDescriptor{ private String mapId; private String mapType; private String deviceType; + private String targetDevice; private String offUrl; private String onUrl; private String httpVerb; @@ -47,7 +48,15 @@ public class DeviceDescriptor{ this.deviceType = deviceType; } - public String getOffUrl() { + public String getTargetDevice() { + return targetDevice; + } + + public void setTargetDevice(String targetDevice) { + this.targetDevice = targetDevice; + } + + public String getOffUrl() { return offUrl; } diff --git a/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java b/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java index 0d4afdd..8abbc20 100644 --- a/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java +++ b/src/main/java/com/bwssystems/HABridge/dao/DeviceRepository.java @@ -187,6 +187,9 @@ public class DeviceRepository { } else if (name.equals("deviceType")) { deviceEntry.setDeviceType(reader.nextString()); log.debug("Read a Device - device json type:" + deviceEntry.getDeviceType()); + } else if (name.equals("targetDevice")) { + deviceEntry.setTargetDevice(reader.nextString()); + log.debug("Read a Device - device json type:" + deviceEntry.getTargetDevice()); } else if (name.equals("offUrl")) { deviceEntry.setOffUrl(reader.nextString()); log.debug("Read a Device - device json off URL:" + deviceEntry.getOffUrl()); diff --git a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java index e49c8ae..34ac8b0 100644 --- a/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java +++ b/src/main/java/com/bwssystems/HABridge/devicemanagmeent/DeviceResource.java @@ -20,7 +20,7 @@ import com.bwssystems.HABridge.JsonTransformer; import com.bwssystems.HABridge.Version; import com.bwssystems.HABridge.dao.DeviceDescriptor; import com.bwssystems.HABridge.dao.DeviceRepository; -import com.bwssystems.harmony.HarmonyHandler; +import com.bwssystems.harmony.HarmonyHome; import com.bwssystems.luupRequests.Sdata; import com.bwssystems.vera.VeraInfo; import com.google.gson.Gson; @@ -35,14 +35,13 @@ public class DeviceResource { private DeviceRepository deviceRepository; private VeraInfo veraInfo; private Version version; - private HarmonyHandler myHarmonyHandler; + private HarmonyHome myHarmonyHome; private static final Set supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post")); - public DeviceResource(BridgeSettings theSettings, Version theVersion, HarmonyHandler myHarmony) { - super(); + public DeviceResource(BridgeSettings theSettings, Version theVersion, HarmonyHome theHarmonyHome) { this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb()); this.veraInfo = new VeraInfo(theSettings.getVeraAddress(), theSettings.isValidVera()); - this.myHarmonyHandler = myHarmony; + this.myHarmonyHome = theHarmonyHome; this.version = theVersion; setupEndpoints(); } @@ -109,6 +108,7 @@ public class DeviceResource { deviceEntry.setDeviceType(device.getDeviceType()); deviceEntry.setMapId(device.getMapId()); deviceEntry.setMapType(device.getMapType()); + deviceEntry.setTargetDevice(device.getTargetDevice()); deviceEntry.setOnUrl(device.getOnUrl()); deviceEntry.setOffUrl(device.getOffUrl()); deviceEntry.setHttpVerb(device.getHttpVerb()); @@ -187,32 +187,32 @@ public class DeviceResource { get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> { log.debug("Get harmony activities"); - if(myHarmonyHandler == null) { + if(myHarmonyHome == null) { response.status(HttpStatus.SC_NOT_FOUND); return null; } response.status(HttpStatus.SC_OK); - return myHarmonyHandler.getActivities(); + return myHarmonyHome.getActivities(); }, new JsonTransformer()); get (API_CONTEXT + "/harmony/show", "application/json", (request, response) -> { log.debug("Get harmony current activity"); - if(myHarmonyHandler == null) { + if(myHarmonyHome == null) { response.status(HttpStatus.SC_NOT_FOUND); return null; } response.status(HttpStatus.SC_OK); - return myHarmonyHandler.getCurrentActivity(); + return myHarmonyHome.getCurrentActivities(); }, new JsonTransformer()); get (API_CONTEXT + "/harmony/devices", "application/json", (request, response) -> { log.debug("Get harmony devices"); - if(myHarmonyHandler == null) { + if(myHarmonyHome == null) { response.status(HttpStatus.SC_NOT_FOUND); return null; } response.status(HttpStatus.SC_OK); - return myHarmonyHandler.getDevices(); + return myHarmonyHome.getDevices(); }, new JsonTransformer()); } diff --git a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java index 3a46a45..8ef49a3 100644 --- a/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java +++ b/src/main/java/com/bwssystems/HABridge/hue/HueMulator.java @@ -9,6 +9,7 @@ import com.bwssystems.HABridge.api.hue.HueApiResponse; import com.bwssystems.HABridge.dao.*; import com.bwssystems.harmony.ButtonPress; import com.bwssystems.harmony.HarmonyHandler; +import com.bwssystems.harmony.HarmonyHome; import com.bwssystems.harmony.RunActivity; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -56,21 +57,19 @@ public class HueMulator { private static final String HUE_CONTEXT = "/api"; private DeviceRepository repository; - private HarmonyHandler myHarmony; + private HarmonyHome myHarmonyHome; private HttpClient httpClient; private ObjectMapper mapper; - private Map lastUserIdCount; private BridgeSettings bridgeSettings; - public HueMulator(BridgeSettings theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHandler theHandler){ + public HueMulator(BridgeSettings theBridgeSettings, DeviceRepository aDeviceRepository, HarmonyHome theHarmonyHome){ httpClient = HttpClients.createDefault(); mapper = new ObjectMapper(); //armzilla: work around Echo incorrect content type and breaking mapping. Map manually mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); repository = aDeviceRepository; - myHarmony = theHandler; + myHarmonyHome = theHarmonyHome; bridgeSettings = theBridgeSettings; - lastUserIdCount = new HashMap<>(); } // This function sets up the sparkjava rest calls for the hue api @@ -252,26 +251,29 @@ public class HueMulator { */ String userId = request.params(":userid"); String lightId = request.params(":id"); - log.debug("hue state change requested: " + userId + " from " + request.ip() + " body: " + request.body()); - + String responseString = null; + String url = null; DeviceState state = null; + log.debug("hue state change requested: " + userId + " from " + request.ip() + " body: " + request.body()); + response.header("Access-Control-Allow-Origin", request.headers("Origin")); + response.type("application/json; charset=utf-8"); + response.status(HttpStatus.SC_OK); + try { state = mapper.readValue(request.body(), DeviceState.class); } catch (IOException e) { log.error("Object mapper barfed on input of body.", e); - response.status(HttpStatus.SC_BAD_REQUEST); - return null; + responseString = "[{\"error\":{\"type\": 2, \"address\": \"/lights/" + lightId + ",\"description\": \"Object mapper barfed on input of body.\"}}]"; + return responseString; } DeviceDescriptor device = repository.findOne(lightId); if (device == null) { - response.status(HttpStatus.SC_NOT_FOUND); - log.error("Could not find devcie: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body()); - return null; + log.error("Could not find device: " + lightId + " for hue state change request: " + userId + " from " + request.ip() + " body: " + request.body()); + responseString = "[{\"error\":{\"type\": 3, \"address\": \"/lights/" + lightId + ",\"description\": \"Could not find device\", \"resource\": \"/lights/" + lightId + "\"}}]"; + return responseString; } - String responseString =null; - String url = null; if (state.isOn()) { responseString = "[{\"success\":{\"/lights/" + lightId + "/state/on\":true}}"; url = device.getOnUrl(); @@ -294,19 +296,32 @@ public class HueMulator { } else responseString = responseString + "]"; - - + if(device.getDeviceType().toLowerCase().contains("activity")) { log.debug("executing activity to Harmony: " + url); RunActivity anActivity = new Gson().fromJson(url, RunActivity.class); - myHarmony.startActivity(anActivity); + HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice()); + if(myHarmony == null) + { + log.error("Should not get here, no harmony hub available"); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; + } + else + myHarmony.startActivity(anActivity); } else if(device.getDeviceType().toLowerCase().contains("button")) { log.debug("executing button press to Harmony: " + url); ButtonPress aDeviceButton = new Gson().fromJson(url, ButtonPress.class); - myHarmony.pressButton(aDeviceButton); + HarmonyHandler myHarmony = myHarmonyHome.getHarmonyHandler(device.getTargetDevice()); + if(myHarmony == null) + { + log.error("Should not get here, no harmony hub available"); + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; + } + else + myHarmony.pressButton(aDeviceButton); } else { @@ -320,15 +335,11 @@ public class HueMulator { body = replaceIntensityValue(device.getContentBodyOff(), state.getBri()); // make call if (!doHttpRequest(url, device.getHttpVerb(), device.getContentType(), body)) { - response.status(HttpStatus.SC_SERVICE_UNAVAILABLE); log.error("Error on calling url to change device state: " + url); - return null; + responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId + ",\"description\": \"Error on calling url to change device state\", \"parameter\": \"/lights/" + lightId + "state\"}}]"; } } - response.header("Access-Control-Allow-Origin", request.headers("Origin")); - response.type("application/json; charset=utf-8"); - response.status(HttpStatus.SC_OK); return responseString; }); } diff --git a/src/main/java/com/bwssystems/harmony/HarmonyActivity.java b/src/main/java/com/bwssystems/harmony/HarmonyActivity.java new file mode 100644 index 0000000..5b65a71 --- /dev/null +++ b/src/main/java/com/bwssystems/harmony/HarmonyActivity.java @@ -0,0 +1,21 @@ +package com.bwssystems.harmony; + +import net.whistlingfish.harmony.config.Activity; + +public class HarmonyActivity { + private String hub; + private Activity activity; + public String getHub() { + return hub; + } + public void setHub(String hub) { + this.hub = hub; + } + public Activity getActivity() { + return activity; + } + public void setActivity(Activity activity) { + this.activity = activity; + } + +} diff --git a/src/main/java/com/bwssystems/harmony/HarmonyCurrentActivity.java b/src/main/java/com/bwssystems/harmony/HarmonyCurrentActivity.java new file mode 100644 index 0000000..b908e61 --- /dev/null +++ b/src/main/java/com/bwssystems/harmony/HarmonyCurrentActivity.java @@ -0,0 +1,5 @@ +package com.bwssystems.harmony; + +public class HarmonyCurrentActivity { + +} diff --git a/src/main/java/com/bwssystems/harmony/HarmonyDevice.java b/src/main/java/com/bwssystems/harmony/HarmonyDevice.java new file mode 100644 index 0000000..a1a5fcc --- /dev/null +++ b/src/main/java/com/bwssystems/harmony/HarmonyDevice.java @@ -0,0 +1,5 @@ +package com.bwssystems.harmony; + +public class HarmonyDevice { + +} diff --git a/src/main/java/com/bwssystems/harmony/HarmonyHome.java b/src/main/java/com/bwssystems/harmony/HarmonyHome.java new file mode 100644 index 0000000..58d98e0 --- /dev/null +++ b/src/main/java/com/bwssystems/harmony/HarmonyHome.java @@ -0,0 +1,70 @@ +package com.bwssystems.harmony; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.bwssystems.HABridge.BridgeSettings; +import com.bwssystems.HABridge.NamedIP; + +import net.whistlingfish.harmony.config.Activity; + +public class HarmonyHome { + private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class); + private Map hubs; + + public HarmonyHome(BridgeSettings bridgeSettings) { + super(); + hubs = new HashMap(); + Iterator theList = bridgeSettings.getHarmonyAddress().getDevices().iterator(); + while(theList.hasNext()) { + NamedIP aHub = theList.next(); + try { + hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings, aHub)); + } catch (Exception e) { + log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + e.getMessage(), e); + return; + } + } + } + + public HarmonyHandler getHarmonyHandler(String aName) { + if(aName == null || aName.equals("")) { + HarmonyHandler aHandler = hubs.get("default").getMyHarmony(); + if(aHandler == null) { + Set keys = hubs.keySet(); + if(!keys.isEmpty()) { + aHandler = hubs.get(keys.toArray()[0]).getMyHarmony(); + } + else + aHandler = null; + } + return aHandler; + } + return hubs.get(aName).getMyHarmony(); + } + + public List getActivities() { + Iterator keys = hubs.keySet().iterator(); + while(keys.hasNext()) { + List theActivities = hubs.get(keys.next()).getMyHarmony().getActivities(); + ListIterator activities = theActivities.listIterator(); + while(activities.hasNext()) { + + } + } + return null; + } + public List getCurrentActivities() { + return null; + } + public List getDevices() { + return null; + } +} diff --git a/src/main/java/com/bwssystems/harmony/HarmonyServer.java b/src/main/java/com/bwssystems/harmony/HarmonyServer.java index 1e1ec50..43d0dcf 100644 --- a/src/main/java/com/bwssystems/harmony/HarmonyServer.java +++ b/src/main/java/com/bwssystems/harmony/HarmonyServer.java @@ -8,6 +8,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.bwssystems.HABridge.BridgeSettings; +import com.bwssystems.HABridge.NamedIP; import com.google.inject.Guice; import com.google.inject.Injector; @@ -24,23 +25,25 @@ public class HarmonyServer { private HarmonyHandler myHarmony; private DevModeResponse devResponse; private OAReplyProvider dummyProvider; + private NamedIP myNameAndIP; private Logger log = LoggerFactory.getLogger(HarmonyServer.class); - public HarmonyServer() { + public HarmonyServer(NamedIP theHarmonyAddress) { super(); myHarmony = null; dummyProvider = null; + myNameAndIP = theHarmonyAddress; } - public static HarmonyServer setup(BridgeSettings bridgeSettings) throws Exception { + public static HarmonyServer setup(BridgeSettings bridgeSettings, NamedIP theHarmonyAddress) throws Exception { if(!bridgeSettings.isValidHarmony()) { - return new HarmonyServer(); + return new HarmonyServer(theHarmonyAddress); } Injector injector = null; if(!bridgeSettings.isDevMode()) injector = Guice.createInjector(new HarmonyClientModule()); - HarmonyServer mainObject = new HarmonyServer(); + HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress); if(!bridgeSettings.isDevMode()) injector.injectMembers(mainObject); mainObject.execute(bridgeSettings); @@ -70,7 +73,7 @@ public class HarmonyServer { log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel())); } }); - harmonyClient.connect(mySettings.getHarmonyAddress().getDevices().get(0).getIp(), mySettings.getHarmonyUser(), mySettings.getHarmonyPwd()); + harmonyClient.connect(myNameAndIP.getIp(), mySettings.getHarmonyUser(), mySettings.getHarmonyPwd()); } myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse); } diff --git a/src/main/resources/public/views/harmonyactivity.html b/src/main/resources/public/views/harmonyactivity.html index eb8e9da..f0f80fb 100644 --- a/src/main/resources/public/views/harmonyactivity.html +++ b/src/main/resources/public/views/harmonyactivity.html @@ -65,7 +65,7 @@ {{harmonyactivity.label}} {{harmonyactivity.id}} + ng-click="deleteDeviceByMapId(harmonyactivity.id, 'harmonyActivity')">Delete diff --git a/src/main/resources/public/views/veradevice.html b/src/main/resources/public/views/veradevice.html index e62ec45..c1b8911 100644 --- a/src/main/resources/public/views/veradevice.html +++ b/src/main/resources/public/views/veradevice.html @@ -93,7 +93,7 @@ {{veradevice.room}} + ng-click="deleteDeviceByMapId(veradevice.id, 'veraDevice')">Delete diff --git a/src/main/resources/public/views/verascene.html b/src/main/resources/public/views/verascene.html index d39e2c3..7b6926e 100644 --- a/src/main/resources/public/views/verascene.html +++ b/src/main/resources/public/views/verascene.html @@ -76,7 +76,7 @@ {{verascene.room}} + ng-click="deleteDeviceByMapId(verascene.id, 'veraScene')">Delete