Skip to content

Commit

Permalink
Merge pull request #843 from bwssytems/FixesForV5
Browse files Browse the repository at this point in the history
Fixes for v5

Fixes #842 Show and manage linked devices to the ha-bridge enhancement
Fixes #797 harmony hub not pairing bug question
Fixes #817 Log full of error: The requested route [/(null)] has not been mapped in Spark bug question
Fixes #821 Support HEX-Formatted RGB Values for color enhancement question
Fixes #837 -Dexec.garden breaks script execution with trailing slash enhancement question
Fixes #800 5.0.0 no longer connects to the vera enhancement question
Fixes #801 Fibaro scenes are not created bug question
Fixes #805 Fibaro HomeCenter2: Devices "Build Item" broken bug question
Fixes #841 add support for timestamp http URL variable
Fixes #836 Add support for cheap HomeWizard SmartPlugs (Smartwares Smarthome Controller)
  • Loading branch information
bwssytems committed Dec 12, 2017
2 parents 71c4447 + 9d07fac commit dc49de4
Show file tree
Hide file tree
Showing 38 changed files with 1,171 additions and 34 deletions.
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ THe Harmony Hub Path looks like this:

**FAQ: Please look here for the current FAQs! https://github.com/bwssytems/ha-bridge/wiki/HA-Bridge-FAQs**

In the cases of systems that require authorization and/or have APIs that cannot be handled in the current method, a module may need to be built. The Harmony Hub is such a module and so is the Nest module. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge, Nest, Somfy Tahoma and the ability to proxy all of your real Hue bridges behind this bridge.
In the cases of systems that require authorization and/or have APIs that cannot be handled in the current method, a module may need to be built. The Harmony Hub is such a module and so is the Nest module. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge, Nest, Somfy Tahoma, Home Assistant, Domoticz, HAL, Fibaro, HomeWizard and the ability to proxy all of your real Hue bridges behind this bridge.

Alternatively the Bridge supports custom calls as well using http/https/udp and tcp such as the LimitlessLED/MiLight bulbs using the UDP protocol. Binary data is supported with UDP/TCP.

Expand All @@ -61,17 +61,17 @@ ATTENTION: This requires JDK 1.8 to run
ATTENTION: Due to port 80 being the default, Linux restricts this to super user. Use the instructions below.

```
java -jar ha-bridge-5.0.0.jar
java -jar ha-bridge-5.1.0.jar
```
### Automation on Linux systems
To have this configured and running automatically there are a few resources to use. One is using Docker and a docker container has been built for this and can be gotten here: https://github.com/aptalca/docker-ha-bridge

Create the directory and make sure that ha-bridge-5.0.0.jar is in your /home/pi/habridge directory.
Create the directory and make sure that ha-bridge-5.1.0.jar is in your /home/pi/habridge directory.
```
pi@raspberrypi:~ $ mkdir habridge
pi@raspberrypi:~ $ cd habridge
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.0.0/ha-bridge-5.0.0.jar
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.1.0/ha-bridge-5.1.0.jar
```

#### System Control Setup on a pi (preferred)
Expand All @@ -92,7 +92,7 @@ After=network.target
[Service]
Type=simple
WorkingDirectory=/home/pi/habridge
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.0.0.jar
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.1.0.jar
[Install]
WantedBy=multi-user.target
Expand Down Expand Up @@ -127,7 +127,7 @@ Then cut and past this, modify any locations that are not correct
```
cd /home/pi/habridge
rm /home/pi/habridge/habridge-log.txt
nohup java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.0.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
nohup java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.1.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
chmod 777 /home/pi/habridge/habridge-log.txt
```
Expand Down Expand Up @@ -257,6 +257,8 @@ The default location for the db to contain the devices as they are added is "dat
The server defaults to the first available address on the host if this is not given. This default may NOT be the correct IP that is your public IP for your host on the network. It is best to set this parameter to not have discovery issues. Replace this value with the server ipv4 address you would like to use as the address that any upnp device will call after discovery.
#### Use UPNP Address Interface
The server tries to bind to all interfaces to respond to UPNP request. Setting this to `true` will make the binding to the interface that has the `UPNP IP Address`. The default is to be all interfaces which is set as false.
#### Use Rooms for Alexa
This setting controls rooms for Alexa. If it is set to true, any device ID abaove 10000 is treated as a special group. The default is set as false.
#### Web Server IP Address
The server defaults to all interfaces on the machine (0.0.0.0). Replace this value with the server ipv4 address you would like to use as the address that will bind to a specific ip address on an interface if you would like. This is only necessary if you want to isolate how access is handled to the web UI.
#### Web Server Port
Expand Down Expand Up @@ -358,7 +360,7 @@ The Add/Edit tab will show you the fields to fill in for the above in a form, wh
The format of the item can be the default HTTP request which executes the URLs formatted as `http:https://<your stuff here>` as a GET. Other options to this are to select the HTTP Verb and add the data type and add a body that is passed with the request. Secure https is supported as well, just use `https://<your secure call here>`. When using POST and PUT, you have the ability to specify the body that will be sent with the request as well as the application type for the http call.

