mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-16 18:24:36 +00:00
Merge pull request #796 from bwssytems/FeaturesfFor5.0
Features for 5.0 Fixes #749 No Login Feedback - No Password reset enhancement question Fixes #717 Having to often repeat command enhancement question Fixes #768 Hue Items error with ha-bridge-5.0.0rc2 bug question Fixes #782 getting server error 500 out of nowhere enhancement question Fixes #779 Allow custom hue-bridgeid? enhancement question Fixes #450 Unable to edit on ipad enhancement question Fixes #336 Fibaro support enhancement help wanted Fixes #560 How to run Fibaro Scene in HA-Bridge? enhancement question Fixes #737 2 HA-Bridge instances: UpnpListener encountered an error sending upnp notify packet. IP: 239.255.255.250 with message: Operation not permitted enhancement question Fixes #761 Philips Hue app update - bridge update required enhancement question Fixes #747 Issue with MQTT messages - intermittent success enhancement question Fixes #722 Long time no operation causes failure of the first operation of home assistant devices enhancement question Fixes #671 action taking place only on the second time i ask to do it enhancement question Fixes #381 Resize Target Item Field enhancement question Fixes #705 Item Delete Button deletes multiple items bug question Fixes #327 Add Color or Raw Info enhancement question Fixes #704 Rename "Clear Device" to "Clear" enhancement Fixes #713 Room and basic color (especially limitless/milight) support enhancement
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -12,3 +12,5 @@ data
|
||||
/.settings/
|
||||
/start.bat
|
||||
/.classpath
|
||||
|
||||
sftp-config\.json
|
||||
|
||||
47
README.md
47
README.md
@@ -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-4.5.6.jar
|
||||
java -jar ha-bridge-5.0.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-4.5.6.jar is in your /home/pi/habridge directory.
|
||||
Create the directory and make sure that ha-bridge-5.0.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/v4.5.6/ha-bridge-4.5.6.jar
|
||||
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v5.0.0/ha-bridge-5.0.0.jar
|
||||
```
|
||||
|
||||
#### System Control Setup on a pi (preferred)
|
||||
@@ -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-4.5.6.jar
|
||||
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-5.0.0.jar
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -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-4.5.6.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.0.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
|
||||
|
||||
chmod 777 /home/pi/habridge/habridge-log.txt
|
||||
```
|
||||
@@ -265,6 +265,8 @@ The server defaults to running on port 80. To override what the default is, spec
|
||||
The upnp response port that will be used. The default is 50000.
|
||||
#### Vera Names and IP Addresses
|
||||
Provide IP Addresses of your Veras 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 Vera and device/scene you configure.
|
||||
#### Fibaro Names and IP Addresses
|
||||
Provide IP Addresses of your Fibaros 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 Fibaro and device/scene you configure.
|
||||
#### Harmony Names and IP Addresses
|
||||
Provide IP Addresses of your Harmony Hubs 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 activity or buttons by the call it receives and send it to the target Harmony Hub and activity/button you configure. Also, an option of webhook can be called when the activity changes on the harmony hub that will send an HTTP GET call to the the address of your choosing. This can contain the replacement variables of ${activity.id} and/or ${activity.label}. Example : http://192.168.0.1/activity/${activity.id}/${activity.label} OR http://hook?a=${activity.label}
|
||||
#### Hue Names and IP Addresses
|
||||
@@ -273,28 +275,34 @@ Provide IP Addresses of your Hue Bridges that you want to proxy through the brid
|
||||
Don't forget - You will need to push the link button when you got to the Hue Tab the first time after the process comes up. (The user name is not persistent when the process comes up.)
|
||||
#### HAL Names and IP Addresses
|
||||
Provide IP Addresses of your HAL 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 HAL and device/scene you configure.
|
||||
#### HAL Token
|
||||
The token you generate or give to a HAL and must be the same for all HAL's you have identified. This needs to be given if you are using the HAL features.
|
||||
#### 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.
|
||||
#### 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.
|
||||
#### Domoticz Names and IP Addresses
|
||||
Provide IP Addresses of your Domoticz 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 Domoticz and device/scene you configure.
|
||||
#### Somfy Tahoma Names and IP Addresses
|
||||
Provide user name and password used to login to www.tahomalink.com. This needs to be provided if you're using the Somfy Tahoma features (for connecting to IO Homecontrol used by Velux among others). There is no need to give any IP address or host information as this contacts your cloud account. *Note:* you have to 'turn on' a window to open it, and 'turn off' to close.
|
||||
#### Nest Username
|
||||
The user name of the home.nest.com account for the Nest user. This needs to be given if you are using the Nest features. There is no need to give any ip address or host information as this contacts your cloud account.
|
||||
#### Nest Password
|
||||
The password for the user name of the home.nest.com account for the Nest user. This needs to be given if you are using the Nest features.
|
||||
#### Nest Temp Fahrenheit
|
||||
This setting allows the value being sent into the bridge to be interpreted as Fahrenheit or Celsius. The default is to have Fahrenheit.
|
||||
#### Somfy Tahoma Username
|
||||
The user name used to login to www.tahomalink.com. This needs to be provided if you're using the Somfy Tahoma features (for connecting to IO Homecontrol used by Velux among others). There is no need to give any IP address or host information as this contacts your cloud account. *Note:* you have to 'turn on' a window to open it, and 'turn off' to close.
|
||||
#### Somfy Tahoma Password
|
||||
The password associated with the Somfy Tahoma username above
|
||||
#### LIFX Support
|
||||
This setting will have the ha-bridge look for LIFX devices on your network. Since this is broadcast based, there is no other info needed.
|
||||
#### Emulate Hue Hub Version
|
||||
This setting is used to set the version that the ha-bridge will return in the hub version field. The default is 9999999999 which should work to be higher than the versions that are being used.
|
||||
#### Emulate MAC
|
||||
This setting is in bridge-id, uuid, etc. in ha-bridge hue config replies. Leave blank unless needed as it is mainly a tool to keep a config to a specific set of devices whtn the ha-bridge is moved to another machine
|
||||
#### Button Press/Call Item Loop Sleep Interval (ms)
|
||||
This setting is the time used in between button presses when there is multiple buttons in a button device. It also controls the time between multiple items in a custom device call. This is defaulted to 100ms and the number represents milliseconds (1000 milliseconds = 1 second).
|
||||
#### Log Messages to Buffer
|
||||
This controls how many log messages will be kept and displayed on the log tab. This does not affect what is written to the standard output for logging. The default is 512. Changing this will incur more memory usage of the process.
|
||||
#### UPNP Strict Handling
|
||||
Upnp has been set to be very specific as to respond as a Hue. There may be a need to make this response a little more open for other devices that may want to find the ha-bridge. The default is to be strict which is set as true.
|
||||
#### Trace UPNP Calls
|
||||
Turn on tracing for upnp discovery messages to the log. The default is false.
|
||||
#### My Echo URL
|
||||
This sets the URL that is used in the menu bar to ge to your echo. For certain countries, this needs to be set to a different URL.
|
||||
|
||||
At the bottom of the screen is the "Bridge Settings Backup" which can be accessed with clicking on the `+` to expand this frame. Here you can backup and restore configurations that you have saved. These configs can be named or by clicking the `Backup Settings' button will create a backup and name it for you. You can manage these backups by restoring them or deleting them.
|
||||
### The Logs Tab
|
||||
@@ -304,7 +312,7 @@ The bottom part of the Logs Screen has configuration to change the logging level
|
||||
### Bridge Device Additions
|
||||
You must configure devices before you will have anything for the Echo or other controller that is connected to the ha-bridge to receive.
|
||||
#### Helpers
|
||||
The easy way to get devices configured is with the use of the helpers for the Vera or Harmony, Nest and Hue to create devices that the bridge will present.
|
||||
The easy way to get devices configured is with the use of the helpers for the Vera or Harmony, Nest, Hue and others to create devices that the bridge will present.
|
||||
|
||||
For the Helpers, each item being presented from the target system has a button such as `Build Item`, `Build A Button` or specific tasks such as `Temp` for thermostats that is used to create the specific device parameters. The build action buttons will put you into the edit screen. The next thing to check is the name for the bridge device that it is something that makes sense especially if you using the ha-bridge with an Echo or Google Home as this is what the Echo or Google Home will interpret as the device you want. Also, you can go back to any helper tab and click a build action button to add another item for a multi-command. After you are done in the edit tab, click the `Add Bridge Device` to finish that selection setup.
|
||||
|
||||
@@ -314,7 +322,18 @@ Another way to add a device is through the Manual Add Tab. This allows you to ma
|
||||
|
||||
There is a new format for the on/dim/off URL areas. The new editor handles the intricacies of the components, but is broken down here for explanation.
|
||||
|
||||
It is imperative when adding a line by hand that you hit the ```Add``` button at the end of the line before adding or updating the whole entry.
|
||||
|
||||
```Update Bridge Device``` Button is for editing a current bridge device entry.
|
||||
|
||||
```Add Bridge Device``` Button is to ccreate a new bridge device entry.
|
||||
|
||||
```Clear``` Button is used to clear the contents of the entry on the screen.
|
||||
|
||||
```Change Edit Mode``` Button is used to swithc back to a pure editor for the on/off/dim/color lines within the device entry.
|
||||
|
||||
Here are the fields that can be put into the call item:
|
||||
|
||||
Json Type | field name | What | Use
|
||||
----------|------------|------|-----
|
||||
String or JsonElement | item | This is the payload that will be called for devices | Required
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>4.5.6</version>
|
||||
<version>5.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
@@ -63,7 +63,7 @@
|
||||
<dependency>
|
||||
<groupId>com.sparkjava</groupId>
|
||||
<artifactId>spark-core</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>2.7.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
|
||||
@@ -65,6 +65,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
public void buildSettings() {
|
||||
String addressString = null;
|
||||
String theVeraAddress = null;
|
||||
String theFibaroAddress = null;
|
||||
String theSomfyAddress = null;
|
||||
String theHarmonyAddress = null;
|
||||
String configFileProperty = System.getProperty("config.file");
|
||||
@@ -75,6 +76,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
String serverPortOverride = System.getProperty("server.port");
|
||||
String serverIpOverride = System.getProperty("server.ip");
|
||||
String upnpStrictOverride = System.getProperty("upnp.strict", "true");
|
||||
if(configFileProperty != null)
|
||||
{
|
||||
log.info("reading from config file: " + configFileProperty);
|
||||
@@ -90,6 +92,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setServerPort(System.getProperty("server.port", Configuration.DEFAULT_WEB_PORT));
|
||||
theBridgeSettings.setUpnpConfigAddress(System.getProperty("upnp.config.address"));
|
||||
theBridgeSettings.setUpnpDeviceDb(System.getProperty("upnp.device.db"));
|
||||
theBridgeSettings.setUpnpGroupDb(System.getProperty("upnp.group.db"));
|
||||
theBridgeSettings.setUpnpResponsePort(System.getProperty("upnp.response.port", Configuration.UPNP_RESPONSE_PORT));
|
||||
|
||||
theVeraAddress = System.getProperty("vera.address");
|
||||
@@ -107,6 +110,22 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
}
|
||||
theBridgeSettings.setVeraAddress(theVeraList);
|
||||
|
||||
theFibaroAddress = System.getProperty("fibaro.address");
|
||||
IpList theFibaroList = null;
|
||||
if(theFibaroAddress != null) {
|
||||
try {
|
||||
theFibaroList = new Gson().fromJson(theFibaroAddress, IpList.class);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
theFibaroList = new Gson().fromJson("{devices:[{name:default,ip:" + theFibaroAddress + "}]}", IpList.class);
|
||||
} catch (Exception et) {
|
||||
log.error("Cannot parse fibaro.address, not set with message: " + e.getMessage(), e);
|
||||
theFibaroList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
theBridgeSettings.setFibaroAddress(theFibaroList);
|
||||
|
||||
theHarmonyAddress = System.getProperty("harmony.address");
|
||||
IpList theHarmonyList = null;
|
||||
@@ -170,6 +189,9 @@ public class BridgeSettings extends BackupHandler {
|
||||
|
||||
if(theBridgeSettings.getUpnpDeviceDb() == null)
|
||||
theBridgeSettings.setUpnpDeviceDb(Configuration.DEVICE_DB_DIRECTORY);
|
||||
|
||||
if(theBridgeSettings.getUpnpGroupDb() == null)
|
||||
theBridgeSettings.setUpnpGroupDb(Configuration.GROUP_DB_DIRECTORY);
|
||||
|
||||
if(theBridgeSettings.getNumberoflogmessages() == null || theBridgeSettings.getNumberoflogmessages() <= 0)
|
||||
theBridgeSettings.setNumberoflogmessages(new Integer(Configuration.NUMBER_OF_LOG_MESSAGES));
|
||||
@@ -178,6 +200,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setButtonsleep(Integer.parseInt(Configuration.DEFAULT_BUTTON_SLEEP));
|
||||
|
||||
theBridgeSettings.setVeraconfigured(theBridgeSettings.isValidVera());
|
||||
theBridgeSettings.setFibaroconfigured(theBridgeSettings.isValidFibaro());
|
||||
theBridgeSettings.setHarmonyconfigured(theBridgeSettings.isValidHarmony());
|
||||
theBridgeSettings.setNestConfigured(theBridgeSettings.isValidNest());
|
||||
theBridgeSettings.setHueconfigured(theBridgeSettings.isValidHue());
|
||||
@@ -191,6 +214,8 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setServerPort(serverPortOverride);
|
||||
if(serverIpOverride != null)
|
||||
theBridgeSettings.setWebaddress(serverIpOverride);
|
||||
if(upnpStrictOverride != null)
|
||||
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(upnpStrictOverride));
|
||||
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
|
||||
|
||||
bridgeSecurity.setSecurityData(theBridgeSettings.getSecurityData());
|
||||
|
||||
@@ -24,18 +24,21 @@ public class BridgeSettingsDescriptor {
|
||||
@SerializedName("upnpdevicedb")
|
||||
@Expose
|
||||
private String upnpdevicedb;
|
||||
@SerializedName("upnpgroupdb")
|
||||
@Expose
|
||||
private String upnpgroupdb;
|
||||
@SerializedName("veraaddress")
|
||||
@Expose
|
||||
private IpList veraaddress;
|
||||
@SerializedName("fibaroaddress")
|
||||
@Expose
|
||||
private IpList fibaroaddress;
|
||||
@SerializedName("harmonyaddress")
|
||||
@Expose
|
||||
private IpList harmonyaddress;
|
||||
@SerializedName("buttonsleep")
|
||||
@Expose
|
||||
private Integer buttonsleep;
|
||||
@SerializedName("upnpstrict")
|
||||
@Expose
|
||||
private boolean upnpstrict;
|
||||
@SerializedName("traceupnp")
|
||||
@Expose
|
||||
private boolean traceupnp;
|
||||
@@ -60,9 +63,6 @@ public class BridgeSettingsDescriptor {
|
||||
@SerializedName("haladdress")
|
||||
@Expose
|
||||
private IpList haladdress;
|
||||
@SerializedName("haltoken")
|
||||
@Expose
|
||||
private String haltoken;
|
||||
@SerializedName("whitelist")
|
||||
@Expose
|
||||
private Map<String, WhitelistEntry> whitelist;
|
||||
@@ -87,6 +87,9 @@ public class BridgeSettingsDescriptor {
|
||||
@SerializedName("hubversion")
|
||||
@Expose
|
||||
private String hubversion;
|
||||
@SerializedName("hubmac")
|
||||
@Expose
|
||||
private String hubmac;
|
||||
@SerializedName("securityData")
|
||||
@Expose
|
||||
private String securityData;
|
||||
@@ -94,6 +97,7 @@ public class BridgeSettingsDescriptor {
|
||||
|
||||
private boolean settingsChanged;
|
||||
private boolean veraconfigured;
|
||||
private boolean fibaroconfigured;
|
||||
private boolean harmonyconfigured;
|
||||
private boolean hueconfigured;
|
||||
private boolean nestconfigured;
|
||||
@@ -103,6 +107,10 @@ public class BridgeSettingsDescriptor {
|
||||
private boolean domoticzconfigured;
|
||||
private boolean somfyconfigured;
|
||||
private boolean lifxconfigured;
|
||||
|
||||
// Deprecated settings
|
||||
private String haltoken;
|
||||
private boolean upnpstrict;
|
||||
|
||||
public BridgeSettingsDescriptor() {
|
||||
super();
|
||||
@@ -111,6 +119,7 @@ public class BridgeSettingsDescriptor {
|
||||
this.traceupnp = false;
|
||||
this.nestconfigured = false;
|
||||
this.veraconfigured = false;
|
||||
this.fibaroconfigured = false;
|
||||
this.somfyconfigured = false;
|
||||
this.harmonyconfigured = false;
|
||||
this.hueconfigured = false;
|
||||
@@ -123,9 +132,10 @@ public class BridgeSettingsDescriptor {
|
||||
this.farenheit = true;
|
||||
this.securityData = null;
|
||||
this.settingsChanged = false;
|
||||
this.myechourl = "echo.amazon.com/#cards";
|
||||
this.myechourl = "alexa.amazon.com/spa/index.html#cards";
|
||||
this.webaddress = "0.0.0.0";
|
||||
this.hubversion = HueConstants.HUB_VERSION;
|
||||
this.hubmac = null;
|
||||
}
|
||||
public String getUpnpConfigAddress() {
|
||||
return upnpconfigaddress;
|
||||
@@ -163,15 +173,27 @@ public class BridgeSettingsDescriptor {
|
||||
public void setUpnpDeviceDb(String upnpDeviceDb) {
|
||||
this.upnpdevicedb = upnpDeviceDb;
|
||||
}
|
||||
public String getUpnpGroupDb() {
|
||||
return upnpgroupdb;
|
||||
}
|
||||
public void setUpnpGroupDb(String upnpGroupDb) {
|
||||
this.upnpgroupdb = upnpGroupDb;
|
||||
}
|
||||
public IpList getVeraAddress() {
|
||||
return veraaddress;
|
||||
}
|
||||
public IpList getFibaroAddress() {
|
||||
return fibaroaddress;
|
||||
}
|
||||
public IpList getSomfyAddress() {
|
||||
return somfyaddress;
|
||||
}
|
||||
public void setVeraAddress(IpList veraAddress) {
|
||||
this.veraaddress = veraAddress;
|
||||
}
|
||||
public void setFibaroAddress(IpList fibaroAddress) {
|
||||
this.fibaroaddress = fibaroAddress;
|
||||
}
|
||||
public void setSomfyAddress(IpList somfyAddress) {
|
||||
this.somfyaddress = somfyAddress;
|
||||
}
|
||||
@@ -208,12 +230,18 @@ public class BridgeSettingsDescriptor {
|
||||
public boolean isVeraconfigured() {
|
||||
return veraconfigured;
|
||||
}
|
||||
public boolean isFibaroconfigured() {
|
||||
return fibaroconfigured;
|
||||
}
|
||||
public boolean isSomfyconfigured() {
|
||||
return somfyconfigured;
|
||||
}
|
||||
public void setVeraconfigured(boolean veraconfigured) {
|
||||
this.veraconfigured = veraconfigured;
|
||||
}
|
||||
public void setFibaroconfigured(boolean fibaroconfigured) {
|
||||
this.fibaroconfigured = fibaroconfigured;
|
||||
}
|
||||
public void setSomfyconfigured(boolean somfyconfigured) {
|
||||
this.somfyconfigured = somfyconfigured;
|
||||
}
|
||||
@@ -337,6 +365,12 @@ public class BridgeSettingsDescriptor {
|
||||
public void setHubversion(String hubversion) {
|
||||
this.hubversion = hubversion;
|
||||
}
|
||||
public String getHubmac() {
|
||||
return hubmac;
|
||||
}
|
||||
public void setHubmac(String hubmac) {
|
||||
this.hubmac = hubmac;
|
||||
}
|
||||
public IpList getDomoticzaddress() {
|
||||
return domoticzaddress;
|
||||
}
|
||||
@@ -369,6 +403,14 @@ public class BridgeSettingsDescriptor {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidFibaro() {
|
||||
if(this.getFibaroAddress() == null || this.getFibaroAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
List<NamedIP> devicesList = this.getFibaroAddress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidHarmony() {
|
||||
if(this.getHarmonyAddress() == null || this.getHarmonyAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.bwssystems.HABridge;
|
||||
|
||||
public class Configuration {
|
||||
public final static String DEVICE_DB_DIRECTORY = "data/device.db";
|
||||
public final static String GROUP_DB_DIRECTORY = "data/group.db";
|
||||
public final static String UPNP_RESPONSE_PORT = "50000";
|
||||
public final static String DEFAULT_ADDRESS = "1.1.1.1";
|
||||
public final static String LOOP_BACK_ADDRESS = "127.0.0.1";
|
||||
|
||||
@@ -7,6 +7,8 @@ public class DeviceMapTypes {
|
||||
public final static String[] CUSTOM_DEVICE = { "custom", "Custom"};
|
||||
public final static String[] VERA_DEVICE = { "veraDevice", "Vera Device"};
|
||||
public final static String[] VERA_SCENE = { "veraScene", "Vera Scene"};
|
||||
public final static String[] FIBARO_DEVICE = { "fibaroDevice", "Fibaro Device"};
|
||||
public final static String[] FIBARO_SCENE = { "fibaroScene", "Fibaro Scene"};
|
||||
public final static String[] HARMONY_ACTIVITY = { "harmonyActivity", "Harmony Activity"};
|
||||
public final static String[] HARMONY_BUTTON = { "harmonyButton", "Harmony Button"};
|
||||
public final static String[] NEST_HOMEAWAY = { "nestHomeAway", "Nest Home Status"};
|
||||
@@ -57,6 +59,8 @@ public class DeviceMapTypes {
|
||||
deviceMapTypes.add(UDP_DEVICE);
|
||||
deviceMapTypes.add(VERA_DEVICE);
|
||||
deviceMapTypes.add(VERA_SCENE);
|
||||
deviceMapTypes.add(FIBARO_DEVICE);
|
||||
deviceMapTypes.add(FIBARO_SCENE);
|
||||
deviceMapTypes.add(SOMFY_DEVICE);
|
||||
}
|
||||
public static int getTypeIndex() {
|
||||
|
||||
@@ -2,11 +2,14 @@ package com.bwssystems.HABridge;
|
||||
|
||||
import static spark.Spark.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.devicemanagmeent.*;
|
||||
import com.bwssystems.HABridge.hue.HueMulator;
|
||||
import com.bwssystems.HABridge.plugins.http.HttpClientPool;
|
||||
import com.bwssystems.HABridge.upnp.UpnpListener;
|
||||
import com.bwssystems.HABridge.upnp.UpnpSettingsResource;
|
||||
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||
@@ -39,14 +42,17 @@ public class HABridge {
|
||||
SystemControl theSystem;
|
||||
BridgeSettings bridgeSettings;
|
||||
Version theVersion;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
HttpClientPool thePool;
|
||||
|
||||
theVersion = new Version();
|
||||
// Singleton initialization
|
||||
thePool = new HttpClientPool();
|
||||
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") starting....");
|
||||
|
||||
bridgeSettings = new BridgeSettings();
|
||||
// sparkjava config directive to set html static file location for Jetty
|
||||
staticFileLocation("/public");
|
||||
while(!bridgeSettings.getBridgeControl().isStop()) {
|
||||
bridgeSettings.buildSettings();
|
||||
bridgeSettings.getBridgeSecurity().removeTestUsers();
|
||||
@@ -55,6 +61,8 @@ public class HABridge {
|
||||
ipAddress(bridgeSettings.getBridgeSettingsDescriptor().getWebaddress());
|
||||
// sparkjava config directive to set port for the web server to listen on
|
||||
port(bridgeSettings.getBridgeSettingsDescriptor().getServerPort());
|
||||
staticFileLocation("/public");
|
||||
initExceptionHandler((e) -> HABridge.theExceptionHandler(e, bridgeSettings.getBridgeSettingsDescriptor().getServerPort()));
|
||||
if(!bridgeSettings.getBridgeControl().isReinit())
|
||||
init();
|
||||
bridgeSettings.getBridgeControl().setReinit(false);
|
||||
@@ -72,23 +80,35 @@ public class HABridge {
|
||||
homeManager.buildHomes(bridgeSettings, udpSender);
|
||||
// setup the class to handle the resource setup rest api
|
||||
theResources = new DeviceResource(bridgeSettings, homeManager);
|
||||
// setup the class to handle the upnp response rest api
|
||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
theSettingResponder.setupServer();
|
||||
// setup the class to handle the hue emulator rest api
|
||||
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), homeManager);
|
||||
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), theResources.getGroupRepository(), homeManager);
|
||||
theHueMulator.setupServer();
|
||||
// wait for the sparkjava initialization of the rest api classes to be complete
|
||||
awaitInitialization();
|
||||
|
||||
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().isTraceupnp())
|
||||
log.info("Traceupnp: upnp config address: " + bridgeSettings.getBridgeSettingsDescriptor().getUpnpConfigAddress() + "-useIface:" +
|
||||
bridgeSettings.getBridgeSettingsDescriptor().isUseupnpiface() + " on web server: " +
|
||||
bridgeSettings.getBridgeSettingsDescriptor().getWebaddress() + ":" + bridgeSettings.getBridgeSettingsDescriptor().getServerPort());
|
||||
// setup the class to handle the upnp response rest api
|
||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
theSettingResponder.setupServer();
|
||||
|
||||
// start the upnp ssdp discovery listener
|
||||
theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl(), udpSender);
|
||||
if(theUpnpListener.startListening())
|
||||
theUpnpListener = null;
|
||||
try {
|
||||
theUpnpListener = new UpnpListener(bridgeSettings.getBridgeSettingsDescriptor(), bridgeSettings.getBridgeControl(), udpSender);
|
||||
} catch (IOException e) {
|
||||
log.error("Could not initialize UpnpListener, exiting....", e);
|
||||
theUpnpListener = null;
|
||||
}
|
||||
if(theUpnpListener != null && theUpnpListener.startListening())
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") reinitialization requessted....");
|
||||
else
|
||||
bridgeSettings.getBridgeControl().setStop(true);
|
||||
if(bridgeSettings.getBridgeSettingsDescriptor().isSettingsChanged())
|
||||
bridgeSettings.save(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
log.info("Going to close all homes");
|
||||
homeManager.closeHomes();
|
||||
udpSender.closeResponseSocket();
|
||||
udpSender = null;
|
||||
@@ -98,15 +118,28 @@ public class HABridge {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
log.error("Sleep error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
bridgeSettings.getBridgeSecurity().removeTestUsers();
|
||||
if(bridgeSettings.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettings.updateConfigFile();
|
||||
try {
|
||||
HttpClientPool.shutdown();
|
||||
thePool = null;
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Error shutting down http pool: " + e.getMessage());;
|
||||
} catch (IOException e) {
|
||||
log.warn("Error shutting down http pool: " + e.getMessage());;
|
||||
}
|
||||
log.info("HA Bridge (v" + theVersion.getVersion() + ") exiting....");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private static void theExceptionHandler(Exception e, Integer thePort) {
|
||||
Logger log = LoggerFactory.getLogger(HABridge.class);
|
||||
log.error("Could not start ha-bridge webservice on port [" + thePort + "] due to: " + e.getMessage());
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,9 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.devicemanagmeent.ResourceHandler;
|
||||
import com.bwssystems.HABridge.plugins.NestBridge.NestHome;
|
||||
import com.bwssystems.HABridge.plugins.domoticz.DomoticzHome;
|
||||
@@ -19,9 +22,11 @@ import com.bwssystems.HABridge.plugins.somfy.SomfyHome;
|
||||
import com.bwssystems.HABridge.plugins.tcp.TCPHome;
|
||||
import com.bwssystems.HABridge.plugins.udp.UDPHome;
|
||||
import com.bwssystems.HABridge.plugins.vera.VeraHome;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.FibaroHome;
|
||||
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||
|
||||
public class HomeManager {
|
||||
private static final Logger log = LoggerFactory.getLogger(HomeManager.class);
|
||||
Map<String, Home> homeList;
|
||||
Map<String, Home> resourceList;
|
||||
|
||||
@@ -73,6 +78,8 @@ public class HomeManager {
|
||||
homeList.put(DeviceMapTypes.CUSTOM_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
homeList.put(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the tcp handler Home
|
||||
aHome = new TCPHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.TCP_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
@@ -85,7 +92,11 @@ public class HomeManager {
|
||||
aHome = new VeraHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the Domoticz configuration if available
|
||||
// Setup Fibaro Home if available
|
||||
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
|
||||
aHome = new DomoticzHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
@@ -107,8 +118,10 @@ public class HomeManager {
|
||||
}
|
||||
|
||||
public void closeHomes() {
|
||||
log.info("Manager close homes called....");
|
||||
Collection<Home> theHomes = homeList.values();
|
||||
for(Home aHome : theHomes) {
|
||||
log.info("Closing home: " + aHome.getClass().getCanonicalName());
|
||||
aHome.closeHome();
|
||||
}
|
||||
homeList.clear();
|
||||
|
||||
@@ -10,15 +10,18 @@ public class LinkButtonPressed extends TimerTask {
|
||||
private static final Logger log = LoggerFactory.getLogger(LinkButtonPressed.class);
|
||||
private BridgeControlDescriptor linkDescriptor;
|
||||
private Timer myTimer;
|
||||
private boolean isSilent;
|
||||
|
||||
public LinkButtonPressed(BridgeControlDescriptor theDescriptor, Timer aTimer) {
|
||||
public LinkButtonPressed(BridgeControlDescriptor theDescriptor, Timer aTimer, boolean keepSilent) {
|
||||
linkDescriptor = theDescriptor;
|
||||
myTimer = aTimer;
|
||||
isSilent = keepSilent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.info("Link button time ended....");
|
||||
if(!isSilent)
|
||||
log.info("Link button time ended....");
|
||||
linkDescriptor.setLinkButton(false);
|
||||
myTimer.cancel();
|
||||
}
|
||||
|
||||
20
src/main/java/com/bwssystems/HABridge/LinkParams.java
Normal file
20
src/main/java/com/bwssystems/HABridge/LinkParams.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
public class LinkParams {
|
||||
private Integer seconds;
|
||||
private boolean silent;
|
||||
|
||||
public Integer getSeconds() {
|
||||
return seconds;
|
||||
}
|
||||
public void setSeconds(Integer seconds) {
|
||||
this.seconds = seconds;
|
||||
}
|
||||
public boolean isSilent() {
|
||||
return silent;
|
||||
}
|
||||
public void setSilent(boolean silent) {
|
||||
this.silent = silent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,8 +2,8 @@ package com.bwssystems.HABridge;
|
||||
|
||||
public class NamedIP {
|
||||
private String name;
|
||||
private String ip;
|
||||
private String webhook;
|
||||
private String ip;
|
||||
private String webhook;
|
||||
private String port;
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
@@ -245,10 +245,22 @@ public class SystemControl {
|
||||
});
|
||||
// http://ip_address:port/system/presslinkbutton which sets the link button for device registration
|
||||
put(SYSTEM_CONTEXT + "/presslinkbutton", (request, response) -> {
|
||||
log.info("Link button pressed....");
|
||||
LinkParams linkParams = null;
|
||||
if(!request.body().isEmpty()) {
|
||||
linkParams = new Gson().fromJson(request.body(), LinkParams.class);
|
||||
if(linkParams.getSeconds() <= 0)
|
||||
linkParams.setSeconds(1);
|
||||
}
|
||||
else {
|
||||
linkParams = new LinkParams();
|
||||
linkParams.setSilent(false);
|
||||
linkParams.setSeconds(30);
|
||||
}
|
||||
if(!linkParams.isSilent())
|
||||
log.info("Link button pressed....");
|
||||
bridgeSettings.getBridgeControl().setLinkButton(true);
|
||||
Timer theTimer = new Timer();
|
||||
theTimer.schedule(new LinkButtonPressed(bridgeSettings.getBridgeControl(), theTimer), 30000);
|
||||
theTimer.schedule(new LinkButtonPressed(bridgeSettings.getBridgeControl(), theTimer, linkParams.isSilent()), (linkParams.getSeconds() * 1000));
|
||||
response.status(HttpStatus.SC_OK);
|
||||
response.type("application/json");
|
||||
return "";
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.GroupDescriptor;
|
||||
|
||||
/**
|
||||
* Created by arm on 4/14/15.
|
||||
@@ -14,6 +15,8 @@ public class DeviceResponse {
|
||||
private String luminaireuniqueid;
|
||||
private String uniqueid;
|
||||
private String swversion;
|
||||
private String swconfigid;
|
||||
private String productid;
|
||||
|
||||
public DeviceState getState() {
|
||||
return state;
|
||||
@@ -71,6 +74,23 @@ public class DeviceResponse {
|
||||
this.swversion = swversion;
|
||||
}
|
||||
|
||||
public String getSwconfigid() {
|
||||
return swconfigid;
|
||||
}
|
||||
|
||||
public void setSwconfigid(String swconfigid) {
|
||||
this.swconfigid = swconfigid;
|
||||
}
|
||||
|
||||
public String getProductid() {
|
||||
return productid;
|
||||
}
|
||||
|
||||
public void setProductid(String productid) {
|
||||
this.productid = productid;
|
||||
}
|
||||
|
||||
|
||||
public String getLuminaireuniqueid() {
|
||||
return luminaireuniqueid;
|
||||
}
|
||||
@@ -86,11 +106,41 @@ public class DeviceResponse {
|
||||
response.setName(device.getName());
|
||||
response.setUniqueid(device.getUniqueid());
|
||||
response.setManufacturername("Philips");
|
||||
response.setType("Dimmable light");
|
||||
response.setModelid("LWB004");
|
||||
response.setSwversion("66012040");
|
||||
|
||||
if (device.isColorDevice()) {
|
||||
response.setType("Extended color light");
|
||||
response.setModelid("LCT010");
|
||||
response.setSwversion("1.15.2_r19181");
|
||||
response.setSwconfigid("F921C859");
|
||||
response.setProductid("Philips-LCT010-1-A19ECLv4");
|
||||
} else {
|
||||
response.setType("Dimmable light");
|
||||
response.setModelid("LWB007");
|
||||
response.setSwversion("66012040");
|
||||
}
|
||||
|
||||
response.setLuminaireuniqueid(null);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static DeviceResponse createResponseForVirtualLight(GroupDescriptor group){
|
||||
DeviceResponse response = new DeviceResponse();
|
||||
response.setState(group.getAction());
|
||||
|
||||
response.setName(group.getName());
|
||||
response.setUniqueid("00:17:88:5E:D3:FF-" + String.format("%02X", Integer.parseInt(group.getId())));
|
||||
response.setManufacturername("Philips");
|
||||
response.setType("Extended color light");
|
||||
response.setModelid("LCT010");
|
||||
response.setSwversion("1.15.2_r19181");
|
||||
response.setSwconfigid("F921C859");
|
||||
response.setProductid("Philips-LCT010-1-A19ECLv4");
|
||||
|
||||
response.setLuminaireuniqueid(null);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
// import java.util.ArrayList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -9,14 +9,15 @@ import java.util.List;
|
||||
public class DeviceState {
|
||||
private boolean on;
|
||||
private int bri;
|
||||
private int hue;
|
||||
private int sat;
|
||||
private Integer hue;
|
||||
private Integer sat;
|
||||
private String effect;
|
||||
private int ct;
|
||||
private List<Double> xy;
|
||||
private Integer ct;
|
||||
private String alert;
|
||||
private String colormode;
|
||||
private boolean reachable;
|
||||
private List<Double> xy;
|
||||
|
||||
// private int transitiontime;
|
||||
|
||||
public boolean isOn() {
|
||||
@@ -36,19 +37,21 @@ public class DeviceState {
|
||||
}
|
||||
|
||||
public int getHue() {
|
||||
return hue;
|
||||
return hue != null ? hue.intValue() : 0;
|
||||
}
|
||||
|
||||
public void setHue(int hue) {
|
||||
this.hue = hue;
|
||||
this.colormode = "hs";
|
||||
}
|
||||
|
||||
public int getSat() {
|
||||
return sat;
|
||||
return sat != null ? sat.intValue() : 0;
|
||||
}
|
||||
|
||||
public void setSat(int sat) {
|
||||
this.sat = sat;
|
||||
this.colormode = "hs";
|
||||
}
|
||||
|
||||
public String getEffect() {
|
||||
@@ -60,11 +63,12 @@ public class DeviceState {
|
||||
}
|
||||
|
||||
public int getCt() {
|
||||
return ct;
|
||||
return ct != null ? ct.intValue() : 0;
|
||||
}
|
||||
|
||||
public void setCt(int ct) {
|
||||
this.ct = ct;
|
||||
this.colormode = "ct";
|
||||
}
|
||||
|
||||
public String getAlert() {
|
||||
@@ -97,6 +101,7 @@ public class DeviceState {
|
||||
|
||||
public void setXy(List<Double> xy) {
|
||||
this.xy = xy;
|
||||
this.colormode = "xy";
|
||||
}
|
||||
// public int getTransitiontime() {
|
||||
// return transitiontime;
|
||||
@@ -106,22 +111,28 @@ public class DeviceState {
|
||||
// this.transitiontime = transitiontime;
|
||||
// }
|
||||
|
||||
public static DeviceState createDeviceState() {
|
||||
public static DeviceState createDeviceState(boolean color) {
|
||||
DeviceState newDeviceState = new DeviceState();
|
||||
newDeviceState.fillIn();
|
||||
// newDeviceState.setColormode("none");
|
||||
// ArrayList<Double> doubleArray = new ArrayList<Double>();
|
||||
// doubleArray.add(new Double(0));
|
||||
// doubleArray.add(new Double(0));
|
||||
// newDeviceState.setXy(doubleArray);
|
||||
|
||||
newDeviceState.fillIn(color);
|
||||
if (color) {
|
||||
newDeviceState.setColormode("xy");
|
||||
newDeviceState.setHue(0);
|
||||
newDeviceState.setSat(0);
|
||||
newDeviceState.setCt(153);
|
||||
ArrayList<Double> doubleArray = new ArrayList<Double>();
|
||||
doubleArray.add(0.3146);
|
||||
doubleArray.add(0.3303);
|
||||
newDeviceState.setXy(doubleArray);
|
||||
}
|
||||
return newDeviceState;
|
||||
}
|
||||
public void fillIn() {
|
||||
public void fillIn(boolean color) {
|
||||
if(this.getAlert() == null)
|
||||
this.setAlert("none");
|
||||
if(this.getEffect() == null)
|
||||
this.setEffect("none");
|
||||
if (color) {
|
||||
if(this.getEffect() == null)
|
||||
this.setEffect("none");
|
||||
}
|
||||
this.setReachable(true);
|
||||
}
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GroupClassTypes {
|
||||
|
||||
public final static String BATHROOM = "Bathroom";
|
||||
public final static String BEDROOM = "Bedroom";
|
||||
public final static String CARPORT = "Carport";
|
||||
public final static String DINING = "Dining";
|
||||
public final static String DRIVEWAY = "Driveway";
|
||||
public final static String FRONT_DOOR = "Front door";
|
||||
public final static String GARAGE = "Garage";
|
||||
public final static String GARDEN = "Garden";
|
||||
public final static String GYM = "Gym";
|
||||
public final static String HALLWAY = "Hallway";
|
||||
public final static String BEDROOM_KIDS = "Kids bedroom";
|
||||
public final static String KITCHEN = "Kitchen";
|
||||
public final static String LIVING_ROOM = "Living room";
|
||||
public final static String NURSERY = "Nursery";
|
||||
public final static String OFFICE = "Office";
|
||||
public final static String OTHER = "Other";
|
||||
public final static String RECREATION = "Recreation";
|
||||
public final static String TERRACE = "Terrace";
|
||||
public final static String TOILET = "Toilet";
|
||||
|
||||
ArrayList<String> groupClassTypes;
|
||||
|
||||
public GroupClassTypes() {
|
||||
groupClassTypes = new ArrayList<String>();
|
||||
groupClassTypes.add(BATHROOM);
|
||||
groupClassTypes.add(BEDROOM);
|
||||
groupClassTypes.add(CARPORT);
|
||||
groupClassTypes.add(DINING);
|
||||
groupClassTypes.add(DRIVEWAY);
|
||||
groupClassTypes.add(FRONT_DOOR);
|
||||
groupClassTypes.add(GARAGE);
|
||||
groupClassTypes.add(GARDEN);
|
||||
groupClassTypes.add(GYM);
|
||||
groupClassTypes.add(HALLWAY);
|
||||
groupClassTypes.add(BEDROOM_KIDS);
|
||||
groupClassTypes.add(KITCHEN);
|
||||
groupClassTypes.add(LIVING_ROOM);
|
||||
groupClassTypes.add(NURSERY);
|
||||
groupClassTypes.add(OFFICE);
|
||||
groupClassTypes.add(OTHER);
|
||||
groupClassTypes.add(RECREATION);
|
||||
groupClassTypes.add(TERRACE);
|
||||
groupClassTypes.add(TOILET);
|
||||
}
|
||||
|
||||
public Boolean validateType(String type) {
|
||||
if(type == null || type.trim().isEmpty())
|
||||
return false;
|
||||
for(String classType : groupClassTypes) {
|
||||
if(type.trim().contentEquals(classType))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.GroupDescriptor;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class GroupResponse {
|
||||
@@ -16,6 +16,8 @@ public class GroupResponse {
|
||||
private String type;
|
||||
@SerializedName("class")
|
||||
String class_name;
|
||||
@SerializedName("state")
|
||||
private GroupState state;
|
||||
|
||||
public DeviceState getAction() {
|
||||
return action;
|
||||
@@ -23,6 +25,14 @@ public class GroupResponse {
|
||||
public void setAction(DeviceState action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public GroupState getState() {
|
||||
return state;
|
||||
}
|
||||
public void setState(GroupState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String[] getLights() {
|
||||
return lights;
|
||||
}
|
||||
@@ -48,34 +58,69 @@ public class GroupResponse {
|
||||
public void setClass_name(String class_name) {
|
||||
this.class_name = class_name;
|
||||
}
|
||||
public static GroupResponse createDefaultGroupResponse(List<DeviceDescriptor> deviceList) {
|
||||
String[] theList = new String[deviceList.size()];
|
||||
int i = 0;
|
||||
for (DeviceDescriptor device : deviceList) {
|
||||
theList[i] = device.getId();
|
||||
i++;
|
||||
}
|
||||
GroupResponse theResponse = new GroupResponse();
|
||||
theResponse.setAction(DeviceState.createDeviceState());
|
||||
theResponse.setName("Lightset 0");
|
||||
theResponse.setLights(theList);
|
||||
theResponse.setType("LightGroup");
|
||||
return theResponse;
|
||||
}
|
||||
public static GroupResponse createOtherGroupResponse(List<DeviceDescriptor> deviceList) {
|
||||
String[] theList = new String[deviceList.size()];
|
||||
int i = 0;
|
||||
for (DeviceDescriptor device : deviceList) {
|
||||
theList[i] = device.getId();
|
||||
i++;
|
||||
}
|
||||
GroupResponse theResponse = new GroupResponse();
|
||||
theResponse.setAction(DeviceState.createDeviceState());
|
||||
theResponse.setName("AGroup");
|
||||
theResponse.setLights(theList);
|
||||
theResponse.setType("Room");
|
||||
theResponse.setClass_name("Other");
|
||||
|
||||
public static GroupResponse createDefaultGroupResponse(Map<String, DeviceResponse> deviceList) {
|
||||
String[] theList = new String[deviceList.size()];
|
||||
Boolean all_on = true;
|
||||
Boolean any_on = false;
|
||||
int i = 0;
|
||||
for (Map.Entry<String, DeviceResponse> device : deviceList.entrySet()) {
|
||||
if (Integer.parseInt(device.getKey()) >= 10000) { // don't show fake lights for other groups
|
||||
continue;
|
||||
}
|
||||
theList[i] = device.getKey();
|
||||
Boolean is_on = device.getValue().getState().isOn();
|
||||
if (is_on)
|
||||
any_on = true;
|
||||
else
|
||||
all_on = false;
|
||||
i++;
|
||||
}
|
||||
GroupResponse theResponse = new GroupResponse();
|
||||
theResponse.setAction(DeviceState.createDeviceState(true));
|
||||
theResponse.setState(new GroupState(all_on, any_on));
|
||||
theResponse.setName("Group 0");
|
||||
theResponse.setLights(theList);
|
||||
theResponse.setType("LightGroup");
|
||||
return theResponse;
|
||||
}
|
||||
|
||||
return theResponse;
|
||||
}
|
||||
public static GroupResponse createResponse(GroupDescriptor group, Map<String, DeviceResponse> lights){
|
||||
GroupResponse response = new GroupResponse();
|
||||
Boolean all_on = true;
|
||||
Boolean any_on = false;
|
||||
String[] groupLights = null;
|
||||
if (lights == null) {
|
||||
all_on = false;
|
||||
groupLights = group.getLights();
|
||||
} else {
|
||||
for (DeviceResponse light : lights.values()) {
|
||||
Boolean is_on = light.getState().isOn();
|
||||
if (is_on)
|
||||
any_on = true;
|
||||
else
|
||||
all_on = false;
|
||||
}
|
||||
|
||||
// group.getLights() is not filtered by requester, lights is
|
||||
// we want the filtered version but keep the order from group.getLights()
|
||||
groupLights = new String[lights.size()];
|
||||
int i = 0;
|
||||
for (String light : group.getLights()) {
|
||||
if (lights.keySet().contains(light)) {
|
||||
groupLights[i] = light;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.setState(new GroupState(all_on, any_on));
|
||||
response.setAction(group.getAction());
|
||||
response.setName(group.getName());
|
||||
response.setType(group.getGroupType());
|
||||
response.setLights(groupLights);
|
||||
response.setClass_name(group.getGroupClass());
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
/**
|
||||
* Created by Florian Foerderreuther on 07/23/17
|
||||
*/
|
||||
public class GroupState {
|
||||
private boolean all_on;
|
||||
private boolean any_on;
|
||||
|
||||
public boolean isAllOn() {
|
||||
return all_on;
|
||||
}
|
||||
|
||||
public boolean isAnyOn() {
|
||||
return any_on;
|
||||
}
|
||||
|
||||
public void setState(boolean all_on, boolean any_on) {
|
||||
this.all_on = all_on;
|
||||
this.any_on = any_on;
|
||||
}
|
||||
|
||||
public GroupState(boolean all_on, boolean any_on) {
|
||||
this.all_on = all_on;
|
||||
this.any_on = any_on;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GroupState{" +
|
||||
"all_on=" + all_on +
|
||||
", any_on=" + any_on +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,9 @@ public class HueApiResponse {
|
||||
private Map<String, JsonObject> rules;
|
||||
private HueConfig config;
|
||||
|
||||
public HueApiResponse(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed) {
|
||||
public HueApiResponse(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed, String emulateMAC) {
|
||||
super();
|
||||
this.setConfig(HueConfig.createConfig(name, ipaddress, awhitelist, emulateHubVersion, isLinkButtonPressed));
|
||||
this.setConfig(HueConfig.createConfig(name, ipaddress, awhitelist, emulateHubVersion, isLinkButtonPressed, emulateMAC));
|
||||
this.setRules(new HashMap<>());
|
||||
this.setSensors(new HashMap<>());
|
||||
this.setSchedules(new HashMap<>());
|
||||
|
||||
@@ -34,7 +34,7 @@ public class HueConfig
|
||||
private String replacesbridgeid;
|
||||
private Map<String, WhitelistEntry> whitelist;
|
||||
|
||||
public static HueConfig createConfig(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed) {
|
||||
public static HueConfig createConfig(String name, String ipaddress, Map<String, WhitelistEntry> awhitelist, String emulateHubVersion, boolean isLinkButtonPressed, String emulateMAC) {
|
||||
HueConfig aConfig = new HueConfig();
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
@@ -56,7 +56,7 @@ public class HueConfig
|
||||
aConfig.setLocaltime(dateFormat.format(new Date()));
|
||||
aConfig.setTimezone(TimeZone.getDefault().getID());
|
||||
aConfig.setZigbeechannel("6");
|
||||
aConfig.setBridgeid(HuePublicConfig.createConfig(name, ipaddress, emulateHubVersion).getHueBridgeIdFromMac());
|
||||
aConfig.setBridgeid(HuePublicConfig.createConfig(name, ipaddress, emulateHubVersion, emulateMAC).getHueBridgeIdFromMac());
|
||||
aConfig.setModelid(HueConstants.MODEL_ID);
|
||||
aConfig.setFactorynew(false);
|
||||
aConfig.setReplacesbridgeid(null);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.bwssystems.HABridge.api.hue;
|
||||
|
||||
public class HueConstants {
|
||||
public final static String HUB_VERSION = "1705121051";
|
||||
public final static String HUB_VERSION = "9999999999";
|
||||
public final static String API_VERSION = "1.19.0";
|
||||
public final static String MODEL_ID = "BSB002";
|
||||
public final static String UUID_PREFIX = "2f402f80-da50-11e1-9b23-";
|
||||
|
||||
@@ -18,9 +18,9 @@ public class HuePublicConfig
|
||||
private Boolean factorynew;
|
||||
private String modelid;
|
||||
|
||||
public static HuePublicConfig createConfig(String name, String ipaddress, String emulateHubVersion) {
|
||||
public static HuePublicConfig createConfig(String name, String ipaddress, String emulateHubVersion, String emulateMAC) {
|
||||
HuePublicConfig aConfig = new HuePublicConfig();
|
||||
aConfig.setMac(HuePublicConfig.getMacAddress(ipaddress));
|
||||
aConfig.setMac(HuePublicConfig.getMacAddress(ipaddress, emulateMAC));
|
||||
aConfig.setApiversion(HueConstants.API_VERSION);
|
||||
aConfig.setSwversion(emulateHubVersion);
|
||||
aConfig.setName(name);
|
||||
@@ -32,34 +32,39 @@ public class HuePublicConfig
|
||||
return aConfig;
|
||||
}
|
||||
|
||||
private static String getMacAddress(String addr)
|
||||
private static String getMacAddress(String addr, String aMAC)
|
||||
{
|
||||
InetAddress ip;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
if(aMAC == null || aMAC.trim().length() <= 0) {
|
||||
try {
|
||||
|
||||
ip = InetAddress.getByName(addr);
|
||||
|
||||
ip = InetAddress.getByName(addr);
|
||||
|
||||
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
||||
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
|
||||
|
||||
byte[] mac = network.getHardwareAddress();
|
||||
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : ""));
|
||||
}
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
|
||||
byte[] mac = network.getHardwareAddress();
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
} catch (SocketException e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
} catch (Exception e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? ":" : ""));
|
||||
}
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
} catch (SocketException e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
} catch (Exception e){
|
||||
|
||||
sb.append("00:00:88:00:bb:ee");
|
||||
|
||||
}
|
||||
else {
|
||||
sb.append(aMAC.trim());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -38,6 +38,9 @@ public class DeviceDescriptor{
|
||||
@SerializedName("onUrl")
|
||||
@Expose
|
||||
private String onUrl;
|
||||
@SerializedName("colorUrl")
|
||||
@Expose
|
||||
private String colorUrl;
|
||||
@SerializedName("headers")
|
||||
@Expose
|
||||
private String headers;
|
||||
@@ -142,6 +145,14 @@ public class DeviceDescriptor{
|
||||
this.onUrl = onUrl;
|
||||
}
|
||||
|
||||
public String getColorUrl() {
|
||||
return colorUrl;
|
||||
}
|
||||
|
||||
public void setColorUrl(String colorUrl) {
|
||||
this.colorUrl = colorUrl;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -208,7 +219,7 @@ public class DeviceDescriptor{
|
||||
|
||||
public DeviceState getDeviceState() {
|
||||
if(deviceState == null)
|
||||
deviceState = DeviceState.createDeviceState();
|
||||
deviceState = DeviceState.createDeviceState(this.isColorDevice());
|
||||
return deviceState;
|
||||
}
|
||||
|
||||
@@ -282,7 +293,22 @@ public class DeviceDescriptor{
|
||||
|
||||
if(this.offUrl != null && this.offUrl.contains(aType))
|
||||
return true;
|
||||
|
||||
if(this.colorUrl != null && this.colorUrl.contains(aType))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isColorDevice() {
|
||||
boolean color = true;
|
||||
if ((deviceType == null || !deviceType.trim().equals("passthru")) && (colorUrl == null || colorUrl.trim().equals(""))) {
|
||||
color = false;
|
||||
} else if (deviceType != null && deviceType.trim().equals("passthru")) {
|
||||
if (deviceState != null && (deviceState.getColormode() == null || deviceState.getColormode().equals(""))) {
|
||||
color = false;
|
||||
}
|
||||
}
|
||||
return color;
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,21 @@ import javax.xml.bind.DatatypeConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.util.BackupHandler;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/*
|
||||
* This is an in memory list to manage the configured devices and saves the list as a JSON string to a file for later
|
||||
* loading.
|
||||
@@ -86,6 +94,10 @@ public class DeviceRepository extends BackupHandler {
|
||||
|
||||
public List<DeviceDescriptor> findAllByRequester(String anAddress) {
|
||||
List<DeviceDescriptor> list = new ArrayList<DeviceDescriptor>(devices.values());
|
||||
return findAllByRequester(anAddress, list);
|
||||
}
|
||||
|
||||
private List<DeviceDescriptor> findAllByRequester(String anAddress, Collection<DeviceDescriptor> list) {
|
||||
List<DeviceDescriptor> theReturnList = new ArrayList<DeviceDescriptor>();
|
||||
Iterator<DeviceDescriptor> anIterator = list.iterator();
|
||||
DeviceDescriptor theDevice;
|
||||
@@ -111,6 +123,45 @@ public class DeviceRepository extends BackupHandler {
|
||||
return theReturnList;
|
||||
}
|
||||
|
||||
public Map<String, DeviceResponse> findAllByGroupWithState(String[] lightsInGroup, String anAddress, HueHome myHueHome, Gson aGsonBuilder) {
|
||||
return findAllByGroupWithState(lightsInGroup, anAddress, myHueHome, aGsonBuilder, false);
|
||||
}
|
||||
|
||||
public Map<String, DeviceResponse> findAllByGroupWithState(String[] lightsInGroup, String anAddress, HueHome myHueHome, Gson aGsonBuilder, boolean ignoreAddress) {
|
||||
Map<String, DeviceResponse> deviceResponseMap = new HashMap<String, DeviceResponse>();
|
||||
Map<String, DeviceDescriptor> lights = new HashMap<String, DeviceDescriptor>(devices);
|
||||
lights.keySet().retainAll(Arrays.asList(lightsInGroup));
|
||||
for (DeviceDescriptor light : (ignoreAddress ? lights.values() : findAllByRequester(anAddress, lights.values()))) {
|
||||
DeviceResponse deviceResponse = null;
|
||||
if(!light.isInactive()) {
|
||||
if (light.containsType(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
CallItem[] callItems = null;
|
||||
try {
|
||||
if(light.getOnUrl() != null)
|
||||
callItems = aGsonBuilder.fromJson(light.getOnUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
log.warn("Could not decode Json for url items to get Hue state for device: " + light.getName());
|
||||
callItems = null;
|
||||
}
|
||||
|
||||
for (int i = 0; callItems != null && i < callItems.length; i++) {
|
||||
if((callItems[i].getType() != null && callItems[i].getType().equals(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex])) ||
|
||||
(callItems[i].getItem() != null && callItems[i].getItem().getAsString() != null && callItems[i].getItem().getAsString().contains("hueName"))) {
|
||||
deviceResponse = myHueHome.getHueDeviceInfo(callItems[i], light);
|
||||
i = callItems.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceResponse == null) {
|
||||
deviceResponse = DeviceResponse.createResponse(light);
|
||||
}
|
||||
deviceResponseMap.put(light.getId(), deviceResponse);
|
||||
}
|
||||
}
|
||||
return (deviceResponseMap.size() == 0) ? null : deviceResponseMap;
|
||||
}
|
||||
|
||||
public DeviceDescriptor findOne(String id) {
|
||||
return devices.get(id);
|
||||
}
|
||||
|
||||
147
src/main/java/com/bwssystems/HABridge/dao/GroupDescriptor.java
Normal file
147
src/main/java/com/bwssystems/HABridge/dao/GroupDescriptor.java
Normal file
@@ -0,0 +1,147 @@
|
||||
package com.bwssystems.HABridge.dao;
|
||||
|
||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.bwssystems.HABridge.api.hue.GroupState;
|
||||
|
||||
/*
|
||||
* Object to handle the device configuration
|
||||
*/
|
||||
public class GroupDescriptor{
|
||||
@SerializedName("id")
|
||||
@Expose
|
||||
private String id;
|
||||
@SerializedName("name")
|
||||
@Expose
|
||||
private String name;
|
||||
@SerializedName("groupType")
|
||||
@Expose
|
||||
private String groupType;
|
||||
@SerializedName("groupClass")
|
||||
@Expose
|
||||
private String groupClass;
|
||||
@SerializedName("requesterAddress")
|
||||
@Expose
|
||||
private String requesterAddress;
|
||||
@SerializedName("inactive")
|
||||
@Expose
|
||||
private boolean inactive;
|
||||
@SerializedName("description")
|
||||
@Expose
|
||||
private String description;
|
||||
@SerializedName("comments")
|
||||
@Expose
|
||||
private String comments;
|
||||
|
||||
private DeviceState action;
|
||||
private GroupState groupState;
|
||||
|
||||
@SerializedName("lights")
|
||||
@Expose
|
||||
private String[] lights;
|
||||
@SerializedName("exposeAsLight")
|
||||
@Expose
|
||||
private String exposeAsLight;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getGroupType() {
|
||||
return groupType;
|
||||
}
|
||||
|
||||
public void setGroupType(String groupType) {
|
||||
this.groupType = groupType;
|
||||
}
|
||||
|
||||
public String getGroupClass() {
|
||||
return groupClass;
|
||||
}
|
||||
|
||||
public void setGroupClass(String groupClass) {
|
||||
this.groupClass = groupClass;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public GroupState getGroupState() {
|
||||
if(groupState == null)
|
||||
groupState = new GroupState(false,false);
|
||||
return groupState;
|
||||
}
|
||||
|
||||
public void setGroupState(GroupState groupState) {
|
||||
this.groupState = groupState;
|
||||
}
|
||||
|
||||
public DeviceState getAction() {
|
||||
if(action == null)
|
||||
action = DeviceState.createDeviceState(true);
|
||||
return action;
|
||||
}
|
||||
|
||||
public void setAction(DeviceState action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public boolean isInactive() {
|
||||
return inactive;
|
||||
}
|
||||
|
||||
public void setInactive(boolean inactive) {
|
||||
this.inactive = inactive;
|
||||
}
|
||||
|
||||
public String getRequesterAddress() {
|
||||
return requesterAddress;
|
||||
}
|
||||
|
||||
public void setRequesterAddress(String requesterAddress) {
|
||||
this.requesterAddress = requesterAddress;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void setComments(String comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
public String[] getLights() {
|
||||
return lights;
|
||||
}
|
||||
|
||||
public void setLights(String[] lights) {
|
||||
this.lights = lights;
|
||||
}
|
||||
|
||||
public void setExposeAsLight(String exposeFor) {
|
||||
this.exposeAsLight = exposeFor;
|
||||
}
|
||||
|
||||
public String getExposeAsLight() {
|
||||
return exposeAsLight;
|
||||
}
|
||||
}
|
||||
220
src/main/java/com/bwssystems/HABridge/dao/GroupRepository.java
Normal file
220
src/main/java/com/bwssystems/HABridge/dao/GroupRepository.java
Normal file
@@ -0,0 +1,220 @@
|
||||
package com.bwssystems.HABridge.dao;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.dao.GroupDescriptor;
|
||||
import com.bwssystems.HABridge.util.BackupHandler;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.util.List;
|
||||
/*
|
||||
* This is an in memory list to manage the configured groups and saves the list as a JSON string to a file for later
|
||||
* loading.
|
||||
*/
|
||||
public class GroupRepository extends BackupHandler {
|
||||
private Map<String, GroupDescriptor> groups;
|
||||
private Path repositoryPath;
|
||||
private Gson gson;
|
||||
private Integer nextId;
|
||||
private Logger log = LoggerFactory.getLogger(GroupRepository.class);
|
||||
|
||||
public GroupRepository(String groupDb) {
|
||||
super();
|
||||
gson =
|
||||
new GsonBuilder()
|
||||
.excludeFieldsWithoutExposeAnnotation()
|
||||
.create();
|
||||
nextId = 0;
|
||||
try {
|
||||
repositoryPath = null;
|
||||
repositoryPath = Paths.get(groupDb);
|
||||
setupParams(repositoryPath, ".bk", "group.db-");
|
||||
_loadRepository(repositoryPath);
|
||||
} catch (Exception ex) {
|
||||
groups = new HashMap<String, GroupDescriptor>();
|
||||
}
|
||||
}
|
||||
|
||||
public void loadRepository() {
|
||||
if(repositoryPath != null)
|
||||
_loadRepository(repositoryPath);
|
||||
}
|
||||
private void _loadRepository(Path aPath){
|
||||
String jsonContent = repositoryReader(aPath);
|
||||
groups = new HashMap<String, GroupDescriptor>();
|
||||
|
||||
if(jsonContent != null)
|
||||
{
|
||||
GroupDescriptor list[] = gson.fromJson(jsonContent, GroupDescriptor[].class);
|
||||
for(int i = 0; i < list.length; i++) {
|
||||
list[i].setGroupState(null);
|
||||
put(list[i].getId(), list[i]);
|
||||
if(Integer.decode(list[i].getId()) > nextId) {
|
||||
nextId = Integer.decode(list[i].getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findAll() {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>(groups.values());
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findActive() {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>();
|
||||
for(GroupDescriptor aGroup : new ArrayList<GroupDescriptor>(groups.values())) {
|
||||
if(!aGroup.isInactive())
|
||||
list.add(aGroup);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findAllByRequester(String anAddress) {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>(groups.values());
|
||||
List<GroupDescriptor> theReturnList = new ArrayList<GroupDescriptor>();
|
||||
Iterator<GroupDescriptor> anIterator = list.iterator();
|
||||
GroupDescriptor theGroup;
|
||||
String theRequesterAddress;
|
||||
|
||||
HashMap<String,String > addressMap;
|
||||
while (anIterator.hasNext()) {
|
||||
theGroup = anIterator.next();
|
||||
theRequesterAddress = theGroup.getRequesterAddress();
|
||||
addressMap = new HashMap<String, String>();
|
||||
if(theRequesterAddress != null) {
|
||||
if (theRequesterAddress.contains(",")) {
|
||||
String[] theArray = theRequesterAddress.split(",");
|
||||
for (String v : theArray) {
|
||||
addressMap.put(v.trim(), v.trim());
|
||||
}
|
||||
} else
|
||||
addressMap.put(theRequesterAddress, theRequesterAddress);
|
||||
}
|
||||
if (theRequesterAddress == null || theRequesterAddress.length() == 0 || addressMap.containsKey(anAddress))
|
||||
theReturnList.add(theGroup);
|
||||
}
|
||||
return theReturnList;
|
||||
}
|
||||
|
||||
public List<GroupDescriptor> findVirtualLights(String anAddress) {
|
||||
List<GroupDescriptor> list = new ArrayList<GroupDescriptor>();
|
||||
for (GroupDescriptor group : groups.values()) {
|
||||
String expose = group.getExposeAsLight();
|
||||
if (expose != null && expose.contains(anAddress)) {
|
||||
list.add(group);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public GroupDescriptor findOne(String id) {
|
||||
return groups.get(id);
|
||||
}
|
||||
|
||||
private void put(String id, GroupDescriptor aDescriptor) {
|
||||
groups.put(id, aDescriptor);
|
||||
}
|
||||
|
||||
public void save() {
|
||||
save(groups.values().toArray(new GroupDescriptor[0]));
|
||||
}
|
||||
|
||||
public void save(GroupDescriptor[] descriptors) {
|
||||
String theNames = "";
|
||||
for(int i = 0; i < descriptors.length; i++) {
|
||||
if(descriptors[i].getId() != null && descriptors[i].getId().length() > 0)
|
||||
groups.remove(descriptors[i].getId());
|
||||
else {
|
||||
nextId++;
|
||||
descriptors[i].setId(String.valueOf(nextId));
|
||||
}
|
||||
|
||||
put(descriptors[i].getId(), descriptors[i]);
|
||||
theNames = theNames + " " + descriptors[i].getName() + ", ";
|
||||
}
|
||||
String jsonValue = gson.toJson(findAll());
|
||||
repositoryWriter(jsonValue, repositoryPath);
|
||||
log.debug("Save group(s): " + theNames);
|
||||
}
|
||||
|
||||
public Integer getNewId() {
|
||||
return nextId + 1;
|
||||
}
|
||||
|
||||
public String delete(GroupDescriptor aDescriptor) {
|
||||
if (aDescriptor != null) {
|
||||
groups.remove(aDescriptor.getId());
|
||||
JsonTransformer aRenderer = new JsonTransformer();
|
||||
String jsonValue = aRenderer.render(findAll());
|
||||
repositoryWriter(jsonValue, repositoryPath);
|
||||
return "Group with id '" + aDescriptor.getId() + "' deleted";
|
||||
} else {
|
||||
return "Group not found";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void repositoryWriter(String content, Path filePath) {
|
||||
if(Files.exists(filePath) && !Files.isWritable(filePath)){
|
||||
log.error("Error file is not writable: " + filePath);
|
||||
return;
|
||||
}
|
||||
|
||||
if(Files.notExists(filePath.getParent())) {
|
||||
try {
|
||||
Files.createDirectories(filePath.getParent());
|
||||
} catch (IOException e) {
|
||||
log.error("Error creating the directory: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Path target = null;
|
||||
if(Files.exists(filePath)) {
|
||||
target = FileSystems.getDefault().getPath(filePath.getParent().toString(), "group.db.old");
|
||||
Files.move(filePath, target);
|
||||
}
|
||||
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE);
|
||||
if(target != null)
|
||||
Files.delete(target);
|
||||
} catch (IOException e) {
|
||||
log.error("Error writing the file: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String repositoryReader(Path filePath) {
|
||||
|
||||
String content = null;
|
||||
if(Files.notExists(filePath) || !Files.isReadable(filePath)){
|
||||
log.warn("Error reading the file: " + filePath + " - Does not exist or is not readable. continuing...");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
content = new String(Files.readAllBytes(filePath));
|
||||
} catch (IOException e) {
|
||||
log.error("Error reading the file: " + filePath + " message: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.BackupFilename;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.dao.DeviceRepository;
|
||||
import com.bwssystems.HABridge.dao.GroupRepository;
|
||||
import com.bwssystems.HABridge.dao.ErrorMessage;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
@@ -38,6 +39,7 @@ public class DeviceResource {
|
||||
private static final String API_CONTEXT = "/api/devices";
|
||||
private static final Logger log = LoggerFactory.getLogger(DeviceResource.class);
|
||||
private DeviceRepository deviceRepository;
|
||||
private GroupRepository groupRepository;
|
||||
private HomeManager homeManager;
|
||||
private BridgeSettings bridgeSettings;
|
||||
private Gson aGsonHandler;
|
||||
@@ -46,6 +48,7 @@ public class DeviceResource {
|
||||
public DeviceResource(BridgeSettings theSettings, HomeManager aHomeManager) {
|
||||
bridgeSettings = theSettings;
|
||||
this.deviceRepository = new DeviceRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpDeviceDb());
|
||||
this.groupRepository = new GroupRepository(bridgeSettings.getBridgeSettingsDescriptor().getUpnpGroupDb());
|
||||
homeManager = aHomeManager;
|
||||
aGsonHandler = new GsonBuilder().create();
|
||||
setupEndpoints();
|
||||
@@ -55,6 +58,10 @@ public class DeviceResource {
|
||||
return deviceRepository;
|
||||
}
|
||||
|
||||
public GroupRepository getGroupRepository() {
|
||||
return groupRepository;
|
||||
}
|
||||
|
||||
private void setupEndpoints() {
|
||||
log.info("HABridge device management service started.... ");
|
||||
before(API_CONTEXT + "/*", (request, response) -> {
|
||||
@@ -84,6 +91,7 @@ public class DeviceResource {
|
||||
else {
|
||||
devices = new Gson().fromJson("[" + request.body() + "]", DeviceDescriptor[].class);
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
CallItem[] callItems = null;
|
||||
String errorMessage = null;
|
||||
for(int i = 0; i < devices.length; i++) {
|
||||
@@ -122,6 +130,15 @@ public class DeviceResource {
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
try {
|
||||
if(devices[i].getColorUrl() != null && !devices[i].getColorUrl().isEmpty())
|
||||
callItems = aGsonHandler.fromJson(devices[i].getColorUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||
errorMessage = "Bad color URL JSON in create device(s) for name: " + devices[i].getName() + " with color URL: " + devices[i].getColorUrl();
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
deviceRepository.save(devices);
|
||||
@@ -214,6 +231,18 @@ public class DeviceResource {
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.VERA_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.VERA_SCENE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/fibaro/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get fibaro devices");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/fibaro/scenes", "application/json", (request, response) -> {
|
||||
log.debug("Get fibaro scenes");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/harmony/activities", "application/json", (request, response) -> {
|
||||
log.debug("Get harmony activities");
|
||||
|
||||
22
src/main/java/com/bwssystems/HABridge/hue/ColorData.java
Normal file
22
src/main/java/com/bwssystems/HABridge/hue/ColorData.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
public class ColorData {
|
||||
public enum ColorMode { XY, CT, HS}
|
||||
|
||||
private ColorMode mode;
|
||||
private Object data;
|
||||
|
||||
public ColorData(ColorMode mode, Object value) {
|
||||
this.mode = mode;
|
||||
this.data = value;
|
||||
}
|
||||
|
||||
public Object getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public ColorMode getColorMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,234 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
|
||||
public class ColorDecode {
|
||||
private static final Logger log = LoggerFactory.getLogger(ColorDecode.class);
|
||||
private static final String COLOR_R = "${color.r}";
|
||||
private static final String COLOR_G = "${color.g}";
|
||||
private static final String COLOR_B = "${color.b}";
|
||||
private static final Pattern COLOR_MILIGHT = Pattern.compile("\\$\\{color.milight\\:([01234])\\}");
|
||||
|
||||
public static String convertCIEtoRGB(List<Double> xy) {
|
||||
double x;
|
||||
double y;
|
||||
double Y;
|
||||
public static List<Integer> convertCIEtoRGB(List<Double> xy, int brightness) {
|
||||
List<Integer> rgb;
|
||||
double x = xy.get(0); // the given x value
|
||||
double y = xy.get(1); // the given y value
|
||||
double z = 1.0 - x - y;
|
||||
double Y = (double)brightness/(double)254.00; // The given brightness value
|
||||
double X = (Y / y) * x;
|
||||
double Z = (Y / y) * z;
|
||||
|
||||
double r = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
||||
double g = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
|
||||
double b = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
|
||||
|
||||
if (r > b && r > g && r > 1.0) {
|
||||
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
else if (g > b && g > r && g > 1.0) {
|
||||
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
else if (b > r && b > g && b > 1.0) {
|
||||
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
|
||||
|
||||
r = r <= 0.0031308 ? 12.92 * r : (1.0 + 0.055) * Math.pow(r, (1.0 / 2.4)) - 0.055;
|
||||
g = g <= 0.0031308 ? 12.92 * g : (1.0 + 0.055) * Math.pow(g, (1.0 / 2.4)) - 0.055;
|
||||
b = b <= 0.0031308 ? 12.92 * b : (1.0 + 0.055) * Math.pow(b, (1.0 / 2.4)) - 0.055;
|
||||
|
||||
x = xy.get(0) * 100;
|
||||
y = xy.get(1) * 100;
|
||||
Y= y;
|
||||
double R = 3.240479*((x*Y)/y) + -1.537150*Y + -0.498535*(((1-x-y)*Y)/y);
|
||||
double G = -0.969256*((x*Y)/y) + 1.875992*Y + 0.041556*(((1-x-y)*Y)/y);
|
||||
double B = 0.055648*((x*Y)/y) + -0.204043*Y + 1.057311*(((1-x-y)*Y)/y);
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
if (r > 1.0) {
|
||||
g = g / r;
|
||||
b = b / r;
|
||||
r = 1.0;
|
||||
}
|
||||
}
|
||||
else if (g > b && g > r) {
|
||||
// green is biggest
|
||||
if (g > 1.0) {
|
||||
r = r / g;
|
||||
b = b / g;
|
||||
g = 1.0;
|
||||
}
|
||||
}
|
||||
else if (b > r && b > g) {
|
||||
// blue is biggest
|
||||
if (b > 1.0) {
|
||||
r = r / b;
|
||||
g = g / b;
|
||||
b = 1.0;
|
||||
}
|
||||
}
|
||||
if(r < 0.0)
|
||||
r = 0;
|
||||
if(g < 0.0)
|
||||
g = 0;
|
||||
if(b < 0.0)
|
||||
b = 0;
|
||||
|
||||
rgb = new ArrayList<Integer>();
|
||||
rgb.add((int)Math.round(r * 255));
|
||||
rgb.add((int)Math.round(g * 255));
|
||||
rgb.add((int)Math.round(b * 255));
|
||||
log.debug("Color change with XY: " + x + " " + y + " Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return rgb;
|
||||
}
|
||||
|
||||
// took that approximation from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
|
||||
public static List<Integer> convertCTtoRGB(Integer ct) {
|
||||
double temperature = 1000000.0 / (double)ct;
|
||||
temperature /= 100;
|
||||
double r,g,b;
|
||||
if (temperature <= 66) {
|
||||
r = 255;
|
||||
g = temperature;
|
||||
g = 99.4708025861 * Math.log(g) - 161.1195681661;
|
||||
} else {
|
||||
r = temperature - 60;
|
||||
r = 329.698727446 * (Math.pow(r, -0.1332047592));
|
||||
g = temperature - 60;
|
||||
g = 288.1221695283 * (Math.pow(g, -0.0755148492));
|
||||
}
|
||||
|
||||
if (temperature >= 66) {
|
||||
b = 255;
|
||||
} else {
|
||||
if (temperature <= 19) {
|
||||
b = 0;
|
||||
} else {
|
||||
b = temperature - 10;
|
||||
b = 138.5177312231 * Math.log(b) - 305.0447927307;
|
||||
}
|
||||
}
|
||||
r = assureBounds(r);
|
||||
g = assureBounds(g);
|
||||
b = assureBounds(b);
|
||||
List<Integer> rgb = new ArrayList<Integer>();
|
||||
rgb.add((int)Math.round(r));
|
||||
rgb.add((int)Math.round(g));
|
||||
rgb.add((int)Math.round(b));
|
||||
log.debug("Color change with CT: " + ct + ". Resulting RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return rgb;
|
||||
}
|
||||
|
||||
private static double assureBounds(double value) {
|
||||
if (value < 0.0) {
|
||||
value = 0;
|
||||
}
|
||||
if (value > 255.0) {
|
||||
value = 255;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String replaceColorData(String request, ColorData colorData, int setIntensity, boolean isHex) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
if (colorData == null) {
|
||||
return request;
|
||||
}
|
||||
boolean notDone = true;
|
||||
ColorData.ColorMode colorMode = colorData.getColorMode();
|
||||
List<Integer> rgb = null;
|
||||
if (colorMode == ColorData.ColorMode.XY) {
|
||||
rgb = convertCIEtoRGB((List<Double>)colorData.getData(), setIntensity);
|
||||
} else if (colorMode == ColorData.ColorMode.CT) {
|
||||
rgb = convertCTtoRGB((Integer)colorData.getData());
|
||||
}
|
||||
|
||||
return null;
|
||||
while(notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(COLOR_R)) {
|
||||
request = request.replace(COLOR_R, isHex ? String.format("%02X", rgb.get(0)) : String.valueOf(rgb.get(0)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_G)) {
|
||||
request = request.replace(COLOR_G, isHex ? String.format("%02X", rgb.get(1)) : String.valueOf(rgb.get(1)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(COLOR_B)) {
|
||||
request = request.replace(COLOR_B, isHex ? String.format("%02X", rgb.get(2)) : String.valueOf(rgb.get(2)));
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
Matcher m = COLOR_MILIGHT.matcher(request);
|
||||
while (m.find()) {
|
||||
int group = Integer.parseInt(m.group(1));
|
||||
request = m.replaceFirst(getMilightV5FromRgb(rgb, group));
|
||||
m.reset(request);
|
||||
}
|
||||
|
||||
log.debug("Request <<" + request + ">>, not done: " + notDone);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
private static String getMilightV5FromRgb(List<Integer> rgb, int group) {
|
||||
double r = (double)rgb.get(0);
|
||||
double g = (double)rgb.get(1);
|
||||
double b = (double)rgb.get(2);
|
||||
if (r > 245 && g > 245 && b > 245) { // it's white
|
||||
String retVal = "";
|
||||
if (group == 0) {
|
||||
retVal += "C2";
|
||||
} else if (group == 1) {
|
||||
retVal += "C5";
|
||||
} else if (group == 2) {
|
||||
retVal += "C7";
|
||||
} else if (group == 3) {
|
||||
retVal += "C9";
|
||||
} else if (group == 4) {
|
||||
retVal += "CB";
|
||||
}
|
||||
log.debug("Convert RGB to Milight. Result: WHITE. RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return retVal + "0055";
|
||||
} else { // normal color
|
||||
r /= (double)0xFF;
|
||||
g /= (double)0xFF;
|
||||
b /= (double)0xFF;
|
||||
double max = Math.max(Math.max(r, g), b), min = Math.min(Math.min(r, g), b);
|
||||
double h = 0;
|
||||
double d = max - min;
|
||||
|
||||
if (max == min) {
|
||||
h = 0;
|
||||
} else {
|
||||
if (max == r) {
|
||||
h = ((g - b) / d + (g < b ? 6 : 0));
|
||||
} else if (max == g) {
|
||||
h = ((b - r) / d + 2);
|
||||
} else if (max == b){
|
||||
h = ((r - g) / d + 4);
|
||||
}
|
||||
h = Math.round(h * 60);
|
||||
}
|
||||
int milight = (int)((256 + 176 - Math.floor(h / 360.0 * 255.0)) % 256);
|
||||
log.debug("Convert RGB to Milight. Result: " + milight + " RGB Values: " + rgb.get(0) + " " + rgb.get(1) + " " + rgb.get(2));
|
||||
return "40" + String.format("%02X", milight) + "55";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
75
src/main/java/com/bwssystems/HABridge/hue/ColorMap.java
Normal file
75
src/main/java/com/bwssystems/HABridge/hue/ColorMap.java
Normal file
@@ -0,0 +1,75 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
public class ColorMap {
|
||||
private double red;
|
||||
private double green;
|
||||
private double blue;
|
||||
private long R;
|
||||
private long G;
|
||||
private long B;
|
||||
private double X;
|
||||
private double Y;
|
||||
private Double Z;
|
||||
private double z;
|
||||
public double getRed() {
|
||||
return red;
|
||||
}
|
||||
public void setRed(double red) {
|
||||
this.red = red;
|
||||
}
|
||||
public double getGreen() {
|
||||
return green;
|
||||
}
|
||||
public void setGreen(double green) {
|
||||
this.green = green;
|
||||
}
|
||||
public double getBlue() {
|
||||
return blue;
|
||||
}
|
||||
public void setBlue(double blue) {
|
||||
this.blue = blue;
|
||||
}
|
||||
public long getR() {
|
||||
return R;
|
||||
}
|
||||
public void setR(long r) {
|
||||
R = r;
|
||||
}
|
||||
public long getG() {
|
||||
return G;
|
||||
}
|
||||
public void setG(long g) {
|
||||
G = g;
|
||||
}
|
||||
public long getB() {
|
||||
return B;
|
||||
}
|
||||
public void setB(long b) {
|
||||
B = b;
|
||||
}
|
||||
public double getX() {
|
||||
return X;
|
||||
}
|
||||
public void setX(double x) {
|
||||
X = x;
|
||||
}
|
||||
public double getY() {
|
||||
return Y;
|
||||
}
|
||||
public void setY(double y) {
|
||||
Y = y;
|
||||
}
|
||||
public Double getZ() {
|
||||
return Z;
|
||||
}
|
||||
public void setZ(Double z) {
|
||||
Z = z;
|
||||
}
|
||||
public double getz() {
|
||||
return z;
|
||||
}
|
||||
public void setz(double z) {
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.bwssystems.HABridge.api.UserCreateRequest;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceState;
|
||||
import com.bwssystems.HABridge.api.hue.GroupResponse;
|
||||
import com.bwssystems.HABridge.api.hue.GroupClassTypes;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HueConfig;
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
@@ -17,6 +18,7 @@ import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HuePublicConfig;
|
||||
import com.bwssystems.HABridge.api.hue.StateChangeBody;
|
||||
import com.bwssystems.HABridge.dao.*;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
@@ -29,6 +31,7 @@ import static spark.Spark.halt;
|
||||
import static spark.Spark.options;
|
||||
import static spark.Spark.post;
|
||||
import static spark.Spark.put;
|
||||
import static spark.Spark.delete;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
@@ -38,6 +41,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Based on Armzilla's HueMulator - a Philips Hue emulator using sparkjava rest server
|
||||
@@ -48,6 +52,7 @@ public class HueMulator {
|
||||
private static final String HUE_CONTEXT = "/api";
|
||||
|
||||
private DeviceRepository repository;
|
||||
private GroupRepository groupRepository;
|
||||
private HomeManager homeManager;
|
||||
private HueHome myHueHome;
|
||||
private BridgeSettingsDescriptor bridgeSettings;
|
||||
@@ -55,8 +60,9 @@ public class HueMulator {
|
||||
private Gson aGsonHandler;
|
||||
private DeviceMapTypes validMapTypes;
|
||||
|
||||
public HueMulator(BridgeSettings bridgeMaster, DeviceRepository aDeviceRepository, HomeManager aHomeManager) {
|
||||
public HueMulator(BridgeSettings bridgeMaster, DeviceRepository aDeviceRepository, GroupRepository aGroupRepository, HomeManager aHomeManager) {
|
||||
repository = aDeviceRepository;
|
||||
groupRepository = aGroupRepository;
|
||||
validMapTypes = new DeviceMapTypes();
|
||||
bridgeSettingMaster = bridgeMaster;
|
||||
bridgeSettings = bridgeSettingMaster.getBridgeSettingsDescriptor();
|
||||
@@ -70,6 +76,10 @@ public class HueMulator {
|
||||
public void setupServer() {
|
||||
log.info("Hue emulator service started....");
|
||||
before(HUE_CONTEXT + "/*", (request, response) -> {
|
||||
String path = request.pathInfo();
|
||||
if (path.endsWith("/")) { // it should work with or without a trailing slash
|
||||
response.redirect(path.substring(0, path.length() - 1));
|
||||
}
|
||||
log.debug("HueMulator " + request.requestMethod() + " called on api/* with request <<<" + request.pathInfo() + ">>>, and body <<<" + request.body() + ">>>");
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSecure()) {
|
||||
String pathInfo = request.pathInfo();
|
||||
@@ -95,12 +105,12 @@ public class HueMulator {
|
||||
return groupsListHandler(request.params(":userid"), request.ip());
|
||||
} , new JsonTransformer());
|
||||
// http://ip_address:port/api/{userId}/groups/{groupId} returns json
|
||||
// object for specified group. Only 0 is supported
|
||||
// object for specified group.
|
||||
get(HUE_CONTEXT + "/:userid/groups/:groupid", "application/json", (request, response) -> {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return groupsIdHandler(request.params(":groupid"), request.params(":userid"), request.ip());
|
||||
return groupsIdHandler(request.params(":groupid"), request.params(":userid"), request.ip());
|
||||
} , new JsonTransformer());
|
||||
// http://ip_address:port/:userid/groups CORS request
|
||||
options(HUE_CONTEXT + "/:userid/groups", "application/json", (request, response) -> {
|
||||
@@ -112,24 +122,36 @@ public class HueMulator {
|
||||
return "";
|
||||
});
|
||||
// http://ip_address:port/:userid/groups
|
||||
// dummy handler
|
||||
// add a group
|
||||
post(HUE_CONTEXT + "/:userid/groups", "application/json", (request, response) -> {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
log.debug("group add requested from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
|
||||
return "[{\"success\":{\"id\":\"1\"}}]";
|
||||
return addGroup(request.params(":userid"), request.ip(), request.body());
|
||||
});
|
||||
// http://ip_address:port/api/:userid/groups/<groupid>
|
||||
// delete a group
|
||||
delete(HUE_CONTEXT + "/:userid/groups/:groupid", "application/json", (request, response) -> {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return deleteGroup(request.params(":userid"), request.params(":groupid"), request.ip());
|
||||
});
|
||||
// http://ip_address:port/api/:userid/groups/<groupid>
|
||||
// modify a single group
|
||||
put(HUE_CONTEXT + "/:userid/groups/:groupid", "application/json", (request, response) -> {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return modifyGroup(request.params(":userid"), request.params(":groupid"), request.ip(), request.body());
|
||||
});
|
||||
// http://ip_address:port/api/:userid/groups/<groupid>/action
|
||||
// Dummy handler
|
||||
// Error forces Logitech Pop to fall back to individual light control
|
||||
// instead of scene-based control.
|
||||
// group acions
|
||||
put(HUE_CONTEXT + "/:userid/groups/:groupid/action", "application/json", (request, response) -> {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
log.debug("put action to groups API from " + request.ip() + " user " + request.params(":userid") + " with body " + request.body());
|
||||
return "[{\"error\":{\"address\": \"/groups/0/action/scene\", \"type\":7, \"description\": \"invalid value, dummy for parameter, scene\"}}]";
|
||||
return changeGroupState(request.params(":userid"), request.params(":groupid"), request.body(), request.ip(), false);
|
||||
});
|
||||
// http://ip_address:port/api/{userId}/scenes returns json objects of
|
||||
// all scenes configured
|
||||
@@ -418,7 +440,7 @@ public class HueMulator {
|
||||
response.header("Access-Control-Allow-Origin", request.headers("Origin"));
|
||||
response.type("application/json");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return changeState(request.params(":userid"), request.params(":id"), request.body(), request.ip());
|
||||
return changeState(request.params(":userid"), request.params(":id"), request.body(), request.ip(), false);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -467,16 +489,6 @@ public class HueMulator {
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"ct\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/ct\":" + stateChanges.getCt()
|
||||
+ "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setCt(stateChanges.getCt());
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"xy\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
@@ -485,36 +497,34 @@ public class HueMulator {
|
||||
if (deviceState != null)
|
||||
deviceState.setXy(stateChanges.getXy());
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"hue\"")) {
|
||||
} else if (body.contains("\"ct\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/hue\":" + stateChanges.getHue()
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/ct\":" + stateChanges.getCt()
|
||||
+ "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setHue(stateChanges.getHue());
|
||||
deviceState.setCt(stateChanges.getCt());
|
||||
notFirstChange = true;
|
||||
}
|
||||
} else {
|
||||
if (body.contains("\"hue\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/hue\":" + stateChanges.getHue()
|
||||
+ "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setHue(stateChanges.getHue());
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"sat\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/sat\":" + stateChanges.getSat()
|
||||
+ "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setSat(stateChanges.getSat());
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"ct_inc\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/ct_inc\":"
|
||||
+ stateChanges.getCt_inc() + "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setCt(deviceState.getCt() + stateChanges.getCt_inc());
|
||||
notFirstChange = true;
|
||||
if (body.contains("\"sat\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/sat\":" + stateChanges.getSat()
|
||||
+ "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setSat(stateChanges.getSat());
|
||||
notFirstChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (body.contains("\"xy_inc\"")) {
|
||||
@@ -525,26 +535,34 @@ public class HueMulator {
|
||||
if (deviceState != null)
|
||||
deviceState.setXy(stateChanges.getXy());
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"hue_inc\"")) {
|
||||
} else if (body.contains("\"ct_inc\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/hue_inc\":"
|
||||
+ stateChanges.getHue_inc() + "}}";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/ct_inc\":"
|
||||
+ stateChanges.getCt_inc() + "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setHue(deviceState.getHue() + stateChanges.getHue_inc());
|
||||
deviceState.setCt(deviceState.getCt() + stateChanges.getCt_inc());
|
||||
notFirstChange = true;
|
||||
}
|
||||
} else {
|
||||
if (body.contains("\"hue_inc\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/hue_inc\":"
|
||||
+ stateChanges.getHue_inc() + "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setHue(deviceState.getHue() + stateChanges.getHue_inc());
|
||||
notFirstChange = true;
|
||||
}
|
||||
|
||||
if (body.contains("\"sat_inc\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/sat_inc\":"
|
||||
+ stateChanges.getSat_inc() + "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setSat(deviceState.getSat() + stateChanges.getSat_inc());
|
||||
notFirstChange = true;
|
||||
if (body.contains("\"sat_inc\"")) {
|
||||
if (notFirstChange)
|
||||
responseString = responseString + ",";
|
||||
responseString = responseString + "{\"success\":{\"/lights/" + lightId + "/state/sat_inc\":"
|
||||
+ stateChanges.getSat_inc() + "}}";
|
||||
if (deviceState != null)
|
||||
deviceState.setSat(deviceState.getSat() + stateChanges.getSat_inc());
|
||||
notFirstChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (body.contains("\"effect\"")) {
|
||||
@@ -607,7 +625,7 @@ public class HueMulator {
|
||||
}
|
||||
|
||||
private String basicListHandler(String type, String userId, String requestIp) {
|
||||
log.debug("hue " + type + " list requested: " + userId + " from " + requestIp);
|
||||
log.debug("hue " + type + " list requested by user: " + userId + " from address: " + requestIp);
|
||||
HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors != null) {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
@@ -618,23 +636,190 @@ public class HueMulator {
|
||||
|
||||
return "{}";
|
||||
}
|
||||
private Object groupsListHandler(String userId, String requestIp) {
|
||||
log.debug("hue group list requested: " + userId + " from " + requestIp);
|
||||
|
||||
private Object addGroup(String userId, String ip, String body) {
|
||||
HueError[] theErrors = null;
|
||||
Map<String, GroupResponse> groupResponseMap = null;
|
||||
log.debug("group add requested from " + ip + " user " + userId + " with body " + body);
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
groupResponseMap = new HashMap<String, GroupResponse>();
|
||||
groupResponseMap.put("1", (GroupResponse) this.groupsIdHandler("1", userId, requestIp));
|
||||
return groupResponseMap;
|
||||
GroupResponse theGroup = null;
|
||||
try {
|
||||
theGroup = aGsonHandler.fromJson(body, GroupResponse.class);
|
||||
} catch (Exception e) {
|
||||
theGroup = null;
|
||||
}
|
||||
if (theGroup == null) {
|
||||
log.warn("Could not parse add group body. No group created.");
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("5", "/groups/lights",
|
||||
"invalid/missing parameters in body", null, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
List<GroupDescriptor> groups = groupRepository.findAll();
|
||||
GroupDescriptor newGroup = new GroupDescriptor();
|
||||
|
||||
String type = theGroup.getType();
|
||||
String groupClass = theGroup.getClass_name();
|
||||
|
||||
// check type
|
||||
if (type == null || type.trim().equals("")) {
|
||||
type = (groupClass == null || groupClass.trim().equals("")) ? "LightGroup" : "Room";
|
||||
} else if (!type.equals("LightGroup") && !type.equals("Room")) {
|
||||
type = "LightGroup";
|
||||
}
|
||||
// Everything else than a room must contain lights
|
||||
if (!type.equals("Room")) {
|
||||
if (theGroup.getLights() == null || theGroup.getLights().length == 0) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("5", "/groups/lights",
|
||||
"invalid/missing parameters in body", null, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
} else { // check room class if it's a room
|
||||
if (groupClass == null || groupClass.trim().equals("")) {
|
||||
groupClass = GroupClassTypes.OTHER;
|
||||
} else if (!new GroupClassTypes().validateType(groupClass)) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("7", "/groups/class",
|
||||
"invalid value, " + groupClass + ", for parameter, class", null, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
}
|
||||
String name = theGroup.getName();
|
||||
Integer newId = groupRepository.getNewId();
|
||||
if (name == null || name.trim().equals("")) {
|
||||
name = type + " " + newId;
|
||||
}
|
||||
newGroup.setGroupType(type);
|
||||
newGroup.setGroupClass(groupClass);
|
||||
newGroup.setName(name);
|
||||
newGroup.setLights(theGroup.getLights());
|
||||
groups.add(newGroup);
|
||||
groupRepository.save(groups.toArray(new GroupDescriptor[0]));
|
||||
|
||||
return "[{\"success\":{\"id\":\"" + newId + "\"}}]";
|
||||
}
|
||||
|
||||
return theErrors;
|
||||
}
|
||||
|
||||
private Object deleteGroup(String userId, String groupId, String ip) {
|
||||
HueError[] theErrors = null;
|
||||
log.debug("group delete requested from " + ip + " user " + userId);
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
GroupDescriptor group = groupRepository.findOne(groupId);
|
||||
if (group == null || group.isInactive()) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId,
|
||||
"resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class);
|
||||
} else {
|
||||
groupRepository.delete(group);
|
||||
return "[{\"success\":\"/groups/" + groupId + " deleted\"}}]";
|
||||
}
|
||||
}
|
||||
return theErrors;
|
||||
}
|
||||
|
||||
private Object modifyGroup(String userId, String groupId, String ip, String body) {
|
||||
HueError[] theErrors = null;
|
||||
log.debug("group modify requested from " + ip + " user " + userId + " with body " + body);
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
GroupDescriptor group = groupRepository.findOne(groupId);
|
||||
if (group == null || group.isInactive()) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId,
|
||||
"resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class);
|
||||
} else {
|
||||
String successString = "[";
|
||||
GroupResponse theGroup = null;
|
||||
try {
|
||||
theGroup = aGsonHandler.fromJson(body, GroupResponse.class);
|
||||
} catch (Exception e) {
|
||||
theGroup = null;
|
||||
}
|
||||
if (theGroup == null) {
|
||||
log.warn("Could not parse modify group body. Group unchanged.");
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("5", "/groups/lights",
|
||||
"invalid/missing parameters in body", null, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
String groupClass = theGroup.getClass_name();
|
||||
String name = theGroup.getName();
|
||||
if (!(name == null || name.trim().equals(""))) {
|
||||
group.setName(name);
|
||||
successString += "{\"success\":{\"/groups/" + groupId + "/name\":\"" + name + "\"}},";
|
||||
}
|
||||
if (!group.getGroupType().equals("Room")) {
|
||||
if (!(groupClass == null || groupClass.trim().equals(""))) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("6", "/groups/" + groupId + "/class",
|
||||
"parameter, /groups/" + groupId + "/class, not available", null, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
if (theGroup.getLights() != null) {
|
||||
if (theGroup.getLights().length == 0) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("7", "/groups/" + groupId + "/lights",
|
||||
"invalid value, " + Arrays.toString(theGroup.getLights()) + ", for parameter, /groups" + groupId + "/lights", null, null, null).getTheErrors(), HueError[].class);
|
||||
} else {
|
||||
group.setLights(theGroup.getLights());
|
||||
successString += "{\"success\":{\"/groups/" + groupId + "/lights\":\"" + Arrays.toString(theGroup.getLights()) + "\"}},";
|
||||
}
|
||||
}
|
||||
} else { // check room class if it's a room
|
||||
if (!(groupClass == null || groupClass.trim().equals(""))) {
|
||||
if (!new GroupClassTypes().validateType(groupClass)) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("7", "/groups/class",
|
||||
"invalid value, " + groupClass + ", for parameter, class", null, null, null).getTheErrors(), HueError[].class);
|
||||
} else {
|
||||
group.setGroupClass(groupClass);
|
||||
successString += "{\"success\":{\"/groups/" + groupId + "/class\":\"" + groupClass + "\"}},";
|
||||
}
|
||||
}
|
||||
|
||||
if (theGroup.getLights() != null) {
|
||||
group.setLights(theGroup.getLights());
|
||||
successString += "{\"success\":{\"/groups/" + groupId + "/lights\":\"" + Arrays.toString(theGroup.getLights()) + "\"}},";
|
||||
}
|
||||
}
|
||||
|
||||
groupRepository.save();
|
||||
return (successString.length() == 1) ? "[]" : successString.substring(0, successString.length()-1) + "]";
|
||||
}
|
||||
}
|
||||
return theErrors;
|
||||
}
|
||||
|
||||
private Object groupsListHandler(String userId, String requestIp) {
|
||||
HueError[] theErrors = null;
|
||||
Map<String, GroupResponse> groupResponseMap = null;
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue group list requested: " + userId + " from " + requestIp);
|
||||
log.debug("hue group list requested: " + userId + " from " + requestIp);
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
List<GroupDescriptor> groupList = groupRepository.findAllByRequester(requestIp);
|
||||
groupResponseMap = new HashMap<String, GroupResponse>();
|
||||
for (GroupDescriptor group : groupList) {
|
||||
GroupResponse groupResponse = null;
|
||||
if(!group.isInactive()) {
|
||||
Map<String, DeviceResponse> lights = repository.findAllByGroupWithState(group.getLights(), requestIp, myHueHome, aGsonHandler);
|
||||
groupResponse = GroupResponse.createResponse(group, lights);
|
||||
groupResponseMap.put(group.getId(), groupResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (theErrors != null)
|
||||
return theErrors;
|
||||
|
||||
return groupResponseMap;
|
||||
}
|
||||
|
||||
|
||||
private Object groupsIdHandler(String groupId, String userId, String requestIp) {
|
||||
log.debug("hue group id: <" + groupId + "> requested: " + userId + " from " + requestIp);
|
||||
@@ -645,14 +830,21 @@ public class HueMulator {
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
if (groupId.equalsIgnoreCase("0")) {
|
||||
GroupResponse theResponse = GroupResponse.createDefaultGroupResponse(repository.findActive());
|
||||
@SuppressWarnings("unchecked")
|
||||
GroupResponse theResponse = GroupResponse.createDefaultGroupResponse((Map<String, DeviceResponse>)lightsListHandler(userId, requestIp));
|
||||
return theResponse;
|
||||
} else {
|
||||
GroupDescriptor group = groupRepository.findOne(groupId);
|
||||
if (group == null || group.isInactive()) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId,
|
||||
"resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class);
|
||||
} else {
|
||||
Map<String, DeviceResponse> lights = repository.findAllByGroupWithState(group.getLights(), requestIp, myHueHome, aGsonHandler);
|
||||
GroupResponse theResponse = GroupResponse.createResponse(group, lights);
|
||||
return theResponse;
|
||||
}
|
||||
|
||||
}
|
||||
if (!groupId.equalsIgnoreCase("0")) {
|
||||
GroupResponse theResponse = GroupResponse.createOtherGroupResponse(repository.findActive());
|
||||
return theResponse;
|
||||
}
|
||||
theErrors = HueErrorResponse.createResponse("3", userId + "/groups/" + groupId, "Object not found", null, null, null).getTheErrors();
|
||||
}
|
||||
|
||||
return theErrors;
|
||||
@@ -662,7 +854,7 @@ public class HueMulator {
|
||||
HueError[] theErrors = null;
|
||||
Map<String, DeviceResponse> deviceResponseMap = null;
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue lights list requested: " + userId + " from " + requestIp);
|
||||
log.info("Traceupnp: hue lights list requested by user: " + userId + " from address: " + requestIp);
|
||||
log.debug("hue lights list requested: " + userId + " from " + requestIp);
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors == null) {
|
||||
@@ -670,7 +862,6 @@ public class HueMulator {
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
List<DeviceDescriptor> deviceList = repository.findAllByRequester(requestIp);
|
||||
// List<DeviceDescriptor> deviceList = repository.findActive();
|
||||
deviceResponseMap = new HashMap<String, DeviceResponse>();
|
||||
for (DeviceDescriptor device : deviceList) {
|
||||
DeviceResponse deviceResponse = null;
|
||||
@@ -699,6 +890,13 @@ public class HueMulator {
|
||||
deviceResponseMap.put(device.getId(), deviceResponse);
|
||||
}
|
||||
}
|
||||
|
||||
// handle groups which shall be exposed as fake lights to selected devices like amazon echos
|
||||
List<GroupDescriptor> groups = groupRepository.findVirtualLights(requestIp);
|
||||
for (GroupDescriptor group : groups) {
|
||||
deviceResponseMap.put(String.valueOf(Integer.parseInt(group.getId()) + 10000),
|
||||
DeviceResponse.createResponseForVirtualLight(group));
|
||||
}
|
||||
}
|
||||
|
||||
if (theErrors != null)
|
||||
@@ -713,8 +911,10 @@ public class HueMulator {
|
||||
String aDeviceType = null;
|
||||
boolean toContinue = false;
|
||||
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue api user create requested: " + body + " from " + ipAddress);
|
||||
if (bridgeSettings.isTraceupnp() && !body.contains("test_ha_bridge"))
|
||||
log.info("Traceupnp: hue api user create requested: " + body + " from address: " + ipAddress);
|
||||
else
|
||||
log.debug("hue api user create requested: " + body + " from address: " + ipAddress);
|
||||
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isUseLinkButton() && bridgeSettingMaster.getBridgeControl().isLinkButton())
|
||||
toContinue = true;
|
||||
@@ -749,7 +949,7 @@ public class HueMulator {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
if (bridgeSettings.isTraceupnp() && !aDeviceType.equals("test_ha_bridge"))
|
||||
log.info("Traceupnp: hue api user create requested for device type: " + aDeviceType + " and username: "
|
||||
+ newUser + (followingSlash ? " /api/ called" : ""));
|
||||
log.debug("hue api user create requested for device type: " + aDeviceType + " and username: " + newUser + (followingSlash ? " /api/ called" : ""));
|
||||
@@ -762,17 +962,17 @@ public class HueMulator {
|
||||
|
||||
private Object getConfig(String userId, String ipAddress) {
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + ipAddress);
|
||||
log.info("Traceupnp: hue api/:userid/config config requested from user: " + userId + " from address: " + ipAddress);
|
||||
log.debug("hue api config requested: " + userId + " from " + ipAddress);
|
||||
if (bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton()) != null) {
|
||||
log.debug("hue api config requested, User invalid, returning public config");
|
||||
HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue",
|
||||
bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion());
|
||||
HuePublicConfig apiResponse = HuePublicConfig.createConfig("HA-Bridge",
|
||||
bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion(), bridgeSettings.getHubmac());
|
||||
return apiResponse;
|
||||
}
|
||||
|
||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(),
|
||||
bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
|
||||
HueApiResponse apiResponse = new HueApiResponse("HA-Bridge", bridgeSettings.getUpnpConfigAddress(),
|
||||
bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton(), bridgeSettings.getHubmac());
|
||||
log.debug("api response config <<<" + aGsonHandler.toJson(apiResponse.getConfig()) + ">>>");
|
||||
return apiResponse.getConfig();
|
||||
}
|
||||
@@ -786,8 +986,8 @@ public class HueMulator {
|
||||
return theErrors;
|
||||
}
|
||||
|
||||
HueApiResponse apiResponse = new HueApiResponse("Philips hue", bridgeSettings.getUpnpConfigAddress(),
|
||||
bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton());
|
||||
HueApiResponse apiResponse = new HueApiResponse("HA-Bridge", bridgeSettings.getUpnpConfigAddress(),
|
||||
bridgeSettingMaster.getBridgeSecurity().getWhitelist(), bridgeSettings.getHubversion(), bridgeSettingMaster.getBridgeControl().isLinkButton(), bridgeSettings.getHubmac());
|
||||
apiResponse.setLights((Map<String, DeviceResponse>) this.lightsListHandler(userId, ipAddress));
|
||||
apiResponse.setGroups((Map<String, GroupResponse>) this.groupsListHandler(userId, ipAddress));
|
||||
|
||||
@@ -800,6 +1000,11 @@ public class HueMulator {
|
||||
if (theErrors != null)
|
||||
return theErrors;
|
||||
|
||||
if (Integer.parseInt(lightId) >= 10000) {
|
||||
GroupDescriptor group = groupRepository.findOne(String.valueOf(Integer.parseInt(lightId) - 10000));
|
||||
return DeviceResponse.createResponseForVirtualLight(group);
|
||||
}
|
||||
|
||||
DeviceDescriptor device = repository.findOne(lightId);
|
||||
if (device == null) {
|
||||
// response.status(HttpStatus.SC_NOT_FOUND);
|
||||
@@ -870,7 +1075,7 @@ public class HueMulator {
|
||||
|
||||
state = device.getDeviceState();
|
||||
if (state == null)
|
||||
state = DeviceState.createDeviceState();
|
||||
state = DeviceState.createDeviceState(device.isColorDevice());
|
||||
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
|
||||
device.setDeviceState(state);
|
||||
@@ -878,7 +1083,10 @@ public class HueMulator {
|
||||
return responseString;
|
||||
}
|
||||
|
||||
private String changeState(String userId, String lightId, String body, String ipAddress) {
|
||||
private String changeState(String userId, String lightId, String body, String ipAddress, boolean ignoreRequester) {
|
||||
if (Integer.parseInt(lightId) >= 10000) {
|
||||
return changeGroupState(userId, String.valueOf(Integer.parseInt(lightId) - 10000), body, ipAddress, true);
|
||||
}
|
||||
String responseString = null;
|
||||
String url = null;
|
||||
StateChangeBody theStateChanges = null;
|
||||
@@ -891,8 +1099,10 @@ public class HueMulator {
|
||||
aMultiUtil.setSetCount(1);
|
||||
log.debug("hue state change requested: " + userId + " from " + ipAddress + " body: " + body);
|
||||
HueError[] theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors != null)
|
||||
if (theErrors != null) {
|
||||
log.warn("Errors in security: <<<" + aGsonHandler.toJson(theErrors) + ">>>");
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
}
|
||||
try {
|
||||
theStateChanges = aGsonHandler.fromJson(body, StateChangeBody.class);
|
||||
} catch (Exception e) {
|
||||
@@ -921,7 +1131,7 @@ public class HueMulator {
|
||||
|
||||
state = device.getDeviceState();
|
||||
if (state == null) {
|
||||
state = DeviceState.createDeviceState();
|
||||
state = DeviceState.createDeviceState(device.isColorDevice());
|
||||
device.setDeviceState(state);
|
||||
}
|
||||
|
||||
@@ -931,7 +1141,9 @@ public class HueMulator {
|
||||
if (url == null || url.length() == 0)
|
||||
url = device.getOnUrl();
|
||||
} else {
|
||||
if (theStateChanges.isOn()) {
|
||||
if (body.contains("\"xy\"") || body.contains("\"ct\"") || body.contains("\"hue\"")) {
|
||||
url = device.getColorUrl();
|
||||
} else if (theStateChanges.isOn()) {
|
||||
url = device.getOnUrl();
|
||||
} else if (!theStateChanges.isOn()) {
|
||||
url = device.getOffUrl();
|
||||
@@ -968,10 +1180,13 @@ public class HueMulator {
|
||||
}
|
||||
|
||||
for (int i = 0; callItems != null && i < callItems.length; i++) {
|
||||
if(!filterByRequester(device.getRequesterAddress(), ipAddress) || !filterByRequester(callItems[i].getFilterIPs(), ipAddress)) {
|
||||
log.warn("filter for requester address not present in: (device)" + device.getRequesterAddress() + " OR then (item)" + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress);
|
||||
continue;
|
||||
if (!ignoreRequester) {
|
||||
if(!filterByRequester(device.getRequesterAddress(), ipAddress) || !filterByRequester(callItems[i].getFilterIPs(), ipAddress)) {
|
||||
log.warn("filter for requester address not present in: (device)" + device.getRequesterAddress() + " OR then (item)" + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (callItems[i].getCount() != null && callItems[i].getCount() > 0)
|
||||
aMultiUtil.setSetCount(callItems[i].getCount());
|
||||
else
|
||||
@@ -999,13 +1214,37 @@ public class HueMulator {
|
||||
aMultiUtil.setTheDelay(callItems[i].getDelay());
|
||||
else
|
||||
aMultiUtil.setTheDelay(aMultiUtil.getDelayDefault());
|
||||
responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, state.getBri(), targetBri, targetBriInc, device, body);
|
||||
|
||||
ColorData colorData = null;
|
||||
List<Double> xy = theStateChanges.getXy();
|
||||
List<Double> xyInc = theStateChanges.getXy_inc();
|
||||
Integer ct = theStateChanges.getCt();
|
||||
Integer ctInc = theStateChanges.getCt_inc();
|
||||
if (xy != null && xy.size() == 2) {
|
||||
colorData = new ColorData(ColorData.ColorMode.XY, xy);
|
||||
} else if (xyInc != null && xyInc.size() == 2) {
|
||||
List<Double> current = state.getXy();
|
||||
current.set(0, current.get(0) + xyInc.get(0));
|
||||
current.set(1, current.get(1) + xyInc.get(1));
|
||||
colorData = new ColorData(ColorData.ColorMode.XY, current);
|
||||
} else if (ct != null && ct != 0) {
|
||||
colorData = new ColorData(ColorData.ColorMode.CT, ct);
|
||||
} else if (ctInc != null && ctInc != 0) {
|
||||
colorData = new ColorData(ColorData.ColorMode.CT, state.getCt() + ctInc);
|
||||
}
|
||||
log.debug("Calling Home device handler for type : " + callItems[i].getType().trim());
|
||||
responseString = homeManager.findHome(callItems[i].getType().trim()).deviceHandler(callItems[i], aMultiUtil, lightId, state.getBri(), targetBri, targetBriInc, colorData, device, body);
|
||||
if(responseString != null && responseString.contains("{\"error\":")) {
|
||||
x = aMultiUtil.getSetCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
log.warn("Call Items type is null <<<" + callItems[i] + ">>>");
|
||||
}
|
||||
|
||||
if(callItems.length == 0)
|
||||
log.warn("No call items were available: <<<" + url + ">>>");
|
||||
} else {
|
||||
log.warn("Could not find url: " + lightId + " for hue state change request: " + userId + " from "
|
||||
+ ipAddress + " body: " + body);
|
||||
@@ -1014,15 +1253,123 @@ public class HueMulator {
|
||||
}
|
||||
|
||||
if (responseString == null || !responseString.contains("[{\"error\":")) {
|
||||
log.debug("Response is in error: " + ((responseString == null) ? "null" : responseString));
|
||||
if(!device.isNoState()) {
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
|
||||
device.setDeviceState(state);
|
||||
} else {
|
||||
DeviceState dummyState = DeviceState.createDeviceState();
|
||||
DeviceState dummyState = DeviceState.createDeviceState(device.isColorDevice());
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc, device.isOffState());
|
||||
}
|
||||
}
|
||||
return responseString;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private String changeGroupState(String userId, String groupId, String body, String ipAddress, boolean fakeLightResponse) {
|
||||
log.debug("PUT action to group " + groupId + " from " + ipAddress + " user " + userId + " with body " + body);
|
||||
HueError[] theErrors = null;
|
||||
theErrors = bridgeSettingMaster.getBridgeSecurity().validateWhitelistUser(userId, null, bridgeSettingMaster.getBridgeSecurity().isUseLinkButton());
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettingMaster.getBridgeSecurity().isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
GroupDescriptor group = null;
|
||||
Integer targetBriInc = null;
|
||||
Integer targetBri = null;
|
||||
DeviceState state = null;
|
||||
Map<String, DeviceResponse> lights = null;
|
||||
if (groupId.equalsIgnoreCase("0")) {
|
||||
lights = (Map<String, DeviceResponse>)lightsListHandler(userId, ipAddress);
|
||||
} else {
|
||||
group = groupRepository.findOne(groupId);
|
||||
if (group == null || group.isInactive()) {
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("3", "/groups/" + groupId,
|
||||
"resource, /groups/" + groupId + ", not available", null, null, null).getTheErrors(), HueError[].class);
|
||||
} else {
|
||||
if (fakeLightResponse) {
|
||||
lights = repository.findAllByGroupWithState(group.getLights(), ipAddress, myHueHome, aGsonHandler, true);
|
||||
} else {
|
||||
lights = repository.findAllByGroupWithState(group.getLights(), ipAddress, myHueHome, aGsonHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lights != null) {
|
||||
StateChangeBody theStateChanges = null;
|
||||
try {
|
||||
theStateChanges = aGsonHandler.fromJson(body, StateChangeBody.class);
|
||||
} catch (Exception e) {
|
||||
theStateChanges = null;
|
||||
}
|
||||
if (theStateChanges == null) {
|
||||
log.warn("Could not parse state change body. Light state not changed.");
|
||||
return aGsonHandler.toJson(HueErrorResponse.createResponse("2", "/groups/" + groupId + "/action",
|
||||
"Could not parse state change body.", null, null, null).getTheErrors(), HueError[].class);
|
||||
}
|
||||
|
||||
if (group != null) {
|
||||
if (body.contains("\"bri_inc\"")) {
|
||||
targetBriInc = new Integer(theStateChanges.getBri_inc());
|
||||
}
|
||||
else if (body.contains("\"bri\"")) {
|
||||
targetBri = new Integer(theStateChanges.getBri());
|
||||
}
|
||||
|
||||
state = group.getAction();
|
||||
if (state == null) {
|
||||
state = DeviceState.createDeviceState(true);
|
||||
group.setAction(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean turnOn = false;
|
||||
boolean turnOff = false;
|
||||
if (!(body.contains("\"bri_inc\"") || body.contains("\"bri\""))) {
|
||||
if (!(body.contains("\"xy\"") || body.contains("\"ct\"") || body.contains("\"hue\""))) {
|
||||
if (theStateChanges.isOn()) {
|
||||
turnOn = true;
|
||||
} else if (!theStateChanges.isOn()) {
|
||||
turnOff = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, DeviceResponse> light : lights.entrySet()) {
|
||||
log.debug("Processing light" + light.getKey() + ": " + turnOn + " " + turnOff + " " + light.getValue().getState().isOn());
|
||||
// ignore on/off for devices that are already on/off
|
||||
if (turnOff && !light.getValue().getState().isOn())
|
||||
continue;
|
||||
if (turnOn && light.getValue().getState().isOn())
|
||||
continue;
|
||||
changeState(userId, light.getKey(), body, ipAddress, fakeLightResponse);
|
||||
}
|
||||
// construct success response: one success message per changed property, but not per light
|
||||
if (group != null) { // if not group 0
|
||||
String response = formatSuccessHueResponse(theStateChanges, body, String.valueOf(Integer.parseInt(groupId) + 10000),
|
||||
state, targetBri, targetBriInc, true);
|
||||
group.setAction(state);
|
||||
if (fakeLightResponse) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
String successString = "[";
|
||||
for (String pairStr : body.replaceAll("[{|}]", "").split(",\\s*\"")) {
|
||||
String[] pair = pairStr.split(":");
|
||||
if (fakeLightResponse) {
|
||||
successString += "{\"success\":{ \"/lights/" + String.valueOf(Integer.parseInt(groupId) + 10000) + "/state/" + pair[0].replaceAll("\"", "").trim() + "\": " + pair[1].trim() + "}},";
|
||||
} else {
|
||||
successString += "{\"success\":{ \"address\": \"/groups/" + groupId + "/action/" + pair[0].replaceAll("\"", "").trim() + "\", \"value\": " + pair[1].trim() + "}},";
|
||||
}
|
||||
|
||||
}
|
||||
return (successString.length() == 1) ? "[]" : successString.substring(0, successString.length()-1) + "]";
|
||||
}
|
||||
}
|
||||
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ package com.bwssystems.HABridge.hue;
|
||||
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
|
||||
public interface HueMulatorHandler {
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body);
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.nest.controller.Home;
|
||||
import com.bwssystems.nest.controller.Nest;
|
||||
@@ -31,10 +32,13 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
||||
private Gson aGsonHandler;
|
||||
private Boolean isFarenheit;
|
||||
private Boolean validNest;
|
||||
private boolean closed;
|
||||
|
||||
public NestHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,17 +96,23 @@ public class NestHome implements com.bwssystems.HABridge.Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(theSession != null) {
|
||||
theNest.endNestSession();
|
||||
}
|
||||
theNest = null;
|
||||
theSession = null;
|
||||
nestItems = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
log.debug("executing HUE api request to set away for nest " + anItem.getType() + ": " + anItem.getItem().toString());
|
||||
if(!validNest) {
|
||||
|
||||
@@ -17,8 +17,10 @@ import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class DomoticzHome implements Home {
|
||||
@@ -26,10 +28,13 @@ public class DomoticzHome implements Home {
|
||||
private Map<String, DomoticzHandler> domoticzs;
|
||||
private Boolean validDomoticz;
|
||||
private HTTPHandler httpClient;
|
||||
private boolean closed;
|
||||
|
||||
public DomoticzHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,7 +76,7 @@ public class DomoticzHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
Devices theDomoticzApiResponse = null;
|
||||
String responseString = null;
|
||||
|
||||
@@ -128,7 +133,7 @@ public class DomoticzHome implements Home {
|
||||
log.info("Domoticz Home created." + (validDomoticz ? "" : " No Domoticz devices configured."));
|
||||
if(!validDomoticz)
|
||||
return null;
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
domoticzs = new HashMap<String, DomoticzHandler>();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getDomoticzaddress().getDevices().iterator();
|
||||
while(theList.hasNext()) {
|
||||
@@ -161,8 +166,15 @@ public class DomoticzHome implements Home {
|
||||
}
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
if(httpClient != null)
|
||||
httpClient.closeHandler();
|
||||
|
||||
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -17,14 +19,17 @@ import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
public class CommandHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(CommandHome.class);
|
||||
private BridgeSettings theSettings;
|
||||
private boolean closed;
|
||||
|
||||
public CommandHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int itensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
log.debug("Exec Request called with url: " + anItem.getItem().getAsString() + " and exec Garden: " + (theSettings.getBridgeSecurity().getExecGarden() == null ? "not given" : theSettings.getBridgeSecurity().getExecGarden()));
|
||||
String responseString = null;
|
||||
String intermediate;
|
||||
@@ -32,7 +37,10 @@ public class CommandHome implements Home {
|
||||
intermediate = anItem.getItem().getAsString().substring(anItem.getItem().getAsString().indexOf("://") + 3);
|
||||
else
|
||||
intermediate = anItem.getItem().getAsString();
|
||||
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, itensity, targetBri, targetBriInc, false);
|
||||
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
intermediate = ColorDecode.replaceColorData(intermediate, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
intermediate = DeviceDataDecode.replaceDeviceData(intermediate, device);
|
||||
intermediate = TimeDecode.replaceTimeValue(intermediate);
|
||||
String execGarden = theSettings.getBridgeSecurity().getExecGarden();
|
||||
@@ -88,8 +96,13 @@ public class CommandHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
// noop
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Device;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Scene;
|
||||
|
||||
public class FibaroHome implements Home
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FibaroHome.class);
|
||||
private Map<String, FibaroInfo> fibaros;
|
||||
private Boolean validFibaro;
|
||||
private boolean closed;
|
||||
|
||||
public FibaroHome(BridgeSettings bridgeSettings)
|
||||
{
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public List<Device> getDevices()
|
||||
{
|
||||
log.debug("consolidating devices for fibaros");
|
||||
Iterator<String> keys = fibaros.keySet().iterator();
|
||||
ArrayList<Device> deviceList = new ArrayList<>();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
String key = keys.next();
|
||||
for(Device device : fibaros.get(key).getDevices())
|
||||
deviceList.add(device);
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
public List<Scene> getScenes()
|
||||
{
|
||||
log.debug("consolidating scenes for fibaros");
|
||||
Iterator<String> keys = fibaros.keySet().iterator();
|
||||
ArrayList<Scene> sceneList = new ArrayList<>();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
String key = keys.next();
|
||||
for(Scene scene : fibaros.get(key).getScenes())
|
||||
sceneList.add(scene);
|
||||
}
|
||||
return sceneList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body)
|
||||
{
|
||||
// Not a device handler
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type)
|
||||
{
|
||||
if(validFibaro)
|
||||
{
|
||||
if(type.equalsIgnoreCase(DeviceMapTypes.FIBARO_DEVICE[DeviceMapTypes.typeIndex]))
|
||||
return getDevices();
|
||||
if(type.equalsIgnoreCase(DeviceMapTypes.FIBARO_SCENE[DeviceMapTypes.typeIndex]))
|
||||
return getScenes();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings)
|
||||
{
|
||||
validFibaro = bridgeSettings.getBridgeSettingsDescriptor().isValidFibaro();
|
||||
log.info("Fibaro Home created." + (validFibaro ? "" : " No Fibaros configured."));
|
||||
if(validFibaro)
|
||||
{
|
||||
fibaros = new HashMap<String, FibaroInfo>();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getBridgeSettingsDescriptor().getFibaroAddress().getDevices().iterator();
|
||||
while(theList.hasNext())
|
||||
{
|
||||
NamedIP aFibaro = theList.next();
|
||||
fibaros.put(aFibaro.getName(), new FibaroInfo(aFibaro));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome()
|
||||
{
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
fibaros = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Device;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Room;
|
||||
import com.bwssystems.HABridge.plugins.fibaro.json.Scene;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class FibaroInfo
|
||||
{
|
||||
private static final Logger log = LoggerFactory.getLogger(FibaroInfo.class);
|
||||
|
||||
private final NamedIP fibaroAddress;
|
||||
private final String fibaroAuth;
|
||||
private final Gson gson;
|
||||
|
||||
// You can disable it if you want TODO config
|
||||
boolean useSaveLogs = true; // This can be used to exclude some devices from list
|
||||
boolean useUserDescription = true;
|
||||
boolean replaceTrash = true;
|
||||
boolean scenesWithLiliCommandOnly = true;
|
||||
|
||||
public FibaroInfo(NamedIP addressName)
|
||||
{
|
||||
super();
|
||||
fibaroAddress = addressName;
|
||||
fibaroAuth = "Basic " + new String(Base64.encodeBase64((addressName.getUsername() + ":" + addressName.getPassword()).getBytes()));
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
private String request(String request)
|
||||
{
|
||||
String result = null;
|
||||
try
|
||||
{
|
||||
URL url = new URL("http://" + fibaroAddress.getIp() + ":" + fibaroAddress.getPort() + request);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Authorization", fibaroAuth);
|
||||
connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
|
||||
connection.connect();
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
String line;
|
||||
while((line = br.readLine()) != null)
|
||||
{
|
||||
buffer.append(line).append("\n");
|
||||
}
|
||||
br.close();
|
||||
result = buffer.toString();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
log.warn("Error while get getJson: {} ", request, e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean sendCommand(String request)
|
||||
{
|
||||
try
|
||||
{
|
||||
URL url = new URL("http://" + fibaroAddress.getIp() + ":" + fibaroAddress.getPort() + request);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Authorization", fibaroAuth);
|
||||
connection.getResponseMessage();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
log.warn("Error while get getJson: {} ", request, e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String replaceTrash(String name)
|
||||
{
|
||||
String sanitizedName = name.replaceAll("[0-9:/-]", "");
|
||||
sanitizedName = name.replaceAll("\\s+", " ");
|
||||
return sanitizedName.trim();
|
||||
}
|
||||
|
||||
private Room[] getRooms()
|
||||
{
|
||||
String result = request("/api/rooms");
|
||||
Room[] rooms = result == null ? new Room[0] : gson.fromJson(result, Room[].class);
|
||||
if(replaceTrash)
|
||||
for(Room r : rooms)
|
||||
r.setName(replaceTrash(r.getName()));
|
||||
return rooms;
|
||||
}
|
||||
|
||||
public Device[] getDevices()
|
||||
{
|
||||
Room[] rooms = getRooms();
|
||||
|
||||
log.info("Found: " + rooms.length + " rooms");
|
||||
|
||||
String result = request("/api/devices?enabled=true&visible=true");
|
||||
Device[] all_devices = result == null ? new Device[0] : gson.fromJson(result, Device[].class);
|
||||
|
||||
int count = 0;
|
||||
for(Device d : all_devices)
|
||||
if(d.getRoomID() > 0 && (useSaveLogs ? "true".equals(d.getProperties().getSaveLogs()) : true))
|
||||
count++;
|
||||
|
||||
Device[] devices = new Device[count];
|
||||
int i = 0;
|
||||
for(Device d : all_devices)
|
||||
if(d.getRoomID() > 0 && (useSaveLogs ? "true".equals(d.getProperties().getSaveLogs()) : true))
|
||||
{
|
||||
if(useUserDescription && d.getProperties().getUserDescription() != null && !d.getProperties().getUserDescription().isEmpty())
|
||||
d.setName(d.getProperties().getUserDescription());
|
||||
if(replaceTrash)
|
||||
d.setName(replaceTrash(d.getName()));
|
||||
|
||||
devices[i++] = d;
|
||||
|
||||
for(Room room : rooms)
|
||||
if(d.getRoomID() == room.getId())
|
||||
d.setRoomName(room.getName());
|
||||
|
||||
d.fibaroaddress = fibaroAddress.getIp();
|
||||
d.fibaroport = fibaroAddress.getPort();
|
||||
d.fibaroAuth = fibaroAuth;
|
||||
d.fibaroname = fibaroAddress.getName();
|
||||
}
|
||||
|
||||
log.info("Found: " + devices.length + " devices");
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
public Scene[] getScenes()
|
||||
{
|
||||
Room[] rooms = getRooms();
|
||||
|
||||
String result = request("/api/scenes?enabled=true&visible=true");
|
||||
Scene[] all_scenes = result == null ? new Scene[0] : gson.fromJson(result, Scene[].class);
|
||||
|
||||
int count = 0;
|
||||
for(Scene s : all_scenes)
|
||||
if(!scenesWithLiliCommandOnly || s.getLiliStartCommand() != null && !s.getLiliStartCommand().isEmpty())
|
||||
count++;
|
||||
Scene[] scenes = new Scene[count];
|
||||
int i = 0;
|
||||
for(Scene s : all_scenes)
|
||||
if(!scenesWithLiliCommandOnly || s.getLiliStartCommand() != null && !s.getLiliStartCommand().isEmpty())
|
||||
{
|
||||
if(replaceTrash)
|
||||
s.setName(replaceTrash(s.getName()));
|
||||
|
||||
scenes[i++] = s;
|
||||
|
||||
for(Room room : rooms)
|
||||
if(s.getRoomID() == room.getId())
|
||||
s.setRoomName(room.getName());
|
||||
|
||||
s.fibaroaddress = fibaroAddress.getIp();
|
||||
s.fibaroport = fibaroAddress.getPort();
|
||||
s.fibaroAuth = fibaroAuth;
|
||||
s.fibaroname = fibaroAddress.getName();
|
||||
}
|
||||
log.info("Found: " + count + " scenes");
|
||||
return scenes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro;
|
||||
|
||||
public enum ModeType {
|
||||
OFF(0, "Off"),
|
||||
HEAT(1, "Heat"),
|
||||
COOL(2, "Cool"),
|
||||
AUTO(3, "Auto"),
|
||||
AUX_HEAT(4, "Aux Heat"),
|
||||
RESUME(5, "Resume"),
|
||||
FAN_ONLY(6, "Fan Only"),
|
||||
FURNANCE(7, "Furnace"),
|
||||
DRY_AIR(8, "Dry Air"),
|
||||
MOIST_AIR(9, "Moist Air"),
|
||||
AUTO_CHANGEOVER(10, "Auto Changeover"),
|
||||
HEAT_ECON(11, "Heat Econ"),
|
||||
COOL_ECON(12, "Cool Econ"),
|
||||
AWAY(13, "Away"),
|
||||
MANUAL(31, "Manual");
|
||||
|
||||
private int key;
|
||||
private String label;
|
||||
|
||||
private ModeType(int key, String label) {
|
||||
this.key = key;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public int getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Device {
|
||||
private String roomName;
|
||||
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("roomID")
|
||||
private int roomID;
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
|
||||
@SerializedName("baseType")
|
||||
private String baseType;
|
||||
|
||||
@SerializedName("enabled")
|
||||
private boolean enabled;
|
||||
|
||||
@SerializedName("visible")
|
||||
private boolean visible;
|
||||
|
||||
@SerializedName("isPlugin")
|
||||
private boolean isPlugin;
|
||||
|
||||
@SerializedName("parentId")
|
||||
private int parentId;
|
||||
|
||||
@SerializedName("remoteGatewayId")
|
||||
private int remoteGatewayId;
|
||||
|
||||
@SerializedName("viewXml")
|
||||
private boolean viewXml;
|
||||
|
||||
@SerializedName("configXml")
|
||||
private boolean configXml;
|
||||
|
||||
@SerializedName("interfaces")
|
||||
private Object interfaces;
|
||||
|
||||
@SerializedName("properties")
|
||||
private DeviceProperties properties;
|
||||
|
||||
@SerializedName("actions")
|
||||
private Object actions;
|
||||
|
||||
@SerializedName("created")
|
||||
private int created;
|
||||
|
||||
@SerializedName("modified")
|
||||
private int modified;
|
||||
|
||||
@SerializedName("sortOrder")
|
||||
private int sortOrder;
|
||||
|
||||
public String getRoomName() {
|
||||
return roomName;
|
||||
}
|
||||
|
||||
public void setRoomName(String roomName) {
|
||||
this.roomName = roomName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getRoomID() {
|
||||
return roomID;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public DeviceProperties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public boolean isThermostat() {
|
||||
return type.equals("com.fibaro.setPoint") || type.equals("com.fibaro.thermostatDanfoss")
|
||||
|| type.equals("com.fibaro.thermostatHorstmann");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + id + ", " + name + "}";
|
||||
}
|
||||
|
||||
public String fibaroaddress;
|
||||
public String fibaroport;
|
||||
public String fibaroAuth;
|
||||
public String fibaroname;
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class DeviceProperties {
|
||||
@SerializedName("batteryLevel")
|
||||
private String batteryLevel;
|
||||
|
||||
@SerializedName("UIMessageSendTime")
|
||||
private String UIMessageSendTime;
|
||||
|
||||
@SerializedName("autoConfig")
|
||||
private String autoConfig;
|
||||
|
||||
@SerializedName("color")
|
||||
private String color;
|
||||
|
||||
@SerializedName("date")
|
||||
private String date;
|
||||
|
||||
@SerializedName("dead")
|
||||
private String dead;
|
||||
|
||||
@SerializedName("deviceControlType")
|
||||
private String deviceControlType;
|
||||
|
||||
@SerializedName("deviceIcon")
|
||||
private String deviceIcon;
|
||||
|
||||
@SerializedName("disabled")
|
||||
private String disabled;
|
||||
|
||||
@SerializedName("emailNotificationID")
|
||||
private String emailNotificationID;
|
||||
|
||||
@SerializedName("emailNotificationType")
|
||||
private String emailNotificationType;
|
||||
|
||||
@SerializedName("endPoint")
|
||||
private String endPoint;
|
||||
|
||||
@SerializedName("energy")
|
||||
private String energy;
|
||||
|
||||
@SerializedName("liliOffCommand")
|
||||
private String liliOffCommand;
|
||||
|
||||
@SerializedName("liliOnCommand")
|
||||
private String liliOnCommand;
|
||||
|
||||
@SerializedName("log")
|
||||
private String log;
|
||||
|
||||
@SerializedName("logTemp")
|
||||
private String logTemp;
|
||||
|
||||
@SerializedName("manufacturer")
|
||||
private String manufacturer;
|
||||
|
||||
@SerializedName("markAsDead")
|
||||
private String markAsDead;
|
||||
|
||||
@SerializedName("mode")
|
||||
private String mode;
|
||||
|
||||
@SerializedName("model")
|
||||
private String model;
|
||||
|
||||
@SerializedName("nodeID")
|
||||
private String nodeID;
|
||||
|
||||
@SerializedName("pollingDeadDevice")
|
||||
private String pollingDeadDevice;
|
||||
|
||||
@SerializedName("pollingTime")
|
||||
private String pollingTime;
|
||||
|
||||
@SerializedName("pollingTimeNext")
|
||||
private String pollingTimeNext;
|
||||
|
||||
@SerializedName("pollingTimeSec")
|
||||
private int pollingTimeSec;
|
||||
|
||||
@SerializedName("power")
|
||||
private String power;
|
||||
|
||||
@SerializedName("productInfo")
|
||||
private String productInfo;
|
||||
|
||||
@SerializedName("pushNotificationID")
|
||||
private String pushNotificationID;
|
||||
|
||||
@SerializedName("pushNotificationType")
|
||||
private String pushNotificationType;
|
||||
|
||||
@SerializedName("remoteGatewayId")
|
||||
private String remoteGatewayId;
|
||||
|
||||
@SerializedName("requestNodeNeighborStat")
|
||||
private String requestNodeNeighborStat;
|
||||
|
||||
@SerializedName("requestNodeNeighborStatTimeStemp")
|
||||
private String requestNodeNeighborStatTimeStemp;
|
||||
|
||||
@SerializedName("requestNodeNeighborState")
|
||||
private String requestNodeNeighborState;
|
||||
|
||||
@SerializedName("requestNodeNeighborStateTimeStemp")
|
||||
private String requestNodeNeighborStateTimeStemp;
|
||||
|
||||
@SerializedName("saveLogs")
|
||||
private String saveLogs;
|
||||
|
||||
@SerializedName("showChildren")
|
||||
private String showChildren;
|
||||
|
||||
@SerializedName("smsNotificationID")
|
||||
private String smsNotificationID;
|
||||
|
||||
@SerializedName("smsNotificationType")
|
||||
private String smsNotificationType;
|
||||
|
||||
@SerializedName("supportedModes")
|
||||
private String supportedModes;
|
||||
|
||||
@SerializedName("targetLevel")
|
||||
private String targetLevel;
|
||||
|
||||
@SerializedName("unit")
|
||||
private String unit;
|
||||
|
||||
@SerializedName("useTemplate")
|
||||
private String useTemplate;
|
||||
|
||||
@SerializedName("status")
|
||||
private String status;
|
||||
|
||||
@SerializedName("sunriseHour")
|
||||
private String sunriseHour;
|
||||
|
||||
@SerializedName("sunsetHour")
|
||||
private String sunsetHour;
|
||||
|
||||
@SerializedName("userDescription")
|
||||
private String userDescription;
|
||||
|
||||
@SerializedName("value")
|
||||
private String value;
|
||||
|
||||
@SerializedName("zwaveBuildVersion")
|
||||
private String zwaveBuildVersion;
|
||||
|
||||
@SerializedName("zwaveCompany")
|
||||
private String zwaveCompany;
|
||||
|
||||
@SerializedName("zwaveInfo")
|
||||
private String zwaveInfo;
|
||||
|
||||
@SerializedName("zwaveRegion")
|
||||
private String zwaveRegion;
|
||||
|
||||
@SerializedName("zwaveVersion")
|
||||
private double zwaveVersion;
|
||||
|
||||
public String getBatteryLevel() {
|
||||
return batteryLevel;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public String getDeviceControlType() {
|
||||
return deviceControlType;
|
||||
}
|
||||
|
||||
public String getEnergy() {
|
||||
return energy;
|
||||
}
|
||||
|
||||
public String getPower() {
|
||||
return power;
|
||||
}
|
||||
|
||||
public String getTargetLevel() {
|
||||
return targetLevel;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
// --- begin yrWeather plugin ---
|
||||
@SerializedName("Humidity")
|
||||
private String Humidity;
|
||||
|
||||
@SerializedName("Pressure")
|
||||
private String Pressure;
|
||||
|
||||
@SerializedName("Temperature")
|
||||
private String Temperature;
|
||||
|
||||
@SerializedName("WeatherCondition")
|
||||
private String WeatherCondition;
|
||||
|
||||
@SerializedName("Wind")
|
||||
private String Wind;
|
||||
|
||||
public String getHumidity() {
|
||||
return Humidity;
|
||||
}
|
||||
|
||||
public String getPressure() {
|
||||
return Pressure;
|
||||
}
|
||||
|
||||
public String getSaveLogs()
|
||||
{
|
||||
return saveLogs;
|
||||
}
|
||||
|
||||
public String getTemperature() {
|
||||
return Temperature;
|
||||
}
|
||||
|
||||
public String getWeatherCondition() {
|
||||
return WeatherCondition;
|
||||
}
|
||||
|
||||
public String getWind() {
|
||||
return Wind;
|
||||
}
|
||||
// --- end yrWeather plugin ---
|
||||
|
||||
public String getUserDescription()
|
||||
{
|
||||
return userDescription;
|
||||
}
|
||||
|
||||
public void setUserDescription(String userDescription)
|
||||
{
|
||||
this.userDescription = userDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Room {
|
||||
@SerializedName("id")
|
||||
private int id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("sectionID")
|
||||
private int sectionID;
|
||||
|
||||
@SerializedName("icon")
|
||||
private String icon;
|
||||
|
||||
@SerializedName("defaultSensors")
|
||||
private Sensor defaultSensors;
|
||||
|
||||
@SerializedName("defaultThermostat")
|
||||
private int defaultThermostat;
|
||||
|
||||
@SerializedName("sortOrder")
|
||||
private int sortOrder;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getSectionID()
|
||||
{
|
||||
return sectionID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Scene {
|
||||
private String roomName;
|
||||
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
|
||||
@SerializedName("type")
|
||||
private String type;
|
||||
|
||||
@SerializedName("properties")
|
||||
private String properties;
|
||||
|
||||
@SerializedName("roomID")
|
||||
private int roomID;
|
||||
|
||||
@SerializedName("iconID")
|
||||
private int iconID;
|
||||
|
||||
@SerializedName("runConfig")
|
||||
private String runConfig;
|
||||
|
||||
@SerializedName("autostart")
|
||||
private boolean autostart;
|
||||
|
||||
@SerializedName("protectedByPIN")
|
||||
private boolean protectedByPIN;
|
||||
|
||||
@SerializedName("killable")
|
||||
private boolean killable;
|
||||
|
||||
@SerializedName("maxRunningInstances")
|
||||
private int maxRunningInstances;
|
||||
|
||||
@SerializedName("runningInstances")
|
||||
private int runningInstances;
|
||||
|
||||
@SerializedName("visible")
|
||||
private boolean visible;
|
||||
|
||||
@SerializedName("isLua")
|
||||
private boolean isLua;
|
||||
|
||||
@SerializedName("triggers")
|
||||
private SceneTriggers triggers;
|
||||
|
||||
@SerializedName("liliStartCommand")
|
||||
private String liliStartCommand;
|
||||
|
||||
@SerializedName("liliStopCommand")
|
||||
private String liliStopCommand;
|
||||
|
||||
@SerializedName("sortOrder")
|
||||
private int sortOrder;
|
||||
|
||||
public String getRoomName() {
|
||||
return roomName;
|
||||
}
|
||||
|
||||
public void setRoomName(String roomName) {
|
||||
this.roomName = roomName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getRoomID() {
|
||||
return roomID;
|
||||
}
|
||||
|
||||
public String getLiliStartCommand()
|
||||
{
|
||||
return liliStartCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + id + ", " + name + "}";
|
||||
}
|
||||
|
||||
public String fibaroaddress;
|
||||
public String fibaroport;
|
||||
public String fibaroAuth;
|
||||
public String fibaroname;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class SceneProperties {
|
||||
@SerializedName("id")
|
||||
private String id;
|
||||
|
||||
@SerializedName("name")
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class SceneTriggers {
|
||||
@SerializedName("properties")
|
||||
private SceneProperties[] properties;
|
||||
|
||||
@SerializedName("globals")
|
||||
private String[] globals;
|
||||
|
||||
@SerializedName("events")
|
||||
private String[] events;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.bwssystems.HABridge.plugins.fibaro.json;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Sensor {
|
||||
@SerializedName("temperature")
|
||||
private int temperature;
|
||||
|
||||
@SerializedName("humidity")
|
||||
private int humidity;
|
||||
|
||||
@SerializedName("light")
|
||||
private int light;
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -26,10 +27,13 @@ public class HalHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(HalHome.class);
|
||||
private Map<String, HalInfo> hals;
|
||||
private Boolean validHal;
|
||||
private boolean closed;
|
||||
|
||||
public HalHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,7 +115,7 @@ public class HalHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
boolean halFound = false;
|
||||
String responseString = null;
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
@@ -193,7 +197,13 @@ public class HalHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
// noop
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
|
||||
hals = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.util.TextStringFormatter;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
@@ -38,7 +39,7 @@ public class HalInfo {
|
||||
|
||||
public HalInfo(NamedIP addressName, String aGivenToken) {
|
||||
super();
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
halAddress = addressName;
|
||||
if(halAddress.getPassword() == null || halAddress.getPassword().trim().isEmpty())
|
||||
halAddress.setPassword(aGivenToken);
|
||||
|
||||
@@ -18,6 +18,7 @@ import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -31,16 +32,24 @@ public class HarmonyHome implements Home {
|
||||
private Boolean isDevMode;
|
||||
private Boolean validHarmony;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public HarmonyHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
if(!validHarmony)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(isDevMode || hubs == null)
|
||||
return;
|
||||
Iterator<String> keys = hubs.keySet().iterator();
|
||||
@@ -50,6 +59,7 @@ public class HarmonyHome implements Home {
|
||||
}
|
||||
|
||||
hubs = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public HarmonyHandler getHarmonyHandler(String aName) {
|
||||
@@ -125,7 +135,7 @@ public class HarmonyHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
log.debug("executing HUE api request to change " + anItem.getType() + " to Harmony: " + device.getName());
|
||||
if(!validHarmony) {
|
||||
|
||||
@@ -5,6 +5,8 @@ import static java.lang.String.format;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -44,7 +46,7 @@ public class HarmonyServer {
|
||||
dummyProvider = null;
|
||||
myNameAndIP = theHarmonyAddress;
|
||||
isDevMode = false;
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
}
|
||||
|
||||
public static HarmonyServer setup(
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -25,10 +26,13 @@ public class HassHome implements Home {
|
||||
private Map<String, HomeAssistant> hassMap;
|
||||
private Boolean validHass;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public HassHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,7 +119,7 @@ public class HassHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String theReturn = null;
|
||||
log.debug("executing HUE api request to send message to HomeAssistant: " + anItem.getItem().toString());
|
||||
if(!validHass) {
|
||||
@@ -151,6 +155,11 @@ public class HassHome implements Home {
|
||||
public void closeHome() {
|
||||
if(!validHass)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(hassMap == null)
|
||||
return;
|
||||
Iterator<String> keys = hassMap.keySet().iterator();
|
||||
@@ -160,5 +169,6 @@ public class HassHome implements Home {
|
||||
}
|
||||
|
||||
hassMap = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class HomeAssistant {
|
||||
@@ -21,7 +22,7 @@ public class HomeAssistant {
|
||||
|
||||
public HomeAssistant(NamedIP addressName) {
|
||||
super();
|
||||
anHttpHandler = new HTTPHandler();
|
||||
anHttpHandler = HTTPHome.getHandler();
|
||||
hassAddress = addressName;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,14 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -25,13 +21,9 @@ import com.bwssystems.HABridge.api.NameValue;
|
||||
|
||||
public class HTTPHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(HTTPHandler.class);
|
||||
private CloseableHttpClient httpClient;
|
||||
private RequestConfig globalConfig;
|
||||
|
||||
|
||||
public HTTPHandler() {
|
||||
globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
|
||||
httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +36,7 @@ public class HTTPHandler {
|
||||
URI theURI = null;
|
||||
ContentType parsedContentType = null;
|
||||
StringEntity requestBody = null;
|
||||
|
||||
if (contentType != null && !contentType.trim().isEmpty()) {
|
||||
parsedContentType = ContentType.parse(contentType);
|
||||
if (body != null && body.length() > 0)
|
||||
@@ -55,6 +48,7 @@ public class HTTPHandler {
|
||||
log.warn("Error creating URI http request: " + url + " with message: " + e1.getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (httpVerb == null || httpVerb.trim().isEmpty() || HttpGet.METHOD_NAME.equalsIgnoreCase(httpVerb)) {
|
||||
request = new HttpGet(theURI);
|
||||
@@ -81,45 +75,49 @@ public class HTTPHandler {
|
||||
request.setHeader(headers[i].getName(), headers[i].getValue());
|
||||
}
|
||||
}
|
||||
HttpResponse response = null;
|
||||
CloseableHttpResponse response = null;
|
||||
for (int retryCount = 0; retryCount < 2; retryCount++) {
|
||||
try {
|
||||
response = httpClient.execute(request);
|
||||
response = HttpClientPool.getClient().execute(request);
|
||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
|
||||
+ response.getStatusLine().getStatusCode());
|
||||
if (response != null && response.getEntity() != null) {
|
||||
try {
|
||||
|
||||
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||
// content
|
||||
// for
|
||||
// data
|
||||
|
||||
EntityUtils.consume(response.getEntity()); // close out
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
} catch (Exception e) {
|
||||
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (response != null && response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||
retryCount = 2;
|
||||
} else if (response != null) {
|
||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: "
|
||||
+ response.getStatusLine());
|
||||
if (response.getStatusLine().getStatusCode() == 504) {
|
||||
log.warn("HTTP response code was 504, retrying...");
|
||||
} else
|
||||
retryCount = 2;
|
||||
|
||||
theContent = null;
|
||||
}
|
||||
|
||||
} catch (ClientProtocolException e) {
|
||||
log.warn("Client Protocol Exception received, retyring....");
|
||||
} catch (IOException e) {
|
||||
log.warn("Error calling out to HA gateway: IOException in log", e);
|
||||
}catch (IOException e) {
|
||||
log.warn("Error calling out to HA gateway: IOException in log: " + e.getMessage());
|
||||
retryCount = 2;
|
||||
}
|
||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
|
||||
+ response.getStatusLine().getStatusCode());
|
||||
if (response != null && response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||
retryCount = 2;
|
||||
} else if (response != null) {
|
||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: "
|
||||
+ response.getStatusLine());
|
||||
if (response.getStatusLine().getStatusCode() == 504) {
|
||||
log.warn("HTTP response code was 504, retrying...");
|
||||
} else
|
||||
retryCount = 2;
|
||||
}
|
||||
|
||||
if (response != null && response.getEntity() != null) {
|
||||
try {
|
||||
theContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||
// content
|
||||
// for
|
||||
// data
|
||||
EntityUtils.consume(response.getEntity()); // close out
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
} catch (Exception e) {
|
||||
log.debug("Error ocurred in handling response entity after successful call, still responding success. "
|
||||
+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if(retryCount < 2) {
|
||||
theContent = null;
|
||||
@@ -132,23 +130,6 @@ public class HTTPHandler {
|
||||
}
|
||||
return theContent;
|
||||
}
|
||||
|
||||
// public HttpClient getHttpClient() {
|
||||
// return httpClient;
|
||||
// }
|
||||
|
||||
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
|
||||
public void closeHandler() {
|
||||
try {
|
||||
httpClient.close();
|
||||
} catch (IOException e) {
|
||||
// noop
|
||||
}
|
||||
httpClient = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -18,16 +20,25 @@ import com.google.gson.Gson;
|
||||
|
||||
public class HTTPHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(HTTPHome.class);
|
||||
private HTTPHandler anHttpHandler;
|
||||
private static HTTPHandler anHttpHandler = null;
|
||||
private boolean closed;
|
||||
|
||||
public HTTPHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public static HTTPHandler getHandler() {
|
||||
if(anHttpHandler == null)
|
||||
anHttpHandler = new HTTPHandler();
|
||||
return anHttpHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
@@ -50,6 +61,9 @@ public class HTTPHome implements Home {
|
||||
|
||||
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrl,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
anUrl = ColorDecode.replaceColorData(anUrl, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
@@ -57,6 +71,9 @@ public class HTTPHome implements Home {
|
||||
if(anItem.getHttpBody()!= null && !anItem.getHttpBody().isEmpty()) {
|
||||
aBody = BrightnessDecode.calculateReplaceIntensityValue(anItem.getHttpBody(),
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
aBody = ColorDecode.replaceColorData(aBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
aBody = DeviceDataDecode.replaceDeviceData(aBody, device);
|
||||
aBody = TimeDecode.replaceTimeValue(aBody);
|
||||
}
|
||||
@@ -80,7 +97,8 @@ public class HTTPHome implements Home {
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettings bridgeSettings) {
|
||||
anHttpHandler = new HTTPHandler();
|
||||
if(anHttpHandler == null)
|
||||
anHttpHandler = new HTTPHandler();
|
||||
log.info("Http Home created.");
|
||||
return this;
|
||||
}
|
||||
@@ -93,9 +111,15 @@ public class HTTPHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(anHttpHandler != null)
|
||||
anHttpHandler.closeHandler();
|
||||
anHttpHandler = null;
|
||||
closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.bwssystems.HABridge.plugins.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class HttpClientPool {
|
||||
private static final Logger log = LoggerFactory.getLogger(HttpClientPool.class);
|
||||
|
||||
// Single-element enum to implement Singleton.
|
||||
private static enum Singleton {
|
||||
// Just one of me so constructor will be called once.
|
||||
Client;
|
||||
// The thread-safe client.
|
||||
private final CloseableHttpClient threadSafeClient;
|
||||
// The pool monitor.
|
||||
private final IdleConnectionMonitorThread monitor;
|
||||
|
||||
// The constructor creates it - thus late
|
||||
private Singleton() {
|
||||
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
|
||||
// Increase max total connection to 200
|
||||
cm.setMaxTotal(200);
|
||||
// Increase default max connection per route to 20
|
||||
cm.setDefaultMaxPerRoute(20);
|
||||
// Build the client.
|
||||
threadSafeClient = HttpClients.custom()
|
||||
.setConnectionManager(cm)
|
||||
.build();
|
||||
// Start up an eviction thread.
|
||||
monitor = new IdleConnectionMonitorThread(cm);
|
||||
// Don't stop quitting.
|
||||
monitor.setDaemon(true);
|
||||
monitor.start();
|
||||
}
|
||||
|
||||
public CloseableHttpClient get() {
|
||||
return threadSafeClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static CloseableHttpClient getClient() {
|
||||
// The thread safe client is held by the singleton.
|
||||
return Singleton.Client.get();
|
||||
}
|
||||
|
||||
// Watches for stale connections and evicts them.
|
||||
private static class IdleConnectionMonitorThread extends Thread {
|
||||
// The manager to watch.
|
||||
private final PoolingHttpClientConnectionManager cm;
|
||||
// Use a BlockingQueue to stop everything.
|
||||
private final BlockingQueue<Stop> stopSignal = new ArrayBlockingQueue<Stop>(1);
|
||||
|
||||
// Pushed up the queue.
|
||||
private static class Stop {
|
||||
// The return queue.
|
||||
private final BlockingQueue<Stop> stop = new ArrayBlockingQueue<Stop>(1);
|
||||
|
||||
// Called by the process that is being told to stop.
|
||||
public void stopped() {
|
||||
// Push me back up the queue to indicate we are now stopped.
|
||||
stop.add(this);
|
||||
}
|
||||
|
||||
// Called by the process requesting the stop.
|
||||
public void waitForStopped() throws InterruptedException {
|
||||
// Wait until the callee acknowledges that it has stopped.
|
||||
stop.take();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IdleConnectionMonitorThread(PoolingHttpClientConnectionManager cm) {
|
||||
super();
|
||||
this.cm = cm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Holds the stop request that stopped the process.
|
||||
Stop stopRequest;
|
||||
// Every 5 seconds.
|
||||
while ((stopRequest = stopSignal.poll(5, TimeUnit.SECONDS)) == null) {
|
||||
// Close expired connections
|
||||
cm.closeExpiredConnections();
|
||||
// Optionally, close connections that have been idle too long.
|
||||
cm.closeIdleConnections(60, TimeUnit.SECONDS);
|
||||
// Look at pool stats.
|
||||
log.debug("Stats: {}", cm.getTotalStats());
|
||||
}
|
||||
// Acknowledge the stop request.
|
||||
stopRequest.stopped();
|
||||
} catch (InterruptedException ex) {
|
||||
// terminate
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() throws InterruptedException, IOException {
|
||||
log.info("Shutting down client pool");
|
||||
// Signal the stop to the thread.
|
||||
Stop stop = new Stop();
|
||||
stopSignal.add(stop);
|
||||
// Wait for the stop to complete.
|
||||
stop.waitForStopped();
|
||||
// Close the pool - Added
|
||||
Singleton.Client.threadSafeClient.close();
|
||||
// Close the connection manager.
|
||||
cm.close();
|
||||
log.info("Client pool shut down");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void shutdown() throws InterruptedException, IOException {
|
||||
// Shutdown the monitor.
|
||||
Singleton.Client.monitor.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -15,6 +16,7 @@ import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -25,11 +27,14 @@ public class HueHome implements Home {
|
||||
private Boolean validHue;
|
||||
private Gson aGsonHandler;
|
||||
private BridgeSettings theBridgeSettings;
|
||||
private boolean closed;
|
||||
|
||||
public HueHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
theBridgeSettings = bridgeSettings;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,7 +91,7 @@ public class HueHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
if(!validHue)
|
||||
return null;
|
||||
String responseString = null;
|
||||
@@ -133,6 +138,11 @@ public class HueHome implements Home {
|
||||
public void closeHome() {
|
||||
if(!validHue)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
if(hues == null)
|
||||
return;
|
||||
Iterator<String> keys = hues.keySet().iterator();
|
||||
@@ -141,5 +151,6 @@ public class HueHome implements Home {
|
||||
hues.get(key).closeHue();;
|
||||
}
|
||||
hues = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
package com.bwssystems.HABridge.plugins.hue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -20,19 +13,20 @@ import com.bwssystems.HABridge.api.hue.DeviceResponse;
|
||||
import com.bwssystems.HABridge.api.hue.HueApiResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
|
||||
public class HueInfo {
|
||||
private static final Logger log = LoggerFactory.getLogger(HueInfo.class);
|
||||
private HTTPHandler httpClient;
|
||||
private HTTPHandler httpHandler;
|
||||
private NamedIP hueAddress;
|
||||
private HueHome myHome;
|
||||
public static final String HUE_REQUEST = "/api";
|
||||
|
||||
public HueInfo(NamedIP addressName, HueHome theHome) {
|
||||
super();
|
||||
httpClient = new HTTPHandler();
|
||||
httpHandler = HTTPHome.getHandler();
|
||||
hueAddress = addressName;
|
||||
myHome = theHome;
|
||||
}
|
||||
@@ -65,7 +59,7 @@ public class HueInfo {
|
||||
}
|
||||
}
|
||||
theUrl = "http://" + hueAddress.getIp() + HUE_REQUEST + "/" + hueAddress.getUsername();
|
||||
theData = httpClient.doHttpRequest(theUrl, null, null, null, null);
|
||||
theData = httpHandler.doHttpRequest(theUrl, null, null, null, null);
|
||||
if(theData != null) {
|
||||
log.debug("GET HueApiResponse - data: " + theData);
|
||||
if(theData.contains("[{\"error\":")) {
|
||||
@@ -98,35 +92,25 @@ public class HueInfo {
|
||||
public String registerWithHue() {
|
||||
UserCreateRequest theLogin = new UserCreateRequest();
|
||||
theLogin.setDevicetype("HABridge#MyMachine");
|
||||
HttpPost postRequest = new HttpPost("http://" + hueAddress.getIp() + HUE_REQUEST);
|
||||
ContentType parsedContentType = ContentType.parse("application/json");
|
||||
StringEntity requestBody = new StringEntity(new Gson().toJson(theLogin), parsedContentType);
|
||||
HttpResponse response = null;
|
||||
postRequest.setEntity(requestBody);
|
||||
HttpClient anHttpClient = httpClient.getHttpClient();
|
||||
try {
|
||||
response = anHttpClient.execute(postRequest);
|
||||
log.debug("registerWithHue - POST execute on " + hueAddress.getName() + "URL responded: " + response.getStatusLine().getStatusCode());
|
||||
if(response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300){
|
||||
String theBody = EntityUtils.toString(response.getEntity());
|
||||
log.debug("registerWithHue response data: " + theBody);
|
||||
if(theBody.contains("[{\"error\":")) {
|
||||
if(theBody.contains("link button not")) {
|
||||
|
||||
String aMessage = httpHandler.doHttpRequest("http://" + hueAddress.getIp() + HUE_REQUEST, HttpPost.METHOD_NAME, "application/json", new Gson().toJson(theLogin), null);
|
||||
|
||||
log.debug("registerWithHue - POST execute on " + hueAddress.getName() + "URL responded: " + aMessage);
|
||||
if(!aMessage.isEmpty()){
|
||||
log.debug("registerWithHue response data: " + aMessage);
|
||||
if(aMessage.contains("[{\"error\":")) {
|
||||
if(aMessage.contains("link button not")) {
|
||||
log.warn("registerWithHue needs link button pressed on HUE bridge: " + hueAddress.getName());
|
||||
}
|
||||
else
|
||||
log.warn("registerWithHue returned an unexpected error: " + theBody);
|
||||
log.warn("registerWithHue returned an unexpected error: " + aMessage);
|
||||
}
|
||||
else {
|
||||
SuccessUserResponse[] theResponses = new Gson().fromJson(theBody, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
|
||||
SuccessUserResponse[] theResponses = new Gson().fromJson(aMessage, SuccessUserResponse[].class); //read content for data, SuccessUserResponse[].class);
|
||||
hueAddress.setUsername(theResponses[0].getSuccess().getUsername());
|
||||
myHome.updateHue(hueAddress);
|
||||
}
|
||||
}
|
||||
EntityUtils.consume(response.getEntity()); //close out inputstream ignore content
|
||||
} catch (IOException e) {
|
||||
log.warn("Error logging into HUE: IOException in log", e);
|
||||
}
|
||||
return hueAddress.getUsername();
|
||||
}
|
||||
|
||||
@@ -138,7 +122,7 @@ public class HueInfo {
|
||||
registerWithHue();
|
||||
if (hueAddress.getUsername() != null) {
|
||||
// make call
|
||||
responseString = httpClient.doHttpRequest(
|
||||
responseString = httpHandler.doHttpRequest(
|
||||
"http://" + hueAddress.getIp() + "/api/" + hueAddress.getUsername()
|
||||
+ "/lights/" + hueDeviceId,
|
||||
HttpGet.METHOD_NAME, "application/json", null, null);
|
||||
@@ -167,7 +151,7 @@ public class HueInfo {
|
||||
if(hueAddress.getUsername() == null)
|
||||
registerWithHue();
|
||||
if (hueAddress.getUsername() != null) {
|
||||
responseString = httpClient.doHttpRequest(
|
||||
responseString = httpHandler.doHttpRequest(
|
||||
"http://" + deviceId.getIpAddress() + "/api/" + hueAddress.getUsername()
|
||||
+ "/lights/" + deviceId.getDeviceId() + "/state",
|
||||
HttpPut.METHOD_NAME, "application/json", body, null);
|
||||
@@ -188,8 +172,8 @@ public class HueInfo {
|
||||
}
|
||||
|
||||
public void closeHue() {
|
||||
httpClient.closeHandler();
|
||||
httpClient = null;
|
||||
httpHandler.closeHandler();
|
||||
httpHandler = null;
|
||||
}
|
||||
|
||||
public NamedIP getHueAddress() {
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.github.besherman.lifx.LFXClient;
|
||||
import com.github.besherman.lifx.LFXGroup;
|
||||
@@ -37,10 +38,13 @@ public class LifxHome implements Home {
|
||||
private LFXClient client;
|
||||
private Boolean validLifx;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public LifxHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,6 +134,7 @@ public class LifxHome implements Home {
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Boolean addLifxLights(LFXLightCollection theDeviceList) {
|
||||
if(!validLifx)
|
||||
return false;
|
||||
@@ -142,6 +147,7 @@ public class LifxHome implements Home {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private Boolean addLifxGroups(LFXGroupCollection theDeviceList) {
|
||||
if(!validLifx)
|
||||
return false;
|
||||
@@ -156,7 +162,7 @@ public class LifxHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String theReturn = null;
|
||||
float aBriValue;
|
||||
float theValue;
|
||||
@@ -210,7 +216,13 @@ public class LifxHome implements Home {
|
||||
public void closeHome() {
|
||||
if(!validLifx)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
client.close();
|
||||
closed = true;
|
||||
}
|
||||
private static class MyLightListener implements LFXLightCollectionListener {
|
||||
private static final Logger log = LoggerFactory.getLogger(MyLightListener.class);
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.eclipse.paho.client.mqttv3.MqttPersistenceException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttSecurityException;
|
||||
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
|
||||
import org.slf4j.Logger;
|
||||
@@ -53,6 +52,17 @@ public class MQTTHandler {
|
||||
message.setRetained(Optional.ofNullable(retain).orElse(false));
|
||||
|
||||
try {
|
||||
if(!myClient.isConnected()) {
|
||||
try {
|
||||
myClient.connect();
|
||||
} catch (MqttSecurityException e1) {
|
||||
log.error("Could not retry connect to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e1.getMessage());
|
||||
return;
|
||||
} catch (MqttException e1) {
|
||||
log.error("Could not retry connect to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e1.getMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
myClient.publish(topic, message);
|
||||
} catch (MqttException e) {
|
||||
log.error("Could not publish to MQTT client for name: " + myConfig.getName() + " and ip: " + myConfig.getIp() + " with message: " + e.getMessage());
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -25,16 +26,24 @@ public class MQTTHome implements Home {
|
||||
private Map<String, MQTTHandler> handlers;
|
||||
private Boolean validMqtt;
|
||||
private Gson aGsonHandler;
|
||||
private boolean closed;
|
||||
|
||||
public MQTTHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
if(!validMqtt)
|
||||
return;
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
log.debug("Shutting down MQTT handlers.");
|
||||
if(handlers != null && !handlers.isEmpty()) {
|
||||
for (String key : handlers.keySet()) {
|
||||
@@ -42,6 +51,7 @@ public class MQTTHome implements Home {
|
||||
}
|
||||
}
|
||||
handlers = null;
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public MQTTHandler getMQTTHandler(String aName) {
|
||||
@@ -76,7 +86,7 @@ public class MQTTHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
log.debug("executing HUE api request to send message to MQTT broker: " + anItem.getItem().toString());
|
||||
if (validMqtt) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -30,10 +31,13 @@ public class SomfyHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(SomfyHome.class);
|
||||
private Map<String, SomfyInfo> somfys;
|
||||
private Boolean validSomfy;
|
||||
private boolean closed;
|
||||
|
||||
public SomfyHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public SomfyInfo getSomfyHandler(String somfyName) {
|
||||
@@ -62,7 +66,7 @@ public class SomfyHome implements Home {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
if (!validSomfy) {
|
||||
log.warn("Should not get here, no somfy hub available");
|
||||
@@ -113,6 +117,12 @@ public class SomfyHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
somfys = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.bwssystems.HABridge.plugins.somfy;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.NameValue;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup.Device;
|
||||
import com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup.GetSetup;
|
||||
import com.google.gson.Gson;
|
||||
@@ -39,7 +40,7 @@ public class SomfyInfo {
|
||||
|
||||
private void initHttpClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
|
||||
if(httpClient==null) {
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -32,16 +34,18 @@ public class TCPHome implements Home {
|
||||
private byte[] sendData;
|
||||
private Map<String, Socket> theSockets;
|
||||
private Gson aGsonHandler;
|
||||
|
||||
private boolean closed;
|
||||
|
||||
public TCPHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
Socket dataSendSocket = null;
|
||||
log.debug("executing HUE api request to TCP: " + anItem.getItem().getAsString());
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
@@ -81,10 +85,16 @@ public class TCPHome implements Home {
|
||||
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
|
||||
if (theUrlBody.startsWith("0x")) {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
|
||||
if (colorData != null) {
|
||||
theUrlBody = ColorDecode.replaceColorData(theUrlBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), true);
|
||||
}
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
|
||||
} else {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
|
||||
if (colorData != null) {
|
||||
theUrlBody = ColorDecode.replaceColorData(theUrlBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
theUrlBody = StringEscapeUtils.unescapeJava(theUrlBody);
|
||||
sendData = theUrlBody.getBytes();
|
||||
@@ -137,6 +147,11 @@ public class TCPHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
log.debug("Shutting down TCP sockets.");
|
||||
if(theSockets != null && !theSockets.isEmpty()) {
|
||||
Iterator<String> keys = theSockets.keySet().iterator();
|
||||
@@ -149,6 +164,7 @@ public class TCPHome implements Home {
|
||||
}
|
||||
}
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
import com.bwssystems.HABridge.hue.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
@@ -24,16 +26,19 @@ public class UDPHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(UDPHome.class);
|
||||
private UDPDatagramSender theUDPDatagramSender;
|
||||
private byte[] sendData;
|
||||
private boolean closed;
|
||||
|
||||
public UDPHome(BridgeSettings bridgeSettings, UDPDatagramSender aUDPDatagramSender) {
|
||||
super();
|
||||
theUDPDatagramSender = aUDPDatagramSender;
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
log.debug("executing HUE api request to UDP: " + anItem.getItem().getAsString());
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
if(theUrl != null && !theUrl.isEmpty () && theUrl.startsWith("udp://")) {
|
||||
@@ -59,9 +64,18 @@ public class UDPHome implements Home {
|
||||
if (theUrlBody.startsWith("0x")) {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
|
||||
if (colorData != null) {
|
||||
theUrlBody = ColorDecode.replaceColorData(theUrlBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), true);
|
||||
}
|
||||
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
|
||||
} else {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
|
||||
|
||||
if (colorData != null) {
|
||||
theUrlBody = ColorDecode.replaceColorData(theUrlBody, colorData, BrightnessDecode.calculateIntensity(intensity, targetBri, targetBriInc), false);
|
||||
}
|
||||
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
theUrlBody = StringEscapeUtils.unescapeJava(theUrlBody);
|
||||
sendData = theUrlBody.getBytes();
|
||||
@@ -93,8 +107,12 @@ public class UDPHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.bwssystems.HABridge.Home;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.ColorData;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.plugins.vera.luupRequests.Device;
|
||||
import com.bwssystems.HABridge.plugins.vera.luupRequests.Scene;
|
||||
@@ -24,10 +25,13 @@ public class VeraHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(VeraHome.class);
|
||||
private Map<String, VeraInfo> veras;
|
||||
private Boolean validVera;
|
||||
private boolean closed;
|
||||
|
||||
public VeraHome(BridgeSettings bridgeSettings) {
|
||||
super();
|
||||
closed = true;
|
||||
createHome(bridgeSettings);
|
||||
closed = false;
|
||||
}
|
||||
|
||||
public List<Device> getDevices() {
|
||||
@@ -73,7 +77,7 @@ public class VeraHome implements Home {
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Integer targetBri,Integer targetBriInc, ColorData colorData, DeviceDescriptor device, String body) {
|
||||
// Not a device handler
|
||||
return null;
|
||||
}
|
||||
@@ -106,6 +110,12 @@ public class VeraHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
log.debug("Closing Home.");
|
||||
if(closed) {
|
||||
log.debug("Home is already closed....");
|
||||
return;
|
||||
}
|
||||
veras = null;
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.plugins.vera.luupRequests.Categorie;
|
||||
import com.bwssystems.HABridge.plugins.vera.luupRequests.Device;
|
||||
import com.bwssystems.HABridge.plugins.vera.luupRequests.Room;
|
||||
@@ -25,7 +26,7 @@ public class VeraInfo {
|
||||
|
||||
public VeraInfo(NamedIP addressName) {
|
||||
super();
|
||||
httpClient = new HTTPHandler();
|
||||
httpClient = HTTPHome.getHandler();
|
||||
veraAddress = addressName;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.apache.http.conn.util.*;
|
||||
|
||||
public class UpnpListener {
|
||||
private Logger log = LoggerFactory.getLogger(UpnpListener.class);
|
||||
private UDPDatagramSender theUDPDatagramSender;
|
||||
private MulticastSocket upnpMulticastSocket;
|
||||
private int httpServerPort;
|
||||
private String responseAddress;
|
||||
private boolean strict;
|
||||
@@ -68,33 +68,31 @@ public class UpnpListener {
|
||||
"NT: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n" +
|
||||
"USN: uuid:" + HueConstants.UUID_PREFIX + "%s\r\n\r\n";
|
||||
|
||||
public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, UDPDatagramSender aUdpDatagramSender) {
|
||||
public UpnpListener(BridgeSettingsDescriptor theSettings, BridgeControlDescriptor theControl, UDPDatagramSender aUdpDatagramSender) throws IOException {
|
||||
super();
|
||||
theUDPDatagramSender = aUdpDatagramSender;
|
||||
upnpMulticastSocket = null;
|
||||
httpServerPort = Integer.valueOf(theSettings.getServerPort());
|
||||
responseAddress = theSettings.getUpnpConfigAddress();
|
||||
strict = theSettings.isUpnpStrict();
|
||||
traceupnp = theSettings.isTraceupnp();
|
||||
useUpnpIface = theSettings.isUseupnpiface();
|
||||
bridgeControl = theControl;
|
||||
aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION);
|
||||
aHueConfig = HuePublicConfig.createConfig("temp", responseAddress, HueConstants.HUB_VERSION, theSettings.getHubmac());
|
||||
bridgeId = aHueConfig.getBridgeid();
|
||||
bridgeSNUUID = aHueConfig.getSNUUIDFromMac();
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public boolean startListening(){
|
||||
log.info("UPNP Discovery Listener starting....");
|
||||
MulticastSocket upnpMulticastSocket = null;
|
||||
Enumeration<NetworkInterface> ifs = null;
|
||||
|
||||
try {
|
||||
upnpMulticastSocket = new MulticastSocket(Configuration.UPNP_DISCOVERY_PORT);
|
||||
} 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());
|
||||
return false;
|
||||
throw(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean startListening(){
|
||||
log.info("UPNP Discovery Listener starting....");
|
||||
Enumeration<NetworkInterface> ifs = null;
|
||||
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT);
|
||||
try {
|
||||
ifs = NetworkInterface.getNetworkInterfaces();
|
||||
@@ -111,15 +109,18 @@ public class UpnpListener {
|
||||
|
||||
while (addrs.hasMoreElements()) {
|
||||
InetAddress addr = addrs.nextElement();
|
||||
if (traceupnp)
|
||||
log.info("Traceupnp: " + name + " ... has addr " + addr);
|
||||
else
|
||||
log.debug(name + " ... has addr " + addr);
|
||||
log.debug(name + " ... has addr " + addr);
|
||||
if (InetAddressUtils.isIPv4Address(addr.getHostAddress())) {
|
||||
if(!useUpnpIface)
|
||||
if(!useUpnpIface) {
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: Interface: " + name + " valid usable IP address: " + addr);
|
||||
IPsPerNic++;
|
||||
else if(addr.getHostAddress().equals(responseAddress))
|
||||
IPsPerNic++;
|
||||
}
|
||||
else if(addr.getHostAddress().equals(responseAddress)) {
|
||||
if(traceupnp)
|
||||
log.info("Traceupnp: Interface: " + name + " matches upnp config address of IP address: " + addr);
|
||||
IPsPerNic++;
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug("Checking " + name + " to our interface set");
|
||||
@@ -127,7 +128,7 @@ public class UpnpListener {
|
||||
try {
|
||||
upnpMulticastSocket.joinGroup(socketAddress, xface);
|
||||
if (traceupnp)
|
||||
log.info("Traceupnp: Adding " + name + " to our interface set");
|
||||
log.info("Traceupnp: Adding " + name + " to our upnp join interface set.");
|
||||
else
|
||||
log.debug("Adding " + name + " to our interface set");
|
||||
} catch (IOException e) {
|
||||
@@ -163,12 +164,12 @@ public class UpnpListener {
|
||||
|
||||
current = Instant.now();
|
||||
if(ChronoUnit.MILLIS.between(previous, current) > Configuration.UPNP_NOTIFY_TIMEOUT) {
|
||||
sendUpnpNotify(socketAddress.getAddress(), upnpMulticastSocket);
|
||||
sendUpnpNotify(socketAddress.getAddress());
|
||||
previous = Instant.now();
|
||||
}
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
sendUpnpNotify(socketAddress.getAddress(), upnpMulticastSocket);
|
||||
sendUpnpNotify(socketAddress.getAddress());
|
||||
} catch (IOException e) {
|
||||
log.error("UpnpListener encountered an error reading socket. Shutting down", e);
|
||||
error = true;
|
||||
@@ -201,29 +202,22 @@ public class UpnpListener {
|
||||
//Only respond to discover request for strict upnp form
|
||||
String packetString = new String(packet.getData(), 0, packet.getLength());
|
||||
if(packetString != null && packetString.startsWith("M-SEARCH * HTTP/1.1") && packetString.contains("\"ssdp:discover\"")){
|
||||
log.debug("isSSDPDiscovery Found message to be an M-SEARCH message.");
|
||||
log.debug("isSSDPDiscovery Got SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
|
||||
if(strict && (packetString.contains("ST: urn:schemas-upnp-org:device:basic:1") || packetString.contains("ST: upnp:rootdevice") || packetString.contains("ST: ssdp:all")))
|
||||
{
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
log.info("Traceupnp: SSDP M-SEARCH packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
||||
}
|
||||
else
|
||||
log.debug("isSSDPDiscovery found message to be valid under strict rules - strict: " + strict);
|
||||
log.debug("SSDP M-SEARCH packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: <<<" + packetString + ">>>");
|
||||
return true;
|
||||
}
|
||||
else if (!strict)
|
||||
{
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be an M-SEARCH message.");
|
||||
log.info("Traceupnp: isSSDPDiscovery found message to be valid under loose rules - strict: " + strict);
|
||||
log.info("Traceupnp: SSDP packet from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: " + packetString);
|
||||
log.info("Traceupnp: SSDP M-SEARCH packet (!strict) from " + packet.getAddress().getHostAddress() + ":" + packet.getPort());
|
||||
}
|
||||
else
|
||||
log.debug("isSSDPDiscovery found message to be valid under loose rules - strict: " + strict);
|
||||
log.debug("SSDP M-SEARCH packet (!strict) from " + packet.getAddress().getHostAddress() + ":" + packet.getPort() + ", body: <<<" + packetString + ">>>");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -238,39 +232,44 @@ public class UpnpListener {
|
||||
String discoveryResponse = null;
|
||||
discoveryResponse = String.format(responseTemplate1, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: sendUpnpResponse discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
||||
log.info("Traceupnp: send upnp discovery template 1 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
||||
}
|
||||
else
|
||||
log.debug("sendUpnpResponse discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
||||
theUDPDatagramSender.sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " with discovery responseTemplate1 is <<<" + discoveryResponse + ">>>");
|
||||
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
|
||||
discoveryResponse = String.format(responseTemplate2, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: sendUpnpResponse discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
||||
log.info("Traceupnp: send upnp discovery template 2 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
||||
}
|
||||
else
|
||||
log.debug("sendUpnpResponse discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
||||
theUDPDatagramSender.sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate2 is <<<" + discoveryResponse + ">>>");
|
||||
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
|
||||
discoveryResponse = String.format(responseTemplate3, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID);
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: sendUpnpResponse discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
||||
log.info("Traceupnp: send upnp discovery template 3 with response address: " + responseAddress + ":" + httpServerPort + " to address: " + requester + ":" + sourcePort);
|
||||
}
|
||||
else
|
||||
log.debug("sendUpnpResponse discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
||||
theUDPDatagramSender.sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
log.debug("sendUpnpResponse to address: " + requester + ":" + sourcePort + " discovery responseTemplate3 is <<<" + discoveryResponse + ">>>");
|
||||
sendUDPResponse(discoveryResponse.getBytes(), requester, sourcePort);
|
||||
}
|
||||
|
||||
private void sendUDPResponse(byte[] udpMessage, InetAddress requester, int sourcePort) throws IOException {
|
||||
log.debug("Sending response string: <<<" + new String(udpMessage) + ">>>");
|
||||
if(upnpMulticastSocket == null)
|
||||
throw new IOException("Socket not initialized");
|
||||
DatagramPacket response = new DatagramPacket(udpMessage, udpMessage.length, requester, sourcePort);
|
||||
upnpMulticastSocket.send(response);
|
||||
}
|
||||
|
||||
protected void sendUpnpNotify(InetAddress aSocketAddress, MulticastSocket theUpnpMulticastSocket) {
|
||||
protected void sendUpnpNotify(InetAddress aSocketAddress) {
|
||||
String notifyData = null;
|
||||
log.debug("Sending notify packet for upnp.");
|
||||
notifyData = String.format(notifyTemplate, Configuration.UPNP_MULTICAST_ADDRESS, Configuration.UPNP_DISCOVERY_PORT, responseAddress, httpServerPort, bridgeId, bridgeSNUUID, bridgeSNUUID);
|
||||
if(traceupnp) {
|
||||
log.info("Traceupnp: sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>");
|
||||
}
|
||||
log.debug("sendUpnpNotify notifyTemplate is <<<" + notifyData + ">>>");
|
||||
DatagramPacket notifyPacket = new DatagramPacket(notifyData.getBytes(), notifyData.length(), aSocketAddress, Configuration.UPNP_DISCOVERY_PORT);
|
||||
try {
|
||||
theUpnpMulticastSocket.send(notifyPacket);
|
||||
upnpMulticastSocket.send(notifyPacket);
|
||||
} catch (IOException e1) {
|
||||
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);
|
||||
|
||||
@@ -70,21 +70,17 @@ public class UpnpSettingsResource {
|
||||
}
|
||||
|
||||
public void setupServer() {
|
||||
log.info("Hue description service started....");
|
||||
log.info("Description xml service started....");
|
||||
// http://ip_adress:port/description.xml which returns the xml configuration for the hue emulator
|
||||
get("/description.xml", "application/xml; charset=utf-8", (request, response) -> {
|
||||
if(theSettings.isTraceupnp())
|
||||
log.info("Traceupnp: upnp device settings requested: " + " from " + request.ip() + ":" + request.port());
|
||||
else
|
||||
log.debug("upnp device settings requested: " + " from " + request.ip() + ":" + request.port());
|
||||
String portNumber = Integer.toString(request.port());
|
||||
String filledTemplate = null;
|
||||
String bridgeIdMac = HuePublicConfig.createConfig("temp", theSettings.getUpnpConfigAddress(), HueConstants.HUB_VERSION).getSNUUIDFromMac();
|
||||
String bridgeIdMac = HuePublicConfig.createConfig("temp", theSettings.getUpnpConfigAddress(), HueConstants.HUB_VERSION, theSettings.getHubmac()).getSNUUIDFromMac();
|
||||
filledTemplate = String.format(hueTemplate, theSettings.getUpnpConfigAddress(), portNumber, theSettings.getUpnpConfigAddress(), bridgeIdMac, bridgeIdMac);
|
||||
if(theSettings.isTraceupnp())
|
||||
log.info("Traceupnp: upnp device settings template filled with address: " + theSettings.getUpnpConfigAddress() + " and port: " + portNumber);
|
||||
log.info("Traceupnp: request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + theSettings.getUpnpConfigAddress() + ":" + portNumber);
|
||||
else
|
||||
log.debug("Traceupnp: upnp device settings template filled with address: " + theSettings.getUpnpConfigAddress() + " and port: " + portNumber);
|
||||
log.debug("request of description.xml from: " + request.ip() + ":" + request.port() + " filled in with address: " + theSettings.getUpnpConfigAddress() + ":" + portNumber);
|
||||
// response.header("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
|
||||
// response.header("Pragma", "no-cache");
|
||||
// response.header("Expires", "Mon, 1 Aug 2011 09:00:00 GMT");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.scrollableContainer {
|
||||
height: 310px;
|
||||
/* height: 310px; */
|
||||
position: relative;
|
||||
padding-top: 35px;
|
||||
overflow: hidden;
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
.scrollArea {
|
||||
height: 100%;
|
||||
max-height: 800px;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #d5d5d5;
|
||||
|
||||
BIN
src/main/resources/public/img/favicon.ico
Normal file
BIN
src/main/resources/public/img/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -5,6 +5,7 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>HA Bridge</title>
|
||||
<link rel="shortcut icon" href="img/favicon.ico?v=2">
|
||||
<link href="css/main.css" rel="stylesheet">
|
||||
<link href="css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="css/bootstrap-theme.min.css" rel="stylesheet">
|
||||
|
||||
@@ -26,7 +26,15 @@ app.config (function ($locationProvider, $routeProvider) {
|
||||
}).when ('/verascenes', {
|
||||
templateUrl: 'views/verascene.html',
|
||||
controller: 'VeraController',
|
||||
requiresAuthentication: true
|
||||
}).when ('/fibarodevices', {
|
||||
templateUrl: 'views/fibarodevice.html',
|
||||
controller: 'FibaroController',
|
||||
requiresAuthentication: true
|
||||
}).when ('/fibaroscenes', {
|
||||
templateUrl: 'views/fibaroscene.html',
|
||||
controller: 'FibaroController',
|
||||
requiresAuthentication: true
|
||||
}).when ('/harmonydevices', {
|
||||
templateUrl: 'views/harmonydevice.html',
|
||||
controller: 'HarmonyController',
|
||||
@@ -101,8 +109,9 @@ app.run(function ($rootScope, $location, Auth, bridgeService) {
|
||||
|
||||
$rootScope.$on('securityReinit', function(event, data) {
|
||||
event.preventDefault();
|
||||
bridgeService.state.testuser = "";
|
||||
Auth.logout();
|
||||
$location.path("/login");
|
||||
$location.path("/");
|
||||
});
|
||||
|
||||
$rootScope.$on('$routeChangeStart', function (event, next) {
|
||||
@@ -133,8 +142,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
var self = this;
|
||||
this.state = {base: "./api/devices", bridgelocation: ".", systemsbase: "./system", huebase: "./api", configs: [], backups: [], devices: [], device: {},
|
||||
mapandid: [], type: "", settings: [], myToastMsg: [], logMsgs: [], loggerInfo: [], mapTypes: [], olddevicename: "", logShowAll: false,
|
||||
isInControl: false, showVera: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false,
|
||||
showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}};
|
||||
isInControl: false, showVera: false, showFibaro: false, showHarmony: false, showNest: false, showHue: false, showHal: false, showMqtt: false, showHass: false,
|
||||
showDomoticz: false, showSomfy: false, showLifx: false, habridgeversion: {}, viewDevId: "", queueDevId: "", securityInfo: {}, filterDevicesByIpAddress: null,
|
||||
filterDevicesOnlyFiltered: false, filterDeviceType: null};
|
||||
|
||||
this.displayWarn = function(errorTitle, error) {
|
||||
var toastContent = errorTitle;
|
||||
@@ -207,7 +217,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
if (error.status === 401)
|
||||
$rootScope.$broadcast('securityReinit', 'done');
|
||||
else
|
||||
self.displayError("Cannot renumber devices from habridge: ", error);
|
||||
self.displayError("Cannot renumber devices from habridge: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -240,7 +250,12 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
|
||||
this.getTestUser = function () {
|
||||
if(self.state.testuser === undefined || self.state.testuser === "") {
|
||||
return $http.put(this.state.systemsbase + "/presslinkbutton").then(
|
||||
var linkParams = {};
|
||||
linkParams = {
|
||||
seconds: 3,
|
||||
silent: true
|
||||
};
|
||||
return $http.put(this.state.systemsbase + "/presslinkbutton", linkParams).then(
|
||||
function (response) {
|
||||
self.getAUser();
|
||||
},
|
||||
@@ -278,7 +293,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
if (error.status === 401)
|
||||
$rootScope.$broadcast('securityReinit', 'done');
|
||||
else
|
||||
self.displayWarn("Cannot get security info: ", error);
|
||||
self.displayWarn("Cannot get security info: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -410,6 +425,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
|
||||
if(device.offUrl !== undefined && device.offUrl !== null && device.offUrl.indexOf(aType) >= 0)
|
||||
return true;
|
||||
|
||||
if(device.colorUrl !== undefined && device.colorUrl !== null && device.colorUrl.indexOf(aType) >= 0)
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
@@ -455,6 +473,11 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
this.state.showVera = self.state.settings.veraconfigured;
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateShowFibaro = function () {
|
||||
this.state.showFibaro = self.state.settings.fibaroconfigured;
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateShowNest = function () {
|
||||
this.state.showNest = self.state.settings.nestconfigured;
|
||||
@@ -506,6 +529,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
function (response) {
|
||||
self.state.settings = response.data;
|
||||
self.updateShowVera();
|
||||
self.updateShowFibaro();
|
||||
self.updateShowHarmony();
|
||||
self.updateShowNest();
|
||||
self.updateShowHue();
|
||||
@@ -644,6 +668,38 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.viewFibaroDevices = function () {
|
||||
if(!this.state.showFibaro)
|
||||
return;
|
||||
return $http.get(this.state.base + "/fibaro/devices").then(
|
||||
function (response) {
|
||||
self.state.fibarodevices = response.data;
|
||||
},
|
||||
function (error) {
|
||||
if (error.status === 401)
|
||||
$rootScope.$broadcast('securityReinit', 'done');
|
||||
else
|
||||
self.displayWarn("Get Fibaro Devices Error: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.viewFibaroScenes = function () {
|
||||
if(!this.state.showFibaro)
|
||||
return;
|
||||
return $http.get(this.state.base + "/fibaro/scenes").then(
|
||||
function (response) {
|
||||
self.state.fibaroscenes = response.data;
|
||||
},
|
||||
function (error) {
|
||||
if (error.status === 401)
|
||||
$rootScope.$broadcast('securityReinit', 'done');
|
||||
else
|
||||
self.displayWarn("Get Fibaro Scenes Error: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.viewHarmonyActivities = function () {
|
||||
if (!this.state.showHarmony)
|
||||
@@ -1152,7 +1208,7 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
msgDescription = "success " + angular.toJson(response.data);
|
||||
}
|
||||
if (typeof(response.data[0].error) !== 'undefined') {
|
||||
if(reponse.data[0].error.indexOf("unauthorized") > -1) {
|
||||
if(response.data[0].error.description.indexOf("unauthorized") > -1) {
|
||||
self.displayWarn("Authorization error, please retry...", null);
|
||||
}
|
||||
else {
|
||||
@@ -1185,17 +1241,20 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
return formattedItem;
|
||||
};
|
||||
|
||||
this.buildUrls = function (onpayload, dimpayload, offpayload, isObject, anId, deviceName, deviceTarget, deviceType, deviceMapType, count, delay) {
|
||||
this.buildUrls = function (onpayload, dimpayload, offpayload, colorpayload, isObject, anId, deviceName, deviceTarget, deviceType, deviceMapType, count, delay) {
|
||||
var currentOn = "";
|
||||
var currentDim = "";
|
||||
var currentOff = "";
|
||||
var currentColor = "";
|
||||
if (self.state.device !== undefined && self.state.device !== null) {
|
||||
if (self.state.device.onUrl !== undefined && self.state.device.onUrl !== null&& self.state.device.onUrl !== "")
|
||||
currentOn = self.state.device.onUrl;
|
||||
if (self.state.device.dimUrl !== undefined && self.state.device.dimUrl !== null && self.state.device.dimUrl !== "")
|
||||
currentDim = self.state.device.dimUrl;
|
||||
if (self.state.device.offUrl !== undefined && self.state.device.offnUrl !== null && self.state.device.offnUrl !== "")
|
||||
if (self.state.device.offUrl !== undefined && self.state.device.offUrl !== null && self.state.device.offUrl !== "")
|
||||
currentOff = self.state.device.offUrl;
|
||||
if (self.state.device.colorUrl !== undefined && self.state.device.colorUrl !== null && self.state.device.colorUrl !== "")
|
||||
currentColor = self.state.device.colorUrl;
|
||||
}
|
||||
if (self.state.device !== undefined && self.state.device !== null && self.state.device.mapType !== undefined && self.state.device.mapType !== null && self.state.device.mapType !== "") {
|
||||
self.state.device.mapId = self.state.device.mapId + "-" + anId;
|
||||
@@ -1210,6 +1269,9 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "") {
|
||||
self.state.device.offUrl = self.formatUrlItem(currentOff);
|
||||
}
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "") {
|
||||
self.state.device.colorUrl = self.formatUrlItem(currentColor);
|
||||
}
|
||||
} else if (self.state.device === undefined || self.state.device === null || self.state.device.mapType === undefined || self.state.device.mapType === null || self.state.device.mapType === "") {
|
||||
this.clearDevice();
|
||||
self.state.device.deviceType = deviceType;
|
||||
@@ -1223,6 +1285,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device.onUrl = "[{\"item\":";
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "")
|
||||
self.state.device.offUrl = "[{\"item\":";
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "")
|
||||
self.state.device.colorUrl = "[{\"item\":";
|
||||
}
|
||||
|
||||
if (isObject) {
|
||||
@@ -1232,6 +1296,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device.onUrl = self.state.device.onUrl + onpayload;
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "")
|
||||
self.state.device.offUrl = self.state.device.offUrl + offpayload;
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "")
|
||||
self.state.device.colorUrl = self.state.device.colorUrl + colorpayload;
|
||||
|
||||
} else {
|
||||
if (dimpayload !== undefined && dimpayload !== null && dimpayload !== "")
|
||||
@@ -1240,6 +1306,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device.onUrl = self.state.device.onUrl + "\"" + onpayload + "\"";
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "")
|
||||
self.state.device.offUrl = self.state.device.offUrl + "\"" + offpayload + "\"";
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "")
|
||||
self.state.device.colorUrl = self.state.device.colorUrl + "\"" + colorpayload + "\"";
|
||||
}
|
||||
|
||||
if (count !== undefined && count !== null && count !== "") {
|
||||
@@ -1249,6 +1317,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device.onUrl = self.state.device.onUrl + ",\"count\":\"" + count;
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "")
|
||||
self.state.device.offUrl = self.state.device.offUrl + ",\"count\":\"" + count;
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "")
|
||||
self.state.device.colorUrl = self.state.device.colorUrl + ",\"count\":\"" + count;
|
||||
}
|
||||
if (delay !== undefined && delay !== null && delay !== "") {
|
||||
if (dimpayload !== undefined && dimpayload !== null && dimpayload !== "")
|
||||
@@ -1257,6 +1327,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device.onUrl = self.state.device.onUrl + ",\"delay\":\"" + delay;
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "")
|
||||
self.state.device.offUrl = self.state.device.offUrl + ",\"delay\":\"" + delay;
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "")
|
||||
self.state.device.colorUrl = self.state.device.colorUrl + ",\"delay\":\"" + delay;
|
||||
}
|
||||
if (dimpayload !== undefined && dimpayload !== null && dimpayload !== "")
|
||||
self.state.device.dimUrl = self.state.device.dimUrl + ",\"type\":\"" + deviceMapType + "\"}]";
|
||||
@@ -1264,6 +1336,8 @@ app.service ('bridgeService', function ($rootScope, $http, $base64, $location, n
|
||||
self.state.device.onUrl = self.state.device.onUrl + ",\"type\":\"" + deviceMapType + "\"}]";
|
||||
if (offpayload !== undefined && offpayload !== null && offpayload !== "")
|
||||
self.state.device.offUrl = self.state.device.offUrl + ",\"type\":\"" + deviceMapType + "\"}]";
|
||||
if (colorpayload !== undefined && colorpayload !== null && colorpayload !== "")
|
||||
self.state.device.colorUrl = self.state.device.colorUrl + ",\"type\":\"" + deviceMapType + "\"}]";
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1291,6 +1365,25 @@ app.controller ('SystemController', function ($scope, $location, bridgeService,
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.addFibarotoSettings = function (newfibaroname, newfibaroip, newfibaroport, newfibarousername, newfibaropassword) {
|
||||
if($scope.bridge.settings.fibaroaddress === undefined || $scope.bridge.settings.fibaroaddress === null) {
|
||||
$scope.bridge.settings.fibaroaddress = { devices: [] };
|
||||
}
|
||||
var newFibaro = {name: newfibaroname, ip: newfibaroip, port: newfibaroport, username: newfibarousername, password: newfibaropassword }
|
||||
$scope.bridge.settings.fibaroaddress.devices.push(newFibaro);
|
||||
$scope.newfibaroname = null;
|
||||
$scope.newfibaroip = null;
|
||||
$scope.newfibaroport = null;
|
||||
$scope.newfibarousername = null;
|
||||
$scope.newfibaropassword = null;
|
||||
};
|
||||
$scope.removeFibarotoSettings = function (fibaroname, fibaroip, fibaroport) {
|
||||
for(var i = $scope.bridge.settings.fibaroaddress.devices.length - 1; i >= 0; i--) {
|
||||
if($scope.bridge.settings.fibaroaddress.devices[i].name === fibaroname && $scope.bridge.settings.fibaroaddress.devices[i].ip === fibaroip && $scope.bridge.settings.fibaroaddress.devices[i].port === fibaroport) {
|
||||
$scope.bridge.settings.fibaroaddress.devices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.addHarmonytoSettings = function (newharmonyname, newharmonyip, newharmonywebhook) {
|
||||
if($scope.bridge.settings.harmonyaddress === undefined || $scope.bridge.settings.harmonyaddress === null) {
|
||||
$scope.bridge.settings.harmonyaddress = { devices: [] };
|
||||
@@ -1544,7 +1637,8 @@ app.controller('SecurityDialogCtrl', function ($scope, bridgeService, ngDialog)
|
||||
if(bridgeService.state.loggedInUser !== undefined)
|
||||
$scope.username = bridgeService.state.loggedInUser;
|
||||
else
|
||||
$scope.username = ""
|
||||
$scope.username = "";
|
||||
bridgeService.getHABridgeVersion();
|
||||
$scope.showPassword = $scope.isSecure;
|
||||
};
|
||||
|
||||
@@ -1639,7 +1733,7 @@ app.controller('ViewingController', function ($scope, $location, bridgeService,
|
||||
var dialogNeeded = false;
|
||||
if ((type === "on" && device.onUrl !== undefined && bridgeService.aContainsB(device.onUrl, "${intensity")) ||
|
||||
(type === "off" && device.offUrl !== undefined && bridgeService.aContainsB(device.offUrl, "${intensity")) ||
|
||||
(type === "dim" && device.dimUrl !== undefined)) {
|
||||
(type === "dim" && device.dimUrl !== undefined) || (type === "color" && device.colorUrl !== undefined)) {
|
||||
$scope.bridge.device = device;
|
||||
$scope.bridge.type = type;
|
||||
ngDialog.open({
|
||||
@@ -1783,10 +1877,10 @@ app.controller('VeraController', function ($scope, $location, bridgeService, ngD
|
||||
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1&DeviceNum="
|
||||
+ veradevice.id;
|
||||
offpayload = "http://" + veradevice.veraaddress + ":" + $scope.vera.port
|
||||
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum="
|
||||
+ veradevice.id;
|
||||
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, veradevice.id, veradevice.name, veradevice.veraname, "switch", "veraDevice", null, null);
|
||||
+ "/data_request?id=action&output_format=json&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=0&DeviceNum="
|
||||
+ veradevice.id;
|
||||
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, false, veradevice.id, veradevice.name, veradevice.veraname, "switch", "veraDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -1802,7 +1896,7 @@ app.controller('VeraController', function ($scope, $location, bridgeService, ngD
|
||||
+ "/data_request?id=action&output_format=json&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunScene&SceneNum="
|
||||
+ verascene.id;
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, verascene.id, verascene.name, verascene.veraname, "scene", "veraScene", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, false, verascene.id, verascene.name, verascene.veraname, "scene", "veraScene", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -1824,6 +1918,7 @@ app.controller('VeraController', function ($scope, $location, bridgeService, ngD
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -1904,6 +1999,148 @@ app.controller('VeraController', function ($scope, $location, bridgeService, ngD
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('FibaroController', function ($scope, $location, bridgeService, ngDialog) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.device_dim_control = "";
|
||||
$scope.bulk = { devices: [] };
|
||||
$scope.selectAll = false;
|
||||
$scope.fibaro = {base: "http://", port: "80", id: ""};
|
||||
bridgeService.viewFibaroDevices();
|
||||
bridgeService.viewFibaroScenes();
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
$scope.buttonsVisible = false;
|
||||
$scope.comparatorUniqueId = bridgeService.compareUniqueId;
|
||||
|
||||
$scope.clearDevice = function () {
|
||||
bridgeService.clearDevice();
|
||||
$scope.device = bridgeService.state.device;
|
||||
};
|
||||
|
||||
$scope.buildDeviceUrls = function (fibarodevice, dim_control, buildonly) {
|
||||
if(dim_control.indexOf("byte") >= 0 || dim_control.indexOf("percent") >= 0 || dim_control.indexOf("math") >= 0)
|
||||
dimpayload = "http://" + fibarodevice.fibaroaddress + ":" + fibarodevice.fibaroport + "/api/callAction?deviceID=" + fibarodevice.id + "&name=setValue&arg1=" + dim_control;
|
||||
|
||||
onpayload = "http://" + fibarodevice.fibaroaddress + ":" + fibarodevice.fibaroport + "/api/callAction?deviceID=" + fibarodevice.id + "&name=turnOn";
|
||||
offpayload = "http://" + fibarodevice.fibaroaddress + ":" + fibarodevice.fibaroport + "/api/callAction?deviceID=" + fibarodevice.id + "&name=turnOff";
|
||||
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, fibarodevice.id, fibarodevice.name, fibarodevice.fibaroname, "switch", "fibaroDevice", null, null);
|
||||
bridgeService.state.device.headers = "[{\"name\":\"Authorization\",\"value\":\"" + fibarodevice.fibaroAuth + "\"}]";
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
}
|
||||
};
|
||||
|
||||
$scope.buildSceneUrls = function (fibaroscene) {
|
||||
onpayload = "http://" + fibaroscene.fibaroaddress + ":" + fibaroscene.fibaroport + "/api/sceneControl?id=" + fibaroscene.id + "&action=start";
|
||||
offpayload = "http://" + fibaroscene.fibaroaddress + ":" + fibaroscene.fibaroport + "/api/sceneControl?id=" + fibaroscene.id + "&action=stop";
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, fibaroscene.id, fibaroscene.name, fibaroscene.fibaroname, "scene", "fibaroScene", null, null);
|
||||
bridgeService.state.device.headers = "[{\"name\":\"Authorization\",\"value\":\"" + fibaroscene.fibaroAuth + "\"}]";
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
};
|
||||
|
||||
$scope.bulkAddDevices = function(dim_control) {
|
||||
var devicesList = [];
|
||||
$scope.clearDevice();
|
||||
for(var i = 0; i < $scope.bulk.devices.length; i++) {
|
||||
for(var x = 0; x < bridgeService.state.fibarodevices.length; x++) {
|
||||
if(bridgeService.state.fibarodevices[x].id === $scope.bulk.devices[i]) {
|
||||
$scope.buildDeviceUrls(bridgeService.state.fibarodevices[x],dim_control,true);
|
||||
devicesList[i] = {
|
||||
name: $scope.device.name,
|
||||
mapId: $scope.device.mapId,
|
||||
mapType: $scope.device.mapType,
|
||||
deviceType: $scope.device.deviceType,
|
||||
targetDevice: $scope.device.targetDevice,
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
contentBody: $scope.device.contentBody,
|
||||
contentBodyDim: $scope.device.contentBodyDim,
|
||||
contentBodyOff: $scope.device.contentBodyOff
|
||||
};
|
||||
$scope.clearDevice();
|
||||
}
|
||||
}
|
||||
}
|
||||
bridgeService.bulkAddDevice(devicesList).then(
|
||||
function () {
|
||||
$scope.clearDevice();
|
||||
bridgeService.viewDevices();
|
||||
bridgeService.viewfibaroDevices();
|
||||
bridgeService.viewfibaroScenes();
|
||||
},
|
||||
function (error) {
|
||||
bridgeService.displayWarn("Error adding fibaro devices in bulk.", error)
|
||||
}
|
||||
);
|
||||
$scope.bulk = { devices: [] };
|
||||
$scope.selectAll = false;
|
||||
};
|
||||
|
||||
$scope.toggleSelection = function toggleSelection(deviceId) {
|
||||
var idx = $scope.bulk.devices.indexOf(deviceId);
|
||||
|
||||
// is currently selected
|
||||
if (idx > -1) {
|
||||
$scope.bulk.devices.splice(idx, 1);
|
||||
if($scope.bulk.devices.length === 0 && $scope.selectAll)
|
||||
$scope.selectAll = false;
|
||||
}
|
||||
|
||||
// is newly selected
|
||||
else {
|
||||
$scope.bulk.devices.push(deviceId);
|
||||
$scope.selectAll = true;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.toggleSelectAll = function toggleSelectAll() {
|
||||
if($scope.selectAll) {
|
||||
$scope.selectAll = false;
|
||||
$scope.bulk = { devices: [] };
|
||||
}
|
||||
else {
|
||||
$scope.selectAll = true;
|
||||
for(var x = 0; x < bridgeService.state.fibarodevices.length; x++) {
|
||||
if($scope.bulk.devices.indexOf(bridgeService.state.fibarodevices[x]) < 0)
|
||||
$scope.bulk.devices.push(bridgeService.state.fibarodevices[x].id);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.toggleButtons = function () {
|
||||
$scope.buttonsVisible = !$scope.buttonsVisible;
|
||||
if($scope.buttonsVisible)
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-minus";
|
||||
else
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
|
||||
$scope.deleteDevice = function (device) {
|
||||
$scope.bridge.device = device;
|
||||
ngDialog.open({
|
||||
template: 'deleteDialog',
|
||||
controller: 'DeleteDialogCtrl',
|
||||
className: 'ngdialog-theme-default'
|
||||
});
|
||||
};
|
||||
|
||||
$scope.editDevice = function (device) {
|
||||
bridgeService.editDevice(device);
|
||||
$location.path('/editdevice');
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
app.controller('HarmonyController', function ($scope, $location, bridgeService, ngDialog) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.device = bridgeService.state.device;
|
||||
@@ -1924,7 +2161,7 @@ app.controller('HarmonyController', function ($scope, $location, bridgeService,
|
||||
onpayload = "{\"name\":\"" + harmonyactivity.activity.id + "\",\"hub\":\"" + harmonyactivity.hub + "\"}";
|
||||
offpayload = "{\"name\":\"-1\",\"hub\":\"" + harmonyactivity.hub + "\"}";
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, harmonyactivity.activity.id, harmonyactivity.activity.label, harmonyactivity.hub, "activity", "harmonyActivity", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, harmonyactivity.activity.id, harmonyactivity.activity.label, harmonyactivity.hub, "activity", "harmonyActivity", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -1943,7 +2180,7 @@ app.controller('HarmonyController', function ($scope, $location, bridgeService,
|
||||
postCmd = "\"}";
|
||||
offpayload = "{\"device\":\"" + harmonydevice.device.id + "\",\"button\":\"" + actionOff.command + "\",\"hub\":\"" + harmonydevice.hub + postCmd;
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, actionOn.command, harmonydevice.device.label, harmonydevice.hub, "button", "harmonyButton", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, actionOn.command, harmonydevice.device.label, harmonydevice.hub, "button", "harmonyButton", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -1987,7 +2224,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
$scope.buildNestHomeUrls = function (nestitem) {
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"away\":false,\"control\":\"status\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"away\":true,\"control\":\"status\"}";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, nestitem.id, nestitem.name, nestitem.name, "home", "nestHomeAway", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, nestitem.id, nestitem.name, nestitem.name, "home", "nestHomeAway", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -1997,7 +2234,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
|
||||
dimpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, nestitem.id + "-SetTemp", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Temperature", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, nestitem.id + "-SetTemp", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Temperature", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2007,7 +2244,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"heat\"}";
|
||||
dimpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, nestitem.id + "-SetHeat", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Heat", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, nestitem.id + "-SetHeat", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Heat", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2017,7 +2254,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"cool\"}";
|
||||
dimpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"temp\",\"temp\":\"${intensity.percent}\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||
bridgeService.buildUrls(onpayload,dimpayload, offpayload, true, nestitem.id + "-SetCool", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Cool", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload,dimpayload, offpayload, null, true, nestitem.id + "-SetCool", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Cool", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2026,7 +2263,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
$scope.buildNestRangeUrls = function (nestitem) {
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"range\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, nestitem.id + "-SetRange", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Range", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, nestitem.id + "-SetRange", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Range", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2035,7 +2272,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
$scope.buildNestOffUrls = function (nestitem) {
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"range\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"off\"}";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, nestitem.id + "-TurnOff", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Thermostat", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, nestitem.id + "-TurnOff", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Thermostat", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2044,7 +2281,7 @@ app.controller('NestController', function ($scope, $location, bridgeService, ngD
|
||||
$scope.buildNestFanUrls = function (nestitem) {
|
||||
onpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"fan-on\"}";
|
||||
offpayload = "{\"name\":\"" + nestitem.id + "\",\"control\":\"fan-auto\"}";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, nestitem.id + "-SetFan", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Fan", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, nestitem.id + "-SetFan", nestitem.name.substr(0, nestitem.name.indexOf("(")) + " Fan", nestitem.location, "thermo", "nestThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2090,7 +2327,7 @@ app.controller('HueController', function ($scope, $location, bridgeService, ngDi
|
||||
$scope.buildDeviceUrls = function (huedevice, buildonly) {
|
||||
onpayload = "{\"ipAddress\":\"" + huedevice.hueaddress + "\",\"deviceId\":\"" + huedevice.huedeviceid +"\",\"hueName\":\"" + huedevice.huename + "\"}";
|
||||
offpayload = "{\"ipAddress\":\"" + huedevice.hueaddress + "\",\"deviceId\":\"" + huedevice.huedeviceid +"\",\"hueName\":\"" + huedevice.huename + "\"}";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, huedevice.device.uniqueid, huedevice.device.name, huedevice.huename, "passthru", "hueDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, huedevice.device.uniqueid, huedevice.device.name, huedevice.huename, "passthru", "hueDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2114,6 +2351,7 @@ app.controller('HueController', function ($scope, $location, bridgeService, ngDi
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -2257,7 +2495,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
+ preOffCmd
|
||||
+ nameCmd
|
||||
+ haldevice.haldevicename.replaceAll(" ", "%20");
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name, haldevice.haldevicename, haldevice.haladdress.name, aDeviceType, "halDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name, haldevice.haldevicename, haldevice.haladdress.name, aDeviceType, "halDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2271,7 +2509,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
onpayload = "http://" + haldevice.haladdress.ip + "/IrService!IrCmd=Set!IrDevice=" + haldevice.haldevicename.replaceAll(" ", "%20") + "!IrButton=" + actionOn.DeviceName.replaceAll(" ", "%20");
|
||||
offpayload = "http://" + haldevice.haladdress.ip + "/IrService!IrCmd=Set!IrDevice=" + haldevice.haldevicename.replaceAll(" ", "%20") + "!IrButton=" + actionOff.DeviceName.replaceAll(" ", "%20");
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-" + actionOn.DeviceName, haldevice.haldevicename, haldevice.haladdress.name, "button", "halButton", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-" + actionOn.DeviceName, haldevice.haldevicename, haldevice.haladdress.name, "button", "halButton", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2282,7 +2520,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
$scope.buildHALHomeUrls = function (haldevice, buildonly) {
|
||||
onpayload = "http://" + haldevice.haladdress.ip + "/ModeService!ModeCmd=Set!ModeName=Home";
|
||||
offpayload = "http://" + haldevice.haladdress.ip + "/ModeService!ModeCmd=Set!ModeName=Away";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-HomeAway", haldevice.haldevicename, haldevice.haladdress.name, "home", "halHome", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-HomeAway", haldevice.haldevicename, haldevice.haladdress.name, "home", "halHome", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2303,7 +2541,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
+ "/HVACService!HVACCmd=Set!HVACName="
|
||||
+ haldevice.haldevicename.replaceAll(" ", "%20")
|
||||
+ "!HVACMode=Off";
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetHeat", haldevice.haldevicename + " Heat", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetHeat", haldevice.haldevicename + " Heat", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2324,7 +2562,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
+ "/HVACService!HVACCmd=Set!HVACName="
|
||||
+ haldevice.haldevicename.replaceAll(" ", "%20")
|
||||
+ "!HVACMode=Off";
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetCool", haldevice.haldevicename + " Cool", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetCool", haldevice.haldevicename + " Cool", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2341,7 +2579,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
+ "/HVACService!HVACCmd=Set!HVACName="
|
||||
+ haldevice.haldevicename.replaceAll(" ", "%20")
|
||||
+ "!HVACMode=Off";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetAuto", haldevice.haldevicename + " Auto", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetAuto", haldevice.haldevicename + " Auto", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2358,7 +2596,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
+ "/HVACService!HVACCmd=Set!HVACName="
|
||||
+ haldevice.haldevicename.replaceAll(" ", "%20")
|
||||
+ "!HVACMode=Off";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-TurnOff", haldevice.haldevicename + " Thermostat", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-TurnOff", haldevice.haldevicename + " Thermostat", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2375,7 +2613,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
+ "/HVACService!HVACCmd=Set!HVACName="
|
||||
+ haldevice.haldevicename.replaceAll(" ", "%20")
|
||||
+ "!FanMode=Auto";
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetFan", haldevice.haldevicename + " Fan", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, false, haldevice.haldevicename + "-" + haldevice.haladdress.name + "-SetFan", haldevice.haldevicename + " Fan", haldevice.haladdress.name, "thermo", "halThermoSet", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2404,6 +2642,7 @@ app.controller('HalController', function ($scope, $location, bridgeService, ngDi
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -2499,7 +2738,7 @@ app.controller('MQTTController', function ($scope, $location, bridgeService, ngD
|
||||
onpayload = "{\"clientId\":\"" + mqttbroker.clientId + "\",\"topic\":\"" + mqtttopic + "\",\"message\":\"" + mqttmessage + "\",\"qos\":\"" + mqttqos + "\",\"retain\":\"" + mqttretain + "\"}";
|
||||
offpayload = "{\"clientId\":\"" + mqttbroker.clientId + "\",\"topic\":\"" + mqtttopic + "\",\"message\":\"" + mqttmessage + "\",\"qos\":\"" + mqttqos + "\",\"retain\":\"" + mqttretain + "\"}";
|
||||
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, true, mqttbroker.clientId + "-" + mqtttopic, mqttbroker.clientId + mqtttopic, mqttbroker.clientId, "mqtt", "mqttMessage", null, null);
|
||||
bridgeService.buildUrls(onpayload, null, offpayload, null, true, mqttbroker.clientId + "-" + mqtttopic, mqttbroker.clientId + mqtttopic, mqttbroker.clientId, "mqtt", "mqttMessage", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
$location.path('/editdevice');
|
||||
@@ -2551,7 +2790,7 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD
|
||||
dimpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"on\"}";
|
||||
offpayload = "{\"entityId\":\"" + hassdevice.deviceState.entity_id + "\",\"hassName\":\"" + hassdevice.hassname + "\",\"state\":\"off\"}";
|
||||
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, hassdevice.hassname + "-" + hassdevice.deviceState.entity_id, hassdevice.deviceState.entity_id, hassdevice.hassname, hassdevice.domain, "hassDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2575,6 +2814,7 @@ app.controller('HassController', function ($scope, $location, bridgeService, ngD
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -2706,7 +2946,7 @@ app.controller('DomoticzController', function ($scope, $location, bridgeService,
|
||||
+ preCmd
|
||||
+ domoticzdevice.idx
|
||||
+ postOffCmd;
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, false, domoticzdevice.devicename + "-" + domoticzdevice.domoticzname, domoticzdevice.devicename, domoticzdevice.domoticzname, aDeviceType, "domoticzDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, false, domoticzdevice.devicename + "-" + domoticzdevice.domoticzname, domoticzdevice.devicename, domoticzdevice.domoticzname, aDeviceType, "domoticzDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2730,6 +2970,7 @@ app.controller('DomoticzController', function ($scope, $location, bridgeService,
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -2828,7 +3069,7 @@ app.controller('LifxController', function ($scope, $location, bridgeService, ngD
|
||||
dimpayload = angular.toJson(lifxdevice);
|
||||
onpayload = angular.toJson(lifxdevice);
|
||||
offpayload = angular.toJson(lifxdevice);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, lifxdevice.name, lifxdevice.name, lifxdevice.name, null, "lifxDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, lifxdevice.name, lifxdevice.name, lifxdevice.name, null, "lifxDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2852,6 +3093,7 @@ app.controller('LifxController', function ($scope, $location, bridgeService, ngD
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -2955,7 +3197,7 @@ app.controller('SomfyController', function ($scope, $location, bridgeService, ng
|
||||
onpayload = "{\"label\":\"Label that is ignored probably\",\"actions\":[{\"deviceURL\":\""+ somfydevice.deviceUrl+"\",\"commands\":[{\"name\":\"open\",\"parameters\":[]}]}]}";
|
||||
offpayload = "{\"label\":\"Label that is ignored probably\",\"actions\":[{\"deviceURL\":\""+ somfydevice.deviceUrl+"\",\"commands\":[{\"name\":\"close\",\"parameters\":[]}]}]}";
|
||||
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, true, somfydevice.id, somfydevice.name, somfydevice.somfyname, "switch", "somfyDevice", null, null);
|
||||
bridgeService.buildUrls(onpayload, dimpayload, offpayload, null, true, somfydevice.id, somfydevice.name, somfydevice.somfyname, "switch", "somfyDevice", null, null);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
bridgeService.editNewDevice($scope.device);
|
||||
@@ -2980,6 +3222,7 @@ app.controller('SomfyController', function ($scope, $location, bridgeService, ng
|
||||
onUrl: $scope.device.onUrl,
|
||||
dimUrl: $scope.device.dimUrl,
|
||||
offUrl: $scope.device.offUrl,
|
||||
colorUrl: $scope.device.colorUrl,
|
||||
headers: $scope.device.headers,
|
||||
httpVerb: $scope.device.httpVerb,
|
||||
contentType: $scope.device.contentType,
|
||||
@@ -3065,18 +3308,35 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
$scope.onDevices = null;
|
||||
$scope.dimDevices = null;
|
||||
$scope.offDevices = null;
|
||||
$scope.colorDevices = null;
|
||||
$scope.showUrls = false;
|
||||
$scope.onUrl = null;
|
||||
$scope.dimUrl = null;
|
||||
$scope.offUrl = null;
|
||||
$scope.colorUrl = null;
|
||||
if ($scope.device !== undefined && $scope.device.name !== undefined) {
|
||||
if($scope.bridge.device.onUrl !== undefined)
|
||||
if($scope.bridge.device.onUrl !== undefined) {
|
||||
$scope.onDevices = bridgeService.getCallObjects($scope.bridge.device.onUrl);
|
||||
if($scope.bridge.device.dimUrl !== undefined)
|
||||
$scope.onUrl = $scope.bridge.device.onUrl.split("},").join("},\n");
|
||||
}
|
||||
if($scope.bridge.device.dimUrl !== undefined) {
|
||||
$scope.dimDevices = bridgeService.getCallObjects($scope.bridge.device.dimUrl);
|
||||
if($scope.bridge.device.offUrl !== undefined)
|
||||
$scope.dimUrl = $scope.bridge.device.dimUrl.split("},").join("},\n");
|
||||
}
|
||||
if($scope.bridge.device.offUrl !== undefined) {
|
||||
$scope.offDevices = bridgeService.getCallObjects($scope.bridge.device.offUrl);
|
||||
$scope.offUrl = $scope.bridge.device.offUrl.split("},").join("},\n");
|
||||
}
|
||||
if($scope.bridge.device.colorUrl !== undefined) {
|
||||
$scope.colorDevices = bridgeService.getCallObjects($scope.bridge.device.colorUrl);
|
||||
$scope.colorUrl = $scope.bridge.device.colorUrl.split("},").join("},\n");
|
||||
}
|
||||
}
|
||||
|
||||
$scope.newOnItem = {};
|
||||
$scope.newDimItem = {};
|
||||
$scope.newOffItem = {};
|
||||
$scope.newColorItem = {};
|
||||
$scope.mapTypeSelected = bridgeService.getMapType($scope.device.mapType);
|
||||
$scope.device_dim_control = "";
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
@@ -3087,9 +3347,16 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
$scope.onDevices = null;
|
||||
$scope.dimDevices = null;
|
||||
$scope.offDevices = null;
|
||||
$scope.colorDevices = null;
|
||||
$scope.showUrls = false;
|
||||
$scope.onUrl = null;
|
||||
$scope.dimUrl = null;
|
||||
$scope.offUrl = null;
|
||||
$scope.colorUrl = null;
|
||||
$scope.newOnItem = {};
|
||||
$scope.newDimItem = {};
|
||||
$scope.newOffItem = {};
|
||||
$scope.newColorItem = {};
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.mapTypeSelected = null;
|
||||
};
|
||||
@@ -3116,12 +3383,22 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
else
|
||||
$scope.device.mapType = null;
|
||||
|
||||
if ($scope.onDevices !== null)
|
||||
$scope.device.onUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.onDevices));
|
||||
if ($scope.dimDevices !== null)
|
||||
$scope.device.dimUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.dimDevices));
|
||||
if ($scope.offDevices !== null)
|
||||
$scope.device.offUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.offDevices));
|
||||
if ($scope.showUrls) {
|
||||
$scope.device.onUrl = ($scope.onUrl == undefined || $scope.onUrl == null || $scope.onUrl == "") ? null : $scope.onUrl.replace(/\r?\n|\r/g,"");
|
||||
$scope.device.dimUrl = ($scope.dimUrl == undefined || $scope.dimUrl == null || $scope.dimUrl == "") ? null : $scope.dimUrl.replace(/\r?\n|\r/g,"");
|
||||
$scope.device.offUrl = ($scope.offUrl == undefined || $scope.offUrl == null || $scope.offUrl == "") ? null : $scope.offUrl.replace(/\r?\n|\r/g,"");
|
||||
$scope.device.colorUrl = ($scope.colorUrl == undefined || $scope.colorUrl == null || $scope.colorUrl == "") ? null : $scope.colorUrl.replace(/\r?\n|\r/g,"");
|
||||
} else {
|
||||
if ($scope.onDevices !== null)
|
||||
$scope.device.onUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.onDevices));
|
||||
if ($scope.dimDevices !== null)
|
||||
$scope.device.dimUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.dimDevices));
|
||||
if ($scope.offDevices !== null)
|
||||
$scope.device.offUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.offDevices));
|
||||
if ($scope.colorDevices !== null)
|
||||
$scope.device.colorUrl = angular.toJson(bridgeService.updateCallObjectsType($scope.colorDevices));
|
||||
}
|
||||
|
||||
|
||||
bridgeService.addDevice($scope.device).then(
|
||||
function () {
|
||||
@@ -3148,7 +3425,7 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
};
|
||||
$scope.removeItemOn = function (anItem) {
|
||||
for(var i = $scope.onDevices.length - 1; i >= 0; i--) {
|
||||
if($scope.onDevices[i].item === anItem.item && $scope.onDevices[i].type === anItem.type) {
|
||||
if($scope.onDevices[i] === anItem) {
|
||||
$scope.onDevices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
@@ -3165,8 +3442,8 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
};
|
||||
$scope.removeItemDim = function (anItem) {
|
||||
for(var i = $scope.dimDevices.length - 1; i >= 0; i--) {
|
||||
if($scope.dimDevices[i].item === anItem.item && $scope.dimDevices[i].type === anItem.type) {
|
||||
$scope.dimDevices.splice(i, 1);
|
||||
if($scope.dimDevices[i] === anItem) {
|
||||
$scope.dimDevices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -3182,11 +3459,30 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
};
|
||||
$scope.removeItemOff = function (anItem) {
|
||||
for(var i = $scope.offDevices.length - 1; i >= 0; i--) {
|
||||
if($scope.offDevices[i].item === anItem.item && $scope.offDevices[i].type === anItem.type) {
|
||||
if($scope.offDevices[i] === anItem) {
|
||||
$scope.offDevices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.addItemColor = function (anItem) {
|
||||
if (anItem.item === undefined || anItem.item === null || anItem.item === "")
|
||||
return;
|
||||
var newitem = { item: anItem.item, type: anItem.type, delay: anItem.delay, count: anItem.count, filterIPs: anItem.filterIPs, httpVerb: anItem.httpVerb, httpBody: anItem.httpBody, httpHeaders: anItem.httpHeaders, contentType: anItem.contentType };
|
||||
if ($scope.colorDevices === null)
|
||||
$scope.colorDevices = [];
|
||||
$scope.colorDevices.push(newitem);
|
||||
$scope.newColorItem = {};
|
||||
};
|
||||
$scope.removeItemColor = function (anItem) {
|
||||
for(var i = $scope.colorDevices.length - 1; i >= 0; i--) {
|
||||
if($scope.colorDevices[i] === anItem) {
|
||||
$scope.colorDevices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$scope.toggleButtons = function () {
|
||||
$scope.buttonsVisible = !$scope.buttonsVisible;
|
||||
if($scope.buttonsVisible)
|
||||
@@ -3195,6 +3491,22 @@ app.controller('EditController', function ($scope, $location, bridgeService) {
|
||||
$scope.imgButtonsUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
|
||||
$scope.changeEditmode = function () {
|
||||
// copy local changes over to other edit mode
|
||||
if ($scope.showUrls) {
|
||||
$scope.onDevices = ($scope.onUrl == undefined || $scope.onUrl == null || $scope.onUrl == "") ? null : bridgeService.getCallObjects($scope.onUrl.replace(/\r?\n|\r/g,""));
|
||||
$scope.dimDevices = ($scope.dimUrl == undefined || $scope.dimUrl == null || $scope.dimUrl == "") ? null : bridgeService.getCallObjects($scope.dimUrl.replace(/\r?\n|\r/g,""));
|
||||
$scope.offDevices = ($scope.offUrl == undefined || $scope.offUrl == null || $scope.offUrl == "") ? null : bridgeService.getCallObjects($scope.offUrl.replace(/\r?\n|\r/g,""));
|
||||
$scope.colorDevices = ($scope.colorUrl == undefined || $scope.colorUrl == null || $scope.colorUrl == "") ? null : bridgeService.getCallObjects($scope.colorUrl.replace(/\r?\n|\r/g,""));
|
||||
} else {
|
||||
$scope.onUrl = ($scope.onDevices !== null) ? angular.toJson(bridgeService.updateCallObjectsType($scope.onDevices)).split("},").join("},\n") : null;
|
||||
$scope.dimUrl = ($scope.dimDevices !== null) ? angular.toJson(bridgeService.updateCallObjectsType($scope.dimDevices)).split("},").join("},\n") : null;
|
||||
$scope.offUrl = ($scope.offDevices !== null) ? angular.toJson(bridgeService.updateCallObjectsType($scope.offDevices)).split("},").join("},\n") : null;
|
||||
$scope.colorUrl = ($scope.colorDevices !== null) ? angular.toJson(bridgeService.updateCallObjectsType($scope.colorDevices)).split("},").join("},\n") : null;
|
||||
}
|
||||
$scope.showUrls = !$scope.showUrls;
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
app.filter('configuredVeraDevices', function (bridgeService) {
|
||||
@@ -3225,6 +3537,34 @@ app.filter('configuredVeraScenes', function (bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('configuredFibaroDevices', function (bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(bridgeService.deviceContainsType(input[i], "fibaroDevice")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('configuredFibaroScenes', function (bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
if(bridgeService.deviceContainsType(input[i], "fibaroScene")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('configuredNestItems', function (bridgeService) {
|
||||
return function(input) {
|
||||
var out = [];
|
||||
@@ -3365,8 +3705,50 @@ app.filter('configuredSomfyDevices', function (bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
app.controller('LoginController', function ($scope, $location, Auth) {
|
||||
app.filter('filterDevicesByRequester', function () {
|
||||
return function(input,search,mustContain,deviceType) {
|
||||
var out = [];
|
||||
if(input === undefined || input === null || input.length === undefined)
|
||||
return out;
|
||||
var pattern = new RegExp(search);
|
||||
var patternType = new RegExp(deviceType);
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
var pushRequester = false;
|
||||
var pushType = false;
|
||||
|
||||
// Check filter by requester
|
||||
if (!search || search.trim().length === 0) { // if search is empty and mustContain == true push only unfiltered devices
|
||||
if (mustContain) {
|
||||
if (!input[i].requesterAddress || input[i].requesterAddress.length === 0) {
|
||||
pushRequester = true;
|
||||
}
|
||||
} else {
|
||||
pushRequester = true;
|
||||
}
|
||||
} else {
|
||||
if(pattern.test(input[i].requesterAddress) || !mustContain && (!input[i].requesterAddress || input[i].requesterAddress.length === 0)){
|
||||
pushRequester = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check filter by deviceType
|
||||
if (deviceType) {
|
||||
pushType = patternType.test(input[i].deviceType);
|
||||
} else {
|
||||
pushType = true;
|
||||
}
|
||||
|
||||
if (pushRequester && pushType) {
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
app.controller('LoginController', function ($scope, $location, Auth, bridgeService) {
|
||||
$scope.failed = false;
|
||||
$scope.isSecure = bridgeService.isSecure();
|
||||
$scope.loggedIn = Auth.isLoggedIn();
|
||||
$scope.login = function(username, password) {
|
||||
Auth.login(username, password)
|
||||
@@ -3379,8 +3761,12 @@ app.controller('LoginController', function ($scope, $location, Auth) {
|
||||
|
||||
$scope.logout = function() {
|
||||
Auth.logout();
|
||||
$scope.isSecure = bridgeService.isSecure();
|
||||
$scope.loggedIn = Auth.isLoggedIn();
|
||||
$location.path("/login");
|
||||
if($scope.isSecure)
|
||||
$location.path("/login");
|
||||
else
|
||||
$location.path("/");
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
@@ -31,10 +35,33 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
|
||||
<button ng-if="bridge.securityInfo.useLinkButton" class="btn btn-primary" type="submit" ng-click="pushLinkButton()">Link</button>
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
|
||||
<button ng-if="bridge.securityInfo.useLinkButton" class="btn btn-primary" type="submit" ng-click="pushLinkButton()">Link</button>
|
||||
<label for="device-ip-filter">Show devices visible to: </label>
|
||||
<input type="text" id="device-ip-filter" style="width:150px"
|
||||
ng-model="bridge.state.filterDevicesByIpAddress" placeholder="">
|
||||
<input type="checkbox" id="device-ip-filter-mode" ng-model="bridge.state.filterDevicesOnlyFiltered" ng-true-value=true ng-false-value=false style="margin-right: 3px">Must contain filter
|
||||
<label for="device-type-filter" style="margin-left:50px">Filter device type: </label>
|
||||
<select name="device-type" id="device-type-filter"
|
||||
ng-model="bridge.state.filterDeviceType">
|
||||
<option value="">---No Filter---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="custom">Custom</option>
|
||||
<option value="UDP">UDP</option>
|
||||
<option value="TCP">TCP</option>
|
||||
<option value="exec">Execute Script/Program</option>
|
||||
<option value="switch">Switch</option>
|
||||
<option value="scene">Scene</option>
|
||||
<option value="macro">Macro</option>
|
||||
<option value="group">Group</option>
|
||||
<option value="activity">Activity</option>
|
||||
<option value="button">Button</option>
|
||||
<option value="thermo">Thermo</option>
|
||||
<option value="passthru">Pass Thru</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<scrollable-table watch="bridge.devices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
@@ -51,7 +78,7 @@
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices" row-id="{{device.id}}" ng-class="{info: bridge.viewDevId == device.id}" >
|
||||
<tr ng-repeat="device in bridge.devices | filterDevicesByRequester:bridge.state.filterDevicesByIpAddress:bridge.state.filterDevicesOnlyFiltered:bridge.state.filterDeviceType" row-id="{{device.id}}" ng-class="{info: bridge.viewDevId == device.id}" >
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.id}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
@@ -54,8 +58,8 @@
|
||||
Bridge Device</button>
|
||||
<button type="submit" class="col-xs-4 col-sm-2 btn btn-success"
|
||||
ng-click="editDevice(false)">Update Bridge Device</button>
|
||||
<button class="btn btn-danger" ng-click="clearDevice()">Clear
|
||||
Device</button>
|
||||
<button class="btn btn-danger" ng-click="clearDevice()">Clear</button>
|
||||
<button class="btn" ng-click="changeEditmode()">Change Edit Mode</button>
|
||||
</p>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
|
||||
@@ -147,7 +151,14 @@
|
||||
<td><input type="text" class="form-control" id="device-map-id"
|
||||
ng-model="device.mapId" placeholder="1111"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr ng-hide="!showUrls">
|
||||
<td><label>OnUrl</label></td>
|
||||
|
||||
<td><textarea class="form-control" id="device-on-url" style="min-height: 250px; min-width: 1300px"
|
||||
ng-model="onUrl" placeholder="default"></textarea></td>
|
||||
</tr>
|
||||
|
||||
<tr ng-hide="showUrls">
|
||||
<td><label>On Items</label></td>
|
||||
|
||||
<td><scrollable-table watch="onDevices">
|
||||
@@ -171,20 +182,20 @@
|
||||
<tr ng-repeat="onItem in onDevices">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]" style="max-width: 150px"
|
||||
ng-model="onItem.type"></select></td>
|
||||
<td><textarea rows="1" class="form-control"
|
||||
id="item-target" ng-model="onItem.item" placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" class="form-control"
|
||||
id="item-target" ng-model="onItem.item" style="min-width: 600px" placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="onItem.delay" placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" class="form-control"
|
||||
<td><textarea rows="1" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="onItem.count" placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" class="form-control"
|
||||
id="item-filterIPs" ng-model="onItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb"
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="onItem.httpVerb">
|
||||
<option value="">---Please select---</option>
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
@@ -196,7 +207,7 @@
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="onItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type"
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="onItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
@@ -220,24 +231,24 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="newOnItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="newOnItem.item"
|
||||
id="item-target" style="min-width: 600px" ng-model="newOnItem.item"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control"
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="newOnItem.delay"
|
||||
placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control"
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="newOnItem.count"
|
||||
placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="newOnItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb"
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="newOnItem.httpVerb">
|
||||
<option value="">---Please select---</option>
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
@@ -249,7 +260,7 @@
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="newOnItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type"
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="newOnItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
@@ -274,7 +285,14 @@
|
||||
</table>
|
||||
</scrollable-table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr ng-hide="!showUrls">
|
||||
<td><label>DimUrl</label></td>
|
||||
|
||||
<td><textarea class="form-control" id="device-dim-url" style="min-height: 250px; min-width: 1300px"
|
||||
ng-model="dimUrl" placeholder="default"></textarea></td>
|
||||
</tr>
|
||||
|
||||
<tr ng-hide="showUrls">
|
||||
<td><label>Dim Items</label></td>
|
||||
|
||||
<td><scrollable-table watch="dimDevices">
|
||||
@@ -297,22 +315,22 @@
|
||||
</thead>
|
||||
<tr ng-repeat="dimItem in dimDevices">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="dimItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="dimItem.item"
|
||||
id="item-target" ng-model="dimItem.item" style="min-width: 600px"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control"
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="dimItem.delay" placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control"
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="dimItem.count" placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="dimItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb"
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="dimItem.httpVerb">
|
||||
<option value="">---Please select---</option>
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
@@ -324,7 +342,7 @@
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="dimItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type"
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="dimItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
@@ -348,24 +366,24 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="newDimItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="newDimItem.item"
|
||||
id="item-target" ng-model="newDimItem.item" style="min-width: 600px"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control"
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="newDimItem.delay"
|
||||
placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control"
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="newDimItem.count"
|
||||
placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="newDimItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="newDimItem.httpVerb">
|
||||
<option value="">---Please select---</option>
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
@@ -377,7 +395,7 @@
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="newDimItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type"
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="newDimItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
@@ -402,7 +420,14 @@
|
||||
</table>
|
||||
</scrollable-table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr ng-hide="!showUrls">
|
||||
<td><label>OffUrl</label></td>
|
||||
|
||||
<td><textarea class="form-control" id="device-off-url" style="min-height: 250px; min-width: 1300px"
|
||||
ng-model="offUrl" placeholder="default"></textarea></td>
|
||||
</tr>
|
||||
|
||||
<tr ng-hide="showUrls">
|
||||
<td><label>Off Items</label></td>
|
||||
|
||||
<td><scrollable-table watch="offDevices">
|
||||
@@ -425,22 +450,22 @@
|
||||
</thead>
|
||||
<tr ng-repeat="offItem in offDevices">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="offItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="offItem.item"
|
||||
id="item-target" ng-model="offItem.item" style="min-width: 600px"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control"
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="offItem.delay" placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control"
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="offItem.count" placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="offItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb"
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="offItem.httpVerb">
|
||||
<option value="">---Please select---</option>
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
@@ -452,7 +477,7 @@
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="offItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type"
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="offItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
@@ -476,24 +501,24 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="newOffItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="newOffItem.item"
|
||||
id="item-target" ng-model="newOffItem.item" style="min-width: 600px"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control"
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="newOffItem.delay"
|
||||
placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control"
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="newOffItem.count"
|
||||
placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="newOffItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb"
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="newOffItem.httpVerb">
|
||||
<option value="">---Please select---</option>
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
@@ -505,7 +530,7 @@
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="newOffItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type"
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="newOffItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
@@ -530,6 +555,140 @@
|
||||
</table>
|
||||
</scrollable-table></td>
|
||||
</tr>
|
||||
<tr ng-hide="!showUrls">
|
||||
<td><label>ColorUrl</label></td>
|
||||
|
||||
<td><textarea class="form-control" id="device-color-url" style="min-height: 250px; min-width: 1300px"
|
||||
ng-model="colorUrl" placeholder="default"></textarea></td>
|
||||
</tr>
|
||||
<tr ng-hide="showUrls">
|
||||
<td><label>Color Items</label></td>
|
||||
|
||||
<td><scrollable-table watch="colorDevices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<th>Type</th>
|
||||
<th>Target Item</th>
|
||||
<th>Delay</th>
|
||||
<th>Count</th>
|
||||
<th>Filter IPs</th>
|
||||
<th>Http Verb</th>
|
||||
<th>Http Body</th>
|
||||
<th>Http Headers</th>
|
||||
<th>Content Type</th>
|
||||
<th>Manage</th>
|
||||
</div>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="colorItem in colorDevices">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="colorItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="colorItem.item" style="min-width: 600px"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="colorItem.delay" placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="colorItem.count" placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="colorItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="colorItem.httpVerb">
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="POST">POST</option>
|
||||
</select></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpBody" ng-model="colorItem.httpBody"
|
||||
placeholder="body args"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="colorItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="colorItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="application/atom+xml">application/atom+xml</option>
|
||||
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
|
||||
<option value="application/json">application/json</option>
|
||||
<option value="application/octet-stream">application/octet-stream</option>
|
||||
<option value="application/svg+xml">application/svg+xml</option>
|
||||
<option value="application/xhtml+xml">application/xhtml+xml</option>
|
||||
<option value="application/xml">application/xml</option>
|
||||
<option value="*">*</option>
|
||||
<option value="multipart/form-data">multipart/form-data</option>
|
||||
<option value="text/html">text/html</option>
|
||||
<option value="text/plain">text/plain</option>
|
||||
<option value="text/xml">text/xml</option>
|
||||
<option value="*/*">*/*</option>
|
||||
</select></td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="removeItemColor(colorItem)">Del</button></td>
|
||||
</div>
|
||||
</tr>
|
||||
<tr>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<td><select style="max-width: 150px"
|
||||
ng-options="mapType as mapType[1] for mapType in bridge.mapTypes track by mapType[0]"
|
||||
ng-model="newColorItem.type"></select></td>
|
||||
<td><textarea rows="1" cols="20" class="form-control"
|
||||
id="item-target" ng-model="newColorItem.item" style="min-width: 600px"
|
||||
placeholder="The Call"></textarea></td>
|
||||
<td><textarea rows="1" cols="4" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-delay" ng-model="newColorItem.delay"
|
||||
placeholder="millis"></textarea></td>
|
||||
<td><textarea rows="1" cols="2" class="form-control" style="max-width: 80px; min-width: 80px"
|
||||
id="item-count" ng-model="newColorItem.count"
|
||||
placeholder="number"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-filterIPs" ng-model="newColorItem.filterIPs"
|
||||
placeholder="restrict IPs"></textarea></td>
|
||||
<td><select name="item-http-verb" id="item-http-verb" style="max-width: 80px"
|
||||
ng-model="newColorItem.httpVerb">
|
||||
<option value="">---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="GET">GET</option>
|
||||
<option value="PUT">PUT</option>
|
||||
<option value="POST">POST</option>
|
||||
</select></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpBody" ng-model="newColorItem.httpBody"
|
||||
placeholder="body args"></textarea></td>
|
||||
<td><textarea rows="1" cols="16" class="form-control"
|
||||
id="item-httpHeaders" ng-model="newColorItem.httpHeaders"
|
||||
placeholder="format like: [{"name":"A name","value":"a value"}]"></textarea></td>
|
||||
<td><select name="item-content-type" id="item-content-type" style="max-width: 160px"
|
||||
ng-model="newColorItem.contentType">
|
||||
<option value="">---Please select---</option>
|
||||
<!-- not selected / blank option -->
|
||||
<option value="application/atom+xml">application/atom+xml</option>
|
||||
<option value="application/x-www-form-urlencoded">application/x-www-form-urlencoded</option>
|
||||
<option value="application/json">application/json</option>
|
||||
<option value="application/octet-stream">application/octet-stream</option>
|
||||
<option value="application/svg+xml">application/svg+xml</option>
|
||||
<option value="application/xhtml+xml">application/xhtml+xml</option>
|
||||
<option value="application/xml">application/xml</option>
|
||||
<option value="*">*</option>
|
||||
<option value="multipart/form-data">multipart/form-data</option>
|
||||
<option value="text/html">text/html</option>
|
||||
<option value="text/plain">text/plain</option>
|
||||
<option value="text/xml">text/xml</option>
|
||||
<option value="*/*">*/*</option>
|
||||
</select></td>
|
||||
<td><button class="btn btn-success" type="submit"
|
||||
ng-click="addItemColor(newColorItem)">Add</button></td>
|
||||
</div>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Legacy Fields <a ng-click="toggleButtons()"><span class={{imgButtonsUrl}} aria-hidden="true"></span></a></label>
|
||||
</td>
|
||||
|
||||
145
src/main/resources/public/views/fibarodevice.html
Normal file
145
src/main/resources/public/views/fibarodevice.html
Normal file
@@ -0,0 +1,145 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation"><a href="#!/">Bridge Devices</a></li>
|
||||
<li role="presentation"><a href="#!/system">Bridge Control</a></li>
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonydevices">Harmony Devices</a></li>
|
||||
<li ng-if="bridge.showNest" role="presentation"><a href="#!/nest">Nest</a></li>
|
||||
<li ng-if="bridge.showHue" role="presentation"><a
|
||||
href="#!/huedevices">Hue Devices</a></li>
|
||||
<li ng-if="bridge.showHal" role="presentation"><a
|
||||
href="#!/haldevices">HAL Devices</a></li>
|
||||
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
|
||||
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
|
||||
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
|
||||
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
|
||||
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
|
||||
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Fibaro Device List
|
||||
({{bridge.fibarodevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Fibaro Device, use the build action buttons
|
||||
to generate the item addition information into the ha-bridge device
|
||||
and this will put you into the edit screen. Then
|
||||
you can modify the name to anything you want that will be the keyword
|
||||
for the Echo or Google Home. Also, you can go back to any helper tab and click a build
|
||||
action button to add another item for a multi-command. After you are
|
||||
done in the edit tab, click the 'Add Bridge Device' to finish that selection
|
||||
setup. The 'Already Configured Fibaro Devices' list below will show
|
||||
what is already setup for your Fibaro.</p>
|
||||
<p class="text-muted">
|
||||
Also, use this select menu for which type of dim control you would
|
||||
like to be generated: <select name="device-dim-control"
|
||||
id="device-dim-control" ng-model="device_dim_control">
|
||||
<option value="">none</option>
|
||||
<option value="${intensity.byte}">Pass-thru Value</option>
|
||||
<option value="${intensity.percent}">Percentage</option>
|
||||
<option value="${intensity.decimal_percent}">Decimal Percentage</option>
|
||||
<option value="${intensity.math(X*1)}">Custom Math</option>
|
||||
</select>
|
||||
</p>
|
||||
<p class="text-muted">Use the check boxes by the names to use the bulk addition
|
||||
feature. Select your items and dim control type if wanted, then click
|
||||
bulk add below. Your items will be added with on and off or dim and
|
||||
off if selected with the name of the device from the Fibaro.</p>
|
||||
<scrollable-table watch="bridge.fibarodevices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name"><span><input type="checkbox" name="selectAll"
|
||||
value="{{selectAll}}"
|
||||
ng-checked="selectAll"
|
||||
ng-click="toggleSelectAll()"> Name</span></th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">Id</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="fibaroname">Fibaro</th>
|
||||
<th sortable-header col="value">Value</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="fibarodevice in bridge.fibarodevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{fibarodevice.id}}"
|
||||
ng-checked="bulk.devices.indexOf(fibarodevice.id) > -1"
|
||||
ng-click="toggleSelection(fibarodevice.id)">
|
||||
{{fibarodevice.name}}</td>
|
||||
<td>{{fibarodevice.id}}</td>
|
||||
<td>{{fibarodevice.roomName}}</td>
|
||||
<td>{{fibarodevice.fibaroname}}</td>
|
||||
<td>{{fibarodevice.properties.value}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(fibarodevice, device_dim_control, false)">Build Item</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
<div class="panel-footer">
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="bulkAddDevices(device_dim_control)">Bulk Add
|
||||
({{bulk.devices.length}})</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Fibaro Devices <a ng-click="toggleButtons()"><span
|
||||
class={{imgButtonsUrl}} aria-hidden="true"></span></a></a>
|
||||
</h2>
|
||||
</div>
|
||||
<div ng-if="buttonsVisible" class="panel-body">
|
||||
<scrollable-table watch="bridge.devices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="targetDevice">Fibaro</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredFibaroDevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.targetDevice}}</td>
|
||||
<td>{{device.mapId}}</td>
|
||||
<td>
|
||||
<p>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="editDevice(device)">Edit</button>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDevice(device)">Delete</button>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/ng-template" id="deleteMapandIdDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Device Map and Id?</h2>
|
||||
<p>{{mapandid.mapType}} with {{mapandid.id}}</p>
|
||||
<p>Are you Sure?</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-error" ng-click="deleteMapandId(mapandid)">Delete</button>
|
||||
</div>
|
||||
</script>
|
||||
114
src/main/resources/public/views/fibaroscene.html
Normal file
114
src/main/resources/public/views/fibaroscene.html
Normal file
@@ -0,0 +1,114 @@
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation"><a href="#!/">Bridge Devices</a></li>
|
||||
<li role="presentation"><a href="#!/system">Bridge Control</a></li>
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonydevices">Harmony Devices</a></li>
|
||||
<li ng-if="bridge.showNest" role="presentation"><a href="#!/nest">Nest</a></li>
|
||||
<li ng-if="bridge.showHue" role="presentation"><a
|
||||
href="#!/huedevices">Hue Devices</a></li>
|
||||
<li ng-if="bridge.showHal" role="presentation"><a
|
||||
href="#!/haldevices">HAL Devices</a></li>
|
||||
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
|
||||
<li ng-if="bridge.showHass" role="presentation"><a href="#!/hassdevices">HomeAssistant Devices</a></li>
|
||||
<li ng-if="bridge.showDomoticz" role="presentation"><a href="#!/domoticzdevices">Domoticz Devices</a></li>
|
||||
<li ng-if="bridge.showSomfy" role="presentation"><a href="#!/somfydevices">Somfy Devices</a></li>
|
||||
<li ng-if="bridge.showLifx" role="presentation"><a href="#!/lifxdevices">LIFX Devices</a></li>
|
||||
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">Fibaro Scene List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Fibaro Scene, use the build action buttons
|
||||
to generate the item addition information into the ha-bridge device and this will put you into the edit screen. Then
|
||||
you can modify the name to anything you want that will be the keyword
|
||||
for the Echo or Google Home. Also, you can go back to any helper tab and click a build
|
||||
action button to add another item for a multi-command. After you are
|
||||
done in the edit tab, click the 'Add Bridge Device' to finish that selection
|
||||
setup. The 'Already Configured Fibaro Scenes' list below will show what
|
||||
is already setup for your Fibaro.</p>
|
||||
|
||||
<scrollable-table watch="bridge.fibaroscenes">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">Id</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="fibaroname">Fibaro</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="fibaroscene in bridge.fibaroscenes">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{fibaroscene.name}}</td>
|
||||
<td>{{fibaroscene.id}}</td>
|
||||
<td>{{fibaroscene.roomName}}</td>
|
||||
<td>{{fibaroscene.fibaroname}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildSceneUrls(fibaroscene)">Build Item</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Fibaro Scenes <a ng-click="toggleButtons()"><span
|
||||
class={{imgButtonsUrl}} aria-hidden="true"></span></a>
|
||||
</h2>
|
||||
</div>
|
||||
<div ng-if="buttonsVisible" class="panel-body">
|
||||
<scrollable-table watch="bridge.fibaroscenes">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="targetDevice">Fibaro</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredFibaroScenes">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.targetDevice}}</td>
|
||||
<td>{{device.mapId}}</td>
|
||||
<td>
|
||||
<p>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="editDevice(device)">Edit</button>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDevice(device)">Delete</button>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/ng-template" id="deleteMapandIdDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Device Map and Id?</h2>
|
||||
<p>{{mapandid.mapType}} with {{mapandid.id}}</p>
|
||||
<p>Are you Sure?</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-error" ng-click="deleteMapandId(mapandid)">Delete</button>
|
||||
</div>
|
||||
</script>
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li role="presentation" class="active"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li role="presentation"><a href="#!/harmonydevices">Harmony
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li role="presentation"><a href="#!/harmonyactivities">Harmony
|
||||
Activities</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/harmonydevices">Harmony
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#!/harmonydevices">Harmony Devices</a></li>
|
||||
<li ng-if="bridge.showNest" role="presentation"><a href="#!/nest">Nest</a></li>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<h2 class="panel-title">Login</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div ng-if="!loggedIn" class="form-container">
|
||||
<div ng-if="!loggedIn && isSecure" class="form-container">
|
||||
|
||||
<form name="loginForm" role="form" ng-submit="login(username, password)">
|
||||
<legend class="form-label">Enter Credentials</legend>
|
||||
@@ -20,10 +20,16 @@
|
||||
<button type="submit" class="btn btn-success" value="Submit">Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
<div ng-if="failed">
|
||||
<p><font color="red">Login failed! Username or passowrd incorrect.</font></p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div ng-if="loggedIn">
|
||||
<button type="button" class="btn btn-danger" ng-click="logout()">Logout</button>
|
||||
<div ng-if="loggedIn && isSecure">
|
||||
<button type="button" class="btn btn-danger" ng-click="logout()">Are you sure you want to Logout?</button>
|
||||
</div>
|
||||
<div ng-if="!isSecure">
|
||||
<p>This ha-bridge instance is not secured!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a href="#!/harmonydevices">Harmony Devices</a></li>
|
||||
<li ng-if="bridge.showNest" role="presentation"><a href="#!/nest">Nest</a></li>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
<li role="presentation"><a href="#!/">Bridge Devices</a></li>
|
||||
<li role="presentation"><a href="#!/system">Bridge Control</a></li>
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li role="presentation"><a href="#!/veradevices">Vera
|
||||
Devices</a></li>
|
||||
<li role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
href="#!/veradevices">Vera Devices</a></li>
|
||||
<li ng-if="bridge.showVera" role="presentation"><a
|
||||
href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a
|
||||
href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
@@ -75,6 +79,13 @@
|
||||
ng-model="bridge.settings.upnpdevicedb"
|
||||
placeholder="data/device.db"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Groups DB Path and File</td>
|
||||
<td><input id="bridge-settings-upnpgroupdb"
|
||||
class="form-control" type="text"
|
||||
ng-model="bridge.settings.upnpgroupdb"
|
||||
placeholder="data/group.db"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UPNP IP Address</td>
|
||||
<td><input id="bridge-settings-upnpconfigaddress"
|
||||
@@ -140,6 +151,51 @@
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fibaro Names and IP Addresses</td>
|
||||
<td><table
|
||||
class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>IP</th>
|
||||
<th>Port</th>
|
||||
<th>Username</th>
|
||||
<th>Password </th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="fibaro in bridge.settings.fibaroaddress.devices">
|
||||
<td>{{fibaro.name}}</td>
|
||||
<td>{{fibaro.ip}}</td>
|
||||
<td>{{fibaro.port}}</td>
|
||||
<td>{{fibaro.username}}</td>
|
||||
<td ng-if="fibaro.password">*******</td>
|
||||
<td ng-if="!fibaro.password"> </td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="removeFibarotoSettings(fibaro.name, fibaro.ip, fibaro.port)">Del</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="bridge-settings-next-fibaro-name"
|
||||
class="form-control" type="text" ng-model="newfibaroname"
|
||||
placeholder="A Fibaro"></td>
|
||||
<td><input id="bridge-settings-next-fibaro-ip"
|
||||
class="form-control" type="text" ng-model="newfibaroip"
|
||||
placeholder="192.168.1.2"></td>
|
||||
<td><input id="bridge-settings-next-fibaro-port"
|
||||
class="form-control" type="text" ng-model="newfibaroport"
|
||||
placeholder="80"></td>
|
||||
<td><input id="bridge-settings-next-fibaro-username"
|
||||
class="form-control" type="text" ng-model="newfibarousername"
|
||||
placeholder="Fibaro username"></td>
|
||||
<td><input id="bridge-settings-next-fibaro-password"
|
||||
class="form-control" type="password" ng-model="newfibaropassword"
|
||||
placeholder="Fibaro password"></td>
|
||||
<td><button class="btn btn-success" type="submit"
|
||||
ng-click="addFibarotoSettings(newfibaroname, newfibaroip, newfibaroport, newfibarousername, newfibaropassword)">Add</button></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Harmony Names and IP Addresses</td>
|
||||
<td><table
|
||||
@@ -260,12 +316,6 @@
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HAL Token (please use token on individual HAL entry)</td>
|
||||
<td><input id="bridge-settings-haltoken" class="form-control"
|
||||
type="password" ng-model="bridge.settings.haltoken"
|
||||
placeholder="thetoken"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MQTT Client IDs and IP Addresses</td>
|
||||
<td><table
|
||||
@@ -499,7 +549,12 @@
|
||||
placeholder="01036562"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Button Press/Call Item Loop Sleep Interval (ms)</td>
|
||||
<td>Emulate MAC<br />(used in bridge-id, uuid, etc.<br /> - leave blank unless needed)</td>
|
||||
<td><input id="bridge-settings-hubmac" class="form-control"
|
||||
type="text" ng-model="bridge.settings.hubmac"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Button Press/Call Item<br />Loop Sleep Interval (ms)</td>
|
||||
<td><input id="bridge-settings-buttonsleep"
|
||||
class="form-control" type="number" name="input"
|
||||
ng-model="bridge.settings.buttonsleep" min="100" max="9999"></td>
|
||||
@@ -511,12 +566,6 @@
|
||||
ng-model="bridge.settings.numberoflogmessages" min="100"
|
||||
max="65535"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>UPNP Strict Handling</td>
|
||||
<td><input type="checkbox"
|
||||
ng-model="bridge.settings.upnpstrict" ng-true-value=true
|
||||
ng-false-value=false> {{bridge.settings.upnpstrict}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Trace UPNP Calls</td>
|
||||
<td><input type="checkbox"
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
<li role="presentation"><a href="#!/">Bridge Devices</a></li>
|
||||
<li role="presentation"><a href="#!/system">Bridge Control</a></li>
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/veradevices">Vera
|
||||
Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
<li role="presentation"><a href="#!/system">Bridge Control</a></li>
|
||||
<li role="presentation"><a href="#!/logs">Logs</a></li>
|
||||
<li role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/verascenes">Vera
|
||||
Scenes</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/verascenes">Vera Scenes</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibarodevices">Fibaro Devices</a></li>
|
||||
<li ng-if="bridge.showFibaro" role="presentation"><a href="#!/fibaroscenes">Fibaro Scenes</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
href="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li ng-if="bridge.showHarmony" role="presentation"><a
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.bwssystems.color.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -12,10 +13,14 @@ public class ConvertCIEColorTestCase {
|
||||
|
||||
@Test
|
||||
public void testColorConversion() {
|
||||
ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(new Double(0.3972), new Double(0.4564)));
|
||||
ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(new Double(0.671254), new Double(0.303273)));
|
||||
|
||||
String colorDecode = ColorDecode.convertCIEtoRGB(xy);
|
||||
Assert.assertEquals(colorDecode, null);
|
||||
List<Integer> colorDecode = ColorDecode.convertCIEtoRGB(xy, 254);
|
||||
List<Integer> assertDecode = new ArrayList<Integer>();
|
||||
assertDecode.add(0, 255);
|
||||
assertDecode.add(1, 47);
|
||||
assertDecode.add(2, 43);
|
||||
Assert.assertEquals(colorDecode, assertDecode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user