From 179de7ea04cea3ee76bc4363e6aa9b43e88d4f43 Mon Sep 17 00:00:00 2001 From: Kai Kreuzer Date: Wed, 7 Jun 2017 13:49:25 +0200 Subject: [PATCH] updated generated content Signed-off-by: Kai Kreuzer --- _bindings/allplay/readme.md | 4 +- _bindings/avmfritz/readme.md | 43 ++- _bindings/bigassfan/readme.md | 126 +++++++ _bindings/dlinksmarthome/readme.md | 67 ++++ _bindings/dscalarm/readme.md | 209 +++++------ _bindings/ecotouch1/readme.md | 33 +- _bindings/feed/readme.md | 20 +- _bindings/freebox/readme.md | 98 +++++- _bindings/fsinternetradio/readme.md | 7 +- _bindings/globalcache/readme.md | 32 +- _bindings/gpio1/readme.md | 8 +- _bindings/homematic/readme.md | 2 +- _bindings/hue/readme.md | 30 +- _bindings/isy1/readme.md | 106 ++++++ _bindings/kodi/readme.md | 33 +- _bindings/lifx/readme.md | 117 ++++--- _bindings/max/readme.md | 65 ++-- _bindings/milight1/readme.md | 2 +- _bindings/modbus1/readme.md | 2 +- _bindings/mqtt1/readme.md | 97 ++++-- _bindings/network/readme.md | 4 +- _bindings/rfxcom/readme.md | 91 +++-- _bindings/russound/readme.md | 324 +++++++----------- _bindings/satel1/readme.md | 120 ++++++- _bindings/sensebox/readme.md | 120 +++++++ _bindings/serial1/readme.md | 17 +- _bindings/synopanalyzer/readme.md | 71 ++++ _bindings/systeminfo/readme.md | 34 +- _bindings/zway/readme.md | 7 +- _iconsets/classic/icons/battery-off.png | Bin 0 -> 314 bytes _iconsets/classic/icons/battery-off.svg | 9 + _iconsets/classic/icons/battery-on.png | Bin 0 -> 314 bytes _iconsets/classic/icons/battery-on.svg | 9 + _iconsets/classic/icons/colorpicker.png | Bin 0 -> 2399 bytes _iconsets/classic/icons/colorpicker.svg | 15 + ...{poweroutlet-au.png => poweroutlet_au.png} | Bin ...{poweroutlet-au.svg => poweroutlet_au.svg} | 0 ...{poweroutlet-eu.png => poweroutlet_eu.png} | Bin ...{poweroutlet-eu.svg => poweroutlet_eu.svg} | 0 ...{poweroutlet-uk.png => poweroutlet_uk.png} | Bin ...{poweroutlet-uk.svg => poweroutlet_uk.svg} | 0 ...{poweroutlet-us.png => poweroutlet_us.png} | Bin ...{poweroutlet-us.svg => poweroutlet_us.svg} | 0 _io/imperihome/readme.md | 49 ++- _repos/openhab | 2 +- _repos/openhab-bundles | 2 +- _repos/openhab-distro | 2 +- _repos/openhab2-addons | 2 +- _repos/smarthome | 2 +- _uis/habpanel/doc/add-widget.png | Bin 0 -> 12987 bytes .../doc/custom-widget-context-menu.png | Bin 0 -> 3338 bytes .../dashboard-designer-placeholder-menu.png | Bin 0 -> 5446 bytes _uis/habpanel/doc/dashboard-designer.png | Bin 0 -> 60854 bytes _uis/habpanel/doc/habpanel-concepts.png | Bin 0 -> 74281 bytes _uis/habpanel/doc/index.md | 270 +++++++++++++++ _uis/habpanel/doc/main-menu-edit.png | Bin 0 -> 42038 bytes _uis/habpanel/doc/main-menu-run.png | Bin 0 -> 54724 bytes _uis/habpanel/doc/running-dashboard.png | Bin 0 -> 81595 bytes _uis/habpanel/doc/side-drawer.png | Bin 0 -> 719705 bytes _uis/habpanel/doc/widget-button.png | Bin 0 -> 17039 bytes _uis/habpanel/doc/widget-chart.png | Bin 0 -> 60159 bytes _uis/habpanel/doc/widget-clock.png | Bin 0 -> 22037 bytes _uis/habpanel/doc/widget-colorpicker.png | Bin 0 -> 14467 bytes _uis/habpanel/doc/widget-dummy.png | Bin 0 -> 9038 bytes _uis/habpanel/doc/widget-frame.png | Bin 0 -> 79291 bytes _uis/habpanel/doc/widget-image.png | Bin 0 -> 293160 bytes _uis/habpanel/doc/widget-knob.png | Bin 0 -> 20927 bytes _uis/habpanel/doc/widget-label.png | Bin 0 -> 6342 bytes _uis/habpanel/doc/widget-slider.png | Bin 0 -> 21620 bytes _uis/habpanel/doc/widget-switch.png | Bin 0 -> 9335 bytes _uis/habpanel/doc/widget-timeline.png | Bin 0 -> 14809 bytes concepts/diagrams/status_transitions.png | Bin 26332 -> 23639 bytes concepts/guidelines.md | 4 +- concepts/items.md | 12 + concepts/things.md | 8 +- 75 files changed, 1722 insertions(+), 553 deletions(-) create mode 100644 _bindings/bigassfan/readme.md create mode 100644 _bindings/dlinksmarthome/readme.md create mode 100644 _bindings/isy1/readme.md create mode 100644 _bindings/sensebox/readme.md create mode 100644 _bindings/synopanalyzer/readme.md create mode 100644 _iconsets/classic/icons/battery-off.png create mode 100644 _iconsets/classic/icons/battery-off.svg create mode 100644 _iconsets/classic/icons/battery-on.png create mode 100644 _iconsets/classic/icons/battery-on.svg create mode 100644 _iconsets/classic/icons/colorpicker.png create mode 100644 _iconsets/classic/icons/colorpicker.svg rename _iconsets/classic/icons/{poweroutlet-au.png => poweroutlet_au.png} (100%) rename _iconsets/classic/icons/{poweroutlet-au.svg => poweroutlet_au.svg} (100%) rename _iconsets/classic/icons/{poweroutlet-eu.png => poweroutlet_eu.png} (100%) rename _iconsets/classic/icons/{poweroutlet-eu.svg => poweroutlet_eu.svg} (100%) rename _iconsets/classic/icons/{poweroutlet-uk.png => poweroutlet_uk.png} (100%) rename _iconsets/classic/icons/{poweroutlet-uk.svg => poweroutlet_uk.svg} (100%) rename _iconsets/classic/icons/{poweroutlet-us.png => poweroutlet_us.png} (100%) rename _iconsets/classic/icons/{poweroutlet-us.svg => poweroutlet_us.svg} (100%) create mode 100644 _uis/habpanel/doc/add-widget.png create mode 100644 _uis/habpanel/doc/custom-widget-context-menu.png create mode 100644 _uis/habpanel/doc/dashboard-designer-placeholder-menu.png create mode 100644 _uis/habpanel/doc/dashboard-designer.png create mode 100644 _uis/habpanel/doc/habpanel-concepts.png create mode 100644 _uis/habpanel/doc/index.md create mode 100644 _uis/habpanel/doc/main-menu-edit.png create mode 100644 _uis/habpanel/doc/main-menu-run.png create mode 100644 _uis/habpanel/doc/running-dashboard.png create mode 100644 _uis/habpanel/doc/side-drawer.png create mode 100644 _uis/habpanel/doc/widget-button.png create mode 100644 _uis/habpanel/doc/widget-chart.png create mode 100644 _uis/habpanel/doc/widget-clock.png create mode 100644 _uis/habpanel/doc/widget-colorpicker.png create mode 100644 _uis/habpanel/doc/widget-dummy.png create mode 100644 _uis/habpanel/doc/widget-frame.png create mode 100644 _uis/habpanel/doc/widget-image.png create mode 100644 _uis/habpanel/doc/widget-knob.png create mode 100644 _uis/habpanel/doc/widget-label.png create mode 100644 _uis/habpanel/doc/widget-slider.png create mode 100644 _uis/habpanel/doc/widget-switch.png create mode 100644 _uis/habpanel/doc/widget-timeline.png diff --git a/_bindings/allplay/readme.md b/_bindings/allplay/readme.md index e77090145..4aa55c4e8 100644 --- a/_bindings/allplay/readme.md +++ b/_bindings/allplay/readme.md @@ -19,8 +19,8 @@ This binding integrates devices compatible with [Qualcomm AllPlay](https://www.q The binding uses native libraries for the AllJoyn framework. Libraries for the following platforms are already included in the binding: * Linux ARM -* Linux x86 (32 bit) -* Linux x86-64 (64 bit) +* Linux x86 (32 bit, AllJoyn v16.04a) +* Linux x86-64 (64 bit, AllJoyn v16.04a) * Windows x86 (32 bit, AllJoyn v16.04a) * Windows x86-64 (64 bit, AllJoyn v16.04a) diff --git a/_bindings/avmfritz/readme.md b/_bindings/avmfritz/readme.md index 5b632abcb..68682ca93 100644 --- a/_bindings/avmfritz/readme.md +++ b/_bindings/avmfritz/readme.md @@ -22,7 +22,7 @@ The binding integrates the AHA ( [AVM Home Automation](http://avm.de/ratgeber/sm ### FRITZ!Box -The well known FRITZ!Boxes are supported as bridge for accessing other AHA devices. It is planned to support some channels directly at the bridge like call monitoring and others - but these things are under current development by now. The Box has to run at least on firmware FRITZ!OS 6.00 and hast to support the "Smart Home" service. +The well known FRITZ!Boxes are supported as bridge for accessing other AHA devices. It is planned to support some channels directly at the bridge like call monitoring and others - but these things are under current development by now. The Box has to run at least on firmware FRITZ!OS 6.00 and has to support the "Smart Home" service. ### FRITZ!DECT 200 / FRITZ!DECT 210 @@ -36,6 +36,10 @@ This [DECT repeater](https://avm.de/produkte/fritzdect/fritzdect-repeater-100/) This [powerline adapter](http://avm.de/produkte/fritzpowerline/fritzpowerline-546e/) can be used via the bridge or in standalone mode. It supports switching the outlet and current power and energy consumption readings. This device does not contain a temperature sensor. +### FRITZ!DECT 300 / Comet DECT + +These two devices [FRITZ!DECT 300](https://avm.de/produkte/fritzdect/fritzdect-300/) and [Comet DECT](https://www.eurotronic.org/produkte/comet-dect.html) ( [EUROtronic Technology GmbH](https://www.eurotronic.org) ) are used to regulate radiators via DECT protocol. The FRITZ!Box can handle up to twelve heating thermostats. The binding provides channels for reading and setting the temperature. Additionally you can check the eco temperature, the comfort temperature and the battery level of the device. The FRITZ!Box has to run at least on firmware FRITZ!OS 6.35. + ## Discovery The FRITZ!Box and the powerline adapter are discovered through UPNP in the local network. When added as things, a username/password has eventually to be set depending on your Box/Powerline security configuration. The credentials given in the settings must have HomeAuto permissions. @@ -70,23 +74,33 @@ If correct credentials are set in the bridge configuration, connected AHA device * AIN (mandatory), no default (AIN number of device) -## Channels -| Channel Type ID | Item Type | Description | Available on thing | -|-------------|--------|-----------------------------|------------------------------------| -| temperature | Number | Actual measured temperature (in °C) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!DECT Repeater 100 | -| energy | Number | Accumulated energy consumption (in Wh) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | -| power | Number | Current power consumption (in W) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | -| outlet | Switch | Switchable outlet (ON/OFF) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | +## Supported Channels + +| Channel Type ID | Item Type | Description | Available on thing | +|-----------------|-----------|--------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------| +| temperature | Number | Actual measured temperature (in °C) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!DECT Repeater 100, FRITZ!DECT 300, Comet DECT | +| energy | Number | Accumulated energy consumption (in kWh) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | +| power | Number | Current power consumption (in W) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | +| outlet | Switch | Switchable outlet (ON/OFF) | FRITZ!DECT 210, FRITZ!DECT 200, FRITZ!Powerline 546E | +| actual_temp | Number | Actual Temperature of heating thermostat (in °C) | FRITZ!DECT 300, Comet DECT | +| set_temp | Number | Set Temperature of heating thermostat (in °C) | FRITZ!DECT 300, Comet DECT | +| eco_temp | Number | Eco Temperature of heating thermostat (in °C) | FRITZ!DECT 300, Comet DECT | +| comfort_temp | Number | Comfort Temperature of heating thermostat (in °C) | FRITZ!DECT 300, Comet DECT | +| next_change | DateTime | Next change of the Set Temperature if scheduler is activated in the FRITZ!Box settings - FRITZ!OS 6.80 | FRITZ!DECT 300, Comet DECT | +| next_tmep | Number | Next Set Temperature if scheduler is activated in the FRITZ!Box settings (in °C) - FRITZ!OS 6.80 | FRITZ!DECT 300, Comet DECT | +| battery_low | Switch | Battery Level Low (ON/OFF) - FRITZ!OS 6.80 | FRITZ!DECT 300, Comet DECT | + ## Full Example -demo.Things: +demo.things: ``` Bridge avmfritz:fritzbox:1 [ ipAddress="192.168.xxx.xxx", password ="xxx", user="xxx" ] { FRITZ_DECT_200 DECT1 [ ain="xxxxxxxxxxx" ] FRITZ_Powerline_546E PL1 [ ain="yy:yy:yy:yy:yyy" ] + Comet_DECT CD1 [ ain="aaaaaabbbbbb" ] } ``` @@ -99,6 +113,12 @@ Number Energy1 "Accumulated energy consumption [%.3f Wh]" { channel="avmfritz:FR Number Power1 "Current power consumption [%.2f W]" { channel="avmfritz:FRITZ_DECT_200:1:DECT1:power" } Switch Outlet2 { channel="avmfritz:FRITZ_Powerline_546E:1:PL1:outlet" } + +Group gCOMETDECT "Comet DECT heating thermostat" + +Number COMETDECTActualTemp "Actual measured temperature [%.1f °C]" (gCOMETDECT) { channel="avmfritz:Comet_DECT:1:CD1:actual_temp" } +Number COMETDECTSetTemp "Thermostat temperature setpoint [%.1f °C]" (gCOMETDECT) { channel="avmfritz:Comet_DECT:1:CD1:set_temp" } +Switch COMETDECTBattery "Battery low" (gCOMETDECT) { channel="avmfritz:Comet_DECT:1:CD1:battery_low" } ``` demo.sitemap: @@ -115,5 +135,10 @@ sitemap demo label="Main Menu" Frame label="FRITZ!Powerline 546E switchable outlet" { Switch item=Outlet2 } + Frame "Comet DECT heating thermostat" { + Text item=COMETDECTActualTemp icon="temperature" + Setpoint item=COMETDECTSetTemp minValue=8.0 maxValue=28.0 step=0.5 icon="temperature" + Switch item=COMETDECTBattery icon="battery" + } } ``` diff --git a/_bindings/bigassfan/readme.md b/_bindings/bigassfan/readme.md new file mode 100644 index 000000000..bbc2e35c6 --- /dev/null +++ b/_bindings/bigassfan/readme.md @@ -0,0 +1,126 @@ +--- +id: bigassfan +label: BigAssFan +title: BigAssFan - Bindings +type: binding +description: "The [BigAssFan](http://www.bigassfans.com/) binding is used to enable communication between openHAB and Big Ass Fans' Haiku family of residential fans that implement the SenseME technology." +since: 2x +install: auto +--- + + + +{% include base.html %} + +# BigAssFan Binding + +The [BigAssFan](http://www.bigassfans.com/) binding is used to enable communication between openHAB and Big Ass Fans' Haiku family of residential fans that implement the SenseME technology. + +## Overview + +Fans are discovered dynamically. There is a single thing created for each fan connected to the network. Each thing has channels that allow control of the fan and the optional LED light, as well as to monitor the status of the fan. When the fan is controlled from the remote control, Wall Controller, or smartphone app, the openHAB items linked to the fan's channels will be updated to reflect the fan's status. + + +## Device Discovery + +The BigAssFan binding discovers Haiku fans on the network, and creates an inbox entry for each discovered device. Once added as a thing, the user can control the fan and optional LED light kit, similarly to how the fan is controlled using the remote, Wall Controller, or smartphone app. + +Background discovery polls the network every few minutes for fans. Background discovery is **enabled** by default. To **disable** background discovery, add the following line to the *conf/services/runtime.cfg* file: + +``` +org.openhab.binding.bigassfan.discovery.BigAssFanDiscoveryService:backgroundDiscovery.enabled=false +``` + + +## Thing Configuration + +The fan's IP address, MAC address, and name is set at time of discovery. However, in the event that any of this information changes, the fan's configuration must be updated. + +#### Manual Thing Creation + +Fans can be manually created in the *PaperUI* or *HABmin*, or by placing a *.things* file in the *conf/things* directory. See example below. + +## Channels + +The following channels are supported: + +All devices support some of the following channels: + +| Channel Name | Item Type | Description | +|-------------------------|--------------|-------------------------------------------------| +| fan-power | Switch | Power on/off the fan | +| fan-speed | Dimmer | Adjust the speed of the fan | +| fan-direction | Switch | Change the direction in which the fan turns | +| fan-auto | Switch | Enable/disable fan auto mode | +| fan-whoosh | Switch | Enable/disable fan "whoosh" mode | +| fan-smartmode | String | Set Smartmode to HEATING, COOLING, or OFF | +| fan-speed-min | Dimmer | Set minimum fan speed for Smartmode COOLING | +| fan-speed-max | Dimmer | Set maximum fan speed for Smartmode COOLING | +| light-power | Switch | Power on/off the fan | +| light-level | Dimmer | Adjust the brightness of the light from | +| light-auto | Switch | Enable/disable light auto mode | +| light-smarter | String | Enable/disable Smarter Lighting | +| light-level-min | Dimmer | Set minimum light level for Smarter Lighting | +| light-level-max | Dimmer | Set maximum light level for Smarter Lighting | +| motion | Switch | Motion was detected | +| time | DateTime | Fan's date and time | + + +## Items + +The following item definitions would be used to control the fan. + +``` +Switch PorchFanPower { channel="bigassfan:fan:20F85EDAA56A:fan-power" } +Dimmer PorchFanSpeed { channel="bigassfan:fan:20F85EDAA56A:fan-speed" } +Switch PorchFanDirection { channel="bigassfan:fan:20F85EDAA56A:fan-direction" } +Switch PorchFanAuto { channel="bigassfan:fan:20F85EDAA56A:fan-auto" } +Switch PorchFanWhoosh { channel="bigassfan:fan:20F85EDAA56A:fan-whoosh" } +String PorchFanSmartmode { channel="bigassfan:fan:20F85EDAA56A:fan-smartmode" } +Dimmer PorchFanSpeedMin { channel="bigassfan:fan:20F85EDAA56A:fan-speed-min" } +Dimmer PorchFanSpeedMax { channel="bigassfan:fan:20F85EDAA56A:fan-speed-max" } +``` + +The following item definitions would be used to control the light. + +``` +Switch PorchFanLightPower { channel="bigassfan:fan:20F85EDAA56A:light-power" } +Dimmer PorchFanLightLevel { channel="bigassfan:fan:20F85EDAA56A:light-level" } +Switch PorchFanLightAuto { channel="bigassfan:fan:20F85EDAA56A:light-auto" } +Switch PorchFanLightSmarter { channel="bigassfan:fan:20F85EDAA56A:light-smarter" } +Dimmer PorchFanLightLevelMin { channel="bigassfan:fan:20F85EDAA56A:light-level-min" } +Dimmer PorchFanLightLevelMax { channel="bigassfan:fan:20F85EDAA56A:light-level-max" } +``` + +The following readonly items are provided by the fan. + +``` +Switch PorchFanMotionSensor { channel="bigassfan:fan:20F85EDAA56A:motion" } +DateTime PorchFanTime { channel="bigassfan:fan:20F85EDAA56A:time" } +``` + +### Sitemap + +This is an example of how to set up your sitemap. + +``` +Frame label="Control My BigAssFan" { + Switch item=PorchFanPower label="Fan Power [%s]" + Slider item=PorchFanSpeed label="Fan Speed [%s %%]" + Switch item=PorchFanLightPower label="Light Power [%s]" + Slider item=PorchFanLightSpeed label="Light Brightness [%s %%]" +} +``` + +### Manual Thing Creation + +Place a file named *bigassfan.things* in the *conf/things* directory. The file should contain lines formatted like this. + +``` +bigassfan:fan:20F85EDAA56A [ label="Porch Fan", ipAddress="192.168.12.62", macAddress="20:F8:5E:DA:A5:6A" ] +``` + +#### Unsupported Features + +Wall Controllers are not supported. Standalone lights are not supported. + diff --git a/_bindings/dlinksmarthome/readme.md b/_bindings/dlinksmarthome/readme.md new file mode 100644 index 000000000..5715b78ea --- /dev/null +++ b/_bindings/dlinksmarthome/readme.md @@ -0,0 +1,67 @@ +--- +id: dlinksmarthome +label: D-Link Smart Home +title: D-Link Smart Home - Bindings +type: binding +description: "A binding for D-Link Smart Home devices." +since: 2x +install: auto +--- + + + +{% include base.html %} + +# D-Link Smart Home Binding + +A binding for D-Link Smart Home devices. + +## Supported Things + +### DCH-S150 (WiFi motion sensor) + +The binding has been tested with hardware revisions A1 and A2 running firmware version 1.22. + +## Discovery + +The binding can automatically discover devices that have already been added to the Wifi network. Please refer to your mydlink Home app for instructions on how to add your device to your Wifi network. + +## Binding Configuration + +The binding does not require any special configuration. + +## Thing Configuration + +It is recommended to let the binding discover and add devices. Once added the configuration must be updated to specify the PIN code located on the back of the device. + +### DCH-S150 + +* **ipAddress** - Hostname or IP of the device +* **pin** - PIN code from the back of the device + +To manually configure a DCH-S150 Thing you must specify its IP address and PIN code. + +In the thing file, this looks like e.g. + +``` + Thing dlinksmarthome:DCH-S150:mysensor [ ipAddress="192.168.2.132" pin="1234" ] +``` + +## Channels + +### DCH-S150 + +* **motion** - Triggered when the sensor detects motion. + +## Example usage + +### DCH-S150 + +``` + rule "Landing motion" + when + Channel "dlinksmarthome:DCH-S150:90-8D-78-XX-XX-XX:motion" triggered + then + println("Motion has been detected") + end +``` \ No newline at end of file diff --git a/_bindings/dscalarm/readme.md b/_bindings/dscalarm/readme.md index cf16528e1..8d831807b 100644 --- a/_bindings/dscalarm/readme.md +++ b/_bindings/dscalarm/readme.md @@ -3,7 +3,7 @@ id: dscalarm label: DSC Alarm title: DSC Alarm - Bindings type: binding -description: "This is an openHAB binding for a DSC PowerSeries Alarm System utilizing the EyezOn Envisalink 3/2DS interface or the DSC IT-100 RS-232 interface." +description: "The DSC PowerSeries Alarm System is a popular do-it-yourself home security system, which can be monitored and controlled remotely through a standard web-browser or mobile device." since: 2x logo: images/addons/dscalarm.png install: auto @@ -15,11 +15,9 @@ install: auto # DSC Alarm Binding -This is an openHAB binding for a DSC PowerSeries Alarm System utilizing the EyezOn Envisalink 3/2DS interface or the DSC IT-100 RS-232 interface. - The DSC PowerSeries Alarm System is a popular do-it-yourself home security system, which can be monitored and controlled remotely through a standard web-browser or mobile device. -The openHAB DSC Alarm binding provides connectivity to the DSC Alarm panel via a TCP socket connection to the EyesOn Envisalink 3/2DS interface or a RS-232 serial connection to the DSC IT-100 interface. +This is the binding for the DSC PowerSeries Alarm System, utilizing either the EyezOn Envisalink 4/3/2DS interface or the DSC IT-100 RS-232 interface. It provides connectivity to the DSC Alarm panel via a TCP socket connection to the EyesOn Envisalink 4/3/2DS interface or a RS-232 serial connection to the DSC IT-100 interface. Additionally, their is provision to connect to the DSC IT-100 interface through a TCP serial server. ## Supported Things @@ -42,7 +40,11 @@ There are essentially no overall binding configuration settings that need to be ## Discovery -The DSC Alarm binding incorporates several discovery modes in order to find DSC Alarm systems. First, there is the Envisalink bridge discovery mode which performs a network query for any Envisalink adapters and adds them to the discovery inbox. Second, there is The IT-100 bridge discovery mode which will search serial ports for any IT-100 adapters and add them to the discovery inbox. The bridge discovery modes are started manually through PaperUI. Third, after a bridge is discovered and available to openHAB, the binding will attempt to discover DSC Alarm devices and add them to the discovery inbox. The TCP Server bridge does not implement bridge discovery but will utilize device discovery once it is online. +The DSC Alarm binding incorporates several discovery modes in order to find DSC Alarm systems. First, there is the Envisalink bridge discovery mode which performs a network query for any Envisalink adapters and adds them to the discovery inbox. Second, there is The IT-100 bridge discovery mode which will search serial ports for any IT-100 adapters and add them to the discovery inbox. The bridge discovery modes are started manually through PaperUI. Third, after a bridge is discovered and available to openHAB, the binding will attempt to discover DSC Alarm things and add them to the discovery inbox. The TCP Server bridge does not implement bridge discovery but will utilize thing discovery once it is online. + +Note: The Envisalink Bridge discovery does a TCP scan across your local network to find the interface. This may create issues on the network so it is suggested that caution be used when trying this discovery. The recommended method would be to manually add and configure the bridge through the 'dscalarm.thing' file or the PaperUI. And then allow the binding to discover the DSC Alarm things. + + ## Thing Configuration @@ -52,7 +54,7 @@ DSC Alarm things can be configured either through the online configuration utili ThingConfiguration Parameters envisalink
ipAddress - IP address for the Envisalink adapter - Required.
port - TCP port for the Envisalink adapter - Not Required - default = 4025.
password - Password to login to the Envisalink bridge - Not Required.
connectionTimeout - TCP socket connection timeout in milliseconds - Not Required - default=5000.
pollPeriod - Period of time in minutes between the poll command being sent to the Envisalink bridge - Not Required - default=1.
it100
serialPort - Serial port for the IT-100s bridge - Required.
baud - Baud rate of the IT-100 bridge - Not Required - default = 9600.
pollPeriod - Period of time in minutes between the poll command being sent to the IT-100 bridge - Not Required - default=1.
- tcpserver
ipAddress - IP address for the TCP Server - Required.
port - TCP port for the TCP Server - Required.
connectionTimeout - TCP socket connection timeout in milliseconds - Not Required - default=5000.
pollPeriod - Period of time in minutes between the poll command being sent to the TCP Server bridge - Not Required - default=1.
+ tcpserver
ipAddress - IP address for the TCP Server - Required.
port - TCP port for the TCP Server - Required.
connectionTimeout - TCP socket connection timeout in milliseconds - Not Required - default=5000.
pollPeriod - Period of time in minutes between the poll command being sent to the TCP Server bridge - Not Required - default=1.
protocol - The protocol used to interact with the DSC Alarm. Valid values are 1 for IT100 API or 2 for Envisalink TPI. The default is 1. - Not Required.
panel
userCode - User code for the DSC alarm panel - Not Required.
suppressAcknowledgementMsgs - Suppress the display of acknowledgement messages when received - Not Required - default = false.
partitionpartitionNumber - Partition number (1-8) - Required. zone
partitionNumber - Partition number (1-8) - Not Required - default=1.
zoneNumber - Zone number (1-64) - Required.
@@ -89,6 +91,7 @@ DSC Alarm things support a variety of channels as seen below in the following ta + @@ -99,7 +102,7 @@ DSC Alarm things support a variety of channels as seen below in the following ta - + @@ -198,6 +201,7 @@ Group:Contact:OR(OPEN, CLOSED) DSCAlarmSmoke /* DSC Alarm Items */ Switch BRIDGE_CONNECTION {channel="dscalarm:envisalink:MyBridgeName:bridge_reset"} +String SEND_DSC_ALARM_COMMAND "Send a DSC Alarm Command" {channel="dscalarm:envisalink:MyBridgeName:send_command"} /* DSC Alarm Panel Items */ String PANEL_MESSAGE "Panel Message: [%s]" (DSCAlarmPanel) {channel="dscalarm:panel:MyBridgeName:panel:panel_message"} @@ -394,20 +398,20 @@ Here is an example sitemap: ``` Frame label="Alarm System" { - Text label="DSC Alarm System" icon="DSC" { + Text label="DSC Alarm System" { Frame label="Panel" { Switch item=BRIDGE_CONNECTION label="Panel Connection" mappings=[ON="Connected", OFF="Disconnected"] - Text item=PANEL_MESSAGE icon="returnpipe" - Selection item=PANEL_COMMAND icon="flowpipe" mappings=[0="Poll", 1="Status Report", 2="Labels Request (Serial Only)", 8="Dump Zone Timers (TCP Only)", 10="Set Time/Date", 200="Send User Code"] + Text item=PANEL_MESSAGE + Selection item=PANEL_COMMAND mappings=[0="Poll", 1="Status Report", 2="Labels Request (Serial Only)", 8="Dump Zone Timers (TCP Only)", 10="Set Time/Date", 200="Send User Code"] Text item=PANEL_TIME { Switch item=PANEL_TIME_STAMP label="Panel Time Stamp" Switch item=PANEL_TIME_BROADCAST label="Panel Time Broadcast" } - Text item=PANEL_SYSTEM_ERROR icon="systemError" + Text item=PANEL_SYSTEM_ERROR Text item=PANEL_TROUBLE_LED label="Panel Trouble Condition" { - Text item=PANEL_TROUBLE_MESSAGE icon="shieldRed" + Text item=PANEL_TROUBLE_MESSAGE Text item=PANEL_SERVICE_REQUIRED label="Service Required" Text item=PANEL_AC_TROUBLE label="AC Trouble" Text item=PANEL_TELEPHONE_TROUBLE label="Telephone Line Trouble" @@ -420,14 +424,14 @@ Here is an example sitemap: } Frame label="Partitions" { - Text item=PARTITION1_STATUS icon="shieldGreen" { - Switch item=PARTITION1_ARM_MODE label="Partition 1 Arm Options" icon="shieldGreen" mappings=[0="Disarm", 1="Away", 2="Stay", 3="No Entry Delay", 4="With User Code"] - Text item=PARTITION1_OPENING_CLOSING_MODE icon="shieldGreen" + Text item=PARTITION1_STATUS { + Switch item=PARTITION1_ARM_MODE label="Partition 1 Arm Options" mappings=[0="Disarm", 1="Away", 2="Stay", 3="No Entry Delay", 4="With User Code"] + Text item=PARTITION1_OPENING_CLOSING_MODE } } Frame label="Keypad" { - Text label="Keypad LED Status" icon="DSCKeypad" { + Text label="Keypad LED Status" { Text item=KEYPAD_READY_LED label="Ready LED Status" Text item=KEYPAD_ARMED_LED label="Armed LED Status" Text item=KEYPAD_MEMORY_LED label="Memory LED Status" @@ -441,150 +445,150 @@ Here is an example sitemap: } Frame label="Zones" { - Text label="All Zones" icon="ZoneAlarm" { + Text label="All Zones" { Text item=ZONE1_STATUS { - Switch item=ZONE1_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE1_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE1_IN_ALARM icon="statusWarning" - Switch item=ZONE1_TAMPER icon="statusWarning" - Switch item=ZONE1_FAULT icon="statusWarning" + Switch item=ZONE1_IN_ALARM + Switch item=ZONE1_TAMPER + Switch item=ZONE1_FAULT } } Text item=ZONE9_STATUS { - Switch item=ZONE9_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE9_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE9_IN_ALARM icon="statusWarning" - Switch item=ZONE9_TAMPER icon="statusWarning" - Switch item=ZONE9_FAULT icon="statusWarning" + Switch item=ZONE9_IN_ALARM + Switch item=ZONE9_TAMPER + Switch item=ZONE9_FAULT } } Text item=ZONE10_STATUS { - Switch item=ZONE10_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE10_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE10_IN_ALARM icon="statusWarning" - Switch item=ZONE10_TAMPER icon="statusWarning" - Switch item=ZONE10_FAULT icon="statusWarning" + Switch item=ZONE10_IN_ALARM + Switch item=ZONE10_TAMPER + Switch item=ZONE10_FAULT } } Text item=ZONE11_STATUS { - Switch item=ZONE11_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE11_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE11_IN_ALARM icon="statusWarning" - Switch item=ZONE11_TAMPER icon="statusWarning" - Switch item=ZONE11_FAULT icon="statusWarning" + Switch item=ZONE11_IN_ALARM + Switch item=ZONE11_TAMPER + Switch item=ZONE11_FAULT } } Text item=ZONE12_STATUS { - Switch item=ZONE12_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE12_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE12_IN_ALARM icon="statusWarning" - Switch item=ZONE12_TAMPER icon="statusWarning" - Switch item=ZONE12_FAULT icon="statusWarning" + Switch item=ZONE12_IN_ALARM + Switch item=ZONE12_TAMPER + Switch item=ZONE12_FAULT } } Text item=ZONE13_STATUS { - Switch item=ZONE13_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE13_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE13_IN_ALARM icon="statusWarning" - Switch item=ZONE13_TAMPER icon="statusWarning" - Switch item=ZONE13_FAULT icon="statusWarning" + Switch item=ZONE13_IN_ALARM + Switch item=ZONE13_TAMPER + Switch item=ZONE13_FAULT } } Text item=ZONE14_STATUS { - Switch item=ZONE14_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE14_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE14_IN_ALARM icon="statusWarning" - Switch item=ZONE14_TAMPER icon="statusWarning" - Switch item=ZONE14_FAULT icon="statusWarning" + Switch item=ZONE14_IN_ALARM + Switch item=ZONE14_TAMPER + Switch item=ZONE14_FAULT } } Text item=ZONE15_STATUS { - Switch item=ZONE15_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE15_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE15_IN_ALARM icon="statusWarning" - Switch item=ZONE15_TAMPER icon="statusWarning" - Switch item=ZONE15_FAULT icon="statusWarning" + Switch item=ZONE15_IN_ALARM + Switch item=ZONE15_TAMPER + Switch item=ZONE15_FAULT } } Text item=ZONE21_STATUS { - Switch item=ZONE21_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE21_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE21_IN_ALARM icon="statusWarning" - Switch item=ZONE21_TAMPER icon="statusWarning" - Switch item=ZONE21_FAULT icon="statusWarning" + Switch item=ZONE21_IN_ALARM + Switch item=ZONE21_TAMPER + Switch item=ZONE21_FAULT } } Text item=ZONE22_STATUS { - Switch item=ZONE22_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE22_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE22_IN_ALARM icon="statusWarning" - Switch item=ZONE22_TAMPER icon="statusWarning" - Switch item=ZONE22_FAULT icon="statusWarning" + Switch item=ZONE22_IN_ALARM + Switch item=ZONE22_TAMPER + Switch item=ZONE22_FAULT } } Text item=ZONE23_STATUS { - Switch item=ZONE23_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE23_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE23_IN_ALARM icon="statusWarning" - Switch item=ZONE23_TAMPER icon="statusWarning" - Switch item=ZONE23_FAULT icon="statusWarning" + Switch item=ZONE23_IN_ALARM + Switch item=ZONE23_TAMPER + Switch item=ZONE23_FAULT } } Text item=ZONE24_STATUS { - Switch item=ZONE24_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE24_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE24_IN_ALARM icon="statusWarning" - Switch item=ZONE24_TAMPER icon="statusWarning" - Switch item=ZONE24_FAULT icon="statusWarning" + Switch item=ZONE24_IN_ALARM + Switch item=ZONE24_TAMPER + Switch item=ZONE24_FAULT } } Text item=ZONE25_STATUS { - Switch item=ZONE25_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE25_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE25_IN_ALARM icon="statusWarning" - Switch item=ZONE25_TAMPER icon="statusWarning" - Switch item=ZONE25_FAULT icon="statusWarning" + Switch item=ZONE25_IN_ALARM + Switch item=ZONE25_TAMPER + Switch item=ZONE25_FAULT } } Text item=ZONE51_STATUS { - Switch item=ZONE51_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE51_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE51_IN_ALARM icon="statusWarning" - Switch item=ZONE51_TAMPER icon="statusWarning" - Switch item=ZONE51_FAULT icon="statusWarning" + Switch item=ZONE51_IN_ALARM + Switch item=ZONE51_TAMPER + Switch item=ZONE51_FAULT } } Text item=ZONE52_STATUS { - Switch item=ZONE52_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE52_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE52_IN_ALARM icon="statusWarning" - Switch item=ZONE52_TAMPER icon="statusWarning" - Switch item=ZONE52_FAULT icon="statusWarning" + Switch item=ZONE52_IN_ALARM + Switch item=ZONE52_TAMPER + Switch item=ZONE52_FAULT } } Text item=ZONE53_STATUS { - Switch item=ZONE53_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE53_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE53_IN_ALARM icon="statusWarning" - Switch item=ZONE53_TAMPER icon="statusWarning" - Switch item=ZONE53_FAULT icon="statusWarning" + Switch item=ZONE53_IN_ALARM + Switch item=ZONE53_TAMPER + Switch item=ZONE53_FAULT } } Text item=ZONE54_STATUS { - Switch item=ZONE54_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE54_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE54_IN_ALARM icon="statusWarning" - Switch item=ZONE54_TAMPER icon="statusWarning" - Switch item=ZONE54_FAULT icon="statusWarning" + Switch item=ZONE54_IN_ALARM + Switch item=ZONE54_TAMPER + Switch item=ZONE54_FAULT } } Text item=ZONE55_STATUS { - Switch item=ZONE55_BYPASS_MODE icon="ZoneAlarm" mappings=[OFF="Armed", ON="Bypassed"] + Switch item=ZONE55_BYPASS_MODE mappings=[OFF="Armed", ON="Bypassed"] Frame label="Other Status:" { - Switch item=ZONE55_IN_ALARM icon="statusWarning" - Switch item=ZONE55_TAMPER icon="statusWarning" - Switch item=ZONE55_FAULT icon="statusWarning" + Switch item=ZONE55_IN_ALARM + Switch item=ZONE55_TAMPER + Switch item=ZONE55_FAULT } } } @@ -598,18 +602,23 @@ Here is an example sitemap: } ``` -## Change Log +Sample Rules for Sending a DSC Alarm Command -### openHAB 2.0.0 Beta 1 +``` +rule "SendKeystrokeStringCommand" +when + Item SwitchItemName received command ON +then + sendCommand(SEND_DSC_ALARM_COMMAND, "071,1*101#") +end -* Initial commit of the DSC Alarm Binding. ([#324](https://github.com/openhab/openhab2-addons/pull/324)) +rule "SendPollingCommand" -### openHAB 2.0.0 Beta 3 +when + Item SwitchItemName received command ON +then + sendCommand(SEND_DSC_ALARM_COMMAND, "000") +end +``` -* Added support for the DSC Alarm binding to communicate with an IT-100 through a TCP/IP serial server. Also, fixed a bug where the IT-100 serial interface requires a 6 digit usercode but was only receiving 4 digits. The channel named `PANEL_COMMAND` was changed from type String to type Number. Fixed bug where the IT-100 bridge would not connect. ([#846](https://github.com/openhab/openhab2-addons/pull/846)) - -### openHAB 2.0.0 Beta 4 - -* Fixed bug where the binding would prematurely set the channel `PARTITION_ARM_MODE` when issuing a partition arm command. -* Fixed issue where the binding stopped handling incoming messages from the DSC Alarm system. -* Disabled background discovery of DSC Alarm bridges as this may create network issues. Manual discovery is still available. +Notice the command variations in the examples. If a command has data, there needs to be a comma between the command and the data as seen above in the first example. If there is no data then it would only require the command itself as in the second example. \ No newline at end of file diff --git a/_bindings/ecotouch1/readme.md b/_bindings/ecotouch1/readme.md index d49bdb2f4..4f1be8ee9 100644 --- a/_bindings/ecotouch1/readme.md +++ b/_bindings/ecotouch1/readme.md @@ -53,10 +53,13 @@ where `` is one of the following values: | Außentemperatur | temperature_outside | number | | | Außentemperatur gemittelt über 1h | temperature_outside_1h | number | | | Außentemperatur gemittelt über 24h | temperature_outside_24h | number | | -| Quelleneintrittstemperatur | temperature_source_in | number | | -| Quellenaustrittstemperatur | temperature_source_out | number | | +| Quelleneintrittstemperatur | temperature_source_in | number | | Ai1 Geo only | +| Quellenaustrittstemperatur | temperature_source_out | number | | Ai1 Geo only | +| Umgebungstemperatur | temperature_surrounding | number | | Ai1 Air only | | Verdampfungstemperatur | temperature_evaporation | number | | -| Sauggastemperatur | temperature_suction | number | | +| Sauggastemperatur | temperature_suction | number | | Ai1 Geo only | +| Sauggas | temperature_suction_air | number | | Ai1 Air only | +| Ölsumpf | temperature_sump | number | | Ai1 Air only | | Verdampfungsdruck | pressure_evaporation | number | | | Temperatur Rücklauf Soll | temperature_return_set | number | | | Temperatur Rücklauf | temperature_return | number | | @@ -114,7 +117,7 @@ where `` is one of the following values: | Handabschaltung Kühlbetrieb | enable_cooling | switch | yes | | Handabschaltung Warmwasserbetrieb | enable_warmwater | switch | yes | | Handabschaltung Pool_Heizbetrieb | enable_pool | switch | yes | -| Status der Wärmepumpenkomponenten | state | number | | +| Status der Wärmepumpenkomponenten | state | number | | State as a number, see below for possible mapping. | | Status Quellenpumpe | state_sourcepump | switch | | | Status Heizungsumwälzpumpe | state_heatingpump | switch | | | Status Freigabe Regelung EDV / Magnetventil | state_evd | switch | | @@ -139,6 +142,28 @@ where `` is one of the following values: | Handschaltung Vierwegeventil | manual_4wayvalve | | yes | (H-0-A) | Handschaltung Multiausgang Ext. | manual_multiext | | yes | (H-0-A) +### Mappings + +Heatpump event type "state" can be mapped to strings. Different heatpump models seem to have slightly different state values. +Mappings for the Ai1 Geo have been copied from [here](http://www.haustechnikdialog.de/Forum/t/173357/Waterkotte-via-Ethernet-OpenHAB-und-Android-App?page=6). + +| State | Ai1 Geo | Ai1 Air | +| ----- | ----- | ----- | +| 0 | aus | aus | +| 1 | nur Solepumpe 1 | | +| 2 | nur Heizkreispumpe 2 | Standby | +| 3 | unbekannt | | +| 7 | unbekannt | | +| 10 | | Heizbetrieb | +| 15 | Heizbetrieb | | +| 131 | Naturkühlung | | +| 256 | Vorlauf Warmwasser | Vorlauf Warmwasser | +| 258 | Nachlauf Warmwasser | Nachlauf Warmwasser | +| 259 | unbekannt 259 vor WW Bereitung | | +| 263 | unbekannt 263 vor WW Bereitung | | +| 266 | | Warmwasserbereitung | +| 271 | Warmwasserbereitung | | + ## Examples diff --git a/_bindings/feed/readme.md b/_bindings/feed/readme.md index 47451a2e8..0aa028143 100644 --- a/_bindings/feed/readme.md +++ b/_bindings/feed/readme.md @@ -46,16 +46,16 @@ No binding configuration required. The binding supports following channels -| Channel Type ID | Item Type | Description | -|------------------|------------------------|--------------|----------------- |------------- | -| latest-title | String | Contains the title of the last feed entry. | -| latest-description | String | Contains the description of last feed entry. | -| latest-date | DateTime | Contains the published date of the last feed entry. | -| author | String | The name of the feed author, if author is present | -| title | String | The title of the feed | -| description | String | Description of the feed | -| last-update | DateTime | The last update date of the feed | -| number-of-entries | Number | Number of entries in the feed | +| Channel Type ID | Item Type | Description | +|--------------------|-----------|-----------------------------------------------------| +| latest-title | String | Contains the title of the last feed entry. | +| latest-description | String | Contains the description of last feed entry. | +| latest-date | DateTime | Contains the published date of the last feed entry. | +| author | String | The name of the feed author, if author is present | +| title | String | The title of the feed | +| description | String | Description of the feed | +| last-update | DateTime | The last update date of the feed | +| number-of-entries | Number | Number of entries in the feed | ## Full Example diff --git a/_bindings/freebox/readme.md b/_bindings/freebox/readme.md index a0c55df40..ecca8acfa 100644 --- a/_bindings/freebox/readme.md +++ b/_bindings/freebox/readme.md @@ -27,14 +27,19 @@ This binding supports the following thing types: | phone | Thing | The phone wired to the Freebox Revolution. | | net_device | Thing | A network device on the local network. | | net_interface | Thing | A network interface from a device on the local network. | +| airplay | Thing | An AirPlay device in the local network. | ## Discovery -The Freebox Revolution server is discovered automatically through mDNS in the local network. After a Freebox Revolution is discovered and available to openHAB, the binding will automatically discover phone and network devices / interfaces on the local network. +The Freebox Revolution server is discovered automatically through mDNS in the local network. After a Freebox Revolution is discovered and available to openHAB, the binding will automatically discover phone, network devices / interfaces and AirPlay devices with video capability in the local network. Note that the discovered thing will be setup to use only HTTP API (and not HTTPS) because only an IP can be automatically determined while a domain name is required to use HTTPS with a valid certificate. ## Binding configuration -There are no overall binding configuration settings that need to be set. All settings are through thing configuration parameters. +The binding has the following configuration options, which can be set for "binding:freebox": + +| Parameter | Name | Description | Required | +|-------------|--------------|--------------------------------------------------------------------------|----------| +| callbackUrl | Callback URL | URL to use for playing notification sounds, e.g. http://192.168.0.2:8080 | no | ## Thing Configuration @@ -47,6 +52,7 @@ The _server_ bridge thing requires the following configuration parameters: | Freebox Network Address | fqdn | The IP address / FQDN of the Freebox Server (can include port number).| false | mafreebox.freebox.fr | | Application token | appToken | Token generated by the Freebox Server. | false | | | Refresh Interval | refreshInterval | The refresh interval in seconds which is used to poll given Freebox Server.| false | 30 | +| Use only HTTP API | useOnlyHttp | Use HTTP API even if HTTPS is available. | false | false | If the parameter _ipAddress_ is not set, the binding will use the default address used by Free to access your Freebox Server (mafreebox.freebox.fr). The bridge thing will initialize only if a valid application token (parameter _appToken_) is filled. @@ -75,6 +81,83 @@ The _net_interface_ thing requires the following configuration parameters: |------------------------------|--------------------------|----------------------------------------------------|----------| | IP Address | ipAddress | The IP address (v4 or v6) of the network interface.| true | +### AirPlay device + +The _airplay_ thing requires the following configuration parameters: + +| Parameter Label | Parameter ID | Description | Required | +|-----------------|--------------|-----------------------------|----------| +| Name | name | Name of the AirPlay device | true | +| Password | password | AirPlay password | false | +| Accept all MP3 | acceptAllMp3 | Accept any bitrate for MP3 audio or only bitrates greater than 64 kbps | false | + +## HTTPS Access + +Each Freebox server is now automatically assigned a random domain name (in addition to mafreebox.freebox.fr that can be used inside the local network), and an associated TLS certificate to enable secure access to API. This certificate is also valid for the domain name mafreebox.freebox.fr too. +You must validate the certificate chain, by using the following Freebox ECC Root CA and Freebox RSA Root CA: + +``` +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIJAMaRcLnIgyukMAoGCCqGSM49BAMCMGExCzAJBgNVBAYT +AkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAMBgNVBAcMBVBhcmlzMRMwEQYDVQQKDApG +cmVlYm94IFNBMRwwGgYDVQQDDBNGcmVlYm94IEVDQyBSb290IENBMB4XDTE1MDkw +MTE4MDIwN1oXDTM1MDgyNzE4MDIwN1owYTELMAkGA1UEBhMCRlIxDzANBgNVBAgM +BkZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxEzARBgNVBAoMCkZyZWVib3ggU0ExHDAa +BgNVBAMME0ZyZWVib3ggRUNDIFJvb3QgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AASCjD6ZKn5ko6cU5Vxh8GA1KqRi6p2GQzndxHtuUmwY8RvBbhZ0GIL7bQ4f08ae +JOv0ycWjEW0fyOnAw6AYdsN6y1eNvH2DVfoXQyGoCSvXQNAUxla+sJuLGICRYiZz +mnijYzBhMB0GA1UdDgQWBBTIB3c2GlbV6EIh2ErEMJvFxMz/QTAfBgNVHSMEGDAW +gBTIB3c2GlbV6EIh2ErEMJvFxMz/QTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBhjAKBggqhkjOPQQDAgNoADBlAjA8tzEMRVX8vrFuOGDhvZr7OSJjbBr8 +gl2I70LeVNGEXZsAThUkqj5Rg9bV8xw3aSMCMQCDjB5CgsLH8EdZmiksdBRRKM2r +vxo6c0dSSNrr7dDN+m2/dRvgoIpGL2GauOGqDFY= +-----END CERTIFICATE----- +``` + +``` +-----BEGIN CERTIFICATE----- +MIIFmjCCA4KgAwIBAgIJAKLyz15lYOrYMA0GCSqGSIb3DQEBCwUAMFoxCzAJBgNV +BAYTAkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAMBgNVBAcMBVBhcmlzMRAwDgYDVQQK +DAdGcmVlYm94MRgwFgYDVQQDDA9GcmVlYm94IFJvb3QgQ0EwHhcNMTUwNzMwMTUw +OTIwWhcNMzUwNzI1MTUwOTIwWjBaMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGRnJh +bmNlMQ4wDAYDVQQHDAVQYXJpczEQMA4GA1UECgwHRnJlZWJveDEYMBYGA1UEAwwP +RnJlZWJveCBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA +xqYIvq8538SH6BJ99jDlOPoyDBrlwKEp879oYplicTC2/p0X66R/ft0en1uSQadC +sL/JTyfgyJAgI1Dq2Y5EYVT/7G6GBtVH6Bxa713mM+I/v0JlTGFalgMqamMuIRDQ +tdyvqEIs8DcfGB/1l2A8UhKOFbHQsMcigxOe9ZodMhtVNn0mUyG+9Zgu1e/YMhsS +iG4Kqap6TGtk80yruS1mMWVSgLOq9F5BGD4rlNlWLo0C3R10mFCpqvsFU+g4kYoA +dTxaIpi1pgng3CGLE0FXgwstJz8RBaZObYEslEYKDzmer5zrU1pVHiwkjsgwbnuy +WtM1Xry3Jxc7N/i1rxFmN/4l/Tcb1F7x4yVZmrzbQVptKSmyTEvPvpzqzdxVWuYi +qIFSe/njl8dX9v5hjbMo4CeLuXIRE4nSq2A7GBm4j9Zb6/l2WIBpnCKtwUVlroKw +NBgB6zHg5WI9nWGuy3ozpP4zyxqXhaTgrQcDDIG/SQS1GOXKGdkCcSa+VkJ0jTf5 +od7PxBn9/TuN0yYdgQK3YDjD9F9+CLp8QZK1bnPdVGywPfL1iztngF9J6JohTyL/ +VMvpWfS/X6R4Y3p8/eSio4BNuPvm9r0xp6IMpW92V8SYL0N6TQQxzZYgkLV7TbQI +Hw6v64yMbbF0YS9VjS0sFpZcFERVQiodRu7nYNC1jy8CAwEAAaNjMGEwHQYDVR0O +BBYEFD2erMkECujilR0BuER09FdsYIebMB8GA1UdIwQYMBaAFD2erMkECujilR0B +uER09FdsYIebMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqG +SIb3DQEBCwUAA4ICAQAZ2Nx8mWIWckNY8X2t/ymmCbcKxGw8Hn3BfTDcUWQ7GLRf +MGzTqxGSLBQ5tENaclbtTpNrqPv2k6LY0VjfrKoTSS8JfXkm6+FUtyXpsGK8MrLL +hZ/YdADTfbbWOjjD0VaPUoglvo2N4n7rOuRxVYIij11fL/wl3OUZ7GHLgL3qXSz0 ++RGW+1oZo8HQ7pb6RwLfv42Gf+2gyNBckM7VVh9R19UkLCsHFqhFBbUmqwJgNA2/ +3twgV6Y26qlyHXXODUfV3arLCwFoNB+IIrde1E/JoOry9oKvF8DZTo/Qm6o2KsdZ +dxs/YcIUsCvKX8WCKtH6la/kFCUcXIb8f1u+Y4pjj3PBmKI/1+Rs9GqB0kt1otyx +Q6bqxqBSgsrkuhCfRxwjbfBgmXjIZ/a4muY5uMI0gbl9zbMFEJHDojhH6TUB5qd0 +JJlI61gldaT5Ci1aLbvVcJtdeGhElf7pOE9JrXINpP3NOJJaUSueAvxyj/WWoo0v +4KO7njox8F6jCHALNDLdTsX0FTGmUZ/s/QfJry3VNwyjCyWDy1ra4KWoqt6U7SzM +d5jENIZChM8TnDXJzqc+mu00cI3icn9bV9flYCXLTIsprB21wVSMh0XeBGylKxeB +S27oDfFq04XSox7JM9HdTt2hLK96x1T7FpFrBTnALzb7vHv9MhXqAT90fPR/8A== +-----END CERTIFICATE----- +``` + +First copy and paste on your server running openHAB these two public certificates in 2 files named for example /freeboxECC.crt and /freeboxRSA.crt. Then you have to import these two certificate as trusted public certificate for your installed Java Runtime Environment. On Linux server, the command is: + +``` +sudo keytool -import -trustcacerts -file /freeboxECC.crt -alias Freebox -keystore $JAVA_HOME/jre/lib/security/cacerts +sudo keytool -import -trustcacerts -file /freeboxRSA.crt -alias Freebox -keystore $JAVA_HOME/jre/lib/security/cacerts +sudo rm /freeboxECC.crt /freeboxRSA.crt +``` + + ## Authentication You'll have to authorise openHAB to connect to your Freebox. Here is the process described : @@ -149,28 +232,32 @@ The following channels are supported: | phone | outgoing#call_name | String | R | Last outgoing call: called name | | net_device | reachable | Switch | R | Indicates whether the network device is reachable | | net_interface | reachable | Switch | R | Indicates whether the network interface is reachable | +| airplay | playurl | String | W | Play an audio or video media from the given URL | +| airplay | stop | Switch | W | Stop the media playback | ## Example ### Things -Here is an example with minimal configuration parameters (using default values): +Here is an example with minimal configuration parameters (using default values). It will first connect to mafreebox.freebox.fr using HTTPS (and will failback to HTTP if HTTPS access is not available). ``` Bridge freebox:server:fb "Freebox Revolution" [ appToken="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ] { Thing phone Phone "Phone" Thing net_device tv1 "TV living room" [ macAddress="XX:XX:XX:XX:XX:XX" ] Thing net_interface tv2 "TV bedroom" [ ipAddress="192.168.0.100" ] + Thing airplay player "Freebox Player (AirPlay)" [ name="Freebox Player" ] } ``` Here is another example overwritting default configuration parameters: ``` -Bridge freebox:server:fb "Freebox Revolution" [ fqdn="192.168.0.254", appToken="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", refreshInterval=20 ] { +Bridge freebox:server:fb "Freebox Revolution" [ fqdn="abcdefgh.fbxos.fr", appToken="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", refreshInterval=20, useOnlyHttp=false ] { Thing phone Phone "Phone" [ refreshPhoneInterval=10, refreshPhoneCallsInterval=120 ] Thing net_device tv1 "TV living room" [ macAddress="XX:XX:XX:XX:XX:XX" ] Thing net_interface tv2 "TV bedroom" [ ipAddress="192.168.0.100" ] + Thing airplay player "Freebox Player (AirPlay)" [ name="Freebox Player", password="1111", acceptAllMp3=false ] } ``` @@ -224,4 +311,7 @@ DateTime Freebox_outcall_ts "TimeStamp [%1$tA %1$td %1$tR]" {channel= Switch TVLivingRoom "TV living room" {channel="freebox:net_device:fb:tv1:reachable"} Switch TVBedroom "TV bedroom" {channel="freebox:net_interface:fb:tv2:reachable"} + +String freebox_player_playurl "URL [%s]" { channel="freebox:airplay:fb:player:playurl" } +Switch freebox_player_stop "Stop playback" { channel="freebox:airplay:fb:player:stop" } ``` diff --git a/_bindings/fsinternetradio/readme.md b/_bindings/fsinternetradio/readme.md index 0fd8e9c46..1980f9e2c 100644 --- a/_bindings/fsinternetradio/readme.md +++ b/_bindings/fsinternetradio/readme.md @@ -19,7 +19,12 @@ This binding integrates internet radios based on the [Frontier Silicon chipset]( ## Supported Things -Successfully tested are internet radios [Hama IR100](https://de.hama.com/00054823/hama-internetradio-ir110), [Medion MD87180](http://internetradio.medion.com/), and [MEDION MD86988](http://internetradio.medion.com/). +Successfully tested are internet radios + * [Hama IR100](https://de.hama.com/00054823/hama-internetradio-ir110) + * [Medion MD87180](http://internetradio.medion.com/) + * [MEDION MD86988](http://internetradio.medion.com/) + * [Roberts Stream 93i](https://www.robertsradio.com/uk/products/radio/smart-radio/stream-93i) + * [auna Connect 150](http://www.auna.de/HiFi-Geraete/Radios/Internetradios/auna-Connect-150-BK-2-1-Internetradio-Mediaplayer-schwarz.html) But in principle, all internet radios based on the [Frontier Silicon chipset](http://www.frontier-silicon.com/) should be supported because they share the same API. diff --git a/_bindings/globalcache/readme.md b/_bindings/globalcache/readme.md index f26724e2c..650a41b9c 100644 --- a/_bindings/globalcache/readme.md +++ b/_bindings/globalcache/readme.md @@ -35,11 +35,12 @@ Currently supported devices include: * iTach Flex WiFi * GC-100-6 * GC-100-12 +* ZMOTE Wi-Fi Universal Remote ## Device Discovery -GlobalCache GC-100 and iTach devices emit an **announcement beacon** every 10-20 seconds on multicast address 239.255.250.250:9131. The GlobalCache binding will automatically detect those devices, then add them to the inbox. +GlobalCache GC-100, iTach, and Zmote devices emit an **announcement beacon** every 10-20 seconds on multicast address 239.255.250.250:9131. The GlobalCache binding will automatically detect those devices, then add them to the inbox. Background discovery is **enabled** by default. To disable background discovery, add the following line to the *conf/services/runtime.cfg* file: @@ -52,7 +53,7 @@ Note that automatic device discovery **will not work** with GC-100's running fir ## Thing Configuration -The iTach IR, iTach SL, and GC-100 devices require a MAP file in order to transform the openHAB command to an IR command or to a serial command. In the thing configuration, enter the name of the MAP file containing the IR and/or serial codes (). The MAP file should be placed in the *conf/transform* directory. See example below. +The iTach IR, iTach SL, GC-100, and Zmote devices require a MAP file in order to transform the openHAB command to an IR command or to a serial command. In the thing configuration, enter the name of the MAP file containing the IR and/or serial codes (). The MAP file should be placed in the *conf/transform* directory. See example below. For iTach SL and GC-100 devices that support serial connections, you must use the GlobalCache device web application to set the serial port parameters for **baud rate**, **flow control**, and **parity**. These settings must match the serial port settings of the AV device being controlled. @@ -152,7 +153,7 @@ String RS232ME "My RS232-controlled Device" { channel="globalcache:gc100_ Serial commands strings are contained in a MAP file contained within the conf/transform directory. Serial command strings can contain URL-encoded characters in order to represent special characters such as spaces, tabs, carriage returns, line feeds, etc. See example below. -## Serial Direct (SL) Channel +## Serial (SL) Direct Channel The Serial Direct channel type enables serial commands to be sent directly to the device without attempting to map the command using the transformation service. This is useful in rules where the serial command might be constructed "on the fly" in the body of the rule. @@ -162,6 +163,28 @@ For example, the following item links to the module 1 connector 1 channel on an String RUSSCAA66 "Russound CAA66" { channel="globalcache:itachFlex:000C45D530B9:sl-m1#c1-direct" } ``` +## Serial (SL) Receive Channel + +The Serial Receive channel receives feedback from the device connected to the GlobalCache's serial port. You enable +this functionality by setting the **Enable Two Way** switch to ON in the thing configuration. In addition, you must +set the **End-of-Message Delimiter** in the thing configuration. The End-of-Message can be a single character, +or a sequence of characters. Use URL encoding for non-printable characters. + +For example, the following item links to the receive channel on module 1 connector 1 on a GC-100. A rule that looks for +updates on this item will be able to process messages sent from the device connected to the GlobalCache's serial port. + +``` +String RUSSCAA66_Receive "Russound CAA66 Receive" { channel="globalcache:gc100_06:000C1EFFF039:sl-m1#c1-receive" } +``` + +Here are some examples of common **End-ofMessage** delimiters. + +``` +%0D%0A Carriage return / Line feed +%0D Carriage return +%F7 Russound RNET message terminator +``` + ## Example Configuration ### MAP File @@ -215,6 +238,8 @@ String SAMSUNGHLS "Samsung HL-S DLP TV" { channel="globalcac String RS232ME "Preamp" { channel="globalcache:itachIR:000C7720B39F:sl-m1#c1" } String RUSSCAA66 "Russound CAA66" { channel="globalcache:itachFlex:000C45D530B9:sl-m1#c1-direct" } + +String ZSAMSUNGHLS "Samsung HL-S DLP TV" { channel="globalcache:zmote:CI00073306:ir-m1-c1#c1" } ``` ### Sitemap File @@ -314,4 +339,5 @@ globalcache:itachFlex:000C07BA7E11 [ ipAddress="192.168.12.66", mapFilename="ser globalcache:itachFlex:000CED0B3402 [ ipAddress="192.168.12.67", activeCable="FLEX_RELAY"] globalcache:gc100_06:000C1065AE17 [ ipAddress="192.168.12.68", mapFilename="ir-serial-codes.map" ] globalcache:gc100_12:000C162D7902 [ ipAddress="192.168.12.69", mapFilename="ir-serial-codes.map" ] +globalcache:zmote:CI00073306 [ ipAddress="192.168.12.142", mapFilename="ir-serial-codes.map" ] ``` diff --git a/_bindings/gpio1/readme.md b/_bindings/gpio1/readme.md index d5c3d00b3..6fd1dbd5d 100644 --- a/_bindings/gpio1/readme.md +++ b/_bindings/gpio1/readme.md @@ -83,10 +83,10 @@ _NOTE: These options are optional, in most circumstances you don't have to speci Allowed item types are `Contact` and `Switch`. Type `Contact` is used for input pins, `Switch` - for output pins. The configuration string is following: ``` -gpio="pin:PIN_NUMBER [debounce:DEBOUNCE_INTERVAL] [activelow:yes|no] [force:yes|no]" +gpio="pin:PIN_NUMBER [debounce:DEBOUNCE_INTERVAL] [activelow:yes|no] [force:yes|no] [initialValue:high|low]" ``` -Key-value pairs are separated by space; their order isn't important. Character's case is also insignificant. Key-value pair `pin` is mandatory, `debounce` and `activelow` are optional. If omitted `activelow` is set to `no`, `debounce` - to global option in configuration file (`debounce`) or 0 (zero) if neither is specified. +Key-value pairs are separated by space; their order isn't important. Character's case is also insignificant. Key-value pair `pin` is mandatory, `debounce`, `activelow` and `initialValue` are optional. If omitted `activelow` is set to `no`, `debounce` - to global option in configuration file (`debounce`) or 0 (zero) if neither is specified, initialValue is set to LOW. `PIN_NUMBER` is the number of the GPIO pin as seen by the kernel (not necessarily the same as the physical pin number). @@ -94,13 +94,15 @@ Key-value pairs are separated by space; their order isn't important. Character's When `activelow` is set to `no` (or omitted) the pins behaves normally: output pins will be set `high` on `ON` command and `low` on `OFF`, input pins will generate `OPEN` event when they are `high` and `CLOSED` when are `low`. However, if `activelow` is set to `yes` the logic is inverted: when `ON` command is sent to output pin it will be set to `low`, on `OFF` command - to `high`. Input pins will generate `OPEN` event when they are `low` and `CLOSED` event on `high`. +`initialValue` is the state of the pin which is set during initialization. It is applicable only for oputput pins (item Switch) and can be HIGH or LOW. + The "force" option can be used to forcefully get hold of the configured pin even if it is currently in use, so it automatically gets unexported and exported again. Examples: ``` Switch LED "LED" { gpio="pin:1" } -Switch NormallyClosedRelay "Normally Closed Relay" { gpio="pin:2 activelow:yes" } +Switch NormallyClosedRelay "Normally Closed Relay" { gpio="pin:2 activelow:yes initialValue:high" } Contact NormallyOpenPushButton "Normally Open Push Button" { gpio="pin:3 debounce:10" } Contact PIR "PIR" { gpio="pin:4 activelow:yes" } Contact NormallyClosedPushButton "Normally Closed Push Button" { gpio="pin:5 debounce:10 activelow:yes" } diff --git a/_bindings/homematic/readme.md b/_bindings/homematic/readme.md index 6b618072a..cb4a160a2 100644 --- a/_bindings/homematic/readme.md +++ b/_bindings/homematic/readme.md @@ -74,7 +74,7 @@ There are several settings for a bridge: Network address of the Homematic gateway - **gatewayType** -Hint for the binding to identify the gateway type (auto|ccu) (default = auto) +Hint for the binding to identify the gateway type (auto|ccu|noccu) (default = auto). - **callbackHost** Callback network address of the openHAB server, default is auto-discovery diff --git a/_bindings/hue/readme.md b/_bindings/hue/readme.md index e58682b34..d3f00956e 100644 --- a/_bindings/hue/readme.md +++ b/_bindings/hue/readme.md @@ -117,14 +117,16 @@ Bridge hue:bridge:1 [ ipAddress="192.168.0.64" ] { ``` // Bulb1 Switch Light1_Toggle { channel="hue:0210:1:bulb1:color" } -Dimmer Light1_Dimmer { channel="hue:0210:1:bulb1:color" } -Color Light1_Color { channel="hue:0210:1:bulb1:color" } -Dimmer Light1_ColorTemp { channel="hue:0210:1:bulb1:color_temperature" } +Dimmer Light1_Dimmer { channel="hue:0210:1:bulb1:color" } +Color Light1_Color { channel="hue:0210:1:bulb1:color" } +Dimmer Light1_ColorTemp { channel="hue:0210:1:bulb1:color_temperature" } +String Light1_Alert { channel="hue:0210:1:bulb1:alert" } +Switch Light1_Effect { channel="hue:0210:1:bulb1:effect" } // Bulb2 -Switch Light2_Toggle {channel="hue:0220:1:bulb2:brightness"} -Dimmer Light2_Dimm {channel="hue:0220:1:bulb2:brightness"} -Dimmer Light2_ColorTemp {channel="hue:0220:1:bulb2:color_temperature"} +Switch Light2_Toggle { channel="hue:0220:1:bulb2:brightness" } +Dimmer Light2_Dimm { channel="hue:0220:1:bulb2:brightness" } +Dimmer Light2_ColorTemp { channel="hue:0220:1:bulb2:color_temperature" } ``` Note: The bridge ID is in this example **1** but can be different in each system. @@ -136,15 +138,17 @@ sitemap demo label="Main Menu" { Frame { // Bulb1 - Switch item= Light1_Toggle - Slider item= Light1_Dimmer - Colorpicker item= Light1_Color - Slider item= Light1_ColorTemp + Switch item= Light1_Toggle + Slider item= Light1_Dimmer + Colorpicker item= Light1_Color + Slider item= Light1_ColorTemp + Switch item= Light1_Alert mappings=[NONE="None", SELECT="Alert", LSELECT="Long Alert"] + Switch item= Light1_Effect // Bulb2 - Switch item= Light2_Toggle - Slider item= Light2_Dimmer - Slider item= Light2_ColorTemp + Switch item= Light2_Toggle + Slider item= Light2_Dimmer + Slider item= Light2_ColorTemp } } ``` diff --git a/_bindings/isy1/readme.md b/_bindings/isy1/readme.md new file mode 100644 index 000000000..8c09a9ad8 --- /dev/null +++ b/_bindings/isy1/readme.md @@ -0,0 +1,106 @@ +--- +id: isy +label: Description +title: Description - Bindings +type: binding +description: "This is a openHAB binding for the Universal Devices ISY 994i router and PLM. Universal Devices offers a Java SDK for" +source: https://github.com/openhab/openhab1-addons/blob/master/bundles/binding/org.openhab.binding.isy/README.md +since: 1x +install: manual +--- + + + +{% include base.html %} + +## Description + +This is a openHAB binding for the Universal Devices ISY 994i router and PLM. Universal Devices offers a Java SDK for +external programs to communicate with the router. Alternatives include an extensive REST API. See details at +https://www.universal-devices.com/isy-developers/. + +## Items Configuration with ISY Binding Details + +The following settings can be added to the Items definition. + +* ctrl - Controller address in the format "x.y.z.w". This can be the address of a ISY Insteon Scene. Insteon addresses use the first three bytes and the last byte identified a particular capability of the device. +* type - This can be used to select device types with special configuration needs. See the "Device Types" section below. +* cmd - Specific ISY control to send to the ISY router as a command, **ST** is the default if left out +* addr - The Insteon address to monitor for the change. A scene does not report a status change, only the devices in the scene do. Specify the controller of the scene here. Defaults to the controller address if left out + +## Device Types + +You can specify a specific device type to let the binding know that a device is a special type. This is done using the "type=" configuation item in the binding. + +There are currently 3 types available: + +* thermostat - required to perform temperature calculations properly +* lock - locks use the security command instead of the normal off/on commands +* heartbeat - several battery powered sensors send a heartbeat. This is just a ST (status) with value 255, and it means that the sensor is still alive. To make rules easier, you can define these as type=heartbeat with an item type of DateTime, and it will update with the current time every time the heartbeat is received. You can then check the item using a rule to see if the DateTime item is too old. + +## OpenHAB Item Examples + + /* Insteon-enabled thermostat. Note "type=thermostat" to ensure proper temp calculations, and cmd=CLISPH to use the ISY setpoint heat value instead of status */ + Number Temperature_Indoor "Inside [%.2f °F]" (All) {isy="ctrl=29.24.98.1,type=thermostat,cmd=ST"} + Number Temperature_Setpoint "Desired Temperature [%.2f °F]" (All) {isy="ctrl=29.24.98.1,type=thermostat,cmd=CLISPH"} + + /* Regular ISY scene id #12220, but look at device 30.CB.66.1 to get the scene status */ + Switch Light_Hallway2 "Hallway" (GroundFloor,Lights) {isy="ctrl=12220,addr=30.CB.66.1"} + /* Regular ISY device, controlled directly (won't update scenes!) + Switch K_DiningRoom_Light "Dining Room Light" (GroundFloor,Lights) {isy="ctrl=F.C3.7C.1"} + + /* ZWave lock. Note type=lock (makes it use the security commands necessary). The second (Number) entry watches the BATLVL value, which battery-powered devices use to report battery level in percent */ + Switch BDoorLock "Back Door Lock" (Locks) {isy="ctrl=ZW004_1,type=lock"} + Number BDoorLock_Battery "Back Door Lock Battery [%d]" (Locks,BattLevels) {isy="ctrl=ZW004_1,cmd=BATLVL"} + + /* Insteon FanLinc, set up with a Keypadlinc. 4 scenes - Off, Low, Med, High */ + Switch LR_Fan_Off "LR Fan Off" (ISYScenes) {isy="ctrl=4622,addr=1c.e2.d1.3", autoupdate="false"} + Switch LR_Fan_Low "LR Fan Low" (ISYScenes) {isy="ctrl=20771,addr=1c.e2.d1.4", autoupdate="false"} + Switch LR_Fan_Med "LR Fan Med" (ISYScenes) {isy="ctrl=22031,addr=1c.e2.d1.5", autoupdate="false"} + Switch LR_Fan_High "LR Fan High" (ISYScenes) {isy="ctrl=11187,addr=1c.e2.d1.6", autoupdate="false"} + + /* Insteon water sensor - it has 3 subdevices: 1 = dry, 2 = wet, 4 = heartbeat + The heartbeat device sends an "ON" (255) ST code as a heartbeat. With type=heartbeat, the binding + sends a DateTime value. You can use a rule to check that DateTime to see if you have received + a heartbeat recently */ + Contact Water_Heater_Dry "Water Heater Sensor [MAP(watersensor-en.map):%s]" (Sensors) {isy="addr=25.AD.4F.1"} + DateTime Water_Heater_Heartbeat "Water Heater HB [%1$td.%1$tm.%1$tY %1$tH:%1$tM]" (Sensors) {isy="addr=25.AD.4F.4", type=heartbeat} + +The transform file (watersensor-en.map) for the water sensor is: + + CLOSED=Wet + OPEN=Dry + undefined=Unknown + -=Unknown + +## ISY Binding Configuration + +The following settings configure the ISY binding in the openhab.cfg file. + +* isy:refresh=60000 # refresh interval in milliseconds (optional, defaults to 60000 [1 minute]) +* isy:upnp=true # if true, use UPNP to communicate with the ISY 994i +* isy:uuid=uuid:%your_uudid% # UUID of the ISY router +* isy:ip=192.168.x.x # the hostname of the ISY router +* isy:port=80 # the port of the ISY router +* isy:user=user # the user of the ISY router +* isy:password=password # the password of the ISY router + + +## Disclaimer + +There is no guarantee for the function of the binding or its correctness. Use at your own risk. + +## Development Upgrade Instructions + +To build and install the isy binding, you need to first download the Java SDK that corresponds with the firmware version +of your ISY 994i. + + +1. [Download](https://www.universal-devices.com/isy-developers/.) the latest Java SDK zip file, e.g. ISY-WSDK-4.2.21.zip +1. Unzip it to some local folder +1. Copy the isy_inst.jar file into the org.openhab.binding.isy/lib folder +1. Provided that the API and the file name have not changed, there should not be a need to change the source code. Watch for + compilation errors and adjust accordingly. + + +The Lib is pushed with the binding, if you are using a older firmware version than the bundled version you may have issues. The SDK used should work with all newer version. diff --git a/_bindings/kodi/readme.md b/_bindings/kodi/readme.md index 41544ce72..8168430b8 100644 --- a/_bindings/kodi/readme.md +++ b/_bindings/kodi/readme.md @@ -57,7 +57,7 @@ The following configuration options are available for the Kodi binding: | `callbackUrl` | Callback URL | URL to use for playing notification sounds, e.g. `http://192.168.0.2:8080` | no | -## Thing Configuration +### Thing Configuration The Kodi thing requires the IP address of the device hosting your Kodi media center instance and the TCP port to access it on (default: `9090`). These parameters will be found by the auto-discovery feature. @@ -83,11 +83,29 @@ The Kodi thing supports the following channels: | album | String | Album name of the currently played song | | artist | String | Artist name of the currently played song or director of the currently played movie| | playuri | String | Plays the file with the provided URI | +| pvr-open-tv | String | Opens the PVR TV channel with the provided name | +| pvr-open-radio | String | Opens the PVR Radio channel with the provided name | +| pvr-channel | String | Title of the currently played PVR channel | | shownotification | String | Shows the provided notification message on the screen | | input | String | Allows to control Kodi. Valid values are: `Up`, `Down`, `Left`, `Right`, `Select`, `Back`, `Home`, `ContextMenu`, `Info`, `ShowCodec`, `ShowOSD` | | inputtext | String | This channel emulates a keyboard input | | systemcommand | String | This channel allows to send commands to `shutdown`, `suspend`, `hibernate`, `reboot` kodi | -| mediatype | String | The media type of the current file. e.g. song or movie | +| mediatype | String | The media type of the current file. Valid return values are: `unknown`, `channel`, `episode`, `movie`, `musicvideo`, `picture`, `radio`, `song`, `video` | + +### Channel Configuration + +**group** The PVR channels can be put into user-defined PVR channel groups. There are two default PVR channel groups. One for PVR TV channels and one for PVR radio channels. The default labels are "All channels" (in german systems "Alle Kanäle"). You have to adjust this configuration to use the `pvr-open-tv` and `pvr-open-radio` channels properly. You can optionally configure an user-defined PVR channel group. + +A manual setup through a `things/kodi.things` file could look like this: + +``` +kodi:kodi:myKodi [ipAddress="192.168.1.100", port="9090"] { + Channels: + Type pvropentv : pvr-open-tv [ + group="All channels" + ] +} +``` ## Item Configuration @@ -102,8 +120,11 @@ String myKodi_title "Title [%s]" { channel="kodi:kodi:myKodi: String myKodi_showtitle "Show title [%s]" { channel="kodi:kodi:myKodi:showtitle" } String myKodi_album "Album [%s]" { channel="kodi:kodi:myKodi:album" } String myKodi_artist "Artist [%s]" { channel="kodi:kodi:myKodi:artist" } -String myKodi_playuri "PlayerURI [%s]" { channel="kodi:kodi:myKodi:playuri" } -String myKodi_notification "Notification [%s]" { channel="kodi:kodi:myKodi:shownotification" } +String myKodi_playuri "PlayerURI" { channel="kodi:kodi:myKodi:playuri" } +String myKodi_pvropentv "PVR TV channel" { channel="kodi:kodi:myKodi:pvr-open-tv" } +String myKodi_pvropenradio "PVR Radio channel" { channel="kodi:kodi:myKodi:pvr-open-radio" } +String myKodi_pvrchannel "PVR channel [%s]" { channel="kodi:kodi:myKodi:pvr-channel" } +String myKodi_notification "Notification" { channel="kodi:kodi:myKodi:shownotification" } String myKodi_input "Input" { channel="kodi:kodi:myKodi:input" } String myKodi_inputtext "Inputtext" { channel="kodi:kodi:myKodi:inputtext" } String myKodi_systemcommand "Systemcommand" { channel="kodi:kodi:myKodi:systemcommand" } @@ -127,7 +148,9 @@ sitemap demo label="myKodi" Text item=myKodi_showtitle Text item=myKodi_album Text item=myKodi_artist - Text item=myKodi_playuri + Selection item=myKodi_pvropentv mappings=[Add your PVR TV channels here ...] + Selection item=myKodi_pvropenchannel mappings=[Add your PVR radio channels here ...] + Text item=myKodi_pvrchannel Selection item=myKodi_input mappings=[Up='Up', Down='Down', Left='Left', Right='Right', Select='Select', Back='Back', Home='Home', ContextMenu='ContextMenu', Info='Info', ShowCodec='ShowCodec', ShowOSD='ShowOSD'] Selection item=myKodi_systemcommand mappings=[Shutdown='Herunterfahren', Suspend='Bereitschaft', Reboot='Neustart'] Text item=myKodi_mediatype diff --git a/_bindings/lifx/readme.md b/_bindings/lifx/readme.md index de034bd23..95c3a20be 100644 --- a/_bindings/lifx/readme.md +++ b/_bindings/lifx/readme.md @@ -31,22 +31,24 @@ The following table lists the thing types of the supported LIFX devices: | Color 1000 BR30 | colorlight | | LIFX A19 | colorlight | | LIFX BR30 | colorlight | -| LIFX Z | colorlight | | | | | LIFX+ A19 | colorirlight | | LIFX+ BR30 | colorirlight | | | | +| LIFX Z | colormzlight | +| | | | White 800 (Low Voltage) | whitelight | | White 800 (High Voltage) | whitelight | | White 900 BR30 (Low Voltage) | whitelight | The thing type determines the capability of a device and with that the possible ways of interacting with it. The following matrix lists the capabilities (channels) for each type: -| Thing Type | On/Off | Brightness | Color | Color Temperature | Infrared | -|--------------|:------:|:----------:|:-----:|:-----------------:|:--------:| -| colorlight | X | | X | X | | -| colorirlight | X | | X | X | X | -| whitelight | X | X | | X | | +| Thing Type | On/Off | Brightness | Color | Color Zone | Color Temperature | Color Temperature Zone | Infrared | +|--------------|:------:|:----------:|:-----:|:----------:|:-----------------:|:----------------------:|:--------:| +| colorlight | X | | X | | X | | | +| colorirlight | X | | X | | X | | X | +| colormzlight | X | | X | X | X | X | | +| whitelight | X | X | | | X | | | ## Discovery @@ -71,21 +73,29 @@ The *fadetime* is an optional thing configuration parameter which configures the All devices support some of the following channels: -| Channel Type ID | Item Type | Description | Thing Types | -|-----------------|-----------|--------------------------------------------------------------------------------------|--------------------------------------| -| brightness | Dimmer | This channel supports adjusting the brightness value. | whitelight | -| color | Color | This channel supports full color control with hue, saturation and brightness values. | colorlight, colorirlight | +| Channel Type ID | Item Type | Description | Thing Types | +|-----------------|-----------|--------------------------------------------------------------------------------------|----------------------------------------| +| brightness | Dimmer | This channel supports adjusting the brightness value. | whitelight | +| color | Color | This channel supports full color control with hue, saturation and brightness values. | colorlight, colorirlight, colormzlight | +| colorzone | Color | This channel supports full zone color control with hue, saturation and brightness values. | colormzlight | | infrared | Dimmer | This channel supports adjusting the infrared value. *Note:* IR capable lights only activate their infrared LEDs when the brightness drops below a certain level. | colorirlight | -| temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | colorlight, colorirlight, whitelight | +| signalstrength | Number | This channel represents signal strength with values 0, 1, 2, 3 or 4; 0 being worst strength and 4 being best strength. | colorlight, colorirlight, colormzlight, whitelight | +| temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | colorlight, colorirlight, colormzlight, whitelight | +| temperaturezone | Dimmer | This channel supports adjusting the zone color temperature from cold (0%) to warm (100%). | colormzlight | The *color* and *brightness* channels have a "Power on brightness" configuration option that is used to determine the brightness when a light is switched on. When it is left empty, the brightness of a light remains unchanged when a light is switched on or off. +MultiZone lights (*colormzlight*) have serveral channels (e.g. *colorzone0*, *temperaturezone0*, etc.) that allow for controlling specific zones of the light. Changing the *color* and *temperature* channels will update the states of all zones. The *color* and *temperature* channels of MultiZone lights always return the same state as *colorzone0*, *temperaturezone0*. + + ## Full Example In this example **living** is a Color 1000 light that has a *colorlight* thing type which supports *color* and *temperature* channels. The **porch** light is a LIFX+ BR30 that has a *colorirlight* thing type which supports *color*, *temperature* and *infrared* channels. +The **ceiling** light is a LIFX Z with 2 strips (16 zones) that has a *colormzlight* thing type which supports *color*, *colorzone*, *temperature* and *temperaturezone* channels. + Finally, **kitchen** is a White 800 (Low Voltage) light that has a *whitelight* thing type which supports *brightness* and *temperature* channels. Either create a single *Color* item linked to the *color* channel and define *Switch*, *Slider* and *Colorpicker* entries with this item in the sitemap. @@ -96,22 +106,23 @@ Or create items for each type (*Color*, *Switch*, *Dimmer*) and define the corre ``` Thing lifx:colorlight:living [ deviceId="D073D5A1A1A1" ] { - Channels: - Type color : color [ powerOnBrightness= ] + Channels: + Type color : color [ powerOnBrightness= ] } Thing lifx:colorlight:living2 [ deviceId="D073D5A2A2A2" ] { - Channels: - Type color : color [ powerOnBrightness= ] + Channels: + Type color : color [ powerOnBrightness= ] } Thing lifx:colorirlight:porch [ deviceId="D073D5B2B2B2", fadetime=0 ] { - Channels: - Type color : color [ powerOnBrightness=75 ] + Channels: + Type color : color [ powerOnBrightness=75 ] } -Thing lifx:whitelight:kitchen [ deviceId="D073D5C3C3C3", fadetime=150 ] +Thing lifx:colormzlight:ceiling [ deviceId="D073D5C3C3C3" ] +Thing lifx:whitelight:kitchen [ deviceId="D073D5D4D4D4", fadetime=150 ] ``` ### demo.items: @@ -131,12 +142,20 @@ Dimmer Living2_Temperature { channel="lifx:colorlight:living2:temperature" } Color Porch_Color { channel="lifx:colorirlight:porch:color" } Dimmer Porch_Infrared { channel="lifx:colorirlight:porch:infrared" } Dimmer Porch_Temperature { channel="lifx:colorirlight:porch:temperature" } +Number Porch_Signal_Strength { channel="lifx:colorirlight:porch:signalstrength" } + +// Ceiling +Color Ceiling_Color { channel="lifx:colormzlight:ceiling:color" } +Dimmer Ceiling_Temperature { channel="lifx:colormzlight:ceiling:temperature" } +Color Ceiling_Color_Zone_0 { channel="lifx:colormzlight:ceiling:colorzone0" } +Dimmer Ceiling_Temperature_Zone_0 { channel="lifx:colormzlight:ceiling:temperaturezone0" } +Color Ceiling_Color_Zone_15 { channel="lifx:colormzlight:ceiling:colorzone15" } +Dimmer Ceiling_Temperature_Zone_15 { channel="lifx:colormzlight:ceiling:colorzone15" } // Kitchen Switch Kitchen_Toggle { channel="lifx:whitelight:kichen:brightness" } Dimmer Kitchen_Brightness { channel="lifx:whitelight:kitchen:brightness" } Dimmer Kitchen_Temperature { channel="lifx:whitelight:kitchen:temperature" } - ``` ### demo.sitemap: @@ -144,32 +163,44 @@ Dimmer Kitchen_Temperature { channel="lifx:whitelight:kitchen:temperature" } ``` sitemap demo label="Main Menu" { - Frame label="Living" { - Switch item=Living_Color - Slider item=Living_Color - Colorpicker item=Living_Color - Slider item=Living_Temperature - } - - Frame label="Living2" { - Switch item=Living2_Toggle - Slider item=Living2_Dimmer - Colorpicker item=Living2_Color - Slider item=Living2_Temperature + Frame label="Living" { + Switch item=Living_Color + Slider item=Living_Color + Colorpicker item=Living_Color + Slider item=Living_Temperature } - Frame label="Porch" { - Switch item=Porch_Color - Slider item=Porch_Color - Colorpicker item=Porch_Color - Slider item=Porch_Temperature - Slider item=Porch_Infrared - } + Frame label="Living2" { + Switch item=Living2_Toggle + Slider item=Living2_Dimmer + Colorpicker item=Living2_Color + Slider item=Living2_Temperature + } - Frame label="Kitchen" { - Switch item=Kitchen_Toggle - Slider item=Kitchen_Brightness - Slider item=Kitchen_Temperature - } + Frame label="Porch" { + Switch item=Porch_Color + Slider item=Porch_Color + Colorpicker item=Porch_Color + Slider item=Porch_Temperature + Slider item=Porch_Infrared + Text item=Porch_Signal_Strength + } + + Frame label="Ceiling" { + Switch item=Ceiling_Color + Slider item=Ceiling_Color + Colorpicker item=Ceiling_Color + Slider item=Ceiling_Temperature + Colorpicker item=Ceiling_Color_Zone_0 + Slider item=Ceiling_Temperature_Zone_0 + Colorpicker item=Ceiling_Color_Zone_15 + Slider item=Ceiling_Temperature_Zone_15 + } + + Frame label="Kitchen" { + Switch item=Kitchen_Toggle + Slider item=Kitchen_Brightness + Slider item=Kitchen_Temperature + } } ``` diff --git a/_bindings/max/readme.md b/_bindings/max/readme.md index 1ec412352..7e8d1780d 100644 --- a/_bindings/max/readme.md +++ b/_bindings/max/readme.md @@ -22,14 +22,14 @@ This binding allows you to integrate, view and control the MAX! Thermostats in t This binding support 6 different things types -| Thing | Type | Description | -|----------------|---------|-----------------------------------| -| bridge | Bridge | This is the MAX! Cube LAN gateway | -| thermostat | Thing | This is for the MAX! Heating Thermostat. This is also used for the powerplug switch "Zwischenstecker-Schaltaktor". | -| thermostatplus | Thing | This is for the MAX! Heating Thermostat+. This is the type that can hold the program by itself | -| wallthermostat | Thing | MAX! Wall Thermostat. | -| ecoswitch | Thing | MAX! Ecoswitch. | -| shuttercontact | Thing | MAX! Shuttercontact / Window Contact. | +| Thing | Type | Description | +|----------------|--------|--------------------------------------------------------------------------------------------------------------------| +| bridge | Bridge | This is the MAX! Cube LAN gateway. | +| thermostat | Thing | This is for the MAX! Heating Thermostat. This is also used for the powerplug switch "Zwischenstecker-Schaltaktor". | +| thermostatplus | Thing | This is for the MAX! Heating Thermostat+. This is the type that can hold the program by itself. | +| wallthermostat | Thing | MAX! Wall Thermostat. | +| ecoswitch | Thing | MAX! Ecoswitch. | +| shuttercontact | Thing | MAX! Shuttercontact / Window Contact. | Generally one does not have to worry about the thing types as they are automatically defined. If for any reason you need to manually define the Things and you are not exactly sure what type of thermostat you have, you can choose `thermostat` for both the thermostat and thermostat+, this will not affect their working. @@ -37,7 +37,7 @@ If for any reason you need to manually define the Things and you are not exactly ## Discovery The discovery process for the MAX! binding works in 2 steps. -When the binding is started or when manually triggered, the network is queried for the existence of a MAX! Cube lan gateway. When the Cube is found, it will become available in the discovery inbox. Periodically the network is queried again for a Cube. +When the binding is started or when manually triggered, the network is queried for the existence of a MAX! Cube LAN gateway. When the Cube is found, it will become available in the discovery inbox. Periodically the network is queried again for a Cube. Once the Cube is available in openHAB, all the devices connected to it are discovered and added to the discovery inbox. No scan is needed to trigger this. @@ -48,9 +48,9 @@ All the configuration settings are now per MAX! Cube, hence in case you have mul ## Thing Configuration -All the things are identified by their Serial number, hence this is mandatory. -The Cube (`bridge` thing) also requires the IP address to be defined. -All other configuration is optional. +All the things are identified by their serial number, hence this is mandatory. +The Cube (`bridge` thing) also requires the IP address to be defined. +All other configuration is optional. Note that several configuration options are automatically populated. Later versions of the binding may allow you to update this information. These properties can be found in the `Device Settings` section of parameters. @@ -59,22 +59,22 @@ Note that several configuration options are automatically populated. Later versi Depending on the thing it supports different Channels - -| Channel Type ID | Item Type | Description | -|------------------|------------------------|--------------|----------------- |------------- | -| mode | String | This channel indicates the mode of a thermostat | -| battery_low | Switch | This channel indicates if the device battery is low | -| set_temp | Number | This channel indicates the sets temperature of a thermostat. | -| actual_temp | Number | This channel indicates the measured temperature of a thermostat. see below for more details| -| valve | Number | This channel indicates the valve opening in %. Note this is an advaned setting, normally not visible | -| contact_state | Contact | This channel indicates the contact state for a shutterswitch | -| free_mem | Number |This channel indicates the free available memory on the cube to hold send commands. Note this is an advanced setting, normally not visible | -| duty_cycle | Number | This channel indicates the duty cycle (due to regulatory compliance reasons the cube is allowed only to send for a limited time. Duty cycle indicates how much of the available time is consumed) Note this is an advanced setting, normally not visible. | +| Channel Type ID | Item Type | Description | Available on thing | +|-----------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------| +| mode | String | This channel indicates the mode of a thermostat (AUTOMATIC/MANUAL/BOOST/VACATION). | thermostat, thermostatplus, wallthermostat | +| battery_low | Switch | This channel indicates if the device battery is low (ON/OFF). | thermostat, thermostatplus, wallthermostat, ecoswitch, shuttercontact | +| set_temp | Number | This channel indicates the sets temperature (in °C) of a thermostat. | thermostat, thermostatplus, wallthermostat | +| actual_temp | Number | This channel indicates the measured temperature (in °C) of a thermostat (see below for more details). | thermostat, thermostatplus, wallthermostat | +| valve | Number | This channel indicates the valve opening in %. Note this is an advanced setting, normally not visible. | thermostat, thermostatplus, wallthermostat | +| locked | Contact | This channel indicates if the thermostat is locked for adjustments (OPEN/CLOSED). Note this is an advanced setting, normally not visible. | thermostat, thermostatplus, wallthermostat | +| contact_state | Contact | This channel indicates the contact state for a shutterswitch (OPEN/CLOSED). | shuttercontact | +| free_mem | Number | This channel indicates the free available memory on the cube to hold send commands. Note this is an advanced setting, normally not visible. | bridge | +| duty_cycle | Number | This channel indicates the duty cycle (due to regulatory compliance reasons the cube is allowed only to send for a limited time. Duty cycle indicates how much of the available time is consumed) Note this is an advanced setting, normally not visible. | bridge | ## Full Example -In most cases no Things need to be defined manually. In case your Cube can't be discovered you need a `max:bridge` definition incl the right IP address of the Cube. Only in exceptional cases you would need to define the thermostats etc. +In most cases no Things need to be defined manually. In case your Cube can't be discovered you need a `max:bridge` definition incl. the right IP address of the Cube. Only in exceptional cases you would need to define the thermostats etc. max.things: @@ -91,8 +91,8 @@ Group gMAX "MAX Heating" [ "home-group" ] Switch maxBattery "Battery Low" (gMAX) {channel="max:thermostat:KEQ0565026:KEQ0648949:battery_low"} String maxMode "Thermostat Mode Setting" (gMAX) {channel="max:thermostat:KEQ0565026:KEQ0648949:mode"} -Number maxActual "Actual measured room temperature [%.1f �C]" (gMAX) {channel="max:thermostat:KEQ0565026:KEQ0648949:actual_temp"} -Number maxSetTemp "Thermostat temperature setpoint [%.1f �C]" (gMAX) {channel="max:thermostat:KEQ0565026:KEQ0648949:set_temp"} +Number maxActual "Actual measured room temperature [%.1f °C]" (gMAX) {channel="max:thermostat:KEQ0565026:KEQ0648949:actual_temp"} +Number maxSetTemp "Thermostat temperature setpoint [%.1f °C]" (gMAX) {channel="max:thermostat:KEQ0565026:KEQ0648949:set_temp"} ``` @@ -115,24 +115,27 @@ sitemap demo label="Main Menu" ## Actual Temperature Update Please be aware that the actual temperature measure for thermostats is only updated after the valve moved position or the thermostats mode has changed. Hence the temperature you see may be hours old. In that case you can update the temperature by changing the mode, wait approx. 2 minutes and change the mode back. -There is an experimental mode that does this automatically. This can be enabled by showing the "advanced settings"(e.g. in Habmin UI. Than the "Actual Temperature Refresh Rate" can be set. Minimum refresh rate once/10 minutes, recommended 60min to avoid excessive battery drain. +There is an experimental mode that does this automatically. This can be enabled by showing the "advanced settings" (e.g. in HABmin UI. Than the "Actual Temperature Refresh Rate" can be set. Minimum refresh rate once/10 minutes, recommended 60min to avoid excessive battery drain. ## New Device Inclusion + When clicking the discovery button for MAX! devices manually in the UI, you will start New Device Inclusion mode for 60s. During this time holding the _boost_ button on your device will link it to the Cube. ## Device configuration + In the _Configuration Parameters_ section of the device things you can update some of the device configuration parameters. Currently the following parameters can be updated: -* _name_ Name of the thermostat stored in the Cube (also used by the eq3 software). +* _name_ Name of the thermostat stored in the Cube (also used by the eQ-3 software). _Cube device configurable parameters_ * _ntpServer1_ The hostname for NTP Server 1 used by the Cube to get the time * _ntpServer2_ The hostname for NTP Server 2 used by the Cube to get the time -## Action Buttons (visible in Habmin) -In the Habmin thing configuration screen several action buttons are available to trigger special actions on the Cube +## Action Buttons (visible in HABmin) + +In the HABmin thing configuration screen several action buttons are available to trigger special actions on the Cube * _Reset Cube Configuration_. This resets the MAX! Cube room and device information. Devices will need to be included again! To use this button you need to enable 'Advanced settings' @@ -142,4 +145,4 @@ On the MAX! devices you can trigger the following action * _Delete Device from Cube_. Deletes the device from the MAX! Cube. Device will need to be included again! To use this button you need to enable 'Advanced settings' -Note: In PaperUI there are no action buttons. You can trigger these actions changing from 'No Action' in the dropdown to the action value. \ No newline at end of file +Note: In Paper UI there are no action buttons. You can trigger these actions changing from 'No Action' in the dropdown to the action value. \ No newline at end of file diff --git a/_bindings/milight1/readme.md b/_bindings/milight1/readme.md index 9f3c94429..1ac1710f4 100644 --- a/_bindings/milight1/readme.md +++ b/_bindings/milight1/readme.md @@ -6,7 +6,7 @@ type: binding description: "The Milight binding allows openHAB to send commands to multiple Milight bridges." source: https://github.com/openhab/openhab1-addons/blob/master/bundles/binding/org.openhab.binding.milight/README.md since: 1x -install: auto +install: legacy --- diff --git a/_bindings/modbus1/readme.md b/_bindings/modbus1/readme.md index aa16ffe82..968aae7b1 100644 --- a/_bindings/modbus1/readme.md +++ b/_bindings/modbus1/readme.md @@ -175,7 +175,7 @@ The extended format looks like: (for write) ```ini -[slaveName:writeIndex:trigger=TRIGGER, transformation=TRANSFORMATION, valueType=VALUETYPE] +>[slaveName:writeIndex:trigger=TRIGGER, transformation=TRANSFORMATION, valueType=VALUETYPE] ``` Read and write entries can be combined, and there can be zero or more read/write entries. All the keyword arguments after index are optional. Defaults are such that they correspond to binding behaviour currently. Multiple read/write definitions can be specified with commas (whitespace allowed as well). diff --git a/_bindings/mqtt1/readme.md b/_bindings/mqtt1/readme.md index d15999b19..c26db0de8 100644 --- a/_bindings/mqtt1/readme.md +++ b/_bindings/mqtt1/readme.md @@ -3,7 +3,7 @@ id: mqtt label: MQTT title: MQTT - Bindings type: binding -description: "This binding allows openHAB to act as an MQTT client, so that openHAB items can send and receive [MQTT](http://mqtt.org/) messages to/from an MQTT broker. It does not provide MQTT broker functionality, for this you may want to have a look at [Mosquitto](http://mosquitto.org/) or others. There are test servers available at m2m.eclipse.org and test.mosquitto.org." +description: "This binding allows openHAB to act as an MQTT client, so that openHAB items" source: https://github.com/openhab/openhab1-addons/blob/master/bundles/binding/org.openhab.binding.mqtt/README.md since: 1x logo: images/addons/mqtt.png @@ -16,9 +16,13 @@ install: auto # MQTT Binding -This binding allows openHAB to act as an MQTT client, so that openHAB items can send and receive [MQTT](http://mqtt.org/) messages to/from an MQTT broker. It does not provide MQTT broker functionality, for this you may want to have a look at [Mosquitto](http://mosquitto.org/) or others. There are test servers available at m2m.eclipse.org and test.mosquitto.org. +This binding allows openHAB to act as an MQTT client, so that openHAB items +can send and receive [MQTT](http://mqtt.org/) messages to/from an MQTT broker. +It does not provide MQTT broker functionality, for this you may want to have a +look at [Mosquitto](http://mosquitto.org/) or others. There are test servers +available at m2m.eclipse.org and test.mosquitto.org. -OpenHAB provides MQTT support on different levels. The table below gives a quick overview: +openHAB provides MQTT support on different levels. The table below gives a quick overview: | Level | Description | Usage | Configuration | |-------|-------------|-------|--------| @@ -33,18 +37,20 @@ The OwnTracks (formerly Mqttitude) binding is also available, which is an extens In order to consume or publish messages to an MQTT broker, you need to define all the brokers which you want to connect to, in your `services/mqtt.cfg` file. -| Property | Default | Description | -|----------|------------|-------------| -| ``.url | | Required. URL to the MQTT broker, e.g. tcp://localhost:1883 or ssl://localhost:8883 | -| ``.clientId | | Client id (max 23 chars) to use when connecting to the broker. If not provided a default one is generated. | -| ``.user | | User ID to authenticate with the broker. | -| ``.pwd | | Password to authenticate with the broker. | -| ``.qos | 0 | Set the quality of service level for sending messages to this broker. Possible values are 0 (Deliver at most once),1 (Deliver at least once) or 2 (Deliver exactly once). | -| ``.retain | false | true or false. Defines if the broker should retain the messages sent to it. | -| ``.async | true | true or false. Defines if messages are published asynchronously or synchronously. | -| ``.keepAlive | 60 | Integer. Defines the keep alive interval in seconds. | +| Property | Default | Required | Description | +|----------------------|---------|:--------:|-------------------------------------------------------------| +| ``.url | | Yes | URL to the MQTT broker, e.g. tcp://localhost:1883 or ssl://localhost:8883 | +| ``.clientId | random | No* | Client ID to use when connecting to the broker. If not provided a random default is generated. Usually restricted to 23 characters in length. (see the `allowLongerClientIds` setting) | +| ``.user | | Yes | User ID to authenticate with the broker. | +| ``.pwd | | Yes | Password to authenticate with the broker. | +| ``.qos | 0 | No | Set the quality of service level for sending messages to this broker. Possible values are 0 (Deliver at most once), 1 (Deliver at least once) or 2 (Deliver exactly once). | +| ``.retain | false | No | True or false. Defines if the broker should retain the messages sent to it. | +| ``.async | true | No | True or false. Defines if messages are published asynchronously or synchronously. | +| ``.keepAlive | 60 | No | Integer. Defines the keep alive interval in seconds. | +| ``.allowLongerClientIds | false | No | True or false. If set to true, allows the use of clientId values up to 65535 characters long. NOTE: clientId values longer than 23 characters may not be supported by all MQTT servers. Check the server documentation. | -where `` is an alias name for the MQTT broker. This is the name you can use in the item binding configurations afterwards. +`` is an alias name for the MQTT broker. This is the name you can use in the item binding configurations afterwards.
+\* ``.clientId is not required to be provided because a random value will be generated if a value is not provided. ### Example Configurations @@ -54,7 +60,7 @@ Example configuration of a simple broker connection: m2m-eclipse.url=tcp://m2m.eclipse.org:1883 ``` -Example configuration of a encrypted broker connection with authentication: +Example configuration of an encrypted broker connection with authentication: ``` mosquitto.url=ssl://test.mosquitto.org:8883 @@ -67,14 +73,16 @@ mosquitto.async=false ## Item Configuration for Inbound Messages -Below you can see the structure of the inbound mqtt configuration string. Inbound configurations allow you to receive MQTT messages into an openHAB item. -Every item is allowed to have multiple inbound (or outbound) configurations. +Below you can see the structure of the inbound MQTT configuration string. +Inbound configurations allow you to receive MQTT messages into an openHAB +item. Every item is allowed to have multiple inbound (or outbound) +configurations. ``` Item myItem {mqtt="[:::], [:::], ..."} ``` -Since 1.6 it is possible to add an optional 5th configuration like: +Since 1.6 it is possible to add an optional fifth configuration like: ``` Item myItem {mqtt="[::::], [:::], ..."} @@ -83,11 +91,11 @@ Item myItem {mqtt="[::::[::::]" } @@ -113,11 +125,11 @@ Item itemName { mqtt="[::::` is not given, and the number | doors | defines doors | | status | defines a status item | | module | defines connection status item | +| trouble | defines a trouble | +| trouble_memory | defines memory of a trouble | ### Valid state_type values for "zone" objects @@ -111,7 +113,7 @@ Number items can be used only if `` is not given, and the number | Type | Notes | |-------------|-------| -| opened | ON command opens the doors. | +| opened | ON command opens the door. | | opened_long | | @@ -137,6 +139,118 @@ Number items can be used only if `` is not given, and the number | connection_errors | number of consecutive connection errors; clears on successful connection | +### Valid `state_type` values for "trouble" objects + +| Type | Notes | +|------|-------| +| technical_zone | object number range: 1-128 | +| expander_ac | object number range: 1-64 | +| expander_batt | object number range: 1-64 | +| expander_nobatt | object number range: 1-64 | +| system | object number range: 1-24, see table below | +| ptsa_ac | AC trouble of CA-64 PTSA modules, object number range: 1-8 | +| ptsa_batt | BATT trouble of CA-64 PTSA modules, object number range: 1-8 | +| ptsa_nobatt | NO BATT trouble of CA-64 PTSA modules, object number range: 1-8 | +| ethm1 | object number range: 1-8 | +| proximity_a | object number range: 1-64 | +| proximity_b | object number range: 1-64 | +| expander_overload | object number range: 1-64 | +| jammed_acu100 | object number range: 1-16 | +| device_lobatt | object number range: 1-120 | +| device_nocomm | object number range: 1-120 | +| output_nocomm | object number range: 1-120 | +| expander_nocomm | object number range: 1-64 | +| expander_switcherooed | object number range: 1-64 | +| keypad_nocomm | object number range: 1-8 | +| keypad_switcherooed | object number range: 1-8 | +| ethm1_nolan | object number range: 1-8 | +| expander_tamper | object number range: 1-64 | +| keypad_tamper | object number range: 1-8 | +| keypad_init | object number range: 1-8 | +| auxiliary_stm | object number range: 1-8 | +| master_keyfob | object number range: 1-8 | +| user_keyfob | object number range: 1-240 | +| device_lobatt1 | for Integra 256 Plus - last 120 devices, object number range: 1-120 | +| device_nocomm1 | for Integra 256 Plus - last 120 devices, object number range: 1-120 | +| output_nocomm1 | for Integra 256 Plus - last 120 devices, object number range: 1-120 | +| technical_zone1 | for Integra 256 Plus - zones 129..256, object number range: 1-128 | + + +### Valid `state_type` values for "trouble_memory" objects + +| Type | Notes | +|------|-------| +| technical_zone | object number range: 1-128 | +| expander_ac | object number range: 1-64 | +| expander_batt | object number range: 1-64 | +| expander_nobatt | object number range: 1-64 | +| system | object number range: 1-24, see table below | +| ptsa_ac | AC trouble of CA-64 PTSA modules, object number range: 1-8 | +| ptsa_batt | BATT trouble of CA-64 PTSA modules, object number range: 1-8 | +| ptsa_nobatt | NO BATT trouble of CA-64 PTSA modules, object number range: 1-8 | +| ethm1 | object number range: 1-8 | +| proximity_a | object number range: 1-64 | +| proximity_b | object number range: 1-64 | +| expander_overload | object number range: 1-64 | +| jammed_acu100 | object number range: 1-16 | +| lcd_restart | object number range: 1-8 | +| expander_restart | object number range: 1-64 | +| device_lobatt | object number range: 1-120 | +| device_nocomm | object number range: 1-120 | +| output_nocomm | object number range: 1-120 | +| expander_nocomm | object number range: 1-64 | +| expander_switcherooed | object number range: 1-64 | +| keypad_nocomm | object number range: 1-8 | +| keypad_switcherooed | object number range: 1-8 | +| ethm1_nolan | object number range: 1-8 | +| expander_tamper | object number range: 1-64 | +| keypad_tamper | object number range: 1-8 | +| keypad_init | object number range: 1-8 | +| auxiliary_stm | object number range: 1-8 | +| long_violation | object number range: 1-128 | +| no_violation | object number range: 1-128 | +| zone_tamper | object number range: 1-128 | +| technical_zone1 | for Integra 256 Plus - zones 129..256, object number range: 1-128 | +| user_keyfob | object number range: 1-240 | +| device_lobatt1 | for Integra 256 Plus - last 120 devices, object number range: 1-120 | +| device_nocomm1 | for Integra 256 Plus - last 120 devices, object number range: 1-120 | +| output_nocomm1 | for Integra 256 Plus - last 120 devices, object number range: 1-120 | +| long_violation1 | for Integra 256 Plus - zones 129..256, object number range: 1-128 | +| no_violation1 | for Integra 256 Plus - zones 129..256, object number range: 1-128 | +| zone_tamper1 | for Integra 256 Plus - zones 129..256, object number range: 1-128 | + + +### System troubles + +| Number | Description | +|------|-------------| +| 1 | OUT1 trouble | +| 2 | OUT2 trouble | +| 3 | OUT3 trouble | +| 4 | OUT4 trouble | +| 5 | +KPD trouble | +| 6 | +EX1 or +EX2 trouble | +| 7 | BATT trouble | +| 8 | AC trouble | +| 9 | DT1 trouble | +| 10 | DT2 trouble | +| 11 | DTM trouble | +| 12 | RTC trouble | +| 13 | no DTR signal | +| 14 | no BATT present | +| 15 | external modem initialization trouble | +| 16 | external model command (ATE0V1Q0H0S0=0) trouble | +| 17 | no voltage on telephone line (INTEGRA 24, 32, 64 and 128) | +| 17 | auxiliary ST processor trouble (INTEGRA 128-WRL) | +| 18 | bad signal on telephone line | +| 19 | no signal on telephone line | +| 20 | monitoring to station 1 trouble | +| 21 | monitoring to station 2 trouble | +| 22 | EEPROM or access to RTC trouble | +| 23 | RAM memory trouble | +| 24 | INTEGRA main panel restart memory | + + ### Valid options | Name | Description | @@ -415,7 +529,7 @@ To control Integra partitions and outputs, you need to provide security code of ### Disarming and clearing alarms -Although this binding allows you to configure disarming a partition and clearing alarms for a partion, this should be used only in cases when security is not the priority. Don't forget both these operations can be executed in openHAB without specifying a user code, which is required to disarm or clear alarms using Integra panel. Consider adding a keypad in your sitemap to temporarily change user code to execute sensitive operations. You can find such keypad in the [examples](#examples) section. +Although this binding allows you to configure disarming a partition and clearing alarms for a partition, this should be used only in cases when security is not the priority. Don't forget both these operations can be executed in openHAB without specifying a user code, which is required to disarm or clear alarms using Integra panel. Consider adding a keypad in your sitemap to temporarily change user code to execute sensitive operations. You can find such keypad in the [examples](#examples) section. ## Media @@ -423,4 +537,4 @@ Although this binding allows you to configure disarming a partition and clearing ## Future -* troubles support (detailed) +* OH2 version diff --git a/_bindings/sensebox/readme.md b/_bindings/sensebox/readme.md new file mode 100644 index 000000000..8a60fb811 --- /dev/null +++ b/_bindings/sensebox/readme.md @@ -0,0 +1,120 @@ +--- +id: sensebox +label: senseBox +title: senseBox - Bindings +type: binding +description: "The senseBox binding integrates environment data from the [senseBox](https://sensebox.de/)" +since: 2x +logo: images/addons/sensebox.png +install: manual +--- + + + +{% include base.html %} + +# senseBox Binding + +The senseBox binding integrates environment data from the [senseBox](https://sensebox.de/) +Citizen Science Toolkit. + +## Prerequisites + +The API server uses Letsencrypt certificates. Therefore, one needs to either import the Letsencrypt +root certificates into the local keystore (see the description in the +[netatmo addon](http://docs.openhab.org/addons/bindings/netatmo/readme.html)). +Another way would be to simply update the JDK to at least JDK 1.8.0_111 + +## Supported Things + +This binding supports a generic "senseBox" API endpoint which is a representation of the physical box. + +## Discovery + +This binding provides no discovery. The desired senseBox must be configured manually or via a things file. + +## Binding configuration + +The binding has no configuration options itself, all configuration is done at 'Things' level. + +## Thing configuration + +The senseBox thing requires the box Id (which can be obtained on the map) and an interval in seconds +for the API polling. The senseBox support team wrote in an email that polling even every five minutes +is still o.k., therefore the minimum is hardcoded to be 300 seconds. + +``` +Thing sensebox:box:home [ senseBoxId = "foothesmurfingbar", refreshInterval = 600 ] +``` + +## Channels + +In the table is shown more detailed information about each Channel type. +The binding introduces the following channels: + +| Channel ID | Channel Description | Supported item type | Advanced | +|-------------------------------------------------|--------------------------------------------------------------|---------------------|----------| +| descriptors#location | Location of the box | Point | False | +| measurements#uvIntensity | Intensity of Ultraviolet radiation | Number | False | +| measurements#luminance | Illuminance | Number | False | +| measurements#pressure | Air pressure | Number | False | +| measurements#humidity | Humidity | Number | False | +| measurements#temperature | Temperature | Number | False | +| measurements#particulateMatter2dot5 | Particulate Matter 2.5 µm in diameter | Number | False | +| measurements#particulateMatter10 | Temperature Matter 10 µm in diameter | Number | False | +| lastReported#uvIntensityLastReported | The timestamp when uv radiation intensity was last reported | DateTime | True | +| lastReported#luminanceLastReported | The timestamp when illuminance was last reported | DateTime | True | +| lastReported#pressureLastReported | The timestamp when pressure was last reported | DateTime | True | +| lastReported#humidityLastReported | The timestamp when humidity was last reported | DateTime | True | +| lastReported#temperatureLastReported | The timestamp when temperature was last reported | DateTime | True | +| lastReported#particulateMatter2dot5LastReported | The timestamp when particulate matter 2.5 was last reported | DateTime | True | +| lastReported#particulateMatter10LastReported | The timestamp when particulate matter 10 was last reported | DateTime | True | + +The channels starting with "descriptors" are defined on the API server. + +## Full example + +sensebox.things: + +``` +Thing sensebox:box:zugspitze [ senseBoxId = "578cf2ccccff9d1000bd9198", refreshInterval = 900 ] +``` + +sensebox.items: + +``` +Location Zugspitze_Location (Zugspitze) { channel="sensebox:box:zugspitze:descriptors#location" } + +Number Zugspitze_Humidity "Zugspitze Humidity [%.1f %%]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#humidity" } +Number Zugspitze_Luminance "Zugspitze Light Level [%.1f lx]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#luminance" } +Number Zugspitze_Pressure "Zugspitze Pressure [%.1f hPa]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#pressure" } +Number Zugspitze_Temperature "Zugspitze Temperature [%.1f °C]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#temperature" } +Number Zugspitze_UVIntensity "Zugspitze UvIntensity [%.1f μW/cm²]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#uvIntensity" } +Number Zugspitze_PM2dot5 "Zugspitze PM2.5 [%.1f µg/m³]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#particulateMatter2dot5" } +Number Zugspitze_PM10 "Zugspitze PM10 [%.1f µg/m³]" (Zugspitze, Weather) { channel="sensebox:box:zugspitze:measurements#particulateMatter10" } + +``` + +sensebox.sitemap: + +``` +sitemap sensebox label="SenseBox Zugspitze" { + Text item=Zugspitze_Temperature + Text item=Zugspitze_Pressure + Text item=Zugspitze_Humidity + Text item=Zugspitze_Luminance + Text item=Zugspitze_UVIntensity + Text item=Zugspitze_PM2dot5 + Text item=Zugspitze_PM10 + Mapview item=Zugspitze_Location height=10 +} +``` + +## senseBox API + +* https://docs.opensensemap.org/ +* https://docs.opensensemap.org/#api-Boxes-findBox +* https://docs.opensensemap.org/#api-Measurements-getMeasurements + +* https://api.opensensemap.org/boxes/:boxId +* https://api.opensensemap.org/boxes/:senseBoxId/sensors diff --git a/_bindings/serial1/readme.md b/_bindings/serial1/readme.md index c795ff159..416be13a1 100644 --- a/_bindings/serial1/readme.md +++ b/_bindings/serial1/readme.md @@ -64,20 +64,24 @@ This binding does not have a configuration. ## Item Configuration -The format has three variations: +The format has the following variations: ``` serial="@" serial="@,REGEX()" serial="@,BASE64 +serial="@,ON(),OFF()" +serial="@,REGEX(), UP(),DOWN(), STOP()" ``` where: * `` is the identification of the serial port on the host system, e.g. `COM1` on Windows, `/dev/ttyS0` on Linux or `/dev/tty.PL2303-0000103D` on Mac. The same `` can be bound to multiple items. * `` is the baud rate of the port. Backward compatibility is given; if no baud rate is specified the serial binding defaults to 9600 baud. -* `REGEX()` allows parsing for special strings or numbers in the serial stream. This is based on the [RegEx Service](https://github.com/openhab/openhab1-addons/wiki/Transformations#regex-transformation-service). This is optional. +* `REGEX()` allows parsing for special strings or numbers in the serial stream. You can use a capture group (e.g. REGEX(Position:([0-9.]*)) to capture 12 in "Position:12" or substitution (e.g. REGEX(s/Position:100/ON/) or REGEX(s/Position:100/ON/g)) to replace (FIRST or ALL) "Position:100" strings in response with "ON". This is based on the [RegEx Service](https://github.com/openhab/openhab1-addons/wiki/Transformations#regex-transformation-service) and [ESH RegExTransformationService](https://github.com/eclipse/smarthome/tree/master/extensions/transform/org.eclipse.smarthome.transform.regex). This is optional. * `BASE64` enables the Base64 mode. With this mode all data received on the serial port is saved in Base64 format. In this mode also all data that is sent to the serial port has to be Base64 encoded. (This was implemented because some serial devices are using bytes that are not supported by the REST interface). +* `ON(),OFF()` if used in conjunction with a Switch this mapping will send specific commands to serial port and also match a serial command to specific ON/OFF state. This way you don't have to use a rule to send a command to serial +* `UP(),DOWN(),STOP()` if used in conjunction with a Rollershutter this mapping will send specific commands to serial port. Use REGEX to parse Rollershutter postion (0-100%) comming as feedback over serial link Base64 can be decoded in the rules by importing `javax.xml.bind.DatatypeConverter` and then decoding the value like this: @@ -90,7 +94,10 @@ For encoding use the `printBase64Binary` method of the `DatatypeConverter`. This As a result, your lines in the items file might look like these: ``` -Switch HardwareButton "Bell" (Entrance) { serial="/dev/ttyS0" } -String AVR "Surround System" (Multimedia) { serial="/dev/ttyS1@115200" } -Number Temperature "My Temp. Sensor" (Weather) { serial="/dev/ttyS1@115200,REGEX(ID:2.*,T:([0-9.]*))" } +Switch HardwareButton "Bell" (Entrance) { serial="/dev/ttyS0" } +String AVR "Surround System" (Multimedia) { serial="/dev/ttyS1@115200" } +Number Temperature "My Temp. Sensor" (Weather) { serial="/dev/ttyS1@115200,REGEX(ID:2.*,T:([0-9.]*))" } +Switch SerialRelay "Relay Q1" (Entrance) { serial="/dev/ttyS0,ON(Q1_ON\n),OFF(Q1_OFF\n)" } +Rollershutter SerialRollo "Entrance Rollo" (Entrance) { serial="/dev/ttyS0,REGEX(Position:([0-9.]*)),UP(Rollo_UP\n),DOWN(Rollo_Down\n),STOP(Rollo_Stop\n)" } +Switch RoloAt100 "Rolo at 100" (Entrance) { serial="/dev/ttyS0,REGEX(s/Position:100/ON/)" } ``` diff --git a/_bindings/synopanalyzer/readme.md b/_bindings/synopanalyzer/readme.md new file mode 100644 index 000000000..a0ab2416c --- /dev/null +++ b/_bindings/synopanalyzer/readme.md @@ -0,0 +1,71 @@ +--- +id: synopanalyzer +label: Synop Analyzer +title: Synop Analyzer - Bindings +type: binding +description: "This binding integrates the possibility to download and interpret Synop messages." +since: 2x +install: auto +--- + + + +{% include base.html %} + +# Synop Analyzer Binding + +This binding integrates the possibility to download and interpret Synop messages. + +## Binding Configuration + +The binding has no configuration options itself, all configuration is done at 'Things' level. + +## Supported Things + +There is exactly one supported thing, which represents a Synop message. It has the id `synopanalyzer`. + +## Thing Configuration + +Besides the Synop Station Number (as ```synopID``` as a [StationID](http://www.ogimet.com/gsynop_nav.phtml.en) string), the second configuration parameter is ```refreshInterval``` which defines the refresh interval in minutes. Synop message are typically updated every hour. + + +## Channels + +The weather information that is retrieved is available as these channels: + +| Channel Type ID | Item Type | Description | +|---------------------|-----------|--------------------------------------------| +| temperature | Number | The current temperature in degrees Celsius | +| pressure | Number | The current pressure in millibar (mb) | +| wind-angle | Number | Wind angle in degrees | +| wind-direction | String | Wind direction | +| wind-speed-ms | Number | Wind speed in m/s | +| wind-speed-knots | Number | Wind speed in knots | +| wind-speed-beaufort | Number | Wind speed according to Beaufort scale | +| overcast | String | Appreciation of the cloud cover | +| octa | Number | Part of the sky covered by clouds (in 8th) | +| time-utc | DateTime | Observation time of the Synop message | + + +## Example + +### Things + +Here is an example of thing definition : + +``` +synopanalyzer:synopanalyzer:orly [ stationId="07149"] +``` + +### Items + +``` +Number Synop_Temperature "Temperature [%.1f °C]" { channel = "synopanalyzer:synopanalyzer:trappes:temperature" } +Number Synop_Pressure "Pressure [%.1f mb]" { channel = "synopanalyzer:synopanalyzer:trappes:pressure" } +Number Synop_Wind_Angle "Wind Angle [%d°]" { channel = "synopanalyzer:synopanalyzer:trappes:wind-angle"} +String Synop_Wind_Direction "Direction [%s]" { channel = "synopanalyzer:synopanalyzer:trappes:wind-direction"} +Number Synop_Wind_Speed "Wind Speed [%.2f m/s]" { channel = "synopanalyzer:synopanalyzer:trappes:wind-speed-ms"} +Number Synop_Octa "Octa [%d]/8" { channel = "synopanalyzer:synopanalyzer:trappes:octa"} +DateTime Synop_time "Observation Time [%1$ta %1$tR]" { channel = "synopanalyzer:synopanalyzer:trappes:time-utc"} +``` + diff --git a/_bindings/systeminfo/readme.md b/_bindings/systeminfo/readme.md index d92753cdf..c951d9c26 100644 --- a/_bindings/systeminfo/readme.md +++ b/_bindings/systeminfo/readme.md @@ -25,7 +25,7 @@ System information Binding provides operating system and hardware information in - Battery information - estimated remaining time, capacity, name; - Sensors information - CPU voltage and temperature, fan speeds; - Display information; - - Network IP,name and adapter name, mac, data sent and received, packages sent and received; + - Network IP,name and adapter name, mac, data sent and received, packets sent and received; - Process information - size of RAM memory used, CPU load, process name, path, number of threads. The binding uses [OSHI](https://github.com/oshi/oshi) API to access this information regardless of the underlying platform and does not need any native parts. @@ -77,11 +77,11 @@ The binding support several channel group. Each channel group, contains one or m **thing** `computer` * **group** `memory` - **channel** `available, total, used, available_percent` + **channel** `available, total, used, availablePercent, usedPercent` * **group** `swap` - **channel** `available, total, used, available_percent` + **channel** `available, total, used, availablePercent, usedPercent` * **group** `storage` (deviceIndex) - **channel** `available, total, used, available_percent, name, description, type` + **channel** `available, total, used, availablePercent, usedPercent, name, description, type` * **group** `drive` (deviceIndex) **channel** `name, model, serial` * **group** `display` (deviceIndex) @@ -93,7 +93,7 @@ The binding support several channel group. Each channel group, contains one or m * **group** `sensors` **channel** `cpuTemp, cpuVoltage, fanSpeed` * **group** `network` (deviceIndex) - **channel** `ip, mac, networkDisplayName, networkName, packagesSent, packagesReceived, dataSent, dataReceived` + **channel** `ip, mac, networkDisplayName, networkName, packetsSent, packetsReceived, dataSent, dataReceived` * **group** `process` (pid) **channel** `load, used, name, threads, path` @@ -107,6 +107,8 @@ The groups marked with "deviceIndex" may have device index attached to the Chann The binding uses this index to get information about a specific device from a list of devices. (e.g on a single computer could be installed several local disks with names C:\, D:\, E:\ - the first will have deviceIndex=0, the second deviceIndex=1 ant etc). If device with this index is not existing, the binding will display an error message on the console. + +Unfortunately this feature can't be used at the moment without manually adding these new channel groups to the thing description (located in ESH-INF/thing/computer.xml). In the table is shown more detailed information about each Channel type. The binding introduces the following channels: @@ -124,6 +126,7 @@ The binding introduces the following channels: | used | Used size in MB | Number | High | False | | total | Total size in MB | Number | Low | False | | availablePercent | Available size in % | Number | High | False | +| usedPercent | Used size in % | Number | High | False | | model | The model of the device | String | Low | True | | serial | The serial number of the device | String | Low | True | | description | Description of the device | String | Low | True | @@ -138,8 +141,8 @@ The binding introduces the following channels: | mac | MAC address | String | Low | True | | networkName | The name of the network | String | Low | False | | networkDisplayName | The display name of the network | String | Low | False | -| packagesSent | Number of packages sent | Number | Medium | True | -| packagesReceived | Number of packages received | Number | Medium | True | +| packetsSent | Number of packets sent | Number | Medium | True | +| packetsReceived | Number of packets received | Number | Medium | True | | dataSent | Data sent in MB | Number | Medium | True | | dataReceived | Data received in MB | Number | Medium | True | @@ -198,8 +201,8 @@ String Network_IP { channel="systeminfo:computer:work:network# String Network_Mac { channel="systeminfo:computer:work:network#mac" } Number Network_DataSent { channel="systeminfo:computer:work:network#dataSent" } Number Network_DataRecevied { channel="systeminfo:computer:work:network#dataReceived" } -Number Network_PackagesSent { channel="systeminfo:computer:work:network#packagesSent" } -Number Network_PackagesRecevied { channel="systeminfo:computer:work:network#packagesReceived" } +Number Network_PacketsSent { channel="systeminfo:computer:work:network#packetsSent" } +Number Network_PacketsRecevied { channel="systeminfo:computer:work:network#packetsReceived" } /* CPU information*/ String CPU_Name { channel="systeminfo:computer:work:cpu#name" } @@ -224,18 +227,21 @@ Number Storage_Available { channel="systeminfo:computer:work:storage Number Storage_Used { channel="systeminfo:computer:work:storage#used" } Number Storage_Total { channel="systeminfo:computer:work:storage#total" } Number Storage_Available_Percent { channel="systeminfo:computer:work:storage#availablePercent" } +Number Storage_Used_Percent { channel="systeminfo:computer:work:storage#usedPercent" } /* Memory information*/ Number Memory_Available { channel="systeminfo:computer:work:memory#available" } Number Memory_Used { channel="systeminfo:computer:work:memory#used" } Number Memory_Total { channel="systeminfo:computer:work:memory#total" } Number Memory_Available_Percent { channel="systeminfo:computer:work:memory#availablePercent" } +Number Memory_Used_Percent { channel="systeminfo:computer:work:memory#usedPercent" } /* Swap memory information*/ Number Swap_Available { channel="systeminfo:computer:work:swap#available" } Number Swap_Used { channel="systeminfo:computer:work:swap#used" } Number Swap_Total { channel="systeminfo:computer:work:swap#total" } Number Swap_Available_Percent { channel="systeminfo:computer:work:swap#availablePercent" } +Number Swap_Used_Percent { channel="systeminfo:computer:work:swap#usedPercent" } /* Battery information*/ String Battery_Name { channel="systeminfo:computer:work:battery#name" } @@ -251,9 +257,9 @@ Number Sensor_CPUVoltage { channel="systeminfo:computer:work:sensors Number Sensor_FanSpeed { channel="systeminfo:computer:work:sensors#fanSpeed" } /* Process information*/ -Number Process_load { channel="systeminfo:computer:SvilenV-L540:process#load" } -Number Process_used { channel="systeminfo:computer:SvilenV-L540:process#used" } -String Process_name { channel="systeminfo:computer:SvilenV-L540:process#name" } -Number Process_threads { channel="systeminfo:computer:SvilenV-L540:process#threads" } -String Process_path { channel="systeminfo:computer:SvilenV-L540:process#path" } +Number Process_load { channel="systeminfo:computer:work:process#load" } +Number Process_used { channel="systeminfo:computer:work:process#used" } +String Process_name { channel="systeminfo:computer:work:process#name" } +Number Process_threads { channel="systeminfo:computer:work:process#threads" } +String Process_path { channel="systeminfo:computer:work:process#path" } ``` diff --git a/_bindings/zway/readme.md b/_bindings/zway/readme.md index 9f57ac6d2..27fc0c8d1 100644 --- a/_bindings/zway/readme.md +++ b/_bindings/zway/readme.md @@ -144,10 +144,11 @@ The following channels represent universial channels if no further device inform | switchBinary | Switch | Switch | SwitchBinary | | switchMultilevel | Dimmer | - | SwitchMultilevel | | switchColor | Color | ColorLight | SwitchRGBW | -| switchControl | Switch | Switch | SwitchControl | +| switchControl | Switch | Switch | SwitchControl, ToggleButton, SwitchToggle | | thermostat | Number | Temperature | Thermostat | +| sensorDiscrete | Number | - | SensorDiscrete | -Currently unsupported Z-Way device types: SwitchToggle, ToggleButton. +Unsupported Z-Way device types: Camera, SensorMultiline, Text. The integration of these types isn't planned. ### Channels for the Z-Way Server (Bridge) @@ -185,7 +186,7 @@ Because textual configuration isn't useful, follow the instructions in the [Gett ### Restrictions - Z-Way device types (especially the probe types) supported by openHAB channels with detailed information (scale types and so on) are not complete. -- Configuration of the Z-Wave network by the binding is currently not possible (device inclusion or physical device configuration) +- Configuration of the Z-Wave network by the binding is currently not possible (physical device configuration) - Z-Way App "openHAB Connector" is required. Further versions will contain other mechanisms under usage of the WebSocket implementation of Z-Way or MQTT.
diff --git a/_iconsets/classic/icons/battery-off.png b/_iconsets/classic/icons/battery-off.png new file mode 100644 index 0000000000000000000000000000000000000000..d23cf0b4c6a643b60587f3a83c415e82b4e6f0ab GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!q5^zETtR{k4z`Z&*7j~D7WOs{ zZg!3y9<6Z_r+gVs*f4C;`taeyojZ3^Gjf6Aw{PFEv~@MNcHFn`#DayZt?XUrFIZ(^ z?F7{B-W(@+$}c57$JWWi&dF27)ANx0`vpMLd*fm@NLTfw_gAM zzxnU^;phKvlP0t8`FmyqP-UT~i(^OyxLlliRL9xk<^D4TjAAm+ML+m+ zvoIL&%-*p=U3Bq&PwD8RKer1A|1C_GX0r4CCA>}Z0V`8n&D5Q?8*0`>rzZ$b$JU + + + + + + + + diff --git a/_iconsets/classic/icons/battery-on.png b/_iconsets/classic/icons/battery-on.png new file mode 100644 index 0000000000000000000000000000000000000000..389445154fe8d0cf7bc8ec1e418131a4355a3b2c GIT binary patch literal 314 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!q5^zETtR{k4z`Z&*7j~D7WOs{ zZg!3y{a(TEB(y#-h+Jck`taeyojZ3^Gjf6Aw{PFEv~@MNcHFn`#DayZt?XUrFIZ(^ z?F7``>lyq`QadF*$JWWi&dF27)3fuzb&$1kB|(0{3>?!w{{Jxb=YJ6RHs$|YumAtw z{P+Cu^Z&O=liBzDJ+lF*ve47TF{I+w+p8xT8x(k40xvFj&?NotR{iW*%&aUn=d>T( zH#*6{P`CI~)02{wP73RLQcIODmg%u@B`;;X_F6zeo8Q1`fnw5O3Hcc}-UKuC2skh> zZu@bh_?x!b$IVOa#J0-|HvZe=6KFYur>mdKI;Vst E0EC)?O#lD@ literal 0 HcmV?d00001 diff --git a/_iconsets/classic/icons/battery-on.svg b/_iconsets/classic/icons/battery-on.svg new file mode 100644 index 000000000..202af8c95 --- /dev/null +++ b/_iconsets/classic/icons/battery-on.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/_iconsets/classic/icons/colorpicker.png b/_iconsets/classic/icons/colorpicker.png new file mode 100644 index 0000000000000000000000000000000000000000..684c419e315306b7d67457fea1c4abb283a0fc12 GIT binary patch literal 2399 zcmV-l3840gP)nJd!Lxq(-m8)tSqa{~vN?+4OY{EWx& zJ3I%^#cS|d_%g;3H!p>eNp`vA;zkzG$!vVi&8K)ReHAAn373~ z7@64YlFxUKmRTpV@)q!8k(I6xxkpQ#1T$3*MK(1A!?ThH^FhLncBxAiGJwEi>-_dC z6JG(&w`Z6T+^Z*Hz;Oaf9~=V-Ok)Bl**6N9#E^aj9k)s1X1)UGgV2n?6B*@B_#;tbDy7O^m+7)!H8hK)=>^6f-ea*fXFEe(I5=JN?Lsu za1>e*h?j&4(5TfQ5)8gGMtJ~1csFtG5VIkW;x0f$u~T{oVR%c>!2uy81e^}f(VU4` z=e`%4U?7peyclHRJo;N_T1eoj^I)JZvJ#p=L$n;U;n^h!k0q9%nq%NBpcD+G@S`2R z2qnNLwc%^>Jn-Za7`gZsR{_*n{C0GbHiTY&x1pCFF&x@X}{-r(dCoU4LbCKd4W87<`S-W_QI6Q}z@&B8SW9#DZL zBnKNOUH`uYqrmVU2^XLMCW?0cGD&TCPCvp4EsnGvG3z7+Ld}~X+APFU~+vXlBL9(qcl=~ky`rZdIRSt!Y z6VO8j@7>`h*fY+CM;Tlj_VNG%2_hje#KFiU#T@`az%w0c2y&D|F*_q1gz%m=!GNs} zg1x7ISWb}#h)e>LDCu&<&PfG<^7t62*xArU4DY!i7Qxt@j#z6(2-1GKIH~qY3`Bsy zc~S-ulpbn{;60B;^O(_pDMbkQ)8Q|7RfMkczzZ$mV~Ai!uUiNSkDDOHGy35A!~= zoeveAE_#W3Z0QkIHtb7i*onXsl|6^rA9u!57E@->L>Ant4PQrp1|P9@SQENJ41Nyo z=%^+b`3(93I4J|%rY!S}v{hzds5A;8Cn`g$cEH|*2CWzLq(XG|198hNrs zrrf(1HJeO8I{mePub04A{wDZUe+=^32<>GzLd6LUty>qLy_6GETM5&Y+x>FQzaA=$ z{ZCR`*xA5uBeXxReg~JW@VoK#mcrO`h7Hm)w^v4MohzkUH+F@zdL&`~F$wrNrhkNr z%~r***`{=3Z`zXRTQ;TT(*fmQ21k<349#sTJnqZTo`i#RHD>P?$t&o;j()%GG7 z*RF`J?oom|2>g_~4hS;al6nx7Yuo!2|M};`q|4T! zjsAVbI|#+U3fCunit{j<711@jhy_S%9N&tpQNa|a#VSuVTaz3JLeiVo#N9BOrBSC+ zhy-|+Lif_piU^pZ7;KBf+pUT&1RyPngwKcl@n#_;Ed1u(T3Gc&a0#0lVj{|}q?{H4 zo|R~UvB`+4Dk6oSx2($`%67RS)71s59I1lA>(W(Q^l9B&&o6O*a5>pXJpJ#>y*F>l z1?ph-nLa=YKU&CkIUtKE2I%1ZbjVXf(3=ga;(UF&1L3ix654IbM+V!1VECf2ck(@C z@ZM!5^uTIn8_4^_z%e=61WCRwr7&Nw>iIl4xdap--wWdfcXS!iHT}f!-o<4x3^@)B z9J;X`4qeND!&f8W7j?6-_!*DkcdwuOZsiueYQzg#2np7t2Tgb5LSUjSmsS-B3-2l9 z4H{=0z3HB)8_)dYGQx4~!Df|#`=d|xQ{a$*71A1$(C}FJWmn5&0+xPM-ilxXOTat- z6=VZ0Ss7Lt$8K!wg2HFIXgJtzpG-i=(JS_ReVS893GFt8{kl~e2fk#bv^q~Hcr4^l zw-As^H`lNH1fc|z&?|ox_++`Xx?TBw%@TwT2WP z3p+b4Tm>jAYAgstDxuw)bP5@OEO|3RpYJ?C1fS&^gu^!}gyYmB*QxyTs>dV}e%F%p zL0uip0AZpQL6%d)Tfp}mtqA5zH=WD8&KEvkm-Z2;K?DLP05a(kUIOy(8+{e9y6QKV zdKt|s13=bgB}3YlLSeN?S0z#1ui6%lv-=-m_Tw z3RrOb&(<;E?QiN;Z)H`7&4Fh+FE~;lli3Yx>BfK~ZBD)d@Y>DwtNxhZpxX7CPLT{> z%DmqwhJ$U{P9oh)J; RKrH|O002ovPDHLkV1fgDdXE4A literal 0 HcmV?d00001 diff --git a/_iconsets/classic/icons/colorpicker.svg b/_iconsets/classic/icons/colorpicker.svg new file mode 100644 index 000000000..3ac83c0f2 --- /dev/null +++ b/_iconsets/classic/icons/colorpicker.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/_iconsets/classic/icons/poweroutlet-au.png b/_iconsets/classic/icons/poweroutlet_au.png similarity index 100% rename from _iconsets/classic/icons/poweroutlet-au.png rename to _iconsets/classic/icons/poweroutlet_au.png diff --git a/_iconsets/classic/icons/poweroutlet-au.svg b/_iconsets/classic/icons/poweroutlet_au.svg similarity index 100% rename from _iconsets/classic/icons/poweroutlet-au.svg rename to _iconsets/classic/icons/poweroutlet_au.svg diff --git a/_iconsets/classic/icons/poweroutlet-eu.png b/_iconsets/classic/icons/poweroutlet_eu.png similarity index 100% rename from _iconsets/classic/icons/poweroutlet-eu.png rename to _iconsets/classic/icons/poweroutlet_eu.png diff --git a/_iconsets/classic/icons/poweroutlet-eu.svg b/_iconsets/classic/icons/poweroutlet_eu.svg similarity index 100% rename from _iconsets/classic/icons/poweroutlet-eu.svg rename to _iconsets/classic/icons/poweroutlet_eu.svg diff --git a/_iconsets/classic/icons/poweroutlet-uk.png b/_iconsets/classic/icons/poweroutlet_uk.png similarity index 100% rename from _iconsets/classic/icons/poweroutlet-uk.png rename to _iconsets/classic/icons/poweroutlet_uk.png diff --git a/_iconsets/classic/icons/poweroutlet-uk.svg b/_iconsets/classic/icons/poweroutlet_uk.svg similarity index 100% rename from _iconsets/classic/icons/poweroutlet-uk.svg rename to _iconsets/classic/icons/poweroutlet_uk.svg diff --git a/_iconsets/classic/icons/poweroutlet-us.png b/_iconsets/classic/icons/poweroutlet_us.png similarity index 100% rename from _iconsets/classic/icons/poweroutlet-us.png rename to _iconsets/classic/icons/poweroutlet_us.png diff --git a/_iconsets/classic/icons/poweroutlet-us.svg b/_iconsets/classic/icons/poweroutlet_us.svg similarity index 100% rename from _iconsets/classic/icons/poweroutlet-us.svg rename to _iconsets/classic/icons/poweroutlet_us.svg diff --git a/_io/imperihome/readme.md b/_io/imperihome/readme.md index 25c3788aa..f199ab74b 100644 --- a/_io/imperihome/readme.md +++ b/_io/imperihome/readme.md @@ -54,9 +54,8 @@ ImperiHome must be configured to connect to your openHAB instance. Start ImperiHome, open the menu and go to My Systems. Add a new system (+) and choose 'ImperiHome Standard System' as the object type. Now enter the URL to your openHAB instance as Local URL, followed by _/imperihome/iss_. For example, if your openHAB instance is running at _http://192.168.1.10:8080/_, the Local URL would be _http://192.168.1.10:8080/imperihome/iss_. -If you have port forwarding or similar set up to access your OH form the internet, you can also fill the Remote URL in the same way. For example: -_http://my-openhab-url.dyndns.org:8080/imperihome/iss_. Please be aware that this service provides no authentication mechanism, so anyone could use the API to control your -system when accessible from the internet. +If you have port forwarding or similar set up to access your openHAB from the internet, you can also fill the Remote URL in the same way. For example: +_http://my-openhab-url.dyndns.org:8080/imperihome/iss_. Warning: this service provides no authentication mechanism, so anyone could use the API to control your system when accessible from the internet. Add a secure proxy or use the openHAB Cloud proxy to protect your system ([more information](http://docs.openhab.org/installation/security.html)). Click Next to let ImperiHome validate the URL. After validation succeeded the system is added and you can continue to configure your Items for use in ImperiHome. @@ -225,7 +224,7 @@ the Item types you can use them on are listed.
- + @@ -343,8 +342,8 @@ the Item types you can use them on are listed. - - + + @@ -377,10 +376,10 @@ the Item types you can use them on are listed. - - - - + + + + @@ -398,7 +397,9 @@ the Item types you can use them on are listed.
ChannelItem TypeDescription
bridge_resetSwitchReset the bridge connection.
send_commandSwitchSend a DSC Alarm command.
panel_messageStringEvent messages received from the DSC Alarm system.
panel_system_errorStringDSC Alarm system error.
panel_trouble_messageStringDisplays any trouble messages the panel might send.
panel_ftc_troubleSwitchFailure to communicate with monitoring station.
panel_zone_faultSwitchThere is a fault condition on a zone/sensor.
panel_zone_tamperSwitchThere is a tamper condition on a zone/sensor.
panel_time_low_batterySwitchThere is a low battery condition on a zone/sensor.
panel_zone_low_batterySwitchThere is a low battery condition on a zone/sensor.
panel_time_lossSwitchLoss of time on the panel.
panel_timeDateTimeDSC Alarm system time and date.
panel_time_stampSwitchTurn DSC Alarm message time stamping ON/OFF.
DevDimmer Dimmable light YesDimmerDimmer, Number energy
DevShutter Shutter actuatorNoYesDimmer, Number -
DevThermostatThermostatNo-Thermostat (2)YesNumbercurmode, curtemp
DevUV
-(1) When using a String Item for trippable devices, any non-empty value other than 'ok' will set the device to tripped. This makes it compatible with the Nest Protect binding. +(1) When using a String Item for trippable devices, any non-empty value other than 'ok' will set the device to tripped. This makes it compatible with the Nest Protect binding. + +(2) Thermostat devices require additional tags. See [Thermostat](#thermostat) for details. @@ -411,8 +412,7 @@ The _link_ tag refers to the name of the Item it should link to. The item must b ### Switch energy consumption ImperiHome allows you to show the current energy consumption for a _DevDimmer_, _DevRGBLight_ and _DevSwitch_. -This example links the _MyLightEnergy_ Number Item to the _MyLight_ Switch Item, -so the _DevSwitch_ device will also report the energy consumption value to ImperiHome: +This example links the _MyLightEnergy_ Number Item to the _MyLight_ Switch Item, so the _DevSwitch_ device will also report the energy consumption value to ImperiHome: ``` Switch MyLight "My Light" ["iss:type:DevSwitch", "iss:link:energy:MyLight_Energy"] { channel="zwave:device:1:node14:switch_binary1" } @@ -421,8 +421,7 @@ Number MyLightEnergy "My Light Usage [%.1f W]" ["iss:type:DevElectricity"] ### Total energy consumption -The _DevElectricity_ devices main value is the current consumption in Watts. To add the total consumption in KWh, link your electricity device to -a generic sensor device containing the total energy consumption value: +The _DevElectricity_ devices main value is the current consumption in Watts. To add the total consumption in KWh, link your electricity device to a generic sensor device containing the total energy consumption value: ``` Number MyLight_Energy "My Light Usage [%.1f W]" ["iss:type:DevElectricity", "iss:link:kwh:MyLight_Total_Energy"] { channel="zwave:device:1:node14:meter_watts1" } @@ -447,8 +446,7 @@ Number MyHum "Humidity [%d%%]" ["iss:type:DevTempHygro", "iss:link:temp ### Rain accumulation -The _DevRain_ devices main value is the current instant rain value (default in mm per hour). To add the total rain accumulation value, link your rain device to -a generic sensor device: +The _DevRain_ devices main value is the current instant rain value (default in mm per hour). To add the total rain accumulation value, link your rain device to a generic sensor device: ``` Number RainCurrent "Rain current [%.1f mm/h]" ["iss:type:DevRain", "iss:link:accum:RainAccumulation"] { channel="..." } @@ -457,14 +455,27 @@ Number RainAccumulation "Rain accumulation [%.1f mm]" ["iss:type:DevGenericSe ### Wind direction -The _DevWind_ devices main value is the current wind speed (default in km per hour). To add the wind direction value (default in degrees), link your wind device to -a generic sensor device: +The _DevWind_ devices main value is the current wind speed (default in km per hour). To add the wind direction value (default in degrees), link your wind device to a generic sensor device: ``` Number WindSpeed "Wind speed [%.1f km/h]" ["iss:type:DevWind", "iss:link:direction:WindDirection"] { channel="..." } Number WindDirection "Wind direction [%d deg]" ["iss:type:DevGenericSensor", "iss:unit:deg"] { channel="..." } ``` + + +### Thermostat + +The _DevThermostat_ combines a setpoint, current temperature and mode in one ImperiHome device. To accomplish this using openHAB items, it uses a _curtemp_ and _curmode_ link and a few additional tags. + + ``` + Number Thermos_Setpoint "Thermostat" ["iss:room:Test", "iss:type:DevThermostat", "iss:step:0.5", "iss:minVal:15", "iss:maxVal:24", "iss:modes:Home,Away,Comfort,Sleeping", "iss:link:curmode:Thermos_Mode", "iss:link:curtemp:Thermos_Temp"] { channel="..." } + Number Thermos_Temp "Thermos temp" ["iss:room:Test", "iss:type:DevTemperature", "iss:unit:K"] { channel="..." } + String Thermos_Mode "Thermos mode" ["iss:room:Test", "iss:type:DevGenericSensor"] { channel="..." } + ``` + + The main _DevThermostat_ device must be the Item holding the setpoint. Using tags, this device specifies the minimum and maximum setpoint value, the setpoint step and the available modes. The two links specify what Items contain the current temperature and current mode. If you want to use a custom unit, set the _unit_ tag on the current temperature device. + ## Items example ``` diff --git a/_repos/openhab b/_repos/openhab index d16d4a02a..4ed5f59a5 160000 --- a/_repos/openhab +++ b/_repos/openhab @@ -1 +1 @@ -Subproject commit d16d4a02a30e1dedb36874d8bb8847d4602c84e5 +Subproject commit 4ed5f59a5783b099accbf7256a628e891077a771 diff --git a/_repos/openhab-bundles b/_repos/openhab-bundles index 5b4477181..eba009446 160000 --- a/_repos/openhab-bundles +++ b/_repos/openhab-bundles @@ -1 +1 @@ -Subproject commit 5b4477181f86efd252138227019d3497316fb2df +Subproject commit eba0094465c37d42089c26ada127e734a4ba0e56 diff --git a/_repos/openhab-distro b/_repos/openhab-distro index c6fc306e9..c4abbeecb 160000 --- a/_repos/openhab-distro +++ b/_repos/openhab-distro @@ -1 +1 @@ -Subproject commit c6fc306e9f4fab0fb9a1540f0589720e94a44b28 +Subproject commit c4abbeecb9810bff01ed2b96fba7733672e2ef35 diff --git a/_repos/openhab2-addons b/_repos/openhab2-addons index 8b94f8115..7b76fc694 160000 --- a/_repos/openhab2-addons +++ b/_repos/openhab2-addons @@ -1 +1 @@ -Subproject commit 8b94f811511e0a62bc9973612c8dbfb3860e99f4 +Subproject commit 7b76fc69415a4d478aa0e0016ba49a5bc9fd6a64 diff --git a/_repos/smarthome b/_repos/smarthome index 463e6601e..3d7f34d40 160000 --- a/_repos/smarthome +++ b/_repos/smarthome @@ -1 +1 @@ -Subproject commit 463e6601ef9c744a15f461e8192d776d16da37f9 +Subproject commit 3d7f34d40d79e7cc9666bf477a03e40eb68f7001 diff --git a/_uis/habpanel/doc/add-widget.png b/_uis/habpanel/doc/add-widget.png new file mode 100644 index 0000000000000000000000000000000000000000..58baa43b508abf1e1a38fb2c76b1e312849b1ca4 GIT binary patch literal 12987 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 S5B!G{kmgN2^)l6m;r|VKeScv9 literal 0 HcmV?d00001 diff --git a/_uis/habpanel/doc/custom-widget-context-menu.png b/_uis/habpanel/doc/custom-widget-context-menu.png new file mode 100644 index 0000000000000000000000000000000000000000..f0b11efc9770d08f42680aeaff0a2fe4dd792e9c GIT binary patch literal 3338 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 J*P0Fw{sIlt3_bt= literal 0 HcmV?d00001 diff --git a/_uis/habpanel/doc/dashboard-designer-placeholder-menu.png b/_uis/habpanel/doc/dashboard-designer-placeholder-menu.png new file mode 100644 index 0000000000000000000000000000000000000000..1fe55b53ab520ed69133bd73f14088e60a0f6576 GIT binary patch literal 5446 zcmb_gcT`i&w#QEp1?d6`0s>-a37^u$Py|6BGzA3#X+eT?AwWO~Tv18@rMEy(s`}9k z9iku-nizsK0|{V2nk1n~Z#Q_~d+WaS)?4?kx85H!zcXj{{ASOdJ$ugCs9WZSTpS`C zEG#Ts#zy*NImUAG1oKJ!Od^R1$KaNRdMuTF=NFg_R(D-9T^1H>66c-^8?$}t zk&!K&g@wEQs2uC^d-H&WO?tVB!DLw1ap{4iuN=%glfo*W*r}1f7vuWEJK}35w#3?!ML*t@j|e zAMhFSESO&&pl>t(m;3IsPL^I5by+KF!G70}=}Q-@FGJCD=*s{l&Pw970yw}Ez(quZ z)GRH)$T|(T88+C2lN$OmJd?fGEvLUppe{`Vi+n3)&FHpc^fx7lIc}nR>(Qcqk=^&# zk{n!vlT7*ra6ruV%SZ}Ymo}VLKRiq{Z?B0#(JNnhBoGzsB0kj)CgAhy9#kx-d%|3_ z*n?K9*ObTSn2M2d{5wSk>!+zvLxDG5T=j*%^Hv>LE|-MjK5yN+`hgoer|9%@fhWBH z-k`ormVVK2=)QlGaHaKHdE`4&AXCAgOv${)^?1TH1q5cAB4DxaRlsn)X{z2{3c6x= zI)_wnzcodfemOA*GhuM%8lo_GU|I1lman_&baJ{I_e3@CNX1JW^eIx*e^KLlq?S&S z*$?gT<*mZwRWV8%DCNF)UAj8uwRw1R_ML&eIk=LCvU~Zcw`j_(COf8~hw$8YGlkZ> z=?M;}P~$<#k9)=xXr#JDSEttfh+W2cd8g+pnkHtnm9+!Qp@CAfHytJ9sflCGtDo*} z0ONyNNO{gTon(ni((WMau4`_N`vKvAhKGgKm*DV^H~eYyqrqZ2RuVG`4k|}m-k#<= zkx51f7YCQO?g+u1m!7ow$fv}(zePRgwGzs=vMRx__2^BL6JJW5wYfZ?jK1Q_;J{Vp zkxt84`hJpAAf(&?kQ*$TZ$*5vPt<%XZs+v|Bdp zUzKQk9M~Fj<}O(pX+@oAt}`Q%K#}q2uUa z`#0fChfxf|wpG#%ooVM4)LYktdu@#u>G(xRf`jkgeP~v!zgM%*$%AhR zmCDCc50n0}gE4VjcRVMBe)8fnTQvuCW;^;J(&~jHQo(iFYUJCQ+G^vXFPO#6SVJZG}{-bywnMSCO&Bf3sj2jLb*lo=8jKdQj(nKApd^&qH)AfNC za;qTCyk_xYu-km<-b!QI7l{*z6}vc6a*R8dpeRLfM!!t3>oAwP!zGn0X#`cw~Sdo(~zhgKf(qLn?4X%0yzw1p_fC0Ibc5<>|F~ElW7nN6lA4K%jHQ6Nkw~1f6{x zlT(z*>BKnGp*{BN>RBug;Xeg4$S5tOKL>Qqeo>r#Glc{hOcTIa+%ChQNm_X%c8GUL zQ=0~*y)C_?FX+bO^Wk?adzRLQgPbC^sO)RQHcm5_uMe54xPQ47{CTfX z7aF-mjh+3hP^Dt^+FVrtU{3q!mgN9z+262NP}SL7nw)&U{E2hBA|v}Lym1a;Xek(` zgFgt`fwuk{FoA6?Q%h~C9CfWL?Cw4+m_%+mDEo}5)I6f=V={vkk>V@tKC*MD1P0 z*4Pcr4U(%Eh~r*Mc++@`N(r>}U}sUNq>f)`_g7^CUHht<9?e2$e<)aocbOV1(WeCD zwsZ`kM$f)$=T`pafWU08bV;mv#XlvbT{5fwG?HqGRchS}sDTkg*7i3i$=8}L_!+2P( zS7lS@uZ6*`^I_p`Eze4@n~;-tgi(b-E4Y{ zhmBI2;0c{AGQnz0vVyBvkB)6uGmjx?SB_~sp?^$cF3&YuYwe3NfiaFF+~Cm~dg6c! z7K~x5YT5a@H`4L;VzB!z>DS!13VZih;gmedP8%oWu;wnUCfKPwatZ~YNhF>;Tm|=L z1g05ddzdToF_cfP7m+r6Q45WUA{F@L(N6xnY4AOY6Lj)Le52;hd=aewmF`9q^!@&r zS5;jk+syb>f>O($uk#=OMc+)rEwzvt2?3Dio^sLyV!jq^WvZhTu{5Ep!IzS`Pj8s) z^DCeMdumDXmLPt6)Rljy+(r?E)Aq-PIp5d}4bt(9pyf%5sL1x~A2nR^%C!v$9$InD&YIfd0vG=e=F?Pr)K=v|T#_Puyrmf<-UMvgn& znoc4EOf$mHT1c<{NV7l>m)Rh$wpeq_Ww}eis8b0L@0|fkcrWo}Z)-$OKhT*+bNO!{ zYW6XRi5{h%8K!F~h8=%2M#Z=cmYNxCTGvA_2CJhS(02G)M=_DPHC)I=C zG2CPy3*vMT2523ArA&2P@#QQ!O%(cJ{pZMYQT57sa|8%oL)6B-^Ai_s`;fb5qPIJZ ziDmZ>=;BRE`~D%AJ@~@S+|R@0anwz3iI~0QA|b4tK(p*#e+AWdy~4i1?i?R)Pbe=>^(|rb zt$-pWq}$Ff%354@pigo(yBq(=;NhnI90rUS6CxY`+&~PPsgKe}CA#|9R`=G3WH)ky zUqc0;YpU6*n>fb?l08zW@lE3`N;K2wiP@oRv!h|aaWCBVY%bkwU`Q3Y^UGO1aeCFB z=D8m1eleH}DlL9Rs)REN+p0bpJ~(0!IWegYZ4`Z+Lh^BvKPSwA^x7eT3idO^Un`v} z3{YJ9u<004fz_!=3>s?dm;qgyD4{s)9$=f6Uj!_aWX(o;B{>1!TKgeNU7+e=ckr*3 zp;?RZ{f{MO{CeKgGd~miCH>}xj+aR7^d_IpX*&C`Y2Wu);b7Kg2M4_>m2}!YGeZ3P zag}k-5k8Q)ulH=@xkZFS(Euo>=+`=btGT7ghw+RU6rqnK2Y#KZl2%IkrMyiH0KQ2$ zq+%z8avMT+Y8dU3JiWzA^uyQE&5Nat&o*p~X?Awzj+0SroL_tz#;u3$ey(!3t^xG-h1%TLh_J(?ym56{(*Bq_w?!v2b(9(>M3e zr^AuUko9Vw!(+OBAJ#MXr?Yl7sXC^zbR*gsetxWqQ46$#gB&es6m{LV+ss%!=L~Mx z(%4%&d|nU=y@8OdN%(AtVftDSTRTnd{ZEB${cgDTjjFugcffzZDh z$c};?Gnfrpgnr2``jyi5c_Qs0K7x7I(5OBAq#eib*$eB!`J+kU z*8?TQbJ!9_*|ObU1v;o=9p+<|;Xtd7;ncqFv7BniehTRr_SBl@jzF$8+K-Zzk<%Hx zG~shIN!$mg_T^IN`FYypOWx1Jww3P(>WpYtpfwnB=~(!53yGGbA(bPRSY5m0-J95m zS2Fo4!{%oKzEYRwx%M1v>oM*zV>|ar&2;5U+-ZL|W8h52juf^xj*c)O#V+b?UDd^u z(_TK-b9>vRWa24TH6)A@w6GqS1)V{`<=9=4d&zbu z(srTVG+%SHPrWbJWcKdl`%t)xw*SPb>;??d%BgM@f<)=jm^Xio*EbN@6YEYCR}S0o zUK_Hq7`^P%P?<`K5Pn6GcqmU$XCyq&+nkJS#VAwgL>gw%)%ul>x0t35g2MYdxHK+na_TRY|k7T$6!Xi->fv(|Lf2<4iaO&HkTf~9i z2mZ(CmxmnO*gZw6#c{(E3JaUv1TSN`bZn}wd82|d<_n_bQ6SEKE(#&}(g4ddb$ zah%Bkaq#M9PSoqr`x3149S@xcSYHx`d+j2=RHHI0ZQUn_9;gi5%A z>6PGt3D1TGiuv*rR~VbZgHXmFyi%s-^Y4dH_LX(Pw4sV2^-r;#j%xl}82PV4S~Fv*jAuZD`EocbEx zM>d9BuWGUWp6rg{&n;_D4J19etbb6f0kwM}Pzscnx+B?3RyrXme=GUinCM-As%5EE z@IvSM$LL$(ANA4)Kv)Z0zsB1FH+*Rck610Q^9s;3VkMMl<2X72s$p6WZ zQlvMNk{wWo7yA0$1c)^_lMZ3lv!{%ib*UUc)yO-=Sl*b6-~Pc1Ps^uxp`1dYx4O`T zFSp8uE?^BV%_kl~@1X6`%gj>o-%#TC8;TW<1^^9hN=~4FcJV63M-Wr{8=_Q>UN&QD ze?!JiBjyZ&qR&%BF4oTriO4ah{Te6&Jc2uD$s_cy#jR6<%rxJCyF;bQzS=C9y%eH?Zm6h|*n~l$LJkdQQBq z`;zPb{@>5W@kYy=VrLdtPe-H{K2nkgT^w-ZhYvj8)@FqJ$ru%;${#D+LD+V$~|DPY= zpdzEriE(kpz5jPbAS9HhJhv+T>t_I^KL|^LQ&sk#2LFCV#uI7!;9Y9P8x&-G_T!u3H)tzC*Y@UM&v8 zgG+X)?R$;VjP2}h+r9;b2Z!MQQ-#Sggpte5dht-6BJ=5Dh=a_p z7sWv<2JPPs?tXoY9~TZ1U__b2>#Jra2N=gkH@#u zlN#7ij!5FXpNIGf~=2|Is%k5-O!X{ukW+bW~KMn;v&jkR$W`zg80d4n#ig{l%qV zSQh>BH5QpLExv|gBzA(|XY5|0YiZa$KCc|qxsxdpw?6~tAqhfC(agf%;74Qh?^e&F zJ-%AB%r__xXVyvPDT-^q1}AJzH}#I5rZXIV0_yjkG~zEg@;IuJ4kwEWVP@z$@BVSD z7cbF3nTlNFvE}4+IB~cXGeKg~HZ&qp1kL53@)w?8F!`gDS11cq{>PgWG)lsUu|;~d zLu0nPb1hEWwJY>$!i@4}$Ur}s)e5Mwg%4pPMf&~fUbb4*I^<2~_a>Tb3kwf$;oHx? ztAehfujxE$+~mr))Ra%HTFi(I(c9Nrh69?^#mx1`TWQe_pVqtWM6Vh4#Gm_3 z@0^M3@!=woVuw!uS*1(Z0TQ_I;asHzhE(?#sUAOxEC;?k4}VG>(zn@^#$g&N4-rtm zI;w7#4Z)+^3^fF*IU&5mDPuI^>Rp4dih^3{lk zlZnzhtE_ZHB>VQj;JrFRY{w%^4Ax`eaoA&hajkTHv39+lvh`oPmy6lSV>9xm?6v9de>IoW`yi={q-R_$blDNXA@x$GUbV1$RG3(-reTj+SwafdT2NoSiRZ-;SVW`T+xdzUTJ z=EI|bDC7Ok6iklI7)jX9T$Ig5q&DaptkVtVSStvH?QQg%&Y3$F`-bxZCW*{C73CjO zv7kUnjO2Z?`+B0@&0b0wygki$JnPq-2OnA7uHT8bo2fJPHq3iP#Y|ql|7BfvW30IR zYlYYG_WoLKT9@ecsS=}Vj(nARm;BB+6O`1yROzSp^|0B<4(9v?n{F6U~w4t7KVrG&nehmtn|{} z8J+1^gj?6gsbTglud(Ez;*JL%BdF_=ac5mVxe)f;_$OA)Q}xyb4Ls-Er$3Bi-3`!; zSTjA}A?#-vN_-n%h@4sK#|yz8!Z9biPFhAyj@@Fib{JTf{US8tY$=rDHga=ksfW4E zuML_um0!fO;95>rydU2-bxUeE`Vq13?YWJNxQ{%}&7}Cp5TZ!~D!v$!W1lE}T`j#e zS-Cu6o)+hM2C#HhP;wR25MTme3 z%%t;yl4aHogoHoU4AWf0vGDCBFj-?U*lNVMgw6u)lSf{jAM5t-6j%SS68@@FmB?v6 zxf7a9R}huD>|LT)S)`D}RYo=9=~MRR`_lPNbG55>l}+O1RjSu^)XO*~QyuZ*elij7 znpk$jAFOZsSLm|t^J$}$4mC9`A3A}<%Cn6E-V*K31RHue?Hw$)fqj;WhO#BF?Bho3 z3A=c^+d7xFnor*q&a(Aa+A*HES~Hd-&H>wO=9MWQPd}gl(Kh6 z*i)}f-jJ?8iB@~QT^6~UEC5TTDq_dHw&E7)pSdySqK%zqDGg$Q}TShPyvp;KQ! zV07mwBp1o3wM=G8V{142HWGBMw~RVd`%oCj5L6ue>@BB0j!_bcvYo1u?N1dhMrex4 z$;ov;q$gwY=blJNhFS1)qmBRUrJpaxg{@y|APMJVpBW-Bm8;Dt*0c*DDLT-cSay?!hJ54YGVK_;N_jc{VT(n~*zRjz*cu(5Y~R<(O4SP7DCG#6$*QL-@5F&=G#LKnO{4&^+pOIM-! z`vuy%DUC{JOVlfspdZe2!QMh%jSah}LoDLym7DZz_WG)t zAf!%FQ@EV?(Pf0+h4{-jjtn?y`s?Boq6Lgn46VUytE(ODH&%97 zyvXA=tuEKq3q3Sc{s-%bHs?RS<^oQz6eu?*XOdRAFZ~>3&A~X6B!f-hVh(ZDXgg-o zOXjvV6Rt}SqE9Cl_N*WXoDcH!P>(DaA2na&k-LkLBb^+GJ|{C9G^;7xa6IFdrsq1U zp7B=Y0~Fo1F~alRC`~a{XSfXJA*j$zKt=mSYc>S7ZeDk!h2Xb-QM|htr)dxc-kOwr z2=~;_Lk-usSogsjx|7l|MLEi(FXyslKZ>W$S((OW!>(6aN-E-ck`<_5X&u*4wu;H` zKQY}gU0p0?o=X=Lzv?5%k5b}ZTF2eaJ=2Jv?-F*q*G z>aMm;*EF|FS*D*V(tkG57W{Y=o7(HyrA-I!s?e5d7*kQQlV$d2*nC1AX031bBD)va zv;B_EwnptK&AvR@!9+`K^!{kfn`{?H8fbs5mepn&)#9U1ah>PPatO0K+163^OCJ*P zm%pW`FJUqA-YqrrO%?Eqx!B0O%Wvk}rwmGFFMa|o*EArxY7}bD%x^e54pi}5M6cb+ z45J@b7q8v8AXd4S(K#EFiMDdu0s|#T*vP4mlcn- z{+*)Zp_P$5<ruuD={AP%m7nnzAcj5Slh7 zSCRuvq8{`GUF|W2lH6g^+WDrG0FSK}bHw!)+eEF8ZkDRj*$->f3PL3BrE%PP!rdRO zUgZzr)UJR#EuO8p?5T1E40{lkeWbQrYAhkblDa6~X-k_|b_KTf?Aq&?J!a%>SXe2< z=mn%b2a$bJx!>Ud$zC#xd0?&RdFCq2q`3p^PpQ^0v0Ov1)m^Jovla&rTh+EeIjGih zAPB0GQ+RlLG^wh#PB}x6P>JZ zeQa{ApG}m-J*d9(qj5`THd`)1r+){NcRCW+3i71#Ccbs9kVJ7fa>s#(423CU{j==n zARy#%!SWQSR*ge?Z*Z}m^;nUmc+DtDYVw9hWG_#6KL1<+FY zgA}6!Gd};%A{-Jxe>N92#Q$jY@9Lx91K5Quap;>D|Ec8fSVhbR1qWWXw`ldx`2Gj& z!2>`eTFWP)X#Yete~)At05Y|=MHK!6!2BJzQ_2G9M@&}w6Z(IglE0CwZ&Dy6QW8;U z;6D-mUmgGdT#(>;(6;ceALB2-jpCrv?9RrvE4_IOc};&?ue+iFMHON!m3;(A4W5Tq z2-5UA8xQ&WDQ;4$VPgQk>E_crmP|EgwO^yDy#{I34oABW23kWJ4THH|!o{dO zQo{l<{#mskl>IO%Sy*AcmNi8gPIkOZ02`Cc-;y|hwF#rz*t`-jeUvp2s8C16fc4g`X& z?kW3bR=^QB&|?EI!<26&;!C^ptuXM6&P1JQp}9<_Q-I;!?uo4_xqfotETfjUiAirh zT6V|AKAb2wug;|p)c~!~`a+ONImy>XZ1Z75_pN`o`{_f>t@*ki2mkUMAv>I-pvctP zlV;X+e(g2uJP~aGs>f}9j(Z~wnIM>p3VTM8W4kzC*Hoelb)wQbfuS`*>gE++K;TLS zrM9n~w`R)e%eg=jyU4S{jWo5uH1lf~<5`l8S{qqbe`bw5$`2nOMj5wWYMovlWG>2JPJyrCKD_$Jfhym7b*t|EcMytZx7a%dCO3(vpIkB@Tp3k1JzVK@zurl=V!3ji-9#njoWufn=qpnPq~}< z5_#S1+RCjEP*!fMkscg)5EfbVGIM-46teciLSZr+t^VuQu=DGKJ!H`-RgpK#gSRwD zj{1;QL;l{cW+`GGD+|d|HvSae9YT-mcaBc0bI-BeUW#%v-gU4TKLETq6ZROsD8f(qTq87`|0@*PF#?_5g)@X zSTVcB$h0_5{m147cvHQ~l)}shCV6jV`F9JrMMM@peBRnOlK_s+!d@j)pi!JeD(pED zO35DN`M44aY=4wDBN0Uc)?;SXmjhMg>uC@l{c1v2o;-{ z%7M$o)(p3tUhA4K2--U$+Na#1r`v;yzVZsU!S~X0qQX*jI$07?#A7-1P3St9MeC_y zL$D6}ioo6DawA5gvB@giVU5YpqV?dd*tOx@Deme)(kPTt^xk`z#3nki@#tQ zDc9|JZ_Hq7Pw>GDU><*2wQyFr6H5CgrfzWiA$ve4oT#Ne)NatxAy`rV=%sr@s{ zP@sQMTO65t$OVN0E~`d|BYt#5o3-m9U>IpWv5anW<&lBgLJ$p9y_|c3A^5+*22X|n#l*G8CO#aSH_mTMw ziof~X)>nwwhfo5OxypB+X!2f4m5q3uo{^MvA93x3gvGo7Vb@%~Cb?HYUO6q`5|(R5 zfCZ5qkdR`k8y(JVPi^!v84Zn78GX;KS@cR-1FB;gL&|MCsRqC{blnNbv@&LLINgT%ZGjTehYv zmeJZ)dP}!;&24j>sxGl+Oo@i>SKYwC_JHTfXzFwo!OHVL+x?PgfQaT%)bLblYCh$< z*4ch{$x?Ygy%(F23aXKUVuk&+NWN;lV$QBve`W7aWXvdodb{GhCz!%I6&A0*e=tiN zE7c-sO;Xpn9sw)~kNppuRvjh&<%f(`-zEg`UjpWg&2qY?jNq#$Bovc?C@Dlh4{pK1 z*4Upq<7Lu2$<5QCE;?1?nCSxzodaIhnO6ZE@bkt#aGpPUG^nrJ$G_Tcf*Mmk#{n`B zT#Y)077o~N@O%@AAh5}5S0QU{iQ7t7pQ@a{ni@F#Ii*sqjZ_rFQAhSU@R;K1i@GMX zH4Q<%Qlo%MS%NdGX3xgZ1pa`j z{pI3U8p_4wb_CDXKWLOVTi~(qQbBzW$JbaCO60r}h0~OZF2{}rJN;udRW_G`6KIBr zjSf=-Kh9|(K;{g-&M;1fB)IHb0)c>x1r6a*X3ZRFs`r!aV|0w0-U0^*tk^vPZ@$+mCk*0~VjXXp)}s~%S6KUK!oeMX~ooZPQgvprGX9*T3A zw|1>=v1)#^1_zl6AOmXyV;IMe?rVcKei$OK9#hr@l{=FPxyy)LIHdHX3JcmvQPg3o z)S!mbVYnzR@J2&S36b^3-t!2))!2GAA~MolM3k=17evmqz-=kko5anTf#>u#2y|ql zbL+r>62~0*um{%UdwDKPl-ZeL{4r$O=dg0{N*~x;M6GYI5s)-qa~-`VVzZ!H^Mg(H z%ebB<)kBl!JsvAQ=P+XKY`{AMekzEd*!q75;!u z7_CSqsEu2+q1}8ve_tEs?x-eOB13Mpl9Nu&H|gV#@$l(6$Q<`*Q-}r-gTa5s-Je^x zN{aA3MLJIiD7@=^4eBk8W25EqtdA8ZyPjnw(fJvAKjWS<^^OXSb0Ig%ebMI&C%z&& zi!OOf#WfKd_(<@LT8TPRc6z2Y0vg9^)@Tk6@^l^TE~M&T=N^9l{BVP}0|y@7u5kC0 zXYTOO&=L@*#^KSuOsb4aF3RO&Mk=D}>#LIMBQ_%F_iVB|$VywAlo!TX5?aZJX zHP)9?l$u2+nIA2zDMH_*D-DS&Gf=Vp(l2&eTc-OnVnBW`0+dYh5z9KAZo66 zU!4yefrVPu)x%sQbPhBJ9YWhp`3U+ zEPrZoA+5~+?ZyKoXz?X%?rJG{oBh1?-cYllAIT7j=PL1>rlDVN`Mei^sP((hyuGCM z1zhz99JfU26rcNwQU5Ymk&M$;xj=B&`(lq_f5vUr0~*YZ;y{aA^g2Ik?81{i!JqI% z9ptt;@Vw4#$9Jfyp>C!>I2JcmoHBy|KDopnVst2PO=1$~&Vs2b*c8n_kAk3B$a|e1f>75BCZWj|+|X>wUb|CNhKcH;6qg&JF_Nd|v*19O8SISJ%KfHJ>5coC7W? z?cT=kK!)H3uTd+~qH2Y!JM?|tYy8Apc5M)$b=RQ=wQ2!D%dY$S$oFV?9)U(6T8ZoW z$2IX~*gY4$cz!j0@FwQsM4~VE-F@ti`kf{Q3_`YFdOovgM$#x7@h_5jY@OmhAUG>g z8sYtKvvVe#R$<-jF-hFkorA{GO9}kV9Vck`O9L(MQgvy_k;idcFiCi#ea!4Fn%@ft zef}eZi|qH5x<)RcP1_QQ8!1XV<*lopDj%!aq=3~MWsX=X7fZ{IF z`OgTmdh`R~T=muy{#(;!3?*6$)Stxtk>|ab9_kXUe_44A<opf&#LrfYPL#j4ylCKq;Z@?X4CRumn6*gdSy7I0BV~ z-;uCGx?M9ZEl~PZDzoE%gA*c)06{t@oni&80MYUW9jX3k1cVZu1b`X&$q`?r#Q|Ia zll!(0>Mynrut6C7NL21b0CkWDI11eU)cXYpX)`7;i+CGQ%1rr!{GSj23H2ldK(>^M zW%cy{Mb&@(CVOkjJ?Bw$&&u{JE{iI_4h*;kW>Tf6)~KZA5^uj51YC zZ+G-D&{_|r10Y|3wG-2WKVN~6)ydQp^-Y=k}BWVL#=;;R8Ad=jJE)7pOySWJCEG=vRx4o7F98KuALH zaj`i7AG(8BQhWSo3k4y&`*FsD=KWqm>Re5Z`pbz+jJX}V=BZIT zP3MYIpB`Jx*4;ka@LG^9FIbTM-no?3h zFe%bzG-K{x>b?M+1AWvvPTym}iPU&{I=O`C`#qrT2de<`8neILH6@splVgTDCz?#? z&qk<635;fZt8{qBw4rZQf}y9ZMu|2}v2JyIx_IEr%(k#>qZZ_!b+#O4J%Tsr%9`_X zoJxfZu2*xhuId)XTan{H(Q9p;#EsC;gh94bLpD$L0cMOuV_|}xQ;5w3OmZDzPno8W z%F>!j6tA2aO()j@FrVnRrm7PbzJHwBT`p<58iKa_{3`R4%~#1@I-0VpOcMp%*`bS( zpZmW`bC&@QR6;reI}S<+j?pym(5`dYeuLmufSlFpdGFEvtcyM(0$^`WgS{1#wP?CE zQ=5sGp^tztkoEeayni`6!4PH&FaSlnCS9$wEf?ukvMg|Qf8a9GENxgCw$EnhPe*aX z*(e>+ZybdP6g7~cUn?feeeVr_v4^wARwZI7GeQLBR=ZudktH2L4zn11!)Y+uj{{FI z^sUu%l(f%R%g-Qa>rP;eiN$5y|477pVAU{Ewr_atsn-?D2BDf1{2a0~Wmm87duEvf zIl*FG8O&@q`M$qQwEW-@qzToV;P`COwhFL}X2yhnc@@WmPm%E2#GYZ2j013R$l2M^ zlzp}?!cHaq&0T)))zY35-@pf)i)G>c5J9*2tIIRFUL9^$n&rZshZuyczs6srVEy*q zfT>T~g5`qgaPHjqY{9<3Wo<~iEu4%Qn9a}>zpGQH#W3DZE}8`$;`!Vc>Ijgb<9C9g zYJ1W0qcv%oeHDNh%U=0z#)L+Z`@PQnApqFz=$3kKH`}CdSGPvbs13^!I_t<(DRM81 zdGY1Y8&lMG1>$A`a49()1}O7&vI~4X1_COS(wI#lxCx%uhAY=ha*xw(Jf# z&Pu&_u6Zkdii7S1^%!)$NO2vhQLNJmOb~lKeIGXQAOm)Q;}xfzDV2@krP{_VbjzE#;V+ZIz%UDeDqoR93LQJ%Y|>;AQ2`?Vs}f!EobG=r4;Sm>WXwKyFO82e|`pi zFLbDOwp4^Z4K`1C-TqV%&8wXZ=Cu6MW4?AJtGLz-&V9#Zd%AWXASx}dxv!!A(lqoL zReU<@eb75pX3XHR_nmO_+tvUTBH7WVl8l0c*OJBWOx19r);Z|nAj;2-m}Ummhzy^Q zMazgD)u597b%H*)HW7#Y3BG75<#2Pd-OkLkJmn{1?xE1d`kh+oqeRzX_J-ZJBgMLi z(ATCLhz6RAwi^kScz_5318I7`;h^WsaVSBxV2^)pXX$p`0UQ66yN03ryhrWXx~M7Y zTuv@mToSic*M*^9TyYySDfw7Yss;hn(C4z!`*1nohBM1Q`oJYkA;~)$By!Nhx#etj z%^^+Bx#4j5>X}cN$MeU$+jmIfi+_yb(x`swfOxAYa0%&tKgsxjVcJEgy7|f3{NOEY z;6cNEEYe6_d02FRn5J9%5t-9kcB2Ub3W3dfUjfw0u6Ni%7G?>A6Dxrw_UHs~R-KAS zz!Zus5*Q{tdu*LI1%H0WcHt@6NNe{h-FpFEUl8it^p`GSDp0@|e1|cR66a#F;%b%U zj8v-U8Dsvd^tTri5@obc z->AH&ZVhY4Gk(o`rD8&po1PZX)Qy*N@)E>}6>AeRp** zlM@Zj)K>19naD5FxU~izo8nKQ)jo7NI!dzs6!go5(e_0FK!9gf6;Z+_#3JnO>wb^# zv^l*oFyG2?)OfrpN@M$s%Lrb{<6Qt89yo2TDklosLop$fNp&`uYvLwEiw+RW z1Em_%+d-Z%9{v(|a{}vTi}5@h691CGqRk>M|82m7e!8XtO_c4`7ysg)z^RLE^!EmG zc6A3{uD2J$oJ|D`ouBiZ#wsPQG~UFr>bm^bjYTI^!yt2nGaLYu3rv6U5{iL=p)Wrqd$N_ zdoe|+O|>+z9RU2+QP_z|a@QH(N!mz?gT!&-KoOPi7I~Rn$TjF86 zu0pU2!70KxVuD-BKp3vWPVkc$rk^Pl79$~m%r{tv)OCaLQ-YDxk+m2k(w;4TLgx$9 z(5ZF$fC(HwDkbsQTG8a?D5crayUtb`7@2#YoVVT>gZxT_ZIa7d&*gmrl|n@z0Pkej zYHFJ2=lC@ZaMF@cZ5F5`@|&mBrtSr%C32aHf)`R!uKRyzdh>?qIM;P z`Cz4=kZd5$dx0_ELShY|5t)fcse`OnN6Y)M5^l~+Y0Ox6Q}ydjM^=@it60^ypHi!v z$G3-(Fr+2BHqF$zRm&Ft@IFwmw867nUP97%<~#pEf2(f#nHi=dc6nM!pt{f1sX15} zR?e`98PGmXH)mz@$U3%VQr89NzaiVmf5Ch^UZ! zJNJ6=Wl&_F8Muwv(x3*yQj?ueq$#y&udq;wz>3YF=kl!apcu^7ApMPA z%!Pr-=TIBI-YunfSf8pc!Hr6r62@w6jUPSt2-?fw5zJ0(Ecg5<7x#p5gV!!n@Dm>x zro&@1($N!2$VC)$Z1P@g;iCW`apFxksUf#`1YRsb_@;pc7xbQO0C9Ip?e?@zbVPvkq#m1TM1+YdZ_n6gy z3H0mwa@NpRg{3#JsGfTD{U!i9+9J1g#W79kGck!s6MhFqk)7t5VY1Yf4#aqS8#W0$wMg(Z=I=gjbT!7hA>p&=B+Fn z9`xHlPrzruqcxW5z>L1hx0=xTw11m%L@5GbLwoZb`q9BaX$bMhjDMAe1Er4dJBy>= z0j2ztAu9hW{c-axeb*&kDo{F~9E|+0Qcb{IIp1aGRWJd1C1FR_^)IAy8nFI-!d27! z&w=jYSG<1m=r+{klnB(AfaHAs4R}qlfhS$!Ha-S$bWrCSzVvY7g#xdoC%yan2YUdl zPCwA_!2@pWmk)0mwnXdt7tGlJ;HG`LKZIESP7Qm4e7oU&050UC_;S#3ar2ttl@Qr& zXzcVR*UNCp!>;KDxFzu-ynrMS_ibZ2bdNQ!2GBy@0oVu10o5v^oaj9bbn*YkvF&_ z8iMxWlWIVh&dE=Yf!OVz7sTG&Oc}HKR|R?iz}qKTGyN|v8XACjroh9*2c3d|hTUqM zH2>AG0MKwoHO}%!LEy)9l#}?sO78*>Rk-j!d}0882w6I@|Em-mc(`9dKo@qC#+M@I zMDnjvBH&>(_v7zj0DF-S95{`1TOFM;K(9U(OC=iLV7q7(g#TI$mVlTsRclY&D*(X< zqZbAKRWUD6u~RigcEnqtVsr~VM z>D$d|Fy{-qTgv$Bmc6z@usJbEPt7gzidE@yesfSqSjCaZ=lch zaD5coZ2*%%vm7st+MH@u(kRlJKdUnlea6krJy96Ru-tFiY`NK^k8flh#lKvUke(n? z>@fdgD9;i99KPHg-xWn8O(QzZU~Xi-P0V57qXQ)5X21C!3Nz~^o+vX8st-D!V*$RW zd1JoKXX^F{{4?B8W%JG^lquzIz&NVAhql_@RGy>p4RlE=>Z_+xZ5u<-ozSk~Pg|SR zH>xlG-53WO24OU{VTBcc|4op$`DQ->Gu^u5wlzuDjZFKtth@u9WBx5usZcdH{N{`T z{SnKP``F~s>V+Ejq)?2_#}fsS%OD>hwTnR@aC=BOvKYJ=;KI{kJz{T$L-vj}FKI02B%&sBV7iyWqDgSk60Xyx3>X(kja!3as$E z_Vqa5s#f?m#NpOP;PeQ2oRfoXmpMQNnU6tv;VHkF(1-jf71Qhp1j@N9j_BXyAe2QDGmUguY*?Gz$}(^( z0+0eAF1gzW5i~vBH*GS&-;@?)*3QU!(CC|o$%`fIqOvorB+8BNHQewyQJ8m9gcaz- z!v%Q29iIC^X^0zr%VP;Tw=>q4Us#yyAfCU2#^fjrAE>=2=k!Zr+_~QI=^wy>r$#vj z7@{rF`p*PMe+f2f219R>2GY5Kq=B8{HdPL4)AyKYhfWfl!N%r^Xy=1tI@NZpntG14 z4;h`_JkqspbelCG;&zI)8J}Yn;wDDgl)AVli*i2L$CY8)F+in~?GzVNS1cPt-w8n0 z%h`e-b^cCI_^oI&K+%e&hnWz|ExVfed-;aVSF%#S{-$Hi5NUR3qZ;*h)WAznfP56D zmtFD9=0cRx90dk-E|$RIO~KxyoRUOA?~_s=N7ueV?V}eT&^zNMct*H>#ka*8VRa}dQ zGpT!xQgeB{;~VcYSGty3?*eLB1^y{cK$bNH>w%O9Gi_;UM<;cQ%ZS7>SsIRq>|wflBlnjUgcKgY)O^L6X_oEP2ZPV}v;yvU27c@nsT#WqW`M2_?87vQoBx}E0h z02ZB!4(H=_NswUb?80}sj?lQob7qJ(HUT{8bH}`4m7ccc_?IYL`g5N|vdI!~P7LcE zC{ZNtJ)aR9+rzD2J0?R}O2SI39t3a!DUCu61%R#00^AqTU23i0uK87-Nw6JYmve?i z)k%omg;C%ezc$~l<7GEy0E0PHnJQ5vu`#B|@;q1Zad2nV>Pkmyq5gU9bf(vBQbhCTkzD>W&u| zYm^w!oee$iod@Hz_rY>E%yoxb8cy?blZuV7k~+%?lriV{L+~!yDwHrVy~cv$cG2o( zkZYnQ4jN>lsGDvwNd$-G2M#wzd2!{`H&NtRQq`+{bk0y5F^vQ6_9Pu)rrven$9G(A z-y9fEtdDy5_d2vO*D>GH1=zOM&RaHsl^rB^_s^tjcWt7=T5s7(-@ql| zwxShu+vG}ZC$M98wvB<>ueRa??B7(*CrUIBJHGEJ0HLB$jT z5OO$xyO#V;zrZN4UT~3`SiC;4|)B)1srjCuo0p9#dpL!#m?Nmh^&(D6SzM$#ZueH<|JboTLOB^LB!C`Gp z$kV~dHicxK+D9aVO%f*)V@XNE{{0uN6q}w?02WPEU`skOMvXS7Kws!0zSzjBTJSd;Z+UC_*x~${yEI-lE;lWHjIC)@n*=e9vB6#XGt&X5LC{4b``*h#w>J%b*-E6T( zZEQWeqNDb)DmhR%Xfh-`SwKV}C_Gs)uaTg(%{M%72{G{G&gCL0(_6%6nG~+_lqbJ} z%{I{+MZ7bz{^qyG>`k*^?tb1KDAqr(6+I|~ND6}ad2sE_%O;CSbPviQmf`VOWCFoX zBc^y~;Xk?UrLx?(ct4d32H~t~tvcE^;l4sDqUP4SXe$&u8~U6~JX!7=c@tV%1SotI8GhrnT)_|g2s=+vTnf6BSl z3Cyf*B+*g$Xmf_9P@^bzKZkTw!E6k3BdogjJ&$$p8{l-srUpijWjQ|3qm}HS1}TGT zm*=p0>FDU>Ea@q(f{Q0Bvpg%;!9Vp|hpMu(le7=H!K{*_1*0}j$tu||t)V5KR(3dF z&uWwT63|W9Dgl>p=@9XAe1ES_eq@5q-^lVa2x3{|s(@9%~shq%W<*I zENxME3?qLc#1*eYb}q;IK6lYzrv;RJZfk1z6KhV;%*JbRt1z;H73oGX#dw6Unf(;E zwZ>FGH;PW<^ST^^66e&Cs+5^|Y29JMt0k>b+S+!h_r=8C9ks=i>#^E>O2!KCGW38U2ga-(uu2-gma}aS%t{Jnl zR?#-=(Ug$9p$#rirSn2t%PE_*f)x(C)YZpldK1!$_FkSjsW1HM4Si4JypJYK`t`B? zcB6o_Vcp&;Nz6~BBjF4`*uw-$bL`|QF^?;V~ zj0F7JmjJnE>-elT(0A4K%qib`hRZo8lu19ARK$1<^|4QYRyjBf^Yv&yPtt(QUr9Ua zc|~Ol(#;6%%7Gq8`tso-CG@ZxNZdJS?Mp$6J={P{wP;I1CrbW;x2)XdH(>(q$IXw?hEr=TX2f>qn;tdNPLEPtW~&1Ct>4`B{aYm_4qYip}+ z&m!K8^U|`ZvqO^c9VeZ_HEG?OhDy#3e5&+aGgy9HCN{ZSh*o-^!sK;nEWsB5M|)gW zU`v|IBVN&S^<(O!dJ#B>C+iaOL)BI`A$1iaE8ZNq{>N$3GIyfM;ayp+evY?*a$dkR z#?St0_5@&-SClvWxUV%~bsiYV+rFXyoPkdxSwyn^#fk%-?OII^+Kh|*@QNV5Thxmb z8lPDp>5fxdtBoySqS32*i%=c3CXog^6tFu}2c6IKr5rQrV`j)cbCs*{G?O2Z<G&t^-44*Sw~0rm!Wmh;&rv<_=s*v7vw>3!Kw(h8XekV^9|( z^}W2X5-bSIFV44kB`9cuV&yoTyPoy2Y5KdBIn&Dukvgf_i8qShBaV{Kgb3KuWlN`v zwti(o2v~I_?qQQ#wS@^J`Wj3g;R6(|9KT~o!gfz8NxstX6_pywMwUd8^-aj46JPY= zi)(`#5)|Jf3dK%w*1C4I?PzlXQpPj8Hansbn~rcCE0n21-&MOAyt8ak_(_DsLck4wbvGI53EgC3lC z?ysE(wI7*`>8)`mG9>0?v`fHXcE}78ANZi)srr06^7vlU+NRM2Z28mNjG6g;^^^6F zS$&}!v%tZB?q?IhGpEn$P7%8a!IT(AGx0wsk?w4Md+WS9S&pqxGq*WWE<9zLl_1&p zx(2mRL2x*LTYpuf3T>F{p$dZrkKLq&@bzJj1|#ugQ4HN#bna0$wRB_9nIAzrkiBJ2 zFIc!5P_)UEhs;-4`LjJdksEI4eRH)~NHSzCEJZ|tf$D{%Ly`8Ea{Ok+`O!yel&iF% zisS{tmWBk_f~xf+zRC!1(>P_J=-p2AQi{8!W2y&4dRFv@ztgpCAzbcThls_ddsHAKHOY0_~==PY4OlH*B zT<_HzT@{}+ZO`OS_^5w-$T^7o0sRpNxVkT};^tbL{*eird;9nrS=1-T<`)J!RaTaW zrT#=tU9)7-_TJe>@+cvA_)|23ma@$|q_P+5?^E%$zxafC%2h-RJ6X))7D7yyk+6Jn z0)ZPVMP5s~hVfoCgp=8J)F>7yCiAdvYpb@lE4JeoEgDu#Q7+T^mgB=~caWgw4C$_G zQ3yxX?#-35;SzAXA-Pc{;bkL-of$dqA*52b+V04Qp4&A!kuNpL((--69zN3Mhes=C zNn$6I+rcqX^v@&B#y^{nAq1q)&N7pvURl6f?PdKxS&UaYCtOwo7eCbqY(&BCQ>_GCln&rX!Po2 z{J>%mVg_>DraW1BrV8`6)`^WSCG*CWr_@Ve^jgENE)SOWDxmnsPR#y?=;oqx3*TK8 z?0#M`4T-=pNw{FPwKfw&^47ks*30iFt!e#_wChl4)IjZ4<^rd=myog7#hsR4@ZX(1 zfCy-roe949;@sZ%3uG4 zJI=o1XDb>{W4@zes`1ytkEa2VQCUq zevfaYFJ<;ac^NGm%O z8YWK&UsoPX@LnO+7tcb5_j-yDWD+M87~l(Yo$vo2_TKs{ZZPcHMT>ij7PsOQTHKxD z?pEC0h7K;JNYUc%?(SBg$l&ho?)rt-)_czR3(i{Kk4!Ql$vki zaVtPrkvf~u*ILPbcs)Jb)M5H44;gKlHz81fMCvS;E|;3pxJ{XT%_(O;v-bZY7ndj5 z*tQ3n`4?ZT`KX~#y?M?X4ZmRWh0{%a?x!)FgPG2xMF71SaT1A+O2c2Uy?UFyIym{4 zpLdFLMeOar-@Jo3Z$`5c4Fz#nU4=cOLcX>beGnD1HDUXfIZ>1oL1}n__4kDRq zn!Q7#R}BQ|@Y=MuwLanRA3zr@E3e(T*@FXmtzwSzRp5|a-FI27t%x{n@_oX>oA3f| zPrU-2JTu(S0qHfiI?0v|I68@iQfjC6xov=p1EwsRu_PjGA72|VLlqg%2p%>TE8#Zh zrJ2pU!Z~=X=9wx-m)?{Z-@8%zJCDNXP0N2ODRixIkvcqZhX&-OA$pWriNwOj=^ND+ zOG9j)1A#*jFpNzq+0Sw8%#*__{gQ0PO_6x+b54z-tA(uJfz6vF6%){dZbTPo9?;9> z)1{up)Suff2>?Zm=Lg;=n0X|_pv(P>wU0CON-}lhhbv5 zM`QD*UN_pKVgjobZt62ssE;bE?Kki`i(1Zv0GqTgSXk28<3r~I>WBCPaup+@{h#k| zJ_1?BR}x<5S&{$IS5$U;w-c^o0L4gWcTx!l%yC(ebTNMSJKISWFo4vsm)~Idr3QxT zU>&)imwW`&6SIUgjajIUhX?C)-Z_hRjz^5nAsdo9C5l!4s04hyG=a$cU$RAOgsido zSR}u|Xr7)*z##}fJv1o{(OVaTL{`DK{4J(&vy=-0BN2!+cg{^RtC{b4lk|mgoqm`-=5(%=nF3I;~;gX&0&aP@5`N zS-u%ryEE%-gmVT1h~GJYI1Y&4e*ks$u=rVPkC|Bh*(d$ECLC;EYHs1-%TKup(}4}# zp=xkwg|RxceE=cGyuqG@-|LEtPE}#@s313Yj-R~kV-@PgoEDFz;6ie+paCF?atsSx z&9#_Ugn#@xK@)l51W38p+*+Rg0aV`4R_4?)alj)GM%{XUR!IGEL54S>8oo;@SX-Tf z>(d4vuk&gNpdo3Qy5^Ji%a!c{oRp+37diRj>R{oH*N$6$QBf!_iNEmP)NATcAz?TS z-g3%CfHeR3K`tM3U*|mCD-`e!jV-I_1KUA~EwAz4Teg+b&*z|Co}UQIqfZarg@=j3 z=mg(!eg%=7qu0%PwH!~1h*#?4y@yovtX6=vZvk$pXvig-c-_$#{bvoy-}M9*Z6xP= zZ)=rH>(^PCPAw*SF!^|A{7!4Kh6ZGnf}_!klCm|(zEEKRv zrg2t(-MvKT@ldvkkX(44*Tuz%IWA?HkyZf@8e0Aj(wD7T{80waD6D(C$oA%nOF?Lr%#k6EwgT+ z8X5Vqg3a$%2A7WOJ`REe+;+;hE7{#s{b_vb+W#v!%Hg*K3{I1OaYYwB7=mK(s2C2a zbBzPP;aZUm1=$=_XaSAi?%-rQ)dOuqKYhQ!xvFk}iI4^Qqrh;Z0mDeYR){qnOB%}9x~npv zwU8RDt*^L4Fh{@kkU*J>)v^b5ZXm$aBP=rg* z|1@Qc0zMl2nxC}L@6HFlEY@05`rHq-T}%!qu^lBDMYF7h#{%^;XO3T3loJ1LYQF#r zeY!y3sf03cDLdhsesuamPh4(`H1`!x?A*6V2!Pa~O=9tkVSVhYTPwe@f(|xze zxEE*+ph;`!xyHW%8U$XSobMq%FR}aW+J9?Cd35x>j@9nh0x+^cW~F#_z=S@^z5DSV z2oh`qsfEyMw47q z!VelYVP3IgGkMim@mYNo_zj|jb2#GISt9Rvs6F%EjhYv*OqzFd0NBz5n?h_6Xj*jx zC@k%t`sDIYbnKeAjb(kz?i_$}Q8M3o?|7R{4c2dtr&I(&Tgr%MtBf9d`;5nuTa zGArlm5B6;7y~ibhna^O{-;NjS5JBa8I9v5V{Tr=YV?FIAs6_ zSO~2VuAeR;LwE*1qM<9)kF_r#A+L0<2Q$(0f)F=qUsBI2CGPDw6_Y!5$N=E!#8VU9 zTU)4=R++cC3Hb3}L7Z$;&#h?5Z2%|b^k~~)hT1Dna4kIAq{RQ_Z`i}lAp;m>Ko?5` zre|r}(sSs$^H50GogK<95CQRN8Hn+wx~EsI@0RYar8+}CFWz7MX?8tGHJP=u1Gs*o zbi2+^fB_d;cX2MJ{Vf0J=Jmh504!S7nhPm|wv1SCm6NB8devg1`wrzUhYNB*sgkNEM39mlczyoQ-w1rW%3`b2P!&7A>hs#h zRbQ%;-*&!3BvBYXf}e4FyhzKr>|s2GM&trOQ4pDQYU7FwuzOS!`kh*y- zGD5<7dk#miI`u;x+wGCI>Y)T0L=osz3!{b;KQE7N@PvT$9+aIkrh#!yANLgT6z&0U$9G2v#9c1?fN74wT`wpmw%N3%m&}$%D=LHrd+Yr;CpA58uA8WJ z#GzBJ{rMK;lE@8@swe=bnR+d|?&?jPgtN;gUe>U=3@FZ5ItI{9!rm;Qu(T@LeW@7& z5;ZiUM^^nHi5534(0wgzYgZhAwJcL^(AP^6Jk_`dyz)s}9gDf(#~bBV4@aV8cJC(- z9D(O#@ZW8kD{XUK2DRc({gK28K;7RokkoQu7|rLUrk3rRUb(T-X7P`iXd7+fR~mT) zF2@ZI%lYcMI66I^9?Ij^k54A=IMNKq%&+#BCFxa54ev()zq;p)M_U8oUmh8qN<(Nm z^G2W`_bK0@`p6se{<=CbMR4p4PpPgA(1oQ@+ouQr?!V;u1|+q_du(=}c@*?LPPiWzzt#6ZU^E|plLv$h_yr)8YKT4# zA3Xr@JaBod@-JMv?= z$;i4)C_jFCZt>0s>$t7*a{K_`X4VD|tr-!%N)^ih#@yCcF#+vqR+ft=HgfR0^Zj&z zDJN34lI-?SLc^wI!l)jb=a9=&>zW9$;Ly)tSx7oNZ_ewiw@iOqa0FqJ^uE8D?h3Q< zEALG3{O%MG6mU(jE^qo9DGn%c)g$@(WhyCY^a=vkxi<5y+>2EVCGAWu&&NsT>2y5I zudJ7niwOsbi@DM`(qG+l-@rrB(~IHe3HqR-a02$f3z0YA=f~>?xBSgLAQX7a>o0G^ zdp%%?K}%Jv)r|4EJrhHxXhYl06%WvJdOV9S*E`oh+||u$47pR z7AYgfsBUKnW=0sK=TThT%4X+`}^X_?fLu^xa&U#qQ9?@KRsuF^}D4l3Tqb)4jdHu}d5{~xF9~5>a zb?QFfHgv;kG!^Y3R$X#-`oHF~83zHd<>^FT4RPz#VR8B#k$vmna68x*POl`~goy`d zX}0wW@+DyXXWaXyUR2Nmom@KK{I4+w=%oTkeD&Yf*8dK=@jAD<3{Eh%4a#%XP=dbl zi5u+HvQH|q5p!jLtP=Hp=dO=}EHqu*j5OpC8US{PjzF5{(GPEPZpiSM!jp&pepE-) z%X7tNSQ`|;Mvx2mbRg*XK#8NuUlSn(8n!$>LL%_+!Qw*&Va(Mi@9Drqo=jQigd#CG zX&MiYma4FFKe0~b$Mv+v@meXY4)AmlzWV^ri^S?Oa9#bQ&#CA1gN~pc?d9^-{>`=s zLJ~mT8E9AqTX&C`J>B>dE^8lTA{pupk$?(6;j`}$TSGuwQ{Mc;3)eNn%_VOk+xGh# zqDzt4#qyqq;kgJ(Uj^%V5$~sSNe1OF?+s?Hi1{3Z^g-v;bn2~%sBAZi!?ML(BvC+w zj&|`hEg_akha-i9)M$3(5XE@E+H|Xgr6W#3;9jiRy<@;beKa0;jAq@;<4EG+?m$`_ zOZaFTLcHiccfH+gBWAE;-?53V)#Q|yR%x+#;zHms0+qz;Ue0$lCQ4wGvraztpp(J2 z?R}uTJ~H(tAR)Cq>Lfy?5gvn_cYw`w15aIfX-ta&|Z1y z!8#-hisaZh-Vl5l2i<;Y=mVlN0BAiu=2txZe5hJPv+}9I2;tZ5qJoSV^j)`sdhjao zW4T^=t?@28uliU1ydu84&VXtFZ^i4Es0eDDgnU#ItPUbq&TXka#*odk(+l>pf zBD&Oy)d$ZU>TSK6u|Av6w~{oweNn9(zBi3b6LO-7za|#51(5uL(E!9O`!l)5>{fnS zQ|Kopti(y)cpd1aX+$e9hE|PP-S+g{74LsUCoPX8X|G%+XqF~F5{exE-7Gob+QBu@g@mCaKUc&=UaY~M-I>J*`uF3^o|epf~qJR55-jUe6YpizRU33KTdP2o&y-C7$Q+VsS0^sjLJVcDxC znXYD`Z{$7qCGQsg>7?bCnPHB@@xfN1;9yMyuj4v5+-FJ3y9zdz)S8jb5^@93UZz)s z=isy}E1}3q>(YcS*sx-Gs2nWB+wQtcVFefu|J-)h>v3c`9u(U0E_^Z)VcywpPD(g% zXSAvy@u~w!Yf~3@(oC{6pzlz;l4UUck-PlnTO|ww!A0CE0iycd@Rv-yN?G*?O6q_O zudVg+hBp+E)~2*mCB)%CG^N&Q>U3{R=LQ5Ry`bk z`hco+u?-UImS^~AgquF+8PBJNnz9kR(lRIV&QE_``#xyUBQ0Bsi!ka|DxN&dD|~G` z?l3i&_GZ}V0vpK_v#uQ?g&-h)$v%H6tw#gJG4idnrMoOD-hK>Ql?=x(!ukLi;E8Cj z=HFtUo&@T4T@TE}Csdt54;yzYbCj5H&=TilN2zEZJ&H|rS!Vp@$$D^TWXF~kNiBY^ z(p%r+sv*DXpiPH1^M<7vJy!P^F2Ql7VY#B<@_L_1HCC{=&@Q1{S0f#!HaVAKn(_8B z%;)ZoLRaBs0io`q@xQe`@-;7L>uaO`{@g^|e6Mocl$cIm&S}|DP)PdzoKo`%jwUg^ znJhiKqYLM%I=J4ywxwinfkg)p((72!vRUQHY0tldO9yc=-1hE|xNEjoYs|D__1Ny) z01sEQ$3a0Kt3Zs`NmDLq19809)Ms{n3#ve;HSeEv$7UpN+^1AB$jh@< zlTaJ^iE+!(s?p@yJ|*;M#ov1*KZ&XL6oHsn@Tc*_pkEfgs{QpQF@jr*rCRJv94-ML zuzY`FFM0)Yv&A3xECnse7U)xnA`*4&7BvtS2!AX)g!2Fk-ftNX5w%LIa5jHhPp>c` zA!9gZSmsLd!~l0v99D&fbCmN_lQ=_SMZ zfjz_4QW8BJp>?@&9SJhU=0nDkAk*iOKTw+j4Z}cQk+CHG-&7GoPsKB~A@6sn)4Oem zkDWMzp)DNb1dC9(!R}bQBt7i1I_D7+db6E1gW?xCDcoEWO)pK3obPASf=3CbuAbil z6R<}JUj>Y*V1%&%??!`8i=p*wSv=sX)L9=pQ(fm%<#oZ3c(|H`REBS-eKl!`U+2+)XxF2$hy_ z1<^Fa(G8Tb|8e%T!EEukMB|lgna%N0#&W(F0wz3@gth!kHMLBhO2TL;pDN~NPhGbw zTTFy|G}Pl`AUoEY`-=DCMJrXT0o$oI4U8;?gBf?y5%k}^G&ubAv7Zu2MMbCzC9`PU zi&~z(#Jf-hl$}>l1+xtz*s(55<|=SQbQ;5yWKk6sV(%}EB*Q-%<-KQ`i6aaYZsG5g zD&tn8tQGPe6+C^aB{5W;?OXbZhVOAEr2biBp2)9gr`*J3fZwcj6SOQ;y42ENTx2Av zXw>E_cgT}`18dJV@X3bK$=8w4pWl4(bm$8LEW_gDjE1%4+A^ZM_*{Dm)FMZ-2>)(j z&)G(piZc%fZH+h%a4zig5ICjNGz4ZW+^~Q~XDb!z;a^m+7z@${|3H}o#r4B;v2*2u zNjR=$x5Z<1u~qLfUSA#pH|>}R^1qSqF&j{Y~xH85XCzgeJOPz={e=79pK{U_M0s9`YTQvR} zH1i@q)d%WM)(gb->PxfZmxW$@Zb7#oD+WBVuzx>sXYVczUUYjB7a%kxFn6NM(qfH= zsAz&I*-crrx3k1*)J?BbtmRCEglY5$_yWlMrv^+1NW zB^hCEW&8*LY7VQ}*U3#(tu=|DJ@0}{Bq&(KMd?0=_B=|#9BsmmOD=&>+wOrLYPN&$ zT*f^#X-^KVV)-8pcO$uR4fdUWeEucN-HGZKS&o1o#vSNiZ!xY+;<1J?6HJZ_okcbj zKAS%zZNMuXj7DVkp;g2rB+a`De8}Oc3;8K7HnQCD;7U=~t8X%|M0F^Clin|c6 zll!{UkA_|vsMt8b6q>Fe`+JT zaWU=m64l}B1lgTDiSL@*q*H#ZPoI&#ODkvjYv5)3kGnAlH?T$;{Y-4nh3Pt`C)VQ* zOH!5LAn*q3>pPv_*+K4yPpSJ{)wFY*s882+#MPC-pYfS;_2;2t)IgG9AOm?N>@al)?U)_S9F%8`v8CsC* zm=w1j$WR9a>~YBT2CBqAsF+V%HNa3&cAf<6EUR&)#bcd&$8AbZTgjGM;AI)kt(R(a zq^nt8L~t4;NRoKZv7MbbpDXqreqmDHEI;t5igDk{nv2iZsL(f+Lp~#Un>WIjjob^z zT5T8IlFC8hBI1n`gBV2oqsXg=GhnS8gf2Qsmki?BdH?ljgyXhCbC88+7gm zFjpvQElNv$P!QoG5W;r(oV~{fA zSwqWum^l_hwgAdk=`y#pXpFU(ll->+<=y)&vE(it`}U+ln($AkTdx!&@O?YT z;14lSIj1M@*&75*FT~6ap(S)iCqFHL5cQlF*i{uI8eevpbQod6UDt@MPC>UPrXM&( zpRsr23kyqEbiB&G0P@gvZ-AY;i+>yU)|8gb_e|fEODFZ)boO0Qg8b>xs+H=JIP+Lo z-TZN`LT$T@TEmQ`^%bb$+IAU9U-tENH5O^#Hj2NG5#pIqaC4etT$OQ%??KqKS7K0z ziSJ?LLW7B*7it}b3KZLFlp|{A)~T45w)l7o6_1r5$U%&&hhn~Pi4Q_>F9A?UtZL*L zhz{5g+T9KMBx#x^{F#=66Rq3To(`a#ht&6ik7WPS*c#DdJ&QZL+hN?6AgWeX8d1b zh{o11;gx~;s5LHLzFBJ-jiW`yE6X32J4Z2ViM=)u8cxjo9yrDz5sviJZ7LFlCIo&f z?6pj+-}YX$mgn){D9VC#_)xbWixkk26-V4ocyA{p^#7ia|9e9I?+E$--6aDBGaQDv zh2z%|zoN3~I#u(7V%Qzp&jb|gQ&6rXco6|iYwcLuk1^yz{5kq?enQ1fllF^sS6#5) zq&v=HzKEF66hd%6p|Hqc{`-$?e_&2krRwv>{{JlcDI|{=1+@!DN=oxTtN+h;{R+v1 zU_O43uFClDE&b0TXo@HtV3OhP>JJJ1-~Z}AS0JND+)9J0i7{0bBTe(J?lyEW`LLa? z49R9}+q+6r%gmuHDZGv2U^>7Kmv}8QACFR*@*;SkA0z90Yx+gF3lNW_0o02rprBWK zKR=Xaggr!TZ*MD+ijX}kxc^PXK?jjy`)j-(V6`CxT$FUHjIX3t?D}z0F~%tM~pH*IaRX+AH$L|1GHALoGy+B`YS5~ z0iRT_eu|5C2ZnC`+3BVsD#a~@=JV@#q0YW-n1)fSKte%ES~^sI?J>8sl#zof@mog9 zgx5HG)T(})mkglsZvjCzWql=bnFPkca#*aUu!p#m%!|*VDiEhw;g9K~2+;5DkIS|i z0MQQD1n>*S_XS5AF4Qb_1pk=(QVLniEYxeMS5-fW2I>uc!Eh=FHIu@?@o+^$?FPpx z!Ocl~+iGrz`O9&Xzo8hTDJ8x&*e&Ne+2;*|eEziZJgadlZa)v~>qeBs#?67uq7AP* zQ?`&ev@(>F(R905Ijr_gHYlLUR*Wx?m-^D0{V1l_twm9bAV z#X+bvRUFr{lwFQfHQII7gPiRzX!n0R?WKAi&`d`b>Mov~A^Wct=cVQzWV20^(%#4D zs>P!$2JL*fRCB7tx#{;0smM1`MWA<`4>!jQJs}veJ0scyKm$^jl~no+pO+>U#t8Dx z!2$avsmh{n7!|#08U{=uMeeK8TyNl^B#vWK$ghkcs`T)u%?qWqUnblcm0 zjr&?{AXn4jZ4C=J=?bemKRAVlLn=rLs0nk;WNX$EB1_TbILSWX_|`1@VPAB5QJXf) znuyab1__5|FZlQ!WYwP8*_`cyh!fkU7+o2{=kpC7+^NbBd*8O^kCF#8c0qaq#vgSo zjoie~yuS3$U;TkM*A5N}fS(v&t!7$n)aIUZN-#~qZ&*B$!Di^2>U=Y=J`i`QT~W=* z#1s#_uzQLuol>PoJ}nRzD*txz6mMc=C!?KH1%Jz9oMKnVP+GBzOi3qpol?3ev)9Xx z^$4)SKbdP6CGmRttW~1V!;)YClN$NNBYg&#yi5jT`l2C7z!$z+%}M<=U|&JzbkjdO zQApvCTLB$1u~?ZcAG)8&N_rp5AFZ@47GHmNlCKQqkpj*a!G|YkoNLs~2x71JkB+@v zJRe36126=m%riV^*vq47JLjWT8>0+W;=O@R*@PFYt-((AW5h?2GNg4P*R8tVH0L%0 z6_&tH3hX(<6g!K7(#uH%u;)Hc=T7TEcv8#FA#PQEJCSL;Tj%{G316*Sg9;wVfvp-$ zN;xcDp<)5PgWs|BwhJ?Nnm~BM)DwUy^7-_7?~K|E*y~FDzxGlOP;MuH1|@`dBT2lH z>FF1>=DL(}zB+X_bkweg-_+F9zORw>0+}kgColjzn+`Lyj8uuo?O!OY+RWF>rw9K| z=Qp`B%_;L&89fZs?K{Q&A1^?A6q17MfX;wnF@+{s$4D|~!>{6b4d55f1>Qpr;sp}f zLl9vZb&tI&hx7r|suZ3fyIO`a_;#vhL$encaYO1%rc2YCrSy%XheIs0gOtDH{sD3f zKT}S5)j4b$BwUS5dLIUS7vqh|$!Y z^}Be|W24=oh%DCSCVlOg?R7wRq~2Apnbkh5S^0*V4O0l9;{4K%#& z3|hhKxQg#2`ZSJ9<7#)sLg-tMuD#9??5B`5|=kr zyvT4=3RJz2aptQnXIhi4j>cs|2g?W4Ln3q1jcR~P+!)(v?D5*7#NDi&fu)0Qh$ z1o1&qM#aBZcE@RU*`5B6;93%Rm7)}L8L-^iz7&$T^Jv;=rMXyXBj*tt)|x(O$5St& z@t2iRY2yI_{gvD4j2`8m1#Ke6CJ*(RG+qolOm{`J(md{CYd##q(sfzjpHu_C`V++O z-h0A?A6C7RNw3AN&g!^y7VS%i#ui`aNvc5y9KNq9Mb}(WpgCk;_y)xV6OvSZb>GdJ zBE6J$8TQTD8StyP zY`-&(yFx`#pPK=4OWG(~9L<_5#pCRY4fX};+xhR{eRzm4DtUJ~wR*pCz~R?_N}!CX zo@V#msRiFdMc**GzptsX98ERwuz12Yyy95q?vmI0^~)w_0%A?~X*f_YC#O-&s-u11eFcRDcAi~jXx4$rOmyubZmujbknyMZNY4Tv@k zHM<^Kk^Mn|KAF!c_+me^?TM@fch%?^@N>B_!(3pxZMu&<_XYV#;wN0{j{JJ{C~w;ud}eu!)=7hmULZLy2O^$LgW%v5Zf$P~)Ji4SV>7ey~~jg9^e`^9ECN}WH5J8L!- zHrJ@9fZmNeeRT_5r6TgYwm;Wi@xb*`uE)>*;tEEQB6Bq=3as`#hqZ<)wW7!4m$KGe zQETyp=iB9rF$~ad6{kzq^-q}w&rCFsqWlA`a_4j%h|~0<%@r_OM42-EU=g&f-{(sE zqIi_0M2Di71UUZtn)?!Ui)n$c#CboG7dvXM5^adR_Jcfi(M#x?gdW#7ps8MhW~Z9^ z$)DYHFMWZBJxU0Rf~2po^77WKGb|lRXZAP)(x@9&Vo9|8jA?9yMfLe#El71*T#@;G z)jQD;bTwr*E=K`|32uF_=dVehje~dJO&otW04@K{%axb@dU4p~_vL07*oHbp%J-6z zdMc~Y=E`)UcCf2EGcn)~vlczh>yuBr$jRhLnny$I(~dbD!fH%7oY#1s378yuG$T-U zrbc&{4}0xtpTKFPqV;Y4ThQb}ylyrLe2rpV=i{IYy&dRX zX~jpcyf1cBjmh+OON~k-;3Fjnj%TyM6~3&|GXH+#D5-n~TDS7B=A#Bw{GE4C5Z zT?e7yYN7;~BoyKNh}x~O8x!}z=pziKT@90vE#3aGt-jHI$#c@US=tASY)bw_Xo5dI zgvX+v8UwZIy`{aL$bzY}M*-x&E|7;ZNgR8zW*iO2mY2WfwpdGX(ttjKjSg{XocJ(^ z!(#>Vs$=pG38bU}6A;b~YBc)TIYjVvshYo@-x(WcPnL(j<`};?O>~wuI$%y1L5B|7 zDu?LH7>k&I(Ckvvp~aADOZ+#8KOe$f%;{5Sa*v|wr_~!&6pXndY8hM&UP7elb0EiR zXj^J1AbQToxRQxeX+L;{%Hwdi9-`ys5ENWTu2v+IQ2x#LRtG3urmv@c`c-Y*k6toD z%%fp^IR@^NgZK+%d^p4|HBMb0N!Q2)W|4O%K(eiPM9nRW3Dfw!i)b`Ut$jvo)L>7_ zzPlHC-+6GQ-pO@FnRB9#V=lqff__I|XkucyIR~@^2O@`~Bb6>^noJcpLV=cKo%^VZ zBv9TV8UUpJ{YIz>T47(uGIjk*4NjaE_fztgIE=g!Ig{eDuxsv4+v($Dny#b^Nw#gM z0*Veru7-_z4gYaz_ZP#h%EW;nsGb@Gwr9W?rnSN?ODJhAuJ}WhL)sB{?H`R`pK4w| z^T+@eB@;{QrT@ooj&}Kkuq+xtHN@lJ5*63%$2HY0yk~)(MB^_V<$l}LeyGu#Q2f5< zGTYGant}>I05fMM@HAX#F4Nrg=3rWf)3%=a0y*sgmZDaY6O0Rfu+*ND1>SrDIP@Sw zCRNff;I176W}9liUc=7`;fcO{c@ylIgbl>b@-Np1Gm}BWC=3ekZF?=15>I-*xvpHP zj}(Dr`8zeaJe$})bZNJN;!QD9skl;-;ejedY_!1@5s#UDvJm8^@HX3TLDhyrv_EE_ zVBuh)F2!}UGR^&@7QBCjYTHeupnS>qlItc%j8dLglQUa8K3SCgS-S zHD4Q~x{SH-%izL9j9{kbwL5JiTjndd0dH|Gx=^F6?v9f-6C1L6E!4dBgsTg~w`TvQ z@bY&?(mlPSH~suc0=8(nnpFMdCA~kBH2AqNpP{XU=l+o03P`u-1ql>f$x@T@WShz6r# z7Yp%9JCv(ssze*KTvmQgBt3R8o5S`vQw~}nrRognJ~=1hgmxpb-*K(OHDg>rfm`@0_R(BkRnkJ4mR?!dPnhsG^#lk z=ut86arw`DofhsdPxl1wEU|JIG&p~Fnth4*EGotQKhw2WsHq5QoHk`J5W$4s@<>;% zI{R8rPdNL=2J$aHzoYBwMn_ThkiyJHR`^N05fg@hKV2Q0CYWmL$QgT07r&BNY>v-D z;}n=kK}FCU!CL-6=;@28zL#l$!Af%qFRjd89jYzdu~BGF)@AVcZ#Gw9Rp3C5C$sNq z=b!Ggv(W3}Vf-Mh4J1t-J9UV=GiiW@F!3Jzcu2hYJBzLu7r#q6POG--5U!O<<;v%2&DLR90q1t z3CV{e^``5|Wot&nXzRcz`aNV3`7~~lB18vZCgKZGwAy37!g%g$!D5S8-GjcV5S$kv zpy3zI@G2qcK_}P11BHfu#ep7;gZ)v7iFR?qpnXDrDHm{-VWGh zk}Dywc4JW7O(3z=KV|AeKkfdxpgTZF+Dfwp!|;5Rn09BEU3sTS=;(j43YB}(z@*Y4 z0JDGB=s0X@0F0-{RG3^%n5vQ7CgZo@I<$dCFtzh{L;c<#iNyjza=y{cRdTbc4A(1v zth`dWI}>-u(0BN}+IwFYB~`LXxnj=P`3aH7l}^5G30RLqWmUylPq;O~FvsIlYvYCp5|tF-#?p6hz}h52Yx zW6}}&3=i9|Vj=eV8F*2~|IR>NP2F7Rp8h!`6!Sj%CTIhG+Nn5hK(z>_1rjIoE~y3i zOWYhX!Bk&bTc%i^j4D*G2v*DTr#>{;P=8cS#I;o+k<25>gQnk_h-9g_-1JGsLhJ~Q z&8nE$3)-~Y_?c)2YS)`g=T^Fof~}?_s&;eNbu1p-Ko8yovQD=ksYjAPKardHtxI7I z%w($&#vI=v`enGTt&DbL7fu<-5&hVJ%xbk(Te~zcY4qsrL(AKf$xX8l9hR8n4*C@T zAt@bw%qvw|j04uU;)jiyKGuvE53ce!&W}b#^^-5N{>foc;%U+t)$ltf>Pc50k#z+F zJN)Tu0e{JAX1j~UD!Ec8VjvVs{pS#gI zMw(QC`KZ;MdStc4LuWm82~3;MD>=XOPDKGFz9S9kC#hMWllFY8WzB9ffqdGPi0s)% z6K$QgPBnyL?20bnNqsy=M1gs(^?nSCCW_nSHzEFhxrth4)ru(A*Ws)(ow`5F$*=K$`SfEq&FH7UozW|w^@M3O1A4L& z2jz2X$fIdG@e_}cf{lh;OmS{f_lb>OmQ6MnfDjFu7rvQisSvY<<@8C1z_qIW=F75? zuDn(NUndT#y=Xpz%BX$*ZqG%_;6og;@qyOa0-hv)551{VPbGQ9UkmMrvwZ#N|E2c_v^QqCq&&JIk-W~5=eDfWD zCq>O?LROztE^7oyO2>FS%|9T!X4FkKFHY~`cI@Jm1XQGcol#mFLZ7pBgp2MeydT`X z6bimI)Lr?p25W#kSx}t(>*E?NjljOv`LpasCnpiM4f6e0KoFKw1GFvKjr@f&Rf`Rq zEk}*tHQjw_vjEMbjDBpiX0ImtCn-!S6B0+z)8FxQqv65g{B9f`&x`l>UwY`E23;Vh zOG#)*9BEI5hL{3HUq|>*RFaNB!8(^ZD1}S!$ILmW!+n&!g5q z;pvZc5HB}s&m4f>QN(0|Y# z_S(!h=Tb9#x;rPNc4r-4@dUVdLl=LE>^*QL0STA~J3J?bZTksyVuMJ^s)SHvzOM2G zkV`-Hq;o3-R7Gd7yGQczZ(BnAS-W9ve)A9@MWWopzXNug4))yuw|RyhWgzl4L`FuY z?9#4Hw@G%xf;NeE?#qRBH6R6jI7mvU_~dh&Y}KGl9(cBE4?e_ZNbB)D{x6}oWHc~= z0S_kJEhb1bMZ$a20z&xJhHA5dz&?nSmu0{WFh90;XF8|x#zwC-Mj5EMMuB$vv=N*u zikty@gNEh!T#vQyPu9Kv&~h6kunfajr2RL=yyd=@OyJ&Zr3I-%*py)P?_%9Huyar~|DlymxLK1>=&{iADmN;>&(%cn+1b>UCD@uzX< zt-N}Au;z>M*x^2$gO}F7+3i5Vjv1ai4g_3hQ&!_DI#VUDy@5#n^vn7cKZb$(Z+Pk! zP`J1k_}gp!8V2qt0yJobdNVcqRaO4S1!>wr&)w9LzTX(rKj_82Nit6`enYIS=^^Wy zyAJe&eO?Gz4fIQ{aHM zAVbB)mfz-TaAe+|B1RP1H7gSYN$=V z&UQuCE%MlSfeea&vsCF2fuM7}se+|k5&j``!MCbTUNeIM99M&W;H%|<)(Km-+z^^5 zPeW=u(ODQOG$6OSxlwNDiIKs=?1wX4habeUz!jR`i^QBthX?_#yA+A%K|GjR z%ePO?jVGffguNt|flsJ9-#!UN1#Umk}Zwug=Ru1ui z1swz1`%PJ*A^*P4>NC8K`OD+b$`4QK+$XyLn^6|@7xD$+!u_)efJ@}Td=Ha9U;Ekk z@4!IxYTR!6V@uUx#hXZM*YS*ge-?nT^|HD`8dtnEC9isgdU$(S-lD$(x*QoWOo=r_ z^-6@BD-b$u+tuG+$_rcaI_19@mn2p58anSMWibFcq-_J)&}bm~z-5a0{Y zGh-kpFRxmpM7E%%Tgtbp{>c4%hgieyX+;bg(Tw%=$?o>Nd0U3-H<;AN+4JX9AA{Me z)u@7ubY4L zr)X52FAlLTaCZ|!%<*9odW?Y5Ek^>{%hJR&{PDhF*{$W{*eft==%MqLwmqHy#)yJ? zoMI8c1;cgMYlaJCe-vhWGu+?_lVftE?9h-&e)J4XEkk*EOG^PJ;VoLhdub}9%46Mo zAjoOr%cH{Fbcby@o}I^c)=9b*!MSoqWruC3;4t0Tq_Qi25oYkDyijLL3*@Gy?3%X! z^zz$1w`}j|n5-2Q;MyJ^+W7#rBBvfSPR+>1mXl@%PO_IvmwLFnxy{J3zX87@B7lM* zizYlb0+&tv>I9Y{OJ~vswB1x;7N9g~a>OOb;D1=Ai>;K~(7y`0l|X<#(E5+sa14~B z7HIsyYtBZS9%Ctk;KG=76;S^`mrTFXi8n**PYlJ)Vo#v~+ry8H-tJ34lMgbUE?osdaDcf!J4 zzrp0G>kFqpBprd?pK5E_GHJDHej{b7;{%U=o+{FloT)Hii6G*vpGh5nmghuY z0~*Awjz=A$P1NaVXtCORN3hP4z2}hyz4NTKm{z7KWVCNRr|~>(OS(Xy?rKbZaKHN8 zF9qNTu+L;4cfX+64;*AG;YrJY5oTVTcZZ`_OT4?aw)ATtiRZlOjKS;6ZHLb3OXNTEz5N22$$YueTW~g;k0zy@&(&tel*KEK9DJp7oV&(J{ljA~ zj)G?MZxkYNv_sA)($#z8H+N+5{wcr>Fl)P=6wgq{@dQExPhF!Gl6Q?nDIuhug$ta} z<(Gd`Ds+ls=R8q$|N$%)t8*zIY8Nz>q+nMnN4A`cl(-@2vNjYWXQkB^b9uP`?70zVy;3L+(T?!0e$y?k_@S!!aV~D~u1QIjO0R4+No@ zdj`)38csk?n?CfetKTNTL{Aa#bj}jWp8T-AZ?t)HC<*-)EdN-Y@U-;T`YsgTt|1d+oXAoa>%I*lL<(%v{9{Sp{0T@a78Jo-4I@|%dpa78>4s#<3l-UzcPb#LXq7#7S?FlToVK#;j?<-U5&0bUkvK?9lffZNY|X$D z0D_cqP|yNOXDW@QOVzlyjaZf76H!jH)Rc#4TKx3S!QC1go>fNQXZEkhPN@PexO$J> z8%7ttA&TycfM6{Z5UTOTK+8 zQ>iQvOLrcXXYL9(V-jk)zw8Q^Zya-|xt#L&2NqzAt1uJ!;bq;t-~IjLts60HOpKxH zbWmcN{33t{z59vf$8`G=>+W^B-~H_c>m_#Tux8sy*GEb_9D|K73+F9@M{dPEZu_$q zIEP4e98j$CWQ1(mmgyTvz`=NJ#b*+B$96d@^#{}ovgAIWQgYJF+=Fe3{hKJg`pXpJ z52|@2cKbde6DaL2XbpsQBZp66TDe)9;ZZ5AruI2 zOZ#YL&Dzhr{X*q;=qtdYAb5ZTZ2}Qfj&{xdix)4tJSTmz9$g;h`(A4=#nX<@Jybmf zRk0^*i$Ha<&?qF(rf*X)`vZydUW>HR(_D`$P?9lQ2 zpmM>li**Fsjn`QdlU)jz2elg%J4*}vEqUhS2Kf%tm`R3|eZ&uh5eA#D25w(f=3ck{ zxsoM`NeYE9&h?j?JhPpjKt?S!8b~W-h*qb3RiZ_IUzB~*?#rmjEbpC(`~SL|@;=2>5qTkIY`_Lq*!mJN|{EUW+j=Zu(aWzbNJxO8E)%7V7dAe~fArkpV^9SbXx1v4E z!2ExI>D|wS*vcMCio}E*hYz1+0Q&{AOphJ_UWbEfmCTk-KQ8*H?zxn!{rY&qK_C89 z92901H#VV$fiFB&lcpiQP9oO_Z|>u{xaTL%^#UG#RL9a+ESkSbkoT(&;Skc z?ifz~K94ae!!clQwV!l8xJ<io%VyI1WrZ z*lCC@Vm-1G_B@SVvS{MCqdf4E4c8hN9v+Ena*c)SOQ660Y_)haLG0uoQ;=f$*K!45 zFXR28D0#bfp`jiAj!55Q?QxB&*Mb}B( zR%jlX$6az~eM^BIc?8JYnpgeeI$))rs}RiktG$O;ZzCSNzMfY|djc}o{QQ5uWwA=u zDH`3zRQ!I3B=-u5Wa3s0%1#XJ9G?G-3J{=2*O6aTBd~glm3~-FJ;nI`J(a4Zn^=ZP z6~M2!^>eE~Z3Q2dzOrzNb7G7*1Jh zn=U0Q{^>W3C);5x#nFIHIGDeV-YN7RP^EOb-q_~CUqB+-22`>uZ!I(GGuaY z%99+wyEcI@C|0c3?HDPY0cfKr0WyoW+GqHI*jYpb60c*9c`mYQLoHj9P}m2Zq{Y<> z&wM?nQjg*MldF;v?+$^atcHeG0TW|Czz?mdkV1E;RYiAr6(I9A_vMOaK4aLAvEPBC ztY(58lU$oWu?Q4j4!fpZhl|XPB-U429w~ldiL`f4nGGb<&L)yj*_)$e;Hx80DF|n4 zns$6LLr|YO@v{-vfbWOx-Qq=I*uam;Vr`a4Ql3~KsI1Aqw14g}8$Ko(X{I8$$KAIQ zjzJ^HMsY9VeQ95-*;v}09DFBHlIFQx5*jvAi)-MvTi?OhGUh`TxX&uVHJBZnYTRMI&ye?q!xhGgSlSIL2O>6eLJ*zYF_(Y)fJf!>= zT}xAYdvJ(<5QNd;u>>~oLXiVF=Q5PDFab?tV=yB+%1w~21t+%o1aeY$w!QtvX3peK zK`^G_(1jX+g+wwf5i%n3g?7o$c94P^%u(q_?Y>G2hd6hKPDNoB%zX!|&xm}sxEtIiq(Z3n25J?VrBq@oB#-117qGUI zW{xrXHs$==Xi!hC#gk2&BHGviS(qr>z?V|ae;|QFc2mN?^YddIMA&!*m6|CjUCVet z1~#}Y+Ln8bq;Po6%{vldRC_hKiqv8FZAqRJE#Pb?jr_(KSeEmbq(xg1lt?yh2$AFv z+kV5;Zs5%*=O0PPfxIaLZY%Kr`fcT~*j+M+03V0#!S<0=93r1DC);EQSh67RhFP#= zii;g2tf=;7(Ps71lK!1l=EGh2Z@1qRw(C~@jD-+l{F#2Hl>A6AhR_6*eZRI))XT{G z8!_C4`PCh+^+p^-CA0(cqa8SZGRqO zhRs%4DVnTNylL`&vn$U&Wm~($uq1}qKx2Rpb&b_04dIJ102oQotj2gXBxbZooA>*? zHgm;dI(>7^0G1gQ`bv{=H~s z6Qsmna`w1ybo9kclTR`uPE4YEU^wr!6sRlU@rkUXg5XKj{%D;H`%uw;4B%n}0cxw- zvay|maeBN;8#BLCHdG7)u`{YsA&T$!A<6yS&tS^#iXovL;<9eM<-ZXNzRNiOi_yTe zMD;OV^rXXf#37FsI)+>eU%oC$Ve~v5r5ys)QVU#+ z1NR18gYo@ux&_rQ$@wZ}cE-QQahnfQadd};MQ)!7S5io36E^(R>g~dFAcZnb2H7GqHZ$rkhwH{I&n7LI&O}`tSA8m zfXGU_yoOUtM!rgiHiJ@{y4GU{o-%>T9vSEEXllpVF+QWW}aA29Izmi`XQ zcT7PuN@{RjNsvT54ianpb7s=N*_UHhlJ*F-c$DVH$-2)Ip#H%>lhtwBpa-xtgQXkB zom_ZOP*y97k)=zrl_CZ8(XKOom0p&|+^@}Rcb96G3YxSp;u0?dBe6W-`v-@8aUUHF zO~3Srni9oW(O=wG(0Mb1bv(AJPJZt*#0Y~hZ+kemWWoCz2_-d*8OPsdYqqN3iTcI{ zkdZj?l8%DZJNW|b4oLh~2;J_>{h5lqFUT`&!{S1+v|q@3=>Pz@z1~sM-!q=n*IPgk zSjdXDP`9-xF&@O}q!VSFUCqUzB;!Q)zcr*-(^+?YdvIsnH%lFRnXK7*?ALC9bg0PjjUz7JQ1lTHz)&0V_V1Jxq7{Sf5_5_y;{`bL zU>Hxy`}*+2oR$G=i)t@|vr!)+c8P61lb@sG(V=NERc!Os$zD(8ra83SBI}~HGlr_g z$hJ;#`}@@78-Dhsui_KpF9}@t>HHxpkH4#boyb)*zQ4OI-|urN_nfe_x`6(gW_ev) ziOJzcvc#aAOcy3Zg=pRtwKw|10dIjoShMyaGOr)VJHl<7uNDl3d^Jw)9B7=tSdpxCcE1 zpsrPna(rbCPSwE&^ow!eVBea(6!f+6@JStUyD}fTirSm2?h6b;&u^>-3AWMdqE}xg zt7D2kRE^6NJ&wdScf+Tc)H+lH6S?S#+$})Hf>BkC64qj3c)vES*e#1tL8XS8+|Ul=8qV-8lGy^&SFFRBROL2f9?ysDNlm z&UUab{*Ds9+UDur1Q6lEvsj;*GXwi^`jE$Wm@l-S>%|a2_lKL_SwF`OXID7AE^V7- zp*Z1uic}EII-~ zzglbqvMI#BA%q1Z6S<>A{+Rde)Z71RC9$b@<61G6;@FBJ;}|_|1(1%+)0h`lPVIft zhQI$-K;KS+`&oo=KP#id%SoI{9h04A1z>b3`2jbQt#cSKRo>?jbiJ)heF(tJgJ-1q zDi^zNsz% z?Qu&%Wgon&GwdhoL$}rMM)kbA+A!Xquk}#(OhecuRuGAP0PJnP?7xlzkSW=Bh+Wnx z5Cec}b4K;d=WIZyIUM)Mc=|5 zmEGI{;B(>yZG!>=->h%~G^GuCoUON%z_o$Br+MK=& z8d)|!q>jw3 z!%s$E&i~e&Ha(ODX3u2kgo@c=y({%Ng+|%mhW5eN(Bq4wV(Zp4u14Da=45NBYXAg! zi`7t~u69MW+R`S4H|^QbFk zR&P9I*o?6fEv1k#$(YR2JWQYEAfJ++Dm4MF@EI9Q+z^+u<5{KPIF}?6Y57|anJQ5| zaO;Aj#{f7NVk&{BR;Ru=*TU;{6V=GRm?O1LR95Dw@ zha@%oRcQ0Y;x(s+(S4&H9mC&@$A1@%@uC(N&S#}9nY{6kzdh$i8;XI*iYx3ImEm0e z2iz^caGo`eQ8h+Y^mg3oB7(Ms2UTVy2>5g+LfhS3hSa_-#H$}fUSQ$|0~WzishJjq`*%C~_jL^bvT+Q6F?lvW>0sVJkqEnk z2%};_(^q+o2`CUD_zd?1Ii1#((wPX?IaGd6IM@J~)6F{Xg<^%N@>)XkWsY~tNhFXHTCyym=doL$0UGp@vsF@@ z@9SLl9-F25R6o%y6$9!3Mec#!&o|&0zI6Ls?OlD(nH86$X9@bWY>!ZoxVF6#otfQrSFPE|A7T)wZA%En_zh8t~gtB5dHb#$(i!y z4V~l#5!f@HGKLbcl!30ae%H5>2RA3OAjj}(X;blBWSbb(p2xG(i<8zsHVLRbObOh3 z^u*FTZlt<-(zGOL^E-p;G-2g$FE&ubpUKnSt!EqrqTEX7pjp5`GH(KpjaHxD?Sb1f zp+7)ye-a_JU<0z`-8Y~>hujB5!kDpyZw#IdF-wRQ-wwKEmweEiVr7nT*=hRpfuyO< zy5~iBWkxEQ?1PRmv$ia6(XM^++s`mPRF4p?H7faK*!y! zM)^xZrJRrPTJ`rJR0exGtfH8HENnrNnU-5RTS zn(k{Z&?oa&x*`*R^osV*;_)$>$M*MTEyU}u;cW4qE<0L7cGGHU6Awg82teQBDg7?L;i!}JmHFYX;EQ-4gR?%+<%Rf*6LcIybsT$YxVbIz3BJCM&Z!s_(!TpMC4YQ6rm9UHlxInVdwOZ- z=cUD%q-fl2A-SqNv31{g?TZmH=dXz2b#^uA-rWHUPR zN#L4)ymV>o&di7`IjiXSz!aRz{%i1Drmt0%P-~HKJL%%;GtYpaskcO>Z}$aWc8z2g z=5eZ3GcDWw&YF}K!DMRJIll@pXMWm)nIBz@@UNN%4TJ3;@uMCBd&jahk`*j;bJ+GO zf5EN!T99owH-j7DSf)2^kq)(OLd#IsYNrL4sqYCF&K|!*QIA11t~u0_ z<+b+Nh!wX2C|pD!UV?5RpJm5e{JVeGX>=W)K@rAxE`p`LRn(VgYU&7|TfV7t{yu+J zk^bQ^;MlLxrRjYC$ajo#b@b7C`t+)BUUZdbcs%0C8|?+-vL={Mu$$j5co zfzCT)`aT-!$dviN$inI$^4+b1vh($Lgg5T8)ibhH%6s?cmJ|6o)WaKFG7O>>=QnI8=OD;Ve7urPyStm> z^uDx4ukp5VnZ?N!b?ind;gejW^My)_JNxhxbtajqY>P1f-I<9ZdM`A$rM|B`3tHKjSV$)2Qdao}a!e6H)zAm=}(NbZU*Pz4Gx@4HY{-A5`y@fdqI zN3wFhKV41tJ`NquIYZ33fID$EGJ>v)w{THxInE6v!+8nxYMPGi&Kw5u^Lp&&yq!pJ%~ zLTOfdU4qRH%WK=ZE7Pl8uA-O4r1pQC?c2&Rm9d}`msbK&x}t5qG}^*#^EX|{cT9kv z8V%=JaQfZd@a2>2n6c-cqQu41WI`20xjmJU7DJmLKT#Upj z)ZL4*Z&5e->}PY_qrqMm^Q2=RCm+AEG)4~QN5@B&37(JGJP56TW$lm<@!cEE?ND7O zj2Y7f`W`~4n5814}3 zdeo@^(-GQTndG$5nx`8)!i75hH4bY$>S3Qh3JabtR`0!6y_f)(M&{E&I35hB$oy9b z3SXBZVn4h}r!(Vd%#6KEr!s*81L{OIxcn#g95qZTV;EQR+Pn==hZx#Tz(Z3ju6I0)!f=sI0Pcm^~_91WzX zT)}g6sjQN*GdgUGVS|KzpjeU(K$as1O8E1z0(DbNpgtHR1LCz|l#|;`N&h(aO({d; z;BRI!Vb7f3(Lgc5v+rTsd@1|7))FGN3!M0<)NXzQmEYq5RG{*S1i(Q+!xat=f@`=| zkOM_Sv`FAKWa6w}O9lgY&v0maH|F!92z;x}2huPy@a%Kcv)o3~eE~QD(?EumOfbf& zC8Zra;C~cAfS_$gw5cG7JMrO+3b=@DFeW_i#0!lf|C&b3JUNUJhR6q=y;>5)oni3^ zw6HQzk>+!y+3@EN1rPY2tfBvmAA@8P53tBVX&+2Jt)P@J*NehTQhZc<@a)#X=3@~A ztjIEmhQZ)DcBKZPPPloPhyjqZCn%q09-y+jP%$Bzj|BpWT2P-?GY1QX9?8B$DF9$k zVDe>LLp)8hH6?kOfO>6c`!wcAE-{N1W&}z*ybe7bnu4%Sr$YX}8}I)M8!w<6dszbE z=S3I#UmBlAEm@sQ)bPv-AvT%KPwZvGGK1mc4ot8EzGMCq8Uo&T2u?R4tOxLJ4vKTI zD7)8?yyH>ufd=xjVTP@3GF{7hFOL!}Efh13yMJGiT8P1vwsQmrU_BVYomS{<-T`B0 z9nCJu4l)n_US^TPU5-WxTmW*RRG+|m9sJ_S?n?&n6)x)brAC1F-~AWe?})zyT;T-> zf_VQ|?|ZD`FRtW{695#99}izi#T_Vo02$L?|`X+KwkyqQh@iw02h{70>gkc z746*#91(Eae^R7X6$>QJde;Y%jXttY*_OSA!qgBE(QrmyU}M==cM`1D0GUw$gQo$y zq;cit<Ek_CJGOH2XHTAJn_<#mdJq^ngxf!da$>P$1M| zBXz#NzykLvfsAOHcvvq&F3E`cgNM;hgCcWiNsf9u8u2-Ra_Mu;qe?^bKc#n<6X0r` zu5PXei#8LUp++kI4%mqJo6zO2XLq;%)VVbLm(FG6W`_7X?$x*M7;B4aP2v=+J}-eh z+_wCYypqt*j$|KrxdD}o@&p8^rHnt^oiI@@;cAvkKjI9)WAX#g06pv(_K)*fs~jK( z`s~hUaGwA8^i!TN?IR1=e7=by^LOpn`T6;{2*}j7fWZCx08o+&^biYPv3?)@tx5XK zb-uFiCGBjM85Xh6jJd`5x987dd;r&q^H(Tp+KIoslG50XeN?dLBbD03Nfum#F*=gP zBS7c)w(z|EmCbhnd-KRi(E1dx^TZ9K0pV|A$ID#!gB+XtyGC2!9Ad#Dl_PNr2q*LY68t4819+? z44uS^4||o5pp(;MuahkpWfeW(Ka?7Ea-{7y2Cg;JZm*rnWy7~T8foPHQ{N8tM3^!B z#kHgTD95=F!UI%MqjsE9KD~ZvUOenL(`?uL+NWk8ln0PVDUU-yd4SfSVF6BuZZcSr z6v6I}hrGLS-5eIz{zh-*5;w~N?Id}sGLfmQUw@_cOhf|l1r20ww94xBo7};nv$}xw zi!d^%>&6Xe!vT3Rh9f`yeZIm>^%+*Ve#SfZC>d_SPx4CTa1h7`aFX-hTsp&jBeP(< zgI@9gYm`#14MGYMpvl;H=BUE1621v~vV!J+((z9P@d*;IzoFkhC|*GO$e~RIvqhwl z_IGd>IF?mVP{3XJ_A;lTNg!&M+KI6lSRDd2*c%lU?mw~Yjo&OJxQ+a!Mux1FRwjW4;u zl?C6_+fE2a>@QJ4w699h4A7^gP8%xv22vj&Z6S3%B_%kF9!vzN4A4Qs*4jqoRk!h= ztZe;e-_X^I-rj}dd8eU1kQ80LS_6nI>J;c^Yd+T*Y?kOi5O+E{K#x%9&`8Iw5(ili0y@0xc`7*{VT zs&F)Dl75%}?%U(td3gx5Q{zRRRDp6r_ucKa$wI=8F<=!>?jy98y)M?VAUE9SZc_fj zBaiPPhB6#QK9>U`u{svdQb%G;+dDu(%my|&@Nwv&`N{$TDT{NSQ_k6vIca@vwd~xC zYkpaBUAX(rQCA<})MaRr9nT}Y`^?g}TGplTOzAc{Sd_GpilYY(0$~C0aUGo1lNoTT zreG*EFjAsqk5(PI-OL{U5y(0?9!WbP|GOC8OD`KhAe>wVbI3jO-a^ve8QT9~Zs4xy!lSlE5{_v# zbZ6$N8k!NckUWbqQ{?n1m&N0pzU;_6%xPaC4j1!dN0(+kqf%w-vl^F2cW!nYZEi#MeviIqq?=4 zEdC5InIsbh6YIULNa#-jQ+7EgLXOD{hL)aDqCml`ON}k@unsu&2-LyGAz)uj(rb3{ zwI!cS*hG&2mW<{O{dM`y&*g85*cvzF+0|bgXjowLnLfxfU+Esb{j_=UHn{4wM8n)4 z!AU*M18N@|fK_}1wJqAII6lUh^u%tivYb#DK1XY84#L&LUl&&<;d@@^x|h3J)9U#e zM6pF#{Cmzn_=*;e>HV65Q6K@D=?L?$78Y%BQ<(ke)G_TJAETEpP!FH0P{=)Yy#sy3 z_=-`D|5OZ#RJf9GSdjUgj>J#7{b~(*HtTv|+SwCgI7-fMn7tO{rWY-_MVm9Z9+D8= z-j1%-FvSKN=W6ag;%9^VS>oXr>w#iG$4ROa$a{(WCEFH}Df^KERh1>G%~_C`)5AY? zhxcXb{tQ5b@Gzp8^H2HhyZxezd8)gtEaKiCSFuOH@|teaQFDphX}7GLSCT_RJ(aL_ zlO&xU7@Vh#r!N2~L>0rpw24;C#mL7_I`OPn9(EaL>GoFDI1f1u(T24M6SwGZq(bG!&;WK2v(cxY&dXTXbkuISGdvt*3Ohl0gE zn=0xjBHU7JmkBV8#QzW}6Sa!>F0L=|eTs`G`t69g1jMX=FR8-dy|z}6;l?@+aVlS9 z?t(*ZtD9}MI}e#}2{f`Aq54ULkV2w(*6`xJdS2b%K?1ZefWV4|%YZ#6T>G+rIBUg~ zpCjY`lg^RCz{}qC4p~CqKxY?S@8$c7>8VEp>AIEX&wn3KsWGXky?PbT^dTCJT@ab5 zYmaIQwC{;HG`S(?XLf&`H<+5Oyi@(f??qa-sQ3uts(%J{pp8L{VuYbKNU=pA`>8QO z53-P_!%4jA6WZHB9c7LZ>=?fvN6dEc9n%)>b}dV#4YQ6jSY53P7kz63^3ZKkjIsP2 zYKQn%jAnx+^;1Cq&qkGdwyUntDdFj8!yBhJ^|nQ4`OY}rm%@Zt>}jGvvk)M986F+E z6pP1Ys={{l8L#MY4#UNaQQ05ND}-8yKKkyM#(|vmArRpl>9^(U+lo77C%1yiSp8hC zHEV>B`}aqZ(#Pu?L)U ztyMCOjE#ZhgfcYlMGMkFzF@Jraw#TftA#fmwL_$jd)NG5O`ki(Bwqdv679K8z_ECM z4C8uulZpedUy zFA&S(>5CuGE__BbyE)Pr%x&XpFC60b^&2w^N3jH+0iWD#m7o%Oa6!B@3IG4t>cd{RJ{7^H2(J?SM;n=Do0)r);7h?@Y+~!IFL(#RrRD>}2Bh zVvL_SuXfZ`*PiXC^S8X6+}}KlMC9}23^)8J@1Mm~WquB5+?`BiB9d>PM2{=I&Mn#ug zPaD@7_bMnDjlYG@jOcR)mo9@K8)sx{GhTo-4&O?|TTb^wsvUfa>-_v#Hnzr7Rga4W zw+bKS-y*aqKxU~yRnoMg=jtp%ubYB>A_S9+Pi;`>q~B5jYm;{~$s6FUxA_qR+v$wM ztjyiMnSDUxF>V7{pCqw|`%ysLJ{0jClWFf&Bw8WLkxV3E1nLG}UY}8Qm+|&2>tjwM z(X4=$%cGTo)CWcvp8xQ%v08~>DPf3RK{tjs{|X%HWl#uu(-Y$3Eh$=fQ~?U+H|o>H zT|9u4QeD1Ggh#%@z_WJ}qauWVIa$j0R>Ep~c7Tn-I|_wP(qMPGU^Rpmv*ZY`H6z_; z{moDYv9$jJ9iPhTlrd~RS6Q1_(6zAAa)L8+xf{Xvpz*>azw^%Pf5u~gXv`K@=S{7w zaC2YzaqOQxC;T*8XjI^*=`KUs!>TxySWx7C9ZpG^fA#WBtu}*d8cn+IpYI#{#IpW2 zxDj8`flt@xJ|1J%E^*`EBU710!Eir--t;|FIu%e1MXoNhKALQYv-MJ7a2$LBHnRa*wT8)byTiaT$Z^Pm_Qh z9rQftJrrvs#FSC$e~xN_WYGm^#R}Zk{#Zs?JPbqt12!8Zw5lsBpG}vBXJ&a0VM+hJxcw?*=fulYY7T|d^3)F|w`@^4s zj-Q6qL#}{v(#;DF5O~fNT^OEDW22!3l1p3?5t)>TAe|;{tb}Ya7J);LEP-hF5v0=) zUoHbZpbAfZKn+jx6g2H8;s=L13G|18awuvKOF8@eWpuN@SU>7am&%y_ zZN0&S`(=1kA=6w;!Wb1Jf_GWLII3}ZDdp!w1=e?l#utm(*{rOBx2ayLg9j;gOHam} z_W6f4_|s0jJpC@t^IoWxD&0A*hFH&6K7Wy_+KU%bOB?LopP^H%4V@%LZ+j0xDn&Kv zL_wM!(?sS$x7KVH|A5H$dS}nfB-zN&wg*)W!e~aSTbp-J<)tp=YApz&I@Be5U5zUB zV*UFAVKY_eyf9Xro&o6wLsyH{xenC&^}!*sop*kGqYbi|M^AEYUFA z{Pr_RC|N=_T4#um#@T9xl_guAICIDlPae%&Q+;>5#bVPPP19CapLHvZ=(N zDKHY<7l5as7#gV(Am%P(CuYK5Kp0bIf1ocfDkTWEELb^& zT$mD!@Mu6M-{d=thHX9aC)B7I^N$RWY=D4 zot|yh)zxkC+U^ZOczGy3YZQbT&;M|Ep|8&dDCMa%>3j}fpS)?1^5yfaJl#vCetqX8 zoo|(&Q(et-nKdSakaEcR>lhR5@a@RYY%L;Oq|zXH2WN#{iztRkG0g>nmS1LlH#a$s zSH~vA{Fd1%ciM5EK7UrY8_j{o@uMYvq81hwF(0vfpB&sArJBbBMX*>xz3$Kb{m83x zc6NQDLusFn!yNftwqNGSVlpa!p<}!KLtncfoBg#xhlG?AL#hXRiw?}Pef3N9We3%W zk9P<~OBJ$?j*fIYNl(7d=;HZkWUp|w=%OzluDu)>7$_Gs_gY!U=+Q1!(<-Uy4O?rD znV;8RWcCL|GUlFMPlm@4pkK1X>+u}B1Q|B0Zzw#mZ1=Z0g->(3+NM~(Ksyq)pP-0fG)e+CL&{SNn&fBW`VD$L#GD7ifU zo7|s^9X1o~J|JL=#~@)G!Ht&zcHrB5B>VMYr8m`uRGwuMjr%`bS^e9V(w=ee);r18 ztTbcs#vEcEZsm^s{J<%GzWW^uZF|tox9zY^uuE0=w$gjyxGF`+gA*53U+-|mEdBH7 zXie7rkah;19+S=@KUCz2K*9?ags+flPF59_FyVooN)psEz!x-1+3m)IareJ)$m-*cj>jj*kWBE+ITM1BPDw+$a zcqhSsqtydkw67&%!J*;eovy24Y=RB>SnM zQb0-rg*b2GXWPh*OFlkX%vB3@^b_^2^6Lmm$63n-1HWkf_js)Y2KjGpfL6C=t>anP zDeC^C1nWg5Xo~TRv71@&o-x|*%~l=D9iBzj@HEkPMUjWgp!;cSoO;IS+-;*(3+>WE*WwyK&^u@R~ESN456PO!3&_Fw;)@h@6W?B4p zwoa?oW5x8)+O}Be5&qA5E6dee@&iUKNKG^14rRI@g)kn@-79Nl2Zub2w*Y2(JZn|( zb?J-7-aPY?&!Koy441GcLt=>-V}sa_h6EkW8McHwFa?0;B~$u!EfKejf@P> z%LA4?pkW|QSR1H*5jR#ny+K_nZScFl`*w-pSLdrNFeuovhja)`n6bj)uGHldyUWRj zrRJ;pO^=oHbdQsDB)=@1+=pnsCy(w`7uyLqCY z7TGn$G^g|9HLTT2hzOp{=%(kOqoDzv{#+S9uOE3`_YqL`XcriM%Vf@bRC?AH>aK%j*TRpyzARladLruJW?c;@Hdk!=`hr zal>Q5kK*D*a)Sx^;_v(#4EmMf*XIvmyA~W&j;M&(r4r!6Fm86#I2hS)hN@fgaF=zv zePtOHsP&7vgR<$dn?cbL+T~cVM-*r19?^pzrDq_qKr0>OhHe#uK^L}5Wf37xj~R-s z;-XL)1c3_)EDUfNkoelcbO}D%>0g>pj!1z`XIC#7mE~Qf`hAscp$A8OLb?1C1@NO_ z@<;IvQY~Pkx?s?n;MqA)O7lAWyXmpTTF}6SETb)SN@(^WV7lC%OeQtg@)GkSmCD;R zcNwal2;NJ5^j8FH_|zm$6KJcngUQckZV?zm%&vzI8a%rpwt;FmG)9ri-=6?n_$oU< zJ`sNzoA>+Pfo36>pOYP@Bbq_ntnbH;v~{<;Pzq=QSVP@jhB78p`w%esa_asrxu|k( z@IixT@1SZ)dxSufAO?Z5fD4P{5aQUGTc~Yc%q^8^n%%808n1$FS9MDfEgD3oN z8*dr=_5W_X|DSF=3w4NgW(Qpg&NpU#zt>M{6@7P@)UCu8UOjwU;pVJ z4>tZI%2XV%MG>+8`PZnlKa5Y8vjb$q|KsyYu#2lMHzWRaWB9+KpMrN~E0%dZ^gln( zpa<`KhpgGZ-5C5tfHMy8iV~DKRR8mHC@XkrSVaVA|83ade%ax`sjf2)^Pu_9&&`3k zvpO0f{`X;Hi&5!<5suNT_v8KN=VFS$UW9)f{KtI!eV|)3hoUbhuOH}yG(3TTKl0Kl KQpFMmf&T{wF@j$J literal 0 HcmV?d00001 diff --git a/_uis/habpanel/doc/habpanel-concepts.png b/_uis/habpanel/doc/habpanel-concepts.png new file mode 100644 index 0000000000000000000000000000000000000000..fc01c1b78744c0ec60f94867cf1fc7e71d2ff924 GIT binary patch literal 74281 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 Pz|U)o53XV}<<$QHeolAt literal 0 HcmV?d00001 diff --git a/_uis/habpanel/doc/index.md b/_uis/habpanel/doc/index.md new file mode 100644 index 000000000..f492bd078 --- /dev/null +++ b/_uis/habpanel/doc/index.md @@ -0,0 +1,270 @@ +# Designing dashboard interfaces with HABPanel + +The [HABPanel]({{base}}/addons/ui/habpanel/readme.html) user interface is installed by default when choosing any initial setup package, and allows the creation of user-friendly dashboards, particularly suited for (e.g. wall-mounted) tablets. These dashboards can be designed interactively in the embedded designer, rather than using configuration files. + +Despite being similar, HABPanel's dashboards and [sitemaps]({{base}}/configuration/sitemaps.html) are separate concepts, and can be designed independently as they aren't related to each other; however, they rely and act on [items]({{base}}/concepts/items.html) which must therefore be [defined]({{base}}/configuration/items.html) first. The [demo setup package]({{base}}/configuration/packages.html#demo-package-sample-setup), available for installation when starting openHAB for the first time, defines a series of sample items and configures HABPanel with a comprehensive set of dashboards to showcase a possible end result. It's the same as the one installed on the [openHAB Demo Server](https://demo.openhab.org/){:target="_blank"}, and it may be modified without risk of breaking anything: it's the best playground to discover HABPanel's features. + +## Concepts + +HABPanel has its own terminology of entities presented below: + +![HABPanel concepts](habpanel-concepts.png) + +- The **Panel Registry** is the central storage used by HABPanel on a given openHAB instance, it contains several **Panel Configurations**; +- A **Panel Configuration** is a container holding a **Panel** along with its **Settings** and the definition of **Custom Widgets**. Each device HABPanel runs on (desktop browser, tablet...) has an active panel configuration and displays the panel associated with it; +- A **Panel** is a set of **Dashboards** (or pages) which can be presented to end users, who can also easily switch between them using the menu. +- A **Dashboard** is comprised of discrete **Widgets** positioned on the dashboard's surface at design time. There are several types of built-in *standard widgets*, configured separately, and the administrator can also develop (or import) *custom widgets*. + +## About data persistence + +By default, when running HABPanel on a new browser or device, a tutorial will be displayed allowing the user to start from scratch, or switch to an previously defined panel configuration. **Until a panel configuration is created (or chosen), HABPanel will run in "local storage" mode for this device: the settings will be retained in the browser's local storage only and nothing will be persisted on the server.** By contrast, when an active panel configuration is set, each change performed on the device will update the panel configuration on the server. This allows the sharing of panel configuration among devices, because other browsers and devices using this panel configuration will pick up the changes with a page refresh - this is useful for instance to design a panel comfortably on a computer, then use it on a tablet. + +To switch from the local storage to a server-hosted panel configuration, go to the Settings page from the main menu or the side drawer (see below). A list of panel configurations will be presented in the _Current storage configuration_ section; if only the _"Local storage"_ option is available, click on the **Save the current configuration to a new panel configuration** link, give it a name to identify it (avoid spaces or special characters), and it should be added to the list. The radio button is also automatically checked, meaning it is now the active panel configuration. + +Even when there is an active panel configuration, HABPanel uses the browser's storage to sync a locally-managed copy. With the **Edit the local panel configuration (experts only)** link under the _"Local storage"_ storage configuration option in the settings screen, the raw structure of the panel configuration can be inspected, modified, and exported or imported from/to a .json file. It is also an alternative way to backup, restore and share the configuration. + +HABPanel uses service configuration variables to store its data on the openHAB server. They can be accessed using Paper UI (_Configuration > Services > UI > HABPanel > Configure_) or in the openHAB Karaf console: + +``` +openhab> config:edit org.openhab.habpanel +openhab> config:property-get +``` +The following properties are defined: + +- `panelsRegistry`: contains the entire registry serialized in JSON, it is maintained by the application and shouldn't be modified directly (editing it by hand, while possible, is strongly discouraged); +- `lockEditing`: when enabled, all HABPanel instances will hide their editing features (a page refresh is necessary). When panels are complete and stable, it is advisable to turn on this setting so they cannot be easily modified by end users; +- `initialPanelConfig`: if this option is unset and no prior local configuration is detected, the tutorial will be displayed until some dashboards are added or a panel configuration is selected. This setting allows to bypass the tutorial and switch directly to the existing panel configuration with the given name. + +## Major interface elements and features + +### The main menu + +The main menu is HABPanel's home page. It contains tiles linking to the panel's dashboards, and an icon to switch between the run mode and the edit mode (if available). + +![Main menu - run mode](main-menu-run.png) + +Use the gears icon in the top-right corner to switch between the two modes. + +![Main menu - edit mode](main-menu-edit.png) + +When in edit mode, several features are available: +* Add a new empty dashboard with the **Add new dashboard** link; +* Go to the settings screen (for instance, to switch from local storage to a server-managed panel configuration) by clicking on the **Advanced settings** link; +* Adjust the number of columns for the grid of main menu tiles with the slider, from 1 (the default) to 6; +* Drag the arrow icons in the top-left corner of each tile to move it; +* Resize tiles with the chevron (triangle) in the bottom-right corner of each tile; +* Configure the tiles and the dashboards themselves with the gears icons in the top-right corner of each tile; +* Enter the dashboard designer by clicking inside a tile. + +The configuration dialog when clicking on a tile's gear icon contains the following settings: + +| Setting | Description +|---------|-------------| +| Name | The name of the dashboard, also displayed on the tile +| Background URL | The URL of a background image *for the main menu tile* +| Backdrop Icon | Iconset and icon displayed on the tile as a Backdrop +| Center backdrop horizontally | When unchecked, the backdrop is aligned to the right of the tile; when checked, it is centered +| Icon | Icon associated with the dashboard, currently only used in the side drawer +| Size (icon) | _(currently unused)_ +| Title Text Color | Color for the name of the dashboard on the tile +| Advanced tab | Contains settings currently unstable or buggy, for advanced users only + +It also contains a **Delete** button which will delete the entire dashboard and its contents - this happens immediately and cannot be undone! + +### The side drawer + +![Side drawer](side-drawer.png) + +The side drawer can be accessed from any screen by a swipe or drag to the right (on most elements where there isn't a conflict with this gesture), or with the "hamburger icon" ☰ in the top-left corner. + +It is comprised of three parts: + +1. A **header** - clicking on it returns to the main menu. Note: if defined, the title of the panel is displayed instead of the default "HABPanel" label, it is configured in the settings (see below); +2. A **list of dashboards** for quick switching bettween dashboards without going back to the main menu - they are presented in the order of the menu (sorted by row, then by column); +3. A **footer** displaying the current date & time and featuring a link to the settings screen (if available). + +### The dashboard designer + +![Dashboard designer](dashboard-designer.png) + +The dashboard designer is where widgets can be added, positioned, resized and configured. Placeholders are displayed where actual widgets would be on the running dashboard. + +To add a widget, use the **Add widget** button and choose among the list of standard widgets, or eventual custom widgets in the panel configuration. +See below for a description of the standard widgets. + +![Add widget menu](add-widget.png) + +Use the header of a widget placeholder (with the four-arrow icon and the widget type) to move the widget. Moving a widget over other widgets do not push them away to make room (contrary to the main menu tiles), so ensure there is sufficient room for your widget before moving it. + +![Widget placeholder features](dashboard-designer-placeholder-menu.png) + +When hovering over a placeholder (or tapping inside it if on a touch interface), a chevron appears in the bottom-right corner allowing to resize it. + +Use the ellipsis icon **⁝** to bring up the widget's contextual menu, offering the following options: + +- **Edit...:** Displays the configuration dialog for the widget. The options available in the dialog depend on the type of the widget and are detailed in the Widgets section; +- **Copy/move to...**: Displays a dialog allowing to clone the widget with its configuration, to the current dashboard or another, or move it to another dashboard (the target widget will retain its size of the source widget but it will be placed where there is available room, use the target dashboard's designer to find it and reposition it); +- **Delete**: Deletes the widget. + +Modifications to the dashboard are not saved automatically, use the **Save** button in the header to commit the changes to the panel configuration (or local storage). The **Run** button also saves, then runs the dashboard. + +### Running dashboards + +![A running dashboard](running-dashboard.png) + +When a dashboard is running, widgets can be interacted with, and server-sent events are received when items' states are updated, so widgets update automatically in HABPanel. + +The icons in the top-right corner perform the following: +- the **speech balloon** activates the speech recognition feature and send the results as text to openHAB's default human language interpreter. This implies [some configuration on the server]({{base}}/configuration/multimedia.html#human-language-interpreter), and this icon might not be displayed if the browser doesn't support voice recognition ([currently only in Chrome on desktops and Android](http://caniuse.com/#feat=speech-recognition){:target="_blank"}). It can also be configured in the panel configuration to appear on the bottom of the screen; +- the **refresh** button forces HABPanel to retrieve the current state of all items; +- the **fullscreen** button tells the browser to go fullscreen, if supported. + +## Additional features and settings + +Apart from the storage configuration discussed above, the settings screen contains several settings kept as part of the panel configuration (meaning they are set separately): + + +| Setting | Description +|---------|-------------| +| Panel name | An user-friendly name for the panel. It will be displayed in the header of the side drawer. +| Theme | HABPanel comes with a number of built-in themes, with this setting a different theme may applied to the panel. Themes are not user-modifiable. +| Background image | Sets the specified URL as background image for the whole panel. *Tip: the background image works best with the 'translucent' theme!* +| No clock on the home menu | _(Deprecated)_ +| Prevent scrolling (when not editing) | When enabled, it is impossible to scroll the dashboard on a tablet (and it prevents the "elastic" bouncing effect on iOS/Safari) +| Manage > | Goes to the list of custom widget definitions for the active panel configuration +| Voice | Selects a voice from the detected list for text-to-speech* +| Speak the new value of the following item when it changes | When the selected String item change to a new text, HABPanel will use the browser's text-to-speech engine and the selected voice to read it aloud* +| Display a floating speech button at the bottom of the screen | Use an alternative style for the Speak (voice input) button in dashboards +| When this item changes to a dashboard's name, switch to it | This allows controlling the currently displayed dashboard by an openHAB item (useful with rules and as a side-effect to commands) + +*Note: the text-to-speech functionality featured in HABPanel is unrelated to the [TTS services]({{base}}/configuration/multimedia.html#text-to-speech) defined on the openHAB server, and they are not compatible (this is why a String item is required and the `say()` function cannot be used). However, HABPanel will play audio streamed through the ['webaudio' sink]({{base}}/configuration/multimedia.html#audio), including spoken text. + + +## Widgets + +### Standard widgets + +The following built-in widgets are available: + +#### Dummy (dummy) + +![Dummy widget](widget-dummy.png) + +The so-called dummy widget (whose name is explained by historical reasons - it evolved from the first developed widget) displays the current state of an item without any interactivity, along with a label and an optional icon. + +#### Switch (switch) + +![Switch widget](widget-switch.png) + +The switch widget is a simple widget to control a Switch item as defined in openHAB - it reports its state and is able to toggle it between ON and OFF. + +#### Label (label) + +![Label widget](widget-label.png) + +The label widget is straightforward: it simply displays a fixed text and has a few appeareance options (color, font). It can for example be used as a header for a group of widgets below it. + +#### Button (button) + +![Button widget](widget-button.png) + +The button widget can be clicked (or tapped) and will perform an action, like sending commands to an item or navigating to another dashboard. It can also adjust its colors depending on the state of the underlying item. + +Multiple buttons are often used together to present different options for an item. + +#### Slider (slider) + +![Slider widget](widget-slider.png) + +The slider widget can reflect the state of, and update, numerical items within a range of values. Several options are available to alter its appearance and behavior. + +#### Knob (knob) + +![Knob widget](widget-knob.png) + +The knob widget is similar in essence to the slider, but in a rotary fashion. It also offers extensive configurability over its appearance and behavior. + +#### Color picker (colorpicker) + +![Color picker widget](widget-colorpicker.png) + +The color picker widget offers several ways of displaying and updating the state of an openHAB Color item (or group). + +#### Image (image) + +![Image widget](widget-image.png) + +The image widget can display an image, directly or via an openHAB String item, and can refresh it at regular intervals. + +#### Frame (frame) + +![Frame widget](widget-frame.png) + +The frame widget displays an external web page in a HTML `