mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-19 16:41:53 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce97e928ad | ||
|
|
df67980bd6 | ||
|
|
b6b78c4849 | ||
|
|
b1d1f2ac46 | ||
|
|
750056df06 | ||
|
|
3f13e957ad | ||
|
|
afc254720c | ||
|
|
943e4420e6 | ||
|
|
c9e6cd079f | ||
|
|
faae6aa31f | ||
|
|
c25f08f142 | ||
|
|
d6ad9d288e | ||
|
|
3400c4d43a | ||
|
|
ddcbea001c | ||
|
|
9a35e47c27 | ||
|
|
199fcce549 | ||
|
|
bfeb382d1f | ||
|
|
dc28eb2984 | ||
|
|
b8acb4a52c | ||
|
|
21fdaf4545 | ||
|
|
db192df2c6 | ||
|
|
4a24d263c1 | ||
|
|
3394559539 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,3 +15,7 @@ data
|
|||||||
|
|
||||||
sftp-config\.json
|
sftp-config\.json
|
||||||
/bin/
|
/bin/
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/launch.test.json
|
||||||
|
.vscode/settings.json
|
||||||
|
.vscode/tasks.json
|
||||||
|
|||||||
112
README.md
112
README.md
@@ -29,7 +29,7 @@ A Custom implementation path looks like this:
|
|||||||
```
|
```
|
||||||
**SECURITY RISK: If you are unsure on how this software operates and what it exposes to your network, please make sure you understand that it can allow root access to your system. It is best practice to not open this to the Internet through your router as there are no security protocols in place to protect the system. The License agreement states specifically that you use this at your own risk.**
|
**SECURITY RISK: If you are unsure on how this software operates and what it exposes to your network, please make sure you understand that it can allow root access to your system. It is best practice to not open this to the Internet through your router as there are no security protocols in place to protect the system. The License agreement states specifically that you use this at your own risk.**
|
||||||
|
|
||||||
**ATTENTION: This requires a physical Amazon Echo, Dot or Tap and does not work with prototype devices built using the Alexa Voice Service e.g. Amazon's Alexa AVS Sample App and Sam Machin's AlexaPi. The AVS version does not have any capability for Hue Bridge discovery!**
|
**ATTENTION: This requires a physical Amazon Echo, Echo Plus, Spot, Tap or Show and does not work with prototype devices built using the Alexa Voice Service e.g. Amazon's Alexa AVS Sample App and Sam Machin's AlexaPi. The AVS version does not have any capability for Hue Bridge discovery!**
|
||||||
|
|
||||||
**NOTE: This software does require the user to have knowledge on how processes run on Linux or Windows with java. Also, an understanding of networking basics will help as well. This system receives upnp udp multicast packets from devices to be found, so that is something to understand. Please make sure you have all your devices use static IP addresses from your router. Most all questions have been answered already. PLEASE USE GOOGLE TO FIND YOUR ANSWERS!**
|
**NOTE: This software does require the user to have knowledge on how processes run on Linux or Windows with java. Also, an understanding of networking basics will help as well. This system receives upnp udp multicast packets from devices to be found, so that is something to understand. Please make sure you have all your devices use static IP addresses from your router. Most all questions have been answered already. PLEASE USE GOOGLE TO FIND YOUR ANSWERS!**
|
||||||
|
|
||||||
@@ -63,31 +63,31 @@ 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.
|
ATTENTION: Due to port 80 being the default, Linux restricts this to super user. Use the instructions below.
|
||||||
|
|
||||||
```
|
```
|
||||||
java -jar ha-bridge-5.2.1.jar
|
java -jar ha-bridge-5.2.2.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
ATTENTION: If running Java9, you will need to add the xml bind module
|
ATTENTION: If running Java9, you will need to add the xml bind module
|
||||||
```
|
```
|
||||||
java -jar --add-modules java.xml.bind ha-bridge-5.2.1.jar
|
java -jar --add-modules java.xml.bind ha-bridge-5.2.2.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.2.1.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.2.1/ha-bridge-5.2.1.jar
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### System Control Setup on a pi (preferred)
|
## Manual installation of ha-bridge and setup of systemd service
|
||||||
For next gen Linux systems (this includes the Raspberry Pi), here is a systemctl unit file that you can install. Here is a link on how to do this: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
|
Next gen Linux systems (this includes the Raspberry Pi), use systemd to run and manage services.
|
||||||
|
Here is a link on how to use systemd: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
|
||||||
|
|
||||||
Start here to create the habridge.service unit file:
|
Create the directory and make sure that ha-bridge-5.2.2.jar is in your /home/pi/ha-bridge directory.
|
||||||
|
|
||||||
|
```
|
||||||
|
pi@raspberrypi:~ $ mkdir ha-bridge
|
||||||
|
pi@raspberrypi:~ $ cd ha-bridge
|
||||||
|
|
||||||
|
pi@raspberrypi:~/ha-bridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.2.2/ha-bridge-5.2.2.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
Create the ha-bridge.service unit file:
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~ $ cd /etc/systemd/system
|
pi@raspberrypi:~ $ cd /etc/systemd/system
|
||||||
pi@raspberrypi:~ $ sudo nano habridge.service
|
pi@raspberrypi:~ $ sudo nano ha-bridge.service
|
||||||
```
|
```
|
||||||
Copy the text below into the editor nano.
|
Copy the text below into the editor nano.
|
||||||
```
|
```
|
||||||
@@ -98,58 +98,92 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
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.2.1.jar
|
WorkingDirectory=/home/pi/ha-bridge
|
||||||
|
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/ha-bridge/data/habridge.config /home/pi/ha-bridge/ha-bridge-5.2.2.jar
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
```
|
```
|
||||||
|
|
||||||
Save the file in the editor by hitting CTL-X and then saying Y to update and save.
|
Save the file in the editor by hitting CTL-X and then saying Y to update and save.
|
||||||
|
|
||||||
Reload the system control config:
|
Reload the system control config:
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~ $ sudo systemctl daemon-reload
|
pi@raspberrypi:~ $ sudo systemctl daemon-reload
|
||||||
```
|
```
|
||||||
|
|
||||||
To start the bridge:
|
To start the bridge:
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~ $ sudo systemctl start habridge.service
|
pi@raspberrypi:~ $ sudo systemctl start ha-bridge.service
|
||||||
```
|
```
|
||||||
|
|
||||||
To start the service at boot, use the `enable` command:
|
To start the service at boot, use the `enable` command:
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~ $ sudo systemctl enable habridge.service
|
pi@raspberrypi:~ $ sudo systemctl enable ha-bridge.service
|
||||||
```
|
```
|
||||||
|
|
||||||
To look at the log, the output goes into the system log at `/var/log/syslog':
|
To look at the log, the output goes into the system log at `/var/log/syslog':
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~ $ tail -f /var/log/syslog
|
pi@raspberrypi:~ $ tail -f /var/log/syslog
|
||||||
```
|
```
|
||||||
#### Basic script setup to run the bridge on a pi.
|
|
||||||
|
|
||||||
*NOTE ON RC.LOCAL*: Due to the way network subsystem is brought up on the pi, it uses the new systemctl to start services. The old style runlevel setup, which rc.local is part of does not get the benefit of knowing if the network has been fully realized. Starting ha-bridge from rc.local on next gen systems will cause unexpected results and issues with discovering registered devices.
|
### ha-bridge inside Docker container
|
||||||
|
Docker start offering official support for Raspbian operating system since autumn 2016.
|
||||||
|
Running services inside containers became to be a good alternative to normal installation method described before.
|
||||||
|
|
||||||
Edit the shell script for starting:
|
Install Docker Community Edition (CE) on Raspberry Pi
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~/habridge $ nano starthabridge.sh
|
pi@raspberrypi:~ $ curl -fsSL get.docker.com -o get-docker.sh
|
||||||
|
pi@raspberrypi:~ $ sudo sh get-docker.sh
|
||||||
```
|
```
|
||||||
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.2.1.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
|
|
||||||
|
|
||||||
chmod 777 /home/pi/habridge/habridge-log.txt
|
For every architecture there is a specialized ha-bridge Docker image available.
|
||||||
|
Please use the suitable image from the following list.
|
||||||
|
|
||||||
|
* Generic x86 / x86_64 system: [aptalca/home-automation-bridge](https://hub.docker.com/r/aptalca/home-automation-bridge)
|
||||||
|
* Raspberry Pi 1 (ARM): [habridge/ha-bridge-raspberry-pi](https://hub.docker.com/r/habridge/ha-bridge-raspberry-pi)
|
||||||
|
* Raspberry Pi 2 (ARM): [habridge/ha-bridge-raspberry-pi2](https://hub.docker.com/r/habridge/ha-bridge-raspberry-pi2)
|
||||||
|
* Raspberry Pi 3 (ARM): [habridge/ha-bridge-raspberrypi3](https://hub.docker.com/r/habridge/ha-bridge-raspberrypi3)
|
||||||
|
|
||||||
|
The following example explains how to run the latest version of ha-bridge Docker container on Raspberry Pi 3.
|
||||||
```
|
```
|
||||||
Exit and save the file with ctrl-X and follow the prompts and then execute on the command line:
|
pi@raspberrypi:~ $ docker pull habridge/ha-bridge-raspberrypi3
|
||||||
|
pi@raspberrypi:~ $ docker run \
|
||||||
|
--name ha-bridge \
|
||||||
|
--rm \
|
||||||
|
--init \
|
||||||
|
--detach \
|
||||||
|
--net=host \
|
||||||
|
--volume=$PWD:/ha-bridge/data \
|
||||||
|
--volume=/etc/localtime:/etc/localtime:ro \
|
||||||
|
--volume=/etc/timezone:/etc/timezone:ro \
|
||||||
|
habridge/ha-bridge-raspberrypi3
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~/habridge $ chmod u+x starthabridge.sh
|
|
||||||
|
To set additional arguments for ha-bridge just write them as arguments for docker run command.
|
||||||
```
|
```
|
||||||
Then execute the script:
|
pi@raspberrypi:~ $ docker run \
|
||||||
|
--name ha-bridge \
|
||||||
|
--rm \
|
||||||
|
--init \
|
||||||
|
--detach \
|
||||||
|
--net=host \
|
||||||
|
--volume=$PWD:/ha-bridge/data \
|
||||||
|
--volume=/etc/localtime:/etc/localtime:ro \
|
||||||
|
--volume=/etc/timezone:/etc/timezone:ro \
|
||||||
|
habridge/ha-bridge-raspberry-pi3 \
|
||||||
|
-Dserver.port=8080 \
|
||||||
|
-Dsecurity.key=secret
|
||||||
```
|
```
|
||||||
pi@raspberrypi:~/habridge $ ./starthabridge.sh
|
|
||||||
|
To halt the ha-bridge Docker container use the `stop` command:
|
||||||
```
|
```
|
||||||
You should now be running the bridge. Check for errors:
|
pi@raspberrypi:~ $ docker stop ha-bridge
|
||||||
```
|
|
||||||
pi@raspberrypi:~/habridge $ tail -f habridge-log.txt
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you like to automate the deployment just use the Ansible role on https://github.com/escalate/ansible-ha-bridge-docker.
|
||||||
|
|
||||||
## Run ha-bridge alongside web server already on port 80
|
## Run ha-bridge alongside web server already on port 80
|
||||||
These examples will help you proxy your current webserver requests to the ha-bridge running on a different port, such as 8080.
|
These examples will help you proxy your current webserver requests to the ha-bridge running on a different port, such as 8080.
|
||||||
|
|
||||||
@@ -287,7 +321,7 @@ Provide IP Addresses of your HAL Systems that you want to utilize with the bridg
|
|||||||
#### MQTT Client IDs and IP Addresses
|
#### MQTT Client IDs and IP Addresses
|
||||||
Provide Client ID and IP Addresses and ports of your MQTT Brokers that you want to utilize with the bridge. Also, you can provide the username and password if you have secured your MQTT broker which is optional. When these Client ID and IP's are given, the bridge will be able to publish MQTT messages by the call it receives and send it to the target MQTT Broker you configure. The MQTT Messages Tab will become available to help you build messages.
|
Provide Client ID and IP Addresses and ports of your MQTT Brokers that you want to utilize with the bridge. Also, you can provide the username and password if you have secured your MQTT broker which is optional. When these Client ID and IP's are given, the bridge will be able to publish MQTT messages by the call it receives and send it to the target MQTT Broker you configure. The MQTT Messages Tab will become available to help you build messages.
|
||||||
#### Home Assistant Names and IP Addresses
|
#### Home Assistant Names and IP Addresses
|
||||||
Provide IP Addresses and ports of your Home Assistant that you want to utilize with the bridge. Also, give a meaningful name to each one so it is easy to decipher in the helper tab. When these names and IP's are given, the bridge will be able to control the devices or scenes by the call it receives and send it to the target Home Assistant and device/scene you configure.
|
<Provide IP Addresses and ports of your Home Assistant that you want to utilize with the bridge. Also, give a meaningful name to each one so it is easy to decipher in the helper tab. When these names and IP's are given, the bridge will be able to control the devices or scenes by the call it receives and send it to the target Home Assistant and device/scene you configure.
|
||||||
#### HomeWizard Gateways Names and IP Addresses
|
#### HomeWizard Gateways Names and IP Addresses
|
||||||
Provide IP Addresses of your HomeWizard Systems that you want to utilize with the bridge. Also, give a meaningful name to each one so it is easy to decipher in the helper tab. When these names and IP's are given, the bridge will be able to control the devices or scenes by the call it receives and send it to the target HomeWizard and device/scene you configure.
|
Provide IP Addresses of your HomeWizard Systems that you want to utilize with the bridge. Also, give a meaningful name to each one so it is easy to decipher in the helper tab. When these names and IP's are given, the bridge will be able to control the devices or scenes by the call it receives and send it to the target HomeWizard and device/scene you configure.
|
||||||
#### Domoticz Names and IP Addresses
|
#### Domoticz Names and IP Addresses
|
||||||
|
|||||||
15
pom.xml
15
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>5.2.1</version>
|
<version>5.2.2RC3</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>HA Bridge</name>
|
<name>HA Bridge</name>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sparkjava</groupId>
|
<groupId>com.sparkjava</groupId>
|
||||||
<artifactId>spark-core</artifactId>
|
<artifactId>spark-core</artifactId>
|
||||||
<version>2.7.1</version>
|
<version>2.7.2</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
<artifactId>slf4j-simple</artifactId>
|
<artifactId>slf4j-simple</artifactId>
|
||||||
@@ -114,12 +114,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.paho</groupId>
|
<groupId>org.eclipse.paho</groupId>
|
||||||
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.12</version>
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.bwssytems</groupId>
|
<groupId>com.github.bwssytems</groupId>
|
||||||
@@ -156,6 +157,14 @@
|
|||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.1</version>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import com.bwssystems.HABridge.util.BackupHandler;
|
import com.bwssystems.HABridge.util.BackupHandler;
|
||||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||||
|
import com.bwssystems.HABridge.util.ParseRoute;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
public class BridgeSettings extends BackupHandler {
|
public class BridgeSettings extends BackupHandler {
|
||||||
@@ -166,8 +167,9 @@ public class BridgeSettings extends BackupHandler {
|
|||||||
theBridgeSettings.setNestpwd(System.getProperty("nest.pwd"));
|
theBridgeSettings.setNestpwd(System.getProperty("nest.pwd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParseRoute aDefaultRoute = ParseRoute.getInstance();
|
||||||
if(theBridgeSettings.getUpnpConfigAddress() == null || theBridgeSettings.getUpnpConfigAddress().trim().equals("") || theBridgeSettings.getUpnpConfigAddress().trim().equals("0.0.0.0")) {
|
if(theBridgeSettings.getUpnpConfigAddress() == null || theBridgeSettings.getUpnpConfigAddress().trim().equals("") || theBridgeSettings.getUpnpConfigAddress().trim().equals("0.0.0.0")) {
|
||||||
addressString = checkIpAddress(null, true);
|
addressString = aDefaultRoute.getLocalIPAddress();
|
||||||
if(addressString != null) {
|
if(addressString != null) {
|
||||||
theBridgeSettings.setUpnpConfigAddress(addressString);
|
theBridgeSettings.setUpnpConfigAddress(addressString);
|
||||||
log.info("Adding " + addressString + " as our default upnp config address.");
|
log.info("Adding " + addressString + " as our default upnp config address.");
|
||||||
@@ -177,8 +179,10 @@ public class BridgeSettings extends BackupHandler {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
addressString = checkIpAddress(theBridgeSettings.getUpnpConfigAddress(), false);
|
addressString = checkIpAddress(theBridgeSettings.getUpnpConfigAddress(), false);
|
||||||
if(addressString == null)
|
if(addressString == null) {
|
||||||
log.warn("The upnp config address, " + theBridgeSettings.getUpnpConfigAddress() + ", does not match any known IP's on this host.");
|
addressString = aDefaultRoute.getLocalIPAddress();
|
||||||
|
log.warn("The upnp config address, " + theBridgeSettings.getUpnpConfigAddress() + ", does not match any known IP's on this host. Using default address: " + addressString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(theBridgeSettings.getUpnpResponsePort() == null)
|
if(theBridgeSettings.getUpnpResponsePort() == null)
|
||||||
@@ -215,8 +219,10 @@ public class BridgeSettings extends BackupHandler {
|
|||||||
// Lifx is either configured or not, so it does not need an update.
|
// Lifx is either configured or not, so it does not need an update.
|
||||||
if(serverPortOverride != null)
|
if(serverPortOverride != null)
|
||||||
theBridgeSettings.setServerPort(serverPortOverride);
|
theBridgeSettings.setServerPort(serverPortOverride);
|
||||||
if(serverIpOverride != null)
|
if(serverIpOverride != null) {
|
||||||
theBridgeSettings.setWebaddress(serverIpOverride);
|
theBridgeSettings.setWebaddress(serverIpOverride);
|
||||||
|
theBridgeSettings.setUpnpConfigAddress(serverIpOverride);
|
||||||
|
}
|
||||||
if(upnpStrictOverride != null)
|
if(upnpStrictOverride != null)
|
||||||
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride));
|
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride));
|
||||||
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
|
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ public class DeviceDescriptor{
|
|||||||
@SerializedName("onFirstDim")
|
@SerializedName("onFirstDim")
|
||||||
@Expose
|
@Expose
|
||||||
private boolean onFirstDim;
|
private boolean onFirstDim;
|
||||||
|
@SerializedName("onWhenDimPresent")
|
||||||
|
@Expose
|
||||||
|
private boolean onWhenDimPresent;
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
@@ -286,6 +289,14 @@ public class DeviceDescriptor{
|
|||||||
this.onFirstDim = onFirstDim;
|
this.onFirstDim = onFirstDim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOnWhenDimPresent() {
|
||||||
|
return onWhenDimPresent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnWhenDimPresent(boolean onWhenDimPresent) {
|
||||||
|
this.onWhenDimPresent = onWhenDimPresent;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean containsType(String aType) {
|
public boolean containsType(String aType) {
|
||||||
if(aType == null)
|
if(aType == null)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -52,11 +52,22 @@ public class BrightnessDecode {
|
|||||||
boolean notDone = true;
|
boolean notDone = true;
|
||||||
String replaceValue = null;
|
String replaceValue = null;
|
||||||
String replaceTarget = null;
|
String replaceTarget = null;
|
||||||
int percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
int percentBrightness = 0;
|
||||||
float decimalBrightness = (float) (intensity / 255.0);
|
float decimalBrightness = (float) 0.0;
|
||||||
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||||
String mathDescriptor = null;
|
String mathDescriptor = null;
|
||||||
|
|
||||||
|
if(intensity > 0) {
|
||||||
|
decimalBrightness = (float) (intensity / 255.0);
|
||||||
|
if(intensity > 0 && intensity < 5)
|
||||||
|
percentBrightness = 1;
|
||||||
|
else
|
||||||
|
percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
||||||
|
} else {
|
||||||
|
decimalBrightness = (float) 0.0;
|
||||||
|
percentBrightness = 0;
|
||||||
|
}
|
||||||
|
|
||||||
while(notDone) {
|
while(notDone) {
|
||||||
notDone = false;
|
notDone = false;
|
||||||
if (request.contains(INTENSITY_BYTE)) {
|
if (request.contains(INTENSITY_BYTE)) {
|
||||||
|
|||||||
@@ -570,8 +570,8 @@ public class HueMulator {
|
|||||||
if (body.contains("\"effect\"")) {
|
if (body.contains("\"effect\"")) {
|
||||||
if (notFirstChange)
|
if (notFirstChange)
|
||||||
responseString = responseString + ",";
|
responseString = responseString + ",";
|
||||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/effect\":"
|
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/effect\":\""
|
||||||
+ stateChanges.getEffect() + "}}";
|
+ stateChanges.getEffect() + "\"}}";
|
||||||
if (deviceState != null)
|
if (deviceState != null)
|
||||||
deviceState.setEffect(stateChanges.getEffect());
|
deviceState.setEffect(stateChanges.getEffect());
|
||||||
notFirstChange = true;
|
notFirstChange = true;
|
||||||
@@ -590,8 +590,8 @@ public class HueMulator {
|
|||||||
if (body.contains("\"alert\"")) {
|
if (body.contains("\"alert\"")) {
|
||||||
if (notFirstChange)
|
if (notFirstChange)
|
||||||
responseString = responseString + ",";
|
responseString = responseString + ",";
|
||||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/alert\":"
|
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/alert\":\""
|
||||||
+ stateChanges.getAlert() + "}}";
|
+ stateChanges.getAlert() + "\"}}";
|
||||||
if (deviceState != null)
|
if (deviceState != null)
|
||||||
deviceState.setAlert(stateChanges.getAlert());
|
deviceState.setAlert(stateChanges.getAlert());
|
||||||
notFirstChange = true;
|
notFirstChange = true;
|
||||||
@@ -1186,13 +1186,22 @@ public class HueMulator {
|
|||||||
isOnRequest = true;
|
isOnRequest = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!device.isOnFirstDim() && device.isOnWhenDimPresent() && isDimRequest) {
|
||||||
|
isOnRequest = true;
|
||||||
|
theStateChanges.setOn(true);
|
||||||
|
} else if(!device.isOnFirstDim() && !device.isOnWhenDimPresent() && isDimRequest) {
|
||||||
|
isOnRequest = false;
|
||||||
|
}
|
||||||
|
|
||||||
if(device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) {
|
if(device.isOnFirstDim() && isDimRequest && !device.getDeviceState().isOn()) {
|
||||||
isOnRequest = true;
|
isOnRequest = true;
|
||||||
|
theStateChanges.setOn(true);
|
||||||
isDimRequest = false;
|
isDimRequest = false;
|
||||||
isColorRequest = false;
|
isColorRequest = false;
|
||||||
} else if(device.isOnFirstDim() && isDimRequest && device.getDeviceState().isOn()) {
|
} else if(device.isOnFirstDim() && isDimRequest && device.getDeviceState().isOn()) {
|
||||||
if(device.getDeviceState().getBri() == theStateChanges.getBri()) {
|
if(device.getDeviceState().getBri() == theStateChanges.getBri()) {
|
||||||
isOnRequest = true;
|
isOnRequest = true;
|
||||||
|
theStateChanges.setOn(true);
|
||||||
isDimRequest = false;
|
isDimRequest = false;
|
||||||
isColorRequest = false;
|
isColorRequest = false;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.whistlingfish.harmony.HarmonyClient;
|
|||||||
import net.whistlingfish.harmony.config.Activity;
|
import net.whistlingfish.harmony.config.Activity;
|
||||||
import net.whistlingfish.harmony.config.Device;
|
import net.whistlingfish.harmony.config.Device;
|
||||||
import net.whistlingfish.harmony.config.HarmonyConfig;
|
import net.whistlingfish.harmony.config.HarmonyConfig;
|
||||||
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
|
|
||||||
public class HarmonyHandler {
|
public class HarmonyHandler {
|
||||||
private static final Logger log = LoggerFactory.getLogger(HarmonyHandler.class);
|
private static final Logger log = LoggerFactory.getLogger(HarmonyHandler.class);
|
||||||
@@ -16,8 +17,9 @@ public class HarmonyHandler {
|
|||||||
private Boolean noopCalls;
|
private Boolean noopCalls;
|
||||||
private Boolean devMode;
|
private Boolean devMode;
|
||||||
private DevModeResponse devResponse;
|
private DevModeResponse devResponse;
|
||||||
|
private NamedIP myNameAndIP;
|
||||||
|
|
||||||
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting) {
|
public HarmonyHandler(HarmonyClient theClient, Boolean noopCallsSetting, DevModeResponse devResponseSetting, NamedIP aNameAndIP) {
|
||||||
super();
|
super();
|
||||||
noopCalls = noopCallsSetting;
|
noopCalls = noopCallsSetting;
|
||||||
devMode = Boolean.TRUE;
|
devMode = Boolean.TRUE;
|
||||||
@@ -27,6 +29,7 @@ public class HarmonyHandler {
|
|||||||
else
|
else
|
||||||
devResponse = devResponseSetting;
|
devResponse = devResponseSetting;
|
||||||
harmonyClient = theClient;
|
harmonyClient = theClient;
|
||||||
|
myNameAndIP = aNameAndIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Activity> getActivities() {
|
public List<Activity> getActivities() {
|
||||||
@@ -34,7 +37,16 @@ public class HarmonyHandler {
|
|||||||
if(devMode)
|
if(devMode)
|
||||||
return devResponse.getActivities();
|
return devResponse.getActivities();
|
||||||
|
|
||||||
return harmonyClient.getConfig().getActivities();
|
List<Activity> listOfActivities = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
listOfActivities = harmonyClient.getConfig().getActivities();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
handleExceptionError(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return listOfActivities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Device> getDevices() {
|
public List<Device> getDevices() {
|
||||||
@@ -42,7 +54,15 @@ public class HarmonyHandler {
|
|||||||
if(devMode)
|
if(devMode)
|
||||||
return devResponse.getDevices();
|
return devResponse.getDevices();
|
||||||
|
|
||||||
return harmonyClient.getConfig().getDevices();
|
List<Device> listOfDevices = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
listOfDevices = harmonyClient.getConfig().getDevices();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
handleExceptionError(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return listOfDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HarmonyConfig getConfig() {
|
public HarmonyConfig getConfig() {
|
||||||
@@ -50,7 +70,14 @@ public class HarmonyHandler {
|
|||||||
if(devMode)
|
if(devMode)
|
||||||
return devResponse.getConfig();
|
return devResponse.getConfig();
|
||||||
|
|
||||||
return harmonyClient.getConfig();
|
HarmonyConfig aConfig = null;
|
||||||
|
try {
|
||||||
|
aConfig = harmonyClient.getConfig();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
handleExceptionError(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return aConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Activity getCurrentActivity() {
|
public Activity getCurrentActivity() {
|
||||||
@@ -58,7 +85,14 @@ public class HarmonyHandler {
|
|||||||
if(devMode)
|
if(devMode)
|
||||||
return devResponse.getCurrentActivity();
|
return devResponse.getCurrentActivity();
|
||||||
|
|
||||||
return harmonyClient.getCurrentActivity();
|
Activity anActivity = null;
|
||||||
|
try {
|
||||||
|
anActivity = harmonyClient.getCurrentActivity();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
handleExceptionError(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return anActivity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean startActivity(RunActivity anActivity) {
|
public Boolean startActivity(RunActivity anActivity) {
|
||||||
@@ -82,12 +116,14 @@ public class HarmonyHandler {
|
|||||||
harmonyClient.startActivityByName(anActivity.getName());
|
harmonyClient.startActivityByName(anActivity.getName());
|
||||||
} catch (IllegalArgumentException ei) {
|
} catch (IllegalArgumentException ei) {
|
||||||
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||||
return false;
|
} catch (RuntimeException e1) {
|
||||||
|
return handleExceptionError(e1);
|
||||||
}
|
}
|
||||||
|
} catch (RuntimeException e1) {
|
||||||
|
return handleExceptionError(e1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
log.error("Error in finding activity: " + anActivity.getName() + " for a hub: " + anActivity.getHub());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -113,11 +149,22 @@ public class HarmonyHandler {
|
|||||||
harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton());
|
harmonyClient.pressButton(aDeviceButton.getDevice(), aDeviceButton.getButton());
|
||||||
} catch (IllegalArgumentException ei) {
|
} catch (IllegalArgumentException ei) {
|
||||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
||||||
return false;
|
} catch (RuntimeException e1) {
|
||||||
|
return handleExceptionError(e1);
|
||||||
}
|
}
|
||||||
|
} catch (RuntimeException e1) {
|
||||||
|
return handleExceptionError(e1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
log.error("Error in finding device: " + aDeviceButton.getDevice() +" and a button: " + aDeviceButton.getButton() + " for a hub: " + aDeviceButton.getHub());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean handleExceptionError(Exception e) {
|
||||||
|
if(e.getMessage().equalsIgnoreCase("Failed communicating with Harmony Hub")) {
|
||||||
|
log.warn("Issue in communcicating with Harmony Hub, retrying connect....");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,9 +175,19 @@ public class HarmonyHandler {
|
|||||||
log.debug("Harmony api shutdown requested.");
|
log.debug("Harmony api shutdown requested.");
|
||||||
if(devMode)
|
if(devMode)
|
||||||
return;
|
return;
|
||||||
|
try {
|
||||||
harmonyClient.disconnect();
|
harmonyClient.disconnect();
|
||||||
|
} catch(Exception e)
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
harmonyClient = null;
|
harmonyClient = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the myNameAndIP
|
||||||
|
*/
|
||||||
|
public NamedIP getMyNameAndIP() {
|
||||||
|
return myNameAndIP;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,11 +74,9 @@ public class HarmonyHome implements Home {
|
|||||||
Set<String> keys = hubs.keySet();
|
Set<String> keys = hubs.keySet();
|
||||||
if (!keys.isEmpty()) {
|
if (!keys.isEmpty()) {
|
||||||
aHandler = hubs.get(keys.toArray()[0]).getMyHarmony();
|
aHandler = hubs.get(keys.toArray()[0]).getMyHarmony();
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
aHandler = null;
|
aHandler = null;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
aHandler = hubs.get(aName).getMyHarmony();
|
aHandler = hubs.get(aName).getMyHarmony();
|
||||||
return aHandler;
|
return aHandler;
|
||||||
}
|
}
|
||||||
@@ -91,6 +89,14 @@ public class HarmonyHome implements Home {
|
|||||||
while (keys.hasNext()) {
|
while (keys.hasNext()) {
|
||||||
String key = keys.next();
|
String key = keys.next();
|
||||||
Iterator<Activity> activities = hubs.get(key).getMyHarmony().getActivities().iterator();
|
Iterator<Activity> activities = hubs.get(key).getMyHarmony().getActivities().iterator();
|
||||||
|
if (activities == null) {
|
||||||
|
resetHub(hubs.get(key).getMyHarmony());
|
||||||
|
activities = hubs.get(key).getMyHarmony().getActivities().iterator();
|
||||||
|
if (activities == null) {
|
||||||
|
log.error("Could not get communication restored with hub: " + key + ", please restart...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (activities != null) {
|
||||||
while (activities.hasNext()) {
|
while (activities.hasNext()) {
|
||||||
HarmonyActivity anActivity = new HarmonyActivity();
|
HarmonyActivity anActivity = new HarmonyActivity();
|
||||||
anActivity.setActivity(activities.next());
|
anActivity.setActivity(activities.next());
|
||||||
@@ -98,8 +104,10 @@ public class HarmonyHome implements Home {
|
|||||||
activityList.add(anActivity);
|
activityList.add(anActivity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return activityList;
|
return activityList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<HarmonyActivity> getCurrentActivities() {
|
public List<HarmonyActivity> getCurrentActivities() {
|
||||||
Iterator<String> keys = hubs.keySet().iterator();
|
Iterator<String> keys = hubs.keySet().iterator();
|
||||||
ArrayList<HarmonyActivity> activityList = new ArrayList<HarmonyActivity>();
|
ArrayList<HarmonyActivity> activityList = new ArrayList<HarmonyActivity>();
|
||||||
@@ -108,13 +116,23 @@ public class HarmonyHome implements Home {
|
|||||||
while (keys.hasNext()) {
|
while (keys.hasNext()) {
|
||||||
String key = keys.next();
|
String key = keys.next();
|
||||||
Activity theActivity = hubs.get(key).getMyHarmony().getCurrentActivity();
|
Activity theActivity = hubs.get(key).getMyHarmony().getCurrentActivity();
|
||||||
|
if (theActivity == null) {
|
||||||
|
resetHub(hubs.get(key).getMyHarmony());
|
||||||
|
theActivity = hubs.get(key).getMyHarmony().getCurrentActivity();
|
||||||
|
if (theActivity == null) {
|
||||||
|
log.error("Could not get communication restored with hub: " + key + ", please restart...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (theActivity != null) {
|
||||||
HarmonyActivity anActivity = new HarmonyActivity();
|
HarmonyActivity anActivity = new HarmonyActivity();
|
||||||
anActivity.setActivity(theActivity);
|
anActivity.setActivity(theActivity);
|
||||||
anActivity.setHub(key);
|
anActivity.setHub(key);
|
||||||
activityList.add(anActivity);
|
activityList.add(anActivity);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return activityList;
|
return activityList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<HarmonyDevice> getDevices() {
|
public List<HarmonyDevice> getDevices() {
|
||||||
Iterator<String> keys = hubs.keySet().iterator();
|
Iterator<String> keys = hubs.keySet().iterator();
|
||||||
ArrayList<HarmonyDevice> deviceList = new ArrayList<HarmonyDevice>();
|
ArrayList<HarmonyDevice> deviceList = new ArrayList<HarmonyDevice>();
|
||||||
@@ -123,6 +141,14 @@ public class HarmonyHome implements Home {
|
|||||||
while (keys.hasNext()) {
|
while (keys.hasNext()) {
|
||||||
String key = keys.next();
|
String key = keys.next();
|
||||||
Iterator<Device> devices = hubs.get(key).getMyHarmony().getDevices().iterator();
|
Iterator<Device> devices = hubs.get(key).getMyHarmony().getDevices().iterator();
|
||||||
|
if (devices == null) {
|
||||||
|
resetHub(hubs.get(key).getMyHarmony());
|
||||||
|
devices = hubs.get(key).getMyHarmony().getDevices().iterator();
|
||||||
|
if (devices == null) {
|
||||||
|
log.error("Could not get communication restored with hub: " + key + ", please restart...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (devices != null) {
|
||||||
while (devices.hasNext()) {
|
while (devices.hasNext()) {
|
||||||
HarmonyDevice aDevice = new HarmonyDevice();
|
HarmonyDevice aDevice = new HarmonyDevice();
|
||||||
aDevice.setDevice(devices.next());
|
aDevice.setDevice(devices.next());
|
||||||
@@ -130,6 +156,7 @@ public class HarmonyHome implements Home {
|
|||||||
deviceList.add(aDevice);
|
deviceList.add(aDevice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return deviceList;
|
return deviceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,8 +171,7 @@ public class HarmonyHome implements Home {
|
|||||||
+ "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/"
|
+ "\",\"description\": \"Should not get here, no harmony configured\", \"parameter\": \"/lights/"
|
||||||
+ lightId + "state\"}}]";
|
+ lightId + "state\"}}]";
|
||||||
} else {
|
} else {
|
||||||
if(anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex]))
|
if (anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_ACTIVITY[DeviceMapTypes.typeIndex])) {
|
||||||
{
|
|
||||||
RunActivity anActivity = null;
|
RunActivity anActivity = null;
|
||||||
if (anItem.getItem().isJsonObject())
|
if (anItem.getItem().isJsonObject())
|
||||||
anActivity = aGsonHandler.fromJson(anItem.getItem(), RunActivity.class);
|
anActivity = aGsonHandler.fromJson(anItem.getItem(), RunActivity.class);
|
||||||
@@ -160,9 +186,21 @@ public class HarmonyHome implements Home {
|
|||||||
+ "\",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/"
|
+ "\",\"description\": \"Should not get here, no harmony hub available\", \"parameter\": \"/lights/"
|
||||||
+ lightId + "state\"}}]";
|
+ lightId + "state\"}}]";
|
||||||
} else {
|
} else {
|
||||||
myHarmony.startActivity(anActivity);
|
if (!myHarmony.startActivity(anActivity)) {
|
||||||
|
if (resetHub(myHarmony)) {
|
||||||
|
myHarmony = getHarmonyHandler(anActivity.getHub());
|
||||||
|
if (!myHarmony.startActivity(anActivity)) {
|
||||||
|
log.error("Could not get communication restored with hub: " + anActivity.getHub()
|
||||||
|
+ ", please restart...");
|
||||||
|
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||||
|
+ "\",\"description\": \"Could not communicate with harmony\", \"parameter\": \"/lights/"
|
||||||
|
+ lightId + "state\"}}]";
|
||||||
}
|
}
|
||||||
} else if(anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (anItem.getType().trim()
|
||||||
|
.equalsIgnoreCase(DeviceMapTypes.HARMONY_BUTTON[DeviceMapTypes.typeIndex])) {
|
||||||
String url = null;
|
String url = null;
|
||||||
if (anItem.getItem().isJsonObject() || anItem.getItem().isJsonArray()) {
|
if (anItem.getItem().isJsonObject() || anItem.getItem().isJsonArray()) {
|
||||||
url = aGsonHandler.toJson(anItem.getItem());
|
url = aGsonHandler.toJson(anItem.getItem());
|
||||||
@@ -191,14 +229,29 @@ public class HarmonyHome implements Home {
|
|||||||
aMultiUtil.setTheDelay(anItem.getDelay());
|
aMultiUtil.setTheDelay(anItem.getDelay());
|
||||||
else
|
else
|
||||||
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
||||||
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - " + deviceButtons[z].getButton() + " with pressTime of: " + deviceButtons[z].getPressTime() + " - iteration: " + String.valueOf(z) + " - count: " + String.valueOf(y));
|
log.debug("pressing button: " + deviceButtons[z].getDevice() + " - "
|
||||||
|
+ deviceButtons[z].getButton() + " with pressTime of: "
|
||||||
|
+ deviceButtons[z].getPressTime() + " - iteration: " + String.valueOf(z) + " - count: "
|
||||||
|
+ String.valueOf(y));
|
||||||
if (deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty())
|
if (deviceButtons[z].getHub() == null || deviceButtons[z].getHub().isEmpty())
|
||||||
deviceButtons[z].setHub(device.getTargetDevice());
|
deviceButtons[z].setHub(device.getTargetDevice());
|
||||||
HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub());
|
HarmonyHandler myHarmony = getHarmonyHandler(deviceButtons[z].getHub());
|
||||||
if (myHarmony == null)
|
if (myHarmony == null)
|
||||||
log.warn("Button Press - Should not get here, no harmony hub available");
|
log.warn("Button Press - Should not get here, no harmony hub available");
|
||||||
else
|
else{
|
||||||
myHarmony.pressButton(deviceButtons[z]);
|
if (myHarmony.pressButton(deviceButtons[z])) {
|
||||||
|
if (resetHub(myHarmony)) {
|
||||||
|
myHarmony = getHarmonyHandler(deviceButtons[z].getHub());
|
||||||
|
if (!myHarmony.pressButton(deviceButtons[z])) {
|
||||||
|
log.error("Could not get communication restored with hub: " + deviceButtons[z].getHub()
|
||||||
|
+ ", please restart...");
|
||||||
|
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||||
|
+ "\",\"description\": \"Could not communicate with harmony\", \"parameter\": \"/lights/"
|
||||||
|
+ lightId + "state\"}}]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,12 +263,11 @@ public class HarmonyHome implements Home {
|
|||||||
public Home createHome(BridgeSettings bridgeSettings) {
|
public Home createHome(BridgeSettings bridgeSettings) {
|
||||||
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
||||||
validHarmony = bridgeSettings.getBridgeSettingsDescriptor().isValidHarmony();
|
validHarmony = bridgeSettings.getBridgeSettingsDescriptor().isValidHarmony();
|
||||||
log.info("Harmony Home created." + (validHarmony ? "" : " No Harmony devices configured.") + (isDevMode ? " DevMode is set." : ""));
|
log.info("Harmony Home created." + (validHarmony ? "" : " No Harmony devices configured.")
|
||||||
|
+ (isDevMode ? " DevMode is set." : ""));
|
||||||
if (validHarmony || isDevMode) {
|
if (validHarmony || isDevMode) {
|
||||||
hubs = new HashMap<String, HarmonyServer>();
|
hubs = new HashMap<String, HarmonyServer>();
|
||||||
aGsonHandler =
|
aGsonHandler = new GsonBuilder().create();
|
||||||
new GsonBuilder()
|
|
||||||
.create();
|
|
||||||
if (isDevMode) {
|
if (isDevMode) {
|
||||||
NamedIP devModeIp = new NamedIP();
|
NamedIP devModeIp = new NamedIP();
|
||||||
devModeIp.setIp("10.10.10.10");
|
devModeIp.setIp("10.10.10.10");
|
||||||
@@ -226,18 +278,20 @@ public class HarmonyHome implements Home {
|
|||||||
thedevList.setDevices(theList);
|
thedevList.setDevices(theList);
|
||||||
bridgeSettings.getBridgeSettingsDescriptor().setHarmonyAddress(thedevList);
|
bridgeSettings.getBridgeSettingsDescriptor().setHarmonyAddress(thedevList);
|
||||||
}
|
}
|
||||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getHarmonyAddress().getDevices().iterator();
|
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getHarmonyAddress().getDevices()
|
||||||
|
.iterator();
|
||||||
while (theList.hasNext() && validHarmony) {
|
while (theList.hasNext() && validHarmony) {
|
||||||
NamedIP aHub = theList.next();
|
NamedIP aHub = theList.next();
|
||||||
boolean loopControl = true;
|
boolean loopControl = true;
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
while (loopControl) {
|
while (loopControl) {
|
||||||
try {
|
try {
|
||||||
hubs.put(aHub.getName(), HarmonyServer.setup(bridgeSettings.getBridgeSettingsDescriptor(), isDevMode, aHub));
|
hubs.put(aHub.getName(), HarmonyServer.setup(isDevMode, aHub));
|
||||||
loopControl = false;
|
loopControl = false;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (retryCount > 3) {
|
if (retryCount > 3) {
|
||||||
log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: " + e.getMessage(), e);
|
log.error("Cannot get harmony client (" + aHub.getName() + ") setup, Exiting with message: "
|
||||||
|
+ e.getMessage(), e);
|
||||||
loopControl = false;
|
loopControl = false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@@ -257,6 +311,25 @@ public class HarmonyHome implements Home {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean resetHub(HarmonyHandler aHarmony) {
|
||||||
|
boolean resetSuccess = false;
|
||||||
|
isDevMode = Boolean.parseBoolean(System.getProperty("dev.mode", "false"));
|
||||||
|
NamedIP resetIp = aHarmony.getMyNameAndIP();
|
||||||
|
log.info("Resetting harmony hub due to communication errror: " + resetIp.getName());
|
||||||
|
if (!isDevMode) {
|
||||||
|
try {
|
||||||
|
hubs.remove(resetIp.getName());
|
||||||
|
aHarmony.shutdown();
|
||||||
|
hubs.put(resetIp.getName(), HarmonyServer.setup(isDevMode, resetIp));
|
||||||
|
resetSuccess = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Cannot reset harmony client (" + resetIp.getName() + "), Exiting with message: "
|
||||||
|
+ e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resetSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getItems(String type) {
|
public Object getItems(String type) {
|
||||||
if (validHarmony) {
|
if (validHarmony) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.apache.http.client.methods.HttpGet;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
|
||||||
import com.bwssystems.HABridge.NamedIP;
|
import com.bwssystems.HABridge.NamedIP;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
@@ -50,11 +49,10 @@ public class HarmonyServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static HarmonyServer setup(
|
public static HarmonyServer setup(
|
||||||
BridgeSettingsDescriptor bridgeSettings,
|
|
||||||
Boolean harmonyDevMode,
|
Boolean harmonyDevMode,
|
||||||
NamedIP theHarmonyAddress
|
NamedIP theHarmonyAddress
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
if (!bridgeSettings.isValidHarmony() && harmonyDevMode) {
|
if (harmonyDevMode) {
|
||||||
return new HarmonyServer(theHarmonyAddress);
|
return new HarmonyServer(theHarmonyAddress);
|
||||||
}
|
}
|
||||||
Injector injector = null;
|
Injector injector = null;
|
||||||
@@ -65,11 +63,11 @@ public class HarmonyServer {
|
|||||||
if (!harmonyDevMode) {
|
if (!harmonyDevMode) {
|
||||||
injector.injectMembers(mainObject);
|
injector.injectMembers(mainObject);
|
||||||
}
|
}
|
||||||
mainObject.execute(bridgeSettings, harmonyDevMode);
|
mainObject.execute(harmonyDevMode);
|
||||||
return mainObject;
|
return mainObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void execute(BridgeSettingsDescriptor mySettings, Boolean harmonyDevMode) throws Exception {
|
private void execute(Boolean harmonyDevMode) throws Exception {
|
||||||
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
||||||
isDevMode = harmonyDevMode;
|
isDevMode = harmonyDevMode;
|
||||||
String modeString = "";
|
String modeString = "";
|
||||||
@@ -110,7 +108,7 @@ public class HarmonyServer {
|
|||||||
});
|
});
|
||||||
harmonyClient.connect(myNameAndIP.getIp());
|
harmonyClient.connect(myNameAndIP.getIp());
|
||||||
}
|
}
|
||||||
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
|
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse, myNameAndIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HarmonyHandler getMyHarmony() {
|
public HarmonyHandler getMyHarmony() {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class UpnpListener {
|
|||||||
private Logger log = LoggerFactory.getLogger(UpnpListener.class);
|
private Logger log = LoggerFactory.getLogger(UpnpListener.class);
|
||||||
private MulticastSocket upnpMulticastSocket;
|
private MulticastSocket upnpMulticastSocket;
|
||||||
private int httpServerPort;
|
private int httpServerPort;
|
||||||
private String responseAddress;
|
private String upnpConfigIP;
|
||||||
private boolean strict;
|
private boolean strict;
|
||||||
private boolean traceupnp;
|
private boolean traceupnp;
|
||||||
private boolean useUpnpIface;
|
private boolean useUpnpIface;
|
||||||
@@ -73,16 +73,19 @@ public class UpnpListener {
|
|||||||
super();
|
super();
|
||||||
upnpMulticastSocket = null;
|
upnpMulticastSocket = null;
|
||||||
httpServerPort = Integer.valueOf(theSettings.getServerPort());
|
httpServerPort = Integer.valueOf(theSettings.getServerPort());
|
||||||
responseAddress = theSettings.getUpnpConfigAddress();
|
upnpConfigIP = theSettings.getUpnpConfigAddress();
|
||||||
strict = theSettings.isUpnpStrict();
|
strict = theSettings.isUpnpStrict();
|
||||||
traceupnp = theSettings.isTraceupnp();
|
traceupnp = theSettings.isTraceupnp();
|
||||||
useUpnpIface = theSettings.isUseupnpiface();
|
useUpnpIface = theSettings.isUseupnpiface();
|
||||||
theUpnpSendDelay = theSettings.getUpnpsenddelay();
|
theUpnpSendDelay = theSettings.getUpnpsenddelay();
|
||||||
bridgeControl = theControl;
|
bridgeControl = theControl;
|
||||||
aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION, theSettings.getHubmac());
|
aHueConfig = HuePublicConfig.createConfig("temp", upnpConfigIP, HueConstants.HUB_VERSION, theSettings.getHubmac());
|
||||||
bridgeId = aHueConfig.getBridgeid();
|
bridgeId = aHueConfig.getBridgeid();
|
||||||
bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
|
bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
|
||||||
try {
|
try {
|
||||||
|
if(useUpnpIface)
|
||||||
|
upnpMulticastSocket = new MulticastSocket(new InetSocketAddress(upnpConfigIP, Configuration.UPNP_DISCOVERY_PORT));
|
||||||
|
else
|
||||||
upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
|
upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
|
||||||
} catch(IOException e){
|
} catch(IOException e){
|
||||||
log.error("Upnp Discovery Port is in use, or restricted by admin (try running with sudo or admin privs): " + Configuration.UPNP_DISCOVERY_PORT + " with message: " + e.getMessage());
|
log.error("Upnp Discovery Port is in use, or restricted by admin (try running with sudo or admin privs): " + Configuration.UPNP_DISCOVERY_PORT + " with message: " + e.getMessage());
|
||||||
@@ -118,7 +121,7 @@ public class UpnpListener {
|
|||||||
log.info("Traceupnp: Interface: " + name + " valid usable IP address: " + addr);
|
log.info("Traceupnp: Interface: " + name + " valid usable IP address: " + addr);
|
||||||
IPsPerNic++;
|
IPsPerNic++;
|
||||||
}
|
}
|
||||||
else if(addr.getHostAddress().equals(responseAddress)) {
|
else if(addr.getHostAddress().equals(upnpConfigIP)) {
|
||||||
if(traceupnp)
|
if(traceupnp)
|
||||||
log.info("Traceupnp: Interface: " + name + " matches upnp config address of IP address: " + addr);
|
log.info("Traceupnp: Interface: " + name + " matches upnp config address of IP address: " + addr);
|
||||||
IPsPerNic++;
|
IPsPerNic++;
|
||||||
@@ -157,7 +160,7 @@ public class UpnpListener {
|
|||||||
upnpMulticastSocket.receive(packet);
|
upnpMulticastSocket.receive(packet);
|
||||||
if (isSSDPDiscovery(packet)) {
|
if (isSSDPDiscovery(packet)) {
|
||||||
try {
|
try {
|
||||||
sendUpnpResponse(packet.getAddress(), packet.getPort());
|
sendUpnpResponse(packet);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.warn("UpnpListener encountered an error sending upnp response packet. IP: " + packet.getAddress().getHostAddress() + " with message: " + e.getMessage());
|
log.warn("UpnpListener encountered an error sending upnp response packet. IP: " + packet.getAddress().getHostAddress() + " with message: " + e.getMessage());
|
||||||
log.debug("UpnpListener send upnp exception: ", e);
|
log.debug("UpnpListener send upnp exception: ", e);
|
||||||
@@ -230,16 +233,21 @@ public class UpnpListener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void sendUpnpResponse(InetAddress requester, int sourcePort) throws IOException {
|
protected void sendUpnpResponse(DatagramPacket aPacket) throws IOException {
|
||||||
|
SocketAddress requesterAddress = aPacket.getSocketAddress();
|
||||||
|
InetAddress requester = aPacket.getAddress();
|
||||||
|
int sourcePort = aPacket.getPort();
|
||||||
String discoveryResponse = null;
|
String discoveryResponse = null;
|
||||||
|
// refactored suggestion by https://github.com/pvint
|
||||||
|
String httpLocationAddress = getOutboundAddress(requesterAddress).getHostAddress();
|
||||||
try {
|
try {
|
||||||
Thread.sleep(theUpnpSendDelay);
|
Thread.sleep(theUpnpSendDelay);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
||||||
if(traceupnp) {
|
if(traceupnp) {
|
||||||
log.info("Traceupnp: send upnp discovery template 1 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
log.info("Traceupnp: send upnp discovery template 1 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
||||||
@@ -250,9 +258,9 @@ public class UpnpListener {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
||||||
if(traceupnp) {
|
if(traceupnp) {
|
||||||
log.info("Traceupnp: send upnp discovery template 2 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
log.info("Traceupnp: send upnp discovery template 2 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
||||||
@@ -263,9 +271,9 @@ public class UpnpListener {
|
|||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// noop
|
// noop
|
||||||
}
|
}
|
||||||
discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, httpLocationAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
||||||
if(traceupnp) {
|
if(traceupnp) {
|
||||||
log.info("Traceupnp: send upnp discovery template 3 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
log.info("Traceupnp: send upnp discovery template 3 with response address: " + httpLocationAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
||||||
@@ -282,7 +290,7 @@ public class UpnpListener {
|
|||||||
|
|
||||||
protected void sendUpnpNotify(InetAddress aSocketAddress) {
|
protected void sendUpnpNotify(InetAddress aSocketAddress) {
|
||||||
String notifyData = null;
|
String notifyData = null;
|
||||||
notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, upnpConfigIP, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
||||||
log.debug("sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>");
|
log.debug("sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>");
|
||||||
DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT);
|
DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT);
|
||||||
try {
|
try {
|
||||||
@@ -291,6 +299,20 @@ public class UpnpListener {
|
|||||||
log.warn("UpnpListener encountered an error sending upnp notify packet. IP: " + notifyPacket.getAddress().getHostAddress() + " with message: " + e1.getMessage());
|
log.warn("UpnpListener encountered an error sending upnp notify packet. IP: " + notifyPacket.getAddress().getHostAddress() + " with message: " + e1.getMessage());
|
||||||
log.debug("UpnpListener send upnp notify exception: ", e1);
|
log.debug("UpnpListener send upnp notify exception: ", e1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// added by https://github.com/pvint
|
||||||
|
// Ruthlessly stolen from https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface
|
||||||
|
// Try to get a source IP that makes sense for the requestor to contact for use in the LOCATION header in replies
|
||||||
|
private InetAddress getOutboundAddress(SocketAddress remoteAddress) throws SocketException {
|
||||||
|
DatagramSocket sock = new DatagramSocket();
|
||||||
|
// connect is needed to bind the socket and retrieve the local address
|
||||||
|
// later (it would return 0.0.0.0 otherwise)
|
||||||
|
sock.connect(remoteAddress);
|
||||||
|
final InetAddress localAddress = sock.getLocalAddress();
|
||||||
|
sock.disconnect();
|
||||||
|
sock.close();
|
||||||
|
sock = null;
|
||||||
|
return localAddress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,14 @@ import com.bwssystems.HABridge.BridgeSettings;
|
|||||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||||
import com.bwssystems.HABridge.api.hue.HueConstants;
|
import com.bwssystems.HABridge.api.hue.HueConstants;
|
||||||
import com.bwssystems.HABridge.api.hue.HuePublicConfig;
|
import com.bwssystems.HABridge.api.hue.HuePublicConfig;
|
||||||
|
import com.bwssystems.HABridge.util.ParseRoute;
|
||||||
|
|
||||||
import static spark.Spark.get;
|
import static spark.Spark.get;
|
||||||
|
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -75,12 +80,13 @@ public class UpnpSettingsResource {
|
|||||||
|
|
||||||
String portNumber = Integer.toString(request.port());
|
String portNumber = Integer.toString(request.port());
|
||||||
String filledTemplate = null;
|
String filledTemplate = null;
|
||||||
String bridgeIdMac = HuePublicConfig.createConfig("temp", theSettings.getUpnpConfigAddress(), HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
|
String httpLocationAddr = getOutboundAddress(request.ip(), request.port()).getHostAddress();
|
||||||
filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress(), bridgeIdMac, bridgeIdMac);
|
String bridgeIdMac = HuePublicConfig.createConfig("temp", httpLocationAddr, HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
|
||||||
|
filledTemplate = String.format(hueTemplate, httpLocationAddr, portNumber, httpLocationAddr, bridgeIdMac, bridgeIdMac);
|
||||||
if(theSettings.isTraceupnp())
|
if(theSettings.isTraceupnp())
|
||||||
log.info("Traceupnp: request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + theSettings.getUpnpConfigAddress() + ":" + portNumber);
|
log.info("Traceupnp: request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + httpLocationAddr + ":" + portNumber);
|
||||||
else
|
else
|
||||||
log.debug("request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + theSettings.getUpnpConfigAddress() + ":" + portNumber);
|
log.debug("request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + httpLocationAddr + ":" + portNumber);
|
||||||
// response.header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
|
// response.header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
|
||||||
// response.header("Pragma", "no-cache");
|
// response.header("Pragma", "no-cache");
|
||||||
// response.header("Expires", "Mon, 1 Aug 2011 09:00:00 GMT");
|
// response.header("Expires", "Mon, 1 Aug 2011 09:00:00 GMT");
|
||||||
@@ -109,4 +115,28 @@ public class UpnpSettingsResource {
|
|||||||
return "";
|
return "";
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
// added by https://github.com/pvint
|
||||||
|
// Ruthlessly stolen from https://stackoverflow.com/questions/22045165/java-datagrampacket-receive-how-to-determine-local-ip-interface
|
||||||
|
// Try to get a source IP that makes sense for the requester to contact for use in the LOCATION header in replies
|
||||||
|
private InetAddress getOutboundAddress(String remoteAddress, int remotePort) {
|
||||||
|
InetAddress localAddress = null;
|
||||||
|
try {
|
||||||
|
DatagramSocket sock = new DatagramSocket();
|
||||||
|
// connect is needed to bind the socket and retrieve the local address
|
||||||
|
// later (it would return 0.0.0.0 otherwise)
|
||||||
|
sock.connect(new InetSocketAddress(remoteAddress, remotePort));
|
||||||
|
localAddress = sock.getLocalAddress();
|
||||||
|
sock.disconnect();
|
||||||
|
sock.close();
|
||||||
|
sock = null;
|
||||||
|
} catch(Exception e) {
|
||||||
|
ParseRoute theRoute = ParseRoute.getInstance();
|
||||||
|
try {
|
||||||
|
localAddress = InetAddress.getByName(theRoute.getLocalIPAddress());
|
||||||
|
} catch(Exception e1) {}
|
||||||
|
log.warn("Error <" + e.getMessage() + "> on determining interface to reply for <" + remoteAddress + ">. Using default route IP Address of " + localAddress.getHostAddress());
|
||||||
|
}
|
||||||
|
log.debug("getOutbountAddress returning IP Address of " + localAddress.getHostAddress());
|
||||||
|
return localAddress;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
165
src/main/java/com/bwssystems/HABridge/util/ParseRoute.java
Normal file
165
src/main/java/com/bwssystems/HABridge/util/ParseRoute.java
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
package com.bwssystems.HABridge.util;
|
||||||
|
|
||||||
|
import java.net.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find out the local IP address and default gateway
|
||||||
|
* @author Henry Zheng
|
||||||
|
* @url http://www.ireasoning.com
|
||||||
|
*/
|
||||||
|
public class ParseRoute
|
||||||
|
{
|
||||||
|
private String _gateway;
|
||||||
|
private String _ip;
|
||||||
|
private static ParseRoute _instance;
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ParseRoute pr = ParseRoute.getInstance();
|
||||||
|
System.out.println( "Gateway: " + pr.getGateway() );
|
||||||
|
System.out.println( "IP: " + pr.getLocalIPAddress() );
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
System.out.println( e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParseRoute ()
|
||||||
|
{
|
||||||
|
parse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWindows ()
|
||||||
|
{
|
||||||
|
String os = System.getProperty ( "os.name" ).toUpperCase ();
|
||||||
|
return os.contains( "WINDOWS" ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isLinux ()
|
||||||
|
{
|
||||||
|
String os = System.getProperty ( "os.name" ).toUpperCase ();
|
||||||
|
return os.contains( "LINUX" ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalIPAddress()
|
||||||
|
{
|
||||||
|
return _ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGateway()
|
||||||
|
{
|
||||||
|
return _gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ParseRoute getInstance()
|
||||||
|
{
|
||||||
|
if(_instance == null)
|
||||||
|
{
|
||||||
|
_instance = new ParseRoute();
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parse()
|
||||||
|
{
|
||||||
|
if(isWindows())
|
||||||
|
{
|
||||||
|
parseWindows();
|
||||||
|
}
|
||||||
|
else if(isLinux())
|
||||||
|
{
|
||||||
|
parseLinux();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseWindows()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Process pro = Runtime.getRuntime().exec("cmd.exe /c route print");
|
||||||
|
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pro.getInputStream()));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while((line = bufferedReader.readLine())!=null)
|
||||||
|
{
|
||||||
|
line = line.trim();
|
||||||
|
String [] tokens = Tokenizer.parse(line, ' ', true , true);// line.split(" ");
|
||||||
|
if(tokens.length == 5 && tokens[0].equals("0.0.0.0"))
|
||||||
|
{
|
||||||
|
_gateway = tokens[2];
|
||||||
|
_ip = tokens[3];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//pro.waitFor();
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
System.err.println(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseLinux()
|
||||||
|
{
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reader = new BufferedReader(new FileReader("/proc/net/route"));
|
||||||
|
String line;
|
||||||
|
while((line = reader.readLine())!=null)
|
||||||
|
{
|
||||||
|
line = line.trim();
|
||||||
|
String [] tokens = Tokenizer.parse(line, '\t', true , true);// line.split(" ");
|
||||||
|
if(tokens.length > 1 && tokens[1].equals("00000000"))
|
||||||
|
{
|
||||||
|
String gateway = tokens[2]; //0102A8C0
|
||||||
|
if(gateway.length() == 8)
|
||||||
|
{
|
||||||
|
String[] s4 = new String[4];
|
||||||
|
s4[3] = String.valueOf(Integer.parseInt(gateway.substring(0, 2), 16));
|
||||||
|
s4[2] = String.valueOf(Integer.parseInt(gateway.substring(2, 4), 16));
|
||||||
|
s4[1] = String.valueOf(Integer.parseInt(gateway.substring(4, 6), 16));
|
||||||
|
s4[0] = String.valueOf(Integer.parseInt(gateway.substring(6, 8), 16));
|
||||||
|
_gateway = s4[0] + "." + s4[1] + "." + s4[2] + "." + s4[3];
|
||||||
|
}
|
||||||
|
String iface = tokens[0];
|
||||||
|
NetworkInterface nif = NetworkInterface.getByName(iface);
|
||||||
|
Enumeration<java.net.InetAddress> addrs = nif.getInetAddresses();
|
||||||
|
while(addrs.hasMoreElements())
|
||||||
|
{
|
||||||
|
Object obj = addrs.nextElement();
|
||||||
|
if(obj instanceof Inet4Address)
|
||||||
|
{
|
||||||
|
_ip = obj.toString();
|
||||||
|
if(_ip.startsWith("/")) _ip = _ip.substring(1);
|
||||||
|
reader.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
System.err.println(e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch(Exception e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
195
src/main/java/com/bwssystems/HABridge/util/StringArray.java
Normal file
195
src/main/java/com/bwssystems/HABridge/util/StringArray.java
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
package com.bwssystems.HABridge.util;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is an auto-resizable String array. It has similar methods to ArrayList
|
||||||
|
*
|
||||||
|
* @author Henry Zheng
|
||||||
|
* @url http://www.ireasoning.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class StringArray implements Serializable
|
||||||
|
{
|
||||||
|
public static final long serialVersionUID = 42L;
|
||||||
|
public static final int DEFAULT_CAPACITY = 10;
|
||||||
|
|
||||||
|
protected String[] _strings = null;
|
||||||
|
protected int _upperBound = 0;
|
||||||
|
protected int _capacity = DEFAULT_CAPACITY;
|
||||||
|
protected int _initialSize = _capacity;
|
||||||
|
protected float _loadFactory = 1.5F;
|
||||||
|
|
||||||
|
public StringArray ()
|
||||||
|
{
|
||||||
|
this(DEFAULT_CAPACITY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringArray( int size)
|
||||||
|
{
|
||||||
|
_capacity = size;
|
||||||
|
_initialSize = size;
|
||||||
|
_strings = new String[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void ensureCapacity(int capacity)
|
||||||
|
{
|
||||||
|
if(_capacity < capacity)
|
||||||
|
{
|
||||||
|
_capacity = (_capacity * 3)/2 + 1;
|
||||||
|
if(_capacity < capacity)
|
||||||
|
{
|
||||||
|
_capacity = capacity;
|
||||||
|
}
|
||||||
|
String [] oldData = _strings;
|
||||||
|
_strings = new String[_capacity];
|
||||||
|
System.arraycopy(oldData, 0, _strings, 0, _upperBound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public synchronized void add(String s)
|
||||||
|
{
|
||||||
|
if(_upperBound == _capacity )
|
||||||
|
{
|
||||||
|
resize((int) (_capacity * _loadFactory));
|
||||||
|
}
|
||||||
|
_strings[_upperBound++] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void add(StringArray sa)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sa.size() ; i++)
|
||||||
|
{
|
||||||
|
add(sa.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized String get(int index)
|
||||||
|
{
|
||||||
|
return _strings[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void set(int index, String newVal)
|
||||||
|
{
|
||||||
|
_strings[index] = newVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds all elements in passed string array */
|
||||||
|
public synchronized void add(String [] strs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < strs.length ; i++)
|
||||||
|
{
|
||||||
|
add(strs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resets this object. */
|
||||||
|
public synchronized void clear()
|
||||||
|
{
|
||||||
|
_capacity = _initialSize;
|
||||||
|
_strings = new String[_capacity];
|
||||||
|
_upperBound = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized String remove(int index)
|
||||||
|
{
|
||||||
|
if(index >= _upperBound )
|
||||||
|
{
|
||||||
|
throw new IndexOutOfBoundsException();
|
||||||
|
}
|
||||||
|
String s = _strings[index];
|
||||||
|
for (int i = index; i < _upperBound - 1 ; i++)
|
||||||
|
{
|
||||||
|
_strings[i] = _strings[i + 1];
|
||||||
|
}
|
||||||
|
_upperBound --;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the first occurance of passed str
|
||||||
|
* @return the string removed, or null if not found
|
||||||
|
*/
|
||||||
|
public synchronized String remove(String str)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _upperBound ; i++)
|
||||||
|
{
|
||||||
|
if(_strings[i].equals(str))
|
||||||
|
{
|
||||||
|
return remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int size()
|
||||||
|
{
|
||||||
|
return _upperBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean isEmpty()
|
||||||
|
{
|
||||||
|
return _upperBound == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized String[] toArray()
|
||||||
|
{
|
||||||
|
String [] ret = new String[_upperBound];
|
||||||
|
for (int i = 0; i < _upperBound ; i++)
|
||||||
|
{
|
||||||
|
ret[i] = _strings[i];
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void resize(int newCapacity)
|
||||||
|
{
|
||||||
|
String [] as = new String[newCapacity];
|
||||||
|
for (int i = 0; i < _strings.length ; i++)
|
||||||
|
{
|
||||||
|
as[i] = _strings[i];
|
||||||
|
}
|
||||||
|
_strings = as;
|
||||||
|
_capacity = newCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
for (int i = 0; i < _upperBound ; i++)
|
||||||
|
{
|
||||||
|
buf.append(_strings[i] + "\n");
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
StringArray as = new StringArray();
|
||||||
|
String [] ss = null;
|
||||||
|
ss = as.toArray();
|
||||||
|
// System.out.println( "ss len="+ss.length);
|
||||||
|
// System.out.println( "ss = " + ss);
|
||||||
|
for (int i = 0; i < 10 ; i++)
|
||||||
|
{
|
||||||
|
as.add("" + i);
|
||||||
|
}
|
||||||
|
// System.out.println( "size = " + as.size());
|
||||||
|
ss = as.toArray();
|
||||||
|
for (int i = 0; i < ss.length ; i++)
|
||||||
|
{
|
||||||
|
// System.out.println( ss[i]);
|
||||||
|
}
|
||||||
|
// System.out.println( "remove 5th element.");
|
||||||
|
as.remove(5);
|
||||||
|
|
||||||
|
// System.out.println( "size = " + as.size());
|
||||||
|
ss = as.toArray();
|
||||||
|
for (int i = 0; i < ss.length ; i++)
|
||||||
|
{
|
||||||
|
// System.out.println( ss[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//end of class StringArray
|
||||||
175
src/main/java/com/bwssystems/HABridge/util/Tokenizer.java
Normal file
175
src/main/java/com/bwssystems/HABridge/util/Tokenizer.java
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
package com.bwssystems.HABridge.util;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class perform similar functionality to StringTokenizer class but faster.
|
||||||
|
* The difference is StringTokenizer doesn't count empty token, but this class does.
|
||||||
|
*
|
||||||
|
* @author Henry Zheng
|
||||||
|
* @url http://www.ireasoning.com
|
||||||
|
*/
|
||||||
|
public class Tokenizer
|
||||||
|
{
|
||||||
|
private Tokenizer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It's different from the other parse method in that it checks left and right string first, which take higer
|
||||||
|
* priority than the delimiter. For example, if left and right is ", for string a:b:1"c:d"2:3 ,
|
||||||
|
* it returns { a, b, 1"c:d"2, 3 }
|
||||||
|
* @param left the openning tag of higher priority token
|
||||||
|
* @param right the closing tag of higher priority token
|
||||||
|
* @trimEachToken if true, each token will be trim by calling String.trim()
|
||||||
|
*/
|
||||||
|
public static String[] parse(String text, char delimiter, boolean trimEachToken, String left, String right)
|
||||||
|
{
|
||||||
|
if(text == null) return null;
|
||||||
|
StringArray tokens = new StringArray();
|
||||||
|
int pos1 = -1;
|
||||||
|
int pos2 = -1;
|
||||||
|
int firstPos = -1;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
pos2 = text.indexOf(delimiter, firstPos + 1);
|
||||||
|
if(pos2 < 0 )
|
||||||
|
{
|
||||||
|
String str = text.substring(pos1 + 1);
|
||||||
|
if(trimEachToken )
|
||||||
|
{
|
||||||
|
str = str.trim();
|
||||||
|
}
|
||||||
|
tokens.add(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(pos2 == pos1 + 1)
|
||||||
|
{
|
||||||
|
tokens.add("");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tagPos1 = text.indexOf(left, firstPos + 1);
|
||||||
|
if(tagPos1 > 0 && tagPos1 < pos2 )
|
||||||
|
{
|
||||||
|
int tagPos2 = text.indexOf(right, tagPos1 + 1);
|
||||||
|
if(tagPos2 > 0)
|
||||||
|
{
|
||||||
|
firstPos = tagPos2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String str = text.substring(pos1 + 1, pos2);
|
||||||
|
if(trimEachToken )
|
||||||
|
{
|
||||||
|
str = str.trim();
|
||||||
|
}
|
||||||
|
tokens.add(str);
|
||||||
|
}
|
||||||
|
pos1 = pos2;
|
||||||
|
firstPos = pos1;
|
||||||
|
}
|
||||||
|
String[] ret = tokens.toArray();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @trimEachToken if true, each token will be trim by calling String.trim()
|
||||||
|
*/
|
||||||
|
public static String[] parse(String text, char delimiter, boolean trimEachToken)
|
||||||
|
{
|
||||||
|
return parse(text, delimiter, trimEachToken, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @trimEachToken if true, each token will be trim by calling String.trim()
|
||||||
|
*/
|
||||||
|
public static String[] parse(String text, char delimiter, boolean trimEachToken, boolean ignoreEmptyToken)
|
||||||
|
{
|
||||||
|
if(text == null) return null;
|
||||||
|
StringArray tokens = new StringArray();
|
||||||
|
int pos1 = -1;
|
||||||
|
int pos2 = -1;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
pos2 = text.indexOf(delimiter, pos1 + 1);
|
||||||
|
if(pos2 < 0 )
|
||||||
|
{
|
||||||
|
String str = text.substring(pos1 + 1);
|
||||||
|
if(trimEachToken )
|
||||||
|
{
|
||||||
|
str = str.trim();
|
||||||
|
}
|
||||||
|
if(ignoreEmptyToken)
|
||||||
|
{
|
||||||
|
if(str.length() != 0) tokens.add(str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tokens.add(str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(pos2 == pos1 + 1)
|
||||||
|
{
|
||||||
|
if(!ignoreEmptyToken) { tokens.add(""); }
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String str = text.substring(pos1 + 1, pos2);
|
||||||
|
if(trimEachToken )
|
||||||
|
{
|
||||||
|
str = str.trim();
|
||||||
|
}
|
||||||
|
if(ignoreEmptyToken)
|
||||||
|
{
|
||||||
|
if(str.length() != 0) tokens.add(str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tokens.add(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos1 = pos2;
|
||||||
|
}
|
||||||
|
String[] ret = tokens.toArray();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not trim each token.
|
||||||
|
* @see #parse(String, char, boolean)
|
||||||
|
*/
|
||||||
|
public static String[] parse(String text, char delimiter)
|
||||||
|
{
|
||||||
|
return parse(text, delimiter, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static void main(String[] args)
|
||||||
|
// {
|
||||||
|
// String str = "1,\"2,\"ab\",ttt1,\"3,,a\"222\",4";
|
||||||
|
// if(args.length > 0)
|
||||||
|
// {
|
||||||
|
// str = args[0];
|
||||||
|
// }
|
||||||
|
// String [] tokens = Tokenizer.parse(str, ',');
|
||||||
|
//
|
||||||
|
//// System.out.println( "Text = (" + str + ")");
|
||||||
|
// // System.out.println( "------------------------------------------");
|
||||||
|
// for (int i = 0; i < tokens.length ; i++)
|
||||||
|
// {
|
||||||
|
// // System.out.println( "(" + tokens[i] + ")");
|
||||||
|
// }
|
||||||
|
// // System.out.println( "------------------------------------------");
|
||||||
|
|
||||||
|
// String [] tokens = Tokenizer.parse(str, ',', new String[]{"("}, new String[]{")"});
|
||||||
|
//
|
||||||
|
// // System.out.println( "Text = [" + str + "]");
|
||||||
|
// // System.out.println( "------------------------------------------");
|
||||||
|
// for (int i = 0; i < tokens.length ; i++)
|
||||||
|
// {
|
||||||
|
// // System.out.println( "[" + tokens[i] + "]");
|
||||||
|
// }
|
||||||
|
// // System.out.println( "------------------------------------------");
|
||||||
|
|
||||||
|
// }
|
||||||
|
}//end of class Tokenizer
|
||||||
@@ -1684,11 +1684,11 @@ app.controller ('SystemController', function ($scope, $location, bridgeService,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
$scope.addDomoticztoSettings = function (newdomoticzname, newdomoticzip, newdomoticzport, newdomoticzusername, newdomoticzpassword) {
|
$scope.addDomoticztoSettings = function (newdomoticzname, newdomoticzip, newdomoticzport, newdomoticzusername, newdomoticzpassword, newdomoticzsecure) {
|
||||||
if($scope.bridge.settings.domoticzaddress === undefined || $scope.bridge.settings.domoticzaddress === null) {
|
if($scope.bridge.settings.domoticzaddress === undefined || $scope.bridge.settings.domoticzaddress === null) {
|
||||||
$scope.bridge.settings.domoticzaddress = { devices: [] };
|
$scope.bridge.settings.domoticzaddress = { devices: [] };
|
||||||
}
|
}
|
||||||
var newdomoticz = {name: newdomoticzname, ip: newdomoticzip, port: newdomoticzport, username: newdomoticzusername, password: newdomoticzpassword }
|
var newdomoticz = {name: newdomoticzname, ip: newdomoticzip, port: newdomoticzport, username: newdomoticzusername, password: newdomoticzpassword, secure: newdomoticzsecure }
|
||||||
$scope.bridge.settings.domoticzaddress.devices.push(newdomoticz);
|
$scope.bridge.settings.domoticzaddress.devices.push(newdomoticz);
|
||||||
$scope.newdomoticzname = null;
|
$scope.newdomoticzname = null;
|
||||||
$scope.newdomoticzip = null;
|
$scope.newdomoticzip = null;
|
||||||
|
|||||||
@@ -94,6 +94,12 @@
|
|||||||
ng-model="device.offState" ng-true-value=true
|
ng-model="device.offState" ng-true-value=true
|
||||||
ng-false-value=false> {{device.offState}}</td>
|
ng-false-value=false> {{device.offState}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label>On when Dim is present (Always uses on with a dim request otherwise it will ignore a given on was well. This is overidden by onFirstDim.)</label></td>
|
||||||
|
<td><input type="checkbox"
|
||||||
|
ng-model="device.onWhenDimPresent" ng-true-value=true
|
||||||
|
ng-false-value=false> {{device.onWhenDimPresent}}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label>On with First Dim (If the device is not on in the ha-bridge state, it will send on instead of the dim.)</label></td>
|
<td><label>On with First Dim (If the device is not on in the ha-bridge state, it will send on instead of the dim.)</label></td>
|
||||||
<td><input type="checkbox"
|
<td><input type="checkbox"
|
||||||
|
|||||||
@@ -512,6 +512,7 @@
|
|||||||
<th>Port</th>
|
<th>Port</th>
|
||||||
<th>Username (opt)</th>
|
<th>Username (opt)</th>
|
||||||
<th>Password (opt)</th>
|
<th>Password (opt)</th>
|
||||||
|
<th>Use SSL</th>
|
||||||
<th>Manage</th>
|
<th>Manage</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -531,6 +532,9 @@
|
|||||||
<td><input id="bridge-settings-next-domoticz-password"
|
<td><input id="bridge-settings-next-domoticz-password"
|
||||||
class="form-control" type="password" ng-model="domoticz.password"
|
class="form-control" type="password" ng-model="domoticz.password"
|
||||||
placeholder="Domoticz password (opt)"></td>
|
placeholder="Domoticz password (opt)"></td>
|
||||||
|
<td><input type="checkbox"
|
||||||
|
ng-model="domoticz.secure" ng-true-value=true
|
||||||
|
ng-false-value=false></td>
|
||||||
<td><button class="btn btn-danger" type="submit"
|
<td><button class="btn btn-danger" type="submit"
|
||||||
ng-click="removeDomoticztoSettings(domoticz.name, domoticz.ip)">Del</button></td>
|
ng-click="removeDomoticztoSettings(domoticz.name, domoticz.ip)">Del</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -550,8 +554,11 @@
|
|||||||
<td><input id="bridge-settings-new-domoticz-password"
|
<td><input id="bridge-settings-new-domoticz-password"
|
||||||
class="form-control" type="password" ng-model="newdomoticzpassword"
|
class="form-control" type="password" ng-model="newdomoticzpassword"
|
||||||
placeholder="Domoticz password (opt)"></td>
|
placeholder="Domoticz password (opt)"></td>
|
||||||
|
<td><input type="checkbox"
|
||||||
|
ng-model="newdomoticzsecure" ng-true-value=true
|
||||||
|
ng-false-value=false></td>
|
||||||
<td><button class="btn btn-success" type="submit"
|
<td><button class="btn btn-success" type="submit"
|
||||||
ng-click="addDomoticztoSettings(newdomoticzname, newdomoticzip, newdomoticzport, newdomoticzusername, newdomoticzpassword)">Add</button></td>
|
ng-click="addDomoticztoSettings(newdomoticzname, newdomoticzip, newdomoticzport, newdomoticzusername, newdomoticzpassword, newdomoticzsecure)">Add</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table></td>
|
</table></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user