package com.bwssystems.HABridge.plugins.harmony;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
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.DeviceMapTypes;
import com.bwssystems.HABridge.Home;
import com.bwssystems.HABridge.IpList;
import com.bwssystems.HABridge.NamedIP;
import com.bwssystems.HABridge.api.CallItem;
import com.bwssystems.HABridge.dao.DeviceDescriptor;
import com.bwssystems.HABridge.hue.BrightnessDecode;
import com.bwssystems.HABridge.hue.MultiCommandUtil;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.whistlingfish.harmony.config.Activity;
import net.whistlingfish.harmony.config.Device;
public class HarmonyHome implements Home {
private static final Logger log = LoggerFactory.getLogger(HarmonyHome.class);
private Map<String, HarmonyServer> hubs;
private Boolean isDevMode;
private Boolean validHarmony;
private Gson aGsonHandler;
public HarmonyHome(BridgeSettings bridgeSettings) {
super();
createHome(bridgeSettings);
}
@Override
public void closeHome() {
if(!validHarmony)
return;
if(isDevMode || hubs == null)
return;
Iterator<String> keys = hubs.keySet().iterator();
while(keys.hasNext()) {
String key = keys.next();
hubs.get(key).getMyHarmony().shutdown();
}
hubs = null;
}
public HarmonyHandler getHarmonyHandler(String aName) {
if(!validHarmony)
return null;
HarmonyHandler aHandler = null;
if(aName == null || aName.equals("")) {
aName = "default";
}
if(hubs.get(aName) == null) {
Set<String> keys = hubs.keySet();
if(!keys.isEmpty()) {
aHandler = hubs.get(keys.toArray()[0]).getMyHarmony();
}
else
aHandler = null;
}
else
aHandler = hubs.get(aName).getMyHarmony();
return aHandler;
}
public List<HarmonyActivity> getActivities() {
Iterator<String> keys = hubs.keySet().iterator();
ArrayList<HarmonyActivity> activityList = new ArrayList<HarmonyActivity>();
if(!validHarmony)
return null;
while(keys.hasNext()) {
String key = keys.next();
Iterator<Activity> activities = hubs.get(key).getMyHarmony().getActivities().iterator();
while(activities.hasNext()) {
HarmonyActivity anActivity = new HarmonyActivity();
anActivity.setActivity(activities.next());
anActivity.setHub(key);
activityList.add(anActivity);
}
}
return activityList;
}
public List<HarmonyActivity> getCurrentActivities() {
Iterator<String> keys = hubs.keySet().iterator();
ArrayList<HarmonyActivity> activityList = new ArrayList<HarmonyActivity>();
if(!validHarmony)
return null;
while(keys.hasNext()) {
String key = keys.next();
Activity theActivity = hubs.get(key).getMyHarmony().getCurrentActivity();
HarmonyActivity anActivity = new HarmonyActivity();
anActivity.setActivity(theActivity);
anActivity.setHub(key);
activityList.add(anActivity);
}
return activityList;
}
public List<HarmonyDevice> getDevices() {
Iterator<String> keys = hubs.keySet().iterator();
ArrayList<HarmonyDevice> deviceList = new ArrayList<HarmonyDevice>();
if(!validHarmony)
return null;
while(keys.hasNext()) {
String key = keys.next();
Iterator<Device> devices = hubs.get(key).getMyHarmony().getDevices().iterator();
while(devices.hasNext()) {
HarmonyDevice aDevice = new HarmonyDevice();
aDevice.setDevice(devices.next());
aDevice.setHub(key);
deviceList.add(aDevice);
}
}
return deviceList;
}
@Override
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
String responseString = null;
log.debug("executing HUE api request to change " + anItem.getType() + " to Harmony: " + device.getName());
if(!validHarmony) {
log.warn("Should not get here, no harmony configured");
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
+ "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/"
+ lightId + "state\"}}]";
} else {
if(anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex]))
{
RunActivity anActivity = null;
if(anItem.getItem().isJsonObject())
anActivity = aGsonHandler.fromJson(anItem.getItem(), RunActivity.class);
else
anActivity = aGsonHandler.fromJson(anItem.getItem().getAsString(), RunActivity.class);
if(anActivity.getHub() == null || anActivity.getHub().isEmpty())
anActivity.setHub(device.getTargetDevice());
HarmonyHandler myHarmony = getHarmonyHandler(anActivity.getHub());
if (myHarmony == null) {
log.warn("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(anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) {
String url = null;
if(anItem.getItem().isJsonObject() || anItem.getItem().isJsonArray()) {
url = aGsonHandler.toJson(anItem.getItem());
} else
url = anItem.getItem().getAsString();
if (url.substring(0, 1).equalsIgnoreCase("{")) {
url = "[" + url + "]";
}
url = BrightnessDecode.calculateReplaceIntensityValue(url, intensity, targetBri, targetBriInc, false);
ButtonPress[] deviceButtons = aGsonHandler.fromJson(url, ButtonPress[].class);
Integer theCount = 1;
for(int z = 0; z < deviceButtons.length; z++) {
if(deviceButtons[z].getCount() != null && deviceButtons[z].getCount() > 0)
theCount = deviceButtons[z].getCount();
for(int y = 0; y < theCount; y++) {
if( y > 0 || z > 0) {
try {
Thread.sleep(aMultiUtil.getTheDelay());
} catch (InterruptedException e) {
// ignore
}
}
if (anItem.getDelay() != null && anItem.getDelay() > 0)
aMultiUtil.setTheDelay(anItem.getDelay());
else
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y));
if(deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty())
deviceButtons[z].setHub(device.getTargetDevice());
HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub());
if (myHarmony == null)
log.warn("Button Press - Should not get here, no harmony hub available");
else
myHarmony.pressButton(deviceButtons[z]);
}
}
}
}
return responseString;
}
@Override
public Home createHome(BridgeSettings bridgeSettings) {
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
validHarmony = bridgeSettings.getBridgeSettingsDescriptor().isValidHarmony();
log.info("Harmony Home created." + (validHarmony ? "" : " No Harmony devices configured.") + (isDevMode ? " DevMode is set." : ""));
if(validHarmony || isDevMode) {
hubs = new HashMap<String, HarmonyServer>();
aGsonHandler =
new GsonBuilder()
.create();
if(isDevMode) {
NamedIP devModeIp = new NamedIP();
devModeIp.setIp("10.10.10.10");
devModeIp.setName("devMode");
List<NamedIP> theList = new ArrayList<NamedIP>();
theList.add(devModeIp);
IpList thedevList = new IpList();
thedevList.setDevices(theList);
bridgeSettings.getBridgeSettingsDescriptor().setHarmonyAddress(thedevList);
}
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getHarmonyAddress().getDevices().iterator();
while(theList.hasNext() && validHarmony) {
NamedIP aHub = theList.next();
boolean loopControl = true;
int retryCount = 0;
while(loopControl) {
try {
hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings.getBridgeSettingsDescriptor(), isDevMode, aHub));
loopControl = false;
} catch (Exception e) {
if(retryCount > 3) {
log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
loopControl = false;
} else {
try {
Thread.sleep(2000);
} catch (InterruptedException e1) {
// ignore
}
}
retryCount++;
}
}
}
if(hubs.isEmpty())
validHarmony = false;
}
return this;
}
@Override
public Object getItems(String type) {
if(validHarmony) {
if(type.equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex]))
return getActivities();
if(type.equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex]))
return getDevices();
if(type.equalsIgnoreCase("current_activity"))
return getCurrentActivities();
}
return null;
}
}