mirror of
https://github.com/bwssytems/ha-bridge.git
synced 2025-12-18 08:13:23 +00:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bcec27861 | ||
|
|
bb0ffeb570 | ||
|
|
0c4292bfd7 | ||
|
|
0083c5854f | ||
|
|
c13b9bd8f4 | ||
|
|
ca5a6c6667 | ||
|
|
c9c6d6e66d | ||
|
|
c8b1827150 | ||
|
|
d7d83e866e | ||
|
|
fb24e9d1a3 | ||
|
|
d15a1c58d0 | ||
|
|
08c87eb3aa | ||
|
|
7da4bf13e0 | ||
|
|
cd701ca02e | ||
|
|
1b676632fe | ||
|
|
62e366c028 | ||
|
|
838b86a266 | ||
|
|
ed8fc95782 | ||
|
|
f6cb41b880 | ||
|
|
a578aa9fd8 | ||
|
|
7b97bd75ae | ||
|
|
4de14217b4 | ||
|
|
02918dc49d | ||
|
|
3a8c64aac6 | ||
|
|
10df2f1c3e | ||
|
|
c45cb24b20 | ||
|
|
88f34f3221 | ||
|
|
15223630eb | ||
|
|
f8474f5f41 | ||
|
|
3fea7f4f1a | ||
|
|
44fbaa68f8 | ||
|
|
470f6b3c15 | ||
|
|
2fbf26a5fa | ||
|
|
ee066f1449 | ||
|
|
e5871e61b5 | ||
|
|
6b8a714959 | ||
|
|
cf3ec7cfe4 | ||
|
|
805aac9fde | ||
|
|
1221df4c96 | ||
|
|
1c897e3b36 | ||
|
|
65b0d6e470 | ||
|
|
99e2243e2d | ||
|
|
7a354619d0 | ||
|
|
2dc245bb96 | ||
|
|
e36145f216 | ||
|
|
8cd571c183 |
124
README.md
124
README.md
@@ -1,6 +1,32 @@
|
||||
# ha-bridge
|
||||
Emulates Philips Hue api to other home automation gateways such as an Amazon Echo or Google Home. The Bridge handles basic commands such as "On", "Off" and "brightness" commands of the hue protocol. This bridge can control most devices that have a distinct API.
|
||||
|
||||
Here are some diagrams to put this software in perspective.
|
||||
|
||||
The Echo Path looks like this:
|
||||
```
|
||||
+------------------------+ +------------------------+
|
||||
+-------------+ | H A +------------------| | A +------------------+ |
|
||||
| Amazon Echo |----->| U P | ha-bridge core |--->| P | Device to control| |
|
||||
+-------------+ | E I +------------------| | I +------------------+ |
|
||||
+------------------------+ +------------------------+
|
||||
```
|
||||
The Google Home Path looks like this:
|
||||
```
|
||||
+------------------------+ +------------------------+
|
||||
+-------------+ | H A +------------------| | A +------------------+ |
|
||||
| Google Home |----->| U P | ha-bridge core |--->| P | Device to control| |
|
||||
+-------------+ | E I +------------------| | I +------------------+ |
|
||||
+------------------------+ +------------------------+
|
||||
```
|
||||
THe Harmony Hub Path looks like this:
|
||||
```
|
||||
+------------------------+ +------------------------+
|
||||
+-------------+ | H A +------------------| | A +------------------+ |
|
||||
| Harmony Hub |----->| U P | ha-bridge core |--->| P | Device to control| |
|
||||
+-------------+ | E I +------------------| | I +------------------+ |
|
||||
+------------------------+ +------------------------+
|
||||
```
|
||||
**SECURITY RISK: If you are unsure on how this software operates and what it exposes to your network, please make sure you understand that it can allow root access to your system. It is best practice to not open this to the Internet through your router as there are no security protocols in place to protect the system. The License agreement states specifically that you use this at your own risk.**
|
||||
|
||||
**ATTENTION: This requires a physical Amazon Echo, Dot or Tap and does not work with prototype devices built using the Alexa Voice Service e.g. Amazon's Alexa AVS Sample App and Sam Machin's AlexaPi. The AVS version does not have any capability for Hue Bridge discovery!**
|
||||
@@ -11,7 +37,7 @@ Emulates Philips Hue api to other home automation gateways such as an Amazon Ech
|
||||
|
||||
**FAQ: Please look here for the current FAQs! https://github.com/bwssytems/ha-bridge/wiki/HA-Bridge-FAQs**
|
||||
|
||||
In the cases of systems that require authorization and/or have API's that cannot be handled in the current method, a module may need to be built. The Harmony Hub is such a module and so is the Nest module. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge, Nest and the ability to proxy all of your real Hue bridges behind this bridge.
|
||||
In the cases of systems that require authorization and/or have API's that cannot be handled in the current method, a module may need to be built. The Harmony Hub is such a module and so is the Nest module. The Bridge has helpers to build devices for the gateway for the Logitech Harmony Hub, Vera, Vera Lite or Vera Edge, Nest, Somfy Tahoma and the ability to proxy all of your real Hue bridges behind this bridge.
|
||||
|
||||
Alternatively the Bridge supports custom calls as well using http/https/udp and tcp such as the LimitlessLED/MiLight bulbs using the UDP protocol. Binary data is supported with UDP/TCP.
|
||||
|
||||
@@ -33,23 +59,23 @@ 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.2.0.jar
|
||||
java -jar ha-bridge-4.3.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.2.0.jar is in your /home/pi/habridge directory.
|
||||
Create the directory and make sure that ha-bridge-4.3.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.2.0/ha-bridge-4.2.0.jar
|
||||
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v4.3.0/ha-bridge-4.3.0.jar
|
||||
```
|
||||
Create the directory and make sure that ha-bridge-4.2.0.jar is in your /home/pi/habridge directory.
|
||||
Create the directory and make sure that ha-bridge-4.3.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.2.0/ha-bridge-4.2.0.jar
|
||||
pi@raspberrypi:~/habridge $ wget https://github.com/bwssytems/ha-bridge/releases/download/v4.3.0/ha-bridge-4.3.0.jar
|
||||
```
|
||||
#### System Control Setup on a pi (preferred)
|
||||
For next gen Linux systems (this includes the Raspberry Pi), here is a systemctl unit file that you can install. Here is a link on how to do this: https://www.digitalocean.com/community/tutorials/how-to-use-systemctl-to-manage-systemd-services-and-units
|
||||
@@ -69,7 +95,7 @@ After=network.target
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.2.0.jar
|
||||
ExecStart=/usr/bin/java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.3.0.jar
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -104,7 +130,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.2.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
|
||||
nohup java -jar -Dconfig.file=/home/pi/habridge/data/habridge.config /home/pi/habridge/ha-bridge-4.3.0.jar > /home/pi/habridge/habridge-log.txt 2>&1 &
|
||||
|
||||
chmod 777 /home/pi/habridge/habridge-log.txt
|
||||
```
|
||||
@@ -149,54 +175,6 @@ Added the following lines to my Apache config file “000-default”
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
service apache2 restart
|
||||
### lighthttpd Example
|
||||
```
|
||||
server.modules += ( "mod_proxy" )
|
||||
proxy.server = (
|
||||
"/api" =>
|
||||
(
|
||||
( "host" => "127.0.0.1",
|
||||
"port" => "8080"
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
### nginx Example
|
||||
```
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8080/api;
|
||||
}
|
||||
```
|
||||
## Run ha-bridge alongside web server already on port 80
|
||||
These examples will help you proxy your current webserver requests to the ha-bridge running on a different port, such as 8080.
|
||||
### Apache Example
|
||||
Reverse proxy with Apache on Ubuntu linux:
|
||||
|
||||
a2enmod proxy
|
||||
a2enmod proxy_http
|
||||
a2enmod headers
|
||||
|
||||
Added the following lines to my Apache config file “000-default”
|
||||
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
ProxyPass /api http://localhost:8080/api nocanon
|
||||
ProxyPassReverse /api http://localhost:8080/api
|
||||
ProxyRequests Off
|
||||
AllowEncodedSlashes NoDecode
|
||||
|
||||
# Local reverse proxy authorization override
|
||||
# Most unix distribution deny proxy by default (ie /etc/apache2/mods-enabled/proxy.conf in Ubuntu)
|
||||
<Proxy http://localhost:8080/api*>
|
||||
Order deny,allow
|
||||
Allow from all
|
||||
</Proxy>
|
||||
|
||||
….. (the rest of the VirtualHost config section) …..
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
service apache2 restart
|
||||
### lighthttpd Example
|
||||
```
|
||||
@@ -261,13 +239,9 @@ The server defaults to running on port 80. To override what the default is, spec
|
||||
#### UPNP Response Port
|
||||
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.
|
||||
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.
|
||||
#### 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.
|
||||
#### Harmony Username
|
||||
deprecated
|
||||
#### Harmony Password
|
||||
deprecated
|
||||
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
|
||||
Provide IP Addresses of your Hue Bridges that you want to proxy through 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 passthru the call it receives to the target Hue and device you configure.
|
||||
|
||||
@@ -284,6 +258,10 @@ The user name of the home.nest.com account for the Nest user. This needs to be g
|
||||
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
|
||||
#### 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
|
||||
@@ -314,7 +292,7 @@ There is a new format for the on/dim/off URL areas. The new editor handles the i
|
||||
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
|
||||
String or JsonElement | item | This is the payload that will be called for devices | Required
|
||||
Integer | count | This is how many times this items will be executed | Optional
|
||||
Integer | delay | This is how long we will wait until the next call after | Optional
|
||||
String | type | This is the type of device we are executing | Required
|
||||
@@ -334,7 +312,7 @@ The Add/Edit tab will show you the fields to fill in for the above in a form, wh
|
||||
The format of the item can be the default HTTP request which executes the URLs formatted as `http://<your stuff here>` as a GET. Other options to this are to select the HTTP Verb and add the data type and add a body that is passed with the request. Secure https is supported as well, just use `https://<your secure call here>`. When using POST and PUT, you have the ability to specify the body that will be sent with the request as well as the application type for the http call.
|
||||
|
||||
The valid device types are: "custom", "veraDevice", "veraScene", "harmonyActivity", "harmonyButton", "nestHomeAway", "nestThermoSet", "hueDevice", "halDevice",
|
||||
"halButton", "halHome", "halThermoSet", "mqttMessage", "cmdDevice", "hassDevice", "tcpDevice", "udpDevice", "httpDevice", "domoticzDevice"
|
||||
"halButton", "halHome", "halThermoSet", "mqttMessage", "cmdDevice", "hassDevice", "tcpDevice", "udpDevice", "httpDevice", "domoticzDevice", "somfyDevice"
|
||||
|
||||
Filter Ip example:
|
||||
```
|
||||
@@ -354,7 +332,7 @@ Headers can be added as well using a Json construct [{"name":"header type name",
|
||||
|
||||
Another option that is detected by the bridge is to use UDP or TCP direct calls such as `udp://<ip_address>:<port>/<your stuff here>` to send a UDP request. TCP calls are handled the same way as `tcp://<ip_address>:<port>/<your stuff here>`. If your data for the UDP or TCP request is formatted as "0x00F009B9" lexical hex format, the bridge will convert the data into a binary stream to send.
|
||||
|
||||
You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, ${intensity.percent} for 0-100 or ${intensity.byte} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}". See Value Passing Controls Below.
|
||||
You can also use the value replacement constructs within these statements. Such as using the expressions "${time.format(Java time format string)}" for inserting a date/time stamp, ${intensity.percent} or ${intensity.percent.hex} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} or ${intensity.byte.hex} for 0-255 for straight pass through of the value or items that require special calculated values using ${intensity.math()} i.e. "${intensity.math(X/4)}" or "${intensity.math(X/4).hex}". See Value Passing Controls Below.
|
||||
Examples:
|
||||
```
|
||||
|
||||
@@ -399,18 +377,18 @@ To configure this type of manual add, you will need to select the Device type of
|
||||
|
||||
In the URL areas, the format of the execution is just providing what command line you would like to run, or using the multiple call item construct described above.
|
||||
```
|
||||
[{"item":"C:\\Users\\John\\Documents\\Applications\\putty.exe 192.168.1.1","type":"cmdDevice"},
|
||||
{"item":"notepad.exe","type":"cmdDevice"}]
|
||||
|
||||
OR
|
||||
|
||||
[{"item":"exec://notepad.exe","type":"cmdDevice"}]
|
||||
[{"item":"exec://C:\\Users\\John\\Documents\\Applications\\putty.exe 192.168.1.1","type":"cmdDevice"},{"item":"exec://notepad.exe","type":"cmdDevice"}]
|
||||
|
||||
[{"item":"/home/pi/scripts/dothisscript.sh","type":"cmdDevice"}]
|
||||
```
|
||||
#### Value Passing Controls
|
||||
There are multiple replacement constructs available to be put into any of the calls except Harmony items, Net Items and HAL items. These constructs are: "${time.format(Java time format string)}", "${intensity.percent}", "${intensity.byte}" and "${intensity.math(using X in your calc)}".
|
||||
There are multiple replacement constructs available to be put into any of the calls except Harmony items, Net Items and HAL items. These constructs are: "${time.format(Java time format string)}", "${intensity.percent}", "${intensity.percent.hex}", "${intensity.decimal_percent}", "${intensity.byte}", "${intensity.byte.hex}", "${intensity.math(using X in your calc)}" and "${intensity.math(using X in your calc).hex}".
|
||||
|
||||
You can control items that require special calculated values using ${intensity.math(<your expression using "X" as the value to operate on>)} i.e. "${intensity.math(X/4)}".
|
||||
|
||||
For the items that want to have a date time put into the message, utilize ${time.format(yyyy-MM-ddTHH:mm:ssXXX)} where "yyyy-MM-ddTHH:mm:ssXXX" can be any format from the Java SimpleDateFormat documented here: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
|
||||
|
||||
Also, device data can be inserted into your payloads by the use of "${device.name}", "${device.id}", "${device.uniqueid}", "${device.targetDevice}", "${device.mapId}", "${device.mapType}" and "${device.deviceType}". These work just like the dimming value replacements.
|
||||
e.g.
|
||||
```
|
||||
[{"item":"http://192.168.1.201:3480/data_request?id=action&output_format=json&DeviceNum=10&serviceId=urn:upnp-org:serviceId:Dimming1&action=SetLoadLevelTarget&newLoadlevelTarget=${intensity.math(X/4)}","type":"httpDevice"}]
|
||||
@@ -518,7 +496,7 @@ contentBodyOff | string | This is the content body that you would like to send w
|
||||
}
|
||||
```
|
||||
#### Dimming Control Example
|
||||
Dimming is also supported by using the expressions ${intensity.percent} for 0-100 or ${intensity.byte} for 0-255 for straight pass through of the value.
|
||||
Dimming is also supported by using the expressions ${intensity.percent} for 0-100 or ${intensity.decimal_percent} for 0.00-1.00 or ${intensity.byte} for 0-255 for straight pass through of the value.
|
||||
e.g.
|
||||
```
|
||||
{
|
||||
|
||||
144
kodivolume.md
144
kodivolume.md
@@ -1,144 +0,0 @@
|
||||
# Kodi volume control using dim commands & JSON-RPC
|
||||
|
||||
You can use HA Bridge to adjust the Kodi software volume output. This allows you to use dim commands and set the volume level with percentage values.
|
||||
|
||||
### What is JSON-RPC?
|
||||
|
||||
The short answer is JSON-RPC an interface to communicate with Kodi. [See the official Kodi Wiki for more info](http://kodi.wiki/view/JSON-RPC_API)
|
||||
|
||||
### Setup Kodi to allow control through JSON-RPC
|
||||
|
||||
In Kodi navigate to Settings/Services/Control ([screenshot](http://kodi.wiki/view/Settings/Services/Control))
|
||||
|
||||
Turn **ON** the following:
|
||||
- Allow control of Kodi via HTTP
|
||||
- Allow remote control from applications on this system
|
||||
- Allow remote control from applications on other systems
|
||||
|
||||
Change the **username** to something unique and set a strong **password**.
|
||||
|
||||
Make a note of the **PORT**
|
||||
### Adding the device to HA Bridge
|
||||
|
||||
Access the HA Bridge Configuration in your browser and open the **Manual Add** tab.
|
||||
#### Name
|
||||
|
||||
Give the device a unique name that doesn’t include **“volume”** as it will cause conflicts with the Echo’s built in volume controls. A device name of **“cody sound”** works well.
|
||||
#### Device type
|
||||
|
||||
Select **TCP** in the dropdown
|
||||
### URLs
|
||||
|
||||
This section might seem a little long winded and if you know what you are doing then feel free to jump ahead.
|
||||
#### Building the URL
|
||||
|
||||
We need to log into the Kodi web server without having to fill in the popup each time. You can do this by putting the username and password in the URL. It is not a good idea to do this on other websites as it does put your password in clear view, but for your local network it is fine.
|
||||
|
||||
Use the example below replacing the relevant sections with the details that you defined in the Kodi settings screen in the first step. Replacing the IP with the address of the machine that Kodi is running on.
|
||||
|
||||
```
|
||||
http://KODI_USERNAME:KODI_PASSWORD@192.168.1.123:8080/jsonrpc
|
||||
```
|
||||
##### Testing the URL in a browser
|
||||
|
||||
Before you continue, open your custom URL in a browser (making sure Kodi is running). If all is working as it should you will see a big page of JSON that starts with:
|
||||
|
||||
``` json
|
||||
{
|
||||
"description": "JSON-RPC API of XBMC",
|
||||
"id": "http://xbmc.org/jsonrpc/ServiceDescription.json",
|
||||
```
|
||||
|
||||
If you don’t see something that looks like the code above, then go back and double check your settings.
|
||||
#### The JSON request
|
||||
|
||||
The URL is what connects you to Kodi, JSON is what is used to communicate with it. The JSON that is used to set the volume level is:
|
||||
|
||||
``` json
|
||||
{"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":100},"id":1}
|
||||
```
|
||||
##### Joining the URL and JSON
|
||||
|
||||
Join the two together by adding `?request=` to the end of the URL and then add the JSON to the end of the request. You will end up with something like:
|
||||
|
||||
```
|
||||
http://KODI_USERNAME:KODI_PASSWORD@192.168.1.123:8080/jsonrpc?request={"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":100},"id":1}
|
||||
```
|
||||
### Testing the request in a browser
|
||||
|
||||
Go ahead and test the combined URL/JSON in a browser changing **100** to whatever level you want to set. Kodi should adjust the volume accordingly, try a few different levels to be sure it is working correctly.
|
||||
|
||||
The browser will reformat the URL each time you press return so don’t build the URL in the browser bar without making a copy first.
|
||||
|
||||
Ideally build the URL in a text document which you can easily edit and then copy/paste each time.
|
||||
|
||||
### Prepare the three URLs
|
||||
|
||||
You want to end up with three full URLs in your text file, one for each of the commands.
|
||||
|
||||
**ON**
|
||||
|
||||
```
|
||||
http://KODI_USERNAME:KODI_PASSWORD@192.168.1.123:8080/jsonrpc?request={"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":100},"id":1}
|
||||
```
|
||||
|
||||
**DIM**
|
||||
|
||||
```
|
||||
http://KODI_USERNAME:KODI_PASSWORD@192.168.1.123:8080/jsonrpc?request={"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":45},"id":1}
|
||||
```
|
||||
|
||||
**OFF**
|
||||
|
||||
```
|
||||
http://KODI_USERNAME:KODI_PASSWORD@192.168.1.123:8080/jsonrpc?request={"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":0},"id":1}
|
||||
```
|
||||
|
||||
### Test the three URLS
|
||||
|
||||
You should now be able to control the volume of Kodi using the structured URL you built above in a browser.
|
||||
|
||||
If you can’t get it to work in a browser then you won’t be able to get it to work in HA Bridge.
|
||||
|
||||
|
||||
### Manually adding the device
|
||||
|
||||
Add a new manual device and give it a name e.g. “Cody Sound”
|
||||
|
||||
Set `Device type` to `Custom`
|
||||
|
||||
Use the same URL for all three (ON, OFF, DIM)
|
||||
|
||||
```
|
||||
http://KODI_USERNAME:KODI_PASSWORD@192.168.1.123:8080/jsonrpc?request=
|
||||
```
|
||||
|
||||
* `HTTP Verb` to `POST`
|
||||
* `Content type` to `application/json`
|
||||
|
||||
**Content body On**
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":100},"id":1}
|
||||
```
|
||||
**Content body Dim**
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":${intensity.percent}},"id":1}
|
||||
```
|
||||
**Content body Off**
|
||||
```json
|
||||
{"jsonrpc":"2.0","method":"Application.SetVolume","params":{"volume":0},"id":1}
|
||||
```
|
||||
|
||||
|
||||
### HA Bridge
|
||||
|
||||
Save and test the button in the Bridge Devices tab and hopefully it should turn the volume up in Kodi.
|
||||
|
||||
### Controlling the Device
|
||||
|
||||
You can use the commands as listed in the [README](https://github.com/bwssytems/ha-bridge#ask-alexa)
|
||||
|
||||
“Set Cody Sound to 50 percent”
|
||||
“Cody Sound to 70 percent”
|
||||
|
||||
Remembering that “Turn on Cody Sound” will set the volume to 100%, and “Turn off Cody Sound” will mute.
|
||||
9
pom.xml
9
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>com.bwssystems.HABridge</groupId>
|
||||
<artifactId>ha-bridge</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<version>4.3.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>HA Bridge</name>
|
||||
@@ -48,7 +48,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.bwssytems</groupId>
|
||||
<artifactId>nest-controller</artifactId>
|
||||
<version>1.0.13</version>
|
||||
<version>1.0.14</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
@@ -126,6 +126,11 @@
|
||||
<artifactId>lifx-sdk-java</artifactId>
|
||||
<version>2.1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -46,6 +46,7 @@ public class BridgeSettings extends BackupHandler {
|
||||
public void buildSettings() {
|
||||
String addressString = null;
|
||||
String theVeraAddress = null;
|
||||
String theSomfyAddress = null;
|
||||
String theHarmonyAddress = null;
|
||||
String configFileProperty = System.getProperty("config.file");
|
||||
if(configFileProperty == null) {
|
||||
@@ -103,6 +104,23 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
}
|
||||
theBridgeSettings.setHarmonyAddress(theHarmonyList);
|
||||
|
||||
theSomfyAddress = System.getProperty("somfy.address");
|
||||
IpList theSomfyList = null;
|
||||
if(theSomfyAddress != null) {
|
||||
try {
|
||||
theSomfyList = new Gson().fromJson(theSomfyAddress, IpList.class);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
theSomfyList = new Gson().fromJson("{devices:[{name:default,ip:" + theSomfyAddress + "}]}", IpList.class);
|
||||
} catch (Exception et) {
|
||||
log.error("Cannot parse somfy.address, not set with message: " + e.getMessage(), e);
|
||||
theSomfyList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
theBridgeSettings.setSomfyAddress(theSomfyList);
|
||||
|
||||
theBridgeSettings.setUpnpStrict(Boolean.parseBoolean(System.getProperty("upnp.strict", "true")));
|
||||
theBridgeSettings.setTraceupnp(Boolean.parseBoolean(System.getProperty("trace.upnp", "false")));
|
||||
theBridgeSettings.setButtonsleep(Integer.parseInt(System.getProperty("button.sleep", Configuration.DEFAULT_BUTTON_SLEEP)));
|
||||
@@ -148,12 +166,15 @@ public class BridgeSettings extends BackupHandler {
|
||||
theBridgeSettings.setMqttconfigured(theBridgeSettings.isValidMQTT());
|
||||
theBridgeSettings.setHassconfigured(theBridgeSettings.isValidHass());
|
||||
theBridgeSettings.setDomoticzconfigured(theBridgeSettings.isValidDomoticz());
|
||||
theBridgeSettings.setSomfyconfigured(theBridgeSettings.isValidSomfy());
|
||||
// Lifx is either configured or not, so it does not need an update.
|
||||
if(serverPortOverride != null)
|
||||
theBridgeSettings.setServerPort(serverPortOverride);
|
||||
if(serverIpOverride != null)
|
||||
theBridgeSettings.setWebaddress(serverIpOverride);
|
||||
setupParams(Paths.get(theBridgeSettings.getConfigfile()), ".cfgbk", "habridge.config-");
|
||||
|
||||
setupInternalTestUser();
|
||||
}
|
||||
|
||||
public void loadConfig() {
|
||||
@@ -188,6 +209,16 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
|
||||
|
||||
public void updateConfigFile() {
|
||||
log.debug("Save HA Bridge settings.");
|
||||
Path configPath = Paths.get(theBridgeSettings.getConfigfile());
|
||||
JsonTransformer aRenderer = new JsonTransformer();
|
||||
String jsonValue = aRenderer.render(theBridgeSettings);
|
||||
configWriter(jsonValue, configPath);
|
||||
_loadConfig(configPath);
|
||||
}
|
||||
|
||||
|
||||
private void configWriter(String content, Path filePath) {
|
||||
if(Files.exists(filePath) && !Files.isWritable(filePath)){
|
||||
log.error("Error file is not writable: " + filePath);
|
||||
@@ -279,4 +310,9 @@ public class BridgeSettings extends BackupHandler {
|
||||
}
|
||||
return addressString;
|
||||
}
|
||||
private void setupInternalTestUser() {
|
||||
theBridgeSettings.setupInternalTestUser();
|
||||
if(theBridgeSettings.isSettingsChanged())
|
||||
this.updateConfigFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.bwssystems.HABridge.api.hue.HueConstants;
|
||||
import com.bwssystems.HABridge.api.hue.HueError;
|
||||
import com.bwssystems.HABridge.api.hue.HueErrorResponse;
|
||||
import com.bwssystems.HABridge.api.hue.WhitelistEntry;
|
||||
|
||||
public class BridgeSettingsDescriptor {
|
||||
private static final String DEFAULT_INTERNAL_USER = "thehabridgeuser";
|
||||
private static final String DEFAULT_USER_DESCRIPTION = "default_test_user";
|
||||
private String upnpconfigaddress;
|
||||
private Integer serverport;
|
||||
private Integer upnpresponseport;
|
||||
@@ -40,6 +49,9 @@ public class BridgeSettingsDescriptor {
|
||||
private String hubversion;
|
||||
private IpList domoticzaddress;
|
||||
private boolean domoticzconfigured;
|
||||
private IpList somfyaddress;
|
||||
private boolean somfyconfigured;
|
||||
|
||||
private boolean lifxconfigured;
|
||||
|
||||
public BridgeSettingsDescriptor() {
|
||||
@@ -48,6 +60,7 @@ public class BridgeSettingsDescriptor {
|
||||
this.traceupnp = false;
|
||||
this.nestconfigured = false;
|
||||
this.veraconfigured = false;
|
||||
this.somfyconfigured = false;
|
||||
this.harmonyconfigured = false;
|
||||
this.hueconfigured = false;
|
||||
this.halconfigured = false;
|
||||
@@ -93,9 +106,15 @@ public class BridgeSettingsDescriptor {
|
||||
public IpList getVeraAddress() {
|
||||
return veraaddress;
|
||||
}
|
||||
public IpList getSomfyAddress() {
|
||||
return somfyaddress;
|
||||
}
|
||||
public void setVeraAddress(IpList veraAddress) {
|
||||
this.veraaddress = veraAddress;
|
||||
}
|
||||
public void setSomfyAddress(IpList somfyAddress) {
|
||||
this.somfyaddress = somfyAddress;
|
||||
}
|
||||
public IpList getHarmonyAddress() {
|
||||
return harmonyaddress;
|
||||
}
|
||||
@@ -129,9 +148,15 @@ public class BridgeSettingsDescriptor {
|
||||
public boolean isVeraconfigured() {
|
||||
return veraconfigured;
|
||||
}
|
||||
public boolean isSomfyconfigured() {
|
||||
return somfyconfigured;
|
||||
}
|
||||
public void setVeraconfigured(boolean veraconfigured) {
|
||||
this.veraconfigured = veraconfigured;
|
||||
}
|
||||
public void setSomfyconfigured(boolean somfyconfigured) {
|
||||
this.somfyconfigured = somfyconfigured;
|
||||
}
|
||||
public boolean isHarmonyconfigured() {
|
||||
return harmonyconfigured;
|
||||
}
|
||||
@@ -335,7 +360,88 @@ public class BridgeSettingsDescriptor {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidSomfy() {
|
||||
if(this.getSomfyAddress() == null || this.getSomfyAddress().getDevices().size() <= 0)
|
||||
return false;
|
||||
List<NamedIP> devicesList = this.getSomfyAddress().getDevices();
|
||||
if(devicesList.get(0).getIp().contains(Configuration.DEFAULT_ADDRESS))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public Boolean isValidLifx() {
|
||||
return this.isLifxconfigured();
|
||||
}
|
||||
|
||||
public HueError[] validateWhitelistUser(String aUser, String userDescription, boolean strict) {
|
||||
String validUser = null;
|
||||
boolean found = false;
|
||||
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
|
||||
&& !aUser.equalsIgnoreCase("")) {
|
||||
if (whitelist != null) {
|
||||
Set<String> theUserIds = whitelist.keySet();
|
||||
Iterator<String> userIterator = theUserIds.iterator();
|
||||
while (userIterator.hasNext()) {
|
||||
validUser = userIterator.next();
|
||||
if (validUser.equals(aUser))
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!found && !strict) {
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return HueErrorResponse.createResponse("1", "/api/" + aUser, "unauthorized user", null, null, null).getTheErrors();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void newWhitelistUser(String aUser, String userDescription) {
|
||||
if (whitelist == null) {
|
||||
whitelist = new HashMap<>();
|
||||
}
|
||||
if(userDescription == null)
|
||||
userDescription = "auto insert user";
|
||||
|
||||
whitelist.put(aUser, WhitelistEntry.createEntry(userDescription));
|
||||
setSettingsChanged(true);
|
||||
}
|
||||
|
||||
public String createWhitelistUser(String userDescription) {
|
||||
String aUser = getNewUserID();
|
||||
newWhitelistUser(aUser, userDescription);
|
||||
return aUser;
|
||||
}
|
||||
|
||||
private String getNewUserID() {
|
||||
UUID uid = UUID.randomUUID();
|
||||
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
|
||||
String newUser = "";
|
||||
while (st.hasMoreTokens()) {
|
||||
newUser = newUser + st.nextToken();
|
||||
}
|
||||
|
||||
return newUser;
|
||||
}
|
||||
|
||||
public String getInternalTestUser() {
|
||||
return DEFAULT_INTERNAL_USER;
|
||||
}
|
||||
|
||||
public void setupInternalTestUser() {
|
||||
boolean found = false;
|
||||
for (String key : whitelist.keySet()) {
|
||||
if(key.equals(DEFAULT_INTERNAL_USER))
|
||||
found = true;
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
newWhitelistUser(DEFAULT_INTERNAL_USER, DEFAULT_USER_DESCRIPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +1,87 @@
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
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[] HARMONY_ACTIVITY = { "harmonyActivity", "Harmony Activity"};
|
||||
public final static String[] HARMONY_BUTTON = { "harmonyButton", "Harmony Button"};
|
||||
public final static String[] NEST_HOMEAWAY = { "nestHomeAway", "Nest Home Status"};
|
||||
public final static String[] NEST_THERMO_SET = { "nestThermoSet", "Nest Thermostat"};
|
||||
public final static String[] HUE_DEVICE = { "hueDevice", "Hue Device"};
|
||||
public final static String[] HAL_DEVICE = { "halDevice", "HAL Device"};
|
||||
public final static String[] HAL_BUTTON = { "halButton", "HAL Button"};
|
||||
public final static String[] HAL_HOME = { "halHome", "HAL Home Status"};
|
||||
public final static String[] HAL_THERMO_SET = { "halThermoSet", "HAL Thermostat"};
|
||||
public final static String[] MQTT_MESSAGE = { "mqttMessage", "MQTT Message"};
|
||||
public final static String[] EXEC_DEVICE_COMPAT = { "exec", "Execute Script/Program"};
|
||||
public final static String[] CMD_DEVICE = { "cmdDevice", "Execute Command/Script/Program"};
|
||||
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
|
||||
public final static String[] TCP_DEVICE = { "tcpDevice", "TCP Device"};
|
||||
public final static String[] TCP_DEVICE_COMPAT = { "TCP", "TCP Device"};
|
||||
public final static String[] UDP_DEVICE = { "udpDevice", "UDP Device"};
|
||||
public final static String[] UDP_DEVICE_COMPAT = { "UDP", "UDP Device"};
|
||||
public final static String[] HTTP_DEVICE = { "httpDevice", "HTTP Device"};
|
||||
public final static String[] DOMOTICZ_DEVICE = { "domoticzDevice", "Domoticz Device"};
|
||||
public final static String[] LIFX_DEVICE = { "lifxDevice", "LIFX Device"};
|
||||
|
||||
public final static int typeIndex = 0;
|
||||
public final static int displayIndex = 1;
|
||||
|
||||
ArrayList<String[]> deviceMapTypes;
|
||||
|
||||
public DeviceMapTypes() {
|
||||
super();
|
||||
deviceMapTypes = new ArrayList<String[]>();
|
||||
deviceMapTypes.add(CMD_DEVICE);
|
||||
deviceMapTypes.add(DOMOTICZ_DEVICE);
|
||||
deviceMapTypes.add(HAL_DEVICE);
|
||||
deviceMapTypes.add(HAL_HOME);
|
||||
deviceMapTypes.add(HAL_THERMO_SET);
|
||||
deviceMapTypes.add(HAL_BUTTON);
|
||||
deviceMapTypes.add(HARMONY_ACTIVITY);
|
||||
deviceMapTypes.add(HARMONY_BUTTON);
|
||||
deviceMapTypes.add(HASS_DEVICE);
|
||||
deviceMapTypes.add(HTTP_DEVICE);
|
||||
deviceMapTypes.add(HUE_DEVICE);
|
||||
deviceMapTypes.add(LIFX_DEVICE);
|
||||
deviceMapTypes.add(MQTT_MESSAGE);
|
||||
deviceMapTypes.add(NEST_HOMEAWAY);
|
||||
deviceMapTypes.add(NEST_THERMO_SET);
|
||||
deviceMapTypes.add(TCP_DEVICE);
|
||||
deviceMapTypes.add(UDP_DEVICE);
|
||||
deviceMapTypes.add(VERA_DEVICE);
|
||||
deviceMapTypes.add(VERA_SCENE);
|
||||
}
|
||||
public static int getTypeIndex() {
|
||||
return typeIndex;
|
||||
}
|
||||
public static int getDisplayIndex() {
|
||||
return displayIndex;
|
||||
}
|
||||
public ArrayList<String[]> getDeviceMapTypes() {
|
||||
return deviceMapTypes;
|
||||
}
|
||||
|
||||
public Boolean validateType(String type) {
|
||||
if(type == null || type.trim().isEmpty())
|
||||
return false;
|
||||
for(String[] mapType : deviceMapTypes) {
|
||||
if(type.trim().contentEquals(mapType[typeIndex]))
|
||||
return true;
|
||||
}
|
||||
if(type.trim().contentEquals(EXEC_DEVICE_COMPAT[typeIndex]))
|
||||
return true;
|
||||
if(type.trim().contentEquals(TCP_DEVICE_COMPAT[typeIndex]))
|
||||
return true;
|
||||
if(type.trim().contentEquals(UDP_DEVICE_COMPAT[typeIndex]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
package com.bwssystems.HABridge;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
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[] HARMONY_ACTIVITY = { "harmonyActivity", "Harmony Activity"};
|
||||
public final static String[] HARMONY_BUTTON = { "harmonyButton", "Harmony Button"};
|
||||
public final static String[] NEST_HOMEAWAY = { "nestHomeAway", "Nest Home Status"};
|
||||
public final static String[] NEST_THERMO_SET = { "nestThermoSet", "Nest Thermostat"};
|
||||
public final static String[] HUE_DEVICE = { "hueDevice", "Hue Device"};
|
||||
public final static String[] HAL_DEVICE = { "halDevice", "HAL Device"};
|
||||
public final static String[] HAL_BUTTON = { "halButton", "HAL Button"};
|
||||
public final static String[] HAL_HOME = { "halHome", "HAL Home Status"};
|
||||
public final static String[] HAL_THERMO_SET = { "halThermoSet", "HAL Thermostat"};
|
||||
public final static String[] MQTT_MESSAGE = { "mqttMessage", "MQTT Message"};
|
||||
public final static String[] EXEC_DEVICE_COMPAT = { "exec", "Execute Script/Program"};
|
||||
public final static String[] CMD_DEVICE = { "cmdDevice", "Execute Command/Script/Program"};
|
||||
public final static String[] HASS_DEVICE = { "hassDevice", "HomeAssistant Device"};
|
||||
public final static String[] TCP_DEVICE = { "tcpDevice", "TCP Device"};
|
||||
public final static String[] TCP_DEVICE_COMPAT = { "TCP", "TCP Device"};
|
||||
public final static String[] UDP_DEVICE = { "udpDevice", "UDP Device"};
|
||||
public final static String[] UDP_DEVICE_COMPAT = { "UDP", "UDP Device"};
|
||||
public final static String[] HTTP_DEVICE = { "httpDevice", "HTTP Device"};
|
||||
public final static String[] DOMOTICZ_DEVICE = { "domoticzDevice", "Domoticz Device"};
|
||||
public final static String[] SOMFY_DEVICE = { "somfyDevice", "Somfy Device"};
|
||||
public final static String[] LIFX_DEVICE = { "lifxDevice", "LIFX Device"};
|
||||
|
||||
public final static int typeIndex = 0;
|
||||
public final static int displayIndex = 1;
|
||||
|
||||
ArrayList<String[]> deviceMapTypes;
|
||||
|
||||
public DeviceMapTypes() {
|
||||
super();
|
||||
deviceMapTypes = new ArrayList<String[]>();
|
||||
deviceMapTypes.add(CMD_DEVICE);
|
||||
deviceMapTypes.add(DOMOTICZ_DEVICE);
|
||||
deviceMapTypes.add(HAL_DEVICE);
|
||||
deviceMapTypes.add(HAL_HOME);
|
||||
deviceMapTypes.add(HAL_THERMO_SET);
|
||||
deviceMapTypes.add(HAL_BUTTON);
|
||||
deviceMapTypes.add(HARMONY_ACTIVITY);
|
||||
deviceMapTypes.add(HARMONY_BUTTON);
|
||||
deviceMapTypes.add(HASS_DEVICE);
|
||||
deviceMapTypes.add(HTTP_DEVICE);
|
||||
deviceMapTypes.add(HUE_DEVICE);
|
||||
deviceMapTypes.add(LIFX_DEVICE);
|
||||
deviceMapTypes.add(MQTT_MESSAGE);
|
||||
deviceMapTypes.add(NEST_HOMEAWAY);
|
||||
deviceMapTypes.add(NEST_THERMO_SET);
|
||||
deviceMapTypes.add(SOMFY_DEVICE);
|
||||
deviceMapTypes.add(TCP_DEVICE);
|
||||
deviceMapTypes.add(UDP_DEVICE);
|
||||
deviceMapTypes.add(VERA_DEVICE);
|
||||
deviceMapTypes.add(VERA_SCENE);
|
||||
deviceMapTypes.add(SOMFY_DEVICE);
|
||||
}
|
||||
public static int getTypeIndex() {
|
||||
return typeIndex;
|
||||
}
|
||||
public static int getDisplayIndex() {
|
||||
return displayIndex;
|
||||
}
|
||||
public ArrayList<String[]> getDeviceMapTypes() {
|
||||
return deviceMapTypes;
|
||||
}
|
||||
|
||||
public Boolean validateType(String type) {
|
||||
if(type == null || type.trim().isEmpty())
|
||||
return false;
|
||||
for(String[] mapType : deviceMapTypes) {
|
||||
if(type.trim().contentEquals(mapType[typeIndex]))
|
||||
return true;
|
||||
}
|
||||
if(type.trim().contentEquals(EXEC_DEVICE_COMPAT[typeIndex]))
|
||||
return true;
|
||||
if(type.trim().contentEquals(TCP_DEVICE_COMPAT[typeIndex]))
|
||||
return true;
|
||||
if(type.trim().contentEquals(UDP_DEVICE_COMPAT[typeIndex]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public class HABridge {
|
||||
theSettingResponder = new UpnpSettingsResource(bridgeSettings.getBridgeSettingsDescriptor());
|
||||
theSettingResponder.setupServer();
|
||||
// setup the class to handle the hue emulator rest api
|
||||
theHueMulator = new HueMulator(bridgeSettings.getBridgeSettingsDescriptor(), theResources.getDeviceRepository(), homeManager);
|
||||
theHueMulator = new HueMulator(bridgeSettings, theResources.getDeviceRepository(), homeManager);
|
||||
theHueMulator.setupServer();
|
||||
// wait for the sparkjava initialization of the rest api classes to be complete
|
||||
awaitInitialization();
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.bwssystems.HABridge.plugins.http.HTTPHome;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.plugins.lifx.LifxHome;
|
||||
import com.bwssystems.HABridge.plugins.mqtt.MQTTHome;
|
||||
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;
|
||||
@@ -88,6 +89,10 @@ public class HomeManager {
|
||||
aHome = new DomoticzHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.DOMOTICZ_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the Somfy configuration if available
|
||||
aHome = new SomfyHome(bridgeSettings);
|
||||
homeList.put(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
resourceList.put(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
//setup the Lifx configuration if available
|
||||
aHome = new LifxHome(bridgeSettings);
|
||||
resourceList.put(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex], aHome);
|
||||
|
||||
@@ -2,7 +2,8 @@ package com.bwssystems.HABridge;
|
||||
|
||||
public class NamedIP {
|
||||
private String name;
|
||||
private String ip;
|
||||
private String ip;
|
||||
private String webhook;
|
||||
private String port;
|
||||
private String username;
|
||||
private String password;
|
||||
@@ -20,7 +21,13 @@ public class NamedIP {
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
public String getPort() {
|
||||
public String getWebhook() {
|
||||
return webhook;
|
||||
}
|
||||
public void setWebhook(final String webhook) {
|
||||
this.webhook = webhook;
|
||||
}
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
public void setPort(String port) {
|
||||
|
||||
@@ -62,6 +62,13 @@ public class SystemControl {
|
||||
return "{\"version\":\"" + version.getVersion() + "\"}";
|
||||
});
|
||||
|
||||
// http://ip_address:port/system/habridge/testuser gets the valid test user for calling the api
|
||||
get (SYSTEM_CONTEXT + "/habridge/testuser", "application/json", (request, response) -> {
|
||||
log.debug("Get HA Bridge testuser: " + bridgeSettings.getBridgeSettingsDescriptor().getInternalTestUser());
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return "{\"user\":\"" + bridgeSettings.getBridgeSettingsDescriptor().getInternalTestUser() + "\"}";
|
||||
});
|
||||
|
||||
// http://ip_address:port/system/logmsgs gets the log messages for the bridge
|
||||
get (SYSTEM_CONTEXT + "/logmsgs", "application/json", (request, response) -> {
|
||||
log.debug("Get logmsgs.");
|
||||
|
||||
@@ -62,6 +62,18 @@ public class DeviceDescriptor{
|
||||
@SerializedName("noState")
|
||||
@Expose
|
||||
private boolean noState;
|
||||
@SerializedName("offState")
|
||||
@Expose
|
||||
private boolean offState;
|
||||
@SerializedName("requesterAddress")
|
||||
@Expose
|
||||
private String requesterAddress;
|
||||
@SerializedName("description")
|
||||
@Expose
|
||||
private String description;
|
||||
@SerializedName("comments")
|
||||
@Expose
|
||||
private String comments;
|
||||
|
||||
private DeviceState deviceState;
|
||||
|
||||
@@ -219,6 +231,38 @@ public class DeviceDescriptor{
|
||||
this.noState = noState;
|
||||
}
|
||||
|
||||
public boolean isOffState() {
|
||||
return offState;
|
||||
}
|
||||
|
||||
public void setOffState(boolean offState) {
|
||||
this.offState = offState;
|
||||
}
|
||||
|
||||
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 boolean containsType(String aType) {
|
||||
if(aType == null)
|
||||
return false;
|
||||
|
||||
@@ -83,6 +83,33 @@ public class DeviceRepository extends BackupHandler {
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<DeviceDescriptor> findAllByRequester(String anAddress) {
|
||||
List<DeviceDescriptor> list = new ArrayList<DeviceDescriptor>(devices.values());
|
||||
List<DeviceDescriptor> theReturnList = new ArrayList<DeviceDescriptor>();
|
||||
Iterator<DeviceDescriptor> anIterator = list.iterator();
|
||||
DeviceDescriptor theDevice;
|
||||
String theRequesterAddress;
|
||||
|
||||
HashMap<String,String > addressMap;
|
||||
while (anIterator.hasNext()) {
|
||||
theDevice = anIterator.next();
|
||||
theRequesterAddress = theDevice.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(theDevice);
|
||||
}
|
||||
return theReturnList;
|
||||
}
|
||||
|
||||
public DeviceDescriptor findOne(String id) {
|
||||
return devices.get(id);
|
||||
}
|
||||
|
||||
@@ -18,12 +18,15 @@ import org.slf4j.LoggerFactory;
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.HomeManager;
|
||||
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.ErrorMessage;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
spark core server for bridge configuration
|
||||
@@ -33,11 +36,13 @@ public class DeviceResource {
|
||||
private static final Logger log = LoggerFactory.getLogger(DeviceResource.class);
|
||||
private DeviceRepository deviceRepository;
|
||||
private HomeManager homeManager;
|
||||
private Gson aGsonHandler;
|
||||
private static final Set<String> supportedVerbs = new HashSet<>(Arrays.asList("get", "put", "post"));
|
||||
|
||||
public DeviceResource(BridgeSettingsDescriptor theSettings, HomeManager aHomeManager) {
|
||||
this.deviceRepository = new DeviceRepository(theSettings.getUpnpDeviceDb());
|
||||
homeManager = aHomeManager;
|
||||
aGsonHandler = new GsonBuilder().create();
|
||||
setupEndpoints();
|
||||
}
|
||||
|
||||
@@ -65,14 +70,44 @@ public class DeviceResource {
|
||||
else {
|
||||
devices = new Gson().fromJson("[" + request.body() + "]", DeviceDescriptor[].class);
|
||||
}
|
||||
CallItem[] callItems = null;
|
||||
String errorMessage = null;
|
||||
for(int i = 0; i < devices.length; i++) {
|
||||
if(devices[i].getContentBody() != null ) {
|
||||
if (devices[i].getContentType() == null || devices[i].getHttpVerb() == null || !supportedVerbs.contains(devices[i].getHttpVerb().toLowerCase())) {
|
||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||
log.debug("Bad http verb in create a Device(s): " + request.body());
|
||||
return new ErrorMessage("Bad http verb in create a Device(s): " + request.body() + " ");
|
||||
errorMessage = "Bad http verb in create device(s) for name: " + devices[i].getName() + " with verb: " + devices[i].getHttpVerb();
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if(devices[i].getOnUrl() != null && !devices[i].getOnUrl().isEmpty())
|
||||
callItems = aGsonHandler.fromJson(devices[i].getOnUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||
errorMessage = "Bad on URL JSON in create device(s) for name: " + devices[i].getName() + " with on URL: " + devices[i].getOnUrl();
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
try {
|
||||
if(devices[i].getDimUrl() != null && !devices[i].getDimUrl().isEmpty())
|
||||
callItems = aGsonHandler.fromJson(devices[i].getDimUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||
errorMessage = "Bad dim URL JSON in create device(s) for name: " + devices[i].getName() + " with dim URL: " + devices[i].getDimUrl();
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
try {
|
||||
if(devices[i].getOffUrl() != null && !devices[i].getOffUrl().isEmpty())
|
||||
callItems = aGsonHandler.fromJson(devices[i].getOffUrl(), CallItem[].class);
|
||||
} catch(JsonSyntaxException e) {
|
||||
response.status(HttpStatus.SC_BAD_REQUEST);
|
||||
errorMessage = "Bad off URL JSON in create device(s) for name: " + devices[i].getName() + " with off URL: " + devices[i].getOffUrl();
|
||||
log.debug(errorMessage);
|
||||
return new ErrorMessage(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
deviceRepository.save(devices);
|
||||
@@ -225,7 +260,13 @@ public class DeviceResource {
|
||||
return homeManager.findResource(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.LIFX_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/map/types", "application/json", (request, response) -> {
|
||||
get (API_CONTEXT + "/somfy/devices", "application/json", (request, response) -> {
|
||||
log.debug("Get somfy devices");
|
||||
response.status(HttpStatus.SC_OK);
|
||||
return homeManager.findResource(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]).getItems(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
}, new JsonTransformer());
|
||||
|
||||
get (API_CONTEXT + "/map/types", "application/json", (request, response) -> {
|
||||
log.debug("Get map types");
|
||||
return new DeviceMapTypes().getDeviceMapTypes();
|
||||
}, new JsonTransformer());
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.bwssystems.HABridge.hue;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.Conversion;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import net.java.dev.eval.Expression;
|
||||
@@ -10,10 +12,14 @@ import net.java.dev.eval.Expression;
|
||||
public class BrightnessDecode {
|
||||
private static final Logger log = LoggerFactory.getLogger(BrightnessDecode.class);
|
||||
private static final String INTENSITY_PERCENT = "${intensity.percent}";
|
||||
private static final String INTENSITY_DECIMAL_PERCENT = "${intensity.decimal_percent}";
|
||||
private static final String INTENSITY_BYTE = "${intensity.byte}";
|
||||
private static final String INTENSITY_MATH = "${intensity.math(";
|
||||
private static final String INTENSITY_MATH_VALUE = "X";
|
||||
private static final String INTENSITY_MATH_CLOSE = ")}";
|
||||
private static final String INTENSITY_MATH_CLOSE_HEX = ").hex}";
|
||||
private static final String INTENSITY_PERCENT_HEX = "${intensity.percent.hex}";
|
||||
private static final String INTENSITY_BYTE_HEX = "${intensity.byte.hex}";
|
||||
|
||||
public static int calculateIntensity(int setIntensity, Integer targetBri, Integer targetBriInc) {
|
||||
if (targetBri != null) {
|
||||
@@ -42,45 +48,79 @@ public class BrightnessDecode {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
if (request.contains(INTENSITY_BYTE)) {
|
||||
if (isHex) {
|
||||
String hexValue = Integer.toHexString(intensity);
|
||||
request = request.replace(INTENSITY_BYTE, hexValue);
|
||||
} else {
|
||||
String intensityByte = String.valueOf(intensity);
|
||||
request = request.replace(INTENSITY_BYTE, intensityByte);
|
||||
}
|
||||
} else if (request.contains(INTENSITY_PERCENT)) {
|
||||
int percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
||||
if (isHex) {
|
||||
String hexValue = Integer.toHexString(percentBrightness);
|
||||
request = request.replace(INTENSITY_PERCENT, hexValue);
|
||||
} else {
|
||||
String intensityPercent = String.valueOf(percentBrightness);
|
||||
request = request.replace(INTENSITY_PERCENT, intensityPercent);
|
||||
}
|
||||
} else if (request.contains(INTENSITY_MATH)) {
|
||||
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||
String mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),
|
||||
request.indexOf(INTENSITY_MATH_CLOSE));
|
||||
variables.put(INTENSITY_MATH_VALUE, new BigDecimal(intensity));
|
||||
|
||||
try {
|
||||
boolean notDone = true;
|
||||
String replaceValue = null;
|
||||
String replaceTarget = null;
|
||||
int percentBrightness = (int) Math.round(intensity / 255.0 * 100);
|
||||
float decimalBrightness = (float) (intensity / 255.0);
|
||||
Map<String, BigDecimal> variables = new HashMap<String, BigDecimal>();
|
||||
String mathDescriptor = null;
|
||||
|
||||
while(notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(INTENSITY_BYTE)) {
|
||||
if (isHex) {
|
||||
replaceValue = convertToHex(intensity);
|
||||
} else {
|
||||
replaceValue = String.valueOf(intensity);
|
||||
}
|
||||
replaceTarget = INTENSITY_BYTE;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_BYTE_HEX)) {
|
||||
replaceValue = convertToHex(intensity);
|
||||
replaceTarget = INTENSITY_BYTE_HEX;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_PERCENT)) {
|
||||
if (isHex) {
|
||||
replaceValue = convertToHex(percentBrightness);
|
||||
} else {
|
||||
replaceValue = String.valueOf(percentBrightness);
|
||||
}
|
||||
replaceTarget = INTENSITY_PERCENT;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_PERCENT_HEX)) {
|
||||
replaceValue = convertToHex(percentBrightness);
|
||||
replaceTarget = INTENSITY_PERCENT_HEX;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_DECIMAL_PERCENT)) {
|
||||
replaceValue = String.format("%1.2f", decimalBrightness);
|
||||
replaceTarget = INTENSITY_DECIMAL_PERCENT;
|
||||
notDone = true;
|
||||
} else if (request.contains(INTENSITY_MATH_CLOSE)) {
|
||||
mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),
|
||||
request.indexOf(INTENSITY_MATH_CLOSE));
|
||||
variables.put(INTENSITY_MATH_VALUE, new BigDecimal(intensity));
|
||||
|
||||
log.debug("Math eval is: " + mathDescriptor + ", Where " + INTENSITY_MATH_VALUE + " is: "
|
||||
+ String.valueOf(intensity));
|
||||
Expression exp = new Expression(mathDescriptor);
|
||||
BigDecimal result = exp.eval(variables);
|
||||
Integer endResult = Math.round(result.floatValue());
|
||||
if (isHex) {
|
||||
String hexValue = Integer.toHexString(endResult);
|
||||
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE, hexValue);
|
||||
} else {
|
||||
request = request.replace(INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE,
|
||||
endResult.toString());
|
||||
Integer endResult = calculateMath(variables, mathDescriptor);
|
||||
if(endResult != null) {
|
||||
if (isHex) {
|
||||
replaceValue = convertToHex(endResult);
|
||||
} else {
|
||||
replaceValue = endResult.toString();
|
||||
}
|
||||
replaceTarget = INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE;
|
||||
notDone = true;
|
||||
}
|
||||
} else if (request.contains(INTENSITY_MATH_CLOSE_HEX)) {
|
||||
mathDescriptor = request.substring(request.indexOf(INTENSITY_MATH) + INTENSITY_MATH.length(),
|
||||
request.indexOf(INTENSITY_MATH_CLOSE_HEX));
|
||||
variables.put(INTENSITY_MATH_VALUE, new BigDecimal(intensity));
|
||||
|
||||
Integer endResult = calculateMath(variables, mathDescriptor);
|
||||
if(endResult != null) {
|
||||
if (isHex) {
|
||||
replaceValue = convertToHex(endResult);
|
||||
} else {
|
||||
replaceValue = endResult.toString();
|
||||
}
|
||||
replaceTarget = INTENSITY_MATH + mathDescriptor + INTENSITY_MATH_CLOSE_HEX;
|
||||
notDone = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not execute Math: " + mathDescriptor, e);
|
||||
}
|
||||
if(notDone)
|
||||
request = request.replace(replaceTarget, replaceValue);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
@@ -89,4 +129,28 @@ public class BrightnessDecode {
|
||||
public static String calculateReplaceIntensityValue(String request, int theIntensity, Integer targetBri, Integer targetBriInc, boolean isHex) {
|
||||
return replaceIntensityValue(request, calculateIntensity(theIntensity, targetBri, targetBriInc), isHex);
|
||||
}
|
||||
}
|
||||
|
||||
// Apache Commons Conversion utils likes little endian too much
|
||||
private static String convertToHex(int theValue) {
|
||||
String destHex = "00";
|
||||
String hexValue = Conversion.intToHex(theValue, 0, destHex, 0, 2);
|
||||
byte[] theBytes = hexValue.getBytes();
|
||||
byte[] newBytes = new byte[2];
|
||||
newBytes[0] = theBytes[1];
|
||||
newBytes[1] = theBytes[0];
|
||||
return new String(newBytes);
|
||||
}
|
||||
|
||||
private static Integer calculateMath(Map<String, BigDecimal> variables, String mathDescriptor) {
|
||||
Integer endResult = null;
|
||||
try {
|
||||
Expression exp = new Expression(mathDescriptor);
|
||||
BigDecimal result = exp.eval(variables);
|
||||
endResult = Math.round(result.floatValue());
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not execute Math: " + mathDescriptor, e);
|
||||
endResult = null;
|
||||
}
|
||||
return endResult;
|
||||
}
|
||||
}
|
||||
21
src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java
Normal file
21
src/main/java/com/bwssystems/HABridge/hue/ColorDecode.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ColorDecode {
|
||||
|
||||
public static String convertCIEtoRGB(List<Double> xy) {
|
||||
double x;
|
||||
double y;
|
||||
double Y;
|
||||
|
||||
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);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
|
||||
public class DeviceDataDecode {
|
||||
private static final Logger log = LoggerFactory.getLogger(DeviceDataDecode.class);
|
||||
private static final String DEVICE_ID = "${device.id}";
|
||||
private static final String DEVICE_UNIQUEID = "${device.uniqueid}";
|
||||
private static final String DEVICE_NAME = "${device.name}";
|
||||
private static final String DEVICE_MAPID = "${device.mapId}";
|
||||
private static final String DEVICE_MAPTYPE = "${device.mapType}";
|
||||
private static final String DEVICE_DEVICETYPE = "${device.deviceType}";
|
||||
private static final String DEVICE_TARGETDEVICE = "${device.targetDevice}";
|
||||
|
||||
public static String replaceDeviceData(String request, DeviceDescriptor device) {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
boolean notDone = true;
|
||||
|
||||
while(notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(DEVICE_ID)) {
|
||||
request = request.replace(DEVICE_ID, device.getId());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_UNIQUEID)) {
|
||||
request = request.replace(DEVICE_UNIQUEID, device.getUniqueid());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_NAME)) {
|
||||
request = request.replace(DEVICE_NAME, device.getName());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_MAPID)) {
|
||||
request = request.replace(DEVICE_MAPID, device.getMapId());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_MAPTYPE)) {
|
||||
request = request.replace(DEVICE_MAPTYPE, device.getMapType());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_DEVICETYPE)) {
|
||||
request = request.replace(DEVICE_DEVICETYPE, device.getDeviceType());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
if (request.contains(DEVICE_TARGETDEVICE)) {
|
||||
request = request.replace(DEVICE_TARGETDEVICE, device.getTargetDevice());
|
||||
notDone = true;
|
||||
}
|
||||
|
||||
log.debug("Request <<" + request + ">>, not done: " + notDone);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bwssystems.HABridge.hue;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettings;
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
import com.bwssystems.HABridge.DeviceMapTypes;
|
||||
import com.bwssystems.HABridge.HomeManager;
|
||||
@@ -14,7 +15,6 @@ import com.bwssystems.HABridge.api.hue.HueError;
|
||||
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.api.hue.WhitelistEntry;
|
||||
import com.bwssystems.HABridge.dao.*;
|
||||
import com.bwssystems.HABridge.plugins.hue.HueHome;
|
||||
import com.bwssystems.HABridge.util.JsonTransformer;
|
||||
@@ -33,12 +33,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Based on Armzilla's HueMulator - a Philips Hue emulator using sparkjava rest server
|
||||
@@ -52,13 +48,15 @@ public class HueMulator {
|
||||
private HomeManager homeManager;
|
||||
private HueHome myHueHome;
|
||||
private BridgeSettingsDescriptor bridgeSettings;
|
||||
private BridgeSettings bridgeSettingMaster;
|
||||
private Gson aGsonHandler;
|
||||
private DeviceMapTypes validMapTypes;
|
||||
|
||||
public HueMulator(BridgeSettingsDescriptor theBridgeSettings, DeviceRepository aDeviceRepository, HomeManager aHomeManager) {
|
||||
public HueMulator(BridgeSettings bridgeMaster, DeviceRepository aDeviceRepository, HomeManager aHomeManager) {
|
||||
repository = aDeviceRepository;
|
||||
validMapTypes = new DeviceMapTypes();
|
||||
bridgeSettings = theBridgeSettings;
|
||||
bridgeSettingMaster = bridgeMaster;
|
||||
bridgeSettings = bridgeSettingMaster.getBridgeSettingsDescriptor();
|
||||
homeManager= aHomeManager;
|
||||
myHueHome = (HueHome) homeManager.findHome(DeviceMapTypes.HUE_DEVICE[DeviceMapTypes.typeIndex]);
|
||||
aGsonHandler = new GsonBuilder().create();
|
||||
@@ -393,7 +391,7 @@ public class HueMulator {
|
||||
}
|
||||
|
||||
private String formatSuccessHueResponse(StateChangeBody stateChanges, String body, String lightId,
|
||||
DeviceState deviceState, Integer targetBri, Integer targetBriInc) {
|
||||
DeviceState deviceState, Integer targetBri, Integer targetBriInc, boolean offState) {
|
||||
|
||||
String responseString = "[";
|
||||
boolean notFirstChange = false;
|
||||
@@ -408,6 +406,8 @@ public class HueMulator {
|
||||
deviceState.setOn(stateChanges.isOn());
|
||||
if(!deviceState.isOn() && deviceState.getBri() == 254)
|
||||
deviceState.setBri(0);
|
||||
if(!deviceState.isOn() && offState)
|
||||
deviceState.setBri(0);
|
||||
}
|
||||
notFirstChange = true;
|
||||
}
|
||||
@@ -556,50 +556,6 @@ public class HueMulator {
|
||||
return responseString;
|
||||
}
|
||||
|
||||
private String getNewUserID() {
|
||||
UUID uid = UUID.randomUUID();
|
||||
StringTokenizer st = new StringTokenizer(uid.toString(), "-");
|
||||
String newUser = "";
|
||||
while (st.hasMoreTokens()) {
|
||||
newUser = newUser + st.nextToken();
|
||||
}
|
||||
|
||||
return newUser;
|
||||
}
|
||||
private HueError[] validateWhitelistUser(String aUser, boolean strict) {
|
||||
String validUser = null;
|
||||
boolean found = false;
|
||||
if (aUser != null && !aUser.equalsIgnoreCase("undefined") && !aUser.equalsIgnoreCase("null")
|
||||
&& !aUser.equalsIgnoreCase("")) {
|
||||
if (bridgeSettings.getWhitelist() != null) {
|
||||
Set<String> theUserIds = bridgeSettings.getWhitelist().keySet();
|
||||
Iterator<String> userIterator = theUserIds.iterator();
|
||||
while (userIterator.hasNext()) {
|
||||
validUser = userIterator.next();
|
||||
if (validUser.equals(aUser))
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && !strict) {
|
||||
if (bridgeSettings.getWhitelist() == null) {
|
||||
Map<String, WhitelistEntry> awhitelist = new HashMap<>();
|
||||
bridgeSettings.setWhitelist(awhitelist);
|
||||
}
|
||||
bridgeSettings.getWhitelist().put(aUser, WhitelistEntry.createEntry("auto insert user"));
|
||||
bridgeSettings.setSettingsChanged(true);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
log.debug("Validate user, No User supplied");
|
||||
return HueErrorResponse.createResponse("1", "/api/" + aUser, "unauthorized user", null, null, null).getTheErrors();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Boolean filterByRequester(String requesterFilterList, String anAddress) {
|
||||
if (requesterFilterList == null || requesterFilterList.length() == 0)
|
||||
return true;
|
||||
@@ -620,9 +576,13 @@ public class HueMulator {
|
||||
|
||||
private String basicListHandler(String type, String userId, String requestIp) {
|
||||
log.debug("hue " + type + " list requested: " + userId + " from " + requestIp);
|
||||
HueError[] theErrors = validateWhitelistUser(userId, false);
|
||||
if (theErrors != null)
|
||||
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, false);
|
||||
if (theErrors != null) {
|
||||
if(bridgeSettings.isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
}
|
||||
|
||||
return "{}";
|
||||
}
|
||||
@@ -630,8 +590,11 @@ public class HueMulator {
|
||||
log.debug("hue group list requested: " + userId + " from " + requestIp);
|
||||
HueError[] theErrors = null;
|
||||
Map<String, GroupResponse> groupResponseMap = null;
|
||||
theErrors = validateWhitelistUser(userId, false);
|
||||
theErrors = bridgeSettings.validateWhitelistUser(userId, null, false);
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettings.isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
groupResponseMap = new HashMap<String, GroupResponse>();
|
||||
groupResponseMap.put("1", (GroupResponse) this.groupsIdHandler("1", userId, requestIp));
|
||||
return groupResponseMap;
|
||||
@@ -644,8 +607,11 @@ public class HueMulator {
|
||||
private Object groupsIdHandler(String groupId, String userId, String requestIp) {
|
||||
log.debug("hue group id: <" + groupId + "> requested: " + userId + " from " + requestIp);
|
||||
HueError[] theErrors = null;
|
||||
theErrors = validateWhitelistUser(userId, false);
|
||||
theErrors = bridgeSettings.validateWhitelistUser(userId, null, false);
|
||||
if (theErrors == null) {
|
||||
if(bridgeSettings.isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
if (groupId.equalsIgnoreCase("0")) {
|
||||
GroupResponse theResponse = GroupResponse.createDefaultGroupResponse(repository.findActive());
|
||||
return theResponse;
|
||||
@@ -666,9 +632,13 @@ public class HueMulator {
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue lights list requested: " + userId + " from " + requestIp);
|
||||
log.debug("hue lights list requested: " + userId + " from " + requestIp);
|
||||
theErrors = validateWhitelistUser(userId, false);
|
||||
theErrors = bridgeSettings.validateWhitelistUser(userId, null, false);
|
||||
if (theErrors == null) {
|
||||
List<DeviceDescriptor> deviceList = repository.findActive();
|
||||
if(bridgeSettings.isSettingsChanged())
|
||||
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;
|
||||
@@ -723,12 +693,20 @@ public class HueMulator {
|
||||
newUser = aNewUser.getUsername();
|
||||
aDeviceType = aNewUser.getDevicetype();
|
||||
}
|
||||
if (newUser == null)
|
||||
newUser = getNewUserID();
|
||||
|
||||
validateWhitelistUser(newUser, false);
|
||||
if (aDeviceType == null)
|
||||
aDeviceType = "<not given>";
|
||||
|
||||
if (newUser == null) {
|
||||
newUser = bridgeSettings.createWhitelistUser(aDeviceType);
|
||||
}
|
||||
else {
|
||||
bridgeSettings.validateWhitelistUser(newUser, aDeviceType, false);
|
||||
}
|
||||
|
||||
if(bridgeSettings.isSettingsChanged())
|
||||
bridgeSettingMaster.updateConfigFile();
|
||||
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue api user create requested for device type: " + aDeviceType + " and username: "
|
||||
+ newUser + (followingSlash ? " /api/ called" : ""));
|
||||
@@ -742,7 +720,7 @@ public class HueMulator {
|
||||
if (bridgeSettings.isTraceupnp())
|
||||
log.info("Traceupnp: hue api/:userid/config config requested: " + userId + " from " + ipAddress);
|
||||
log.debug("hue api config requested: " + userId + " from " + ipAddress);
|
||||
if (validateWhitelistUser(userId, true) != null) {
|
||||
if (bridgeSettings.validateWhitelistUser(userId, null, true) != null) {
|
||||
log.debug("hue api config requested, No User supplied, returning public config");
|
||||
HuePublicConfig apiResponse = HuePublicConfig.createConfig("Philips hue",
|
||||
bridgeSettings.getUpnpConfigAddress(), bridgeSettings.getHubversion());
|
||||
@@ -758,7 +736,7 @@ public class HueMulator {
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object getFullState(String userId, String ipAddress) {
|
||||
log.debug("hue api full state requested: " + userId + " from " + ipAddress);
|
||||
HueError[] theErrors = validateWhitelistUser(userId, false);
|
||||
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, true);
|
||||
if (theErrors != null)
|
||||
return theErrors;
|
||||
|
||||
@@ -772,7 +750,7 @@ public class HueMulator {
|
||||
|
||||
private Object getLight(String userId, String lightId, String ipAddress) {
|
||||
log.debug("hue light requested: " + lightId + " for user: " + userId + " from " + ipAddress);
|
||||
HueError[] theErrors = validateWhitelistUser(userId, false);
|
||||
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, true);
|
||||
if (theErrors != null)
|
||||
return theErrors;
|
||||
|
||||
@@ -816,7 +794,7 @@ public class HueMulator {
|
||||
Integer targetBri = null;
|
||||
Integer targetBriInc = null;
|
||||
log.debug("Update state requested: " + userId + " from " + ipAddress + " body: " + body);
|
||||
HueError[] theErrors = validateWhitelistUser(userId, false);
|
||||
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, true);
|
||||
if (theErrors != null)
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
try {
|
||||
@@ -848,7 +826,7 @@ public class HueMulator {
|
||||
if (state == null)
|
||||
state = DeviceState.createDeviceState();
|
||||
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc);
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
|
||||
device.setDeviceState(state);
|
||||
|
||||
return responseString;
|
||||
@@ -866,7 +844,7 @@ public class HueMulator {
|
||||
aMultiUtil.setDelayDefault(bridgeSettings.getButtonsleep());
|
||||
aMultiUtil.setSetCount(1);
|
||||
log.debug("hue state change requested: " + userId + " from " + ipAddress + " body: " + body);
|
||||
HueError[] theErrors = validateWhitelistUser(userId, false);
|
||||
HueError[] theErrors = bridgeSettings.validateWhitelistUser(userId, null, true);
|
||||
if (theErrors != null)
|
||||
return aGsonHandler.toJson(theErrors);
|
||||
try {
|
||||
@@ -944,8 +922,8 @@ public class HueMulator {
|
||||
}
|
||||
|
||||
for (int i = 0; callItems != null && i < callItems.length; i++) {
|
||||
if(!filterByRequester(callItems[i].getFilterIPs(), ipAddress)) {
|
||||
log.debug("filter for requester address not present in list: " + callItems[i].getFilterIPs() + " with request ip of: " + ipAddress);
|
||||
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)
|
||||
@@ -988,11 +966,11 @@ public class HueMulator {
|
||||
|
||||
if (responseString == null || !responseString.contains("[{\"error\":")) {
|
||||
if(!device.isNoState()) {
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc);
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, state, targetBri, targetBriInc, device.isOffState());
|
||||
device.setDeviceState(state);
|
||||
} else {
|
||||
DeviceState dummyState = DeviceState.createDeviceState();
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc);
|
||||
responseString = this.formatSuccessHueResponse(theStateChanges, body, lightId, dummyState, targetBri, targetBriInc, device.isOffState());
|
||||
}
|
||||
}
|
||||
return responseString;
|
||||
|
||||
@@ -21,16 +21,22 @@ public class TimeDecode {
|
||||
if (request == null) {
|
||||
return null;
|
||||
}
|
||||
if (request.contains(TIME_FORMAT)) {
|
||||
String timeFormatDescriptor = request.substring(request.indexOf(TIME_FORMAT) + TIME_FORMAT.length(),
|
||||
request.indexOf(TIME_FORMAT_CLOSE));
|
||||
|
||||
try {
|
||||
log.debug("Time eval is: " + timeFormatDescriptor);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat(timeFormatDescriptor);
|
||||
request = request.replace(TIME_FORMAT + timeFormatDescriptor + TIME_FORMAT_CLOSE, dateFormat.format(new Date()));
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not format current time: " + timeFormatDescriptor, e);
|
||||
boolean notDone = true;
|
||||
|
||||
while(notDone) {
|
||||
notDone = false;
|
||||
if (request.contains(TIME_FORMAT)) {
|
||||
String timeFormatDescriptor = request.substring(request.indexOf(TIME_FORMAT) + TIME_FORMAT.length(),
|
||||
request.indexOf(TIME_FORMAT_CLOSE));
|
||||
|
||||
try {
|
||||
log.debug("Time eval is: " + timeFormatDescriptor);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat(timeFormatDescriptor);
|
||||
request = request.replace(TIME_FORMAT + timeFormatDescriptor + TIME_FORMAT_CLOSE, dateFormat.format(new Date()));
|
||||
notDone = true;
|
||||
} catch (Exception e) {
|
||||
log.warn("Could not format current time: " + timeFormatDescriptor, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return request;
|
||||
|
||||
@@ -161,7 +161,8 @@ public class DomoticzHome implements Home {
|
||||
}
|
||||
@Override
|
||||
public void closeHome() {
|
||||
httpClient.closeHandler();
|
||||
if(httpClient != null)
|
||||
httpClient.closeHandler();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,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.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
|
||||
@@ -31,6 +32,7 @@ public class CommandHome implements Home {
|
||||
else
|
||||
intermediate = anItem.getItem().getAsString();
|
||||
intermediate = BrightnessDecode.calculateReplaceIntensityValue(intermediate, itensity, targetBri, targetBriInc, false);
|
||||
intermediate = DeviceDataDecode.replaceDeviceData(intermediate, device);
|
||||
intermediate = TimeDecode.replaceTimeValue(intermediate);
|
||||
String anError = doExecRequest(intermediate, lightId);
|
||||
if (anError != null) {
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.bwssystems.HABridge.IpList;
|
||||
import com.bwssystems.HABridge.NamedIP;
|
||||
import com.bwssystems.HABridge.api.CallItem;
|
||||
import com.bwssystems.HABridge.dao.DeviceDescriptor;
|
||||
import com.bwssystems.HABridge.hue.BrightnessDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -161,6 +162,8 @@ public class HarmonyHome implements Home {
|
||||
if (url.substring(0, 1).equalsIgnoreCase("{")) {
|
||||
url = "[" + url + "]";
|
||||
}
|
||||
|
||||
url = BrightnessDecode.calculateReplaceIntensityValue(url, intensity, targetBri, targetBriInc, false);
|
||||
ButtonPress[] deviceButtons = aGsonHandler.fromJson(url, ButtonPress[].class);
|
||||
Integer theCount = 1;
|
||||
for(int z = 0; z < deviceButtons.length; z++) {
|
||||
|
||||
@@ -4,6 +4,8 @@ import static java.lang.String.format;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.bwssystems.HABridge.plugins.http.HTTPHandler;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -18,69 +20,98 @@ import net.whistlingfish.harmony.HarmonyClientModule;
|
||||
import net.whistlingfish.harmony.config.Activity;
|
||||
import net.whistlingfish.harmony.protocol.OAReplyProvider;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
|
||||
public class HarmonyServer {
|
||||
|
||||
private static final String ACTIVIY_ID = "${activity.id}";
|
||||
private static final String ACTIVIY_LABEL = "${activity.label}";
|
||||
|
||||
@Inject
|
||||
private HarmonyClient harmonyClient;
|
||||
|
||||
|
||||
private HarmonyHandler myHarmony;
|
||||
private DevModeResponse devResponse;
|
||||
private OAReplyProvider dummyProvider;
|
||||
private NamedIP myNameAndIP;
|
||||
private Boolean isDevMode;
|
||||
private HTTPHandler httpClient;
|
||||
private Logger log = LoggerFactory.getLogger(HarmonyServer.class);
|
||||
|
||||
public HarmonyServer(NamedIP theHarmonyAddress) {
|
||||
super();
|
||||
myHarmony = null;
|
||||
dummyProvider = null;
|
||||
myNameAndIP = theHarmonyAddress;
|
||||
isDevMode = false;
|
||||
}
|
||||
public HarmonyServer(NamedIP theHarmonyAddress) {
|
||||
super();
|
||||
myHarmony = null;
|
||||
dummyProvider = null;
|
||||
myNameAndIP = theHarmonyAddress;
|
||||
isDevMode = false;
|
||||
httpClient = new HTTPHandler();
|
||||
}
|
||||
|
||||
public static HarmonyServer setup(BridgeSettingsDescriptor bridgeSettings, Boolean harmonyDevMode, NamedIP theHarmonyAddress) throws Exception {
|
||||
if(!bridgeSettings.isValidHarmony() && harmonyDevMode) {
|
||||
return new HarmonyServer(theHarmonyAddress);
|
||||
}
|
||||
Injector injector = null;
|
||||
if(!harmonyDevMode)
|
||||
injector = Guice.createInjector(new HarmonyClientModule());
|
||||
HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress);
|
||||
if(!harmonyDevMode)
|
||||
injector.injectMembers(mainObject);
|
||||
mainObject.execute(bridgeSettings, harmonyDevMode);
|
||||
return mainObject;
|
||||
}
|
||||
|
||||
private void execute(BridgeSettingsDescriptor mySettings, Boolean harmonyDevMode) throws Exception {
|
||||
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
||||
isDevMode = harmonyDevMode;
|
||||
String modeString = "";
|
||||
if(dummyProvider != null)
|
||||
log.debug("something is very wrong as dummyProvider is not null...");
|
||||
if(isDevMode)
|
||||
modeString = " (development mode)";
|
||||
else if(noopCalls)
|
||||
modeString = " (no op calls to harmony)";
|
||||
log.info("setup initiated " + modeString + "....");
|
||||
if(isDevMode)
|
||||
{
|
||||
harmonyClient = null;
|
||||
devResponse = new DevModeResponse();
|
||||
public static HarmonyServer setup(
|
||||
BridgeSettingsDescriptor bridgeSettings,
|
||||
Boolean harmonyDevMode,
|
||||
NamedIP theHarmonyAddress
|
||||
) throws Exception {
|
||||
if (!bridgeSettings.isValidHarmony() && harmonyDevMode) {
|
||||
return new HarmonyServer(theHarmonyAddress);
|
||||
}
|
||||
else {
|
||||
devResponse = null;
|
||||
harmonyClient.addListener(new ActivityChangeListener() {
|
||||
@Override
|
||||
public void activityStarted(Activity activity) {
|
||||
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
||||
}
|
||||
});
|
||||
harmonyClient.connect(myNameAndIP.getIp());
|
||||
Injector injector = null;
|
||||
if (!harmonyDevMode) {
|
||||
injector = Guice.createInjector(new HarmonyClientModule());
|
||||
}
|
||||
HarmonyServer mainObject = new HarmonyServer(theHarmonyAddress);
|
||||
if (!harmonyDevMode) {
|
||||
injector.injectMembers(mainObject);
|
||||
}
|
||||
mainObject.execute(bridgeSettings, harmonyDevMode);
|
||||
return mainObject;
|
||||
}
|
||||
|
||||
private void execute(BridgeSettingsDescriptor mySettings, Boolean harmonyDevMode) throws Exception {
|
||||
Boolean noopCalls = Boolean.parseBoolean(System.getProperty("noop.calls", "false"));
|
||||
isDevMode = harmonyDevMode;
|
||||
String modeString = "";
|
||||
if (dummyProvider != null) {
|
||||
log.debug("something is very wrong as dummyProvider is not null...");
|
||||
}
|
||||
if (isDevMode) {
|
||||
modeString = " (development mode)";
|
||||
} else if (noopCalls) {
|
||||
modeString = " (no op calls to harmony)";
|
||||
}
|
||||
log.info("setup initiated " + modeString + "....");
|
||||
if (isDevMode) {
|
||||
harmonyClient = null;
|
||||
devResponse = new DevModeResponse();
|
||||
} else {
|
||||
devResponse = null;
|
||||
harmonyClient.addListener(new ActivityChangeListener() {
|
||||
@Override
|
||||
public void activityStarted(Activity activity) {
|
||||
String webhook = myNameAndIP.getWebhook();
|
||||
if(webhook != null) {
|
||||
try {
|
||||
// Replacing variables
|
||||
webhook = webhook.replace(ACTIVIY_ID, activity.getId().toString());
|
||||
webhook = webhook.replace(ACTIVIY_LABEL, URLEncoder.encode(activity.getLabel(), "UTF-8"));
|
||||
|
||||
log.info(format("calling webhook: %s", webhook));
|
||||
|
||||
// Calling webhook
|
||||
httpClient.doHttpRequest(webhook, HttpGet.METHOD_NAME, null, null, null);
|
||||
} catch (Exception e) {
|
||||
log.warn("could not call webhook: " + webhook, e);
|
||||
}
|
||||
}
|
||||
log.info(format("activity changed: [%d] %s", activity.getId(), activity.getLabel()));
|
||||
}
|
||||
});
|
||||
harmonyClient.connect(myNameAndIP.getIp());
|
||||
}
|
||||
myHarmony = new HarmonyHandler(harmonyClient, noopCalls, devResponse);
|
||||
}
|
||||
}
|
||||
|
||||
public HarmonyHandler getMyHarmony() {
|
||||
return myHarmony;
|
||||
}
|
||||
public HarmonyHandler getMyHarmony() {
|
||||
return myHarmony;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,12 @@ public class HomeAssistant {
|
||||
aUrl = "https";
|
||||
else
|
||||
aUrl = "http";
|
||||
aUrl = aUrl + "://" + hassAddress.getIp() + ":" + hassAddress.getPort() + "/api/services/" + aCommand.getEntityId().substring(0, aCommand.getEntityId().indexOf("."));
|
||||
String domain = aCommand.getEntityId().substring(0, aCommand.getEntityId().indexOf("."));
|
||||
aUrl = aUrl + "://" + hassAddress.getIp() + ":" + hassAddress.getPort() + "/api/services/";
|
||||
if(domain.equals("group"))
|
||||
aUrl = aUrl + "homeassistant";
|
||||
else
|
||||
aUrl = aUrl + domain;
|
||||
String aBody = "{\"entity_id\":\"" + aCommand.getEntityId() + "\"";
|
||||
NameValue[] headers = null;
|
||||
if(hassAddress.getPassword() != null && !hassAddress.getPassword().isEmpty()) {
|
||||
@@ -62,6 +67,7 @@ public class HomeAssistant {
|
||||
aUrl = aUrl + "/turn_off";
|
||||
aBody = aBody + "}";
|
||||
}
|
||||
log.debug("Calling HomeAssistant with url: " + aUrl);
|
||||
String theData = anHttpHandler.doHttpRequest(aUrl, HttpPost.METHOD_NAME, "application/json", aBody, headers);
|
||||
log.debug("call Command return is: <" + theData + ">");
|
||||
return true;
|
||||
|
||||
@@ -5,16 +5,6 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.config.CookieSpecs;
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
@@ -34,21 +24,11 @@ import com.bwssystems.HABridge.api.NameValue;
|
||||
|
||||
public class HTTPHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(HTTPHandler.class);
|
||||
// private HttpClient httpClient;
|
||||
private CloseableHttpClient httpClient;
|
||||
// private SSLContext sslcontext;
|
||||
// private SSLConnectionSocketFactory sslsf;
|
||||
private RequestConfig globalConfig;
|
||||
|
||||
|
||||
public HTTPHandler() {
|
||||
// httpClient = HttpClients.createDefault();
|
||||
// Removed Specific SSL as Apache HttpClient automatically uses SSL if the URI starts with https://
|
||||
// Trust own CA and all self-signed certs
|
||||
// sslcontext = SSLContexts.createDefault();
|
||||
// Allow TLSv1 protocol only
|
||||
// sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLS" }, null,
|
||||
// SSLConnectionSocketFactory.getDefaultHostnameVerifier());
|
||||
globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD).build();
|
||||
httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
|
||||
}
|
||||
@@ -101,40 +81,55 @@ public class HTTPHandler {
|
||||
request.setHeader(headers[i].getName(), headers[i].getValue());
|
||||
}
|
||||
}
|
||||
HttpResponse response;
|
||||
try {
|
||||
HttpResponse response;
|
||||
// Removed Specific SSL as Apache HttpClient automatically uses SSL if the URI starts with https://
|
||||
// if (url.startsWith("xyzhttps"))
|
||||
// response = httpclientSSL.execute(request);
|
||||
// else
|
||||
for(int retryCount = 0; retryCount < 2; retryCount++) {
|
||||
response = httpClient.execute(request);
|
||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute on URL responded: "
|
||||
+ response.getStatusLine().getStatusCode());
|
||||
if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||
if (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);
|
||||
log.debug((httpVerb == null ? "GET" : httpVerb) + " execute (" + retryCount + ") on URL responded: "
|
||||
+ response.getStatusLine().getStatusCode());
|
||||
if (response.getStatusLine().getStatusCode() >= 200 && response.getStatusLine().getStatusCode() < 300) {
|
||||
if (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);
|
||||
}
|
||||
log.debug("Successfull response - The http response is <<<" + theContent + ">>>");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: " + response.getStatusLine());
|
||||
try {
|
||||
EntityUtils.consume(response.getEntity()); // close out
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
} catch (Exception e) {
|
||||
//noop
|
||||
retryCount = 2;
|
||||
} else {
|
||||
log.warn("HTTP response code was not an expected successful response of between 200 - 299, the code was: " + response.getStatusLine());
|
||||
try {
|
||||
String someContent = EntityUtils.toString(response.getEntity(), Charset.forName("UTF-8")); // read
|
||||
// content
|
||||
// for
|
||||
// data
|
||||
EntityUtils.consume(response.getEntity()); // close out
|
||||
// inputstream
|
||||
// ignore
|
||||
// content
|
||||
log.debug("Unsuccessfull response - The http response is <<<" + someContent + ">>>");
|
||||
} catch (Exception e) {
|
||||
//noop
|
||||
}
|
||||
if (response.getStatusLine().getStatusCode() == 504) {
|
||||
log.warn("HTTP response code was 504, retrying...");
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e1) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
else
|
||||
retryCount = 2;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
||||
@@ -11,6 +11,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.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.google.gson.Gson;
|
||||
@@ -49,12 +50,14 @@ public class HTTPHome implements Home {
|
||||
|
||||
String anUrl = BrightnessDecode.calculateReplaceIntensityValue(theUrl,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
|
||||
anUrl = DeviceDataDecode.replaceDeviceData(anUrl, device);
|
||||
anUrl = TimeDecode.replaceTimeValue(anUrl);
|
||||
|
||||
String aBody = null;
|
||||
if(anItem.getHttpBody()!= null && !anItem.getHttpBody().isEmpty()) {
|
||||
aBody = BrightnessDecode.calculateReplaceIntensityValue(anItem.getHttpBody(),
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
aBody = DeviceDataDecode.replaceDeviceData(aBody, device);
|
||||
aBody = TimeDecode.replaceTimeValue(aBody);
|
||||
}
|
||||
// make call
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.bwssystems.HABridge.plugins.mqtt;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
@@ -47,7 +48,7 @@ public class MQTTHandler {
|
||||
}
|
||||
|
||||
public void publishMessage(String topic, String content) {
|
||||
MqttMessage message = new MqttMessage(content.getBytes());
|
||||
MqttMessage message = new MqttMessage(StringEscapeUtils.unescapeJava(content).getBytes());
|
||||
message.setQos(qos);
|
||||
try {
|
||||
myClient.publish(topic, message);
|
||||
|
||||
@@ -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.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.google.gson.Gson;
|
||||
@@ -89,6 +90,7 @@ public class MQTTHome implements Home {
|
||||
mqttObject =anItem.getItem().getAsString();
|
||||
mqttObject = BrightnessDecode.calculateReplaceIntensityValue(mqttObject,
|
||||
intensity, targetBri, targetBriInc, false);
|
||||
mqttObject = DeviceDataDecode.replaceDeviceData(mqttObject, device);
|
||||
mqttObject = TimeDecode.replaceTimeValue(mqttObject);
|
||||
if (mqttObject.substring(0, 1).equalsIgnoreCase("{"))
|
||||
mqttObject = "[" + mqttObject + "]";
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.bwssystems.HABridge.plugins.somfy;
|
||||
|
||||
public class SomfyDevice {
|
||||
private String id;
|
||||
private String room;
|
||||
private String category;
|
||||
private String somfyname;
|
||||
private String name;
|
||||
private String deviceUrl;
|
||||
private String deviceType;
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setRoom(String room) {
|
||||
this.room = room;
|
||||
}
|
||||
|
||||
public String getRoom() {
|
||||
return room;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setSomfyname(String somfyname) {
|
||||
this.somfyname = somfyname;
|
||||
}
|
||||
|
||||
public String getSomfyname() {
|
||||
return somfyname;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setDeviceUrl(String deviceUrl) {
|
||||
this.deviceUrl = deviceUrl;
|
||||
}
|
||||
|
||||
public String getDeviceUrl() {
|
||||
return deviceUrl;
|
||||
}
|
||||
|
||||
public void setDeviceType(String deviceType) {
|
||||
this.deviceType = deviceType;
|
||||
}
|
||||
|
||||
public String getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.bwssystems.HABridge.plugins.somfy;
|
||||
|
||||
import com.bwssystems.HABridge.BridgeSettingsDescriptor;
|
||||
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.MultiCommandUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Support for Somfy Tahoma hub which allows control of IO Homecontrol devices such as Velux windows.
|
||||
* Currently supports 'turn on' for open window, and 'turn off' for close.
|
||||
*
|
||||
* Known issues:
|
||||
* //TODO - Fix bug on UI where bulk update seems to add the single device twice if 'update' is clicked (this is a general bug with Vera too I think)
|
||||
* Enhancements:
|
||||
* //TODO - support 'dimming' for partial window opening.
|
||||
*
|
||||
*/
|
||||
public class SomfyHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(SomfyHome.class);
|
||||
private Map<String, SomfyInfo> somfys;
|
||||
private Boolean validSomfy;
|
||||
|
||||
public SomfyHome(BridgeSettingsDescriptor bridgeSettings) {
|
||||
createHome(bridgeSettings);
|
||||
|
||||
}
|
||||
|
||||
public SomfyInfo getSomfyHandler(String somfyName) {
|
||||
return somfys.get(somfyName);
|
||||
}
|
||||
|
||||
public List<SomfyDevice> getDevices() {
|
||||
log.debug("consolidating devices for somfy");
|
||||
Iterator<String> keys = somfys.keySet().iterator();
|
||||
ArrayList<SomfyDevice> deviceList = new ArrayList<>();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
List<SomfyDevice> devices = somfys.get(key).getSomfyDevices();
|
||||
deviceList.addAll(devices);
|
||||
}
|
||||
return deviceList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItems(String type) {
|
||||
if(validSomfy) {
|
||||
if(type.equalsIgnoreCase(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex]))
|
||||
return getDevices();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity, Integer targetBri, Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
String responseString = null;
|
||||
if (!validSomfy) {
|
||||
log.warn("Should not get here, no somfy hub available");
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Should not get here, no somfy hub available\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} else {
|
||||
if (anItem.getType() != null && anItem.getType().trim().equalsIgnoreCase(DeviceMapTypes.SOMFY_DEVICE[DeviceMapTypes.typeIndex])) {
|
||||
|
||||
log.debug("executing HUE api request to change activity to Somfy: " + anItem.getItem().toString());
|
||||
String jsonToPost = anItem.getItem().toString();
|
||||
|
||||
SomfyInfo somfyHandler = getSomfyHandler(device.getTargetDevice());
|
||||
if(somfyHandler == null) {
|
||||
log.warn("Should not get here, no Somfy configured");
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Should not get here, no somfy configured\", \"parameter\": \"/lights/"
|
||||
+ lightId + "state\"}}]";
|
||||
} else {
|
||||
try {
|
||||
somfyHandler.execApply(jsonToPost);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error posting request to Somfy");
|
||||
responseString = "[{\"error\":{\"type\": 6, \"address\": \"/lights/" + lightId
|
||||
+ "\",\"description\": \"Error posting request to SomfyTahoma\", \"parameter\": \"/lights/" + lightId + "state\"}}]";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return responseString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Home createHome(BridgeSettingsDescriptor bridgeSettings) {
|
||||
validSomfy = bridgeSettings.isValidSomfy();
|
||||
log.info("Somfy Home created." + (validSomfy ? "" : " No Somfys configured."));
|
||||
if(validSomfy) {
|
||||
somfys = new HashMap<>();
|
||||
Iterator<NamedIP> theList = bridgeSettings.getSomfyAddress().getDevices().iterator();
|
||||
while (theList.hasNext()) {
|
||||
NamedIP aSomfy = theList.next();
|
||||
somfys.put(aSomfy.getName(), new SomfyInfo(aSomfy, aSomfy.getName()));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
somfys = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
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.somfy.jsonschema2pojo.getsetup.Device;
|
||||
import com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup.GetSetup;
|
||||
import com.google.gson.Gson;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class SomfyInfo {
|
||||
private static final Logger log = LoggerFactory.getLogger(SomfyInfo.class);
|
||||
private final String somfyName;
|
||||
private final NamedIP namedIP;
|
||||
private HTTPHandler httpClient;
|
||||
private static final String CONNECT_HOST = "https://www.tahomalink.com/";
|
||||
private static final String BASE_URL = CONNECT_HOST + "enduser-mobile-web/externalAPI/";
|
||||
private static final String BASE_URL_ENDUSER = CONNECT_HOST + "enduser-mobile-web/enduserAPI/";
|
||||
|
||||
public SomfyInfo(NamedIP namedIP, String somfyName) {
|
||||
super();
|
||||
this.somfyName = somfyName;
|
||||
this.namedIP = namedIP;
|
||||
}
|
||||
|
||||
private void initHttpClient() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
|
||||
if(httpClient==null) {
|
||||
httpClient = new HTTPHandler();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<SomfyDevice> getSomfyDevices() {
|
||||
|
||||
List<SomfyDevice> somfyDevices = new ArrayList<>();
|
||||
try {
|
||||
login(namedIP.getUsername(), namedIP.getPassword());
|
||||
GetSetup setupData = getSetup();
|
||||
for(Device device : setupData.getSetup().getDevices()) {
|
||||
somfyDevices.add(mapDeviceToSomfyDevice(device));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Could not get Somfy devices", e);
|
||||
}
|
||||
return somfyDevices;
|
||||
}
|
||||
|
||||
|
||||
public void login(String username, String password) throws Exception {
|
||||
|
||||
initHttpClient();
|
||||
NameValue[] httpHeader = getHttpHeaders();
|
||||
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
|
||||
nvps.add(new BasicNameValuePair("userId", username));
|
||||
nvps.add(new BasicNameValuePair("userPassword", password));
|
||||
log.debug("Making SOMFY http login call");
|
||||
UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(nvps);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
urlEncodedFormEntity.writeTo(bos);
|
||||
String body = bos.toString();
|
||||
String response = httpClient.doHttpRequest(BASE_URL + "json/login",HttpPost.METHOD_NAME, "application/x-www-form-urlencoded", body,httpHeader);
|
||||
log.debug(response);
|
||||
}
|
||||
|
||||
private NameValue[] getHttpHeaders() {
|
||||
NameValue userAgentHeader = new NameValue();
|
||||
userAgentHeader.setName("User-Agent");
|
||||
userAgentHeader.setValue("mine");
|
||||
return new NameValue[]{userAgentHeader};
|
||||
}
|
||||
|
||||
public GetSetup getSetup() throws IOException {
|
||||
NameValue[] httpHeader = getHttpHeaders();
|
||||
log.info("Making SOMFY http setup call");
|
||||
String response = httpClient.doHttpRequest(BASE_URL + "json/getSetup", HttpGet.METHOD_NAME, "", "", httpHeader );
|
||||
log.debug(response);
|
||||
GetSetup setupData = new Gson().fromJson(response, GetSetup.class);
|
||||
return setupData;
|
||||
}
|
||||
|
||||
public void execApply(String jsonToPost) throws Exception {
|
||||
login(namedIP.getUsername(), namedIP.getPassword());
|
||||
log.info("Making SOMFY http exec call");
|
||||
String response = httpClient.doHttpRequest(BASE_URL_ENDUSER + "exec/apply", HttpPost.METHOD_NAME, "application/json;charset=UTF-8", jsonToPost, getHttpHeaders());
|
||||
log.info(response);
|
||||
}
|
||||
|
||||
|
||||
protected SomfyDevice mapDeviceToSomfyDevice(Device device) {
|
||||
SomfyDevice somfyDevice = new SomfyDevice();
|
||||
somfyDevice.setId(device.getOid());
|
||||
somfyDevice.setCategory(device.getUiClass());
|
||||
somfyDevice.setRoom("");
|
||||
somfyDevice.setSomfyname(somfyName);
|
||||
somfyDevice.setName(device.getLabel());
|
||||
somfyDevice.setDeviceUrl(device.getDeviceURL());
|
||||
somfyDevice.setDeviceType(device.getWidget());
|
||||
return somfyDevice;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Device {
|
||||
|
||||
@SerializedName("label")
|
||||
@Expose
|
||||
private String label;
|
||||
@SerializedName("deviceURL")
|
||||
@Expose
|
||||
private String deviceURL;
|
||||
@SerializedName("widget")
|
||||
@Expose
|
||||
private String widget;
|
||||
@SerializedName("oid")
|
||||
@Expose
|
||||
private String oid;
|
||||
@SerializedName("uiClass")
|
||||
@Expose
|
||||
private String uiClass;
|
||||
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String getDeviceURL() {
|
||||
return deviceURL;
|
||||
}
|
||||
|
||||
public void setDeviceURL(String deviceURL) {
|
||||
this.deviceURL = deviceURL;
|
||||
}
|
||||
|
||||
|
||||
public String getWidget() {
|
||||
return widget;
|
||||
}
|
||||
|
||||
public void setWidget(String widget) {
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
|
||||
public String getOid() {
|
||||
return oid;
|
||||
}
|
||||
|
||||
public void setOid(String oid) {
|
||||
this.oid = oid;
|
||||
}
|
||||
|
||||
public String getUiClass() {
|
||||
return uiClass;
|
||||
}
|
||||
|
||||
public void setUiClass(String uiClass) {
|
||||
this.uiClass = uiClass;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class GetSetup {
|
||||
|
||||
@SerializedName("setup")
|
||||
@Expose
|
||||
private Setup setup;
|
||||
|
||||
public Setup getSetup() {
|
||||
return setup;
|
||||
}
|
||||
|
||||
public void setSetup(Setup setup) {
|
||||
this.setup = setup;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
package com.bwssystems.HABridge.plugins.somfy.jsonschema2pojo.getsetup;
|
||||
|
||||
import java.util.List;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class Setup {
|
||||
|
||||
@SerializedName("id")
|
||||
@Expose
|
||||
private String id;
|
||||
@SerializedName("devices")
|
||||
@Expose
|
||||
private List<Device> devices = null;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<Device> getDevices() {
|
||||
return devices;
|
||||
}
|
||||
|
||||
public void setDevices(List<Device> devices) {
|
||||
this.devices = devices;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,12 +1,17 @@
|
||||
package com.bwssystems.HABridge.plugins.tcp;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -15,12 +20,14 @@ 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.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
|
||||
public class TCPHome implements Home {
|
||||
private static final Logger log = LoggerFactory.getLogger(TCPHome.class);
|
||||
private byte[] sendData;
|
||||
private Map<String, Socket> theSockets;
|
||||
|
||||
|
||||
public TCPHome(BridgeSettingsDescriptor bridgeSettings) {
|
||||
@@ -31,6 +38,7 @@ public class TCPHome implements Home {
|
||||
@Override
|
||||
public String deviceHandler(CallItem anItem, MultiCommandUtil aMultiUtil, String lightId, int intensity,
|
||||
Integer targetBri,Integer targetBriInc, DeviceDescriptor device, String body) {
|
||||
Socket dataSendSocket = null;
|
||||
log.debug("executing HUE api request to TCP: " + anItem.getItem().getAsString());
|
||||
String theUrl = anItem.getItem().getAsString();
|
||||
if(theUrl != null && !theUrl.isEmpty () && theUrl.startsWith("tcp://")) {
|
||||
@@ -40,34 +48,50 @@ public class TCPHome implements Home {
|
||||
String hostAddr = null;
|
||||
String port = null;
|
||||
InetAddress IPAddress = null;
|
||||
if (hostPortion.contains(":")) {
|
||||
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
|
||||
port = hostPortion.substring(intermediate.indexOf(':') + 1);
|
||||
} else
|
||||
hostAddr = hostPortion;
|
||||
try {
|
||||
IPAddress = InetAddress.getByName(hostAddr);
|
||||
} catch (UnknownHostException e) {
|
||||
// noop
|
||||
dataSendSocket = theSockets.get(hostPortion);
|
||||
if(dataSendSocket == null) {
|
||||
if (hostPortion.contains(":")) {
|
||||
hostAddr = hostPortion.substring(0, intermediate.indexOf(':'));
|
||||
port = hostPortion.substring(intermediate.indexOf(':') + 1);
|
||||
} else
|
||||
hostAddr = hostPortion;
|
||||
try {
|
||||
IPAddress = InetAddress.getByName(hostAddr);
|
||||
} catch (UnknownHostException e) {
|
||||
// noop
|
||||
}
|
||||
|
||||
try {
|
||||
dataSendSocket = new Socket(IPAddress, Integer.parseInt(port));
|
||||
theSockets.put(hostPortion, dataSendSocket);
|
||||
} catch (Exception e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
|
||||
if (theUrlBody.startsWith("0x")) {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
|
||||
} else {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
theUrlBody = StringEscapeUtils.unescapeJava(theUrlBody);
|
||||
sendData = theUrlBody.getBytes();
|
||||
}
|
||||
|
||||
try {
|
||||
Socket dataSendSocket = new Socket(IPAddress, Integer.parseInt(port));
|
||||
DataOutputStream outToClient = new DataOutputStream(dataSendSocket.getOutputStream());
|
||||
outToClient.write(sendData);
|
||||
outToClient.flush();
|
||||
dataSendSocket.close();
|
||||
} catch (Exception e) {
|
||||
// noop
|
||||
log.warn("Could not send data to TCP socket <<<" + e.getMessage() + ">>>, closing socket: " + theUrl);
|
||||
try {
|
||||
dataSendSocket.close();
|
||||
} catch (IOException e1) {
|
||||
// noop
|
||||
}
|
||||
theSockets.remove(hostPortion);
|
||||
}
|
||||
} else
|
||||
log.warn("Tcp Call to be presented as tcp://<ip_address>:<port>/payload, format of request unknown: " + theUrl);
|
||||
@@ -77,6 +101,7 @@ public class TCPHome implements Home {
|
||||
@Override
|
||||
public Home createHome(BridgeSettingsDescriptor bridgeSettings) {
|
||||
log.info("TCP Home created.");
|
||||
theSockets = new HashMap<String, Socket>();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -88,8 +113,18 @@ public class TCPHome implements Home {
|
||||
|
||||
@Override
|
||||
public void closeHome() {
|
||||
// noop
|
||||
|
||||
log.debug("Shutting down TCP sockets.");
|
||||
if(theSockets != null && !theSockets.isEmpty()) {
|
||||
Iterator<String> keys = theSockets.keySet().iterator();
|
||||
while(keys.hasNext()) {
|
||||
String key = keys.next();
|
||||
try {
|
||||
theSockets.get(key).close();
|
||||
} catch (IOException e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.net.UnknownHostException;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -14,6 +15,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.DeviceDataDecode;
|
||||
import com.bwssystems.HABridge.hue.MultiCommandUtil;
|
||||
import com.bwssystems.HABridge.hue.TimeDecode;
|
||||
import com.bwssystems.HABridge.util.UDPDatagramSender;
|
||||
@@ -56,9 +58,12 @@ public class UDPHome implements Home {
|
||||
theUrlBody = TimeDecode.replaceTimeValue(theUrlBody);
|
||||
if (theUrlBody.startsWith("0x")) {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, true);
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
sendData = DatatypeConverter.parseHexBinary(theUrlBody.substring(2));
|
||||
} else {
|
||||
theUrlBody = BrightnessDecode.calculateReplaceIntensityValue(theUrlBody, intensity, targetBri, targetBriInc, false);
|
||||
theUrlBody = DeviceDataDecode.replaceDeviceData(theUrlBody, device);
|
||||
theUrlBody = StringEscapeUtils.unescapeJava(theUrlBody);
|
||||
sendData = theUrlBody.getBytes();
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.scrollableContainer {
|
||||
max-height: 436px; /* sets max-height value for all standards-compliant browsers */
|
||||
height: 310px;
|
||||
position: relative;
|
||||
padding-top: 35px;
|
||||
overflow: hidden;
|
||||
@@ -28,17 +28,17 @@
|
||||
}
|
||||
|
||||
.scrollArea {
|
||||
_height: expression( this.scrollHeight > 599 ? "600px" : "auto" ); /* sets max-height for IE6 */
|
||||
max-height: 400px; /* sets max-height value for all standards-compliant browsers */
|
||||
height: 100%;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #d5d5d5;
|
||||
/* the implementation of this is still quite buggy; specifically, it doesn't like the
|
||||
absolutely positioned headers within
|
||||
-webkit-overflow-scrolling: touch; */
|
||||
-webkit-overflow-scrolling: auto;
|
||||
}
|
||||
.scrollArea table {
|
||||
overflow-x: hidden;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
@@ -48,7 +48,7 @@
|
||||
.scrollArea table th {
|
||||
padding: 0 !important;
|
||||
border: none !important;
|
||||
min-width: 60px;
|
||||
min-width: 40px;
|
||||
}
|
||||
.scrollArea table .th-inner {
|
||||
overflow: hidden;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -44,6 +44,11 @@ app.config (function ($locationProvider, $routeProvider) {
|
||||
controller: 'HassController'
|
||||
}).when ('/domoticzdevices', {
|
||||
templateUrl: 'views/domoticzdevice.html',
|
||||
controller: 'DomoticzController'
|
||||
}).when('/somfydevices', {
|
||||
templateUrl: 'views/somfydevice.html',
|
||||
controller: 'SomfyController'
|
||||
}).otherwise ({
|
||||
controller: 'DomoticzController'
|
||||
}).when ('/lifxdevices', {
|
||||
templateUrl: 'views/lifxdevice.html',
|
||||
@@ -57,6 +62,7 @@ app.config (function ($locationProvider, $routeProvider) {
|
||||
app.run( function (bridgeService) {
|
||||
bridgeService.loadBridgeSettings();
|
||||
bridgeService.getHABridgeVersion();
|
||||
bridgeService.getTestUser();
|
||||
bridgeService.viewMapTypes();
|
||||
});
|
||||
|
||||
@@ -74,7 +80,7 @@ String.prototype.replaceAll = function (search, replace)
|
||||
|
||||
app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
var self = this;
|
||||
this.state = {base: window.location.origin + "/api/devices", bridgelocation: window.location.origin, systemsbase: window.location.origin + "/system", huebase: window.location.origin + "/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, showLifx: false, habridgeversion: ""};
|
||||
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: ""};
|
||||
|
||||
this.displayWarn = function(errorTitle, error) {
|
||||
var toastContent = errorTitle;
|
||||
@@ -146,7 +152,7 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
|
||||
this.clearDevice = function () {
|
||||
self.state.device = {};
|
||||
self.state.olddevicename = "";
|
||||
self.state.olddevicename = null;
|
||||
};
|
||||
|
||||
this.getHABridgeVersion = function () {
|
||||
@@ -160,6 +166,17 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
);
|
||||
};
|
||||
|
||||
this.getTestUser = function () {
|
||||
return $http.get(this.state.systemsbase + "/habridge/testuser").then(
|
||||
function (response) {
|
||||
self.state.testuser = response.data.user;
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Cannot get testuser: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.aContainsB = function (a, b) {
|
||||
return a.indexOf(b) >= 0;
|
||||
}
|
||||
@@ -260,6 +277,11 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateShowSomfy = function () {
|
||||
this.state.showSomfy = self.state.settings.somfyconfigured;
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateShowLifx = function () {
|
||||
this.state.showLifx = self.state.settings.lifxconfigured;
|
||||
return;
|
||||
@@ -277,6 +299,7 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
self.updateShowMqtt();
|
||||
self.updateShowHass();
|
||||
self.updateShowDomoticz();
|
||||
self.updateShowSomfy();
|
||||
self.updateShowLifx();
|
||||
},
|
||||
function (error) {
|
||||
@@ -459,6 +482,20 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
);
|
||||
};
|
||||
|
||||
this.viewSomfyDevices = function () {
|
||||
if(!this.state.showSomfy)
|
||||
return;
|
||||
return $http.get(this.state.base + "/somfy/devices").then(
|
||||
function (response) {
|
||||
self.state.somfydevices = response.data;
|
||||
},
|
||||
function (error) {
|
||||
self.displayWarn("Get Somfy Devices Error: ", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
this.viewLifxDevices = function () {
|
||||
if (!this.state.showLifx)
|
||||
return;
|
||||
@@ -513,6 +550,20 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
type = self.getMapType(s.type[0])
|
||||
s.type = type[0]
|
||||
}
|
||||
if(s.delay === "" || s.delay === null)
|
||||
delete s.delay;
|
||||
if(s.count === "" || s.count === null)
|
||||
delete s.count;
|
||||
if(s.filterIPs === "" || s.filterIPs === null)
|
||||
delete s.filterIPs;
|
||||
if(s.httpVerb === "" || s.httpVerb === null)
|
||||
delete s.httpVerb;
|
||||
if(s.httpBody === "" || s.httpBody === null)
|
||||
delete s.httpBody;
|
||||
if(s.httpHeaders === "" || s.httpHeaders === null)
|
||||
delete s.httpHeaders;
|
||||
if(s.contentType === "" || s.contentType === null)
|
||||
delete s.contentType;
|
||||
}
|
||||
}
|
||||
return theDevices
|
||||
@@ -774,7 +825,7 @@ app.service ('bridgeService', function ($http, $window, ngToast) {
|
||||
|
||||
this.testUrl = function (device, type, value) {
|
||||
var msgDescription = "unknown";
|
||||
var testUrl = this.state.huebase + "/test/lights/" + device.id + "/state";
|
||||
var testUrl = this.state.huebase + "/" + this.state.testuser + "/lights/" + device.id + "/state";
|
||||
var testBody = "{\"on\":";
|
||||
if (type === "off") {
|
||||
testBody = testBody + "false";
|
||||
@@ -1024,6 +1075,25 @@ app.controller ('SystemController', function ($scope, $location, $http, $window,
|
||||
}
|
||||
}
|
||||
};
|
||||
$scope.addSomfytoSettings = function (newsomfyname, newsomfyip, newsomfyusername, newsomfypassword) {
|
||||
if($scope.bridge.settings.somfyaddress == null) {
|
||||
$scope.bridge.settings.somfyaddress = { devices: [] };
|
||||
}
|
||||
var newSomfy = {name: newsomfyname, ip: newsomfyip, username: newsomfyusername, password: newsomfypassword }
|
||||
$scope.bridge.settings.somfyaddress.devices.push(newSomfy);
|
||||
$scope.newsomfyname = null;
|
||||
$scope.newsomfyip = null;
|
||||
$scope.newsomfyusername = null;
|
||||
$scope.newsomfypassword = null;
|
||||
};
|
||||
$scope.removeSomfytoSettings = function (somfyname, somfyip) {
|
||||
for(var i = $scope.bridge.settings.somfyaddress.devices.length - 1; i >= 0; i--) {
|
||||
if($scope.bridge.settings.somfyaddress.devices[i].name === somfyname && $scope.bridge.settings.somfyaddress.devices[i].ip === somfyip) {
|
||||
$scope.bridge.settings.somfyaddress.devices.splice(i, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.bridgeReinit = function () {
|
||||
bridgeService.reinit();
|
||||
};
|
||||
@@ -1096,6 +1166,26 @@ app.controller('LogsController', function ($scope, $location, $http, $window, br
|
||||
};
|
||||
});
|
||||
|
||||
app.directive('postrenderAction', postrenderAction);
|
||||
/* @ngInject */
|
||||
function postrenderAction($timeout) {
|
||||
// ### Directive Interface
|
||||
// Defines base properties for the directive.
|
||||
var directive = {
|
||||
restrict: 'A',
|
||||
priority: 101,
|
||||
link: link
|
||||
};
|
||||
return directive;
|
||||
|
||||
// ### Link Function
|
||||
// Provides functionality for the directive during the DOM building/data binding stage.
|
||||
function link(scope, element, attrs) {
|
||||
$timeout(function() {
|
||||
scope.$evalAsync(attrs.postrenderAction);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
app.controller('ViewingController', function ($scope, $location, $http, $window, bridgeService, ngDialog) {
|
||||
|
||||
bridgeService.viewDevices();
|
||||
@@ -1161,7 +1251,16 @@ app.controller('ViewingController', function ($scope, $location, $http, $window,
|
||||
else
|
||||
$scope.imgBkUrl = "glyphicon glyphicon-plus";
|
||||
};
|
||||
});
|
||||
|
||||
$scope.goToRow = function() {
|
||||
if (bridgeService.state.queueDevId !== null && bridgeService.state.queueDevId !== "") {
|
||||
bridgeService.state.viewDevId = bridgeService.state.queueDevId;
|
||||
$scope.$broadcast("rowSelected", bridgeService.state.viewDevId);
|
||||
console.log("Go to Row selected Id <<" + bridgeService.state.viewDevId + ">>")
|
||||
bridgeService.state.queueDevId = null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('ValueDialogCtrl', function ($scope, bridgeService, ngDialog) {
|
||||
$scope.slider = {
|
||||
@@ -2400,6 +2499,134 @@ app.controller('LifxController', function ($scope, $location, $http, bridgeServi
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('SomfyController', function ($scope, $location, $http, bridgeService, ngDialog) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
$scope.device = bridgeService.state.device;
|
||||
$scope.device_dim_control = "";
|
||||
$scope.bulk = { devices: [] };
|
||||
$scope.selectAll = false;
|
||||
$scope.somfy = {base: "http://", port: "3480", id: ""};
|
||||
bridgeService.viewDevices(); //Needs this if you're navigating to the 'somfy' page directly without going to the home page first..
|
||||
bridgeService.viewSomfyDevices();
|
||||
$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 (somfydevice, dim_control, buildonly) {
|
||||
//TODO - support partial window opening - add back 'dim_control' second param in here, and in somfydevice.html
|
||||
dimpayload = "";
|
||||
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);
|
||||
$scope.device = bridgeService.state.device;
|
||||
if (!buildonly) {
|
||||
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.somfydevices.length; x++) {
|
||||
if(bridgeService.state.somfydevices[x].id === $scope.bulk.devices[i]) {
|
||||
$scope.buildDeviceUrls(bridgeService.state.somfydevices[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.viewSomfyDevices();
|
||||
},
|
||||
function (error) {
|
||||
bridgeService.displayWarn("Error adding Somfy 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.somfydevices.length; x++) {
|
||||
if($scope.bulk.devices.indexOf(bridgeService.state.somfydevices[x]) < 0 && !bridgeService.findDeviceByMapId(bridgeService.state.somfydevices[x].id, bridgeService.state.somfydevices[x].somfyname, "somfyDevice"))
|
||||
$scope.bulk.devices.push(bridgeService.state.somfydevices[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('EditController', function ($scope, $location, $http, bridgeService) {
|
||||
bridgeService.viewMapTypes();
|
||||
$scope.bridge = bridgeService.state;
|
||||
@@ -2447,20 +2674,28 @@ app.controller('EditController', function ($scope, $location, $http, bridgeServi
|
||||
bridgeService.displayWarn("Error adding device. Name has not been changed from original.", null);
|
||||
return;
|
||||
}
|
||||
if (copy)
|
||||
if (copy) {
|
||||
$scope.device.id = null;
|
||||
$scope.device.uniqueid = null;
|
||||
if($scope.bridge.olddevicename !== null && $scope.bridge.olddevicename !== "")
|
||||
$scope.device.mapId = $scope.device.mapId + "-copy";
|
||||
}
|
||||
if($scope.mapTypeSelected !== undefined && $scope.mapTypeSelected !== null)
|
||||
$scope.device.mapType = $scope.mapTypeSelected[0];
|
||||
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));
|
||||
|
||||
bridgeService.addDevice($scope.device).then(
|
||||
function () {
|
||||
bridgeService.state.queueDevId = $scope.device.id;
|
||||
console.log("Device updated for Q Id <<" + bridgeService.state.queueDevId + ">>")
|
||||
$scope.clearDevice();
|
||||
$location.path('/');
|
||||
},
|
||||
@@ -2478,7 +2713,7 @@ app.controller('EditController', function ($scope, $location, $http, bridgeServi
|
||||
if ($scope.onDevices === null)
|
||||
$scope.onDevices = [];
|
||||
$scope.onDevices.push(newitem);
|
||||
$scope.newOnItem = [];
|
||||
$scope.newOnItem = {};
|
||||
};
|
||||
$scope.removeItemOn = function (anItem) {
|
||||
for(var i = $scope.onDevices.length - 1; i >= 0; i--) {
|
||||
@@ -2495,7 +2730,7 @@ app.controller('EditController', function ($scope, $location, $http, bridgeServi
|
||||
if ($scope.dimDevices === null)
|
||||
$scope.dimDevices = [];
|
||||
$scope.dimDevices.push(newitem);
|
||||
$scope.newDimItem = [];
|
||||
$scope.newDimItem = {};
|
||||
};
|
||||
$scope.removeItemDim = function (anItem) {
|
||||
for(var i = $scope.dimDevices.length - 1; i >= 0; i--) {
|
||||
@@ -2512,7 +2747,7 @@ app.controller('EditController', function ($scope, $location, $http, bridgeServi
|
||||
if ($scope.offDevices === null)
|
||||
$scope.offDevices = [];
|
||||
$scope.offDevices.push(newitem);
|
||||
$scope.newOffItem = [];
|
||||
$scope.newOffItem = {};
|
||||
};
|
||||
$scope.removeItemOff = function (anItem) {
|
||||
for(var i = $scope.offDevices.length - 1; i >= 0; i--) {
|
||||
@@ -2685,6 +2920,23 @@ app.filter('configuredLifxItems', function (bridgeService) {
|
||||
}
|
||||
});
|
||||
|
||||
app.filter('configuredSomfyDevices', 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], "somfyDevice")){
|
||||
out.push(input[i]);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
app.controller('VersionController', function ($scope, bridgeService) {
|
||||
$scope.bridge = bridgeService.state;
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,145 +1,148 @@
|
||||
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation" class="active"><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 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.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">
|
||||
<h1 class="panel-title">Current devices ({{bridge.devices.length}})</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
|
||||
</p>
|
||||
|
||||
<scrollable-table watch="bridge.devices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">ID</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="deviceType">Type</th>
|
||||
<th sortable-header col="targetDevice">Target</th>
|
||||
<th sortable-header col="inactive">Inactive</th>
|
||||
<th sortable-header col="noState">No State</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.id}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.deviceType}}</td>
|
||||
<td>{{device.targetDevice}}</td>
|
||||
<td>{{device.inactive}}</td>
|
||||
<td>{{device.noState}}</td>
|
||||
<td>
|
||||
<p>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'on')">Test ON</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'dim')">Test Dim</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'off')">Test OFF</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="editDevice(device)">Edit/Copy</button>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDevice(device)">Delete</button>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">
|
||||
Bridge Device DB Backup <a ng-click="toggleBk()"><span
|
||||
class={{imgBkUrl}} aria-hidden="true"></span></a>
|
||||
</h1>
|
||||
</div>
|
||||
<div ng-if="visibleBk" class="panel-body">
|
||||
<p>Control your backups from this area. Use the default name by hitting backup or specify your own.</p>
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="backup-name">Backup
|
||||
File Name</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input id="backup-name" class="form-control" type="text"
|
||||
ng-model="optionalbackupname" placeholder="Optional">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-click="backupDeviceDb(optionalbackupname)">Backup
|
||||
Device DB</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Filename</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="backup in bridge.backups">
|
||||
<td>{{backup}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="restoreBackup(backup)">Restore</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="deleteBackup(backup)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/ng-template" id="valueDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Select value</h2>
|
||||
<p>
|
||||
<input type="radio" ng-model="valueType" value="percentage" ng-change="changeScale()"> Percentage
|
||||
<input type="radio" ng-model="valueType" value="raw" ng-change="changeScale()"> Raw
|
||||
</p>
|
||||
<p>
|
||||
<rzslider rz-slider-model="slider.value" rz-slider-options="slider.options"></rzslider>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="setValue()">Set</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/ng-template" id="deleteDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Device to Delete?</h2>
|
||||
<p>{{device.name}}</p>
|
||||
<p>Are you Sure?</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-error" ng-click="deleteDevice(device)">Delete</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation" class="active"><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 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 postrender-action="goToRow()">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">Current devices ({{bridge.devices.length}})</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit" ng-click="renumberDevices()">Renumber Devices</button>
|
||||
</p>
|
||||
<scrollable-table watch="bridge.devices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorUniqueId">ID</th>
|
||||
<th sortable-header col="name">Name</th>
|
||||
<th sortable-header col="description">Description</th>
|
||||
<th sortable-header col="deviceType">Type</th>
|
||||
<th sortable-header col="targetDevice">Target</th>
|
||||
<th sortable-header col="inactive">Inactive</th>
|
||||
<th sortable-header col="noState">No State</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices" row-id="{{device.id}}" ng-class="{info: bridge.viewDevId == device.id}" >
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.id}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td class="cr">{{device.description}}</td>
|
||||
<td>{{device.deviceType}}</td>
|
||||
<td>{{device.targetDevice}}</td>
|
||||
<td>{{device.inactive}}</td>
|
||||
<td>{{device.noState}}</td>
|
||||
<td>
|
||||
<p>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'on')">Test ON</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'dim')">Test Dim</button>
|
||||
<button class="btn btn-info" type="submit"
|
||||
ng-click="testUrl(device, 'off')">Test OFF</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="editDevice(device)">Edit/Copy</button>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="deleteDevice(device)">Delete</button>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">
|
||||
Bridge Device DB Backup <a ng-click="toggleBk()"><span
|
||||
class={{imgBkUrl}} aria-hidden="true"></span></a>
|
||||
</h1>
|
||||
</div>
|
||||
<div ng-if="visibleBk" class="panel-body">
|
||||
<p>Control your backups from this area. Use the default name by hitting backup or specify your own.</p>
|
||||
<form class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-xs-12 col-sm-2 control-label" for="backup-name">Backup
|
||||
File Name</label>
|
||||
|
||||
<div class="col-xs-8 col-sm-7">
|
||||
<input id="backup-name" class="form-control" type="text"
|
||||
ng-model="optionalbackupname" placeholder="Optional">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"
|
||||
ng-click="backupDeviceDb(optionalbackupname)">Backup
|
||||
Device DB</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Filename</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="backup in bridge.backups">
|
||||
<td>{{backup}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger" type="submit"
|
||||
ng-click="restoreBackup(backup)">Restore</button>
|
||||
<button class="btn btn-warning" type="submit"
|
||||
ng-click="deleteBackup(backup)">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/ng-template" id="valueDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Select value</h2>
|
||||
<p>
|
||||
<input type="radio" ng-model="valueType" value="percentage" ng-change="changeScale()"> Percentage
|
||||
<input type="radio" ng-model="valueType" value="raw" ng-change="changeScale()"> Raw
|
||||
</p>
|
||||
<p>
|
||||
<rzslider rz-slider-model="slider.value" rz-slider-options="slider.options"></rzslider>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-primary" ng-click="setValue()">Set</button>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/ng-template" id="deleteDialog">
|
||||
<div class="ngdialog-message">
|
||||
<h2>Device to Delete?</h2>
|
||||
<p>{{device.name}}</p>
|
||||
<p>Are you Sure?</p>
|
||||
</div>
|
||||
<div class="ngdialog-buttons mt">
|
||||
<button type="button" class="ngdialog-button ngdialog-button-error" ng-click="deleteDevice(device)">Delete</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<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 role="presentation" class="active"><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>
|
||||
@@ -43,6 +44,7 @@
|
||||
<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>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<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" class="active"><a href="#!/editdevice">Add/Edit</a></li>
|
||||
</ul>
|
||||
@@ -33,7 +34,7 @@
|
||||
fields the bridge uses. Please use care when updating these fields as
|
||||
you may break the settings used by the bridge to call a specific end
|
||||
point device.</p>
|
||||
<p class="text-muted">This area allows you to create any http or
|
||||
<p class="text-muted">This area allows you to create any http, tcp or
|
||||
udp call to an endpoint. You can use the default GET or select the
|
||||
http verb type below and configure a payload for either on, dim or
|
||||
off methods. For Execution of a
|
||||
@@ -41,7 +42,7 @@
|
||||
can use Json notation of array with [{"item":"the
|
||||
payload"},{"item":"another payload"}] to
|
||||
execute multiple entries. Adding the value replacements
|
||||
(${intensity..byte},${intensity.percent},${intensity.math(X*1)}) will
|
||||
(${intensity.byte},${intensity.percent},${intensity.decimal_percent},${intensity.math(X*1)}) will
|
||||
also work. Also, you can go back to any helper tab and click a build
|
||||
action button to add another item for a multi-command.</p>
|
||||
<p class="text-muted">When copying, update the name and select the "Add Bridge
|
||||
@@ -65,17 +66,40 @@
|
||||
ng-model="device.name" placeholder="Device Name"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inactive</td>
|
||||
<td><label>Description</label></td>
|
||||
|
||||
<td><input type="text" class="form-control" id="device-description"
|
||||
ng-model="device.description" placeholder="Device Description"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Comments</label></td>
|
||||
|
||||
<td><input type="text" class="form-control" id="device-comments"
|
||||
ng-model="device.comments" placeholder="Device Comments"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Inactive</label></td>
|
||||
<td><input type="checkbox"
|
||||
ng-model="device.inactive" ng-true-value=true
|
||||
ng-false-value=false> {{device.inactive}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No State (Do not update state for device)</td>
|
||||
<td><label>No State (Do not update state for device)</label></td>
|
||||
<td><input type="checkbox"
|
||||
ng-model="device.noState" ng-true-value=true
|
||||
ng-false-value=false> {{device.noState}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Off State Resets Bri</label></td>
|
||||
<td><input type="checkbox"
|
||||
ng-model="device.offState" ng-true-value=true
|
||||
ng-false-value=false> {{device.offState}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Filter Address (comma separated list)</label></td>
|
||||
<td><input type="text" class="form-control" id="device-requester-addr"
|
||||
ng-model="device.requesterAddress" placeholder="Only use if you want to restrict this device to a specific caller(s)"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Target</label></td>
|
||||
|
||||
|
||||
@@ -1,177 +1,179 @@
|
||||
<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 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.showHue" role="presentation"><a
|
||||
href="#!/huedevices">Hue Devices</a></li>
|
||||
<li role="presentation" class="active"><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.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">HAL Device List
|
||||
({{bridge.haldevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any HAL 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 HAL Devices' list below will show what
|
||||
is already setup for your HAL.</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.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 HAL.</p>
|
||||
<scrollable-table watch="bridge.haldevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="halname">HAL</th>
|
||||
<th>On Button</th>
|
||||
<th>Off Button</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="haldevice in bridge.haldevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{haldevice.haldevicename}}"
|
||||
ng-checked="bulk.devices.indexOf(haldevice.haldevicename) > -1"
|
||||
ng-click="toggleSelection(haldevice.haldevicename)">
|
||||
{{haldevice.haldevicename}}</td>
|
||||
<td>{{haldevice.haldevicetype}}</td>
|
||||
<td>{{haldevice.halname}}</td>
|
||||
<td>
|
||||
<select name="button-on" id="button-on" ng-model="button_on">
|
||||
<option ng-repeat="aButtonOn in haldevice.buttons.DeviceElements"
|
||||
value="{{aButtonOn}}">{{aButtonOn.DeviceName}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select name="button-off" id="button-off" ng-model="button_off">
|
||||
<option ng-repeat="aButtonOff in haldevice.buttons.DeviceElements"
|
||||
value="{{aButtonOff}}">{{aButtonOff.DeviceName}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button ng-if="haldevice.haldevicetype != 'Home' && haldevice.haldevicetype != 'HVAC' && haldevice.haldevicetype != 'IrData'" class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(haldevice, device_dim_control, false)">Build Item</button>
|
||||
<button ng-if="haldevice.haldevicetype == 'Home'" class="btn btn-success" type="submit"
|
||||
ng-click="buildHALHomeUrls(haldevice, false)">Build Home/Away</button>
|
||||
<button ng-if="haldevice.haldevicetype == 'IrData'" class="btn btn-success" type="submit"
|
||||
ng-click="buildButtonUrls(haldevice, button_on, button_off, false)">Build
|
||||
A Button</button>
|
||||
<ul ng-if="haldevice.haldevicetype == 'HVAC'" class="list-group">
|
||||
<li class="list-group-item">
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALHeatUrls(haldevice, false)">Heat</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALCoolUrls(haldevice, false)">Cool</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALAutoUrls(haldevice, false)">Auto</button>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALOffUrls(haldevice, false)">Off</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALFanUrls(haldevice, false)">Fan</button>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</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 HAL 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.haldevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="halname">HAL</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHalItems">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.deviceType}}</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>
|
||||
<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 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.showHue" role="presentation"><a
|
||||
href="#!/huedevices">Hue Devices</a></li>
|
||||
<li role="presentation" class="active"><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">HAL Device List
|
||||
({{bridge.haldevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any HAL 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 HAL Devices' list below will show what
|
||||
is already setup for your HAL.</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 HAL.</p>
|
||||
<scrollable-table watch="bridge.haldevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="halname">HAL</th>
|
||||
<th>On Button</th>
|
||||
<th>Off Button</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="haldevice in bridge.haldevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{haldevice.haldevicename}}"
|
||||
ng-checked="bulk.devices.indexOf(haldevice.haldevicename) > -1"
|
||||
ng-click="toggleSelection(haldevice.haldevicename)">
|
||||
{{haldevice.haldevicename}}</td>
|
||||
<td>{{haldevice.haldevicetype}}</td>
|
||||
<td>{{haldevice.halname}}</td>
|
||||
<td>
|
||||
<select name="button-on" id="button-on" ng-model="button_on">
|
||||
<option ng-repeat="aButtonOn in haldevice.buttons.DeviceElements"
|
||||
value="{{aButtonOn}}">{{aButtonOn.DeviceName}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<select name="button-off" id="button-off" ng-model="button_off">
|
||||
<option ng-repeat="aButtonOff in haldevice.buttons.DeviceElements"
|
||||
value="{{aButtonOff}}">{{aButtonOff.DeviceName}}</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button ng-if="haldevice.haldevicetype != 'Home' && haldevice.haldevicetype != 'HVAC' && haldevice.haldevicetype != 'IrData'" class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(haldevice, device_dim_control, false)">Build Item</button>
|
||||
<button ng-if="haldevice.haldevicetype == 'Home'" class="btn btn-success" type="submit"
|
||||
ng-click="buildHALHomeUrls(haldevice, false)">Build Home/Away</button>
|
||||
<button ng-if="haldevice.haldevicetype == 'IrData'" class="btn btn-success" type="submit"
|
||||
ng-click="buildButtonUrls(haldevice, button_on, button_off, false)">Build
|
||||
A Button</button>
|
||||
<ul ng-if="haldevice.haldevicetype == 'HVAC'" class="list-group">
|
||||
<li class="list-group-item">
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALHeatUrls(haldevice, false)">Heat</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALCoolUrls(haldevice, false)">Cool</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALAutoUrls(haldevice, false)">Auto</button>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALOffUrls(haldevice, false)">Off</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildHALFanUrls(haldevice, false)">Fan</button>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</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 HAL 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.haldevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="halname">HAL</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHalItems">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{device.name}}</td>
|
||||
<td>{{device.deviceType}}</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>
|
||||
|
||||
@@ -1,112 +1,113 @@
|
||||
<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="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li 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.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">Harmony Activity List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Harmony Activity, 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 Activities' list
|
||||
below will show what is already setup for your Harmony Hubs.</p>
|
||||
|
||||
<scrollable-table watch="bridge.harmonyactivities">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="label" comparator-fn="comparatorLabel">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="harmonyactivity in bridge.harmonyactivities">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{harmonyactivity.activity.label}}</td>
|
||||
<td>{{harmonyactivity.activity.id}}</td>
|
||||
<td>{{harmonyactivity.hub}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildActivityUrls(harmonyactivity)">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 Activities <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.harmonyactivities">
|
||||
<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">Hub</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHarmonyActivities">
|
||||
<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>
|
||||
<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="#!/harmonyactivities">Harmony Activities</a></li>
|
||||
<li 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">Harmony Activity List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Harmony Activity, 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 Activities' list
|
||||
below will show what is already setup for your Harmony Hubs.</p>
|
||||
|
||||
<scrollable-table watch="bridge.harmonyactivities">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="label" comparator-fn="comparatorLabel">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="harmonyactivity in bridge.harmonyactivities">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{harmonyactivity.activity.label}}</td>
|
||||
<td>{{harmonyactivity.activity.id}}</td>
|
||||
<td>{{harmonyactivity.hub}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildActivityUrls(harmonyactivity)">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 Activities <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.harmonyactivities">
|
||||
<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">Hub</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHarmonyActivities">
|
||||
<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>
|
||||
@@ -1,131 +1,132 @@
|
||||
<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="#!/harmonyactivities">Harmony
|
||||
Activities</a></li>
|
||||
<li role="presentation" class="active"><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.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">Harmony Device List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Harmony Device and Buttons, 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 Harmony Buttons' list below will show what is already
|
||||
setup for your Harmony Hubs.</p>
|
||||
|
||||
<scrollable-table watch="bridge.harmonydevices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="label" comparator-fn="comparatorLabel">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>On Button</th>
|
||||
<th>Off Button</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmonydevice in bridge.harmonydevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{harmonydevice.device.label}}</td>
|
||||
<td>{{harmonydevice.device.id}}</td>
|
||||
<td>{{harmonydevice.hub}}</td>
|
||||
<td><select name="device-ctrlon" id="device-ctrlon"
|
||||
ng-model="devicectrlon">
|
||||
<optgroup ng-repeat="ctrlon in harmonydevice.device.controlGroup"
|
||||
label="{{ctrlon.name}}">
|
||||
<option ng-repeat="funcon in ctrlon.function"
|
||||
value="{{funcon.action}}">{{funcon.label}}</option>
|
||||
</optgroup>
|
||||
</select></td>
|
||||
<td><select name="device-ctrloff" id="device-ctrloff"
|
||||
ng-model="devicectrloff">
|
||||
<optgroup ng-repeat="ctrloff in harmonydevice.device.controlGroup"
|
||||
label="{{ctrloff.name}}">
|
||||
<option ng-repeat="funcoff in ctrloff.function"
|
||||
value="{{funcoff.action}}">{{funcoff.label}}</option>
|
||||
</optgroup>
|
||||
</select></td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff)">Build
|
||||
A Button</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Harmony Buttons <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.harmonydevices">
|
||||
<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">Hub</th>
|
||||
<th>Harmony Device-Button On-Button Off</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHarmonyButtons | orderBy:predicate:reverse">
|
||||
<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>
|
||||
<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="#!/harmonyactivities">Harmony
|
||||
Activities</a></li>
|
||||
<li role="presentation" class="active"><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">Harmony Device List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Harmony Device and Buttons, 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 Harmony Buttons' list below will show what is already
|
||||
setup for your Harmony Hubs.</p>
|
||||
|
||||
<scrollable-table watch="bridge.harmonydevices">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="label" comparator-fn="comparatorLabel">Name</th>
|
||||
<th sortable-header col="id" comparator-fn="comparatorNumber">Id</th>
|
||||
<th sortable-header col="hub" comparator-fn="comparatorHub">Hub</th>
|
||||
<th>On Button</th>
|
||||
<th>Off Button</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmonydevice in bridge.harmonydevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{harmonydevice.device.label}}</td>
|
||||
<td>{{harmonydevice.device.id}}</td>
|
||||
<td>{{harmonydevice.hub}}</td>
|
||||
<td><select name="device-ctrlon" id="device-ctrlon"
|
||||
ng-model="devicectrlon">
|
||||
<optgroup ng-repeat="ctrlon in harmonydevice.device.controlGroup"
|
||||
label="{{ctrlon.name}}">
|
||||
<option ng-repeat="funcon in ctrlon.function"
|
||||
value="{{funcon.action}}">{{funcon.label}}</option>
|
||||
</optgroup>
|
||||
</select></td>
|
||||
<td><select name="device-ctrloff" id="device-ctrloff"
|
||||
ng-model="devicectrloff">
|
||||
<optgroup ng-repeat="ctrloff in harmonydevice.device.controlGroup"
|
||||
label="{{ctrloff.name}}">
|
||||
<option ng-repeat="funcoff in ctrloff.function"
|
||||
value="{{funcoff.action}}">{{funcoff.label}}</option>
|
||||
</optgroup>
|
||||
</select></td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildButtonUrls(harmonydevice, devicectrlon, devicectrloff)">Build
|
||||
A Button</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Harmony Buttons <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.harmonydevices">
|
||||
<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">Hub</th>
|
||||
<th>Harmony Device-Button On-Button Off</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHarmonyButtons | orderBy:predicate:reverse">
|
||||
<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>
|
||||
@@ -18,6 +18,7 @@
|
||||
<li ng-if="bridge.showMqtt" role="presentation"><a href="#!/mqttmessages">MQTT Messages</a></li>
|
||||
<li role="presentation" class="active"><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>
|
||||
@@ -43,6 +44,7 @@
|
||||
<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>
|
||||
|
||||
@@ -1,127 +1,128 @@
|
||||
<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 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 role="presentation" class="active"><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.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">Hue Device List
|
||||
({{bridge.huedevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Hue 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 Hue Devices' list below will show what
|
||||
is already setup for your Hue.</p>
|
||||
<p class="text-muted">Use the check boxes by the names to use the bulk addition
|
||||
feature. Select your items, then click bulk add below. Your items
|
||||
will be added with on, off and dim with the
|
||||
name of the device from the Hue.</p>
|
||||
<scrollable-table watch="bridge.huedevices">
|
||||
<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">Id</th>
|
||||
<th sortable-header col="huename">Hue</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="huedevice in bridge.huedevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{huedevice.device.uniqueid}}"
|
||||
ng-checked="bulk.devices.indexOf(huedevice.device.uniqueid) > -1"
|
||||
ng-click="toggleSelection(huedevice.device.uniqueid)">
|
||||
{{huedevice.device.name}}</td>
|
||||
<td>{{huedevice.device.uniqueid}}</td>
|
||||
<td>{{huedevice.huename}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(huedevice, false)">Build Item</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
<div class="panel-footer">
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="bulkAddDevices()">Bulk Add
|
||||
({{bulk.devices.length}})</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Hue 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.huedevices">
|
||||
<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">hue</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHueItems">
|
||||
<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>
|
||||
<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 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 role="presentation" class="active"><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">Hue Device List
|
||||
({{bridge.huedevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Hue 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 Hue Devices' list below will show what
|
||||
is already setup for your Hue.</p>
|
||||
<p class="text-muted">Use the check boxes by the names to use the bulk addition
|
||||
feature. Select your items, then click bulk add below. Your items
|
||||
will be added with on, off and dim with the
|
||||
name of the device from the Hue.</p>
|
||||
<scrollable-table watch="bridge.huedevices">
|
||||
<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">Id</th>
|
||||
<th sortable-header col="huename">Hue</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="huedevice in bridge.huedevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{huedevice.device.uniqueid}}"
|
||||
ng-checked="bulk.devices.indexOf(huedevice.device.uniqueid) > -1"
|
||||
ng-click="toggleSelection(huedevice.device.uniqueid)">
|
||||
{{huedevice.device.name}}</td>
|
||||
<td>{{huedevice.device.uniqueid}}</td>
|
||||
<td>{{huedevice.huename}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(huedevice, false)">Build Item</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
<div class="panel-footer">
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="bulkAddDevices()">Bulk Add
|
||||
({{bulk.devices.length}})</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Hue 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.huedevices">
|
||||
<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">hue</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredHueItems">
|
||||
<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>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<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 role="presentation" class="active"><a href="#!/lifxdevices">LIFX Devices</a></li>
|
||||
<li role="presentation"><a href="#!/editdevice">Add/Edit</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -1,89 +1,90 @@
|
||||
<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" class="active"><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.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.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">
|
||||
<h1 class="panel-title">Log Messages</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit" ng-click="updateLogs()">Update
|
||||
Log</button>
|
||||
</p>
|
||||
<scrollable-table watch="bridge.logMsgs">
|
||||
<table class="table table-striped table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th sortable-header col="time">Time</th>
|
||||
<th sortable-header col="level">Level</th>
|
||||
<th sortable-header col="message">Message</th>
|
||||
<th sortable-header col="component">Component</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="logMessage in bridge.logMsgs">
|
||||
<td>{{logMessage.time}}</td>
|
||||
<td>{{logMessage.level}}</td>
|
||||
<td>{{logMessage.message}}</td>
|
||||
<td>{{logMessage.component}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">
|
||||
Logging Configuration <a ng-click="toggle()"><span
|
||||
class={{imgUrl}} aria-hidden="true"></a>
|
||||
</h1>
|
||||
</div>
|
||||
<div ng-if="visible" class="panel-body">
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit"
|
||||
ng-click="updateLoggers()">Update Log Levels</button>
|
||||
Show All Loggers <input type="checkbox" ng-model="bridge.logShowAll"
|
||||
ng-change="reloadLoggers()" ng-true-value=true ng-false-value=false>
|
||||
{{bridge.logShowAll}}
|
||||
</p>
|
||||
<scrollable-table watch="bridge.loggerInfo">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th sortable-header col="logLevel">Log Level</th>
|
||||
<th sortable-header col="loggerName">Component</th>
|
||||
<th>New Log Level</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="logInfo in bridge.loggerInfo">
|
||||
<td>{{logInfo.logLevel.substr(0,logInfo.logLevel.indexOf("_"))}}</td>
|
||||
<td>{{logInfo.loggerName}}</td>
|
||||
<td><select name="new-log-level" id="new-log-level"
|
||||
ng-change="addToUpdate(logInfo)" ng-model="logInfo.newLogLevel">
|
||||
<option ng-repeat="alevel in levels" value="{{alevel}}">{{alevel.substr(0,alevel.indexOf("_"))}}</option>
|
||||
</select></td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
<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" class="active"><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.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">
|
||||
<h1 class="panel-title">Log Messages</h1>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit" ng-click="updateLogs()">Update
|
||||
Log</button>
|
||||
</p>
|
||||
<scrollable-table watch="bridge.logMsgs">
|
||||
<table class="table table-striped table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th sortable-header col="time">Time</th>
|
||||
<th sortable-header col="level">Level</th>
|
||||
<th sortable-header col="message">Message</th>
|
||||
<th sortable-header col="component">Component</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="logMessage in bridge.logMsgs">
|
||||
<td>{{logMessage.time}}</td>
|
||||
<td>{{logMessage.level}}</td>
|
||||
<td>{{logMessage.message}}</td>
|
||||
<td>{{logMessage.component}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h1 class="panel-title">
|
||||
Logging Configuration <a ng-click="toggle()"><span
|
||||
class={{imgUrl}} aria-hidden="true"></a>
|
||||
</h1>
|
||||
</div>
|
||||
<div ng-if="visible" class="panel-body">
|
||||
<p>
|
||||
<button class="btn btn-primary" type="submit"
|
||||
ng-click="updateLoggers()">Update Log Levels</button>
|
||||
Show All Loggers <input type="checkbox" ng-model="bridge.logShowAll"
|
||||
ng-change="reloadLoggers()" ng-true-value=true ng-false-value=false>
|
||||
{{bridge.logShowAll}}
|
||||
</p>
|
||||
<scrollable-table watch="bridge.loggerInfo">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th sortable-header col="logLevel">Log Level</th>
|
||||
<th sortable-header col="loggerName">Component</th>
|
||||
<th>New Log Level</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="logInfo in bridge.loggerInfo">
|
||||
<td>{{logInfo.logLevel.substr(0,logInfo.logLevel.indexOf("_"))}}</td>
|
||||
<td>{{logInfo.loggerName}}</td>
|
||||
<td><select name="new-log-level" id="new-log-level"
|
||||
ng-change="addToUpdate(logInfo)" ng-model="logInfo.newLogLevel">
|
||||
<option ng-repeat="alevel in levels" value="{{alevel}}">{{alevel.substr(0,alevel.indexOf("_"))}}</option>
|
||||
</select></td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,117 +1,118 @@
|
||||
<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 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 role="presentation" class="active"><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.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">MQTT Messages</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any MQTT Broker, 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.
|
||||
You can add topic and content in the text areas provided
|
||||
then selecting the publish generation. 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 MQTT Publish messages' list below will show what is already
|
||||
setup for your MQTT Brokers.</p>
|
||||
|
||||
<scrollable-table watch="bridge.mqttbrokers">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">ClientID</th>
|
||||
<th sortable-header col="ip">IP</th>
|
||||
<th>Topic</th>
|
||||
<th>Content</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="mqttbroker in bridge.mqttbrokers">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{mqttbroker.clientId}}</td>
|
||||
<td>{{mqttbroker.ip}}</td>
|
||||
<td>
|
||||
<textarea rows="2" class="form-control" id="mqtt-topic"
|
||||
ng-model="mqtttopic" placeholder="The MQTT Topic"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<textarea rows="2" class="form-control" id="mqtt-content"
|
||||
ng-model="mqttcontent" placeholder="The MQTT Message Content"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildMQTTPublish(mqttbroker, mqtttopic, mqttcontent)">Build
|
||||
publish Message</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured MQTT Messages <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.mqttbrokers">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="nameclientid">Name</th>
|
||||
<th sortable-header col="targetDevice">ClientID</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredMqttMsgs | orderBy:predicate:reverse">
|
||||
<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>
|
||||
<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 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 role="presentation" class="active"><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">MQTT Messages</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any MQTT Broker, 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.
|
||||
You can add topic and content in the text areas provided
|
||||
then selecting the publish generation. 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 MQTT Publish messages' list below will show what is already
|
||||
setup for your MQTT Brokers.</p>
|
||||
|
||||
<scrollable-table watch="bridge.mqttbrokers">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="name">ClientID</th>
|
||||
<th sortable-header col="ip">IP</th>
|
||||
<th>Topic</th>
|
||||
<th>Content</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="mqttbroker in bridge.mqttbrokers">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{mqttbroker.clientId}}</td>
|
||||
<td>{{mqttbroker.ip}}</td>
|
||||
<td>
|
||||
<textarea rows="2" class="form-control" id="mqtt-topic"
|
||||
ng-model="mqtttopic" placeholder="The MQTT Topic"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<textarea rows="2" class="form-control" id="mqtt-content"
|
||||
ng-model="mqttcontent" placeholder="The MQTT Message Content"></textarea>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildMQTTPublish(mqttbroker, mqtttopic, mqttcontent)">Build
|
||||
publish Message</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured MQTT Messages <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.mqttbrokers">
|
||||
<table class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Row</th>
|
||||
<th sortable-header col="nameclientid">Name</th>
|
||||
<th sortable-header col="targetDevice">ClientID</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredMqttMsgs | orderBy:predicate:reverse">
|
||||
<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>
|
||||
@@ -1,133 +1,134 @@
|
||||
<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 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 role="presentation" class="active"><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.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">Nest Items List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Nest Item, 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 Nest Items' list below will show what
|
||||
is already setup for your Nest.</p>
|
||||
|
||||
<scrollable-table watch="bridge.nestitems">
|
||||
<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="type">Type</th>
|
||||
<th sortable-header col="location">Location</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="nestitem in bridge.nestitems | orderBy:predicate:reverse">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{nestitem.name}}</td>
|
||||
<td>{{nestitem.type}}</td>
|
||||
<td>{{nestitem.location}}</td>
|
||||
<td>
|
||||
<ul class="list-group">
|
||||
<li ng-if="nestitem.type ==='Home' " class="list-group-item">
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestHomeUrls(nestitem)">Home/Away</button>
|
||||
</li>
|
||||
<li ng-if="nestitem.type ==='Thermostat' " class="list-group-item">
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestTempUrls(nestitem)">Temp</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestHeatUrls(nestitem)">Heat</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestCoolUrls(nestitem)">Cool</button>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestRangeUrls(nestitem)">Range</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestOffUrls(nestitem)">Off</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestFanUrls(nestitem)">Fan</button>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Nest Items <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.nestitems">
|
||||
<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">Location</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices | configuredNestItems | orderBy:predicate:reverse">
|
||||
<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>
|
||||
<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 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 role="presentation" class="active"><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">Nest Items List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Nest Item, 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 Nest Items' list below will show what
|
||||
is already setup for your Nest.</p>
|
||||
|
||||
<scrollable-table watch="bridge.nestitems">
|
||||
<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="type">Type</th>
|
||||
<th sortable-header col="location">Location</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="nestitem in bridge.nestitems | orderBy:predicate:reverse">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{nestitem.name}}</td>
|
||||
<td>{{nestitem.type}}</td>
|
||||
<td>{{nestitem.location}}</td>
|
||||
<td>
|
||||
<ul class="list-group">
|
||||
<li ng-if="nestitem.type ==='Home' " class="list-group-item">
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestHomeUrls(nestitem)">Home/Away</button>
|
||||
</li>
|
||||
<li ng-if="nestitem.type ==='Thermostat' " class="list-group-item">
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestTempUrls(nestitem)">Temp</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestHeatUrls(nestitem)">Heat</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestCoolUrls(nestitem)">Cool</button>
|
||||
</p>
|
||||
<p>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestRangeUrls(nestitem)">Range</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestOffUrls(nestitem)">Off</button>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildNestFanUrls(nestitem)">Fan</button>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</scrollable-table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h2 class="panel-title">
|
||||
Already Configured Nest Items <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.nestitems">
|
||||
<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">Location</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="device in bridge.devices | configuredNestItems | orderBy:predicate:reverse">
|
||||
<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>
|
||||
143
src/main/resources/public/views/somfydevice.html
Normal file
143
src/main/resources/public/views/somfydevice.html
Normal file
@@ -0,0 +1,143 @@
|
||||
<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 role="presentation"><a href="#!/veradevices">Vera
|
||||
Devices</a></li>
|
||||
<li role="presentation"><a href="#!/verascenes">Vera 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" class="active"><a href="#!/somfydevices">Somfy 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">Somfy Device List
|
||||
({{bridge.somfydevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Somfy 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 Somfy Devices' list below will show
|
||||
what is already setup for your Somfy.</p>
|
||||
<!-- TODO - dim support for partial window opening.. --<p>
|
||||
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.math(X*1)}">Custom Math</option>
|
||||
</select>
|
||||
</p-->
|
||||
<p>Use the check boxes by the names to use the bulk addition
|
||||
feature. Select your items, then click
|
||||
bulk add below. Your items will be added with the name of the device from the Somfy Tahoma.</p>
|
||||
</div>
|
||||
<scrollable-table watch="bridge.somfydevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="somfyname">Somfy</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="somfydevice in bridge.somfydevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{somfydevice.id}}"
|
||||
ng-checked="bulk.devices.indexOf(somfydevice.id) > -1"
|
||||
ng-click="toggleSelection(somfydevice.id)">
|
||||
{{somfydevice.name}}</td>
|
||||
<td>{{somfydevice.id}}</td>
|
||||
<td>{{somfydevice.category}}</td>
|
||||
<td>{{somfydevice.room}}</td>
|
||||
<td>{{somfydevice.somfyname}}</td>
|
||||
<td>
|
||||
<!--TODO - taken device_dim_control out of here since not yet used-->
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(somfydevice)">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 Somfy Devices <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.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">Somfy</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices |configuredSomfyDevices">
|
||||
<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>
|
||||
@@ -19,6 +19,7 @@
|
||||
<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>
|
||||
@@ -141,25 +142,30 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>IP</th>
|
||||
<th>IP</th>
|
||||
<th>Webhook</th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="harmony in bridge.settings.harmonyaddress.devices">
|
||||
<td>{{harmony.name}}</td>
|
||||
<td>{{harmony.ip}}</td>
|
||||
<td>{{harmony.ip}}</td>
|
||||
<td>{{harmony.webhook}}</td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="removeHarmonytoSettings(harmony.name, harmony.ip)">Del</button></td>
|
||||
ng-click="removeHarmonytoSettings(harmony.name, harmony.ip, harmony.webhook)">Del</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="bridge-settings-next-harmony-name"
|
||||
class="form-control" type="text" ng-model="newharmonyname"
|
||||
placeholder="A Harmony"></td>
|
||||
<td><input id="bridge-settings-next-harmony-ip"
|
||||
class="form-control" type="text" ng-model="newharmonyip"
|
||||
placeholder="192.168.1.3"></td>
|
||||
<td><input id="bridge-settings-next-harmony-ip"
|
||||
class="form-control" type="text" ng-model="newharmonyip"
|
||||
placeholder="192.168.1.3"></td>
|
||||
<td><input id="bridge-settings-next-harmony-webhook"
|
||||
class="form-control" type="text" ng-model="newharmonywebhook"
|
||||
placeholder="http://hook?a=${activity.label}"></td>
|
||||
<td><button class="btn btn-success" type="submit"
|
||||
ng-click="addHarmonytoSettings(newharmonyname, newharmonyip)">Add</button></td>
|
||||
ng-click="addHarmonytoSettings(newharmonyname, newharmonyip, newharmonywebhook)">Add</button></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
@@ -358,6 +364,46 @@
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Somfy Names and IP Addresses</td>
|
||||
<td><table
|
||||
class="table table-bordered table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>IP/hostname</th>
|
||||
<th>Username</th>
|
||||
<th>Password </th>
|
||||
<th>Manage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="somfy in bridge.settings.somfyaddress.devices">
|
||||
<td>{{somfy.name}}</td>
|
||||
<td>{{somfy.ip}}</td>
|
||||
<td>{{somfy.username}}</td>
|
||||
<td ng-if="somfy.password">*******</td>
|
||||
<td ng-if="!somfy.password"> </td>
|
||||
<td><button class="btn btn-danger" type="submit"
|
||||
ng-click="removeSomfytoSettings(somfy.name, somfy.ip)">Del</button></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input id="bridge-settings-next-somfy-name"
|
||||
class="form-control" type="text" ng-model="newsomfyname"
|
||||
placeholder="A Somfy"></td>
|
||||
<td><input id="bridge-settings-next-somfy-ip"
|
||||
class="form-control" type="text" ng-model="newsomfyip"
|
||||
placeholder="https://www.tahomalink.com"></td>
|
||||
<td><input id="bridge-settings-next-somfy-username"
|
||||
class="form-control" type="text" ng-model="newsomfyusername"
|
||||
placeholder="Somfy username"></td>
|
||||
<td><input id="bridge-settings-next-somfy-password"
|
||||
class="form-control" type="password" ng-model="newsomfypassword"
|
||||
placeholder="Somfy password"></td>
|
||||
<td><button class="btn btn-success" type="submit"
|
||||
ng-click="addSomfytoSettings(newsomfyname, newsomfyip, newsomfyusername, newsomfypassword)">Add</button></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nest Username</td>
|
||||
<td><input id="bridge-settings-nestuser" class="form-control"
|
||||
|
||||
@@ -1,142 +1,144 @@
|
||||
<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 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.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.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">Vera Device List
|
||||
({{bridge.veradevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Vera 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 Vera Devices' list below will show
|
||||
what is already setup for your Vera.</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.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 Vera.</p>
|
||||
<scrollable-table watch="bridge.veradevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="veraname">Vera</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="veradevice in bridge.veradevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{veradevice.id}}"
|
||||
ng-checked="bulk.devices.indexOf(veradevice.id) > -1"
|
||||
ng-click="toggleSelection(veradevice.id)">
|
||||
{{veradevice.name}}</td>
|
||||
<td>{{veradevice.id}}</td>
|
||||
<td>{{veradevice.category}}</td>
|
||||
<td>{{veradevice.room}}</td>
|
||||
<td>{{veradevice.veraname}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(veradevice, 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 Vera 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">Vera</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredVeraDevices">
|
||||
<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>
|
||||
<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 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.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">Vera Device List
|
||||
({{bridge.veradevices.length}})</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Vera 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 Vera Devices' list below will show
|
||||
what is already setup for your Vera.</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 Vera.</p>
|
||||
<scrollable-table watch="bridge.veradevices">
|
||||
<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="category">Category</th>
|
||||
<th sortable-header col="room">Room</th>
|
||||
<th sortable-header col="veraname">Vera</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="veradevice in bridge.veradevices">
|
||||
<td>{{$index+1}}</td>
|
||||
<td><input type="checkbox" name="bulk.devices[]"
|
||||
value="{{veradevice.id}}"
|
||||
ng-checked="bulk.devices.indexOf(veradevice.id) > -1"
|
||||
ng-click="toggleSelection(veradevice.id)">
|
||||
{{veradevice.name}}</td>
|
||||
<td>{{veradevice.id}}</td>
|
||||
<td>{{veradevice.category}}</td>
|
||||
<td>{{veradevice.room}}</td>
|
||||
<td>{{veradevice.veraname}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildDeviceUrls(veradevice, 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 Vera 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">Vera</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredVeraDevices">
|
||||
<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>
|
||||
@@ -1,112 +1,113 @@
|
||||
<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 role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/verascenes">Vera
|
||||
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.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">Vera Scene List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Vera 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 Vera Scenes' list below will show what
|
||||
is already setup for your Vera.</p>
|
||||
|
||||
<scrollable-table watch="bridge.verascenes">
|
||||
<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="veraname">Vera</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="verascene in bridge.verascenes">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{verascene.name}}</td>
|
||||
<td>{{verascene.id}}</td>
|
||||
<td>{{verascene.room}}</td>
|
||||
<td>{{verascene.veraname}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildSceneUrls(verascene)">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 Vera 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.verascenes">
|
||||
<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">Vera</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredVeraScenes">
|
||||
<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>
|
||||
<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 role="presentation"><a href="#!/veradevices">Vera Devices</a></li>
|
||||
<li role="presentation" class="active"><a href="#!/verascenes">Vera
|
||||
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">Vera Scene List</h2>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-muted">For any Vera 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 Vera Scenes' list below will show what
|
||||
is already setup for your Vera.</p>
|
||||
|
||||
<scrollable-table watch="bridge.verascenes">
|
||||
<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="veraname">Vera</th>
|
||||
<th>Build Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="verascene in bridge.verascenes">
|
||||
<td>{{$index+1}}</td>
|
||||
<td>{{verascene.name}}</td>
|
||||
<td>{{verascene.id}}</td>
|
||||
<td>{{verascene.room}}</td>
|
||||
<td>{{verascene.veraname}}</td>
|
||||
<td>
|
||||
<button class="btn btn-success" type="submit"
|
||||
ng-click="buildSceneUrls(verascene)">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 Vera 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.verascenes">
|
||||
<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">Vera</th>
|
||||
<th>Map Id</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr
|
||||
ng-repeat="device in bridge.devices | configuredVeraScenes">
|
||||
<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>
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.bwssystems.color.test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.bwssystems.HABridge.hue.ColorDecode;
|
||||
|
||||
public class ConvertCIEColorTestCase {
|
||||
|
||||
@Test
|
||||
public void testColorConversion() {
|
||||
ArrayList<Double> xy = new ArrayList<Double>(Arrays.asList(new Double(0.3972), new Double(0.4564)));
|
||||
|
||||
String colorDecode = ColorDecode.convertCIEtoRGB(xy);
|
||||
Assert.assertEquals(colorDecode, null);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user