mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 00:10:20 +00:00
Comitinue refactor of huemulator
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<groupId>com.bwssystems.HABridge</groupId>
|
<groupId>com.bwssystems.HABridge</groupId>
|
||||||
<artifactId>ha-bridge</artifactId>
|
<artifactId>ha-bridge</artifactId>
|
||||||
<version>3.5.1k</version>
|
<version>3.5.1l</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class DeviceMapTypes {
|
|||||||
public final static String[] HAL_HOME = { "halHome", "HAL Home Status"};
|
public final static String[] HAL_HOME = { "halHome", "HAL Home Status"};
|
||||||
public final static String[] HAL_THERMO_SET = { "halThermoSet", "HAL Thermostat"};
|
public final static String[] HAL_THERMO_SET = { "halThermoSet", "HAL Thermostat"};
|
||||||
public final static String[] MQTT_MESSAGE = { "mqttMessage", "MQTT Message"};
|
public final static String[] MQTT_MESSAGE = { "mqttMessage", "MQTT Message"};
|
||||||
public final static String[] EXEC_DEVICE = { "execDevice", "Execute Script/Program"};
|
public final static String[] EXEC_DEVICE = { "exec", "Execute Script/Program"};
|
||||||
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
|
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
|
||||||
|
|
||||||
public final static int typeIndex = 0;
|
public final static int typeIndex = 0;
|
||||||
|
|||||||
7
src/main/java/com/bwssystems/HABridge/Home.java
Normal file
7
src/main/java/com/bwssystems/HABridge/Home.java
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package com.bwssystems.HABridge;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.hue.HueMulatorHandler;
|
||||||
|
|
||||||
|
public interface Home extends HueMulatorHandler {
|
||||||
|
public Home createHome(BridgeSettingsDescriptor bridgeSettings);
|
||||||
|
}
|
||||||
103
src/main/java/com/bwssystems/HABridge/hue/BrightnessDecode.java
Normal file
103
src/main/java/com/bwssystems/HABridge/hue/BrightnessDecode.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package com.bwssystems.HABridge.hue;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||||
|
import com.bwssystems.HABridge.api.hue.StateChangeBody;
|
||||||
|
|
||||||
|
import net.java.dev.eval.Expression;
|
||||||
|
|
||||||
|
public class BrightnessDecode {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(BrightnessDecode.class);
|
||||||
|
private static final String INTENSITY_PERCENT = "${intensity.percent}";
|
||||||
|
private static final String INTENSITY_BYTE = "${intensity.byte}";
|
||||||
|
private static final String INTENSITY_MATH = "${intensity.math(";
|
||||||
|
private static final String INTENSITY_MATH_VALUE = "X";
|
||||||
|
private static final String INTENSITY_MATH_CLOSE = ")}";
|
||||||
|
|
||||||
|
public static int calculateIntensity(DeviceState state, StateChangeBody theChanges, boolean hasBri, boolean hasBriInc) {
|
||||||
|
int setIntensity = state.getBri();
|
||||||
|
if (hasBri) {
|
||||||
|
setIntensity = theChanges.getBri();
|
||||||
|
} else if (hasBriInc) {
|
||||||
|
if ((setIntensity + theChanges.getBri_inc()) <= 0)
|
||||||
|
setIntensity = theChanges.getBri_inc();
|
||||||
|
else if ((setIntensity + theChanges.getBri_inc()) > 255)
|
||||||
|
setIntensity = theChanges.getBri_inc();
|
||||||
|
else
|
||||||
|
setIntensity = setIntensity + theChanges.getBri_inc();
|
||||||
|
}
|
||||||
|
return setIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* light weight templating here, was going to use free marker but it was a
|
||||||
|
* bit too heavy for what we were trying to do.
|
||||||
|
*
|
||||||
|
* currently provides: intensity.byte : 0-255 brightness. this is raw from
|
||||||
|
* the echo intensity.percent : 0-100, adjusted for the vera
|
||||||
|
* intensity.math(X*1) : where X is the value from the interface call and
|
||||||
|
* can use net.java.dev.eval math
|
||||||
|
*/
|
||||||
|
public static String replaceIntensityValue(String request, int intensity, boolean isHex) {
|
||||||
|
if (request == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (request.contains(INTENSITY_BYTE)) {
|
||||||
|
if (isHex) {
|
||||||
|
BigInteger bigInt = BigInteger.valueOf(intensity);
|
||||||
|
byte[] theBytes = bigInt.toByteArray();
|
||||||
|
String hexValue = DatatypeConverter.printHexBinary(theBytes);
|
||||||
|
request = request.replace(INTENSITY_BYTE, hexValue);
|
||||||
|
} else {
|
||||||
|
String intensityByte = String.valueOf(intensity);
|
||||||
|
request = request.replace(INTENSITY_BYTE, intensityByte);
|
||||||
|
}
|
||||||
|
} else if (request.contains(INTENSITY_PERCENT)) {
|
||||||
|
int percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
||||||
|
if (isHex) {
|
||||||
|
BigInteger bigInt = BigInteger.valueOf(percentBrightness);
|
||||||
|
byte[] theBytes = bigInt.toByteArray();
|
||||||
|
String hexValue = DatatypeConverter.printHexBinary(theBytes);
|
||||||
|
request = request.replace(INTENSITY_PERCENT, hexValue);
|
||||||
|
} else {
|
||||||
|
String intensityPercent = String.valueOf(percentBrightness);
|
||||||
|
request = request.replace(INTENSITY_PERCENT, intensityPercent);
|
||||||
|
}
|
||||||
|
} else if (request.contains(INTENSITY_MATH)) {
|
||||||
|
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||||
|
String mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),
|
||||||
|
request.indexOf(INTENSITY_MATH_CLOSE));
|
||||||
|
variables.put(INTENSITY_MATH_VALUE, new BigDecimal(intensity));
|
||||||
|
|
||||||
|
try {
|
||||||
|
log.debug("Math eval is: " + mathDescriptor + ", Where " + INTENSITY_MATH_VALUE + " is: "
|
||||||
|
+ String.valueOf(intensity));
|
||||||
|
Expression exp = new Expression(mathDescriptor);
|
||||||
|
BigDecimal result = exp.eval(variables);
|
||||||
|
Integer endResult = Math.round(result.floatValue());
|
||||||
|
if (isHex) {
|
||||||
|
BigInteger bigInt = BigInteger.valueOf(endResult);
|
||||||
|
byte[] theBytes = bigInt.toByteArray();
|
||||||
|
String hexValue = DatatypeConverter.printHexBinary(theBytes);
|
||||||
|
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, hexValue);
|
||||||
|
} else {
|
||||||
|
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE,
|
||||||
|
endResult.toString());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Could not execute Math: " + mathDescriptor, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
|||||||
|
package com.bwssystems.HABridge.hue;
|
||||||
|
|
||||||
|
import com.bwssystems.HABridge.api.CallItem;
|
||||||
|
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||||
|
import com.bwssystems.HABridge.api.hue.StateChangeBody;
|
||||||
|
|
||||||
|
public interface HueMulatorHandler {
|
||||||
|
public String deviceHandler(CallItem anItem, MultiCommandUtil multiComand, String lightId, int iterationCount, DeviceState state, StateChangeBody theStateChanges, boolean stateHasBri, boolean stateHasBriInc);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.bwssystems.HABridge.hue;
|
||||||
|
|
||||||
|
public class MultiCommandUtil {
|
||||||
|
private Integer setCount;
|
||||||
|
private Integer theDelay;
|
||||||
|
|
||||||
|
public Integer getSetCount() {
|
||||||
|
return setCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSetCount(Integer setCount) {
|
||||||
|
this.setCount = setCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTheDelay() {
|
||||||
|
return theDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTheDelay(Integer theDelay) {
|
||||||
|
this.theDelay = theDelay;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,21 +10,34 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||||
|
import com.bwssystems.HABridge.Home;
|
||||||
import com.bwssystems.HABridge.NamedIP;
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
|
import com.bwssystems.HABridge.api.CallItem;
|
||||||
|
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||||
|
import com.bwssystems.HABridge.api.hue.StateChangeBody;
|
||||||
|
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||||
|
import com.bwssystems.HABridge.hue.HueMulatorHandler;
|
||||||
|
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
public class HassHome {
|
public class HassHome implements Home {
|
||||||
private static final Logger log = LoggerFactory.getLogger(HassHome.class);
|
private static final Logger log = LoggerFactory.getLogger(HassHome.class);
|
||||||
private Map<String, HomeAssistant> hassMap;
|
private Map<String, HomeAssistant> hassMap;
|
||||||
private Boolean validHass;
|
private Boolean validHass;
|
||||||
|
private Gson aGsonHandler;
|
||||||
|
|
||||||
public HassHome(BridgeSettingsDescriptor bridgeSettings) {
|
public HassHome(BridgeSettingsDescriptor bridgeSettings) {
|
||||||
super();
|
super();
|
||||||
|
createHome(bridgeSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Home createHome(BridgeSettingsDescriptor bridgeSettings) {
|
||||||
validHass = bridgeSettings.isValidHass();
|
validHass = bridgeSettings.isValidHass();
|
||||||
if(!validHass)
|
if(!validHass)
|
||||||
return;
|
return null;
|
||||||
hassMap = new HashMap<String,HomeAssistant>();
|
hassMap = new HashMap<String,HomeAssistant>();
|
||||||
if(!bridgeSettings.isValidHass())
|
|
||||||
return;
|
|
||||||
Iterator<NamedIP> theList = bridgeSettings.getHassaddress().getDevices().iterator();
|
Iterator<NamedIP> theList = bridgeSettings.getHassaddress().getDevices().iterator();
|
||||||
while(theList.hasNext()) {
|
while(theList.hasNext()) {
|
||||||
NamedIP aHass = theList.next();
|
NamedIP aHass = theList.next();
|
||||||
@@ -32,9 +45,13 @@ public class HassHome {
|
|||||||
hassMap.put(aHass.getName(), new HomeAssistant(aHass));
|
hassMap.put(aHass.getName(), new HomeAssistant(aHass));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Cannot get hass (" + aHass.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
|
log.error("Cannot get hass (" + aHass.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
aGsonHandler =
|
||||||
|
new GsonBuilder()
|
||||||
|
.create();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HomeAssistant getHomeAssistant(String aName) {
|
public HomeAssistant getHomeAssistant(String aName) {
|
||||||
@@ -86,4 +103,40 @@ public class HassHome {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String deviceHandler(CallItem anItem, MultiCommandUtil multiComand, String lightId, int iterationCount, DeviceState state,
|
||||||
|
StateChangeBody theStateChanges, boolean stateHasBri, boolean stateHasBriInc) {
|
||||||
|
String theReturn = null;
|
||||||
|
log.debug("executing HUE api request to send message to HomeAssistant: " + anItem.getItem().toString());
|
||||||
|
HassCommand hassCommand = aGsonHandler.fromJson(anItem.getItem(), HassCommand.class);
|
||||||
|
hassCommand.setBri(BrightnessDecode.replaceIntensityValue(hassCommand.getBri(),
|
||||||
|
BrightnessDecode.calculateIntensity(state, theStateChanges, stateHasBri, stateHasBriInc), false));
|
||||||
|
HomeAssistant homeAssistant = getHomeAssistant(hassCommand.getHassName());
|
||||||
|
if (homeAssistant == null) {
|
||||||
|
log.warn("Should not get here, no HomeAssistants available");
|
||||||
|
theReturn = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||||
|
+ "\",\"description\": \"Should not get here, no HiomeAssistant clients available\", \"parameter\": \"/lights/"
|
||||||
|
+ lightId + "state\"}}]";
|
||||||
|
} else {
|
||||||
|
for (int x = 0; x < multiComand.getSetCount(); x++) {
|
||||||
|
if (x > 0 || iterationCount > 0) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(multiComand.getTheDelay());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (anItem.getDelay() != null && anItem.getDelay() > 0)
|
||||||
|
multiComand.setTheDelay(anItem.getDelay());
|
||||||
|
// else
|
||||||
|
// this.setTheDelay(bridgeSettings.getButtonsleep());
|
||||||
|
log.debug("calling HomeAssistant: " + hassCommand.getHassName() + " - "
|
||||||
|
+ hassCommand.getEntityId() + " - " + hassCommand.getState() + " - " + hassCommand.getBri()
|
||||||
|
+ " - iteration: " + String.valueOf(iterationCount) + " - count: " + String.valueOf(x));
|
||||||
|
homeAssistant.callCommand(hassCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return theReturn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user