diff --git a/bundles/org.openhab.binding.hdpowerview/README.md b/bundles/org.openhab.binding.hdpowerview/README.md index a11c9dd108322..cda450a74d1d4 100644 --- a/bundles/org.openhab.binding.hdpowerview/README.md +++ b/bundles/org.openhab.binding.hdpowerview/README.md @@ -1,7 +1,13 @@ # Hunter Douglas (Luxaflex) PowerView Binding This is an openHAB binding for [Hunter Douglas PowerView](https://www.hunterdouglas.com/operating-systems/motorized/powerview-motorization/overview) motorized shades via their PowerView hub. -In some countries the PowerView system is sold under the brand name [Luxaflex](https://www.luxaflex.com/) +In some countries the PowerView system is sold under the brand name [Luxaflex](https://www.luxaflex.com/). + +This binding supports hubs/gateways of all generations. +Hubs of Generation 1 or 2 are handled commonly and their generation specific features are identified with the *'Generation 1/2 only'* annotation and/or via the [1/2] mark. +Gateways of Generation 3 have generation specific features which are identified with the *'Generation 3 only'* annotation and/or via the [3] mark. +Features that are common to all generations are not annotated or marked. + ![PowerView](doc/hdpowerview.png) @@ -13,110 +19,122 @@ By using a scene to control multiple shades at once, the shades will all begin m ## Supported Things -| Thing | Thing Type | Description | -|----------|------------|-------------| -| hub | Bridge | The PowerView hub provides the interface between your network and the shade's radio network. It also contains channels used to interact with scenes. | -| shade | Thing | A motorized shade. | -| repeater | Thing | A PowerView signal repeater. | +| Thing | Generation | Thing Type | Description | +|----------|------------|------------|-------------------------------------------------------------------------------------------------------------------------------| +| hub | 1, 2 | Bridge | The PowerView hub interfaces between the LAN and the shade's radio network. Contains channels to interact with scenes. | +| shade | 1, 2 | Thing | A motorized shade. | +| repeater | 1, 2 | Thing | A PowerView signal repeater. | +| gateway | 3 | Bridge | Generation 3 gateway interfaces between the LAN and the shade's Bluetooth network. Contains channels to interact with scenes. | +| shade3 | 3 | Thing | A Powerview Generation 3 motorized shade. | ## Discovery Make sure your shades are visible in the PowerView app before attempting discovery. -The binding can automatically discover the PowerView hub. +The binding can automatically discover PowerView hubs and gateways. The discovery process can be started by pressing the refresh button in the Main Configuration UI Inbox. However you can also manually create a (bridge) thing for the hub, and enter the required configuration parameters (see Thing Configuration below). -If the configuration parameters are all valid, the binding will then automatically attempt to connect to the hub. +If the configuration parameters are all valid, the binding will then automatically attempt to connect to the hub/gateway. If the connection succeeds, the hub will indicate its status as Online, otherwise it will show an error status. Once the hub thing has been created and successfully connected, the binding will automatically discover all shades and scenes that are in it. - For each shade discovered: the binding will create a new dedicated thing with its own channels. -- For each repeater discovered: the binding will create a new dedicated thing with its own channels. -- For each scene discovered: the binding will create a new channel dynamically within the hub thing. -- For each scene group discovered: the binding will create a new channel dynamically within the hub thing. -- For each automation discovered: the binding will create a new channel dynamically within the hub thing. +- For each scene discovered: the binding will create a new channel dynamically within the hub/gateway thing. +- [1/2] For each repeater discovered: the binding will create a new dedicated thing with its own channels. +- [1/2] For each scene group discovered: the binding will create a new channel dynamically within the hub thing. +- [1/2] For each automation discovered: the binding will create a new channel dynamically within the hub thing. -If in the future, you add additional shades, repeaters, scenes, scene groups or automations to your system, the binding will discover them too. +[1/2] Generation 1/2 hubs only. + +If in the future, you add additional shades, scenes, repeaters, scene groups or automations to your system, the binding will discover them too. ## Thing Configuration -### Thing Configuration for PowerView Hub +### Thing Configuration for PowerView Hub / Gateway (Thing type `hub`[1/2] or `gateway`[3]) + +| Configuration Parameter | Description | +|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------| +| host | The host name or IP address of the hub on your network. | +| refresh[1/2] | The number of milli-seconds between fetches of the PowerView hub's shade state (default 60'000 one minute). | +| hardRefresh | The number of minutes between hard refreshes of the PowerView hub's shade state (default 180 three hours). See [Hard Refreshes](#hard-refreshes). | +| hardRefreshBatteryLevel[1/2] | The number of hours between hard refreshes of battery levels from the PowerView Hub (or 0 to disable, defaulting to weekly). See [Hard Refreshes](#hard-refreshes). | -| Configuration Parameter | Description | -|-------------------------|---------------| -| host | The host name or IP address of the hub on your network. | -| refresh | The number of milli-seconds between fetches of the PowerView hub's shade state (default 60'000 one minute). | -| hardRefresh | The number of minutes between hard refreshes of the PowerView hub's shade state (default 180 three hours). See [Refreshing the PowerView Hub Cache](#refreshing-the-powerview-hub-cache). | -| hardRefreshBatteryLevel | The number of hours between hard refreshes of battery levels from the PowerView Hub (or 0 to disable, defaulting to weekly). See [Refreshing the PowerView Hub Cache](#refreshing-the-powerview-hub-cache). | +[1/2] Generation 1/2 hubs only. -### Thing Configuration for PowerView Shades and Accessories +### Thing Configuration for PowerView Shades and Accessories[3] -PowerView shades and repeaters should preferably be configured via the automatic discovery process. +PowerView shades and repeaters[3] should preferably be configured via the automatic discovery process. However, for manual configuration of shades and repeaters, the console command `openhab:hdpowerview showIds` can be used to identify the IDs of all connected equipment. This can be used for the `id` parameters described below. #### Thing Configuration for PowerView Shades -| Configuration Parameter | Description | -|-------------------------|-------------| +| Configuration Parameter | Description | +|-------------------------|---------------------------------------------------------------| | id | The ID of the PowerView shade in the app. Must be an integer. | -#### Thing Configuration for PowerView Repeaters +#### Thing Configuration for PowerView Repeaters[1/2] -| Configuration Parameter | Description | -|-------------------------|-------------| +| Configuration Parameter | Description | +|-------------------------|------------------------------------------------------------------| | id | The ID of the PowerView repeater in the app. Must be an integer. | ## Channels -### Channels for Hub (Thing type `hub`) +### Channels for Hub[1/2] (Thing type `hub`) or Gateway[3] (Thing type `gateway`) Scene, scene group and automation channels will be added dynamically to the binding as they are discovered in the hub. -Each will have an entry in the hub as shown below, whereby different scenes, scene groups and automations -have different `id` values: +Each will have an entry in the hub as shown below, whereby different scenes, scene groups and automations have different `id` values: -| Channel Group | Channel | Item Type | Description | -|---------------|---------|-----------|-------------| -| scenes | id | Switch | Setting this to ON will activate the scene. Scenes are stateless in the PowerView hub; they have no on/off state. | -| sceneGroups | id | Switch | Setting this to ON will activate the scene group. Scene groups are stateless in the PowerView hub; they have no on/off state. | -| automations | id | Switch | Setting this to ON will enable the automation, while OFF will disable it. | +| Channel Group | Channel | Item Type | Description | +|-----------------------------|---------|-----------|------------------------------------------------------------------------------------------------------------------------| +| scenes | id | Switch | Setting this to ON will activate the scene. Scenes are stateless in the PowerView hub; they have no on/off state. | +| sceneGroups[1/2] | id | Switch | Setting this to ON will activate the scene group. Scene groups are stateless in the PowerView hub; they have no on/off state. | +| automations[1/2] | id | Switch | Setting this to ON will enable the automation, while OFF will disable it. | -### Channels for Shades (Thing type `shade`) +[1/2] Generation 1/2 hubs only. + +### Channels for Shades (Thing type `shade`[1/2] or `shade3`[3]) A shade always implements a roller shutter channel `position` which controls the vertical position of the shade's (primary) rail. If the shade has slats or rotatable vanes, there is also a dimmer channel `vane` which controls the slat / vane position. If it is a dual action (top-down plus bottom-up) shade, there is also a roller shutter channel `secondary` which controls the vertical position of the secondary rail. All of these channels appear in the binding, but only those which have a physical implementation in the shade, will have any physical effect. -| Channel | Item Type | Description | -|----------------|--------------------------|-------------| -| position | Rollershutter | The vertical position of the shade's rail (if any). -- See [next chapter](#roller-shutter-updown-position-vs-openclose-state). Up/Down commands will move the rail completely up or completely down. Percentage commands will move the rail to an intermediate position. Stop commands will halt any current movement of the rail. | -| secondary | Rollershutter | The vertical position of the secondary rail (if any). Its function is similar to the `position` channel above. -- But see [next chapter](#roller-shutter-updown-position-vs-openclose-state). | -| vane | Dimmer | The degree of opening of the slats or vanes (if any). On some shade types, setting this to a non-zero value might first move the shade `position` fully down, since the slats or vanes can only have a defined state if the shade is in its down position. See [Interdependency between Channel positions](#interdependency-between-channel-positions). | -| command | String | Send a command to the shade. Valid values are: `CALIBRATE`, `IDENTIFY` | -| lowBattery | Switch | Indicates ON when the battery level of the shade is low, as determined by the hub's internal rules. | -| batteryLevel | Number | Battery level (10% = low, 50% = medium, 100% = high) | -| batteryVoltage | Number:ElectricPotential | Battery (resp. mains power supply) voltage reported by the shade. | -| signalStrength | Number | Signal strength (0 for no or unknown signal, 1 for weak, 2 for average, 3 for good or 4 for excellent) | -| hubRssi | Number:Power | Received Signal Strength Indicator for Hub | -| repeaterRssi | Number:Power | Received Signal Strength Indicator for Repeater | +| Channel | Item Type | Description | +|--------------------------------|--------------------------|----------------------------------------------------------------------------------------------------------------| +| position | Rollershutter | The vertical position of the shade's rail (if any). -- See [next chapter](#roller-shutter-updown-position-vs-openclose-state). Up/Down commands will move the rail completely up or completely down. Percentage commands will move the rail to an intermediate position. Stop commands will halt any current movement of the rail. | +| secondary | Rollershutter | The vertical position of the secondary rail (if any). Its function is similar to the `position` channel above. -- But see [next chapter](#roller-shutter-updown-position-vs-openclose-state). | +| vane | Dimmer | The degree of opening of the slats or vanes (if any). On some shade types, setting this to a non-zero value might first move the shade `position` fully down, since the slats or vanes can only have a defined state if the shade is in its down position. See [Interdependency between Channel positions](#interdependency-between-channel-positions). | +| command | String | Advanced: Send a command to the shade. | +| lowBattery | Switch | Indicates ON when the battery level of the shade is low, as determined by the hub's internal rules. | +| batteryLevel | Number | Battery level (10% = low, 50% = medium, 100% = high) | +| batteryVoltage[1/2] | Number:ElectricPotential | Battery (resp. mains power supply) voltage reported by the shade. | +| signalStrength | Number / Number:Power | Shade radio signal strength. | +| hubRssi[1/2] | Number:Power | Received Signal Strength Indicator for Hub. | +| repeaterRssi[1/2] | Number:Power | Received Signal Strength Indicator for Repeater. | Notes: - The channels `position`, `secondary` and `vane` exist if the shade physically supports such channels. - The shade's Power Option is set via the PowerView app with possible values 'Battery Wand', 'Rechargeable Battery Wand' or 'Hardwired Power Supply'. The channels `lowBattery` and `batteryLevel` exist if you have _not_ selected 'Hardwired Power Supply' in the app. -- The RSSI values will only be updated upon manual request by a `REFRESH` command (e.g. in a rule). +- On Generation 1/2 hubs, the valid values for the `command` channel are: `CALIBRATE`, `IDENTIFY`. +On Generation 3 gateways, the only valid value is: `IDENTIFY`. +- On Generation 1/2 hubs the signal strength is 0 for no or unknown signal, 1 for weak, 2 for average, 3 for good, or 4 for excellent. +On Generation 3 gateways the signal strength is displayed in dBm (deciBel-milliWatt). +- [1/2] The RSSI values will only be updated upon manual request by a `REFRESH` command (e.g. in a rule). +- [1/2] Repeaters are supported on Generation 1/2 hubs only. -### Channels for Repeaters (Thing type `repeater`) +### Channels for Repeaters (Thing type `repeater`)[1/2] -| Channel | Item Type | Description | -|-----------------|-----------|-------------------------------| +| Channel | Item Type | Description | +|-----------------|-----------|---------------------------------------------------------------------------------------------| | color | Color | Controls the color of the LED ring. A switch item can be linked: ON = white, OFF = turn off | -| brightness | Dimmer | Controls the brightness of the LED ring. | -| identify | String | Flash repeater to identify. Valid values are: `IDENTIFY` | -| blinkingEnabled | Switch | Blink during commands. | +| brightness | Dimmer | Controls the brightness of the LED ring. | +| identify | String | Flash repeater to identify. Valid values are: `IDENTIFY` | +| blinkingEnabled | Switch | Blink during commands. | ### Roller Shutter Up/Down Position vs. Open/Close State @@ -126,22 +144,22 @@ And for horizontal shades, it maps the horizontal position of the "truck" to the Depending on whether the shade is a top-down, bottom-up, left-right, right-left, dual action shade, or, a shade with a secondary blackout panel, the `OPEN` and `CLOSED` position of the shades may differ from the ▲ / ▼ commands follows.. -| Type of Shade | Channel | Rollershutter Command | Motion direction | Shade State | Percent | Pebble Remote Button | -|-----------------------------|-------------------|-----------------------|------------------|----------------|-------------------|----------------------| -| Single action
bottom-up | `position` | ▲ | Up | `OPEN` | 0% | ▲ | -| | | ▼ | Down | `CLOSED` | 100% | ▼ | -| Single action
top-down | `position` | ▲ | Up | **`CLOSED`** | 0% | ▲ | -| | | ▼ | Down | **`OPEN`** | 100% | ▼ | -| Single action
right-left | `position` | ▲ | _**Left**_ | `OPEN` | 0% | ▲ | -| | | ▼ | _**Right**_ | `CLOSED` | 100% | ▼ | -| Single action
left-right | `position` | ▲ | _**Right**_ | `OPEN` | 0% | ▲ | -| | | ▼ | _**Left**_ | `CLOSED` | 100% | ▼ | -| Dual action
(lower rail) | `position` | ▲ | Up | `OPEN` | 0% | ▲ | -| | | ▼ | Down | `CLOSED` | 100% | ▼ | -| Dual action
(upper rail) | _**`secondary`**_ | ▲ | Up | **`CLOSED`** | 0%1) | ![dual_action arrow_right](doc/right.png) | -| | | ▼ | Down | **`OPEN`** | 100%1) | ![dual_action arrow_left](doc/left.png) | -| Blackout panel ('DuoLite') | _**`secondary`**_ | ▲ | Up | `OPEN` | 0% | ▲ | -| | | ▼ | Down | `CLOSED` | 100% | ▼ | +| Type of Shade | Channel | Rollershutter Command | Motion direction | Shade State | Percent | Pebble Remote Button | +|-----------------------------|-------------------|-----------------------|------------------|----------------|-------------------|--------------------------------------------| +| Single action
bottom-up | `position` | ▲ | Up | `OPEN` | 0% | ▲ | +| | | ▼ | Down | `CLOSED` | 100% | ▼ | +| Single action
top-down | `position` | ▲ | Up | **`CLOSED`** | 0% | ▲ | +| | | ▼ | Down | **`OPEN`** | 100% | ▼ | +| Single action
right-left | `position` | ▲ | _**Left**_ | `OPEN` | 0% | ▲ | +| | | ▼ | _**Right**_ | `CLOSED` | 100% | ▼ | +| Single action
left-right | `position` | ▲ | _**Right**_ | `OPEN` | 0% | ▲ | +| | | ▼ | _**Left**_ | `CLOSED` | 100% | ▼ | +| Dual action
(lower rail) | `position` | ▲ | Up | `OPEN` | 0% | ▲ | +| | | ▼ | Down | `CLOSED` | 100% | ▼ | +| Dual action
(upper rail) | _**`secondary`**_ | ▲ | Up | **`CLOSED`** | 0%1) | ![dual_action arrow_right](doc/right.png) | +| | | ▼ | Down | **`OPEN`** | 100%1) | ![dual_action arrow_left](doc/left.png) | +| Blackout panel ('DuoLite') | _**`secondary`**_ | ▲ | Up | `OPEN` | 0% | ▲ | +| | | ▼ | Down | `CLOSED` | 100% | ▼ | _**1) BUG NOTE**_: In openHAB versions v3.1.x and earlier, there was a bug in the handling of the position percent value of the `secondary` shade. Although the RollerShutter Up/Down commands functioned properly as described in the table above, the percent state values (e.g. displayed on a slider control), did not. @@ -177,7 +195,15 @@ And the value of `position` is constrained by the prior value of `secondary`. On shades with a secondary blackout panel 'DuoLite', the secondary blackout panel cannot be moved unless the main shade panel is already down. In this case, the position of the secondary blackout panel is reported as 0%. -## Refreshing the PowerView Hub Cache +## Hard Refreshes + +### Hard Refresh on Generation 3 Gateways[3] + +In Generation 3 systems, whenever the state of a shade or scene changes, it immediately notifies the gateway, and the gateway immediately notifies the openHAB binding. +However, in case that any notifications have been lost, (e.g. due to a network error), the binding occasionally requests a full update (i.e. a 'hard refresh') of all shade and scene states from the gateway. +The time interval between hard refreshes is set in the `hardRefresh` configuration parameter. + +### Hard Refresh on Generation 1/2 Hubs[1/2] The hub maintains a cache of the last known state of its shades, and this binding delivers those values. Usually the shades will be moved by this binding, so since the hub is always involved in the moving process, it updates this cache accordingly. @@ -226,10 +252,16 @@ For single shades the refresh takes the item's channel into consideration: ### `demo.things` File ```java +// generation 1/2 Bridge hdpowerview:hub:home "Luxaflex Hub" @ "Living Room" [host="192.168.1.123"] { Thing shade s50150 "Living Room Shade" @ "Living Room" [id="50150"] Thing repeater r16384 "Bedroom Repeater" @ "Bedroom" [id="16384"] } + +// generation 3 +Bridge hdpowerview:gateway:home "Luxaflex Gateway" @ "Living Room" [host="192.168.1.123"] { + Thing shade3 s50150 "Living Room Shade" @ "Living Room" [id="50150"] +} ``` ### `demo.items` File @@ -237,6 +269,7 @@ Bridge hdpowerview:hub:home "Luxaflex Hub" @ "Living Room" [host="192.168.1.123" Shade items: ```java +// generation 1/2 Rollershutter Living_Room_Shade_Position "Living Room Shade Position [%.0f %%]" {channel="hdpowerview:shade:home:s50150:position"} Rollershutter Living_Room_Shade_Secondary "Living Room Shade Secondary Position [%.0f %%]" {channel="hdpowerview:shade:home:s50150:secondary"} Dimmer Living_Room_Shade_Vane "Living Room Shade Vane [%.0f %%]" {channel="hdpowerview:shade:home:s50150:vane"} @@ -245,9 +278,17 @@ Number Living_Room_Shade_Battery_Level "Battery Level" {channel="hdpowerview:sha Number:ElectricPotential Living_Room_Shade_Battery_Voltage "Battery Voltage" {channel="hdpowerview:shade:home:s50150:batteryVoltage"} String Living_Room_Shade_Command "Living Room Shade Command" {channel="hdpowerview:shade:home:s50150:command"} Number Living_Room_Shade_SignalStrength "Living Room Shade Signal Strength" {channel="hdpowerview:shade:home:s50150:signalStrength"} + +// generation 3 +Rollershutter Living_Room_Shade_Position "Living Room Shade Position [%.0f %%]" {channel="hdpowerview:shade3:home:s50150:position"} +Rollershutter Living_Room_Shade_Secondary "Living Room Shade Secondary Position [%.0f %%]" {channel="hdpowerview:shade3:home:s50150:secondary"} +Dimmer Living_Room_Shade_Vane "Living Room Shade Vane [%.0f %%]" {channel="hdpowerview:shade3:home:s50150:vane"} +Switch Living_Room_Shade_Battery_Low_Alarm "Living Room Shade Battery Low Alarm [%s]" {channel="hdpowerview:shade3:home:s50150:lowBattery"} +Number Living_Room_Shade_Battery_Level "Battery Level" {channel="hdpowerview:shade3:home:s50150:batteryLevel"} +String Living_Room_Shade_Command "Living Room Shade Command" {channel="hdpowerview:shade3:home:s50150:command"} ``` -Repeater items: +Repeater items[1/2]: ```java Color Bedroom_Repeater_Color "Bedroom Repeater Color" {channel="hdpowerview:repeater:home:r16384:color"} @@ -259,16 +300,20 @@ Switch Bedroom_Repeater_BlinkingEnabled "Bedroom Repeater Blinking Enabled [%s]" Scene items: ```java +// generation 1/2 Switch Living_Room_Shades_Scene_Heart "Living Room Shades Scene Heart" (g_Shades_Scene_Trigger) {channel="hdpowerview:hub:home:scenes#22663"} + +// generation 3 +Switch Living_Room_Shades_Scene_Heart "Living Room Shades Scene Heart" (g_Shades_Scene_Trigger) {channel="hdpowerview:gateway:home:scenes#22663"} ``` -Scene Group items: +Scene Group items[1/2]: ```java Switch Children_Rooms_Shades_Up "Good Morning Children" {channel="hdpowerview:hub:home:sceneGroups#27119"} ``` -Automation items: +Automation items[1/2]: ```java Switch Automation_Children_Up_Sun "Children Up At Sunrise" {channel="hdpowerview:hub:home:automations#1262"} @@ -277,14 +322,15 @@ Switch Automation_Children_Up_Time "Children Up At 6:30" {channel="hdpowerview:h ### `demo.sitemap` File -```perl +```php Frame label="Living Room" { Switch item=Living_Room_Shades_Scene_Open Slider item=Living_Room_Shade_Position Switch item=Living_Room_Shade_Command mappings=[CALIBRATE="Calibrate"] Text item=Living_Room_Shade_SignalStrength - Text item=Living_Room_Shade_Battery_Voltage } + +// generation 1/2 only Frame label="Bedroom" { Colorpicker item=PowerViewRepeater_Color Switch item=PowerViewRepeater_Color diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/GatewayWebTargets.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/GatewayWebTargets.java new file mode 100644 index 0000000000000..1ee0b0bcf95f7 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/GatewayWebTargets.java @@ -0,0 +1,439 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal; + +import java.io.Closeable; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSession; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.sse.InboundSseEvent; +import javax.ws.rs.sse.SseEventSource; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets.Query; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Info; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Scene; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade; +import org.openhab.binding.hdpowerview.internal.dto.gen3.ShadeEvent; +import org.openhab.binding.hdpowerview.internal.dto.gen3.ShadePosition; +import org.openhab.binding.hdpowerview.internal.dto.requests.ShadeMotion; +import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; +import org.openhab.binding.hdpowerview.internal.handler.GatewayBridgeHandler; +import org.openhab.core.thing.Thing; +import org.osgi.service.jaxrs.client.SseEventSourceFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonParseException; + +/** + * JAX-RS targets for communicating with an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class GatewayWebTargets implements Closeable, HostnameVerifier { + + private static final String IDS = "ids"; + private static final int SLEEP_SECONDS = 360; + private static final Set HTTP_OK_CODES = Set.of(HttpStatus.OK_200, HttpStatus.NO_CONTENT_204); + + private final Logger logger = LoggerFactory.getLogger(GatewayWebTargets.class); + private final Gson jsonParser = new Gson(); + + private final String shades; + private final String scenes; + private final String sceneActivate; + private final String shadeMotion; + private final String shadePositions; + private final String shadeSingle; + private final String shadeStop; + private final String info; + private final String register; + private final String shadeEvents; + private final HttpClient httpClient; + private final ClientBuilder clientBuilder; + private final SseEventSourceFactory eventSourceFactory; + private final GatewayBridgeHandler hubHandler; + private final String ipAddress; + + private boolean registered; + private boolean closing; + + private @Nullable SseEventSource shadeEventSource; + private @Nullable ScheduledFuture sseQuietCheck; + + /** + * Initialize the web targets + * + * @param httpClient the HTTP client (the binding) + * @param ipAddress the IP address of the server (the hub) + */ + public GatewayWebTargets(GatewayBridgeHandler hubHandler, HttpClient httpClient, ClientBuilder clientBuilder, + SseEventSourceFactory eventSourceFactory, String ipAddress) { + this.ipAddress = ipAddress; + this.httpClient = httpClient; + this.clientBuilder = clientBuilder; + this.eventSourceFactory = eventSourceFactory; + this.hubHandler = hubHandler; + + String base = "http://" + ipAddress + "/"; + String home = base + "home/"; + shades = home + "shades"; + scenes = home + "scenes"; + sceneActivate = home + "scenes/%d/activate"; + shadeMotion = home + "shades/%d/motion"; + shadePositions = home + "shades/positions"; + shadeSingle = home + "shades/%d"; + shadeStop = home + "shades/stop"; + shadeEvents = home + "shades/events?sse=true"; + info = base + "gateway/info"; + + /* + * Hunter Douglas keeps a statistical count of systems (e.g. openHAB, Home Assistant, Amazon etc.) that are + * using their Generation 3 REST API to connect to their gateways. So we are asked to register with the gateway + * on startup. => So do not change the 'openhab.org' tag below !! + */ + register = home + "integration/openhab.org"; + } + + /** + * Issue a command to activate a scene. + * + * @param sceneId the scene to be activated. + * @throws HubProcessingException if any error occurs. + */ + public void activateScene(int sceneId) throws HubProcessingException { + invoke(HttpMethod.PUT, String.format(sceneActivate, sceneId), null, null); + } + + @Override + public void close() throws IOException { + closing = true; + sseClose(); + } + + /** + * Register the binding with the hub (if not already registered). + * + * @throws HubProcessingException if any error occurs. + */ + public boolean gatewayRegister() throws HubProcessingException { + if (!registered) { + invoke(HttpMethod.PUT, register, null, null); + registered = true; + } + return registered; + } + + /** + * Get hub properties. + * + * @return a map containing the hub properties. + * @throws HubProcessingException if any error occurs. + */ + public Map getInformation() throws HubProcessingException { + String json = invoke(HttpMethod.GET, info, null, null); + try { + Info result = jsonParser.fromJson(json, Info.class); + if (result == null) { + throw new HubProcessingException("getInformation(): missing response"); + } + return Map.of( // + Thing.PROPERTY_FIRMWARE_VERSION, result.getFwVersion(), // + Thing.PROPERTY_SERIAL_NUMBER, result.getSerialNumber()); + } catch (JsonParseException e) { + throw new HubProcessingException("getFirmwareVersions(): JsonParseException"); + } + } + + /** + * Get the list of scenes. + * + * @return the list of scenes. + * @throws HubProcessingException if any error occurs. + */ + public List getScenes() throws HubProcessingException { + String json = invoke(HttpMethod.GET, scenes, null, null); + try { + return List.of(jsonParser.fromJson(json, Scene[].class)); + } catch (JsonParseException e) { + throw new HubProcessingException("getScenes() JsonParseException"); + } + } + + /** + * Get the data for a single shade. + * + * @param shadeId the id of the shade to get. + * @return the shade. + * @throws HubProcessingException if any error occurs. + */ + public Shade getShade(int shadeId) throws HubProcessingException { + String json = invoke(HttpMethod.GET, String.format(shadeSingle, shadeId), null, null); + try { + Shade result = jsonParser.fromJson(json, Shade.class); + if (result == null) { + throw new HubProcessingException("getShade() missing response"); + } + return result; + } catch (JsonParseException e) { + throw new HubProcessingException("getShade() JsonParseException"); + } + } + + /** + * Get the list of shades. + * + * @return the list of shades. + * @throws HubProcessingException if any error occurs. + */ + public List getShades() throws HubProcessingException { + String json = invoke(HttpMethod.GET, shades, null, null); + try { + return List.of(jsonParser.fromJson(json, Shade[].class)); + } catch (JsonParseException e) { + throw new HubProcessingException("getShades() JsonParseException"); + } + } + + /** + * Invoke a call on the hub server to retrieve information or send a command. + * + * @param method GET or PUT. + * @param url the host URL to be called. + * @param query the HTTP query parameter. + * @param jsonCommand the request command content (as a JSON string). + * @return the response content (as a JSON string). + * @throws HubProcessingException if something goes wrong. + */ + protected synchronized String invoke(HttpMethod method, String url, @Nullable Query query, + @Nullable String jsonCommand) throws HubProcessingException { + if (logger.isTraceEnabled()) { + if (query != null) { + logger.trace("invoke() method:{}, url:{}, query:{}", method, url, query); + } else { + logger.trace("invoke() method:{}, url:{}", method, url); + } + if (jsonCommand != null) { + logger.trace("invoke() request JSON:{}", jsonCommand); + } + } + Request request = httpClient.newRequest(url).method(method).header("Connection", "close").accept("*/*"); + if (query != null) { + request.param(query.getKey(), query.getValue()); + } + if (jsonCommand != null) { + request.header(HttpHeader.CONTENT_TYPE, "application/json").content(new StringContentProvider(jsonCommand)); + } + ContentResponse response; + try { + response = request.send(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new HubProcessingException(String.format("%s: \"%s\"", e.getClass().getName(), e.getMessage())); + } catch (TimeoutException | ExecutionException e) { + throw new HubProcessingException(String.format("%s: \"%s\"", e.getClass().getName(), e.getMessage())); + } + int statusCode = response.getStatus(); + if (!HTTP_OK_CODES.contains(statusCode)) { + throw new HubProcessingException(String.format("HTTP %d error", statusCode)); + } + String jsonResponse = response.getContentAsString(); + if (logger.isTraceEnabled()) { + logger.trace("invoke() response JSON:{}", jsonResponse); + } + if (method == HttpMethod.GET && jsonResponse.isEmpty()) { + throw new HubProcessingException("Empty response entity"); + } + return jsonResponse; + } + + /** + * Issue a jog command to a shade. + * + * @param shadeId the shade to be jogged. + * @throws HubProcessingException if any error occurs. + */ + public void jogShade(int shadeId) throws HubProcessingException { + String json = jsonParser.toJson(new ShadeMotion(ShadeMotion.Type.JOG)); + invoke(HttpMethod.PUT, String.format(shadeMotion, shadeId), null, json); + } + + /** + * Issue a command to move a shade. + * + * @param shadeId the shade to be moved. + * @param shade DTO with the new position. + * @throws HubProcessingException if any error occurs. + */ + public void moveShade(int shadeId, Shade shade) throws HubProcessingException { + invoke(HttpMethod.PUT, shadePositions, Query.of(IDS, Integer.toString(shadeId)), jsonParser.toJson(shade)); + } + + /** + * Called when the SSE event channel has not received any events for a long time. This could mean that the event + * source socket has dropped. So restart the SSE connection. + */ + public void onSseQuiet() { + if (!closing) { + sseReOpen(); + } + } + + /** + * Handle SSE errors. For the time being just log them, because the framework should automatically recover itself. + * + * @param e the error that was thrown. + */ + private void onSseError(Throwable e) { + if (!closing) { + logger.debug("onSseShadeError() {}", e.getMessage(), e); + } + } + + /** + * Handle inbound shade SSE events. + * + * @param sseEvent the inbound event. + */ + private void onSSeEvent(InboundSseEvent sseEvent) { + if (closing) { + return; + } + ScheduledFuture task = sseQuietCheck; + if (task != null && !task.isCancelled()) { + task.cancel(true); + } + sseQuietCheck = hubHandler.getScheduler().schedule(this::onSseQuiet, SLEEP_SECONDS, TimeUnit.SECONDS); + if (sseEvent.isEmpty()) { + return; + } + String json = sseEvent.readData(); + if (json == null) { + return; + } + logger.trace("onSseShadeEvent() json:{}", json); + ShadeEvent shadeEvent = jsonParser.fromJson(json, ShadeEvent.class); + if (shadeEvent != null) { + ShadePosition positions = shadeEvent.getCurrentPositions(); + hubHandler + .onShadeEvent(new Shade().setId(shadeEvent.getId()).setShadePosition(positions).setPartialState()); + } + } + + /** + * Close the SSE links. + */ + private synchronized void sseClose() { + logger.debug("sseClose() called"); + ScheduledFuture task = sseQuietCheck; + if (task != null) { + task.cancel(true); + sseQuietCheck = null; + } + SseEventSource source; + source = this.shadeEventSource; + if (source != null) { + source.close(); + this.shadeEventSource = null; + } + } + + /** + * Open the SSE links. + */ + public synchronized void sseOpen() { + sseClose(); + + logger.debug("sseOpen() called"); + Client client = clientBuilder.sslContext(httpClient.getSslContextFactory().getSslContext()) + .hostnameVerifier(null).hostnameVerifier(this).readTimeout(0, TimeUnit.SECONDS).build(); + + try { + // open SSE channel for shades + SseEventSource shadeEventSource = eventSourceFactory.newSource(client.target(shadeEvents)); + shadeEventSource.register(this::onSSeEvent, this::onSseError); + shadeEventSource.open(); + this.shadeEventSource = shadeEventSource; + } catch (Exception e) { + // SSE documentation does not say what exceptions may be thrown, so catch everything + logger.warn("sseOpen() {}", e.getMessage(), e); + } + } + + /** + * Reopen the SSE links. If the event source already exists, try first to simply close and re-open it, but if that + * fails, then completely destroy and re-create it. + */ + private synchronized void sseReOpen() { + logger.debug("sseReOpen() called"); + SseEventSource shadeEventSource = this.shadeEventSource; + if (shadeEventSource != null) { + try { + if (shadeEventSource.isOpen()) { + shadeEventSource.close(); + } + if (!shadeEventSource.isOpen()) { + shadeEventSource.open(); + } + return; + } catch (Exception e) { + // SSE documentation does not say what exceptions may be thrown, so catch everything + logger.warn("sseReOpen() {}", e.getMessage(), e); + } + } + sseOpen(); + } + + /** + * Issue a stop command to a shade. + * + * @param shadeId the shade to be stopped. + * @throws HubProcessingException if any error occurs. + */ + public void stopShade(int shadeId) throws HubProcessingException { + invoke(HttpMethod.PUT, shadeStop, Query.of(IDS, Integer.valueOf(shadeId).toString()), null); + } + + /** + * HostnameVerifier method implementation that validates the host name when opening SSE connections. + * + * @param hostName the host name to be verified. + * @param sslSession (not used). + * @return true if the host name matches our own. + */ + @Override + public boolean verify(@Nullable String hostName, @Nullable SSLSession sslSession) { + return this.ipAddress.equals(hostName); + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java index 31215c625f858..7436cd05005a1 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; @@ -74,6 +75,17 @@ public class HDPowerViewBindingConstants { public static final List NETBIOS_NAMES = Arrays.asList("PDBU-Hub3.0", "PowerView-Hub"); + public static final Pattern VALID_IP_V4_ADDRESS = Pattern + .compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b"); + + // generation 3 + public static final ThingTypeUID THING_TYPE_GATEWAY = new ThingTypeUID(BINDING_ID, "gateway"); + public static final ThingTypeUID THING_TYPE_SHADE3 = new ThingTypeUID(BINDING_ID, "shade3"); + public static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_HUB, THING_TYPE_SHADE, - THING_TYPE_REPEATER); + THING_TYPE_REPEATER, THING_TYPE_GATEWAY, THING_TYPE_SHADE3); + + public static final String PROPERTY_NAME = "name"; + public static final String PROPERTY_POWER_TYPE = "powerType"; + public static final String PROPERTY_BLE_NAME = "bleName"; } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewHandlerFactory.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewHandlerFactory.java index 43770e8c53a7d..47359a89a9d7d 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewHandlerFactory.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewHandlerFactory.java @@ -14,13 +14,18 @@ import java.util.Hashtable; +import javax.ws.rs.client.ClientBuilder; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.hdpowerview.internal.discovery.HDPowerViewDeviceDiscoveryService; +import org.openhab.binding.hdpowerview.internal.discovery.ShadeDiscoveryService; +import org.openhab.binding.hdpowerview.internal.handler.GatewayBridgeHandler; import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewHubHandler; import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewRepeaterHandler; import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewShadeHandler; +import org.openhab.binding.hdpowerview.internal.handler.ShadeThingHandler; import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.i18n.LocaleProvider; import org.openhab.core.i18n.TranslationProvider; @@ -35,6 +40,7 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.jaxrs.client.SseEventSourceFactory; /** * The {@link HDPowerViewHandlerFactory} is responsible for creating things and thing @@ -48,15 +54,20 @@ public class HDPowerViewHandlerFactory extends BaseThingHandlerFactory { private final HttpClient httpClient; private final HDPowerViewTranslationProvider translationProvider; + private final ClientBuilder clientBuilder; + private final SseEventSourceFactory eventSourceFactory; @Activate public HDPowerViewHandlerFactory(@Reference HttpClientFactory httpClientFactory, final @Reference TranslationProvider i18nProvider, final @Reference LocaleProvider localeProvider, + final @Reference ClientBuilder clientBuilder, final @Reference SseEventSourceFactory eventSourceFactory, ComponentContext componentContext) { super.activate(componentContext); this.httpClient = httpClientFactory.getCommonHttpClient(); this.translationProvider = new HDPowerViewTranslationProvider(getBundleContext().getBundle(), i18nProvider, localeProvider); + this.clientBuilder = clientBuilder; + this.eventSourceFactory = eventSourceFactory; } @Override @@ -67,8 +78,14 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { @Override protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (HDPowerViewBindingConstants.THING_TYPE_HUB.equals(thingTypeUID)) { + if (HDPowerViewBindingConstants.THING_TYPE_GATEWAY.equals(thingTypeUID)) { + GatewayBridgeHandler handler = new GatewayBridgeHandler((Bridge) thing, httpClient, translationProvider, + clientBuilder, eventSourceFactory); + registerService(new ShadeDiscoveryService(handler)); + return handler; + } else if (HDPowerViewBindingConstants.THING_TYPE_SHADE3.equals(thingTypeUID)) { + return new ShadeThingHandler(thing); + } else if (HDPowerViewBindingConstants.THING_TYPE_HUB.equals(thingTypeUID)) { HDPowerViewHubHandler handler = new HDPowerViewHubHandler((Bridge) thing, httpClient, translationProvider); registerService(new HDPowerViewDeviceDiscoveryService(handler)); return handler; @@ -77,7 +94,6 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } else if (HDPowerViewBindingConstants.THING_TYPE_REPEATER.equals(thingTypeUID)) { return new HDPowerViewRepeaterHandler(thing); } - return null; } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java index 4ce607b8dbe36..1b0a78d5d60d8 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java @@ -102,9 +102,9 @@ public class HDPowerViewWebTargets { private final HttpClient httpClient; /** - * private helper class for passing http url query parameters + * helper class for passing http url query parameters */ - private static class Query { + public static class Query { private final String key; private final String value; @@ -425,7 +425,7 @@ public ScheduledEvents getScheduledEvents() /** * Enables or disables a scheduled event in the hub. - * + * * @param scheduledEventId id of the scheduled event to be enabled or disabled * @param enable true to enable scheduled event, false to disable * @throws HubInvalidResponseException if response is invalid @@ -527,7 +527,7 @@ public RepeaterData identifyRepeater(int repeaterId) /** * Enables or disables blinking for a repeater - * + * * @param repeaterId id of the repeater for which to be enable or disable blinking * @param enable true to enable blinking, false to disable * @return RepeaterData class instance diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/console/HDPowerViewCommandExtension.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/console/HDPowerViewCommandExtension.java index 28c62546425e6..3a257db258217 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/console/HDPowerViewCommandExtension.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/console/HDPowerViewCommandExtension.java @@ -17,11 +17,14 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hdpowerview.internal.GatewayWebTargets; import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants; import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets; import org.openhab.binding.hdpowerview.internal.dto.ShadeData; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade; import org.openhab.binding.hdpowerview.internal.dto.responses.RepeaterData; import org.openhab.binding.hdpowerview.internal.exceptions.HubException; +import org.openhab.binding.hdpowerview.internal.handler.GatewayBridgeHandler; import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewHubHandler; import org.openhab.core.io.console.Console; import org.openhab.core.io.console.ConsoleCommandCompleter; @@ -65,7 +68,7 @@ public void execute(String[] args, Console console) { for (Thing thing : thingRegistry.getAll()) { ThingHandler thingHandler = thing.getHandler(); if (thingHandler instanceof HDPowerViewHubHandler) { - console.println("API bridge: " + thing.getLabel()); + console.println("Generation 1/2 API hub: " + thing.getLabel()); HDPowerViewWebTargets webTargets = ((HDPowerViewHubHandler) thingHandler).getWebTargets(); try { @@ -87,6 +90,21 @@ public void execute(String[] args, Console console) { } catch (HubException e) { console.println("Error retrieving ID's: " + e.getMessage()); } + } else if (thingHandler instanceof GatewayBridgeHandler) { + console.println("Generation 3 API gateway: " + thing.getLabel()); + GatewayWebTargets webTargets = ((GatewayBridgeHandler) thingHandler).getWebTargets(); + + try { + List shades = webTargets.getShades(); + if (!shades.isEmpty()) { + console.println(" - Shades:"); + for (Shade shade : shades) { + console.println(" - ID: " + shade.getId() + " (" + shade.getName() + ")"); + } + } + } catch (HubException e) { + console.println("Error retrieving ID's: " + e.getMessage()); + } } } } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java index 35b233d0bad0b..70dd23308813a 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java @@ -129,7 +129,7 @@ public static class Type extends Base { protected Type() { } - protected Type(int type) { + public Type(int type) { intValue = type; } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/GatewayDiscoveryParticipant.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/GatewayDiscoveryParticipant.java new file mode 100644 index 0000000000000..a79d1559904bf --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/GatewayDiscoveryParticipant.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.discovery; + +import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*; + +import java.util.Set; + +import javax.jmdns.ServiceInfo; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hdpowerview.internal.config.HDPowerViewHubConfiguration; +import org.openhab.core.config.discovery.DiscoveryResult; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Discovers HD PowerView Generation 3 Gateways by means of mDNS. + * + * @author Andrew Fiddian-Green - Initial contribution. + */ +@NonNullByDefault +@Component +public class GatewayDiscoveryParticipant implements MDNSDiscoveryParticipant { + + private static final String LABEL_KEY = "discovery.gateway.label"; + + private final Logger logger = LoggerFactory.getLogger(GatewayDiscoveryParticipant.class); + + @Override + public @Nullable DiscoveryResult createResult(ServiceInfo service) { + for (String host : service.getHostAddresses()) { + if (VALID_IP_V4_ADDRESS.matcher(host).matches()) { + ThingUID thingUID = new ThingUID(THING_TYPE_GATEWAY, host.replace('.', '_')); + DiscoveryResult hub = DiscoveryResultBuilder.create(thingUID) + .withProperty(HDPowerViewHubConfiguration.HOST, host) + .withRepresentationProperty(HDPowerViewHubConfiguration.HOST) + .withLabel(String.format("@text/%s [\"%s\"]", LABEL_KEY, host)).build(); + logger.debug("mDNS discovered Gen 3 gateway on host '{}'", host); + return hub; + } + } + return null; + } + + @Override + public String getServiceType() { + return "_powerview-g3._tcp.local."; + } + + @Override + public Set getSupportedThingTypeUIDs() { + return Set.of(THING_TYPE_GATEWAY); + } + + @Override + public @Nullable ThingUID getThingUID(ServiceInfo service) { + for (String host : service.getHostAddresses()) { + if (VALID_IP_V4_ADDRESS.matcher(host).matches()) { + return new ThingUID(THING_TYPE_GATEWAY, host.replace('.', '_')); + } + } + return null; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java index 156d70492c4b4..c8c1b83128eb9 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java @@ -55,7 +55,7 @@ public class HDPowerViewDeviceDiscoveryService extends AbstractDiscoveryService private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase(); public HDPowerViewDeviceDiscoveryService(HDPowerViewHubHandler hub) { - super(Collections.singleton(HDPowerViewBindingConstants.THING_TYPE_SHADE), 600, true); + super(Collections.singleton(HDPowerViewBindingConstants.THING_TYPE_SHADE), 60, true); this.hub = hub; this.scanner = createScanner(); } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryParticipant.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryParticipant.java index 2c95c33423e40..a4c98977e0d4f 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryParticipant.java @@ -16,7 +16,6 @@ import java.util.Collections; import java.util.Set; -import java.util.regex.Pattern; import javax.jmdns.ServiceInfo; @@ -41,10 +40,9 @@ @Component public class HDPowerViewHubDiscoveryParticipant implements MDNSDiscoveryParticipant { - private final Logger logger = LoggerFactory.getLogger(HDPowerViewHubDiscoveryParticipant.class); + private static final String LABEL_KEY = "discovery.hub.label"; - private static final Pattern VALID_IP_V4_ADDRESS = Pattern - .compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b"); + private final Logger logger = LoggerFactory.getLogger(HDPowerViewHubDiscoveryParticipant.class); @Override public Set getSupportedThingTypeUIDs() { @@ -64,8 +62,8 @@ public String getServiceType() { DiscoveryResult hub = DiscoveryResultBuilder.create(thingUID) .withProperty(HDPowerViewHubConfiguration.HOST, host) .withRepresentationProperty(HDPowerViewHubConfiguration.HOST) - .withLabel("PowerView Hub (" + host + ")").build(); - logger.debug("mDNS discovered hub on host '{}'", host); + .withLabel(String.format("@text/%s [\"%s\"]", LABEL_KEY, host)).build(); + logger.debug("mDNS discovered Gen 1/2 hub on host '{}'", host); return hub; } } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java index d6edb949a880b..6defbf71a93d8 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java @@ -48,7 +48,7 @@ public class HDPowerViewHubDiscoveryService extends AbstractDiscoveryService { private @Nullable ScheduledFuture backgroundFuture; public HDPowerViewHubDiscoveryService() { - super(Collections.singleton(THING_TYPE_HUB), 600, true); + super(Collections.singleton(THING_TYPE_HUB), 60, true); scanner = createScanner(); } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/ShadeDiscoveryService.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/ShadeDiscoveryService.java new file mode 100644 index 0000000000000..80ae30968d610 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/ShadeDiscoveryService.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.discovery; + +import java.util.Collections; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hdpowerview.internal.GatewayWebTargets; +import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants; +import org.openhab.binding.hdpowerview.internal.config.HDPowerViewShadeConfiguration; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade; +import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; +import org.openhab.binding.hdpowerview.internal.handler.GatewayBridgeHandler; +import org.openhab.core.config.discovery.AbstractDiscoveryService; +import org.openhab.core.config.discovery.DiscoveryResultBuilder; +import org.openhab.core.thing.ThingUID; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Discovers shades in an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class ShadeDiscoveryService extends AbstractDiscoveryService { + + private final Logger logger = LoggerFactory.getLogger(ShadeDiscoveryService.class); + private final GatewayBridgeHandler hub; + private final Runnable scanner; + private @Nullable ScheduledFuture backgroundFuture; + + public ShadeDiscoveryService(GatewayBridgeHandler hub) { + super(Collections.singleton(HDPowerViewBindingConstants.THING_TYPE_SHADE3), 60, true); + this.hub = hub; + this.scanner = createScanner(); + } + + @Override + protected void startScan() { + scheduler.execute(scanner); + } + + @Override + protected void startBackgroundDiscovery() { + ScheduledFuture backgroundFuture = this.backgroundFuture; + if (backgroundFuture != null && !backgroundFuture.isDone()) { + backgroundFuture.cancel(true); + } + this.backgroundFuture = scheduler.scheduleWithFixedDelay(scanner, 0, 60, TimeUnit.SECONDS); + } + + @Override + protected void stopBackgroundDiscovery() { + ScheduledFuture backgroundFuture = this.backgroundFuture; + if (backgroundFuture != null && !backgroundFuture.isDone()) { + backgroundFuture.cancel(true); + this.backgroundFuture = null; + } + super.stopBackgroundDiscovery(); + } + + private Runnable createScanner() { + return () -> { + try { + GatewayWebTargets webTargets = hub.getWebTargets(); + discoverShades(webTargets); + } catch (HubProcessingException e) { + logger.warn("Unexpected exception:{}, message:{}", e.getClass().getSimpleName(), e.getMessage()); + } catch (IllegalStateException e) { + // ignore + } + stopScan(); + }; + } + + private void discoverShades(GatewayWebTargets webTargets) throws HubProcessingException { + ThingUID bridgeUid = hub.getThing().getUID(); + for (Shade shade : webTargets.getShades()) { + if (shade.getId() == 0) { + continue; + } + + String id = Integer.toString(shade.getId()); + ThingUID thingUID = new ThingUID(HDPowerViewBindingConstants.THING_TYPE_SHADE3, bridgeUid, id); + + DiscoveryResultBuilder builder = DiscoveryResultBuilder.create(thingUID).withLabel(shade.getName()) + .withBridge(bridgeUid).withProperty(HDPowerViewShadeConfiguration.ID, id) + .withRepresentationProperty(HDPowerViewShadeConfiguration.ID); + String type = shade.getTypeString(); + if (type != null) { + builder.withProperty(HDPowerViewBindingConstants.PROPERTY_SHADE_TYPE, type); + } + logger.debug("Hub discovered shade '{}'", id); + thingDiscovered(builder.build()); + } + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadePosition.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadePosition.java index 381462af9a858..1c536dea8570e 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadePosition.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadePosition.java @@ -75,7 +75,8 @@ public State getState(Capabilities shadeCapabilities, CoordinateSystem posKindCo * @param posKindCoords the actuator class (coordinate system) whose state is to be changed. * @param percent the new position value. */ - private void setPosition1(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) { + private void setPosition1(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percentArg) { + int percent = percentArg; switch (posKindCoords) { case PRIMARY_POSITION: /* @@ -202,7 +203,8 @@ private State getPosition1(Capabilities shadeCapabilities, CoordinateSystem posK * @param posKindCoords the actuator class (coordinate system) whose state is to be changed. * @param percent the new position value. */ - private void setPosition2(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) { + private void setPosition2(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percentArg) { + int percent = percentArg; switch (posKindCoords) { case PRIMARY_POSITION: /* diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Info.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Info.java new file mode 100644 index 0000000000000..99a8210a22a77 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Info.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * DTO for the Generation 3 Gateway information. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class Info { + private @NonNullByDefault({}) String fwVersion; + private @NonNullByDefault({}) String serialNumber; + + public String getFwVersion() { + return fwVersion; + } + + public String getSerialNumber() { + return serialNumber; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/PowerType.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/PowerType.java new file mode 100644 index 0000000000000..62a85c4a697c9 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/PowerType.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +/** + * Enum for Generation 3 shade power types. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +public enum PowerType { + BATTERY, + HARDWIRED, + RECHARGEABLE; +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Scene.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Scene.java new file mode 100644 index 0000000000000..9b884e927ca1a --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Scene.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * DTO for a scene as returned by an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution. + */ +@NonNullByDefault +public class Scene { + private int id; + private @NonNullByDefault({}) String name; + private @NonNullByDefault({}) String ptName; + private @NonNullByDefault({}) String color; + private @NonNullByDefault({}) String icon; + private @NonNullByDefault({}) List roomIds; + + public String getColor() { + return color; + } + + public String getIcon() { + return icon; + } + + public int getId() { + return id; + } + + public String getName() { + return String.join(" ", new String(Base64.getDecoder().decode(name), StandardCharsets.UTF_8), ptName); + } + + public String getPtName() { + return ptName; + } + + public List getRoomIds() { + List roomIds = this.roomIds; + return roomIds != null ? roomIds : List.of(); + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/SceneEvent.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/SceneEvent.java new file mode 100644 index 0000000000000..22947d059fd68 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/SceneEvent.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * DTO for scene SSE event object as supplied an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class SceneEvent { + private int id; + private @NonNullByDefault({}) Scene scene; + + public int getId() { + return id; + } + + public Scene getScene() { + return scene; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Shade.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Shade.java new file mode 100644 index 0000000000000..9552eea959cb4 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/Shade.java @@ -0,0 +1,160 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem; +import org.openhab.binding.hdpowerview.internal.dto.Firmware; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.unit.Units; +import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; + +/** + * DTO for a shade as returned by an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class Shade { + private @Nullable Integer id; + private @Nullable Integer type; + private @Nullable String name; + private @Nullable @SuppressWarnings("unused") String ptName; + private @Nullable Integer capabilities; + private @Nullable Integer powerType; + private @Nullable Integer batteryStatus; + private @Nullable Integer signalStrength; + private @Nullable String bleName; + private @Nullable Firmware firmware; + private @Nullable ShadePosition positions; + + private transient boolean partialState; + + public State getBatteryLevel() { + Integer batteryStatus = this.batteryStatus; + return batteryStatus == null ? UnDefType.UNDEF + : new DecimalType(Math.max(0, Math.min(100, (100 * batteryStatus) / 3))); + } + + public @Nullable String getBleName() { + return bleName; + } + + public @Nullable Integer getCapabilities() { + return capabilities; + } + + public @Nullable String getCapabilitieString() { + Integer capabilities = this.capabilities; + return capabilities == null ? null : Integer.toString(capabilities); + } + + public @Nullable String getFirmware() { + Firmware firmware = this.firmware; + return firmware == null ? null + : String.format("%d.%d.%d", firmware.revision, firmware.subRevision, firmware.build); + } + + public int getId() { + Integer id = this.id; + return id != null ? id.intValue() : 0; + } + + public State getLowBattery() { + Integer batteryStatus = this.batteryStatus; + return batteryStatus == null ? UnDefType.UNDEF : OnOffType.from(batteryStatus == 0); + } + + public String getName() { + return new String(Base64.getDecoder().decode(name), StandardCharsets.UTF_8); + } + + public State getPosition(CoordinateSystem posKindCoords) { + ShadePosition positions = this.positions; + return positions == null ? UnDefType.UNDEF : positions.getState(posKindCoords); + } + + public PowerType getPowerType() { + Integer powerType = this.powerType; + return PowerType.values()[powerType != null ? powerType.intValue() : 0]; + } + + public @Nullable ShadePosition getShadePositions() { + return positions; + } + + public State getSignalStrength() { + Integer signalStrength = this.signalStrength; + return signalStrength != null ? new QuantityType<>(signalStrength, Units.DECIBEL_MILLIWATTS) : UnDefType.UNDEF; + } + + public @Nullable Integer getType() { + return type; + } + + public @Nullable String getTypeString() { + Integer type = this.type; + return type == null ? null : Integer.toString(type); + } + + public boolean hasFullState() { + return !partialState; + } + + public boolean isMainsPowered() { + return getPowerType() == PowerType.HARDWIRED; + } + + public Shade setCapabilities(int capabilities) { + this.capabilities = capabilities; + return this; + } + + public Shade setId(int id) { + this.id = id; + return this; + } + + public Shade setPartialState() { + this.partialState = true; + return this; + } + + public Shade setPosition(CoordinateSystem coordinates, PercentType percent) { + ShadePosition positions = this.positions; + if (positions == null) { + positions = new ShadePosition(); + this.positions = positions; + } + positions.setPosition(coordinates, percent); + return this; + } + + public Shade setShadePosition(ShadePosition position) { + this.positions = position; + return this; + } + + public Shade setType(int type) { + this.type = type; + return this; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/ShadeEvent.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/ShadeEvent.java new file mode 100644 index 0000000000000..f4c66f49c4e8c --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/ShadeEvent.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * DTO for a shade SSE event object as supplied an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class ShadeEvent { + private int id; + private @NonNullByDefault({}) ShadePosition currentPositions; + + public ShadePosition getCurrentPositions() { + return currentPositions; + } + + public int getId() { + return id; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/ShadePosition.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/ShadePosition.java new file mode 100644 index 0000000000000..cc838d75ef518 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/gen3/ShadePosition.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.dto.gen3; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.math.RoundingMode; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; + +/** + * DTO for the position of a shade as returned by an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class ShadePosition { + private static final MathContext MATH_CONTEXT = new MathContext(4, RoundingMode.HALF_UP); + + private @NonNullByDefault({}) Double primary; + private @NonNullByDefault({}) Double secondary; + private @NonNullByDefault({}) Double tilt; + + public State getState(CoordinateSystem posKindCoords) { + Double value; + switch (posKindCoords) { + case PRIMARY_POSITION: + value = primary; + break; + case SECONDARY_POSITION: + value = secondary; + break; + case VANE_TILT_POSITION: + value = tilt; + break; + default: + value = null; + } + return value != null ? new PercentType(new BigDecimal(value * 100f, MATH_CONTEXT)) : UnDefType.UNDEF; + } + + /** + * Set a new position value for this object based on the given coordinates, and the given new value. + * + * @param coordinates which of the position fields shall be set. + * @param percent the new value in percent. + * @return this object. + */ + public ShadePosition setPosition(CoordinateSystem coordinates, PercentType percent) { + Double value = percent.doubleValue() / 100f; + switch (coordinates) { + case PRIMARY_POSITION: + primary = value; + break; + case SECONDARY_POSITION: + secondary = value; + break; + case VANE_TILT_POSITION: + tilt = value; + break; + default: + } + return this; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java index 3bc43abab6fa1..901cf6a7fc67c 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java @@ -20,7 +20,7 @@ * @author Jacob Laursen - Initial contribution */ @NonNullByDefault -class ShadeMotion { +public class ShadeMotion { public enum Type { STOP("stop"), diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/GatewayBridgeHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/GatewayBridgeHandler.java new file mode 100644 index 0000000000000..b8c01af68f497 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/GatewayBridgeHandler.java @@ -0,0 +1,321 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.handler; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.ws.rs.client.ClientBuilder; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.hdpowerview.internal.GatewayWebTargets; +import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants; +import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider; +import org.openhab.binding.hdpowerview.internal.config.HDPowerViewHubConfiguration; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Scene; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade; +import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; +import org.openhab.core.library.CoreItemFactory; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelGroupUID; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseBridgeHandler; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.thing.type.AutoUpdatePolicy; +import org.openhab.core.thing.type.ChannelTypeUID; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.osgi.service.jaxrs.client.SseEventSourceFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Bridge handler for an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class GatewayBridgeHandler extends BaseBridgeHandler { + + private final Logger logger = LoggerFactory.getLogger(GatewayBridgeHandler.class); + private final String channelTypeId = HDPowerViewBindingConstants.CHANNELTYPE_SCENE_ACTIVATE; + private final String channelGroupId = HDPowerViewBindingConstants.CHANNEL_GROUP_SCENES; + + private final HttpClient httpClient; + private final HDPowerViewTranslationProvider translationProvider; + private final ClientBuilder clientBuilder; + private final SseEventSourceFactory eventSourceFactory; + + private @Nullable GatewayWebTargets webTargets; + private @Nullable ScheduledFuture refreshTask; + + private boolean scenesLoaded; + private boolean propertiesLoaded; + private boolean disposing; + + public GatewayBridgeHandler(Bridge bridge, HttpClient httpClient, + HDPowerViewTranslationProvider translationProvider, ClientBuilder clientBuilder, + SseEventSourceFactory eventSourceFactory) { + super(bridge); + this.httpClient = httpClient; + this.translationProvider = translationProvider; + this.clientBuilder = clientBuilder; + this.eventSourceFactory = eventSourceFactory; + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof ShadeThingHandler) { + refreshShade(((ShadeThingHandler) childHandler).getShadeId()); + } + } + + @Override + public void dispose() { + disposing = true; + ScheduledFuture future = this.refreshTask; + if (future != null) { + future.cancel(true); + } + this.refreshTask = null; + + GatewayWebTargets webTargets = this.webTargets; + if (webTargets != null) { + scheduler.submit(() -> disposeWebTargets(webTargets)); + this.webTargets = null; + } + } + + private void disposeWebTargets(GatewayWebTargets webTargets) { + try { + webTargets.close(); + } catch (IOException e) { + } + } + + /** + * Refresh the state of all things. Normally the thing's position state is updated by SSE. However we must do a + * refresh once on start up in order to get the initial state. Also the other properties (battery, signal strength + * etc.) are not updated by SSE. Furthermore we need to do periodic refreshes just in case the SSE connection may + * have been lost. + */ + private void doRefresh() { + logger.debug("doRefresh()"); + try { + if (getWebTargets().gatewayRegister()) { + updateStatus(ThingStatus.ONLINE); + getWebTargets().sseOpen(); + refreshProperties(); + refreshShades(); + refreshScenes(); + } + } catch (IllegalStateException | HubProcessingException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + logger.debug("doRefresh() exception:{}, message:{}", e.getClass().getSimpleName(), e.getMessage(), e); + } + } + + public ScheduledExecutorService getScheduler() { + return scheduler; + } + + /** + * Getter for the list of all child shade thing handlers. + * + * @return the list of shade handlers. + * @throws IllegalStateException if the bridge is not properly initialized. + */ + private List getShadeThingHandlers() throws IllegalStateException { + logger.debug("getShadeThingHandlers()"); + return getThing().getThings().stream().map(Thing::getHandler).filter(ShadeThingHandler.class::isInstance) + .map(ShadeThingHandler.class::cast).collect(Collectors.toList()); + } + + /** + * Getter for the webTargets. + * + * @return the webTargets. + * @throws IllegalStateException if webTargets is not initialized. + */ + public GatewayWebTargets getWebTargets() throws IllegalStateException { + GatewayWebTargets webTargets = this.webTargets; + if (webTargets != null) { + return webTargets; + } + throw new IllegalStateException("WebTargets not initialized."); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (RefreshType.REFRESH == command) { + scheduler.submit(() -> doRefresh()); + return; + } + Channel channel = getThing().getChannel(channelUID.getId()); + if (channel == null) { + return; + } + ChannelTypeUID channelTypeUID = channel.getChannelTypeUID(); + if (channelTypeUID == null) { + return; + } + if (channelTypeId.equals(channelTypeUID.getId()) && OnOffType.ON == command) { + try { + getWebTargets().activateScene(Integer.parseInt(channelUID.getIdWithoutGroup())); + } catch (HubProcessingException | IllegalStateException e) { + logger.warn("handleCommand() exception:{}, message:{}", e.getClass().getSimpleName(), e.getMessage()); + } + } + } + + @Override + public void initialize() { + HDPowerViewHubConfiguration config = getConfigAs(HDPowerViewHubConfiguration.class); + String host = config.host; + + if (host == null || host.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error.no-host-address"); + return; + } + + webTargets = new GatewayWebTargets(this, httpClient, clientBuilder, eventSourceFactory, host); + scenesLoaded = false; + propertiesLoaded = false; + disposing = false; + + /* + * Normally the thing's position state is updated by SSE. However we must do a refresh once on start up in order + * to get the initial state. Also the other properties (battery, signal strength etc.) are not updated by SSE. + * Furthermore we need to do periodic refreshes just in case the SSE connection may have been lost. So we + * schedule the refresh at the 'hardRefresh' interval. + */ + refreshTask = scheduler.scheduleWithFixedDelay(() -> doRefresh(), 0, config.hardRefresh, TimeUnit.MINUTES); + updateStatus(ThingStatus.UNKNOWN); + } + + /** + * Method that is called when a scene changes state. + * + * @param scene the one that changed. + */ + public void onSceneEvent(Scene scene) { + // TODO perhaps we should trigger an OH core event here ?? + } + + /** + * Method that is called when a shade changes state. + * + * @param shade the one that changed. + */ + public void onShadeEvent(Shade shade) { + if (disposing) { + return; + } + try { + for (ShadeThingHandler handler : getShadeThingHandlers()) { + if (handler.notify(shade)) { + break; + } + } + } catch (IllegalStateException e) { + logger.warn("onShadeEvent() exception:{}, message:{}", e.getClass().getSimpleName(), e.getMessage(), e); + } + } + + private void refreshProperties() throws HubProcessingException, IllegalStateException { + if (propertiesLoaded || disposing) { + return; + } + logger.debug("refreshProperties()"); + thing.setProperties(getWebTargets().getInformation()); + propertiesLoaded = true; + } + + /** + * Create the dynamic list of scene channels. + * + * @throws HubProcessingException if the web target connection caused an error. + * @throws IllegalStateException if this handler is in an illegal state. + */ + private void refreshScenes() throws HubProcessingException, IllegalStateException { + if (scenesLoaded || disposing) { + return; + } + logger.debug("refreshScenes()"); + ChannelTypeUID typeUID = new ChannelTypeUID(HDPowerViewBindingConstants.BINDING_ID, channelTypeId); + ChannelGroupUID groupUID = new ChannelGroupUID(thing.getUID(), channelGroupId); + List channels = new ArrayList<>(); + for (Scene scene : getWebTargets().getScenes()) { + ChannelUID channelUID = new ChannelUID(groupUID, Integer.toString(scene.getId())); + String name = scene.getName(); + String description = translationProvider.getText("dynamic-channel.scene-activate.description", name); + channels.add(ChannelBuilder.create(channelUID, CoreItemFactory.SWITCH).withType(typeUID).withLabel(name) + .withDescription(description).withAutoUpdatePolicy(AutoUpdatePolicy.VETO).build()); + } + updateThing(editThing().withChannels(channels).build()); + scenesLoaded = true; + } + + /** + * Refresh a single shade. + * + * @param shadeId the id of the shade to be refreshed. + */ + private void refreshShade(int shadeId) { + try { + Shade shade = getWebTargets().getShade(shadeId); + for (ShadeThingHandler handler : getShadeThingHandlers()) { + if (handler.notify(shade)) { + break; + } + } + } catch (HubProcessingException | IllegalStateException e) { + logger.warn("refreshShade() exception:{}, message:{}", e.getClass().getSimpleName(), e.getMessage(), e); + } + } + + /** + * Get the full list of shades data and notify each of the thing handlers. + * + * @throws HubProcessingException if the web target connection caused an error. + * @throws IllegalStateException if this handler is in an illegal state. + */ + private void refreshShades() throws HubProcessingException, IllegalStateException { + if (disposing) { + return; + } + logger.debug("refreshShades()"); + List handlers = getShadeThingHandlers(); + for (Shade shade : getWebTargets().getShades()) { + for (ShadeThingHandler handler : handlers) { + if (handler.notify(shade)) { + break; + } + } + } + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/ShadeThingHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/ShadeThingHandler.java new file mode 100644 index 0000000000000..a106c52d99cfd --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/ShadeThingHandler.java @@ -0,0 +1,334 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.handler; + +import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*; +import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.StringJoiner; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hdpowerview.internal.GatewayWebTargets; +import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants; +import org.openhab.binding.hdpowerview.internal.config.HDPowerViewShadeConfiguration; +import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase; +import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities; +import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Type; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade; +import org.openhab.binding.hdpowerview.internal.dto.gen3.ShadePosition; +import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.library.types.StopMoveType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.types.UpDownType; +import org.openhab.core.thing.Bridge; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.thing.binding.BridgeHandler; +import org.openhab.core.types.Command; +import org.openhab.core.types.RefreshType; +import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Thing handler for shades in an HD PowerView Generation 3 Gateway. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class ShadeThingHandler extends BaseThingHandler { + + private static final String INVALID_CHANNEL = "invalid channel"; + private static final String INVALID_COMMAND = "invalid command"; + + private static final String COMMAND_IDENTIFY = "IDENTIFY"; + + private static final ShadeCapabilitiesDatabase DB = new ShadeCapabilitiesDatabase(); + + private final Logger logger = LoggerFactory.getLogger(ShadeThingHandler.class); + + private int shadeId; + private boolean isInitialized; + private @Nullable Capabilities capabilities; + + public ShadeThingHandler(Thing thing) { + super(thing); + } + + /** + * Getter for the hub handler. + * + * @return the hub handler. + * @throws IllegalStateException if the bridge or its handler are not initialized. + */ + private GatewayBridgeHandler getBridgeHandler() throws IllegalStateException { + Bridge bridge = this.getBridge(); + if (bridge == null) { + throw new IllegalStateException("Bridge not initialised."); + } + BridgeHandler handler = bridge.getHandler(); + if (!(handler instanceof GatewayBridgeHandler)) { + throw new IllegalStateException("Bridge handler not initialised."); + } + return (GatewayBridgeHandler) handler; + } + + public int getShadeId() { + return shadeId; + } + + private Type getType(Shade shade) { + Integer type = shade.getType(); + return type != null ? DB.getType(type) : new ShadeCapabilitiesDatabase.Type(0); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (RefreshType.REFRESH == command) { + getBridgeHandler().handleCommand(channelUID, command); + return; + } + + GatewayWebTargets webTargets = getBridgeHandler().getWebTargets(); + ShadePosition position = new ShadePosition(); + try { + switch (channelUID.getId()) { + case CHANNEL_SHADE_POSITION: + if (command instanceof PercentType) { + position.setPosition(PRIMARY_POSITION, ((PercentType) command)); + webTargets.moveShade(shadeId, new Shade().setShadePosition(position)); + break; + } else if (command instanceof UpDownType) { + position.setPosition(PRIMARY_POSITION, + (UpDownType.UP == command) && !Objects.requireNonNull(capabilities).isPrimaryInverted() + ? PercentType.HUNDRED + : PercentType.ZERO); + webTargets.moveShade(shadeId, new Shade().setShadePosition(position)); + break; + } else if (StopMoveType.STOP == command) { + webTargets.stopShade(shadeId); + break; + } + throw new IllegalArgumentException(INVALID_COMMAND); + + case CHANNEL_SHADE_SECONDARY_POSITION: + if (command instanceof PercentType) { + position.setPosition(SECONDARY_POSITION, ((PercentType) command)); + webTargets.moveShade(shadeId, new Shade().setShadePosition(position)); + break; + } else if (command instanceof UpDownType) { + position.setPosition(SECONDARY_POSITION, + (UpDownType.UP == command) + && !Objects.requireNonNull(capabilities).supportsSecondaryOverlapped() + ? PercentType.ZERO + : PercentType.HUNDRED); + webTargets.moveShade(shadeId, new Shade().setShadePosition(position)); + break; + } else if (StopMoveType.STOP == command) { + webTargets.stopShade(shadeId); + break; + } + throw new IllegalArgumentException(INVALID_COMMAND); + + case CHANNEL_SHADE_VANE: + if (command instanceof PercentType) { + position.setPosition(VANE_TILT_POSITION, ((PercentType) command)); + webTargets.moveShade(shadeId, new Shade().setShadePosition(position)); + break; + } else if (command instanceof UpDownType) { + position.setPosition(VANE_TILT_POSITION, + UpDownType.UP == command ? PercentType.HUNDRED : PercentType.ZERO); + webTargets.moveShade(shadeId, new Shade().setShadePosition(position)); + break; + } + throw new IllegalArgumentException(INVALID_COMMAND); + + case CHANNEL_SHADE_COMMAND: + if ((command instanceof StringType) && COMMAND_IDENTIFY.equals(((StringType) command).toString())) { + webTargets.jogShade(shadeId); + break; + } + throw new IllegalArgumentException(INVALID_COMMAND); + + default: + throw new IllegalArgumentException(INVALID_CHANNEL); + } + } catch (HubProcessingException | IllegalArgumentException e) { + logger.warn("handleCommand() shadeId:{}, channelUID:{}, command:{}, exception:{}, message:{}", shadeId, + channelUID, command, e.getClass().getSimpleName(), e.getMessage()); + } + } + + private boolean hasPrimary() { + return Objects.requireNonNull(capabilities).supportsPrimary(); + } + + private boolean hasSecondary() { + Capabilities capabilities = Objects.requireNonNull(this.capabilities); + return capabilities.supportsSecondary() || capabilities.supportsSecondaryOverlapped(); + } + + private boolean hasVane() { + Capabilities capabilities = Objects.requireNonNull(this.capabilities); + return capabilities.supportsTilt180() || capabilities.supportsTiltAnywhere() + || capabilities.supportsTiltOnClosed(); + } + + @Override + public void initialize() { + shadeId = getConfigAs(HDPowerViewShadeConfiguration.class).id; + Bridge bridge = getBridge(); + BridgeHandler bridgeHandler = bridge != null ? bridge.getHandler() : null; + if (!(bridgeHandler instanceof GatewayBridgeHandler)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error.invalid-bridge-handler"); + return; + } + isInitialized = false; + updateStatus(ThingStatus.UNKNOWN); + } + + /** + * Handle shade state change notifications. + * + * @param shade the new shade state. + * @return true if we handled the call. + */ + public boolean notify(Shade shade) { + if (shadeId == shade.getId()) { + updateStatus(ThingStatus.ONLINE); + if (!isInitialized && shade.hasFullState()) { + updateCapabilities(shade); + updateProperties(shade); + updateDynamicChannels(shade); + isInitialized = true; + } + updateChannels(shade); + return true; + } + return false; + } + + /** + * Update the capabilities object based on the data in the passed shade instance. + * + * @param shade containing the channel data. + */ + private void updateCapabilities(Shade shade) { + Capabilities capabilities = this.capabilities; + if (capabilities == null) { + capabilities = DB.getCapabilities(shade.getCapabilities()); + this.capabilities = capabilities; + } + } + + /** + * Update channels based on the data in the passed shade instance. + * + * @param shade containing the channel data. + */ + private void updateChannels(Shade shade) { + updateState(CHANNEL_SHADE_POSITION, hasPrimary() ? shade.getPosition(PRIMARY_POSITION) : UnDefType.UNDEF); + updateState(CHANNEL_SHADE_VANE, hasVane() ? shade.getPosition(VANE_TILT_POSITION) : UnDefType.UNDEF); + updateState(CHANNEL_SHADE_SECONDARY_POSITION, + hasSecondary() ? shade.getPosition(SECONDARY_POSITION) : UnDefType.UNDEF); + if (shade.hasFullState()) { + updateState(CHANNEL_SHADE_LOW_BATTERY, shade.getLowBattery()); + updateState(CHANNEL_SHADE_BATTERY_LEVEL, shade.getBatteryLevel()); + updateState(CHANNEL_SHADE_SIGNAL_STRENGTH, shade.getSignalStrength()); + } + } + + /** + * If the given channel exists in the thing, but is NOT required in the thing, then add it to a list of channels to + * be removed. Or if the channel does NOT exist in the thing, but is required in the thing, then log a warning. + * + * @param removeList the list of channels to be removed from the thing. + * @param channelId the id of the channel to be (eventually) removed. + * @param channelRequired true if the thing requires this channel. + */ + private void updateDynamicChannel(List removeList, String channelId, boolean channelRequired) { + Channel channel = thing.getChannel(channelId); + if (!channelRequired && channel != null) { + removeList.add(channel); + } else if (channelRequired && channel == null) { + logger.warn("updateDynamicChannel() shadeId:{} is missing channel:{} => please recreate the thing", shadeId, + channelId); + } + } + + /** + * Remove previously statically created channels if the shade does not support them or they are not relevant. + * + * @param shade containing the channel data. + */ + private void updateDynamicChannels(Shade shade) { + List removeChannels = new ArrayList<>(); + updateDynamicChannel(removeChannels, CHANNEL_SHADE_POSITION, hasPrimary()); + updateDynamicChannel(removeChannels, CHANNEL_SHADE_SECONDARY_POSITION, hasSecondary()); + updateDynamicChannel(removeChannels, CHANNEL_SHADE_VANE, hasVane()); + updateDynamicChannel(removeChannels, CHANNEL_SHADE_BATTERY_LEVEL, !shade.isMainsPowered()); + updateDynamicChannel(removeChannels, CHANNEL_SHADE_LOW_BATTERY, !shade.isMainsPowered()); + if (!removeChannels.isEmpty()) { + if (logger.isDebugEnabled()) { + StringJoiner joiner = new StringJoiner(", "); + removeChannels.forEach(c -> joiner.add(c.getUID().getId())); + logger.debug("updateDynamicChannels() shadeId:{}, removing unsupported channels:{}", shadeId, + joiner.toString()); + } + updateThing(editThing().withoutChannels(removeChannels).build()); + } + } + + /** + * Update thing properties based on the data in the passed shade instance. + * + * @param shade containing the property data. + */ + private void updateProperties(Shade shade) { + thing.setProperties(Stream.of(new String[][] { // + { HDPowerViewBindingConstants.PROPERTY_NAME, shade.getName() }, + { HDPowerViewBindingConstants.PROPERTY_SHADE_TYPE, getType(shade).toString() }, + { HDPowerViewBindingConstants.PROPERTY_SHADE_CAPABILITIES, + Objects.requireNonNull(capabilities).toString() }, + { HDPowerViewBindingConstants.PROPERTY_POWER_TYPE, shade.getPowerType().name().toLowerCase() }, + { HDPowerViewBindingConstants.PROPERTY_BLE_NAME, shade.getBleName() }, + { Thing.PROPERTY_FIRMWARE_VERSION, shade.getFirmware() } // + }).collect(Collectors.toMap(data -> data[0], data -> data[1]))); + } + + /** + * Override base method to only update the channel if it actually exists. + * + * @param channelID id of the channel, which was updated + * @param state new state + */ + @Override + protected void updateState(String channelID, State state) { + if (thing.getChannel(channelID) != null) { + super.updateState(channelID, state); + } + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/config/config.xml index 9945d63e8e68f..21acc75050282 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/config/config.xml @@ -14,7 +14,7 @@ - The numeric ID of the PowerView Shade in the Hub + The numeric ID of the PowerView Shade in the Hub/Gateway diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties index 85f56465b5526..fc10667c8eb4a 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/i18n/hdpowerview.properties @@ -5,6 +5,8 @@ addon.hdpowerview.description = The Hunter Douglas PowerView binding provides ac # thing types +thing-type.hdpowerview.gateway.label = PowerView Gen3 Gateway +thing-type.hdpowerview.gateway.description = Hunter Douglas (Luxaflex) PowerView Generation 3 Gateway/Gateway Pro thing-type.hdpowerview.hub.label = PowerView Hub thing-type.hdpowerview.hub.description = Hunter Douglas (Luxaflex) PowerView Hub thing-type.hdpowerview.repeater.label = PowerView Repeater @@ -12,28 +14,36 @@ thing-type.hdpowerview.repeater.description = Hunter Douglas (Luxaflex) PowerVie thing-type.hdpowerview.repeater.channel.brightness.description = Controls the brightness of the LED ring thing-type.hdpowerview.repeater.channel.color.description = Controls the color of the LED ring thing-type.hdpowerview.shade.label = PowerView Shade -thing-type.hdpowerview.shade.description = Hunter Douglas (Luxaflex) PowerView Shade +thing-type.hdpowerview.shade.description = Hunter Douglas (Luxaflex) PowerView Gen 1/2 Shade thing-type.hdpowerview.shade.channel.hubRssi.label = Hub RSSI thing-type.hdpowerview.shade.channel.hubRssi.description = Received Signal Strength Indicator for Hub thing-type.hdpowerview.shade.channel.repeaterRssi.label = Repeater RSSI thing-type.hdpowerview.shade.channel.repeaterRssi.description = Received Signal Strength Indicator for Repeater thing-type.hdpowerview.shade.channel.secondary.label = Secondary Position thing-type.hdpowerview.shade.channel.secondary.description = The secondary vertical position (on top-down/bottom-up shades) +thing-type.hdpowerview.shade3.label = PowerView Shade +thing-type.hdpowerview.shade3.description = Hunter Douglas (Luxaflex) PowerView Gen3 Shade +thing-type.hdpowerview.shade3.channel.secondary.label = Secondary Position +thing-type.hdpowerview.shade3.channel.secondary.description = The secondary vertical position (on top-down/bottom-up shades) # thing types config +thing-type.config.hdpowerview.gateway.hardRefresh.label = Hard Refresh Interval +thing-type.config.hdpowerview.gateway.hardRefresh.description = The number of minutes between hard refreshes of the PowerView Gateway +thing-type.config.hdpowerview.gateway.host.label = Host +thing-type.config.hdpowerview.gateway.host.description = The host address of the PowerView Gateway thing-type.config.hdpowerview.hub.hardRefresh.label = Hard Position Refresh Interval thing-type.config.hdpowerview.hub.hardRefresh.description = The number of minutes between hard refreshes of positions from the PowerView Hub (or 0 to disable) thing-type.config.hdpowerview.hub.hardRefreshBatteryLevel.label = Hard Battery Level Refresh Interval thing-type.config.hdpowerview.hub.hardRefreshBatteryLevel.description = The number of hours between hard refreshes of battery levels from the PowerView Hub (or 0 to disable, default is weekly) thing-type.config.hdpowerview.hub.host.label = Host -thing-type.config.hdpowerview.hub.host.description = The Host address of the PowerView Hub +thing-type.config.hdpowerview.hub.host.description = The host address of the PowerView Hub thing-type.config.hdpowerview.hub.refresh.label = Refresh Interval thing-type.config.hdpowerview.hub.refresh.description = The number of milliseconds between fetches of the PowerView Hub shade state thing-type.config.hdpowerview.repeater.id.label = ID thing-type.config.hdpowerview.repeater.id.description = The numeric ID of the PowerView Repeater in the Hub thing-type.config.hdpowerview.shade.id.label = ID -thing-type.config.hdpowerview.shade.id.description = The numeric ID of the PowerView Shade in the Hub +thing-type.config.hdpowerview.shade.id.description = The numeric ID of the PowerView Shade in the Hub/Gateway # channel group types @@ -46,6 +56,8 @@ channel-group-type.hdpowerview.scenes.label = Scenes channel-type.hdpowerview.automation-enabled.label = Enable channel-type.hdpowerview.battery-voltage.label = Battery Voltage channel-type.hdpowerview.battery-voltage.description = Battery voltage reported by the shade +channel-type.hdpowerview.ble-signal-strength.label = Signal Strength +channel-type.hdpowerview.ble-signal-strength.description = Signal strength of Bluetooth Low Energy communication channel-type.hdpowerview.repeater-blinking-enabled.label = Blinking Enabled channel-type.hdpowerview.repeater-blinking-enabled.description = Blink during commands channel-type.hdpowerview.repeater-identify.label = Identify @@ -63,12 +75,20 @@ channel-type.hdpowerview.shade-position.label = Position channel-type.hdpowerview.shade-position.description = The vertical position of the shade channel-type.hdpowerview.shade-vane.label = Vane channel-type.hdpowerview.shade-vane.description = The opening of the slats in the shade +channel-type.hdpowerview.shade3-command.label = Command +channel-type.hdpowerview.shade3-command.description = Send a command to identify the shade +channel-type.hdpowerview.shade3-command.command.option.IDENTIFY = Identify # thing status descriptions offline.conf-error.no-host-address = Host address must be set offline.conf-error.invalid-bridge-handler = Invalid bridge handler -offline.gone.shade-unknown-to-hub = Shade is unknown to Hub +offline.gone.shade-unknown-to-hub = Shade is unknown to Hub/Gateway + +# discovery + +discovery.hub.label = PowerView Gen 1/2 Hub ({0}) +discovery.gateway.label = PowerView Gen 3 Gateway ({0}) # dynamic channels diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/bridge.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/bridge.xml index 1c20f86e965d2..44db4ac1545a8 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/bridge.xml @@ -24,7 +24,7 @@ - The Host address of the PowerView Hub + The host address of the PowerView Hub network-address @@ -47,4 +47,33 @@ + + + Hunter Douglas (Luxaflex) PowerView Generation 3 Gateway/Gateway Pro + + + + + + + Hunter Douglas (Luxaflex) + PowerView Gen 3 Gateway + + + host + + + + + The host address of the PowerView Gateway + network-address + + + + The number of minutes between hard refreshes of the PowerView Gateway + 180 + + + + diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/channels.xml index 914bedbb35ae5..71264b04532aa 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/channels.xml @@ -8,13 +8,15 @@ Rollershutter The vertical position of the shade - blinds + Blinds + Dimmer The opening of the slats in the shade + @@ -30,6 +32,18 @@ veto + + String + + Send a command to identify the shade + + + + + + veto + + Switch @@ -77,6 +91,14 @@ Blink during commands + + Number:Power + + Signal strength of Bluetooth Low Energy communication + QualityOfService + + + diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/shade.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/shade.xml index a8dd168767b77..de18d3b353968 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/shade.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/thing/shade.xml @@ -9,7 +9,7 @@ - Hunter Douglas (Luxaflex) PowerView Shade + Hunter Douglas (Luxaflex) PowerView Gen 1/2 Shade @@ -43,4 +43,34 @@ + + + + + + Hunter Douglas (Luxaflex) PowerView Gen3 Shade + + + + + + The secondary vertical position (on top-down/bottom-up shades) + + + + + + + + + + Hunter Douglas (Luxaflex) + PowerView Motorized Shade + + + id + + + + diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml new file mode 100644 index 0000000000000..70a692f2f238d --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/OH-INF/update/update.xml @@ -0,0 +1,22 @@ + + + + + + + powerview:shade-position + + + powerview:shade-position + + The secondary vertical position (on top-down/bottom-up shades) + + + powerview:shade-vane + + + + + diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/gen3/Generation3DtoTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/gen3/Generation3DtoTest.java new file mode 100644 index 0000000000000..911f7cc9ba4f9 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/gen3/Generation3DtoTest.java @@ -0,0 +1,284 @@ +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hdpowerview.internal.gen3; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.hdpowerview.internal.HDPowerViewJUnitTests; +import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase; +import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities; +import org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Scene; +import org.openhab.binding.hdpowerview.internal.dto.gen3.SceneEvent; +import org.openhab.binding.hdpowerview.internal.dto.gen3.Shade; +import org.openhab.binding.hdpowerview.internal.dto.gen3.ShadeEvent; +import org.openhab.binding.hdpowerview.internal.dto.gen3.ShadePosition; +import org.openhab.binding.hdpowerview.internal.handler.ShadeThingHandler; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; +import org.openhab.core.thing.binding.ThingHandlerCallback; +import org.openhab.core.thing.binding.builder.ChannelBuilder; +import org.openhab.core.thing.binding.builder.ThingBuilder; +import org.openhab.core.types.UnDefType; + +import com.google.gson.Gson; + +/** + * Unit tests for Generation 3 DTO's. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class Generation3DtoTest { + + private final Gson gson = new Gson(); + private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase(); + + private String loadJson(String filename) throws IOException { + try (InputStream inputStream = HDPowerViewJUnitTests.class.getResourceAsStream(filename)) { + if (inputStream == null) { + throw new IOException("inputstream is null"); + } + byte[] bytes = inputStream.readAllBytes(); + if (bytes == null) { + throw new IOException("Resulting byte-array empty"); + } + return new String(bytes, StandardCharsets.UTF_8); + } + } + + /** + * Test JSON scene event response. + */ + @Test + public void testSceneEventParsing() throws IOException { + String json = loadJson("gen3/scene-event.json"); + SceneEvent sceneEvent = gson.fromJson(json, SceneEvent.class); + assertNotNull(sceneEvent); + Scene scene = sceneEvent.getScene(); + assertNotNull(scene); + assertEquals("Open All Office Shades\n Open All Office Shades", scene.getName()); + assertEquals(234, scene.getId()); + } + + /** + * Test JSON scenes response. + */ + @Test + public void testScenesParsing() throws IOException { + String json = loadJson("gen3/scenes.json"); + List sceneList = List.of(gson.fromJson(json, Scene[].class)); + assertNotNull(sceneList); + assertEquals(1, sceneList.size()); + Scene scene = sceneList.get(0); + assertEquals("Open All Office Shades\n ABC", scene.getName()); + assertEquals(234, scene.getId()); + } + + /** + * Test JSON shade event response. + */ + @Test + public void testShadeEventParsing() throws IOException { + String json = loadJson("gen3/shade-event.json"); + ShadeEvent shadeEvent = gson.fromJson(json, ShadeEvent.class); + assertNotNull(shadeEvent); + ShadePosition position = shadeEvent.getCurrentPositions(); + assertNotNull(position); + assertEquals(PercentType.valueOf("99"), position.getState(CoordinateSystem.PRIMARY_POSITION)); + assertEquals(PercentType.valueOf("98"), position.getState(CoordinateSystem.SECONDARY_POSITION)); + assertEquals(PercentType.ZERO, position.getState(CoordinateSystem.VANE_TILT_POSITION)); + } + + /** + * Test JSON shade position setting. + */ + @Test + public void testShadePositions() { + ShadePosition pos; + + pos = new ShadePosition(); + pos.setPosition(CoordinateSystem.PRIMARY_POSITION, new PercentType(11)); + assertEquals(PercentType.valueOf("11"), pos.getState(CoordinateSystem.PRIMARY_POSITION)); + assertEquals(UnDefType.UNDEF, pos.getState(CoordinateSystem.SECONDARY_POSITION)); + assertEquals(UnDefType.UNDEF, pos.getState(CoordinateSystem.VANE_TILT_POSITION)); + + pos = new ShadePosition(); + pos.setPosition(CoordinateSystem.PRIMARY_POSITION, new PercentType(11)); + pos.setPosition(CoordinateSystem.SECONDARY_POSITION, new PercentType(22)); + pos.setPosition(CoordinateSystem.VANE_TILT_POSITION, new PercentType(33)); + assertEquals(PercentType.valueOf("11"), pos.getState(CoordinateSystem.PRIMARY_POSITION)); + assertEquals(PercentType.valueOf("22"), pos.getState(CoordinateSystem.SECONDARY_POSITION)); + assertEquals(PercentType.valueOf("33"), pos.getState(CoordinateSystem.VANE_TILT_POSITION)); + } + + /** + * Test JSON shades response. + */ + @Test + public void testShadesParsing() throws IOException { + String json = loadJson("gen3/shades.json"); + List shadeList = List.of(gson.fromJson(json, Shade[].class)); + assertNotNull(shadeList); + assertEquals(2, shadeList.size()); + Shade shadeData = shadeList.get(0); + assertEquals("Upper Left", shadeData.getName()); + assertEquals(2, shadeData.getId()); + assertFalse(shadeData.isMainsPowered()); + assertEquals(new DecimalType(66), shadeData.getBatteryLevel()); + assertEquals(OnOffType.OFF, shadeData.getLowBattery()); + ShadePosition positions = shadeData.getShadePositions(); + assertNotNull(positions); + Integer caps = shadeData.getCapabilities(); + assertNotNull(caps); + Capabilities capabilities = db.getCapabilities(caps); + assertTrue(capabilities.supportsPrimary()); + assertFalse(capabilities.supportsSecondary()); + assertFalse(capabilities.supportsTilt180()); + assertFalse(capabilities.supportsTiltAnywhere()); + assertFalse(capabilities.supportsTiltOnClosed()); + + shadeData = shadeList.get(1); + assertEquals(3, shadeData.getId()); + assertTrue(shadeData.isMainsPowered()); + positions = shadeData.getShadePositions(); + assertNotNull(positions); + caps = shadeData.getCapabilities(); + assertNotNull(caps); + capabilities = db.getCapabilities(caps); + assertTrue(capabilities.supportsPrimary()); + assertFalse(capabilities.supportsSecondary()); + assertFalse(capabilities.supportsTilt180()); + assertFalse(capabilities.supportsTiltAnywhere()); + assertTrue(capabilities.supportsTiltOnClosed()); + } + + /** + * Test sending properties and dynamic channel values to a shade handler. + */ + @Test + public void testShadeHandlerPropertiesAndChannels() throws IOException { + ThingTypeUID thingTypeUID = new ThingTypeUID("hdpowerview:shade"); + ThingUID thingUID = new ThingUID(thingTypeUID, "test"); + + List channels = new ArrayList(); + for (String channelId : Set.of(CHANNEL_SHADE_POSITION, CHANNEL_SHADE_SECONDARY_POSITION, CHANNEL_SHADE_VANE, + CHANNEL_SHADE_BATTERY_LEVEL, CHANNEL_SHADE_LOW_BATTERY, CHANNEL_SHADE_SIGNAL_STRENGTH)) { + ChannelUID channelUID = new ChannelUID(thingUID, channelId); + channels.add(ChannelBuilder.create(channelUID).build()); + } + + String json = loadJson("gen3/shades.json"); + List shadeList = List.of(gson.fromJson(json, Shade[].class)); + assertNotNull(shadeList); + assertEquals(2, shadeList.size()); + + Thing thing = ThingBuilder.create(thingTypeUID, thingUID).withChannels(channels).build(); + ShadeThingHandler shadeThingHandler; + Shade shadeData; + + /* + * Use the first JSON Shade entry. + * It should support 4 dynamic channels. + */ + shadeThingHandler = new ShadeThingHandler(thing); + shadeThingHandler.setCallback(mock(ThingHandlerCallback.class)); + shadeData = shadeList.get(0).setId(0); + assertTrue(shadeData.hasFullState()); + shadeThingHandler.notify(shadeData); + Thing handlerThing = shadeThingHandler.getThing(); + assertEquals("Duette (6)", handlerThing.getProperties().get("type")); + assertEquals("battery", handlerThing.getProperties().get("powerType")); + assertEquals("3.0.359", handlerThing.getProperties().get("firmwareVersion")); + assertEquals(new QuantityType<>(-50, Units.DECIBEL_MILLIWATTS), shadeData.getSignalStrength()); + assertEquals(4, handlerThing.getChannels().size()); + + /* + * Use the second JSON Shade entry. + * It should support only 3 dynamic channels. + */ + shadeThingHandler = new ShadeThingHandler(thing); + shadeThingHandler.setCallback(mock(ThingHandlerCallback.class)); + shadeData = shadeList.get(1).setId(0); + assertTrue(shadeData.hasFullState()); + shadeThingHandler.notify(shadeData); + handlerThing = shadeThingHandler.getThing(); + assertEquals("Silhouette (23)", handlerThing.getProperties().get("type")); + assertEquals("hardwired", handlerThing.getProperties().get("powerType")); + assertEquals("3.0.359", handlerThing.getProperties().get("firmwareVersion")); + assertEquals(new QuantityType<>(-51, Units.DECIBEL_MILLIWATTS), shadeData.getSignalStrength()); + assertEquals(3, handlerThing.getChannels().size()); + } + + /** + * Test sending state change events to shade handler. + */ + @Test + public void testShadeHandlerEvents() throws IOException { + ThingTypeUID thingTypeUID = new ThingTypeUID("hdpowerview:shade"); + ThingUID thingUID = new ThingUID(thingTypeUID, "test"); + + List channels = new ArrayList(); + for (String channelId : Set.of(CHANNEL_SHADE_POSITION, CHANNEL_SHADE_SECONDARY_POSITION, CHANNEL_SHADE_VANE, + CHANNEL_SHADE_BATTERY_LEVEL, CHANNEL_SHADE_LOW_BATTERY, CHANNEL_SHADE_SIGNAL_STRENGTH)) { + ChannelUID channelUID = new ChannelUID(thingUID, channelId); + channels.add(ChannelBuilder.create(channelUID).build()); + } + + String json = loadJson("gen3/shades.json"); + List shadeList = List.of(gson.fromJson(json, Shade[].class)); + assertNotNull(shadeList); + assertEquals(2, shadeList.size()); + + Thing thing = ThingBuilder.create(thingTypeUID, thingUID).withChannels(channels).build(); + ShadeThingHandler shadeThingHandler; + Shade shadeData; + + /* + * Use the second JSON Shade entry, which only has a primary channel. + */ + shadeThingHandler = new ShadeThingHandler(thing); + shadeThingHandler.setCallback(mock(ThingHandlerCallback.class)); + shadeData = shadeList.get(1).setId(0); + shadeThingHandler.notify(shadeData); + + /* + * And try to update it with an event that has all 3 channels. + */ + json = loadJson("gen3/shade-event.json"); + ShadeEvent event = gson.fromJson(json, ShadeEvent.class); + assertNotNull(event); + shadeData = new Shade().setId(0).setShadePosition(event.getCurrentPositions()).setPartialState(); + assertFalse(shadeData.hasFullState()); + shadeThingHandler.notify(shadeData); + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/automations.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/automations.json new file mode 100644 index 0000000000000..1481512f41f60 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/automations.json @@ -0,0 +1,13 @@ +[ + { + "id": 33, + "type": 6, + "enabled": true, + "days": "24", + "hour": 4, + "min": 5, + "bleId": 83, + "sceneId": 116, + "errorShd_Ids": null + } +] diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/openapi.yaml b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/openapi.yaml new file mode 100644 index 0000000000000..1441861242625 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/openapi.yaml @@ -0,0 +1,12912 @@ +swaggerDoc: + openapi: 3.0.3 + info: + title: PowerView Gen3 Gateway + description: >- + The Gateway can be accessed and controlled via HTTP requests over a local + area network via this API. + version: 1.10.0 + servers: + - url: http://10.0.0.127:80 + tags: + - name: Home + description: >- + A Home consists of a number of related objects such as Rooms, Shades, + Scenes, Automations, Gateways, and Remotes. The Home APIs access the + Home in the following way: + * listing objects and their properties + * mutating object relationships and properties + * performing actions such as moving Shades and activating Scenes + + Note: If the Home does not have a HomeDoc, all /home APIs return + statusCode 503/SERVICE_UNAVAILABLE until the Home is correctly + configured and a HomeDoc is successfully retrieved from the Cloud + - name: Events + description: Provide Home Shade and Scene Events over an HTTP Streaming interface + - name: Gateway + description: >- + APIs providing ways to configure, provision, manage and diagnose the + Gateway + - name: HomeKit + description: APIs to manage HomeKit running on the Gateway + - name: HD Internal + description: >- + APIs for the sole use of Hunter Douglas. These APIs are internal hooks + for Hunter Douglas specific Apps and for troubleshooting + paths: + /gateway/: + get: + summary: Retrieve general Gateway information + tags: + - Gateway + responses: + '200': + description: The Gateway information object + content: + application/json: + schema: + type: object + properties: + config: + properties: + rev: + title: Config.rev + description: Config data structure version + type: number + hwVersion: + title: Config.hwVersion + description: Hardware version + type: string + model: + title: Config.model + description: Hardware model + type: string + brand: + title: Config.brand + description: Hardware brand + type: string + serialNumber: + title: Config.serialNumber + description: Unique serial number across all products + type: string + firmware: + title: Config.firmware + description: Software version + properties: + mainProcessor: + title: BuildVersions.mainProcessor + description: Version number + properties: + build: + title: TypescriptAppBuildInfo.build + description: Build number + type: number + name: + title: TypescriptAppBuildInfo.name + description: '???' + type: string + revision: + title: TypescriptAppBuildInfo.revision + description: Major version number + type: number + subRevision: + title: TypescriptAppBuildInfo.subRevision + description: Minor version number + type: number + required: + - build + - name + - revision + - subRevision + additionalProperties: false + type: object + radios: + items: + title: BuildVersions.radios.[] + properties: + build: + title: TransceiverFirmwareBuildInfo.build + description: Build number + type: number + revision: + title: TransceiverFirmwareBuildInfo.revision + description: Major version number + type: number + subRevision: + title: TransceiverFirmwareBuildInfo.subRevision + description: Minor version number + type: number + required: + - build + - revision + - subRevision + additionalProperties: false + description: Transceiver/Radio firmware information + type: object + title: BuildVersions.radios + description: Transceiver/Radio firmware versions + type: array + required: + - mainProcessor + - radios + additionalProperties: false + type: object + homeAssoc: + title: Config.homeAssoc + description: >- + 2-byte Hash of the HomeSecurityKey (AKA: + ShadeSecurityKey) + type: number + color: + title: Config.color + description: >- + User idle color - the color the user chose for the + Idle state + properties: + brightness: + title: LedColor.brightness + description: LED brightness percentage between 0 and 100 + type: number + red: + title: LedColor.red + description: Red color value between 0 and 255 + type: number + green: + title: LedColor.green + description: Green color value between 0 and 255 + type: number + blue: + title: LedColor.blue + description: Blue color value between 0 and 255 + type: number + required: + - brightness + - red + - green + - blue + additionalProperties: false + type: object + cloudConfig: + title: Config.cloudConfig + properties: + cloudEnv: + title: FirestoreConfig.cloudEnv + description: >- + What cloud environment to access (i.e, what + credentials to load) + type: number + collection: + title: FirestoreConfig.collection + description: Cloud collection name for homeDocs + type: string + homeId: + title: FirestoreConfig.homeId + description: Home identifier for this household + type: string + gatewayId: + title: FirestoreConfig.gatewayId + description: Gateway id for THIS gateway + type: number + required: + - cloudEnv + - collection + - homeId + - gatewayId + additionalProperties: false + description: >- + Cloud Config + + The properties required to uniquely identify a Home + and Gateway pairing. + type: object + rangeMapper: + title: Config.rangeMapper + description: Radio scan information + properties: + minRSSI: + title: RangeMapperDb.minRSSI + description: The minimum RSSI (of Shades) to report back on + type: number + levelingSeconds: + title: RangeMapperDb.levelingSeconds + description: >- + The number of seconds over that the algorithm + averages over + type: number + required: + - minRSSI + - levelingSeconds + additionalProperties: false + type: object + networkConfig: + title: Config.networkConfig + description: Persistent network configuration + properties: + staticIpEnabled: + title: NetworkConfig.staticIpEnabled + description: Is static IP configuration enabled? + type: boolean + staticIp: + properties: + ip_address: + title: NetworkConfig.staticIp.ip_address + description: Static IP address + type: string + netmask: + title: NetworkConfig.staticIp.netmask + description: Static IP network mask + type: string + gateway_ip: + title: NetworkConfig.staticIp.gateway_ip + description: >- + Home gateway IP address (i.e., the home + router + type: string + dns: + items: + type: string + title: NetworkConfig.staticIp.dns + description: DNS IP values + type: array + required: + - ip_address + - netmask + - gateway_ip + - dns + additionalProperties: false + title: NetworkConfig.staticIp + description: Static IP values if enabled + type: object + required: + - staticIpEnabled + - staticIp + additionalProperties: false + type: object + networkStatus: + title: Config.networkStatus + description: Transient network information + properties: + ipAddress: + title: NetworkStatus.ipAddress + description: Currently active IP address + type: string + activeInterface: + title: NetworkStatus.activeInterface + description: Current active network interface + type: string + primaryMacAddress: + title: NetworkStatus.primaryMacAddress + description: Primary MAC address to identify device + type: string + dns: + items: + type: string + title: NetworkStatus.dns + description: DNS entries + type: array + eth0: + title: NetworkStatus.eth0 + description: Wired network interface information + wlan0: + title: NetworkStatus.wlan0 + description: Wireless network interface information + internetState: + title: NetworkStatus.internetState + description: Internet connectivity state + type: string + enum: + - Connected + - Disconnected + ssid: + title: NetworkStatus.ssid + description: Wireless SSID + type: string + required: + - ipAddress + - activeInterface + - primaryMacAddress + - dns + - eth0 + - wlan0 + - internetState + - ssid + additionalProperties: false + type: object + mgwConfig: + title: Config.mgwConfig + description: Persistent multi-gateway configuration + properties: + primary: + title: MultiGatewayConfig.primary + description: This gateway is the primary in multi-gateway + type: boolean + required: + - primary + additionalProperties: false + type: object + mgwStatus: + title: Config.mgwStatus + description: Transient multi-gateway information + properties: + running: + title: MultiGatewayStatus.running + description: Multi-gateway is operational + type: boolean + required: + - running + additionalProperties: false + type: object + required: + - rev + - hwVersion + - model + - brand + - serialNumber + - firmware + - homeAssoc + - color + - cloudConfig + - rangeMapper + - networkConfig + - networkStatus + - mgwConfig + - mgwStatus + additionalProperties: false + title: Config + type: object + /gateway/balancer: + get: + summary: Retrieve general Gateway balancer information + tags: + - HD Internal + responses: + '200': + description: The Gateway balancer information object + content: + application/json: + schema: + type: object + properties: + maxShadesPerChannel: + type: number + seqNum: + type: number + balancingAlg: + type: string + example: 0 = BALANCE_BY_GROUP + transactionNum: + type: number + /gateway/cloud/config: + get: + summary: Get the Gateway Cloud configuration + tags: + - Gateway + responses: + '200': + description: The Gateway Cloud configuration + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to + access the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + put: + summary: Set the Gateway Cloud configuration + tags: + - Gateway + requestBody: + description: Parameters for connection to the Cloud database + required: true + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to access + the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + responses: + '200': + description: The Gateway Cloud configuration + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to + access the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /gateway/cloud/config/push: + put: + summary: Push the individual Cloud configurations to each SPS + tags: + - Gateway + requestBody: + description: Parameters for connection to the Cloud database + required: true + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to access + the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + responses: + '200': + description: The Gateway Cloud configuration + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to + access the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /gateway/cloud/config/sps: + get: + summary: Allow a SPS to retrieve its Cloud configuration + tags: + - HD Internal + parameters: + - name: mac + in: query + required: true + description: Primary MAC address + schema: + type: string + example: F8:DC:7A:3D:FB:7A + responses: + '200': + description: The Gateway Cloud configuration + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to + access the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /gateway/factory-reset: + post: + summary: >- + Reset the Gateway by clearing all the settings and restoring them to + the factory defaults + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/homekit: + get: + summary: Returns the homekit information + tags: + - HomeKit + responses: + '200': + description: HomeKit information + content: + application/json: + schema: + type: object + properties: + hapBridge: + type: object + properties: + pid: + type: number + connected: + type: boolean + exitCode: + type: string + killed: + type: boolean + started: + type: string + lastStoppedEvent: + type: string + stoppedMessage: + type: string + respawnDisabled: + type: boolean + debugEnabled: + type: boolean + closeEvents: + type: array + items: + type: string + lastAID: + type: number + accessoryMap: + type: object + /gateway/homekit/setup: + get: + summary: HomeKit setup data + tags: + - HomeKit + responses: + '200': + description: The HomeKit setup data + content: + application/json: + schema: + type: object + properties: + setupCode: + type: string + example: 383-67-992 + setupPayload: + type: string + example: X-HM://0E38KYF3CHSCC03FBKDP6RPW4CM4J5S + required: + - setupCode + - setupPayload + /gateway/homekit/pairing/clear: + put: + summary: Clears pairing signal + tags: + - HomeKit + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/homekit/pairing/restart: + put: + summary: Restarts Homekit pairing mode + tags: + - HomeKit + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/homekit/hdbridge/reset: + put: + summary: Factory resets HomeKit HD Bridge process + tags: + - HomeKit + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/homekit/hdbridge/restart: + put: + summary: Restarts HomeKit HD Bridge process + tags: + - HomeKit + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/homekit/reset: + post: + summary: >- + Factory reset HomeKit only. The response indicates HomeKit reset + completed + tags: + - HomeKit + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/identify: + get: + summary: Identify the Gateway by flashing the LED + tags: + - Gateway + parameters: + - name: time + in: query + required: false + description: The flash time in seconds + schema: + type: string + default: 10 + example: 15 + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + put: + summary: Identify the Gateway by flashing the LED + deprecated: true + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/info: + get: + summary: >- + Retrieve some Gateway info including the serial number and the + firmware version + tags: + - Gateway + responses: + '200': + description: Limited information about the Gateway + content: + application/json: + schema: + type: object + properties: + fwVersion: + type: string + description: Gateway firmware version string + example: 3.1.376 + serialNumber: + type: string + description: Gateway serial number + example: 3b4149d4f24d7bd7 + required: + - fwVersion + - serialNumber + /gateway/info/gateways: + get: + summary: Retrieve the known and missing Gateways + tags: + - Gateway + responses: + '200': + description: Known and missing Gateways + content: + application/json: + schema: + type: object + properties: + known: + type: object + description: Known HomeDoc Gateway identifier + additionalProperties: + type: object + properties: + st: + type: integer + description: >- + The current operating state, which is one of: + 0=STARTUP, 1=IDLE, 2=NEW_GW_NO_NETWORK, + 3=NO_INTERNET, 4=NO_HOME + example: 1 + pri: + type: boolean + description: >- + Optional: true indicates this Gateway is the + primary Gateway. Not set indicates this Gateway is + an auxiliary (aux) Gateway + self: + type: boolean + description: >- + Optional: true indicates this Gateway. Not set + indicates other Gateways in a multi-gateway system + required: + - st + missing: + type: array + description: >- + Gateway identifiers of HomeDoc listed Gateways who have + not reported recently + items: + type: number + description: HomeDoc Gateway identifier + example: 7643 + required: + - known + - missing + /gateway/internet/status: + get: + summary: Test the Gateway connection to the internet + tags: + - Gateway + responses: + '200': + description: Conformation of internet connection + content: + application/json: + schema: + type: object + properties: + HealthCheckResponse: + type: object + properties: + success: + type: boolean + type: + type: string + message: + type: string + required: + - success + - type + - message + required: + - HealthCheckResponse + /gateway/led: + get: + summary: Get the Gateway LED color and brightness + tags: + - Gateway + responses: + '200': + description: The LED Color + content: + application/json: + schema: + description: The Gateway LED color and brightness + type: object + properties: + red: + type: number + description: Red + maximum: 0 + minimum: 255 + green: + type: number + description: Green + maximum: 0 + minimum: 255 + blue: + type: number + description: Blue + maximum: 0 + minimum: 255 + brightness: + type: number + description: Brightness + maximum: 0 + minimum: 100 + required: + - red + - green + - blue + - brightness + put: + summary: Set the Gateway LED color and brightness + tags: + - Gateway + requestBody: + $ref: '#components/requestBodies/LedColor' + responses: + '200': + description: The LED Color + content: + application/json: + schema: + description: The Gateway LED color and brightness + type: object + properties: + red: + type: number + description: Red + maximum: 0 + minimum: 255 + green: + type: number + description: Green + maximum: 0 + minimum: 255 + blue: + type: number + description: Blue + maximum: 0 + minimum: 255 + brightness: + type: number + description: Brightness + maximum: 0 + minimum: 100 + required: + - red + - green + - blue + - brightness + /gateway/log: + get: + summary: Download the Gateway log from this Gateway + tags: + - Gateway + responses: + '200': + description: The current Gateway.log + /gateway/log/level: + get: + summary: Get the current Gateway log level + tags: + - Gateway + responses: + '200': + description: The Gateway current log level + content: + application/json: + schema: + type: object + properties: + level: + type: string + description: >- + The current root log level, which is one of: error, + warn, info, verbose, debug, or silly. The recommended + value is info. + example: info + transports: + type: array + items: + properties: + level: + type: string + description: >- + The current transport log level, which is one of: + error, warn, info, verbose, debug, or silly. The + recommended value is info. + example: silly + required: + - level + required: + - level + - transports + put: + summary: Set the Gateway log level and if it persists across Gateway restarts + tags: + - Gateway + parameters: + - name: level + in: query + required: true + description: >- + The new log level, which must be one of: error, warn, info, + verbose, debug, or silly. The recommended value is info. + schema: + type: string + example: debug + - name: persist + in: query + required: false + description: >- + If the new log level is to persist (be sticky) across application + restarts. Values are string 'true' or 'false' + schema: + type: string + example: 'true' + responses: + '204': + description: The log level was successfully set + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /gateway/log/upload: + get: + summary: Upload the Gateway log to the Cloud + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + put: + summary: Upload the Gateway log to the Cloud + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/network: + get: + summary: Retrieve the current Gateway network information + tags: + - Gateway + responses: + '200': + description: The Gateway's network information + content: + application/json: + schema: + type: object + properties: + networkConfig: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information + is to be applied. The below staticIp object is + optional if staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present + in its entirety. If staticIpEnabled is false, this + object may be present and if present, it must be + fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask to apply to the static IP + address value + example: 255.255.255.0 + gateway_ip: + type: string + description: >- + The static internet Gateway IP address to + utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + networkStatus: + description: The Gateway's network status information + type: object + properties: + ipAddress: + type: string + description: The IP address of the active interface + example: 10.0.0.101 + activeInterface: + type: string + description: >- + The active network interface identifier. Either + 'eth0' (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: eth0 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: 8.8.8.8 + eth0: + type: object + description: >- + The wired (eth0) network information, which may be + empty if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' + (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' + (eth0) or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: >- + The network interface's internet Gateway IP + address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + wlan0: + type: object + description: >- + The wireless (wlan0) network information, which may + be empty if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' + (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' + (eth0) or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: >- + The network interface's internet Gateway IP + address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + internetState: + type: string + description: The IP network's internet connectivity state + enum: + - Connected + - Disconnected + example: Connected + ssid: + type: string + description: >- + The wireless network's SSID value. The value is an + empty string if not configured + example: HunterDouglasWifi + required: + - ipAddress + - activeInterface + - dns + - eth0 + - wlan0 + - internetState + - ssid + required: + - networkConfig + - networkStatus + /gateway/network/config: + get: + summary: Retrieve the Gateway's current network configuration information + tags: + - Gateway + responses: + '200': + description: The Gateway's current network configuration information + content: + application/json: + schema: + type: object + properties: + networkConfig: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information + is to be applied. The below staticIp object is + optional if staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present + in its entirety. If staticIpEnabled is false, this + object may be present and if present, it must be + fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask to apply to the static IP + address value + example: 255.255.255.0 + gateway_ip: + type: string + description: >- + The static internet Gateway IP address to + utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + linuxStaticIpValues: + description: >- + The Gateway operating system's configured static IP + values These values should match the networkConfig + staticIp information + type: object + properties: + staticIpEnabled: + type: boolean + description: Indicates if the staticIp is enabled + example: true + interface: + type: string + description: >- + The network interface currently configured with the + static IP values + example: wlan0 + ip_address: + type: string + description: The IP address being utilized as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask applied to the static IP address + value + example: 255.255.255.0 + gateway_ip: + type: string + description: >- + The static internet Gateway IP address being + utilized + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + required: + - networkConfig + put: + summary: Modify the Gateway's network configuration + tags: + - Gateway + requestBody: + description: Update the network configuration + content: + application/json: + schema: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information is to + be applied. The below staticIp object is optional if + staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present in + its entirety. If staticIpEnabled is false, this object may + be present and if present, it must be fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask to apply to the static IP address + value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address to utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + responses: + '200': + description: The Gateway's current network configuration information + content: + application/json: + schema: + type: object + properties: + networkConfig: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information + is to be applied. The below staticIp object is + optional if staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present + in its entirety. If staticIpEnabled is false, this + object may be present and if present, it must be + fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask to apply to the static IP + address value + example: 255.255.255.0 + gateway_ip: + type: string + description: >- + The static internet Gateway IP address to + utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + linuxStaticIpValues: + description: >- + The Gateway operating system's configured static IP + values These values should match the networkConfig + staticIp information + type: object + properties: + staticIpEnabled: + type: boolean + description: Indicates if the staticIp is enabled + example: true + interface: + type: string + description: >- + The network interface currently configured with the + static IP values + example: wlan0 + ip_address: + type: string + description: The IP address being utilized as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask applied to the static IP address + value + example: 255.255.255.0 + gateway_ip: + type: string + description: >- + The static internet Gateway IP address being + utilized + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + required: + - networkConfig + /gateway/network/sddp: + get: + summary: Retrieve the Gateway's current SDDP configuration information + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + put: + summary: Configure the Gateway's current SDDP debug configuration + tags: + - Gateway + parameters: + - name: debug + in: query + required: true + description: true enables debug output; false disables debug output + schema: + type: boolean + example: true + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + /gateway/network/sddp/online: + put: + summary: Force the Gateway to emit a SDDP online notification message + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + /gateway/network/sddp/offline: + put: + summary: Force the Gateway to emit a SDDP offline notification message + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + /gateway/network/sddp/identify: + put: + summary: Force the Gateway to emit a SDDP identify message + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + /gateway/network/status: + get: + summary: Retrieve the Gateway's current network status information + tags: + - Gateway + responses: + '200': + description: The Gateway's current network status information + content: + application/json: + schema: + type: object + properties: + networkStatus: + description: The Gateway's network status information + type: object + properties: + ipAddress: + type: string + description: The IP address of the active interface + example: 10.0.0.101 + activeInterface: + type: string + description: >- + The active network interface identifier. Either + 'eth0' (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: eth0 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: 8.8.8.8 + eth0: + type: object + description: >- + The wired (eth0) network information, which may be + empty if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' + (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' + (eth0) or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: >- + The network interface's internet Gateway IP + address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + wlan0: + type: object + description: >- + The wireless (wlan0) network information, which may + be empty if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' + (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' + (eth0) or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: >- + The network interface's internet Gateway IP + address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + internetState: + type: string + description: The IP network's internet connectivity state + enum: + - Connected + - Disconnected + example: Connected + ssid: + type: string + description: >- + The wireless network's SSID value. The value is an + empty string if not configured + example: HunterDouglasWifi + required: + - ipAddress + - activeInterface + - dns + - eth0 + - wlan0 + - internetState + - ssid + required: + - networkStatus + /gateway/radios: + get: + summary: Retrieve radio build information + tags: + - Gateway + responses: + '200': + description: Gateway radios + content: + application/json: + schema: + properties: + serialNum: + type: string + appVersion: + type: string + softdeviceVersion: + type: string + bootloaderVersion: + type: string + type: object + /gateway/radios/clear: + post: + summary: Clear the channel maps of a radio + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/radios/shades: + get: + summary: List Shades on a radio or communications channel + tags: + - HD Internal + responses: + '200': + description: Gateway radio shades + content: + application/json: + schema: + type: array + items: + type: array + items: + type: object + properties: + index: + type: number + rssi: + type: number + example: -256 + ready: + type: number + example: 1 + bleName: + type: string + mac: + type: string + /gateway/reboot: + post: + summary: Reboot the Gateway + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/discover: + get: + summary: Returns a list of the Home's Shades with Bluetooth RSSI + description: >- + Returns a list of the Home's Shades and each Shade's Bluetooth RSSI as + observed from the Gateway. The list is sorted by decreasing RSSI + (stronger to weaker signal). Note: In multi-gateway systems, Shades + visible to the Gateway from the entire home are returned, which is + intended to facilitate optimising Gateway placement and + Shade-to-Gateway assignment. + + The list is filtered by the optional minimum RSSI threshold. When + omitted, the saved minimum RSSI level is used. + tags: + - Gateway + parameters: + - name: rssiMinValue + in: query + required: false + description: Minimum RSSI filter. Range is -20 to -100 + schema: + type: number + default: -90 + example: -80 + responses: + '200': + description: List of discovered Shades + content: + application/json: + schema: + type: object + properties: + scan: + type: array + description: Shades discovered List + items: + type: object + description: Discovered Shade entry + properties: + bleName: + type: string + description: Shade name + example: PIR:1E37 + filteredRssi: + type: number + description: Shade RSSI + example: -37 + required: + - bleName + - filteredRssi + required: + - scan + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + post: + summary: Returns a list of the Home's Shades with Bluetooth RSSI + deprecated: true + description: >- + Returns a list of the Home's Shades and each Shade's Bluetooth RSSI as + observed from the Gateway. The list is sorted by decreasing RSSI + (stronger to weaker signal). Note: In multi-gateway systems, Shades + visible to the Gateway from the entire home are returned, which is + intended to facilitate optimising Gateway placement and + Shade-to-Gateway assignment. + + The list is filtered by the optional minimum RSSI threshold. When + omitted, the saved minimum RSSI level is used. + tags: + - Gateway + requestBody: + description: Minimum RSSI filter + required: false + content: + application/json: + schema: + type: object + properties: + rssiMinValue: + type: number + description: Mimimum RSSI value + example: -66 + required: + - rssiMinValue + responses: + '200': + description: List of discovered Shades + content: + application/json: + schema: + type: object + properties: + scan: + type: array + description: Shades discovered List + items: + type: object + description: Discovered Shade entry + properties: + bleName: + type: string + description: Shade name + example: PIR:1E37 + filteredRssi: + type: number + description: Shade RSSI + example: -37 + required: + - bleName + - filteredRssi + required: + - scan + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + /gateway/sshd: + put: + summary: Request permission to SSH into the Gateway + tags: + - HD Internal + parameters: + - name: enable + in: query + required: true + description: >- + Boolean set to 'true' to start and permanently persist SSH. + 'false' stops and permanently disables SSH. + schema: + type: boolean + example: true + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/fab/info: + get: + summary: Returns the current fab Shade information details + tags: + - HD Internal + responses: + '200': + description: Gateway Fab Info response + content: + application/json: + schema: + type: object + properties: + shadesFabInfoAllShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + shadesFabInfoLocalShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + cachedPrimary: + type: boolean + periodicRequesterTimerNextRunTime: + type: string + put: + summary: Force all the fab Shade information data to update + tags: + - HD Internal + responses: + '200': + description: Gateway Fab Info response + content: + application/json: + schema: + type: object + properties: + shadesFabInfoAllShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + shadesFabInfoLocalShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + periodicCheckIntervalMs: + type: number + periodicCheckTimerNextRunTime: + type: string + cachedPrimary: + type: boolean + periodicRequesterTimerNextRunTime: + type: string + delete: + summary: Deletes all the fab Shade information + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/fab/info/aux: + put: + summary: Request the Shades fab information from all auxiliary devices + tags: + - HD Internal + responses: + '200': + description: Gateway Fab Info response + content: + application/json: + schema: + type: object + properties: + shadesFabInfoAllShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + shadesFabInfoLocalShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + periodicCheckIntervalMs: + type: number + periodicCheckTimerNextRunTime: + type: string + cachedPrimary: + type: boolean + periodicRequesterTimerNextRunTime: + type: string + /gateway/shades/fab/info/local: + put: + summary: Force the local Shades fab information to update + tags: + - HD Internal + responses: + '200': + description: Gateway Fab Info response + content: + application/json: + schema: + type: object + properties: + shadesFabInfoAllShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + shadesFabInfoLocalShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + periodicCheckIntervalMs: + type: number + periodicCheckTimerNextRunTime: + type: string + cachedPrimary: + type: boolean + periodicRequesterTimerNextRunTime: + type: string + /gateway/shades/fab/info/all-map: + delete: + summary: Deletes the all shade fab information map + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/fab/info/local-map: + delete: + summary: Deletes the local shade fab information map + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/fab/info/maps: + delete: + summary: Deletes both the local and the all Shade fab information maps + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/fab/info/lds: + delete: + summary: Deletes the Shades fab information local data store + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/shades/time/sync: + put: + summary: >- + Sync all times including sunrise, sunset, and current local time to + all Shades + tags: + - HD Internal + responses: + '200': + description: Gateway Shade Time Information + content: + application/json: + schema: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + setSunTimes: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + setCurrentTime: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + /gateway/shades/time/sync/current: + put: + summary: Sync the current local time to all Shades + tags: + - HD Internal + responses: + '200': + description: Gateway Shade Time Information + content: + application/json: + schema: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + setSunTimes: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + setCurrentTime: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + /gateway/shades/time/sync/info: + get: + summary: Retrieve the Shade Time Sync Manager sync information + tags: + - HD Internal + responses: + '200': + description: Shade Time Sync Manager Info + content: + application/json: + schema: + type: object + properties: + cachedHomeDocInfo: + type: object + properties: + gwId: + type: number + geoPoint: + type: object + properties: + latitude: + type: number + example: 29.9 + longitude: + type: number + example: -100 + tz: + type: string + example: America/Denver + localDstAdjustedOffset: + type: number + nextAllShadesSyncDate: + type: string + lastSuccessfulAllShadesSyncDate: + type: string + nextBleNamesSyncDate: + type: string + bleNamesNeedingSync: + type: array + items: + type: string + delayTimes: + type: object + properties: + homeDocUpdateDelayMs: + type: number + shadesAddedDelayMs: + type: number + syncAllRetryDelayMs: + type: number + syncListRetryDelayMs: + type: number + syncInProgressDelayMs: + type: number + syncInProgress: + type: boolean + /gateway/shades/time/sync/sun: + get: + summary: Sync the sunrise and sunset local time to all Shades + tags: + - HD Internal + responses: + '200': + description: Gateway Shade Time Information + content: + application/json: + schema: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + setSunTimes: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + setCurrentTime: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + /gateway/shades/time/sync/delays: + put: + summary: Override the factory set delay times + tags: + - HD Internal + parameters: + - name: persist + in: query + required: false + description: Boolean set to 'true' to make delay times sticky + schema: + type: boolean + example: true + - name: delayTimes + in: query + required: true + description: Delay times object + schema: + type: object + properties: + homeDocUpdateDelayMs: + type: number + shadesAddedDelayMs: + type: number + syncAllRetryDelayMs: + type: number + syncListRetryDelayMs: + type: number + syncInProgressDelayMs: + type: number + responses: + '200': + description: Shade Time Sync Manager Info + content: + application/json: + schema: + type: object + properties: + cachedHomeDocInfo: + type: object + properties: + gwId: + type: number + geoPoint: + type: object + properties: + latitude: + type: number + example: 29.9 + longitude: + type: number + example: -100 + tz: + type: string + example: America/Denver + localDstAdjustedOffset: + type: number + nextAllShadesSyncDate: + type: string + lastSuccessfulAllShadesSyncDate: + type: string + nextBleNamesSyncDate: + type: string + bleNamesNeedingSync: + type: array + items: + type: string + delayTimes: + type: object + properties: + homeDocUpdateDelayMs: + type: number + shadesAddedDelayMs: + type: number + syncAllRetryDelayMs: + type: number + syncListRetryDelayMs: + type: number + syncInProgressDelayMs: + type: number + syncInProgress: + type: boolean + delete: + summary: Restores the delay times to their factory defaults + tags: + - HD Internal + responses: + '200': + description: Shade Time Sync Manager Info + content: + application/json: + schema: + type: object + properties: + cachedHomeDocInfo: + type: object + properties: + gwId: + type: number + geoPoint: + type: object + properties: + latitude: + type: number + example: 29.9 + longitude: + type: number + example: -100 + tz: + type: string + example: America/Denver + localDstAdjustedOffset: + type: number + nextAllShadesSyncDate: + type: string + lastSuccessfulAllShadesSyncDate: + type: string + nextBleNamesSyncDate: + type: string + bleNamesNeedingSync: + type: array + items: + type: string + delayTimes: + type: object + properties: + homeDocUpdateDelayMs: + type: number + shadesAddedDelayMs: + type: number + syncAllRetryDelayMs: + type: number + syncListRetryDelayMs: + type: number + syncInProgressDelayMs: + type: number + syncInProgress: + type: boolean + /gateway/update: + get: + summary: Trigger a Gateway firmware update check + tags: + - Gateway + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/update/artifact-info: + get: + summary: Retrieve the Gateway's artifact information string + tags: + - Gateway + responses: + '200': + description: Build artifact information + content: + applicaiton/json: + schema: + type: object + properties: + artifact: + type: string + description: Detailed artifact information + example: gw_image-3.1.394-os.77add-ts.60717-hk.13c6a + required: + - artifact + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /gateway/update/channel: + get: + summary: Get the current Gateway firmware update channel + tags: + - Gateway + responses: + '200': + description: The current Gateway firmware update channel + content: + application/json: + schema: + type: object + properties: + channel: + type: string + description: The current Gateway firmware update channel + example: production + required: + - channel + put: + summary: Set the Gateway firmware update channel + tags: + - Gateway + parameters: + - name: channel + in: query + required: true + description: >- + The new update/upgrade channel, which must be one of: [ coredev, + nightly, qa, beta, production ]. The recommended value is + 'production' + schema: + type: string + example: qa + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /gateway/wifi: + put: + summary: Set Gateway Wifi parameters + tags: + - Gateway + requestBody: + description: Set Wifi Parameters + content: + application/json: + schema: + type: object + properties: + ssid: + type: string + description: The WiFi SSID + example: Woodland Hills + password: + type: string + description: The WiFi password. Must be 8..63 characters in length. + minLength: 8 + maxLength: 63 + format: password + example: password + required: + - ssid + - password + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + delete: + summary: Remove the Wifi credentials from the Gateway + tags: + - Gateway + responses: + '204': + description: Success, no content + /gateway/wifi/scan: + get: + summary: Retrieve the Wifi networks observable by the Gateway + tags: + - Gateway + parameters: + - name: delay + in: query + required: false + description: | + The number of seconds to scan before returning the results. + + Minimum is 3 seconds; Maximum is 20 seconds + schema: + type: integer + default: 10 + responses: + '200': + description: Wireless network scan list + content: + application/json: + schema: + type: object + properties: + ssidScanResults: + type: array + items: + type: object + description: Wireless network scan entry + properties: + ssid: + type: string + description: Wireless network name + example: HunterDouglasWiFi + rssi: + type: string + description: Wireless network RSSI value + example: '-81' + required: + - ssid + - rssi + required: + - ssidScanResults + /home: + get: + summary: >- + Get the entire home graph with all the Rooms, Shades, Scenes, + Automations, Gateways, and Remotes. + tags: + - HD Internal + responses: + '200': + description: Web HomeDoc Object + content: + application/json: + schema: + type: object + properties: + id: + type: string + _schemaVersion: + type: number + owner: + type: string + users?: + type: array + items: + type: string + modApp: + type: string + modDate: + type: string + home: + properties: + name: + title: Home.name + type: string + autosEnabled: + title: Home.autosEnabled + description: Are automations enabled globally + type: boolean + key: + title: Home.key + type: string + loc: + title: Home.loc + power: + title: Home.power + type: number + tz: + title: Home.tz + description: TimeZone - available in v24+ + type: string + required: + - name + - autosEnabled + additionalProperties: false + title: Home + type: object + rooms: + type: array + items: + type: object + properties: + id: + type: string + _id: + type: number + type: + type: number + name: + type: string + icon: + type: string + color: + type: string + shades: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter + Douglas use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's + capabilities. In PowerView Gen 3, + + there are over 20 different types of Hunter + Douglas Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, + all can be represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either + from the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot + operate independently - the + + front shade must be down before the rear shade + can deploy. In other cases, + + they are independent with two motors and two + tubes. Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - + there is no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom + up shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: >- + Approximate gauge of remaining Shade battery + power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: >- + Unique numerical identifier for a particular + Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully + open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully + open position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully + open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + scenes: + type: array + items: + properties: + id: + title: Scene.id + description: '@deprecated in v23' + type: string + _id: + title: Scene._id + type: number + name: + title: Scene.name + type: string + icon: + title: Scene.icon + type: string + color: + title: Scene.color + type: string + bleId: + title: Scene.bleId + type: number + modDate: + title: Scene.modDate + type: string + roomId: + title: Scene.roomId + description: '@deprecated in v23' + type: string + room_Id: + title: Scene.room_Id + type: number + members: + items: + properties: + id: + title: SceneMember.id + description: '@deprecated in v23' + type: string + _id: + title: SceneMember._id + type: number + pos: + title: SceneMember.pos + properties: + pos1: + title: ShadePosition.pos1 + type: number + pos2: + title: ShadePosition.pos2 + type: number + pos3: + title: ShadePosition.pos3 + type: number + tilt: + title: ShadePosition.tilt + type: number + vel: + title: ShadePosition.vel + type: number + required: + - pos1 + - pos2 + - pos3 + - tilt + - vel + additionalProperties: false + type: object + shdId: + title: SceneMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: SceneMember.shd_Id + type: number + required: + - id + - _id + - pos + - shdId + - shd_Id + additionalProperties: false + title: SceneMember + type: object + title: Scene.members + type: array + required: + - id + - _id + - name + - icon + - color + - bleId + - modDate + additionalProperties: false + title: Scene + type: object + automations: + type: array + items: + properties: + id: + title: Automation.id + description: '@deprecated in v23' + type: string + _id: + title: Automation._id + type: number + type: + title: Automation.type + type: number + enabled: + title: Automation.enabled + type: boolean + days: + title: Automation.days + type: number + hour: + title: Automation.hour + type: number + min: + title: Automation.min + type: number + bleId: + title: Automation.bleId + type: number + sceneId: + title: Automation.sceneId + description: '@deprecated in v23' + type: string + scene_Id: + title: Automation.scene_Id + type: number + errorShdIds: + items: + type: string + title: Automation.errorShdIds + description: '@deprecated in v23' + type: array + errorShd_Ids: + items: + type: number + title: Automation.errorShd_Ids + type: array + required: + - id + - _id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + - scene_Id + - errorShdIds + - errorShd_Ids + additionalProperties: false + title: Automation + type: object + remotes?: + type: array + items: + properties: + id: + title: Remote.id + description: '@deprecated in v23' + type: string + _id: + title: Remote._id + type: number + name: + title: Remote.name + type: string + v: + title: Remote.v + type: number + mac: + title: Remote.mac + type: string + bleName: + title: Remote.bleName + type: string + members: + items: + properties: + id: + title: RemoteMember.id + description: '@deprecated in v23' + type: string + _id: + title: RemoteMember._id + type: number + group: + title: RemoteMember.group + type: number + shdId: + title: RemoteMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: RemoteMember.shd_Id + type: number + required: + - id + - _id + - group + - shdId + - shd_Id + additionalProperties: false + title: RemoteMember + type: object + title: Remote.members + type: array + required: + - id + - _id + - name + - v + - mac + - bleName + additionalProperties: false + title: Remote + type: object + gateways: + type: array + items: + properties: + id: + title: Gateway.id + description: '@deprecated in v23' + type: string + _id: + title: Gateway._id + type: number + name: + title: Gateway.name + type: string + v: + title: Gateway.v + type: string + radio1V: + title: Gateway.radio1V + type: string + radio2V: + title: Gateway.radio2V + type: string + serial: + title: Gateway.serial + type: string + aux: + title: Gateway.aux + type: boolean + ip: + title: Gateway.ip + type: string + ssid: + title: Gateway.ssid + type: string + shdIds: + items: + type: string + title: Gateway.shdIds + description: '@deprecated in v23' + type: array + shd_Ids: + items: + type: number + title: Gateway.shd_Ids + type: array + required: + - id + - _id + - name + - v + - radio1V + - radio2V + - serial + - ip + - ssid + additionalProperties: false + title: Gateway + type: object + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/automations: + get: + summary: List the Automations for the Home + tags: + - Home + responses: + '200': + description: Web Automation List + content: + application/json: + schema: + type: array + items: + type: object + description: Web Automation Object + properties: + id: + type: number + description: Unique numerical Automation identifier + example: 33 + type: + type: number + description: | + Time-base for the automation + * 0 = Clock-based + * 2 = Before sunrise + * 6 = Before sunset + * 10 = After sunrise + * 14 = After sunset + example: 6 + enabled: + type: boolean + description: True indicates the Automation is enabled + example: true + days: + type: number + description: | + Bitmask of days when the automation is to run + * 0x00 = Reserved + * 0x01 = Monday + * 0x02 = Tuesday + * 0x04 = Wednesday + * 0x08 = Thursay + * 0x10 = Friday + * 0x20 = Saturday + * 0x40 = Sunday + * 0x80 = Reserved + example: 24 (i.e., 0x18, which is Thursday and Friday) + hour: + type: number + description: > + For clock-based automations, the 'hour' field is the + + exact hour the automation will occur. For sunrise & + sunset + + based automations, the 'hour' field is the hour offset + + before/after a sunrise/sunset automation is to run. + example: 4 + min: + type: number + description: > + For clock-based automations, the 'min' field is the + + exact min the automation will occur. For sunrise & + sunset + + based automations, the 'min' field is the minutes + offset + + before/after a sunrise/sunset automation is to run. + example: 5 + bleId: + type: number + description: The automation ID stored on the Shade itself. + example: 83 + sceneId: + type: number + description: >- + The unique numerical Scene identifier associated with + this Automation + example: 116 + errorShd_Ids: + type: array + description: >- + The Shade list where the Automation was unsuccessfully + provisioned. The value can be null + example: null + items: + type: number + description: The failing Shade identifier + example: 55 + required: + - id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/automations/{id}: + get: + summary: Get information for a Automation + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Automation + required: true + schema: + type: string + description: The numerical identifier for a particular Automation + example: 456 + responses: + '200': + description: Web Automation Object + content: + application/json: + schema: + type: object + description: Web Automation Object + properties: + id: + type: number + description: Unique numerical Automation identifier + example: 33 + type: + type: number + description: | + Time-base for the automation + * 0 = Clock-based + * 2 = Before sunrise + * 6 = Before sunset + * 10 = After sunrise + * 14 = After sunset + example: 6 + enabled: + type: boolean + description: True indicates the Automation is enabled + example: true + days: + type: number + description: | + Bitmask of days when the automation is to run + * 0x00 = Reserved + * 0x01 = Monday + * 0x02 = Tuesday + * 0x04 = Wednesday + * 0x08 = Thursay + * 0x10 = Friday + * 0x20 = Saturday + * 0x40 = Sunday + * 0x80 = Reserved + example: 24 (i.e., 0x18, which is Thursday and Friday) + hour: + type: number + description: > + For clock-based automations, the 'hour' field is the + + exact hour the automation will occur. For sunrise & + sunset + + based automations, the 'hour' field is the hour offset + + before/after a sunrise/sunset automation is to run. + example: 4 + min: + type: number + description: > + For clock-based automations, the 'min' field is the + + exact min the automation will occur. For sunrise & + sunset + + based automations, the 'min' field is the minutes offset + + before/after a sunrise/sunset automation is to run. + example: 5 + bleId: + type: number + description: The automation ID stored on the Shade itself. + example: 83 + sceneId: + type: number + description: >- + The unique numerical Scene identifier associated with + this Automation + example: 116 + errorShd_Ids: + type: array + description: >- + The Shade list where the Automation was unsuccessfully + provisioned. The value can be null + example: null + items: + type: number + description: The failing Shade identifier + example: 55 + required: + - id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/id: + get: + summary: Get the Cloud identifier of the Home + tags: + - Home + responses: + '200': + description: The cloud identifier of the Home + content: + application/json: + schema: + type: object + properties: + id: + type: string + description: The Home identifier + required: + - id + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/id/silent: + get: + summary: Get the Home Cloud identifier without logging the operation + tags: + - HD Internal + responses: + '200': + description: The cloud identifier of the Home + content: + application/json: + schema: + type: object + properties: + id: + type: string + description: The Home identifier + required: + - id + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/integration/{integrationName}: + put: + summary: >- + Store the supplied 'integrationName' in the HomeDoc's integrations + list + tags: + - Home + parameters: + - name: integrationName + in: path + description: >- + Unique 3rd party ASCII integration identifier that must be all + lower case, can be a maximum of 12 characters in length, and must + only contain the characters [a-z], [0-9], or the special + characters '.' (dot/period), '@', '_' (underscore) and '-' + (hyphen) + required: true + schema: + type: string + example: hd.com + responses: + '204': + description: Success, no content + delete: + summary: >- + Remove the supplied 'integrationName' from the HomeDoc's integrations + list + tags: + - Home + parameters: + - name: integrationName + in: path + description: >- + Unique 3rd party ASCII integration identifier that must be all + lower case, can be a maximum of 12 characters in length, and must + only contain the characters [a-z], [0-9], or the special + characters '.' (dot/period), '@', '_' (underscore) and '-' + (hyphen) + required: true + schema: + type: string + example: hd.com + responses: + '204': + description: Success, no content + /home/rooms: + get: + summary: List the Rooms for the Home + tags: + - Home + parameters: + - name: shades + in: query + description: >- + Optional query param to return Shades as part of the Room object. + Shades will not be returned if this query param is omitted or + false. + schema: + type: boolean + responses: + '200': + description: Web Room List + content: + application/json: + schema: + type: array + items: + type: object + description: Room information + properties: + id: + type: number + description: Unique numerical Room identifier + example: 674 + name: + type: string + description: Base64 encoded Room name + example: T2ZmaWNlCg== + ptName: + type: string + description: Room name + example: Office + color: + type: string + description: > + Unique identifier for a Room color from HomeDoc Room + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 669 + type: + type: number + description: Room type enumeration value + example: 3 + shades: + type: array + description: >- + Optional list of Shades in a Room, which can be an + empty list + example: [] + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter + Douglas use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's + capabilities. In PowerView Gen 3, + + there are over 20 different types of Hunter + Douglas Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all + can be represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either + from the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot + operate independently - the + + front shade must be down before the rear shade + can deploy. In other cases, + + they are independent with two motors and two + tubes. Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - + there is no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom + up shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: >- + Approximate gauge of remaining Shade battery + power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: >- + Unique numerical identifier for a particular + Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + required: + - id + - name + - ptName + - color + - icon + - type + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/rooms/{id}: + get: + summary: Get information for a Room + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Room + required: true + schema: + type: string + description: The numerical identifier for a particular Room + example: 2 + responses: + '200': + description: Web Room Object + content: + application/json: + schema: + type: object + description: Room information + properties: + id: + type: number + description: Unique numerical Room identifier + example: 674 + name: + type: string + description: Base64 encoded Room name + example: T2ZmaWNlCg== + ptName: + type: string + description: Room name + example: Office + color: + type: string + description: > + Unique identifier for a Room color from HomeDoc Room + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 669 + type: + type: number + description: Room type enumeration value + example: 3 + shades: + type: array + description: >- + Optional list of Shades in a Room, which can be an empty + list + example: [] + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter + Douglas use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. + In PowerView Gen 3, + + there are over 20 different types of Hunter + Douglas Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all + can be represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either + from the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot + operate independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two + tubes. Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - there + is no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up + shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + required: + - id + - name + - ptName + - color + - icon + - type + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/scenes: + get: + summary: List the Scenes for the Home + tags: + - Home + responses: + '200': + description: Web Scene List + content: + application/json: + schema: + type: array + items: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated + with this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/scenes/active: + get: + summary: List the active Scenes for the Home + tags: + - Home + responses: + '200': + description: Web Scene List + content: + application/json: + schema: + type: array + items: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated + with this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/scenes/{id}: + get: + summary: Get information for a Scene + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Scene + required: true + schema: + type: string + description: The numerical identifier for a particular Scene + example: 22 + responses: + '200': + description: Web Scene Object + content: + application/json: + schema: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated + with this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + '404': + description: The resource was not found + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/scenes/{id}/activate: + put: + summary: Activate a particular Scene in the Home + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Scene + required: true + schema: + type: string + description: The numerical identifier for a particular Scene + example: 22 + responses: + '200': + description: List of Shade identifiers associated with a Scene + content: + application/json: + schema: + type: array + description: Array of numerical Shade identifiers + example: + - 22 + - 33 + - 44 + items: + type: number + '404': + description: The resource was not found + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades: + get: + summary: List the Shades for the Home + tags: + - Home + responses: + '200': + description: Web Shade List + content: + application/json: + schema: + type: array + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas + use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas + Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from + the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two tubes. + Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - there is + no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up + shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open position of the + primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open position of the + secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/{id}: + get: + summary: Get information for a Shade + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Shade + required: true + schema: + type: string + description: The numerical identifier for a particular Shade + example: 21 + responses: + '200': + description: Web Shade Object + content: + application/json: + schema: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas use + only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas + Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the + bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two tubes. + Where they are + + dependent, the shade firmware will force the appropriate + front shade + + position when the rear shade is controlled - there is no + need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade + that also tilts plus a rear blackout (non-tilting) + shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/{id}/motion: + put: + summary: Perform the specified motion operation for a Shade + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Shade + required: true + schema: + type: string + description: The numerical identifier for a particular Shade + example: 21 + requestBody: + description: Shade motion command + content: + application/json: + schema: + type: object + properties: + motion: + description: Motion command + type: string + enum: + - jog + example: jog + required: + - motion + responses: + '200': + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/{id}/positions: + put: + summary: Set the positions for a Shade + deprecated: true + tags: + - Home + parameters: + - name: id + in: path + description: Numerical identifier of the Shade + required: true + schema: + type: string + description: The numerical identifier for a particular Shade + example: 21 + requestBody: + description: Shade positions command + content: + application/json: + schema: + type: object + properties: + positions: + type: object + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the primary + rail. When omitted, the position of the primary rail + is not changed. + minimum: 0 + maximum: 1 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that the represents + fully closed to fully open position of the secondary + rail. When omitted, the position of the secondary + rail. is not changed. + minimum: 0 + maximum: 1 + servo3: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the third rail. + When omitted, the position of the third rail is not + changed. + minimum: 0 + maximum: 1 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open tilt position When omitted, + the tilt position is not changed. + minimum: 0 + maximum: 1 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + minimum to maximum velocity of the shade motion. When + omitted, the default velocity is used. + minimum: 0 + maximum: 1 + required: + - positions + examples: + Open: + value: '{"positions": { "primary" : 1}}' + summary: Open Shade(s) - 100% light transmission + Close: + value: '{"positions": { "primary" : 0}}' + summary: Close Shade(s) - 0% light transmission + TiltOpen: + value: '{"positions": { "tilt" : 1}}' + summary: Tilt Open Shade(s) + TiltClose: + value: '{"positions": { "tilt" : 0}}' + summary: Tilt Close Shade(s) + Goto25Percent: + value: '{"positions": { "primary" : 0.25} }' + summary: Move primary rail to 25% light transmission + responses: + '200': + description: Shade event + content: + text/event-stream: + schema: + type: object + description: Shade event + properties: + evt: + type: string + description: Event name + enum: + - shade-offline + - shade-online + - motion-started + - motion-stopped + - battery-alert + example: motion-started + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + bleName: + type: string + description: Shade name + example: PIR:1233 + id: + type: number + description: Unique Shade identifier + example: 55 + currentPositions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + targetPositions: + type: object + description: > + Optional target Shade position values and estimate + completion time + + that may only present when the Event name is + 'motion-started'. + + The property may be omitted even with the Event + 'motion-started' + + if the values cannot be obtained or computed + properties: + etaInSeconds: + type: number + description: >- + Estimated time in seconds for the Shade to reach its + target positions + example: 7 + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + required: + - evt + - isoDate + - bleName + - id + - currentPositions + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/exec: + post: + summary: >- + Execute an arbitrary hexadecimal command on a list of shades (For + Hunter Douglas internal use only) + description: >- + The list of Shades is specified by either of the "ids" or "shades" + parameters. Only one of these should and must be utilized. + + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + tags: + - HD Internal + parameters: + - name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + - name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + requestBody: + description: Hexadecimal representation of a Shade command + content: + application/json: + schema: + type: object + properties: + hex: + type: string + description: Hex Shade command + example: f711990101 + required: + - hex + responses: + '200': + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/positions: + put: + summary: Set the positions of a Shade or set of Shades + description: >- + The list of Shades is specified by either of the "ids" or "shades" + parameters. Only one of these should and must be utilized. + + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + tags: + - Home + parameters: + - name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + - name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + requestBody: + description: Shade positions command + content: + application/json: + schema: + type: object + properties: + positions: + type: object + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the primary + rail. When omitted, the position of the primary rail + is not changed. + minimum: 0 + maximum: 1 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that the represents + fully closed to fully open position of the secondary + rail. When omitted, the position of the secondary + rail. is not changed. + minimum: 0 + maximum: 1 + servo3: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the third rail. + When omitted, the position of the third rail is not + changed. + minimum: 0 + maximum: 1 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open tilt position When omitted, + the tilt position is not changed. + minimum: 0 + maximum: 1 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + minimum to maximum velocity of the shade motion. When + omitted, the default velocity is used. + minimum: 0 + maximum: 1 + required: + - positions + examples: + Open: + value: '{"positions": { "primary" : 1}}' + summary: Open Shade(s) - 100% light transmission + Close: + value: '{"positions": { "primary" : 0}}' + summary: Close Shade(s) - 0% light transmission + TiltOpen: + value: '{"positions": { "tilt" : 1}}' + summary: Tilt Open Shade(s) + TiltClose: + value: '{"positions": { "tilt" : 0}}' + summary: Tilt Close Shade(s) + Goto25Percent: + value: '{"positions": { "primary" : 0.25} }' + summary: Move primary rail to 25% light transmission + responses: + '200': + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/stop: + put: + summary: Stop any current motion on a given list of Shades + description: >- + The list of Shades is specified by either of the "ids" or "shades" + parameters. Only one of these should and must be utilized. + + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + tags: + - Home + parameters: + - name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + - name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + responses: + '200': + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/time: + get: + summary: Get the clock time from the Shade for the given list of Shades + description: >- + The list of Shades is specified by either of the "ids" or "shades" + parameters. Only one of these should and must be utilized. + + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + tags: + - Home + parameters: + - name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + - name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + responses: + '200': + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + put: + summary: Update the Shade clock time to now for the given list of Shades + description: >- + The list of Shades is specified by either of the "ids" or "shades" + parameters. Only one of these should and must be utilized. + + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + tags: + - Home + parameters: + - name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + - name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + responses: + '200': + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '503': + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/events: + get: + summary: >- + Provides an aggregate stream of ALL events via server-sent events + (SSE). + description: This event stream does not work in Swagger. Use the Chrome browser + tags: + - Events + responses: + '100': + description: > + Stream of JSON Scene and Shade event objects. + + + See the /home/scenes/events and /home/shades/events APIs for + object shapes + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/events/listeners: + get: + summary: Returns a list of all active event stream listeners + tags: + - HD Internal + responses: + '200': + description: List of Event Listeners + content: + application/json: + schema: + type: object + properties: + slots: + type: array + items: + type: string + activeListeners: + type: array + items: + type: string + required: + - slots + - activeListeners + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + delete: + summary: Deletes all active event stream listeners + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/scenes/events: + get: + summary: Provides a stream of Shade events via server-sent events (SSE). + description: >- + This event stream does not work in Swagger. Use the Chrome browser. + Scene events are not reported until Shade motion stops + tags: + - Events + responses: + '100': + description: Stream of JSON Scene event objects + content: + text/event-stream: + schema: + type: object + description: Scene event + properties: + evt: + type: string + description: Event name + enum: + - scene-add + - scene-del + - scene-activated + - scene-deactivated + example: scene-activated + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + id: + type: number + description: Unique Scene identifier + example: 55 + scene: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc + Scene object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: > + Unique identifier for a icon from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated + with this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + required: + - evt + - isoDate + - id + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /home/shades/events: + get: + summary: Provides a stream of Shade events via server-sent events (SSE). + description: This event stream does not work in Swagger. Use the Chrome browser + tags: + - Events + responses: + '100': + description: Shade event + content: + text/event-stream: + schema: + type: object + description: Shade event + properties: + evt: + type: string + description: Event name + enum: + - shade-offline + - shade-online + - motion-started + - motion-stopped + - battery-alert + example: motion-started + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + bleName: + type: string + description: Shade name + example: PIR:1233 + id: + type: number + description: Unique Shade identifier + example: 55 + currentPositions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + targetPositions: + type: object + description: > + Optional target Shade position values and estimate + completion time + + that may only present when the Event name is + 'motion-started'. + + The property may be omitted even with the Event + 'motion-started' + + if the values cannot be obtained or computed + properties: + etaInSeconds: + type: number + description: >- + Estimated time in seconds for the Shade to reach its + target positions + example: 7 + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + required: + - evt + - isoDate + - bleName + - id + - currentPositions + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /sps/channels/check: + get: + summary: SPS only - Verifies the SPS comms channels by sending echo messages + tags: + - HD Internal + responses: + '200': + description: >- + Comms channels that are offline, and an empty array means all + operational + content: + application/json: + schema: + type: object + properties: + failedChannels: + type: array + items: + type: string + description: name of downed channel + example: comms01 + required: + - failedChannels + /sps/comms/log/level: + put: + summary: SPS only - Sets the comms layer log level + tags: + - HD Internal + parameters: + - name: level + in: query + required: true + description: >- + The new log level, which must be one of: none, error, warn, info, + debug, or silly. The recommended value is info. + schema: + type: string + example: debug + - name: persist + in: query + required: false + description: >- + If the new log level is to persist (be sticky) across application + restarts. Values are string 'true' or 'false' + schema: + type: string + example: 'true' + responses: + '200': + description: Comms set log level response + content: + application/json: + schema: + type: object + properties: + responseIsOk: + type: boolean + description: The log level set was successful or not + returnedLogLevel: + type: number + description: >- + The new log level. 0=none, 1=error, 2=warn, 3=info, + 4=debug, 5=silly + returnedPersist: + type: boolean + description: The new persistence setting + required: + - responseIsOk + - returnedLogLevel + - returnedPersist + /sps/shades/comparison: + get: + summary: >- + SPS only - Compare the HomeDoc SPS PV+ Shades list against the actual + SPS PV+ Shades + tags: + - HD Internal + responses: + '200': + description: HomeDoc vs actual PV+ Shade comparison results + content: + application/json: + schema: + type: object + properties: + perfectMatch: + type: boolean + description: >- + Indicates if the HomeDoc and the SPS are perfectly + matched + differences: + type: object + spsHomeDocShades: + type: array + items: + type: object + description: Unique Shade information + properties: + bleName: + type: string + description: Shade BleName + example: SON:1234 + required: + - bleName + spsActualShades: + type: array + items: + type: object + description: Unique Shade information + properties: + bleName: + type: string + description: Shade BleName + example: SON:1234 + required: + - bleName + required: + - perfectMatch + - differences + - spsHomeDocShades + - spsActualShades + /sps/shades/enumerated: + get: + summary: SPS only - Returns the list of PV+ Shades on an SPS + tags: + - HD Internal + responses: + '200': + description: PV+ Shades found on the SPS + content: + application/json: + schema: + type: array + items: + type: object + description: SPS port object + properties: + port: + type: number + description: Port/channel number from 1 to 16 inclusive + example: 1 + shades: + type: array + description: Information about PV+ Shades on this port + items: + type: object + description: SPS Shade description + properties: + slot: + type: number + description: >- + Shade port/channel number between 0 and 2 + inclusive + example: 1 + rssi: + type: number + description: Perfect RSSI value + example: -1 + ready: + type: number + description: Shade is ready + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the + version in the release. Time to do a upgrade + example: false + required: + - slot + - rssi + - ready + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + required: + - port + - shades + /sps/shades/exec: + post: + summary: >- + SPS only - Execute an arbitrary hexadecimal command on a list of SPS + Shades (For Hunter Douglas internal use only) + description: >- + The list of Shades is specified by one of the following: + "coordinates", "ids", or "shades" parameters. Only one of these should + and must be utilized. + + - The ``coordinates`` parameter accepts a comma seperated list of channel:slot coordinates like ``1:0`` + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + tags: + - HD Internal + parameters: + - name: coordinates + in: query + required: false + description: > + One or more Shade "channel:slot" coordinate pairs with each pair + separated by a comma + * The "channel" value is an integer in the range from 1 to 16 + * The "slot" value is an integer in the range of 0 to 2 + * The "channel" and "slot" pair values are separated by a colon character (i.e., a ':' character) + schema: + type: array + items: + type: string + style: form + explode: false + example: 1:0,2:1,14:2 + - name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + - name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + - name: failUnresolved + in: query + description: >- + Query param controlling if the request is to fail if any of the + coorinates query parameter pairs fail to resolve to a Shade + required: false + schema: + type: boolean + requestBody: + description: Hexadecimal representation of a Shade command + content: + application/json: + schema: + type: object + properties: + hex: + type: string + description: Hex Shade command + example: f711990101 + required: + - hex + responses: + '200': + description: >- + Aggregate response with status for each requested Shade and + optionally a list of unresolvedCoordinates + content: + application/json: + schema: + type: object + properties: + err: + type: number + unresolvedCoordinates: + type: array + description: Any coordinate pairs that could not be resolved + items: + type: string + description: A unresolved coordinate pair + example: '1:2' + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + '400': + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + default: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + /sps/pca/upgrade: + get: + summary: >- + SPS only - Upgrade the Shade PCA modules using the built in binary + image + tags: + - HD Internal + responses: + '200': + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + /sps/pca/versions: + get: + summary: SPS only - Retrieve the Shade PCA modules version information + tags: + - HD Internal + responses: + '200': + description: List of SPS PV+ Shade PCA versions + content: + application/json: + schema: + type: array + description: List of channels containing arrays of PV+ Shades + items: + type: array + description: >- + PCA information for a list of PV+ Shades on a single + channel + items: + type: object + description: SPS PCA version information + properties: + slot: + type: number + description: Shade port/channel number between 0 and 2 inclusive + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the version + in the release. Time to do a upgrade + example: false + required: + - slot + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + components: + parameters: + RoomShades: + name: shades + in: query + description: >- + Optional query param to return Shades as part of the Room object. + Shades will not be returned if this query param is omitted or false. + schema: + type: boolean + AutomationId: + name: id + in: path + description: Numerical identifier of the Automation + required: true + schema: + type: string + description: The numerical identifier for a particular Automation + example: 456 + AutomationEnable: + name: enable + in: query + description: >- + Query param to enable or disable a Automation. 'true' enables. 'false' + disables + required: true + schema: + type: boolean + FailUnresolved: + name: failUnresolved + in: query + description: >- + Query param controlling if the request is to fail if any of the + coorinates query parameter pairs fail to resolve to a Shade + required: false + schema: + type: boolean + IntegrationName: + name: integrationName + in: path + description: >- + Unique 3rd party ASCII integration identifier that must be all lower + case, can be a maximum of 12 characters in length, and must only + contain the characters [a-z], [0-9], or the special characters '.' + (dot/period), '@', '_' (underscore) and '-' (hyphen) + required: true + schema: + type: string + example: hd.com + RoomId: + name: id + in: path + description: Numerical identifier of the Room + required: true + schema: + type: string + description: The numerical identifier for a particular Room + example: 2 + SceneId: + name: id + in: path + description: Numerical identifier of the Scene + required: true + schema: + type: string + description: The numerical identifier for a particular Scene + example: 22 + ShadeId: + name: id + in: path + description: Numerical identifier of the Shade + required: true + schema: + type: string + description: The numerical identifier for a particular Shade + example: 21 + ShadeCoordinateList: + name: coordinates + in: query + required: false + description: > + One or more Shade "channel:slot" coordinate pairs with each pair + separated by a comma + * The "channel" value is an integer in the range from 1 to 16 + * The "slot" value is an integer in the range of 0 to 2 + * The "channel" and "slot" pair values are separated by a colon character (i.e., a ':' character) + schema: + type: array + items: + type: string + style: form + explode: false + example: 1:0,2:1,14:2 + ShadeNameList: + name: shades + in: query + required: false + description: One or more Shade names (i.e., BleNames) separated by commas + schema: + type: array + items: + type: string + style: form + explode: false + example: SON:1234,PIR:9AE2 + ShadeIdList: + name: ids + in: query + required: false + description: | + One or more Shade identifiers separated by commas. + * _**Preferred over the 'shades' query parameter**_ + * _Note: Shade identifiers remain constant in the eventuality of a motor replacement_ + schema: + type: array + items: + type: number + style: form + explode: false + example: 12,42,133 + requestBodies: + CloudConfig: + description: Parameters for connection to the Cloud database + required: true + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to access + the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + DiscoveryMinRssi: + description: Minimum RSSI filter + required: false + content: + application/json: + schema: + type: object + properties: + rssiMinValue: + type: number + description: Mimimum RSSI value + example: -66 + required: + - rssiMinValue + Hexadecimal: + description: Hexadecimal representation of a Shade command + content: + application/json: + schema: + type: object + properties: + hex: + type: string + description: Hex Shade command + example: f711990101 + required: + - hex + LedColor: + description: The color and brightness of the Gateway LED + content: + application/json: + schema: + description: The Gateway LED color and brightness + type: object + properties: + red: + type: number + description: Red + maximum: 0 + minimum: 255 + green: + type: number + description: Green + maximum: 0 + minimum: 255 + blue: + type: number + description: Blue + maximum: 0 + minimum: 255 + brightness: + type: number + description: Brightness + maximum: 0 + minimum: 100 + required: + - red + - green + - blue + - brightness + NetworkConfig: + description: Update the network configuration + content: + application/json: + schema: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information is to be + applied. The below staticIp object is optional if + staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present in its + entirety. If staticIpEnabled is false, this object may be + present and if present, it must be fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: The subnet mask to apply to the static IP address value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address to utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + Motion: + description: Shade motion command + content: + application/json: + schema: + type: object + properties: + motion: + description: Motion command + type: string + enum: + - jog + example: jog + required: + - motion + Positions: + description: Shade positions command + content: + application/json: + schema: + type: object + properties: + positions: + type: object + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the primary rail. + When omitted, the position of the primary rail is not + changed. + minimum: 0 + maximum: 1 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that the represents + fully closed to fully open position of the secondary + rail. When omitted, the position of the secondary rail. + is not changed. + minimum: 0 + maximum: 1 + servo3: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the third rail. + When omitted, the position of the third rail is not + changed. + minimum: 0 + maximum: 1 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open tilt position When omitted, + the tilt position is not changed. + minimum: 0 + maximum: 1 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + minimum to maximum velocity of the shade motion. When + omitted, the default velocity is used. + minimum: 0 + maximum: 1 + required: + - positions + examples: + Open: + value: '{"positions": { "primary" : 1}}' + summary: Open Shade(s) - 100% light transmission + Close: + value: '{"positions": { "primary" : 0}}' + summary: Close Shade(s) - 0% light transmission + TiltOpen: + value: '{"positions": { "tilt" : 1}}' + summary: Tilt Open Shade(s) + TiltClose: + value: '{"positions": { "tilt" : 0}}' + summary: Tilt Close Shade(s) + Goto25Percent: + value: '{"positions": { "primary" : 0.25} }' + summary: Move primary rail to 25% light transmission + PositionSingular: + description: Shade position command + content: + application/json: + schema: + type: object + properties: + position: + type: object + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the primary rail. + When omitted, the position of the primary rail is not + changed. + minimum: 0 + maximum: 1 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 that the represents + fully closed to fully open position of the secondary + rail. When omitted, the position of the secondary rail. + is not changed. + minimum: 0 + maximum: 1 + servo3: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open position of the third rail. + When omitted, the position of the third rail is not + changed. + minimum: 0 + maximum: 1 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + fully closed to fully open tilt position When omitted, + the tilt position is not changed. + minimum: 0 + maximum: 1 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 that represents the + minimum to maximum velocity of the shade motion. When + omitted, the default velocity is used. + minimum: 0 + maximum: 1 + required: + - position + examples: + Open: + value: '{"position": { "primary" : 1}}' + summary: Open Shade(s) - 100% light transmission + Close: + value: '{"position": { "primary" : 0}}' + summary: Close Shade(s) - 0% light transmission + TiltOpen: + value: '{"position": { "tilt" : 1}}' + summary: Tilt Open Shade(s) + TiltClose: + value: '{"position": { "tilt" : 0}}' + summary: Tilt Close Shade(s) + Goto25Percent: + value: '{"position": { "primary" : 0.25} }' + summary: Move primary rail to 25% light transmission + ProvisionWifi: + description: Set Wifi Parameters + content: + application/json: + schema: + type: object + properties: + ssid: + type: string + description: The WiFi SSID + example: Woodland Hills + password: + type: string + description: The WiFi password. Must be 8..63 characters in length. + minLength: 8 + maxLength: 63 + format: password + example: password + required: + - ssid + - password + responses: + ArtifactInfo: + description: Build artifact information + content: + applicaiton/json: + schema: + type: object + properties: + artifact: + type: string + description: Detailed artifact information + example: gw_image-3.1.394-os.77add-ts.60717-hk.13c6a + required: + - artifact + AggregateResponse: + description: Aggregate response with status for each requested Shade + content: + application/json: + schema: + type: object + properties: + err: + type: number + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + AggregateResponseSpsTestExtended: + description: >- + Aggregate response with status for each requested Shade and optionally + a list of unresolvedCoordinates + content: + application/json: + schema: + type: object + properties: + err: + type: number + unresolvedCoordinates: + type: array + description: Any coordinate pairs that could not be resolved + items: + type: string + description: A unresolved coordinate pair + example: '1:2' + responses: + type: array + items: + type: object + properties: + id: + type: number + bleName: + type: string + err: + description: Only present on error condition + type: number + hex: + description: >- + WC-API encoded response. Only present on success + condition + type: string + required: + - id + - bleName + required: + - err + - responses + CloudConfig: + description: The Gateway Cloud configuration + content: + application/json: + schema: + type: object + description: >- + Cloud configuration information used by the Gateway to access + the Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: >- + Numerical identifier of the Gateway as registered in the + Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, + Production = 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + ConnectionTest: + description: Conformation of internet connection + content: + application/json: + schema: + type: object + properties: + HealthCheckResponse: + type: object + properties: + success: + type: boolean + type: + type: string + message: + type: string + required: + - success + - type + - message + required: + - HealthCheckResponse + DiscoveryShadeList: + description: List of discovered Shades + content: + application/json: + schema: + type: object + properties: + scan: + type: array + description: Shades discovered List + items: + type: object + description: Discovered Shade entry + properties: + bleName: + type: string + description: Shade name + example: PIR:1E37 + filteredRssi: + type: number + description: Shade RSSI + example: -37 + required: + - bleName + - filteredRssi + required: + - scan + GatewayConfig: + description: The Gateway information object + content: + application/json: + schema: + type: object + properties: + config: + properties: + rev: + title: Config.rev + description: Config data structure version + type: number + hwVersion: + title: Config.hwVersion + description: Hardware version + type: string + model: + title: Config.model + description: Hardware model + type: string + brand: + title: Config.brand + description: Hardware brand + type: string + serialNumber: + title: Config.serialNumber + description: Unique serial number across all products + type: string + firmware: + title: Config.firmware + description: Software version + properties: + mainProcessor: + title: BuildVersions.mainProcessor + description: Version number + properties: + build: + title: TypescriptAppBuildInfo.build + description: Build number + type: number + name: + title: TypescriptAppBuildInfo.name + description: '???' + type: string + revision: + title: TypescriptAppBuildInfo.revision + description: Major version number + type: number + subRevision: + title: TypescriptAppBuildInfo.subRevision + description: Minor version number + type: number + required: + - build + - name + - revision + - subRevision + additionalProperties: false + type: object + radios: + items: + title: BuildVersions.radios.[] + properties: + build: + title: TransceiverFirmwareBuildInfo.build + description: Build number + type: number + revision: + title: TransceiverFirmwareBuildInfo.revision + description: Major version number + type: number + subRevision: + title: TransceiverFirmwareBuildInfo.subRevision + description: Minor version number + type: number + required: + - build + - revision + - subRevision + additionalProperties: false + description: Transceiver/Radio firmware information + type: object + title: BuildVersions.radios + description: Transceiver/Radio firmware versions + type: array + required: + - mainProcessor + - radios + additionalProperties: false + type: object + homeAssoc: + title: Config.homeAssoc + description: >- + 2-byte Hash of the HomeSecurityKey (AKA: + ShadeSecurityKey) + type: number + color: + title: Config.color + description: >- + User idle color - the color the user chose for the Idle + state + properties: + brightness: + title: LedColor.brightness + description: LED brightness percentage between 0 and 100 + type: number + red: + title: LedColor.red + description: Red color value between 0 and 255 + type: number + green: + title: LedColor.green + description: Green color value between 0 and 255 + type: number + blue: + title: LedColor.blue + description: Blue color value between 0 and 255 + type: number + required: + - brightness + - red + - green + - blue + additionalProperties: false + type: object + cloudConfig: + title: Config.cloudConfig + properties: + cloudEnv: + title: FirestoreConfig.cloudEnv + description: >- + What cloud environment to access (i.e, what + credentials to load) + type: number + collection: + title: FirestoreConfig.collection + description: Cloud collection name for homeDocs + type: string + homeId: + title: FirestoreConfig.homeId + description: Home identifier for this household + type: string + gatewayId: + title: FirestoreConfig.gatewayId + description: Gateway id for THIS gateway + type: number + required: + - cloudEnv + - collection + - homeId + - gatewayId + additionalProperties: false + description: >- + Cloud Config + + The properties required to uniquely identify a Home and + Gateway pairing. + type: object + rangeMapper: + title: Config.rangeMapper + description: Radio scan information + properties: + minRSSI: + title: RangeMapperDb.minRSSI + description: The minimum RSSI (of Shades) to report back on + type: number + levelingSeconds: + title: RangeMapperDb.levelingSeconds + description: >- + The number of seconds over that the algorithm + averages over + type: number + required: + - minRSSI + - levelingSeconds + additionalProperties: false + type: object + networkConfig: + title: Config.networkConfig + description: Persistent network configuration + properties: + staticIpEnabled: + title: NetworkConfig.staticIpEnabled + description: Is static IP configuration enabled? + type: boolean + staticIp: + properties: + ip_address: + title: NetworkConfig.staticIp.ip_address + description: Static IP address + type: string + netmask: + title: NetworkConfig.staticIp.netmask + description: Static IP network mask + type: string + gateway_ip: + title: NetworkConfig.staticIp.gateway_ip + description: Home gateway IP address (i.e., the home router + type: string + dns: + items: + type: string + title: NetworkConfig.staticIp.dns + description: DNS IP values + type: array + required: + - ip_address + - netmask + - gateway_ip + - dns + additionalProperties: false + title: NetworkConfig.staticIp + description: Static IP values if enabled + type: object + required: + - staticIpEnabled + - staticIp + additionalProperties: false + type: object + networkStatus: + title: Config.networkStatus + description: Transient network information + properties: + ipAddress: + title: NetworkStatus.ipAddress + description: Currently active IP address + type: string + activeInterface: + title: NetworkStatus.activeInterface + description: Current active network interface + type: string + primaryMacAddress: + title: NetworkStatus.primaryMacAddress + description: Primary MAC address to identify device + type: string + dns: + items: + type: string + title: NetworkStatus.dns + description: DNS entries + type: array + eth0: + title: NetworkStatus.eth0 + description: Wired network interface information + wlan0: + title: NetworkStatus.wlan0 + description: Wireless network interface information + internetState: + title: NetworkStatus.internetState + description: Internet connectivity state + type: string + enum: + - Connected + - Disconnected + ssid: + title: NetworkStatus.ssid + description: Wireless SSID + type: string + required: + - ipAddress + - activeInterface + - primaryMacAddress + - dns + - eth0 + - wlan0 + - internetState + - ssid + additionalProperties: false + type: object + mgwConfig: + title: Config.mgwConfig + description: Persistent multi-gateway configuration + properties: + primary: + title: MultiGatewayConfig.primary + description: This gateway is the primary in multi-gateway + type: boolean + required: + - primary + additionalProperties: false + type: object + mgwStatus: + title: Config.mgwStatus + description: Transient multi-gateway information + properties: + running: + title: MultiGatewayStatus.running + description: Multi-gateway is operational + type: boolean + required: + - running + additionalProperties: false + type: object + required: + - rev + - hwVersion + - model + - brand + - serialNumber + - firmware + - homeAssoc + - color + - cloudConfig + - rangeMapper + - networkConfig + - networkStatus + - mgwConfig + - mgwStatus + additionalProperties: false + title: Config + type: object + GatewayBalancer: + description: The Gateway balancer information object + content: + application/json: + schema: + type: object + properties: + maxShadesPerChannel: + type: number + seqNum: + type: number + balancingAlg: + type: string + example: 0 = BALANCE_BY_GROUP + transactionNum: + type: number + GatewayInfo: + description: Limited information about the Gateway + content: + application/json: + schema: + type: object + properties: + fwVersion: + type: string + description: Gateway firmware version string + example: 3.1.376 + serialNumber: + type: string + description: Gateway serial number + example: 3b4149d4f24d7bd7 + required: + - fwVersion + - serialNumber + GatewayRadios: + description: Gateway radios + content: + application/json: + schema: + properties: + serialNum: + type: string + appVersion: + type: string + softdeviceVersion: + type: string + bootloaderVersion: + type: string + type: object + GatewayRadioShades: + description: Gateway radio shades + content: + application/json: + schema: + type: array + items: + type: array + items: + type: object + properties: + index: + type: number + rssi: + type: number + example: -256 + ready: + type: number + example: 1 + bleName: + type: string + mac: + type: string + GatewayFabInfo: + description: Gateway Fab Info response + content: + application/json: + schema: + type: object + properties: + shadesFabInfoAllShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + shadesFabInfoLocalShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + cachedPrimary: + type: boolean + periodicRequesterTimerNextRunTime: + type: string + GatewayFabInfoPut: + description: Gateway Fab Info response + content: + application/json: + schema: + type: object + properties: + shadesFabInfoAllShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + shadesFabInfoLocalShades: + type: array + items: + type: object + properties: + bleName: + type: string + id: + type: number + appIndex: + type: number + modelId: + type: number + sourceGwName: + type: string + shadeLengthTickCnt: + type: number + periodicCheckIntervalMs: + type: number + periodicCheckTimerNextRunTime: + type: string + cachedPrimary: + type: boolean + periodicRequesterTimerNextRunTime: + type: string + GatewayShadeTime: + description: Gateway Shade Time Information + content: + application/json: + schema: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + setSunTimes: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + setCurrentTime: + type: object + properties: + err: + type: number + errMsg: + type: string + example: '' + successfullyUpdated: + type: array + items: + type: string + failedToUpdate: + type: array + items: + type: string + GatewayShadeTimeInfo: + description: Shade Time Sync Manager Info + content: + application/json: + schema: + type: object + properties: + cachedHomeDocInfo: + type: object + properties: + gwId: + type: number + geoPoint: + type: object + properties: + latitude: + type: number + example: 29.9 + longitude: + type: number + example: -100 + tz: + type: string + example: America/Denver + localDstAdjustedOffset: + type: number + nextAllShadesSyncDate: + type: string + lastSuccessfulAllShadesSyncDate: + type: string + nextBleNamesSyncDate: + type: string + bleNamesNeedingSync: + type: array + items: + type: string + delayTimes: + type: object + properties: + homeDocUpdateDelayMs: + type: number + shadesAddedDelayMs: + type: number + syncAllRetryDelayMs: + type: number + syncListRetryDelayMs: + type: number + syncInProgressDelayMs: + type: number + syncInProgress: + type: boolean + HomedocRooms: + description: The rooms in the Home + content: + application/json: + schema: + type: array + items: + properties: + id: + title: Room.id + description: '@deprecated in v23' + type: string + _id: + title: Room._id + type: number + type: + title: Room.type + type: number + name: + title: Room.name + type: string + icon: + title: Room.icon + type: string + color: + title: Room.color + type: string + shades: + items: + properties: + id: + title: Shade.id + description: '@deprecated in v23' + type: string + _id: + title: Shade._id + type: number + name: + title: Shade.name + type: string + v: + title: Shade.v + type: number + index: + title: Shade.index + type: number + serial: + title: Shade.serial + type: string + mac: + title: Shade.mac + type: string + bleName: + title: Shade.bleName + type: string + power: + title: Shade.power + type: number + modelId: + title: Shade.modelId + type: number + required: + - id + - _id + - name + - v + - index + - serial + - mac + - bleName + additionalProperties: false + title: Shade + type: object + title: Room.shades + type: array + required: + - id + - _id + - type + - name + - icon + - color + additionalProperties: false + title: Room + type: object + HomeId: + description: The cloud identifier of the Home + content: + application/json: + schema: + type: object + properties: + id: + type: string + description: The Home identifier + required: + - id + HomeKit: + description: HomeKit information + content: + application/json: + schema: + type: object + properties: + hapBridge: + type: object + properties: + pid: + type: number + connected: + type: boolean + exitCode: + type: string + killed: + type: boolean + started: + type: string + lastStoppedEvent: + type: string + stoppedMessage: + type: string + respawnDisabled: + type: boolean + debugEnabled: + type: boolean + closeEvents: + type: array + items: + type: string + lastAID: + type: number + accessoryMap: + type: object + HomeKitSetup: + description: The HomeKit setup data + content: + application/json: + schema: + type: object + properties: + setupCode: + type: string + example: 383-67-992 + setupPayload: + type: string + example: X-HM://0E38KYF3CHSCC03FBKDP6RPW4CM4J5S + required: + - setupCode + - setupPayload + InfoKnownMissingGateways: + description: Known and missing Gateways + content: + application/json: + schema: + type: object + properties: + known: + type: object + description: Known HomeDoc Gateway identifier + additionalProperties: + type: object + properties: + st: + type: integer + description: >- + The current operating state, which is one of: + 0=STARTUP, 1=IDLE, 2=NEW_GW_NO_NETWORK, 3=NO_INTERNET, + 4=NO_HOME + example: 1 + pri: + type: boolean + description: >- + Optional: true indicates this Gateway is the primary + Gateway. Not set indicates this Gateway is an + auxiliary (aux) Gateway + self: + type: boolean + description: >- + Optional: true indicates this Gateway. Not set + indicates other Gateways in a multi-gateway system + required: + - st + missing: + type: array + description: >- + Gateway identifiers of HomeDoc listed Gateways who have not + reported recently + items: + type: number + description: HomeDoc Gateway identifier + example: 7643 + required: + - known + - missing + LedColor: + description: The LED Color + content: + application/json: + schema: + description: The Gateway LED color and brightness + type: object + properties: + red: + type: number + description: Red + maximum: 0 + minimum: 255 + green: + type: number + description: Green + maximum: 0 + minimum: 255 + blue: + type: number + description: Blue + maximum: 0 + minimum: 255 + brightness: + type: number + description: Brightness + maximum: 0 + minimum: 100 + required: + - red + - green + - blue + - brightness + LogLevel: + description: The Gateway current log level + content: + application/json: + schema: + type: object + properties: + level: + type: string + description: >- + The current root log level, which is one of: error, warn, + info, verbose, debug, or silly. The recommended value is + info. + example: info + transports: + type: array + items: + properties: + level: + type: string + description: >- + The current transport log level, which is one of: + error, warn, info, verbose, debug, or silly. The + recommended value is info. + example: silly + required: + - level + required: + - level + - transports + Network: + description: The Gateway's network information + content: + application/json: + schema: + type: object + properties: + networkConfig: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information is to + be applied. The below staticIp object is optional if + staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present in + its entirety. If staticIpEnabled is false, this object + may be present and if present, it must be fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask to apply to the static IP address + value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address to utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + networkStatus: + description: The Gateway's network status information + type: object + properties: + ipAddress: + type: string + description: The IP address of the active interface + example: 10.0.0.101 + activeInterface: + type: string + description: >- + The active network interface identifier. Either 'eth0' + (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: eth0 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: 8.8.8.8 + eth0: + type: object + description: >- + The wired (eth0) network information, which may be empty + if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) + or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) + or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + wlan0: + type: object + description: >- + The wireless (wlan0) network information, which may be + empty if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) + or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) + or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + internetState: + type: string + description: The IP network's internet connectivity state + enum: + - Connected + - Disconnected + example: Connected + ssid: + type: string + description: >- + The wireless network's SSID value. The value is an empty + string if not configured + example: HunterDouglasWifi + required: + - ipAddress + - activeInterface + - dns + - eth0 + - wlan0 + - internetState + - ssid + required: + - networkConfig + - networkStatus + NetworkConfig: + description: The Gateway's current network configuration information + content: + application/json: + schema: + type: object + properties: + networkConfig: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information is to + be applied. The below staticIp object is optional if + staticIpEnabled is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present in + its entirety. If staticIpEnabled is false, this object + may be present and if present, it must be fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: >- + The subnet mask to apply to the static IP address + value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address to utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + linuxStaticIpValues: + description: >- + The Gateway operating system's configured static IP values + These values should match the networkConfig staticIp + information + type: object + properties: + staticIpEnabled: + type: boolean + description: Indicates if the staticIp is enabled + example: true + interface: + type: string + description: >- + The network interface currently configured with the + static IP values + example: wlan0 + ip_address: + type: string + description: The IP address being utilized as the static IP + example: 10.0.0.101 + netwask: + type: string + description: The subnet mask applied to the static IP address value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address being utilized + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + required: + - networkConfig + NetworkStatus: + description: The Gateway's current network status information + content: + application/json: + schema: + type: object + properties: + networkStatus: + description: The Gateway's network status information + type: object + properties: + ipAddress: + type: string + description: The IP address of the active interface + example: 10.0.0.101 + activeInterface: + type: string + description: >- + The active network interface identifier. Either 'eth0' + (wired) or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: eth0 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: 8.8.8.8 + eth0: + type: object + description: >- + The wired (eth0) network information, which may be empty + if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) + or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) + or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + wlan0: + type: object + description: >- + The wireless (wlan0) network information, which may be + empty if not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) + or 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) + or 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + internetState: + type: string + description: The IP network's internet connectivity state + enum: + - Connected + - Disconnected + example: Connected + ssid: + type: string + description: >- + The wireless network's SSID value. The value is an empty + string if not configured + example: HunterDouglasWifi + required: + - ipAddress + - activeInterface + - dns + - eth0 + - wlan0 + - internetState + - ssid + required: + - networkStatus + Scene: + description: Describes a scene + content: + application/json: + schema: + properties: + id: + title: Scene.id + description: '@deprecated in v23' + type: string + _id: + title: Scene._id + type: number + name: + title: Scene.name + type: string + icon: + title: Scene.icon + type: string + color: + title: Scene.color + type: string + bleId: + title: Scene.bleId + type: number + modDate: + title: Scene.modDate + type: string + roomId: + title: Scene.roomId + description: '@deprecated in v23' + type: string + room_Id: + title: Scene.room_Id + type: number + members: + items: + properties: + id: + title: SceneMember.id + description: '@deprecated in v23' + type: string + _id: + title: SceneMember._id + type: number + pos: + title: SceneMember.pos + properties: + pos1: + title: ShadePosition.pos1 + type: number + pos2: + title: ShadePosition.pos2 + type: number + pos3: + title: ShadePosition.pos3 + type: number + tilt: + title: ShadePosition.tilt + type: number + vel: + title: ShadePosition.vel + type: number + required: + - pos1 + - pos2 + - pos3 + - tilt + - vel + additionalProperties: false + type: object + shdId: + title: SceneMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: SceneMember.shd_Id + type: number + required: + - id + - _id + - pos + - shdId + - shd_Id + additionalProperties: false + title: SceneMember + type: object + title: Scene.members + type: array + required: + - id + - _id + - name + - icon + - color + - bleId + - modDate + additionalProperties: false + title: Scene + type: object + SceneEvent: + description: Scene event + content: + text/event-stream: + schema: + type: object + description: Scene event + properties: + evt: + type: string + description: Event name + enum: + - scene-add + - scene-del + - scene-activated + - scene-deactivated + example: scene-activated + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + id: + type: number + description: Unique Scene identifier + example: 55 + scene: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated + with this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + required: + - evt + - isoDate + - id + SceneShadeList: + description: List of Shade identifiers associated with a Scene + content: + application/json: + schema: + type: array + description: Array of numerical Shade identifiers + example: + - 22 + - 33 + - 44 + items: + type: number + ShadeEvent: + description: Shade event + content: + text/event-stream: + schema: + type: object + description: Shade event + properties: + evt: + type: string + description: Event name + enum: + - shade-offline + - shade-online + - motion-started + - motion-stopped + - battery-alert + example: motion-started + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + bleName: + type: string + description: Shade name + example: PIR:1233 + id: + type: number + description: Unique Shade identifier + example: 55 + currentPositions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + targetPositions: + type: object + description: > + Optional target Shade position values and estimate + completion time + + that may only present when the Event name is + 'motion-started'. + + The property may be omitted even with the Event + 'motion-started' + + if the values cannot be obtained or computed + properties: + etaInSeconds: + type: number + description: >- + Estimated time in seconds for the Shade to reach its + target positions + example: 7 + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + required: + - evt + - isoDate + - bleName + - id + - currentPositions + EventListeners: + description: List of Event Listeners + content: + application/json: + schema: + type: object + properties: + slots: + type: array + items: + type: string + activeListeners: + type: array + items: + type: string + required: + - slots + - activeListeners + ShadeIDList: + description: List of Shade identifiers + content: + application/json: + schema: + type: array + items: + properties: + id: + title: Shade.id + description: '@deprecated in v23' + type: string + _id: + title: Shade._id + type: number + name: + title: Shade.name + type: string + v: + title: Shade.v + type: number + index: + title: Shade.index + type: number + serial: + title: Shade.serial + type: string + mac: + title: Shade.mac + type: string + bleName: + title: Shade.bleName + type: string + power: + title: Shade.power + type: number + modelId: + title: Shade.modelId + type: number + required: + - id + - _id + - name + - v + - index + - serial + - mac + - bleName + additionalProperties: false + title: Shade + type: object + SpsChannelsCheckResponse: + description: >- + Comms channels that are offline, and an empty array means all + operational + content: + application/json: + schema: + type: object + properties: + failedChannels: + type: array + items: + type: string + description: name of downed channel + example: comms01 + required: + - failedChannels + SpsPcaVersions: + description: List of SPS PV+ Shade PCA versions + content: + application/json: + schema: + type: array + description: List of channels containing arrays of PV+ Shades + items: + type: array + description: PCA information for a list of PV+ Shades on a single channel + items: + type: object + description: SPS PCA version information + properties: + slot: + type: number + description: Shade port/channel number between 0 and 2 inclusive + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the version in + the release. Time to do a upgrade + example: false + required: + - slot + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + SpsSetLogLevelResponse: + description: Comms set log level response + content: + application/json: + schema: + type: object + properties: + responseIsOk: + type: boolean + description: The log level set was successful or not + returnedLogLevel: + type: number + description: >- + The new log level. 0=none, 1=error, 2=warn, 3=info, 4=debug, + 5=silly + returnedPersist: + type: boolean + description: The new persistence setting + required: + - responseIsOk + - returnedLogLevel + - returnedPersist + SpsShadeComparisonResults: + description: HomeDoc vs actual PV+ Shade comparison results + content: + application/json: + schema: + type: object + properties: + perfectMatch: + type: boolean + description: Indicates if the HomeDoc and the SPS are perfectly matched + differences: + type: object + spsHomeDocShades: + type: array + items: + type: object + description: Unique Shade information + properties: + bleName: + type: string + description: Shade BleName + example: SON:1234 + required: + - bleName + spsActualShades: + type: array + items: + type: object + description: Unique Shade information + properties: + bleName: + type: string + description: Shade BleName + example: SON:1234 + required: + - bleName + required: + - perfectMatch + - differences + - spsHomeDocShades + - spsActualShades + SpsShadesEnumeration: + description: PV+ Shades found on the SPS + content: + application/json: + schema: + type: array + items: + type: object + description: SPS port object + properties: + port: + type: number + description: Port/channel number from 1 to 16 inclusive + example: 1 + shades: + type: array + description: Information about PV+ Shades on this port + items: + type: object + description: SPS Shade description + properties: + slot: + type: number + description: Shade port/channel number between 0 and 2 inclusive + example: 1 + rssi: + type: number + description: Perfect RSSI value + example: -1 + ready: + type: number + description: Shade is ready + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the version + in the release. Time to do a upgrade + example: false + required: + - slot + - rssi + - ready + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + required: + - port + - shades + Standard200: + description: The request was successfully completed + content: + application/json: + schema: + type: object + properties: + msg: + type: string + required: + - msg + Standard400: + description: The request parameters were incorrect + content: + application/json: + schema: + type: object + properties: + errMsg: + type: string + description: Describes which parameters were incorrect + required: + - errMsg + Standard404: + description: The resource was not found + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + Standard503: + description: The resource is currently unavailable (i.e., no HomeDoc) + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + StandardGeneralError: + description: General unexpected error response + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + StandardUnimplemented: + description: The resource has not been implemented + content: + application/json: + schema: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + UpdateChannel: + description: The current Gateway firmware update channel + content: + application/json: + schema: + type: object + properties: + channel: + type: string + description: The current Gateway firmware update channel + example: production + required: + - channel + WebAutomation: + description: Web Automation Object + content: + application/json: + schema: + type: object + description: Web Automation Object + properties: + id: + type: number + description: Unique numerical Automation identifier + example: 33 + type: + type: number + description: | + Time-base for the automation + * 0 = Clock-based + * 2 = Before sunrise + * 6 = Before sunset + * 10 = After sunrise + * 14 = After sunset + example: 6 + enabled: + type: boolean + description: True indicates the Automation is enabled + example: true + days: + type: number + description: | + Bitmask of days when the automation is to run + * 0x00 = Reserved + * 0x01 = Monday + * 0x02 = Tuesday + * 0x04 = Wednesday + * 0x08 = Thursay + * 0x10 = Friday + * 0x20 = Saturday + * 0x40 = Sunday + * 0x80 = Reserved + example: 24 (i.e., 0x18, which is Thursday and Friday) + hour: + type: number + description: | + For clock-based automations, the 'hour' field is the + exact hour the automation will occur. For sunrise & sunset + based automations, the 'hour' field is the hour offset + before/after a sunrise/sunset automation is to run. + example: 4 + min: + type: number + description: | + For clock-based automations, the 'min' field is the + exact min the automation will occur. For sunrise & sunset + based automations, the 'min' field is the minutes offset + before/after a sunrise/sunset automation is to run. + example: 5 + bleId: + type: number + description: The automation ID stored on the Shade itself. + example: 83 + sceneId: + type: number + description: >- + The unique numerical Scene identifier associated with this + Automation + example: 116 + errorShd_Ids: + type: array + description: >- + The Shade list where the Automation was unsuccessfully + provisioned. The value can be null + example: null + items: + type: number + description: The failing Shade identifier + example: 55 + required: + - id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + WebAutomationList: + description: Web Automation List + content: + application/json: + schema: + type: array + items: + type: object + description: Web Automation Object + properties: + id: + type: number + description: Unique numerical Automation identifier + example: 33 + type: + type: number + description: | + Time-base for the automation + * 0 = Clock-based + * 2 = Before sunrise + * 6 = Before sunset + * 10 = After sunrise + * 14 = After sunset + example: 6 + enabled: + type: boolean + description: True indicates the Automation is enabled + example: true + days: + type: number + description: | + Bitmask of days when the automation is to run + * 0x00 = Reserved + * 0x01 = Monday + * 0x02 = Tuesday + * 0x04 = Wednesday + * 0x08 = Thursay + * 0x10 = Friday + * 0x20 = Saturday + * 0x40 = Sunday + * 0x80 = Reserved + example: 24 (i.e., 0x18, which is Thursday and Friday) + hour: + type: number + description: > + For clock-based automations, the 'hour' field is the + + exact hour the automation will occur. For sunrise & + sunset + + based automations, the 'hour' field is the hour offset + + before/after a sunrise/sunset automation is to run. + example: 4 + min: + type: number + description: | + For clock-based automations, the 'min' field is the + exact min the automation will occur. For sunrise & sunset + based automations, the 'min' field is the minutes offset + before/after a sunrise/sunset automation is to run. + example: 5 + bleId: + type: number + description: The automation ID stored on the Shade itself. + example: 83 + sceneId: + type: number + description: >- + The unique numerical Scene identifier associated with this + Automation + example: 116 + errorShd_Ids: + type: array + description: >- + The Shade list where the Automation was unsuccessfully + provisioned. The value can be null + example: null + items: + type: number + description: The failing Shade identifier + example: 55 + required: + - id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + WebHomeDoc: + description: Web HomeDoc Object + content: + application/json: + schema: + type: object + properties: + id: + type: string + _schemaVersion: + type: number + owner: + type: string + users?: + type: array + items: + type: string + modApp: + type: string + modDate: + type: string + home: + properties: + name: + title: Home.name + type: string + autosEnabled: + title: Home.autosEnabled + description: Are automations enabled globally + type: boolean + key: + title: Home.key + type: string + loc: + title: Home.loc + power: + title: Home.power + type: number + tz: + title: Home.tz + description: TimeZone - available in v24+ + type: string + required: + - name + - autosEnabled + additionalProperties: false + title: Home + type: object + rooms: + type: array + items: + type: object + properties: + id: + type: string + _id: + type: number + type: + type: number + name: + type: string + icon: + type: string + color: + type: string + shades: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter + Douglas use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. + In PowerView Gen 3, + + there are over 20 different types of Hunter + Douglas Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all + can be represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either + from the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot + operate independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two + tubes. Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - there + is no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up + shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the fully closed to fully open + tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 + representing the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + scenes: + type: array + items: + properties: + id: + title: Scene.id + description: '@deprecated in v23' + type: string + _id: + title: Scene._id + type: number + name: + title: Scene.name + type: string + icon: + title: Scene.icon + type: string + color: + title: Scene.color + type: string + bleId: + title: Scene.bleId + type: number + modDate: + title: Scene.modDate + type: string + roomId: + title: Scene.roomId + description: '@deprecated in v23' + type: string + room_Id: + title: Scene.room_Id + type: number + members: + items: + properties: + id: + title: SceneMember.id + description: '@deprecated in v23' + type: string + _id: + title: SceneMember._id + type: number + pos: + title: SceneMember.pos + properties: + pos1: + title: ShadePosition.pos1 + type: number + pos2: + title: ShadePosition.pos2 + type: number + pos3: + title: ShadePosition.pos3 + type: number + tilt: + title: ShadePosition.tilt + type: number + vel: + title: ShadePosition.vel + type: number + required: + - pos1 + - pos2 + - pos3 + - tilt + - vel + additionalProperties: false + type: object + shdId: + title: SceneMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: SceneMember.shd_Id + type: number + required: + - id + - _id + - pos + - shdId + - shd_Id + additionalProperties: false + title: SceneMember + type: object + title: Scene.members + type: array + required: + - id + - _id + - name + - icon + - color + - bleId + - modDate + additionalProperties: false + title: Scene + type: object + automations: + type: array + items: + properties: + id: + title: Automation.id + description: '@deprecated in v23' + type: string + _id: + title: Automation._id + type: number + type: + title: Automation.type + type: number + enabled: + title: Automation.enabled + type: boolean + days: + title: Automation.days + type: number + hour: + title: Automation.hour + type: number + min: + title: Automation.min + type: number + bleId: + title: Automation.bleId + type: number + sceneId: + title: Automation.sceneId + description: '@deprecated in v23' + type: string + scene_Id: + title: Automation.scene_Id + type: number + errorShdIds: + items: + type: string + title: Automation.errorShdIds + description: '@deprecated in v23' + type: array + errorShd_Ids: + items: + type: number + title: Automation.errorShd_Ids + type: array + required: + - id + - _id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + - scene_Id + - errorShdIds + - errorShd_Ids + additionalProperties: false + title: Automation + type: object + remotes?: + type: array + items: + properties: + id: + title: Remote.id + description: '@deprecated in v23' + type: string + _id: + title: Remote._id + type: number + name: + title: Remote.name + type: string + v: + title: Remote.v + type: number + mac: + title: Remote.mac + type: string + bleName: + title: Remote.bleName + type: string + members: + items: + properties: + id: + title: RemoteMember.id + description: '@deprecated in v23' + type: string + _id: + title: RemoteMember._id + type: number + group: + title: RemoteMember.group + type: number + shdId: + title: RemoteMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: RemoteMember.shd_Id + type: number + required: + - id + - _id + - group + - shdId + - shd_Id + additionalProperties: false + title: RemoteMember + type: object + title: Remote.members + type: array + required: + - id + - _id + - name + - v + - mac + - bleName + additionalProperties: false + title: Remote + type: object + gateways: + type: array + items: + properties: + id: + title: Gateway.id + description: '@deprecated in v23' + type: string + _id: + title: Gateway._id + type: number + name: + title: Gateway.name + type: string + v: + title: Gateway.v + type: string + radio1V: + title: Gateway.radio1V + type: string + radio2V: + title: Gateway.radio2V + type: string + serial: + title: Gateway.serial + type: string + aux: + title: Gateway.aux + type: boolean + ip: + title: Gateway.ip + type: string + ssid: + title: Gateway.ssid + type: string + shdIds: + items: + type: string + title: Gateway.shdIds + description: '@deprecated in v23' + type: array + shd_Ids: + items: + type: number + title: Gateway.shd_Ids + type: array + required: + - id + - _id + - name + - v + - radio1V + - radio2V + - serial + - ip + - ssid + additionalProperties: false + title: Gateway + type: object + WebRoom: + description: Web Room Object + content: + application/json: + schema: + type: object + description: Room information + properties: + id: + type: number + description: Unique numerical Room identifier + example: 674 + name: + type: string + description: Base64 encoded Room name + example: T2ZmaWNlCg== + ptName: + type: string + description: Room name + example: Office + color: + type: string + description: | + Unique identifier for a Room color from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 669 + type: + type: number + description: Room type enumeration value + example: 3 + shades: + type: array + description: >- + Optional list of Shades in a Room, which can be an empty + list + example: [] + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas + use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas + Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from + the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two tubes. + Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - there is + no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up + shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open position of the + primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open position of the + secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + required: + - id + - name + - ptName + - color + - icon + - type + WebRoomList: + description: Web Room List + content: + application/json: + schema: + type: array + items: + type: object + description: Room information + properties: + id: + type: number + description: Unique numerical Room identifier + example: 674 + name: + type: string + description: Base64 encoded Room name + example: T2ZmaWNlCg== + ptName: + type: string + description: Room name + example: Office + color: + type: string + description: > + Unique identifier for a Room color from HomeDoc Room + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 669 + type: + type: number + description: Room type enumeration value + example: 3 + shades: + type: array + description: >- + Optional list of Shades in a Room, which can be an empty + list + example: [] + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas + use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. + In PowerView Gen 3, + + there are over 20 different types of Hunter Douglas + Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all can + be represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from + the bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot + operate independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two tubes. + Where they are + + dependent, the shade firmware will force the + appropriate front shade + + position when the rear shade is controlled - there + is no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up + shade that also tilts plus a rear blackout + (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open position of the + primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open position of the + secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing + the Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + required: + - id + - name + - ptName + - color + - icon + - type + WebScene: + description: Web Scene Object + content: + application/json: + schema: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated with + this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + WebSceneList: + description: Web Scene List + content: + application/json: + schema: + type: array + items: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: > + Unique identifier for a Scene color from HomeDoc Scene + object + + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated with + this Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + WebShade: + description: Web Shade Object + content: + application/json: + schema: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas use + only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas Shades + available. + + These Shade have a variety of different motion capabilities. + While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the + bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can deploy. + In other cases, + + they are independent with two motors and two tubes. Where + they are + + dependent, the shade firmware will force the appropriate + front shade + + position when the rear shade is controlled - there is no + need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade that + also tilts plus a rear blackout (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + WebShadeList: + description: Web Shade List + content: + application/json: + schema: + type: array + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas use + only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas Shades + available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the + bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can deploy. + In other cases, + + they are independent with two motors and two tubes. Where + they are + + dependent, the shade firmware will force the appropriate + front shade + + position when the rear shade is controlled - there is no + need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade + that also tilts plus a rear blackout (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + WiFiScanList: + description: Wireless network scan list + content: + application/json: + schema: + type: object + properties: + ssidScanResults: + type: array + items: + type: object + description: Wireless network scan entry + properties: + ssid: + type: string + description: Wireless network name + example: HunterDouglasWiFi + rssi: + type: string + description: Wireless network RSSI value + example: '-81' + required: + - ssid + - rssi + required: + - ssidScanResults + schemas: + BatteryLevel: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + CloudConfig: + type: object + description: >- + Cloud configuration information used by the Gateway to access the + Cloud + properties: + homeId: + type: string + description: Home identifier as a hexadecimal string + example: Xffeg05RhmhUQez88Qyv + gatewayId: + type: number + description: Numerical identifier of the Gateway as registered in the Cloud + example: 103 + collection: + type: string + description: Name of the Home collection + default: homes + example: homes + clouddEnv: + type: number + description: >- + Select the Cloud environment to connect to: Dev = 0, Production = + 1 + default: 0 + example: 1 + required: + - homeId + - gatewayId + ComparableShade: + type: object + description: Unique Shade information + properties: + bleName: + type: string + description: Shade BleName + example: SON:1234 + required: + - bleName + Error: + type: object + description: Error response + properties: + errMsg: + type: string + description: Error description + required: + - errMsg + Hexadecimal: + type: object + description: Shade command payload + properties: + hex: + type: string + required: + - hex + LedColor: + description: The Gateway LED color and brightness + type: object + properties: + red: + type: number + description: Red + maximum: 0 + minimum: 255 + green: + type: number + description: Green + maximum: 0 + minimum: 255 + blue: + type: number + description: Blue + maximum: 0 + minimum: 255 + brightness: + type: number + description: Brightness + maximum: 0 + minimum: 100 + required: + - red + - green + - blue + - brightness + LinuxStaticIp: + description: >- + The Gateway operating system's configured static IP values These + values should match the networkConfig staticIp information + type: object + properties: + staticIpEnabled: + type: boolean + description: Indicates if the staticIp is enabled + example: true + interface: + type: string + description: >- + The network interface currently configured with the static IP + values + example: wlan0 + ip_address: + type: string + description: The IP address being utilized as the static IP + example: 10.0.0.101 + netwask: + type: string + description: The subnet mask applied to the static IP address value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address being utilized + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + NetworkConfig: + description: The Gateway's network configuration information + type: object + properties: + staticIpEnabled: + type: boolean + description: >- + Indicates if the below staticIp object information is to be + applied. The below staticIp object is optional if staticIpEnabled + is false + example: true + staticIp: + type: object + description: >- + The optional static IP configuration information. If + staticIpEnabled is true, this object must be present in its + entirety. If staticIpEnabled is false, this object may be present + and if present, it must be fully provided + properties: + ip_address: + type: string + description: The IP address to utilize as the static IP + example: 10.0.0.101 + netwask: + type: string + description: The subnet mask to apply to the static IP address value + example: 255.255.255.0 + gateway_ip: + type: string + description: The static internet Gateway IP address to utilize + example: 10.0.0.1 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: + - 8.8.8.8 + - 9.9.9.9 + required: + - staticIpEnabled + NetworkStatus: + description: The Gateway's network status information + type: object + properties: + ipAddress: + type: string + description: The IP address of the active interface + example: 10.0.0.101 + activeInterface: + type: string + description: >- + The active network interface identifier. Either 'eth0' (wired) or + 'wlan0' (wireless) + enum: + - eth0 + - wlan0 + example: eth0 + dns: + type: array + items: + type: string + description: The list of DNS server IP addresses + example: 8.8.8.8 + eth0: + type: object + description: >- + The wired (eth0) network information, which may be empty if not + active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) or 'wlan0' + (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) or + 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + wlan0: + type: object + description: >- + The wireless (wlan0) network information, which may be empty if + not active/configured + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) or 'wlan0' + (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) or + 'Wireless' (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + internetState: + type: string + description: The IP network's internet connectivity state + enum: + - Connected + - Disconnected + example: Connected + ssid: + type: string + description: >- + The wireless network's SSID value. The value is an empty string if + not configured + example: HunterDouglasWifi + required: + - ipAddress + - activeInterface + - dns + - eth0 + - wlan0 + - internetState + - ssid + NICType: + description: The Gateway's network interface information + type: object + properties: + name: + type: string + description: >- + The network interface's name either 'eth0' (wired) or 'wlan0' + (wireless) + enum: + - eth0 + - wlan0 + example: wlan0 + type: + type: string + description: >- + The network interface's type either 'Wired' (eth0) or 'Wireless' + (wlan0) + enum: + - Wired + - Wireless + example: Wireless + ip_address: + type: string + description: The network interface's IP address + example: 10.0.0.101 + mac_address: + type: string + description: The network interface's MAC address + example: 00:26:74:be:ef:66 + gateway_ip: + type: string + description: The network interface's internet Gateway IP address + example: 10.0.0.1 + netwask: + type: string + description: The network interface's subnet mask + example: 255.255.255.0 + AutomationId: + type: string + description: The numerical identifier for a particular Automation + example: 456 + PositionsPrimary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully closed to + fully open position of the primary rail + example: 0.99 + PositionsSecondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully closed to + fully open position of the secondary rail + example: 0.99 + PositionsTilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully closed to + fully open tilt position + example: 0 + PositionsVelocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the Shade operation + speed + example: 0.5 + PowerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + RoomId: + type: string + description: The numerical identifier for a particular Room + example: 2 + SceneEvent: + type: object + description: Scene event + properties: + evt: + type: string + description: Event name + enum: + - scene-add + - scene-del + - scene-activated + - scene-deactivated + example: scene-activated + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + id: + type: number + description: Unique Scene identifier + example: 55 + scene: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: | + Unique identifier for a Scene color from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated with this + Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + required: + - evt + - isoDate + - id + SceneId: + type: string + description: The numerical identifier for a particular Scene + example: 22 + ShadeEvent: + type: object + description: Shade event + properties: + evt: + type: string + description: Event name + enum: + - shade-offline + - shade-online + - motion-started + - motion-stopped + - battery-alert + example: motion-started + isoDate: + type: string + description: ISO timestamp + example: '2021-12-06T20:01:11.934Z' + bleName: + type: string + description: Shade name + example: PIR:1233 + id: + type: number + description: Unique Shade identifier + example: 55 + currentPositions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open tilt position + example: 0 + targetPositions: + type: object + description: | + Optional target Shade position values and estimate completion time + that may only present when the Event name is 'motion-started'. + The property may be omitted even with the Event 'motion-started' + if the values cannot be obtained or computed + properties: + etaInSeconds: + type: number + description: >- + Estimated time in seconds for the Shade to reach its target + positions + example: 7 + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open tilt position + example: 0 + required: + - evt + - isoDate + - bleName + - id + - currentPositions + ShadeId: + type: string + description: The numerical identifier for a particular Shade + example: 21 + ShadeCapabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In PowerView Gen + 3, + + there are over 20 different types of Hunter Douglas Shades available. + + These Shade have a variety of different motion capabilities. While + each + + Shade has its own set of unique properties, all can be represented by + the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the bottom or from + the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate independently - + the + + front shade must be down before the rear shade can deploy. In other + cases, + + they are independent with two motors and two tubes. Where they are + + dependent, the shade firmware will force the appropriate front shade + + position when the rear shade is controlled - there is no need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade that also + tilts plus a rear blackout (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + SpsPcaVersionInfo: + type: object + description: SPS PCA version information + properties: + slot: + type: number + description: Shade port/channel number between 0 and 2 inclusive + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the version in the + release. Time to do a upgrade + example: false + required: + - slot + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + SpsPort: + type: object + description: SPS port object + properties: + port: + type: number + description: Port/channel number from 1 to 16 inclusive + example: 1 + shades: + type: array + description: Information about PV+ Shades on this port + items: + type: object + description: SPS Shade description + properties: + slot: + type: number + description: Shade port/channel number between 0 and 2 inclusive + example: 1 + rssi: + type: number + description: Perfect RSSI value + example: -1 + ready: + type: number + description: Shade is ready + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the version in the + release. Time to do a upgrade + example: false + required: + - slot + - rssi + - ready + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + required: + - port + - shades + SpsShadeEntry: + type: object + description: SPS Shade description + properties: + slot: + type: number + description: Shade port/channel number between 0 and 2 inclusive + example: 1 + rssi: + type: number + description: Perfect RSSI value + example: -1 + ready: + type: number + description: Shade is ready + example: 1 + bleName: + type: string + description: Shade's BleName + example: SON:1234 + mac: + type: string + description: Shade's MAC address + example: '00:12:34:56:78:90' + pcaVersion: + type: string + description: Shade PCA version + example: 0.5.0 + pcaChecksum: + type: string + description: Shade PCA release checksum + example: '0x54321ABC' + pcaUpdateNeeded: + type: boolean + description: >- + The Shade PCA version is mismatched with the version in the + release. Time to do a upgrade + example: false + required: + - slot + - rssi + - ready + - bleName + - mac + - pcaVersion + - pcaChecksum + - pcaUpdateNeeded + WebAutomation: + type: object + description: Web Automation Object + properties: + id: + type: number + description: Unique numerical Automation identifier + example: 33 + type: + type: number + description: | + Time-base for the automation + * 0 = Clock-based + * 2 = Before sunrise + * 6 = Before sunset + * 10 = After sunrise + * 14 = After sunset + example: 6 + enabled: + type: boolean + description: True indicates the Automation is enabled + example: true + days: + type: number + description: | + Bitmask of days when the automation is to run + * 0x00 = Reserved + * 0x01 = Monday + * 0x02 = Tuesday + * 0x04 = Wednesday + * 0x08 = Thursay + * 0x10 = Friday + * 0x20 = Saturday + * 0x40 = Sunday + * 0x80 = Reserved + example: 24 (i.e., 0x18, which is Thursday and Friday) + hour: + type: number + description: | + For clock-based automations, the 'hour' field is the + exact hour the automation will occur. For sunrise & sunset + based automations, the 'hour' field is the hour offset + before/after a sunrise/sunset automation is to run. + example: 4 + min: + type: number + description: | + For clock-based automations, the 'min' field is the + exact min the automation will occur. For sunrise & sunset + based automations, the 'min' field is the minutes offset + before/after a sunrise/sunset automation is to run. + example: 5 + bleId: + type: number + description: The automation ID stored on the Shade itself. + example: 83 + sceneId: + type: number + description: >- + The unique numerical Scene identifier associated with this + Automation + example: 116 + errorShd_Ids: + type: array + description: >- + The Shade list where the Automation was unsuccessfully + provisioned. The value can be null + example: null + items: + type: number + description: The failing Shade identifier + example: 55 + required: + - id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + WebHomeDoc: + type: object + properties: + id: + type: string + _schemaVersion: + type: number + owner: + type: string + users?: + type: array + items: + type: string + modApp: + type: string + modDate: + type: string + home: + properties: + name: + title: Home.name + type: string + autosEnabled: + title: Home.autosEnabled + description: Are automations enabled globally + type: boolean + key: + title: Home.key + type: string + loc: + title: Home.loc + power: + title: Home.power + type: number + tz: + title: Home.tz + description: TimeZone - available in v24+ + type: string + required: + - name + - autosEnabled + additionalProperties: false + title: Home + type: object + rooms: + type: array + items: + type: object + properties: + id: + type: string + _id: + type: number + type: + type: number + name: + type: string + icon: + type: string + color: + type: string + shades: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas use + only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas + Shades available. + + These Shade have a variety of different motion + capabilities. While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the + bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can + deploy. In other cases, + + they are independent with two motors and two tubes. + Where they are + + dependent, the shade firmware will force the appropriate + front shade + + position when the rear shade is controlled - there is no + need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade + that also tilts plus a rear blackout (non-tilting) + shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary + rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + scenes: + type: array + items: + properties: + id: + title: Scene.id + description: '@deprecated in v23' + type: string + _id: + title: Scene._id + type: number + name: + title: Scene.name + type: string + icon: + title: Scene.icon + type: string + color: + title: Scene.color + type: string + bleId: + title: Scene.bleId + type: number + modDate: + title: Scene.modDate + type: string + roomId: + title: Scene.roomId + description: '@deprecated in v23' + type: string + room_Id: + title: Scene.room_Id + type: number + members: + items: + properties: + id: + title: SceneMember.id + description: '@deprecated in v23' + type: string + _id: + title: SceneMember._id + type: number + pos: + title: SceneMember.pos + properties: + pos1: + title: ShadePosition.pos1 + type: number + pos2: + title: ShadePosition.pos2 + type: number + pos3: + title: ShadePosition.pos3 + type: number + tilt: + title: ShadePosition.tilt + type: number + vel: + title: ShadePosition.vel + type: number + required: + - pos1 + - pos2 + - pos3 + - tilt + - vel + additionalProperties: false + type: object + shdId: + title: SceneMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: SceneMember.shd_Id + type: number + required: + - id + - _id + - pos + - shdId + - shd_Id + additionalProperties: false + title: SceneMember + type: object + title: Scene.members + type: array + required: + - id + - _id + - name + - icon + - color + - bleId + - modDate + additionalProperties: false + title: Scene + type: object + automations: + type: array + items: + properties: + id: + title: Automation.id + description: '@deprecated in v23' + type: string + _id: + title: Automation._id + type: number + type: + title: Automation.type + type: number + enabled: + title: Automation.enabled + type: boolean + days: + title: Automation.days + type: number + hour: + title: Automation.hour + type: number + min: + title: Automation.min + type: number + bleId: + title: Automation.bleId + type: number + sceneId: + title: Automation.sceneId + description: '@deprecated in v23' + type: string + scene_Id: + title: Automation.scene_Id + type: number + errorShdIds: + items: + type: string + title: Automation.errorShdIds + description: '@deprecated in v23' + type: array + errorShd_Ids: + items: + type: number + title: Automation.errorShd_Ids + type: array + required: + - id + - _id + - type + - enabled + - days + - hour + - min + - bleId + - sceneId + - scene_Id + - errorShdIds + - errorShd_Ids + additionalProperties: false + title: Automation + type: object + remotes?: + type: array + items: + properties: + id: + title: Remote.id + description: '@deprecated in v23' + type: string + _id: + title: Remote._id + type: number + name: + title: Remote.name + type: string + v: + title: Remote.v + type: number + mac: + title: Remote.mac + type: string + bleName: + title: Remote.bleName + type: string + members: + items: + properties: + id: + title: RemoteMember.id + description: '@deprecated in v23' + type: string + _id: + title: RemoteMember._id + type: number + group: + title: RemoteMember.group + type: number + shdId: + title: RemoteMember.shdId + description: '@deprecated in v23' + type: string + shd_Id: + title: RemoteMember.shd_Id + type: number + required: + - id + - _id + - group + - shdId + - shd_Id + additionalProperties: false + title: RemoteMember + type: object + title: Remote.members + type: array + required: + - id + - _id + - name + - v + - mac + - bleName + additionalProperties: false + title: Remote + type: object + gateways: + type: array + items: + properties: + id: + title: Gateway.id + description: '@deprecated in v23' + type: string + _id: + title: Gateway._id + type: number + name: + title: Gateway.name + type: string + v: + title: Gateway.v + type: string + radio1V: + title: Gateway.radio1V + type: string + radio2V: + title: Gateway.radio2V + type: string + serial: + title: Gateway.serial + type: string + aux: + title: Gateway.aux + type: boolean + ip: + title: Gateway.ip + type: string + ssid: + title: Gateway.ssid + type: string + shdIds: + items: + type: string + title: Gateway.shdIds + description: '@deprecated in v23' + type: array + shd_Ids: + items: + type: number + title: Gateway.shd_Ids + type: array + required: + - id + - _id + - name + - v + - radio1V + - radio2V + - serial + - ip + - ssid + additionalProperties: false + title: Gateway + type: object + WebRoom: + type: object + description: Room information + properties: + id: + type: number + description: Unique numerical Room identifier + example: 674 + name: + type: string + description: Base64 encoded Room name + example: T2ZmaWNlCg== + ptName: + type: string + description: Room name + example: Office + color: + type: string + description: | + Unique identifier for a Room color from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Room object + + Note: The numeric value is supplied as a string + example: 669 + type: + type: number + description: Room type enumeration value + example: 3 + shades: + type: array + description: Optional list of Shades in a Room, which can be an empty list + example: [] + items: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: >- + Hunter Douglas unique 'App Index' for Hunter Douglas use + only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In + PowerView Gen 3, + + there are over 20 different types of Hunter Douglas Shades + available. + + These Shade have a variety of different motion capabilities. + While each + + Shade has its own set of unique properties, all can be + represented by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the + bottom or from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can deploy. + In other cases, + + they are independent with two motors and two tubes. Where + they are + + dependent, the shade firmware will force the appropriate + front shade + + position when the rear shade is controlled - there is no + need for the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade that + also tilts plus a rear blackout (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open position of the secondary + rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + fully closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the + Shade operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + required: + - id + - name + - ptName + - color + - icon + - type + WebScene: + type: object + description: Scene information + properties: + id: + type: number + description: Unique numerical Scene identifier + example: 234 + name: + type: string + description: Base64 encoded Scene name + example: T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo= + ptName: + type: string + description: The Scene name + example: Open All Office Shades + color: + type: string + description: | + Unique identifier for a Scene color from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 37 + icon: + type: string + description: | + Unique identifier for a icon from HomeDoc Scene object + + Note: The numeric value is supplied as a string + example: 669 + networkNumber: + type: number + description: Numerical network identifier + example: 7383 + roomIds: + type: array + description: >- + List of unique numerical Room identifiers associated with this + Scene + example: + - 55 + - 66 + items: + type: number + required: + - id + - name + - ptName + - color + - icon + - networkNumber + - roomIds + WebShade: + type: object + description: Shade information + properties: + id: + type: number + description: Unique numerical Shade identifier + example: 789 + type: + type: number + description: Hunter Douglas unique 'App Index' for Hunter Douglas use only + example: 23 + name: + type: string + description: Base64 encoded Shade name + example: Q2VudGVyCg== + ptName: + type: string + description: Shade label + example: Center + capabilities: + type: number + description: > + Describes the Hunter Douglas Shade's capabilities. In PowerView + Gen 3, + + there are over 20 different types of Hunter Douglas Shades + available. + + These Shade have a variety of different motion capabilities. While + each + + Shade has its own set of unique properties, all can be represented + by the following + + motion type capabilities: + + + * Type 0 - Bottom Up + * Examples: Standard roller/screen shades, Duette bottom up + * Uses the “primary” control type + + * Type 1 - Bottom Up w/ 90° Tilt + * Examples: Silhouette, Pirouette + * Uses the “primary” and “tilt” control types + + * Type 2 - Bottom Up w/ 180° Tilt + * Example: Silhouette Halo + * Uses the “primary” and “tilt” control types + + * Type 3 - Vertical (Traversing) + * Examples: Skyline, Duette Vertiglide, Design Studio Drapery + * Uses the “primary” control type + + * Type 4 - Vertical (Traversing) w/ 180° Tilt + * Example: Luminette + * Uses the “primary” and “tilt” control types + + * Type 5 - Tilt Only 180° + * Examples: Palm Beach Shutters, Parkland Wood Blinds + * Uses the “tilt” control type + + * Type 6 - Top Down + * Example: Duette Top Down + * Uses the “primary” control type + + * Type 7 - Top-Down/Bottom-Up (can open either from the bottom or + from the top) + * Examples: Duette TDBU, Vignette TDBU + * Uses the “primary” and “secondary” control types + + * Type 8 - Duolite (front and rear shades) + * Examples: Roller Duolite, Vignette Duolite, Dual Roller + * Uses the “primary” and “secondary” control types + * Note: In some cases the front and rear shades are controlled by a single + motor and are on a single tube so they cannot operate + independently - the + + front shade must be down before the rear shade can deploy. In + other cases, + + they are independent with two motors and two tubes. Where they are + + dependent, the shade firmware will force the appropriate front + shade + + position when the rear shade is controlled - there is no need for + the + + control system to take this into account. + + + * Type 9 - Duolite with 90° Tilt (front bottom up shade that also + tilts plus a rear blackout (non-tilting) shade) + * Example: Silhouette Duolite, Silhouette Adeux + * Uses the “primary,” “secondary,” and “tilt” control types + * Note: Like with Type 8, these can be either dependent or independent. + + * Type 10 - Duolite with 180° Tilt + * Example: Silhouette Halo Duolite + * Uses the “primary,” “secondary,” and “tilt” control types + example: 0 + powerType: + description: | + Identifies the Shade power source + + * 0 = Battery + * 1 = Hardwired + * 2 = Rechargeable + type: number + example: wand + batteryStatus: + description: Approximate gauge of remaining Shade battery power + type: integer + minimum: 0 + maximum: 3 + example: 2 + roomId: + type: number + description: Unique numerical identifier for a particular Room + example: 6833 + signalStrength: + type: number + description: Shade's average RSSI value + example: -55 + bleName: + type: string + description: Shade name + example: PIR:5933 + firmware: + type: object + description: Shade firmware version + properties: + revision: + type: number + description: Firmware major number + example: 3 + subRevision: + type: number + description: Firmware minor number + example: 0 + build: + type: number + description: Firmware build number + example: 309 + positions: + type: object + description: Current Shade position values + properties: + primary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open position of the primary rail + example: 0.99 + secondary: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open position of the secondary rail + example: 0.99 + tilt: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the fully + closed to fully open tilt position + example: 0 + velocity: + type: number + description: >- + Decimal number between 0.0 and 1.0 representing the Shade + operation speed + example: 0.5 + required: + - id + - type + - name + - ptName + - capabilities + - powerType + - batteryStatus + - roomId + - bleName + WiFiScanEntry: + type: object + description: Wireless network scan entry + properties: + ssid: + type: string + description: Wireless network name + example: HunterDouglasWiFi + rssi: + type: string + description: Wireless network RSSI value + example: '-81' + required: + - ssid + - rssi + x-descriptions: + shadeListQuery: >- + The list of Shades is specified by either of the "ids" or "shades" + parameters. Only one of these should and must be utilized. + + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` + shadeListQuerySpsTest: >- + The list of Shades is specified by one of the following: "coordinates", + "ids", or "shades" parameters. Only one of these should and must be + utilized. + + - The ``coordinates`` parameter accepts a comma seperated list of channel:slot coordinates like ``1:0`` + - The ``ids`` parameter accepts a list of numerical shade identifiers. + - The ``shades`` parameter accepts a list of strings like ``PIR:6521`` +customOptions: {} diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/scene-event.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/scene-event.json new file mode 100644 index 0000000000000..6690715b23e44 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/scene-event.json @@ -0,0 +1,17 @@ +{ + "evt": "scene-activated", + "isoDate": "2021-12-06T20:01:11.934Z", + "id": 55, + "scene": { + "id": 234, + "name": "T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo=", + "ptName": "Open All Office Shades", + "color": "37", + "icon": "669", + "networkNumber": 7383, + "roomIds": [ + 55, + 66 + ] + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/scenes.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/scenes.json new file mode 100644 index 0000000000000..3c131f1449736 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/scenes.json @@ -0,0 +1,14 @@ +[ + { + "id": 234, + "name": "T3BlbiBBbGwgT2ZmaWNlIFNoYWRlcwo=", + "ptName": "ABC", + "color": "37", + "icon": "669", + "networkNumber": 7383, + "roomIds": [ + 55, + 66 + ] + } +] diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/shade-event.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/shade-event.json new file mode 100644 index 0000000000000..eb15d42a3b329 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/shade-event.json @@ -0,0 +1,17 @@ +{ + "evt": "motion-started", + "isoDate": "2021-12-06T20:01:11.934Z", + "bleName": "PIR:1233", + "id": 55, + "currentPositions": { + "primary": 0.99, + "secondary": 0.98, + "tilt": 0 + }, + "targetPositions": { + "etaInSeconds": 7, + "primary": 0.99, + "secondary": 0.99, + "tilt": 0 + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/shades.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/shades.json new file mode 100644 index 0000000000000..bd40c2ddb5122 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/gen3/shades.json @@ -0,0 +1,54 @@ +[ + { + "id": 2, + "type": 6, + "name": "VXBwZXIgTGVmdA==", + "ptName": "Upper Left", + "motion": null, + "capabilities": 0, + "powerType": 0, + "batteryStatus": 2, + "roomId": 1, + "firmware": { + "revision": 3, + "subRevision": 0, + "build": 359 + }, + "positions": { + "primary": 0.5, + "secondary": 0, + "tilt": 0, + "velocity": 0 + }, + "signalStrength": -50, + "bleName": "DUE:1444", + "shadeGroupIds": [ + ] + }, + { + "id": 3, + "type": 23, + "name": "VXBwZXIgUmlnaHQ=", + "ptName": "Upper Right", + "motion": null, + "capabilities": 1, + "powerType": 1, + "batteryStatus": 3, + "roomId": 1, + "firmware": { + "revision": 3, + "subRevision": 0, + "build": 359 + }, + "positions": { + "primary": 0, + "secondary": 0, + "tilt": 0, + "velocity": 0 + }, + "signalStrength": -51, + "bleName": "SIL:5AA5", + "shadeGroupIds": [ + ] + } +]