The valid device types are: "custom", "veraDevice", "veraScene", "harmonyActivity", "harmonyButton", "nestHomeAway", "nestThermoSet", "hueDevice", "halDevice",
"halButton", "halHome", "halThermoSet", "mqttMessage", "cmdDevice", "hassDevice", "tcpDevice", "udpDevice", "httpDevice", "domoticzDevice", "somfyDevice"
"halButton", "halHome", "halThermoSet", "mqttMessage", "cmdDevice", "hassDevice", "homewizardDevice", "tcpDevice", "udpDevice", "httpDevice", "domoticzDevice", "somfyDevice"

Filter Ip example:
```
Expand All @@ -378,7 +380,7 @@ Headers can be added as well using a Json construct [{"name":"header type name",

Another option that is detected by the bridge is to use UDP or TCP direct calls such as `udp:https://<ip_address>:<port>/<your stuff here>` to send a UDP request. TCP calls are handled the same way as `tcp:https://<ip_address>:<port>/<your stuff here>`. If your data for the UDP or TCP request is formatted as "0x00F009B9" lexical hex format, the bridge will convert the data into a binary stream to send.

You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below.
You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, "${time.millis}" for inserting a pure timestamp (milliseconds from 1.1.1970), ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below.
Examples:
```
Expand Down Expand Up @@ -432,7 +434,12 @@ There are multiple replacement constructs available to be put into any of the ca

You can control items that require special calculated values using ${intensity.math(<your expression using "X" as the value to operate on>)} i.e. "${intensity.math(X/4)}".

For the items that want to have a date time put into the message, utilize ${time.format(yyyy-MM-ddTHH:mm:ssXXX)} where "yyyy-MM-ddTHH:mm:ssXXX" can be any format from the Java SimpleDateFormat documented here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
For the items that want to have a date time put into the message, utilize ${time.format(yyyy-MM-ddTHH:mm:ssXXX)} where "yyyy-MM-ddTHH:mm:ssXXX" can be any format from the Java SimpleDateFormat documented here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html. Also, there is a $(time.millis) which will put the millis timestamp where this replacement control is located.

Color has been added as a replacement control and the available values are $(color.r), $(color.g), $(color.b) which are representations of each color as 0 - 255. There are hex equivalents as well as $(color.rx), $(color.gx), $(color.bx) and $(color.rgbx) as 2 place hex representations except for rgbx which is a six place hex representation.

Special handling for milights is included and is handled by $(color.milight:x). The usage for that is as follows: udp:https://ip:port/0x${color.milight:x} where x is a number between 0 and 4 (0 all groups, 1-4 specific group). The group is necessary in case the color turns out to be white. The correct group on must of course be sent before that udp packet.
Note that milight can only use 255 colors and white is handled completely separate for the rgbw strips, so setting temperature via ct with milight does something but not really the desired result

Also, device data can be inserted into your payloads by the use of "${device.name}", "${device.id}", "${device.uniqueid}", "${device.targetDevice}", "${device.mapId}", "${device.mapType}", "${device.deviceType}", "${device.requesterAddress}", "${device.description}" and "${device.comments}". These work just like the dimming value replacements.
e.g.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>com.bwssystems.HABridge</groupId>
<artifactId>ha-bridge</artifactId>
<version>5.0.0</version>
<version>5.1.0</version>
<packaging>jar</packaging>

<name>HA Bridge</name>
Expand Down
41 changes: 39 additions & 2 deletions src/main/java/com/bwssystems/HABridge/BridgeSecurity.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ public Map<String, WhitelistEntry> getWhitelist() {
return securityDescriptor.getWhitelist();
}

public void setWhitelist(Map<String, WhitelistEntry> aWhitelist) {
securityDescriptor.setWhitelist(aWhitelist);
settingsChanged = true;
return;
}

public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
String validUser = null;
boolean found = false;
Expand Down Expand Up @@ -238,6 +244,31 @@ public HueError[] validateWhitelistUser(String aUser, String userDescription, bo
return null;
}

public String findWhitelistUserByDeviceType(String aDeviceType) {
String validUser = null;
boolean found = false;
WhitelistEntry anEntry = null;
if (aDeviceType != null) {
if (securityDescriptor.getWhitelist() != null) {
Set<String> theUserIds = securityDescriptor.getWhitelist().keySet();
Iterator<String> userIterator = theUserIds.iterator();
while (!found && userIterator.hasNext()) {
validUser = userIterator.next();
anEntry = securityDescriptor.getWhitelist().get(validUser);
if (anEntry.getName().equals(aDeviceType)) {
found = true;
log.debug("findWhitelistUserByDeviceType: found a user <" + validUser + "> for device type <" + aDeviceType + ">");
}
}
}
}

if(!found)
validUser = null;

return validUser;
}

private void newWhitelistUser(String aUser, String userDescription) {
if (securityDescriptor.getWhitelist() == null) {
securityDescriptor.setWhitelist(new HashMap<>());
Expand All @@ -250,8 +281,14 @@ private void newWhitelistUser(String aUser, String userDescription) {
}

public String createWhitelistUser(String userDescription) {
String aUser = getNewUserID();
newWhitelistUser(aUser, userDescription);
String aUser = null;
String theEntry = findWhitelistUserByDeviceType(userDescription);
if(theEntry == null) {
aUser = getNewUserID();
newWhitelistUser(aUser, userDescription);
} else {
aUser = theEntry;
}
return aUser;
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/bwssystems/HABridge/BridgeSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ public void buildSettings() {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class BridgeSettingsDescriptor {
@SerializedName("useupnpiface")
@Expose
private boolean useupnpiface;
@SerializedName("userooms")
@Expose
private boolean userooms;
@SerializedName("serverport")
@Expose
private Integer serverport;
Expand Down Expand Up @@ -93,7 +96,9 @@ public class BridgeSettingsDescriptor {
@SerializedName("securityData")
@Expose
private String securityData;

@SerializedName("homewizardaddress")
@Expose
private IpList homewizardaddress;

private boolean settingsChanged;
private boolean veraconfigured;
Expand All @@ -107,7 +112,8 @@ public class BridgeSettingsDescriptor {
private boolean domoticzconfigured;
private boolean somfyconfigured;
private boolean lifxconfigured;

private boolean homewizardconfigured;

// Deprecated settings
private String haltoken;
private boolean upnpstrict;
Expand All @@ -116,6 +122,7 @@ public BridgeSettingsDescriptor() {
super();
this.upnpstrict = true;
this.useupnpiface = false;
this.userooms = false;
this.traceupnp = false;
this.nestconfigured = false;
this.veraconfigured = false;
Expand All @@ -127,7 +134,7 @@ public 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;
Expand All @@ -149,6 +156,12 @@ public boolean isUseupnpiface() {
public void setUseupnpiface(boolean useupnpiface) {
this.useupnpiface = useupnpiface;
}
public boolean isUserooms() {
return userooms;
}
public void setUserooms(boolean userooms) {
this.userooms = userooms;
}
public Integer getServerPort() {
return serverport;
}
Expand Down Expand Up @@ -188,6 +201,9 @@ public IpList getFibaroAddress() {
public IpList getSomfyAddress() {
return somfyaddress;
}
public IpList getHomeWizardAddress() {
return homewizardaddress;
}
public void setVeraAddress(IpList veraAddress) {
this.veraaddress = veraAddress;
}
Expand All @@ -197,6 +213,9 @@ public void setFibaroAddress(IpList fibaroAddress) {
public void setSomfyAddress(IpList somfyAddress) {
this.somfyaddress = somfyAddress;
}
public void setHomeWizardAddress(IpList homewizardaddress) {
this.homewizardaddress = homewizardaddress;
}
public IpList getHarmonyAddress() {
return harmonyaddress;
}
Expand Down Expand Up @@ -236,6 +255,9 @@ public boolean isFibaroconfigured() {
public boolean isSomfyconfigured() {
return somfyconfigured;
}
public boolean isHomeWizardConfigured() {
return homewizardconfigured;
}
public void setVeraconfigured(boolean veraconfigured) {
this.veraconfigured = veraconfigured;
}
Expand All @@ -245,6 +267,9 @@ public void setFibaroconfigured(boolean fibaroconfigured) {
public void setSomfyconfigured(boolean somfyconfigured) {
this.somfyconfigured = somfyconfigured;
}
public void setHomeWizardConfigured(boolean homewizardconfigured) {
this.homewizardconfigured = homewizardconfigured;
}
public boolean isHarmonyconfigured() {
return harmonyconfigured;
}
Expand Down Expand Up @@ -492,4 +517,14 @@ public void updateHue(NamedIP aHue) {
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;
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/bwssystems/HABridge/DeviceMapTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -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"};
Expand All @@ -48,6 +49,7 @@ public 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);
Expand Down
7 changes: 6 additions & 1 deletion src/main/java/com/bwssystems/HABridge/HomeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
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;
Expand Down Expand Up @@ -68,6 +69,10 @@ public void buildHomes(BridgeSettings bridgeSettings, UDPDatagramSender aUdpData
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);
Expand Down Expand Up @@ -96,7 +101,7 @@ public void buildHomes(BridgeSettings bridgeSettings, UDPDatagramSender aUdpData
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);
Expand Down
Loading

0 comments on commit dc49de4

Please sign in to comment.