added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.globalcache</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,13 @@
|
||||
This content is produced and maintained by the openHAB project.
|
||||
|
||||
* Project home: https://www.openhab.org
|
||||
|
||||
== Declared Project Licenses
|
||||
|
||||
This program and the accompanying materials are made available under the terms
|
||||
of the Eclipse Public License 2.0 which is available at
|
||||
https://www.eclipse.org/legal/epl-2.0/.
|
||||
|
||||
== Source Code
|
||||
|
||||
https://github.com/openhab/openhab-addons
|
||||
@@ -0,0 +1,415 @@
|
||||
# GlobalCache Binding
|
||||
|
||||
The [GlobalCache](https://www.globalcache.com) binding enables communication
|
||||
between openHAB and GlobalCache [GC-100](https://www.globalcache.com/products/gc-100/) and [iTach](https://www.globalcache.com/products/itach/) family of devices.
|
||||
GlobalCache devices enable the control and automation of infrared, serial, and contact closure devices over a wired or wireless IP network.
|
||||
|
||||
## Overview
|
||||
|
||||
The GlobalCache binding discovers GC-100 and iTach devices on the network, and creates an inbox entry for each discovered device.
|
||||
Once added as a thing, the user can complete the configuration of the device, such as adding the name of the MAP file that contains IR and/or serial codes.
|
||||
|
||||
## Devices Supported
|
||||
|
||||
Devices are discovered dynamically.
|
||||
There is a single thing created for each physical GC-100 or iTach device discovered on the network.
|
||||
Each thing has channels that correspond to the physical connectors on the device.
|
||||
|
||||
Currently supported devices include:
|
||||
|
||||
| Device | Thing ID |
|
||||
|-----------------------------------|-----------|
|
||||
| iTach WF2IR and IP2IR | itachIR |
|
||||
| iTach WF2SL and IP2SL | itachSL |
|
||||
| iTach WF2CC and IP2CC | itachCC |
|
||||
| iTach Flex Ethernet and Flex WiFi | itachFlex |
|
||||
| GC-100-6 | gc100_06 |
|
||||
| GC-100-12 | gc100_12 |
|
||||
| ZMOTE WiFi Universal Remote | zmote |
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
The binding uses the MAP transformation service to convert commands into IR and/or serial codes.
|
||||
If not already installed, the MAP transformation service is installed automatically when the binding is installed.
|
||||
|
||||
In the event that the device's IP address is changed, the thing configuration must be updated manually, as the device cannot auto-discover the change.
|
||||
|
||||
### iTach IR and ZMOTE
|
||||
|
||||
The iTach IR (Infrared) and ZMOTE devices have the following configuration parameters.
|
||||
|
||||
| Parameter | Parameter ID | Required/Optional | Description |
|
||||
|--------------|--------------|-------------------|-------------|
|
||||
| IP Address | ipAddress | Required | The device's IP address. |
|
||||
| MAP Filename | mapFilename | Required | The MAP file that contains mappings of commands to the IR codes. |
|
||||
|
||||
### iTach SL
|
||||
|
||||
The iTach SL (Serial) device has the following configuration parameters.
|
||||
Note that you must use the iTach SL's web application to set the serial port
|
||||
parameters for **baud rate**, **flow control**, and **parity** to match the configuration of the end device to which the iTach is connected.
|
||||
|
||||
| Parameter | Parameter ID | Required/Optional | Description |
|
||||
|----------------|---------------|-------------------|-------------|
|
||||
| IP Address | ipAddress | Required | The device's IP address. |
|
||||
| MAP Filename | mapFilename | Required | The MAP file that contains mappings of commands to the serial codes. |
|
||||
| Enable Two Way | enableTwoWay1 | Optional | Enable two-way communication with the device. By default, the binding only sends commands to the device. |
|
||||
| EOM Delimiter | eomDelimiter1 | Optional | The End-of-Message delimiter used to identify the end of a message that the binding received from the device. |
|
||||
|
||||
### iTach CC
|
||||
|
||||
The iTach CC (Contact Closure) device has the following configuration parameters.
|
||||
|
||||
| Parameter | Parameter ID | Required/Optional | Description |
|
||||
|--------------|--------------|-------------------|-------------|
|
||||
| IP Address | ipAddress | Required | The device's IP address. |
|
||||
|
||||
### iTach Flex
|
||||
|
||||
The iTach Flex device has the following configuration parameters.
|
||||
Note that you must set the Active Cable configuration parameter to match how the Flex is configured.
|
||||
Available options are Infrared, Serial, and Relay/Sensor.
|
||||
The default is Infrared.
|
||||
|
||||
When the iTach Fles is configured for serial operation, you must use the iTach Flex's web application to set the serial port
|
||||
parameters for **baud rate**, **flow control**, and **parity** to match the configuration of the end device to which the iTach Flex is connected.
|
||||
|
||||
| Parameter | Parameter ID | Required/Optional | Description |
|
||||
|----------------|---------------|-------------------|-------------|
|
||||
| IP Address | ipAddress | Required | The device's IP address. |
|
||||
| MAP Filename | mapFilename | Required | The MAP file that contains mappings of commands to the IR and/or serial codes. |
|
||||
| Active Cable | activeCable | Required | Available options are Infrared (FLEX_INFRARED), Serial (FLEX_SERIAL) or Relay/Sensor (FLEX_RELAY). |
|
||||
| Enable Two Way | enableTwoWay1 | Optional | Enable two-way communication with the device. By default, the binding only sends commands to the device. |
|
||||
| EOM Delimiter | eomDelimiter1 | Optional | The End-of-Message delimiter used to identify the end of a message that the binding received from the device. |
|
||||
|
||||
### GC-100-6
|
||||
|
||||
The GC-100-6 device has the following configuration parameters.
|
||||
Note that you must use the GC-100-6's web application to set the serial port
|
||||
parameters for **baud rate**, **flow control**, and **parity** to match the configuration of the end device to which the GC-100-6 is connected.
|
||||
|
||||
| Parameter | Parameter ID | Required/Optional | Description |
|
||||
|----------------|---------------|-------------------|-------------|
|
||||
| IP Address | ipAddress | Required | The device's IP address. |
|
||||
| MAP Filename | mapFilename | Required | The MAP file that contains mappings of commands to the IR and serial codes. |
|
||||
| Enable Two Way | enableTwoWay1 | Optional | Enable two-way communication with the device. By default, the binding only sends commands to the device. |
|
||||
| EOM Delimiter | eomDelimiter1 | Optional | The End-of-Message delimiter used to identify the end of a message that the binding received from the device. |
|
||||
|
||||
### GC-100-12
|
||||
|
||||
The GC-100-12 device has the following configuration parameters.
|
||||
Note that you must use the GC-100-12's web application to set the serial port
|
||||
parameters for **baud rate**, **flow control**, and **parity** to match the configuration of the end device to which the GC-100-12 is connected.
|
||||
|
||||
| Parameter | Parameter ID | Required/Optional | Description |
|
||||
|------------------|---------------|-------------------|-------------|
|
||||
| IP Address | ipAddress | Required | The device's IP address. |
|
||||
| MAP Filename | mapFilename | Required | The MAP file that contains mappings of commands to the IR and/or serial codes. |
|
||||
| Enable Two Way 1 | enableTwoWay1 | Optional | Enable two-way communication between the binding and the device on serial port #1. By default, the binding only sends commands to the device. |
|
||||
| EOM Delimiter 1 | eomDelimiter1 | Optional | The End-of-Message delimiter used to identify the end of a message that the binding received from the device on serial port #1. |
|
||||
| Enable Two Way 2 | enableTwoWay2 | Optional | Enable two-way communication between the binding and the device on serial port #2. By default, the binding only sends commands to the device. |
|
||||
| EOM Delimiter 2 | eomDelimiter2 | Optional | The End-of-Message delimiter used to identify the end of a message that the binding received from the device on serial port #2. |
|
||||
|
||||
### Manual Thing Creation
|
||||
|
||||
Devices can be created in the *Paper UI* or *HABmin*, or by placing a *.things* file in the *conf/things* directory.
|
||||
See example below.
|
||||
|
||||
### Binding Dependencies
|
||||
|
||||
The GlobalCache binding uses the **transform** binding to map commands to IR and serial codes. See example below.
|
||||
|
||||
## Device Discovery
|
||||
|
||||
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:
|
||||
|
||||
```text
|
||||
discovery.globalcache:background=false
|
||||
```
|
||||
|
||||
Note that automatic device discovery **will not work** with GC-100's running firmware earlier than v3.0 as those versions do not emit announcement beacons on the multicast address.
|
||||
GC-100's running firmware earlier than v3.0 must be configured manually, either through *Paper UI* or using a *.things* file.
|
||||
See below.
|
||||
|
||||
## Channels and Channel Types
|
||||
|
||||
There are four *channel types* used across the GC-100 and iTach family of devices.
|
||||
|
||||
- Contact Closure (CC)
|
||||
- Infrared (IR)
|
||||
- Serial (SL)
|
||||
- Serial Direct (SL)
|
||||
|
||||
*Channels* follow a naming convention that relates to the physical configuration of the Global Cache device -- specifically the **module** and **connector** numbers.
|
||||
For example, the channel name **m2c3** refers to connector 3 on module 2.
|
||||
|
||||
For iTach Flex devices, since they can be configured to support infrared, serial, or contact closure, channels are prefixed with ir-, sl-, and cc-, respectively.
|
||||
For example, the IR channel on connector 3 on module 1 is named ir-m1c2.
|
||||
|
||||
## Infrared (IR) Channel
|
||||
|
||||
The *Infrared channel* sends IR codes out the IR connector on the device.
|
||||
For example, the following item links to the module 1 / connector 2 channel on an iTach IR device.
|
||||
|
||||
```java
|
||||
String SamsungTV "TV" (gTheater) { channel="globalcache:itachIR:000C1E0384A5:ir-m1#c2" }
|
||||
```
|
||||
|
||||
The item definition for an iTach Flex Ethernet device would look like this.
|
||||
|
||||
```java
|
||||
String SamsungTV "TV" (gTheater) { channel="globalcache:itachFlexEth:000C1E077BE1:ir-m1#c2" }
|
||||
```
|
||||
|
||||
### How to Specify IR Codes
|
||||
|
||||
IR codes are contained in a MAP file contained within the conf/transform directory.
|
||||
See example below.
|
||||
|
||||
### Supported IR Code Formats
|
||||
|
||||
Two different formatting methods are supported: Global Cache and hex code.
|
||||
Here's an example of the Global Cache format:
|
||||
|
||||
```text
|
||||
38000,1,1,340,170,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,63,21,63,21,63,21,63,21,63,21,21,21,21,21,1691,340,85,21,3753
|
||||
```
|
||||
|
||||
Here's an example of the hex code format:
|
||||
|
||||
```text
|
||||
0000 006E 0000 0024 0154 00AA 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 003F 0015 0015 0015 0015 0015 0015 0015 0015 0015 003F 0015 003F 0015 003F 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 003F 0015 003F 0015 003F 0015 003F 0015 003F 0015 003F 0015 003F 0015 003F 0015 0015 0015 0015 0015 069B 0154 0055 0015 0EA9
|
||||
```
|
||||
|
||||
The [Global Cache iConvert utility](https://www.globalcache.com/files/docs/gc_iconvert_relnotes.txt) can be used to convert between the two formats, if desired.
|
||||
The iConvert utility is available on the Windows platform only.
|
||||
Global Cache also maintains an online [IR Control Tower database](https://irdb.globalcache.com/) of IR codes.
|
||||
There are numerous other sources of IR codes, such as iRule and RemoteCentral.
|
||||
|
||||
#### Unsupported Features
|
||||
|
||||
Currently, only the *IR Out* and *IR Blaster* connector configurations are supported.
|
||||
Other settings, such as *Sensor In*, *Sensor Notify*, and *LED Lighting*, may be supported in the future.
|
||||
|
||||
## Contact Closure (CC) Channel
|
||||
|
||||
A *Contact Closure channel* activates the contact closure (relay) on the iTach or GC-100 device.
|
||||
For example, the following item links to the module 1, connector 1 channel on an iTach CC device.
|
||||
|
||||
```
|
||||
Switch MyRelay "My Relay [%s]" (gRelays) { channel="globalcache:itachCC:000C1E039BCF:cc-m1#c1" }
|
||||
```
|
||||
|
||||
The item definition for an iTach Flex WiFi device would look like this.
|
||||
|
||||
```
|
||||
String MyRelay "My Relay [%s]" (gRelays) { channel="globalcache:itachFlex:000C01AF4990:cc-m1#c1" }
|
||||
```
|
||||
|
||||
## Serial (SL) Channel
|
||||
|
||||
An *SL channel* sends serial command strings out the serial connector on the device.
|
||||
For example, the following item links to the module 1 connector 1 channel on a GC-100-6 device.
|
||||
|
||||
```
|
||||
String RS232ME "My RS232-controlled Device" { channel="globalcache:gc100_6:000C459A120A:sl-m1#c1" }
|
||||
```
|
||||
|
||||
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 (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.
|
||||
For example, the following item links to the module 1 connector 1 channel on an iTach Flex device.
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
```text
|
||||
%0D%0A Carriage return / Line feed
|
||||
%0D Carriage return
|
||||
%F7 Russound RNET message terminator
|
||||
```
|
||||
|
||||
**Example**
|
||||
|
||||
### MAP File
|
||||
|
||||
```text
|
||||
# Harmon Kardon AVR-245 Home Theater Receiver
|
||||
HKAVR245_POWER_ON = 38000,1,1,340,170,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,63,21,63,21,63,21,63,21,63,21,21,21,21,21,1691,340,85,21,3753
|
||||
HKAVR245_POWER_OFF = 38000,1,1,340,170,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,63,21,63,21,63,21,63,21,63,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,21,21,1691,340,85,21,3753
|
||||
HKAVR245_VOLUME_UP = 38000,1,1,340,170,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,63,21,63,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,1691,340,85,21,3753
|
||||
HKAVR245_VOLUME_DOWN = 38000,1,1,340,170,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,63,21,63,21,63,21,63,21,63,21,21,21,63,21,63,21,21,21,21,21,1691,340,85,21,3753
|
||||
HKAVR245_MUTE = 38000,1,1,340,170,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,63,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,21,21,63,21,63,21,63,21,63,21,63,21,21,21,21,21,1691,340,85,21,3753
|
||||
HKAVR245_HDMI1 = 38000,1,69,345,174,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,21,21,64,21,21,21,21,21,64,21,64,21,64,21,64,21,64,21,21,21,64,21,64,21,21,21,21,21,21,21,21,21,1725,345,86,21,3708
|
||||
HKAVR245_HDMI2 = 38000,1,69,345,174,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,64,21,64,21,21,21,21,21,64,21,64,21,64,21,64,21,21,21,21,21,64,21,64,21,21,21,21,21,21,21,21,21,1725,345,86,21,3708
|
||||
|
||||
# Samsung HL-S Series DLP TV
|
||||
SAMSUNGHLS_POWER_ON = 38000,1,1,170,169,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,21,21,64,21,64,21,21,21,21,21,64,21,21,21,64,21,64,21,21,21,21,21,64,21,64,21,21,21,1673
|
||||
SAMSUNGHLS_POWER_OFF = 38000,1,1,170,169,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,21,21,21,21,64,21,64,21,64,21,64,21,21,21,21,21,64,21,64,21,21,21,1673
|
||||
SAMSUNGHLS_HDMI1 = 38000,1,1,170,169,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,64,21,21,21,21,21,64,21,21,21,64,21,64,21,64,21,21,21,1673
|
||||
SAMSUNGHLS_HDMI2 = 38000,1,1,170,169,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,21,21,64,21,21,21,64,21,64,21,64,21,21,21,64,21,64,21,21,21,64,21,21,21,21,21,21,21,1673
|
||||
|
||||
|
||||
# Xfinity Pace XG2V2-P Cable Box
|
||||
XFINITYXG2_GUIDE = 38000,1,37,8,34,8,65,8,29,8,106,8,50,8,50,8,44,8,101,8,525,8,34,8,60,8,29,8,29,8,39,8,65,8,29,8,29,8,3058,8,34,8,65,8,29,8,106,8,50,8,50,8,44,8,101,8,525,8,34,8,101,8,70,8,29,8,39,8,65,8,29,8,29,8,3058
|
||||
XFINITYXG2_EXIT = 38000,1,37,8,34,8,65,8,29,8,106,8,50,8,50,8,44,8,101,8,525,8,34,8,44,8,29,8,29,8,39,8,81,8,29,8,29,8,3058,8,34,8,65,8,29,8,106,8,50,8,50,8,44,8,101,8,525,8,34,8,86,8,70,8,29,8,39,8,81,8,29,8,29,8,3058
|
||||
|
||||
# Serial commands
|
||||
# Represents the command string "POWER ON" followed by carriage return line feed
|
||||
RS232ME_POWER_ON = POWER%20ON%0D%0A
|
||||
# Represents the command string "POWER OFF" followed by carriage return line feed
|
||||
RS232ME_POWER_OFF = POWER%20OFF%0D%0A
|
||||
# Represents the command string "VOLUME UP" followed by carriage return line feed
|
||||
RS232ME_VOLUME_UP = VOLUME%20UP%0D%0A
|
||||
# Represents the command string "VOLUME DOWN" followed by carriage return line feed
|
||||
RS232ME_VOLUME_DOWN = VOLUME%20DOWN%0D%0A
|
||||
```
|
||||
|
||||
### Items File
|
||||
|
||||
```
|
||||
Switch ContactClosure1 "Relay on Connector 1" { channel="globalcache:itachCC:000C1E017BCF:cc-m1#c1" }
|
||||
Switch ContactClosure2 "Relay on Connector 2" { channel="globalcache:itachCC:000C1E017BCF:cc-m1#c2" }
|
||||
Switch ContactClosure3 "Relay on Connector 3" { channel="globalcache:itachCC:000C1E017BCF:cc-m1#c3" }
|
||||
|
||||
Switch GarageDoor "Open/Close Garage Door"
|
||||
Switch GarageLight "Garage Door Light"
|
||||
|
||||
String XFINITYFR "Xfinity Box in Family Room" { channel="globalcache:itachIR:000C1E038B75:ir-m1#c1" }
|
||||
String HKAVR245 "Harmon Kardon AVR-245 Receiver" { channel="globalcache:itachIR:000C1E038B75:ir-m1#c2" }
|
||||
String SAMSUNGHLS "Samsung HL-S DLP TV" { channel="globalcache:itachIR:000C1E038B75:ir-m1#c3" }
|
||||
|
||||
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
|
||||
|
||||
This is an example of how to use contact closure, infrared, and serial devices in a sitemap.
|
||||
|
||||
```
|
||||
Frame label="Contact Closure" {
|
||||
Switch item=ContactClosure1 label="Open/Close Garage Door"
|
||||
Switch item=ContactClosure2 label="Light on Garage Door Opener"
|
||||
Switch item=ContactClosure3 label="Unused"
|
||||
}
|
||||
|
||||
Frame label="Harmon Kardon Receiver" {
|
||||
Switch item=HKAVR245 label="Power" mappings=[HKAVR245_POWER_ON="On", HKAVR245_POWER_OFF="Off"]
|
||||
Switch item=HKAVR245 label="Volume" mappings=[HKAVR245_MUTE="Mute", HKAVR245_VOLUME_UP="Up", HKAVR245_VOLUME_DOWN="Down"]
|
||||
Switch item=HKAVR245 label="Select Input" mappings=[HKAVR245_HDMI1="HDMI 1", HKAVR245_HDMI2="HDMI 2"]
|
||||
}
|
||||
|
||||
Frame label="Samsung TV" {
|
||||
Switch item=SAMSUNGHLS label="Power" mappings=[SAMSUNGHLS_POWER_ON="On",SAMSUNGHLS_POWER_OFF="Off"]
|
||||
}
|
||||
|
||||
Frame label="Xfinity One" {
|
||||
Switch item=XFINITYFR label="Guide" mappings=[XFINITYXG2_GUIDE="Guide",XFINITYXG2_EXIT="Exit"]
|
||||
}
|
||||
|
||||
Frame label="Preamp" {
|
||||
Switch item=RS232ME label="Power" mappings=[RS232ME_POWER_ON="On",RS232ME_POWER_OFF="Off"]
|
||||
}
|
||||
|
||||
Frame label="Garage Door" {
|
||||
Switch item=Garage_Door label="Open/Close" mappings=[ON="Do It"]
|
||||
}
|
||||
```
|
||||
|
||||
### Rule file
|
||||
|
||||
This is an example of how to use a Contact Closure channel within a rule to implement a momentary contact switch, which could be used to trigger a garage door opener.
|
||||
|
||||
```
|
||||
var boolean isRunning = false
|
||||
|
||||
rule "Example Garage Door Opener"
|
||||
when
|
||||
Item Garage_Door received command
|
||||
then
|
||||
if (isRunning == false ) {
|
||||
isRunning = true
|
||||
ContactClosure1.sendCommand(ON)
|
||||
Thread.sleep(750)
|
||||
ContactClosure1.sendCommand(OFF)
|
||||
isRunning = false
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
This is an example of how to send IR and/or serial commands from within a rule.
|
||||
|
||||
```
|
||||
rule "AV Power On/Off"
|
||||
when
|
||||
Item AVPowerOn received command
|
||||
then
|
||||
if(receivedCommand == ON) {
|
||||
SAMSUNGHLS.sendCommand("SAMSUNGHLS_POWER_ON")
|
||||
HKAVR245.sendCommand("HKAVR245_POWER_ON")
|
||||
}
|
||||
else {
|
||||
SAMSUNGHLS.sendCommand("SAMSUNGHLS_POWER_OFF")
|
||||
HKAVR245.sendCommand("HKAVR245_POWER_OFF")
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
This is an example of how to send a serial command directly from within a rule.
|
||||
|
||||
```
|
||||
rule "Russound Set Zone 1 Volume to 20"
|
||||
when
|
||||
Item RussoundSetVolume received command
|
||||
then
|
||||
RUSSCAA66.sendCommand("%F0%00%00%7F%00%00%70%05%02%02%00%00%F1%21%00%14%00%00%00%01%23%F7")
|
||||
end
|
||||
```
|
||||
|
||||
### Manual Thing Creation
|
||||
|
||||
Place a file named *globalcache.things* in the *conf/things* directory.
|
||||
The file should contain lines formatted like this.
|
||||
|
||||
```
|
||||
globalcache:itachCC:000CFF17B106 [ ipAddress="192.168.12.62" ]
|
||||
globalcache:itachIR:000C0B1E54A0 [ ipAddress="192.168.12.63", mapFilename="ir-codes.map" ]
|
||||
globalcache:itachSL:000CF886B107 [ ipAddress="192.168.12.64", mapFilename="serial-codes.map" ]
|
||||
globalcache:itachFlex:000C8A76E610 [ ipAddress="192.168.12.65", mapFilename="ir-codes.map", activeCable="FLEX_INFRARED"]
|
||||
globalcache:itachFlex:000C07BA7E11 [ ipAddress="192.168.12.66", mapFilename="serial-codes.map", activeCable="FLEX_SERIAL"]
|
||||
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" ]
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
|
||||
<version>3.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>org.openhab.binding.globalcache</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: GlobalCache Binding</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.openhab.addons.bundles</groupId>
|
||||
<artifactId>org.openhab.transform.map</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.globalcache-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>file:${basedirRoot}/bundles/org.openhab.transform.map/target/feature/feature.xml</repository>
|
||||
|
||||
<feature name="openhab-binding-globalcache" description="GlobalCache Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transformation-map</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.globalcache/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link GlobalCacheBindingConstants} class defines common constants that are
|
||||
* used by the globalcache binding.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class GlobalCacheBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "globalcache";
|
||||
|
||||
/*
|
||||
* GlobalCache thing definitions
|
||||
*/
|
||||
// GlobalCache Thing Type UIDs -- IR = Infrared, CC = Contact Closure, SL = Serial
|
||||
public static final ThingTypeUID THING_TYPE_ITACH_IR = new ThingTypeUID(BINDING_ID, "itachIR");
|
||||
public static final ThingTypeUID THING_TYPE_ITACH_CC = new ThingTypeUID(BINDING_ID, "itachCC");
|
||||
public static final ThingTypeUID THING_TYPE_ITACH_SL = new ThingTypeUID(BINDING_ID, "itachSL");
|
||||
public static final ThingTypeUID THING_TYPE_ITACH_FLEX = new ThingTypeUID(BINDING_ID, "itachFlex");
|
||||
public static final ThingTypeUID THING_TYPE_GC_100_06 = new ThingTypeUID(BINDING_ID, "gc100_06");
|
||||
public static final ThingTypeUID THING_TYPE_GC_100_12 = new ThingTypeUID(BINDING_ID, "gc100_12");
|
||||
public static final ThingTypeUID THING_TYPE_ZMOTE = new ThingTypeUID(BINDING_ID, "zmote");
|
||||
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(
|
||||
Stream.of(THING_TYPE_ITACH_IR, THING_TYPE_ITACH_CC, THING_TYPE_ITACH_SL, THING_TYPE_ITACH_FLEX,
|
||||
THING_TYPE_GC_100_06, THING_TYPE_GC_100_12, THING_TYPE_ZMOTE).collect(Collectors.toSet()));
|
||||
|
||||
// GlobalCache-specific thing properties
|
||||
public static final String THING_PROPERTY_UID = "uid";
|
||||
public static final String THING_PROPERTY_MAC = "macAddress";
|
||||
|
||||
/*
|
||||
* GlobalCache thing configuration items
|
||||
*/
|
||||
// Network address of the device
|
||||
public static final String THING_PROPERTY_IP = "ipAddress";
|
||||
|
||||
// MAP file containing mappings from command to IR and SL string
|
||||
public static final String THING_CONFIG_MAP_FILENAME = "mapFilename";
|
||||
|
||||
// Flex "Current Active Cable"
|
||||
public static final String THING_CONFIG_ACTIVECABLE = "activeCable";
|
||||
|
||||
public static final String ACTIVE_CABLE_INFRARED = "FLEX_INFRARED";
|
||||
public static final String ACTIVE_CABLE_SERIAL = "FLEX_SERIAL";
|
||||
public static final String ACTIVE_CABLE_RELAY = "FLEX_RELAY";
|
||||
|
||||
// Serial readers
|
||||
public static final String CONFIG_ENABLE_TWO_WAY_PORT_1 = "enableTwoWay1";
|
||||
public static final String CONFIG_END_OF_MESSAGE_DELIMITER_PORT_1 = "eomDelimiter1";
|
||||
public static final String CONFIG_ENABLE_TWO_WAY_PORT_2 = "enableTwoWay2";
|
||||
public static final String CONFIG_END_OF_MESSAGE_DELIMITER_PORT_2 = "eomDelimiter2";
|
||||
|
||||
// Indicates TCP connection over which the command will be sent
|
||||
public enum CommandType {
|
||||
COMMAND,
|
||||
SERIAL1,
|
||||
SERIAL2
|
||||
}
|
||||
|
||||
/*
|
||||
* Channel constants
|
||||
*/
|
||||
// GlobalCache Channel Types
|
||||
public static final String CHANNEL_TYPE_IR = "channel-type-ir";
|
||||
public static final String CHANNEL_TYPE_CC = "channel-type-cc";
|
||||
public static final String CHANNEL_TYPE_SL = "channel-type-sl";
|
||||
public static final String CHANNEL_TYPE_SL_DIRECT = "channel-type-sl-direct";
|
||||
public static final String CHANNEL_TYPE_SL_FEEDBACK = "channel-type-sl-receive";
|
||||
|
||||
// Channels for handing feedback from serial devices
|
||||
public static final String CHANNEL_SL_M1_RECEIVE = "sl-m1#c1-receive";
|
||||
public static final String CHANNEL_SL_M2_RECEIVE = "sl-m2#c1-receive";
|
||||
|
||||
// Channel properties that are used to specify module number and connector number
|
||||
public static final String CHANNEL_PROPERTY_MODULE = "module";
|
||||
public static final String CHANNEL_PROPERTY_CONNECTOR = "connector";
|
||||
|
||||
// List of iTach model strings returned in the device discovery beacon
|
||||
public static final String GC_MODEL_ITACH = "iTach";
|
||||
public static final String GC_MODEL_ITACHIP2IR = "iTachIP2IR";
|
||||
public static final String GC_MODEL_ITACHWF2IR = "iTachWF2IR";
|
||||
public static final String GC_MODEL_ITACHIP2CC = "iTachIP2CC";
|
||||
public static final String GC_MODEL_ITACHWF2CC = "iTachWF2CC";
|
||||
public static final String GC_MODEL_ITACHIP2SL = "iTachIP2SL";
|
||||
public static final String GC_MODEL_ITACHWF2SL = "iTachWF2SL";
|
||||
public static final String GC_MODEL_ITACHFLEXETH = "iTachFlexEthernet";
|
||||
public static final String GC_MODEL_ITACHFLEXETHPOE = "iTachFlexEthernetPoE";
|
||||
public static final String GC_MODEL_ITACHFLEXWIFI = "iTachFlexWiFi";
|
||||
|
||||
// List of GC-100 model strings returned in the device discovery beacon
|
||||
public static final String GC_MODEL_GC_100 = "GC-100";
|
||||
public static final String GC_MODEL_GC_100_06 = "GC-100-06";
|
||||
public static final String GC_MODEL_GC_100_12 = "GC-100-12";
|
||||
|
||||
// List of Zmote strings returned in the device discovery beacon
|
||||
public static final String GC_MODEL_ZMOTE = "ZV-2";
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal;
|
||||
|
||||
import static org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.SUPPORTED_THING_TYPES_UIDS;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.globalcache.internal.handler.GlobalCacheHandler;
|
||||
import org.openhab.core.net.NetworkAddressService;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link GlobalCacheHandlerFactory} is responsible for creating thing handlers.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.globalcache")
|
||||
public class GlobalCacheHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final NetworkAddressService networkAddressService;
|
||||
|
||||
@Activate
|
||||
public GlobalCacheHandlerFactory(@Reference NetworkAddressService networkAddressService) {
|
||||
this.networkAddressService = networkAddressService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
return new GlobalCacheHandler(thing, networkAddressService.getPrimaryIpv4HostAddress());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+517
@@ -0,0 +1,517 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants;
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.binding.globalcache.internal.handler.GlobalCacheHandler;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link AbstractCommand} class implements the basic functionality needed for all GlobalCache commands.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public abstract class AbstractCommand implements CommandInterface {
|
||||
private final Logger logger = LoggerFactory.getLogger(AbstractCommand.class);
|
||||
|
||||
private LinkedBlockingQueue<RequestMessage> requestQueue;
|
||||
|
||||
private final int RESPONSE_QUEUE_MAX_DEPTH = 1;
|
||||
private final int RESPONSE_QUEUE_TIMEOUT = 3000;
|
||||
|
||||
protected Thing thing;
|
||||
|
||||
protected String ipAddress;
|
||||
|
||||
// Actual command strings sent to/received from the device (without CR)
|
||||
protected String deviceCommand;
|
||||
protected String deviceReply;
|
||||
|
||||
// Short human-readable name of the command
|
||||
protected String commandName;
|
||||
|
||||
// Determines which TCP port will be used for the command
|
||||
private CommandType commandType;
|
||||
|
||||
protected String module;
|
||||
protected String connector;
|
||||
|
||||
protected String errorModule;
|
||||
protected String errorConnector;
|
||||
protected String errorCode;
|
||||
protected String errorMessage;
|
||||
|
||||
private boolean isQuiet;
|
||||
|
||||
/*
|
||||
* The {@link AbstractCommand} abstract class is the basis for all GlobalCache device command classes.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public AbstractCommand(Thing t, LinkedBlockingQueue<RequestMessage> q, String n, CommandType c) {
|
||||
thing = t;
|
||||
requestQueue = q;
|
||||
commandName = n;
|
||||
commandType = c;
|
||||
setQuiet(false);
|
||||
|
||||
module = null;
|
||||
connector = null;
|
||||
deviceCommand = null;
|
||||
deviceReply = null;
|
||||
errorCode = null;
|
||||
errorMessage = null;
|
||||
|
||||
ipAddress = ((GlobalCacheHandler) thing.getHandler()).getIP();
|
||||
}
|
||||
|
||||
public String getCommandName() {
|
||||
return commandName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
public void setModule(String m) {
|
||||
module = m;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConnector() {
|
||||
return connector;
|
||||
}
|
||||
|
||||
public void setConnector(String c) {
|
||||
connector = c;
|
||||
}
|
||||
|
||||
public void setCommandType(CommandType commandType) {
|
||||
this.commandType = commandType;
|
||||
}
|
||||
|
||||
public boolean isGC100Model12() {
|
||||
return thing.getThingTypeUID().equals(GlobalCacheBindingConstants.THING_TYPE_GC_100_12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void parseSuccessfulReply();
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return errorCode == null ? true : false;
|
||||
}
|
||||
|
||||
public String successAsString() {
|
||||
return errorCode == null ? "succeeded" : "failed";
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public String getErrorModule() {
|
||||
return errorModule;
|
||||
}
|
||||
|
||||
public String getErrorConnector() {
|
||||
return errorConnector;
|
||||
}
|
||||
|
||||
protected boolean isQuiet() {
|
||||
return isQuiet;
|
||||
}
|
||||
|
||||
private void setQuiet(boolean quiet) {
|
||||
isQuiet = quiet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a GlobalCache device command
|
||||
*/
|
||||
public void executeQuiet() {
|
||||
setQuiet(true);
|
||||
execute();
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
if (requestQueue == null) {
|
||||
createGenericError("Execute method was called with a null requestQueue");
|
||||
return;
|
||||
}
|
||||
|
||||
if (deviceCommand == null) {
|
||||
createGenericError("Execute method was called with a null deviceCommand");
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing == null) {
|
||||
createGenericError("Execute method was called with a null thing");
|
||||
return;
|
||||
}
|
||||
|
||||
// Send command & get response
|
||||
if (sendCommand()) {
|
||||
parseSuccessfulReply();
|
||||
if (!isQuiet()) {
|
||||
logSuccess();
|
||||
}
|
||||
} else {
|
||||
if (!isQuiet()) {
|
||||
logFailure();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Place a request message onto the request queue, then wait on the response queue for the
|
||||
* response message. The CommandHandler private class in GlobalCacheHandler.java
|
||||
* is responsible for the actual device interaction.
|
||||
*/
|
||||
private boolean sendCommand() {
|
||||
// Create a response queue. The command processor will use this queue to return the device's reply.
|
||||
LinkedBlockingQueue<ResponseMessage> responseQueue = new LinkedBlockingQueue<>(RESPONSE_QUEUE_MAX_DEPTH);
|
||||
|
||||
// Create the request message
|
||||
RequestMessage requestMsg = new RequestMessage(commandName, commandType, deviceCommand, responseQueue);
|
||||
|
||||
try {
|
||||
// Put the request message on the request queue
|
||||
requestQueue.put(requestMsg);
|
||||
logger.trace("Put request on queue (depth={}), sent command '{}'", requestQueue.size(), deviceCommand);
|
||||
|
||||
// Wait on the response queue for the response message
|
||||
ResponseMessage responseMsg = responseQueue.poll(RESPONSE_QUEUE_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||
|
||||
if (responseMsg == null) {
|
||||
createGenericError("Timed out waiting on response queue for message");
|
||||
return false;
|
||||
}
|
||||
|
||||
deviceReply = responseMsg.getDeviceReply();
|
||||
logger.trace("Got response message off response queue, received reply '{}'", deviceReply);
|
||||
|
||||
if (isErrorReply(deviceReply)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
createGenericError("Poll of response queue was interrupted");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the reply and set error values if an error occurred.
|
||||
*/
|
||||
private boolean isErrorReply(String reply) {
|
||||
logger.trace("Checking device reply for error condition: {}", reply);
|
||||
|
||||
Pattern pattern;
|
||||
Matcher matcher;
|
||||
|
||||
// Generic (generated by binding) errors are of the form
|
||||
// ERROR: message
|
||||
if (reply.startsWith("ERROR:")) {
|
||||
createGenericError(reply);
|
||||
return true;
|
||||
}
|
||||
|
||||
// iTach response for unknown command are of the form
|
||||
// unknowncommand,eee, where eee is the error number
|
||||
if (reply.startsWith("unknowncommand,") && reply.length() >= 16) {
|
||||
String eCode = reply.substring(15);
|
||||
createGenericError("Device does not understand command, error code is " + eCode);
|
||||
errorCode = eCode;
|
||||
return true;
|
||||
}
|
||||
|
||||
// GC-100 response for unknown command are of the form
|
||||
// unknowncommand ee, where ee is the error number
|
||||
if (reply.startsWith("unknowncommand ") && reply.length() >= 16) {
|
||||
errorModule = "";
|
||||
errorConnector = "";
|
||||
errorCode = reply.substring(15);
|
||||
errorMessage = lookupErrorMessage(errorCode, GC100_ERROR_MESSAGES);
|
||||
logger.debug("Device reply indicates GC-100 error condition");
|
||||
return true;
|
||||
}
|
||||
|
||||
// iTach error replies are of the form ERR_m:c,eee, where m is the module number,
|
||||
// c is the connector number, and eee is the error number
|
||||
pattern = Pattern.compile("ERR_[0-9]:[0-3],\\d\\d\\d");
|
||||
matcher = pattern.matcher(reply);
|
||||
if (matcher.find()) {
|
||||
errorModule = reply.substring(4, 5);
|
||||
errorConnector = reply.substring(6, 7);
|
||||
errorCode = reply.substring(8, 11);
|
||||
errorMessage = lookupErrorMessage(errorCode, ITACH_ERROR_MESSAGES);
|
||||
logger.debug("Device reply indicates iTach error condition");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Flex general error replies are of the form ERR eee, where eee is the error number
|
||||
pattern = Pattern.compile("ERR \\d\\d\\d");
|
||||
matcher = pattern.matcher(reply);
|
||||
if (matcher.find()) {
|
||||
errorModule = "";
|
||||
errorConnector = "";
|
||||
errorCode = reply.substring(4);
|
||||
errorMessage = lookupErrorMessage(errorCode, FLEX_ERROR_MESSAGES);
|
||||
logger.debug("Device reply indicates Flex general error condition");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Flex infrared error replies are of the form ERR IReee, where eee is the error number
|
||||
pattern = Pattern.compile("ERR IR\\d\\d\\d");
|
||||
matcher = pattern.matcher(reply);
|
||||
if (matcher.find()) {
|
||||
errorModule = "";
|
||||
errorConnector = "";
|
||||
errorCode = reply.substring(6);
|
||||
errorMessage = lookupErrorMessage(errorCode, FLEX_IR_ERROR_MESSAGES);
|
||||
logger.debug("Device reply indicates Flex IR error condition");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Flex serial error replies are of the form ERR SLeee, where eee is the error number
|
||||
pattern = Pattern.compile("ERR SL\\d\\d\\d");
|
||||
matcher = pattern.matcher(reply);
|
||||
if (matcher.find()) {
|
||||
errorModule = "";
|
||||
errorConnector = "";
|
||||
errorCode = reply.substring(6);
|
||||
errorMessage = lookupErrorMessage(errorCode, FLEX_SL_ERROR_MESSAGES);
|
||||
logger.debug("Device reply indicates Flex SL error condition");
|
||||
return true;
|
||||
}
|
||||
|
||||
errorCode = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void createGenericError(String s) {
|
||||
errorModule = "N/A";
|
||||
errorConnector = "N/A";
|
||||
errorCode = "N/A";
|
||||
errorMessage = s;
|
||||
}
|
||||
|
||||
private String lookupErrorMessage(String errorCode, String[] errorMessageArray) {
|
||||
int eCode;
|
||||
try {
|
||||
eCode = Integer.parseInt(errorCode);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
eCode = 0;
|
||||
logger.debug("Badly formatted error code '{}' received from device: {}", errorCode, e.getMessage());
|
||||
}
|
||||
|
||||
if (eCode < 1 || eCode > errorMessageArray.length) {
|
||||
eCode = 0;
|
||||
}
|
||||
return errorMessageArray[eCode];
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors returned by GlobalCache iTach devices
|
||||
*/
|
||||
private static final String[] ITACH_ERROR_MESSAGES = {
|
||||
// 0
|
||||
"Unknown error",
|
||||
// 1
|
||||
"Invalid command. Command not found.",
|
||||
// 2
|
||||
"Invalid module address (does not exist).",
|
||||
// 3
|
||||
"Invalid connector address (does not exist).",
|
||||
// 4
|
||||
"Invalid ID value.",
|
||||
// 5
|
||||
"Invalid frequency value",
|
||||
// 6
|
||||
"Invalid repeat value.",
|
||||
// 7
|
||||
"Invalid offset value.",
|
||||
// 8
|
||||
"Invalid pulse count.",
|
||||
// 9
|
||||
"Invalid pulse data.",
|
||||
// 10
|
||||
"Uneven amount of <on|off> statements.",
|
||||
// 11
|
||||
"No carriage return found.",
|
||||
// 12
|
||||
"Repeat count exceeded.",
|
||||
// 13
|
||||
"IR command sent to input connector.",
|
||||
// 14
|
||||
"Blaster command sent to non-blaster connector.",
|
||||
// 15
|
||||
"No carriage return before buffer full.",
|
||||
// 16
|
||||
"No carriage return.",
|
||||
// 17
|
||||
"Bad command syntax.",
|
||||
// 18
|
||||
"Sensor command sent to non-input connector.",
|
||||
// 19
|
||||
"Repeated IR transmission failure.",
|
||||
// 20
|
||||
"Above designated IR <on|off> pair limit.",
|
||||
// 21
|
||||
"Symbol odd boundary.",
|
||||
// 22
|
||||
"Undefined symbol.",
|
||||
// 23
|
||||
"Unknown option.",
|
||||
// 24
|
||||
"Invalid baud rate setting.",
|
||||
// 25
|
||||
"Invalid flow control setting.",
|
||||
// 26
|
||||
"Invalid parity setting.",
|
||||
// 27
|
||||
"Settings are locked."
|
||||
//
|
||||
};
|
||||
|
||||
/*
|
||||
* Errors returned by GlobalCache GC-100 devices
|
||||
*/
|
||||
private static final String[] GC100_ERROR_MESSAGES = {
|
||||
// 0
|
||||
"Unknown error.",
|
||||
// 1
|
||||
"Time out occurred because <CR> not received. Request not processed",
|
||||
// 2
|
||||
"Invalid module address (module does not exist) received with getversion.",
|
||||
// 3
|
||||
"Invalid module address (module does not exist).",
|
||||
// 4
|
||||
"Invalid connector address.",
|
||||
// 5
|
||||
"Connector address 1 is set up as “sensor in” when attempting IR command.",
|
||||
// 6
|
||||
"Connector address 2 is set up as “sensor in” when attempting IR command.",
|
||||
// 7
|
||||
"Connector address 3 is set up as “sensor in” when attempting IR command.",
|
||||
// 8
|
||||
"Offset is set to an even transition number, but should be odd.",
|
||||
// 9
|
||||
"Maximum number of transitions exceeded (256 total allowed).",
|
||||
// 10
|
||||
"Number of transitions in the IR command is not even.",
|
||||
// 11
|
||||
"Contact closure command sent to a module that is not a relay.",
|
||||
// 12
|
||||
"Missing carriage return. All commands must end with a carriage return.",
|
||||
// 13
|
||||
"State was requested of an invalid connector address.",
|
||||
// 14
|
||||
"Command sent to the unit is not supported by the GC-100.",
|
||||
// 15
|
||||
"Maximum number of IR transitions exceeded. (SM_IR_INPROCESS)",
|
||||
// 16
|
||||
"Invalid number of IR transitions (must be an even number).",
|
||||
// 17
|
||||
"Unknown error.",
|
||||
// 18
|
||||
"Unknown error.",
|
||||
// 19
|
||||
"Unknown error.",
|
||||
// 20
|
||||
"Unknown error.",
|
||||
// 21
|
||||
"Attempted to send an IR command to a non-IR module.",
|
||||
// 22
|
||||
"Unknown error.",
|
||||
// 23
|
||||
"Command sent is not supported by this type of module."
|
||||
//
|
||||
};
|
||||
|
||||
/*
|
||||
* General errors returned by Flex devices
|
||||
*/
|
||||
private static final String[] FLEX_ERROR_MESSAGES = {
|
||||
// 0
|
||||
"Unknown error.",
|
||||
// 1
|
||||
"Invalid command. Command not found.",
|
||||
// 2
|
||||
"Bad command syntax used with a known command.",
|
||||
// 3
|
||||
"Invalid connector address (does not exist).",
|
||||
// 4
|
||||
"No carriage return found.",
|
||||
// 5
|
||||
"Command not supported by current Flex Link Port setting.",
|
||||
// 6
|
||||
"Settings are locked.",
|
||||
//
|
||||
};
|
||||
|
||||
/*
|
||||
* Infrared errors returned by Flex devices
|
||||
*/
|
||||
private static final String[] FLEX_IR_ERROR_MESSAGES = {
|
||||
// 0
|
||||
"Unknown error.",
|
||||
// 1
|
||||
"Invalid ID value.",
|
||||
// 2
|
||||
"Invalid frequency.",
|
||||
// 3
|
||||
"Invalid repeat.",
|
||||
// 4
|
||||
"Invalid offset.",
|
||||
// 5
|
||||
"Invalid IR pulse value.",
|
||||
// 6
|
||||
"Odd amount of IR pulse values (must be even).",
|
||||
// 7
|
||||
"Maximum pulse pair limit exceeded.",
|
||||
//
|
||||
};
|
||||
|
||||
/*
|
||||
* Serial errors returned by Flex devices
|
||||
*/
|
||||
private static final String[] FLEX_SL_ERROR_MESSAGES = {
|
||||
// 0
|
||||
"Unknown error.",
|
||||
// 1
|
||||
"Invalid baud rate.",
|
||||
// 2
|
||||
"Invalid flow control setting.",
|
||||
// 3
|
||||
"Invalid parity setting.",
|
||||
//
|
||||
};
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandGetdevices} class implements the GlobalCache getdevices command.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandGetdevices extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandGetdevices.class);
|
||||
|
||||
public CommandGetdevices(Thing thing, LinkedBlockingQueue<RequestMessage> requestQueue) {
|
||||
super(thing, requestQueue, "getdevices", CommandType.COMMAND);
|
||||
deviceCommand = "getdevices";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
// decode response
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded on thing {} at {}", commandName, thing.getUID().getId(), ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed for thing {} at {}, errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandGetserial} class implements the GlobalCache get_SERIAL command, which retrieves the serial
|
||||
* port parameters (baud, flow control, and parity) from the device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandGetserial extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandGetserial.class);
|
||||
|
||||
private String baud;
|
||||
private String flow;
|
||||
private String parity;
|
||||
|
||||
public CommandGetserial(Thing thing, LinkedBlockingQueue<RequestMessage> requestQueue, String mod, String con) {
|
||||
super(thing, requestQueue, "get_SERIAL", CommandType.COMMAND);
|
||||
|
||||
deviceCommand = "get_SERIAL," + mod + ":" + con;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// decode response of form SERIAL,1:1,<baudrate>,<flowcontrol>,<parity
|
||||
Pattern p = Pattern.compile("SERIAL,\\d:\\d,\\S+,\\S+,\\S+");
|
||||
Matcher m = p.matcher(deviceReply);
|
||||
if (!m.matches()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fields[] = deviceReply.split(",");
|
||||
if (fields.length != 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
setModule(fields[1].substring(0, 1));
|
||||
setConnector(fields[1].substring(2));
|
||||
baud = fields[2];
|
||||
flow = fields[3];
|
||||
parity = fields[4];
|
||||
}
|
||||
|
||||
public String getBaud() {
|
||||
return baud;
|
||||
}
|
||||
|
||||
public String getFlowcontrol() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public String getParity() {
|
||||
return parity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded on thing {} at {}", commandName, thing.getUID().getId(), ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed on thing {} at {}: errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandGetstate} class implements the GlobalCache getstate command, which retrieves the
|
||||
* current state of the contact closure on the device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandGetstate extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandGetstate.class);
|
||||
|
||||
private OnOffType state;
|
||||
|
||||
public CommandGetstate(Thing thing, LinkedBlockingQueue<RequestMessage> requestQueue, String mod, String con) {
|
||||
super(thing, requestQueue, "getstate", CommandType.COMMAND);
|
||||
deviceCommand = "getstate," + mod + ":" + con;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// decode response of form state,1:3,0
|
||||
Pattern p = Pattern.compile("state,\\d:\\d,[01]");
|
||||
Matcher m = p.matcher(deviceReply);
|
||||
if (!m.matches()) {
|
||||
logger.warn("Successful reply from device can't be matched: {}", deviceReply);
|
||||
state = OnOffType.OFF;
|
||||
return;
|
||||
}
|
||||
|
||||
setModule(deviceReply.substring(6, 7));
|
||||
setConnector(deviceReply.substring(8, 9));
|
||||
setState((deviceReply.charAt(10) == '0' ? OnOffType.OFF : OnOffType.ON));
|
||||
}
|
||||
|
||||
private void setState(OnOffType s) {
|
||||
state = s;
|
||||
}
|
||||
|
||||
public OnOffType state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded on thing {} at {}, state={}", commandName, thing.getUID().getId(),
|
||||
ipAddress, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed on thing {} at {}: errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandGetversion} class implements the GlobalCache getversion command, which retrieves software
|
||||
* version of the device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandGetversion extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandGetversion.class);
|
||||
|
||||
private String version;
|
||||
|
||||
public CommandGetversion(Thing thing, LinkedBlockingQueue<RequestMessage> requestQueue) {
|
||||
super(thing, requestQueue, "getversion", CommandType.COMMAND);
|
||||
deviceCommand = "getversion";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
// decode response of form <textversionstring>
|
||||
version = deviceReply;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded on thing {} at {}, version={}", commandName, thing.getUID().getId(),
|
||||
ipAddress, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed for thing {} at {}, errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
/**
|
||||
* The {@link CommandInterface} interface class defines the methods that all command classes must implement.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public interface CommandInterface {
|
||||
|
||||
/**
|
||||
* Get the module number to which the command will be sent
|
||||
*
|
||||
* @return module number as String
|
||||
*/
|
||||
public String getModule();
|
||||
|
||||
/**
|
||||
* Get the connector number to which the command will be sent
|
||||
*
|
||||
* @return connector number as String
|
||||
*/
|
||||
public String getConnector();
|
||||
|
||||
/**
|
||||
* Used by command implementations to parse the device's response
|
||||
*/
|
||||
abstract void parseSuccessfulReply();
|
||||
|
||||
/*
|
||||
* Used by command implementations to report a successful command execution
|
||||
*/
|
||||
abstract void logSuccess();
|
||||
|
||||
/*
|
||||
* Used by command implementations to report a failed command execution
|
||||
*/
|
||||
abstract void logFailure();
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandSendir} class implements the GlobalCache sendir command, which sends
|
||||
* an infrared command to the device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandSendir extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandSendir.class);
|
||||
|
||||
private String rcvCounter;
|
||||
Command command;
|
||||
|
||||
public CommandSendir(Thing thing, Command command, LinkedBlockingQueue<RequestMessage> queue, String mod,
|
||||
String con, String code, int sendCounter) {
|
||||
super(thing, queue, "sendir", CommandType.COMMAND);
|
||||
|
||||
this.command = command;
|
||||
deviceCommand = "sendir," + mod + ":" + con + "," + String.valueOf(sendCounter) + "," + code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// decode response of form completeir,1:1,<ID>
|
||||
if (deviceReply.startsWith("completeir")) {
|
||||
setModule(deviceReply.substring(11, 12));
|
||||
setConnector(deviceReply.substring(13, 14));
|
||||
setRcvCounter(deviceReply.substring(15));
|
||||
}
|
||||
}
|
||||
|
||||
private void setRcvCounter(String c) {
|
||||
rcvCounter = c;
|
||||
}
|
||||
|
||||
public String getRcvCounter() {
|
||||
return rcvCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded for command {} on thing {} at {}", commandName, command.toString(),
|
||||
thing.getUID().getId(), ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed on thing {} at {}: errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandSendserial} class sends a serial command string to the device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandSendserial extends AbstractCommand {
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandSendserial.class);
|
||||
|
||||
private Command command;
|
||||
|
||||
public CommandSendserial(Thing thing, Command command, LinkedBlockingQueue<RequestMessage> queue, String mod,
|
||||
String con, String code) {
|
||||
super(thing, queue, "sendserial", CommandType.SERIAL1);
|
||||
// Check to see if this is for the second serial port on a GC-100-12
|
||||
if (isGC100Model12() && mod.equals("2")) {
|
||||
setCommandType(CommandType.SERIAL2);
|
||||
}
|
||||
this.command = command;
|
||||
this.deviceCommand = code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
// decode response
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded for command {} on thing {} at {}", commandName, command.toString(),
|
||||
thing.getUID().getId(), ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed on thing {} at {}: errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandSetserial} class implements the GlobalCache set_SERIAL command, which sets the serial
|
||||
* port parameters (baud, flow control, and parity) on the device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandSetserial extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandSetserial.class);
|
||||
|
||||
private String baud;
|
||||
private String flow;
|
||||
private String parity;
|
||||
|
||||
public CommandSetserial(Thing thing, LinkedBlockingQueue<RequestMessage> requestQueue, String mod, String con,
|
||||
String baud, String flowcontrol, String parity) {
|
||||
super(thing, requestQueue, "set_SERIAL", CommandType.COMMAND);
|
||||
|
||||
deviceCommand = "set_SERIAL," + mod + ":" + con + "," + baud + "," + flowcontrol + "," + parity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// decode response of form SERIAL,1:1,<baudrate>,<flowcontrol>,<parity
|
||||
Pattern p = Pattern.compile("SERIAL,\\d:\\d,\\S+,\\S+,\\S+");
|
||||
Matcher m = p.matcher(deviceReply);
|
||||
if (!m.matches()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String fields[] = deviceReply.split(",");
|
||||
if (fields.length != 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
setModule(fields[1].substring(0, 1));
|
||||
setConnector(fields[1].substring(2));
|
||||
baud = fields[2];
|
||||
flow = fields[3];
|
||||
parity = fields[4];
|
||||
}
|
||||
|
||||
public String getBaud() {
|
||||
return baud;
|
||||
}
|
||||
|
||||
public String getFlowcontrol() {
|
||||
return flow;
|
||||
}
|
||||
|
||||
public String getParity() {
|
||||
return parity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded on thing {} at {}", commandName, thing.getUID().getId(), ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed on thing {} at: ipAdress={}, errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link CommandSetstate} class implements the GlobalCache setstate command for devices that support contact
|
||||
* closure.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class CommandSetstate extends AbstractCommand {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(CommandSetstate.class);
|
||||
|
||||
private Command command;
|
||||
private OnOffType state;
|
||||
|
||||
public CommandSetstate(Thing thing, Command command, LinkedBlockingQueue<RequestMessage> queue, String mod,
|
||||
String con) {
|
||||
super(thing, queue, "setstate", CommandType.COMMAND);
|
||||
|
||||
this.command = command;
|
||||
if (command instanceof OnOffType) {
|
||||
deviceCommand = "setstate," + mod + ":" + con + "," + (command.equals(OnOffType.ON) ? "1" : "0");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseSuccessfulReply() {
|
||||
if (deviceReply == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Match on response of form setstate,1:3,0 or state,1:3,0
|
||||
if (!matchSetstate()) {
|
||||
logger.warn("Successful reply from device can't be matched: {}", deviceReply);
|
||||
setState(OnOffType.OFF);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchSetstate() {
|
||||
// Matches both iTach and GC-100 responses
|
||||
Pattern p = Pattern.compile("(setstate|state),(\\d):(\\d),([01])");
|
||||
Matcher m = p.matcher(deviceReply);
|
||||
if (m.matches()) {
|
||||
logger.trace("Matched setstate response: g2={}, g3={}, g4={}", m.group(2), m.group(3), m.group(4));
|
||||
if (m.groupCount() == 4) {
|
||||
setModule(m.group(2));
|
||||
setConnector(m.group(3));
|
||||
setState(m.group(4).equals("0") ? OnOffType.OFF : OnOffType.ON);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setState(OnOffType s) {
|
||||
state = s;
|
||||
}
|
||||
|
||||
public OnOffType state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSuccess() {
|
||||
logger.debug("Execute '{}' succeeded for command {} on thing {} at {}", commandName, command,
|
||||
thing.getUID().getId(), ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logFailure() {
|
||||
logger.error("Execute '{}' failed on thing {} at {}: errorCode={}, errorMessage={}", commandName,
|
||||
thing.getUID().getId(), ipAddress, errorCode, errorMessage);
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
import org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.CommandType;
|
||||
|
||||
/**
|
||||
* The {@link RequestMessage} class is responsible for storing the command to be sent to the GlobalCache
|
||||
* device and for storing whether the command is serial or not.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class RequestMessage {
|
||||
private LinkedBlockingQueue<ResponseMessage> rcvQueue;
|
||||
private String deviceCommand;
|
||||
private CommandType commandType;
|
||||
private String commandName;
|
||||
|
||||
public RequestMessage(String commandName, CommandType commandType, String deviceCommand,
|
||||
LinkedBlockingQueue<ResponseMessage> rcvQueue) {
|
||||
this.commandName = commandName;
|
||||
this.commandType = commandType;
|
||||
this.deviceCommand = deviceCommand;
|
||||
this.rcvQueue = rcvQueue;
|
||||
}
|
||||
|
||||
public String getDeviceCommand() {
|
||||
return deviceCommand;
|
||||
}
|
||||
|
||||
public String getCommandName() {
|
||||
return commandName;
|
||||
}
|
||||
|
||||
public CommandType getCommandType() {
|
||||
return commandType;
|
||||
}
|
||||
|
||||
public boolean isCommand() {
|
||||
return commandType == CommandType.COMMAND;
|
||||
}
|
||||
|
||||
public boolean isSerial() {
|
||||
return commandType == CommandType.SERIAL1 || commandType == CommandType.SERIAL2;
|
||||
}
|
||||
|
||||
public boolean isSerial1() {
|
||||
return commandType == CommandType.SERIAL1;
|
||||
}
|
||||
|
||||
public boolean isSerial2() {
|
||||
return commandType == CommandType.SERIAL2;
|
||||
}
|
||||
|
||||
public LinkedBlockingQueue<ResponseMessage> getReceiveQueue() {
|
||||
return rcvQueue;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.command;
|
||||
|
||||
/**
|
||||
* The {@link ResponseMessage} class is responsible for storing the raw and parsed response from the
|
||||
* GlobalCache device.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class ResponseMessage {
|
||||
|
||||
private String deviceReply;
|
||||
|
||||
public ResponseMessage(String deviceReply) {
|
||||
this.deviceReply = deviceReply;
|
||||
}
|
||||
|
||||
public String getDeviceReply() {
|
||||
return deviceReply;
|
||||
}
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.net.NetworkAddressService;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Modified;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link GlobalCacheDiscoveryService} class implements a service
|
||||
* for discovering the GlobalCache devices.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.globalcache")
|
||||
public class GlobalCacheDiscoveryService extends AbstractDiscoveryService {
|
||||
private final Logger logger = LoggerFactory.getLogger(GlobalCacheDiscoveryService.class);
|
||||
|
||||
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
|
||||
private ScheduledFuture<?> gcDiscoveryJob;
|
||||
|
||||
// Discovery parameters
|
||||
public static final boolean BACKGROUND_DISCOVERY_ENABLED = true;
|
||||
public static final int BACKGROUND_DISCOVERY_DELAY = 10;
|
||||
|
||||
private NetworkAddressService networkAddressService;
|
||||
|
||||
private boolean terminate;
|
||||
|
||||
public GlobalCacheDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, 0, BACKGROUND_DISCOVERY_ENABLED);
|
||||
gcDiscoveryJob = null;
|
||||
terminate = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||
return SUPPORTED_THING_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate(Map<String, Object> configProperties) {
|
||||
logger.debug("Globalcache discovery service activated");
|
||||
super.activate(configProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
logger.debug("Globalcache discovery service deactivated");
|
||||
stopBackgroundDiscovery();
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Modified
|
||||
protected void modified(Map<String, Object> configProperties) {
|
||||
super.modified(configProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startBackgroundDiscovery() {
|
||||
if (gcDiscoveryJob == null) {
|
||||
terminate = false;
|
||||
logger.debug("Starting background discovery job in {} seconds", BACKGROUND_DISCOVERY_DELAY);
|
||||
gcDiscoveryJob = scheduledExecutorService.schedule(this::discover, BACKGROUND_DISCOVERY_DELAY,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stopBackgroundDiscovery() {
|
||||
if (gcDiscoveryJob != null) {
|
||||
logger.debug("Canceling background discovery job");
|
||||
terminate = true;
|
||||
gcDiscoveryJob.cancel(false);
|
||||
gcDiscoveryJob = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startScan() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopScan() {
|
||||
}
|
||||
|
||||
private synchronized void discover() {
|
||||
logger.debug("Discovery job is running");
|
||||
|
||||
MulticastListener gcMulticastListener;
|
||||
|
||||
try {
|
||||
gcMulticastListener = new MulticastListener(networkAddressService.getPrimaryIpv4HostAddress());
|
||||
} catch (SocketException se) {
|
||||
logger.error("Discovery job got Socket exception creating multicast socket: {}", se.getMessage());
|
||||
return;
|
||||
} catch (IOException ioe) {
|
||||
logger.error("Discovery job got IO exception creating multicast socket: {}", ioe.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
while (!terminate) {
|
||||
boolean beaconReceived;
|
||||
try {
|
||||
// Wait for a discovery beacon.
|
||||
beaconReceived = gcMulticastListener.waitForBeacon();
|
||||
} catch (IOException ioe) {
|
||||
logger.debug("Discovery job got exception waiting for beacon: {}", ioe.getMessage());
|
||||
beaconReceived = false;
|
||||
}
|
||||
|
||||
if (beaconReceived) {
|
||||
// We got a discovery beacon. Process it as a potential new thing
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
|
||||
properties.put(THING_PROPERTY_IP, gcMulticastListener.getIPAddress());
|
||||
properties.put(THING_PROPERTY_MAC, gcMulticastListener.getMACAddress());
|
||||
properties.put(THING_PROPERTY_UID, gcMulticastListener.getUID());
|
||||
properties.put(Thing.PROPERTY_VENDOR, gcMulticastListener.getVendor());
|
||||
properties.put(Thing.PROPERTY_MODEL_ID, gcMulticastListener.getModel());
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, gcMulticastListener.getSoftwareRevision());
|
||||
properties.put(Thing.PROPERTY_HARDWARE_VERSION, gcMulticastListener.getHardwareRevision());
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, gcMulticastListener.getSerialNumber());
|
||||
|
||||
logger.trace("Device of type {} discovered with MAC {} and IP {}", gcMulticastListener.getModel(),
|
||||
gcMulticastListener.getMACAddress(), gcMulticastListener.getIPAddress());
|
||||
|
||||
ThingTypeUID typeUID = gcMulticastListener.getThingTypeUID();
|
||||
if (typeUID != null) {
|
||||
ThingUID uid = new ThingUID(typeUID, gcMulticastListener.getSerialNumber());
|
||||
logger.trace("Creating discovery result for: {}, type={}, IP={}", uid,
|
||||
gcMulticastListener.getModel(), gcMulticastListener.getIPAddress());
|
||||
thingDiscovered(DiscoveryResultBuilder.create(uid).withProperties(properties)
|
||||
.withLabel(gcMulticastListener.getVendor() + " " + gcMulticastListener.getModel()).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
gcMulticastListener.shutdown();
|
||||
logger.debug("Discovery job is exiting");
|
||||
}
|
||||
|
||||
@Reference
|
||||
protected void setNetworkAddressService(NetworkAddressService networkAddressService) {
|
||||
this.networkAddressService = networkAddressService;
|
||||
}
|
||||
|
||||
protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) {
|
||||
this.networkAddressService = null;
|
||||
}
|
||||
}
|
||||
+323
@@ -0,0 +1,323 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.globalcache.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.MulticastSocket;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link MulticastListener} class is responsible for listening for the GlobalCache device announcement
|
||||
* beacons on the multicast address, and then extracting the data fields out of the received datagram.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class MulticastListener {
|
||||
private final Logger logger = LoggerFactory.getLogger(MulticastListener.class);
|
||||
|
||||
private MulticastSocket socket;
|
||||
|
||||
private String serialNumber = "";
|
||||
private String vendor = "";
|
||||
private String model = "";
|
||||
private String softwareRevision = "";
|
||||
private String hardwareRevision = "";
|
||||
|
||||
// GlobalCache-specific properties defined in this binding
|
||||
private String uid = "";
|
||||
private String ipAddress = "";
|
||||
private String macAddress = "";
|
||||
|
||||
private Date lastUpdate;
|
||||
|
||||
// GC devices announce themselves on a multicast port
|
||||
private static final String GC_MULTICAST_GROUP = "239.255.250.250";
|
||||
private static final int GC_MULTICAST_PORT = 9131;
|
||||
|
||||
// How long to wait in milliseconds for a discovery beacon
|
||||
public static final int DEFAULT_SOCKET_TIMEOUT = 3000;
|
||||
|
||||
/*
|
||||
* Constructor joins the multicast group, throws IOException on failure.
|
||||
*/
|
||||
public MulticastListener(String ipv4Address) throws IOException, SocketException {
|
||||
InetAddress ifAddress = InetAddress.getByName(ipv4Address);
|
||||
logger.debug("Discovery job using address {} on network interface {}", ifAddress.getHostAddress(),
|
||||
NetworkInterface.getByInetAddress(ifAddress).getName());
|
||||
socket = new MulticastSocket(GC_MULTICAST_PORT);
|
||||
socket.setInterface(ifAddress);
|
||||
socket.setSoTimeout(DEFAULT_SOCKET_TIMEOUT);
|
||||
InetAddress mcastAddress = InetAddress.getByName(GC_MULTICAST_GROUP);
|
||||
socket.joinGroup(mcastAddress);
|
||||
logger.debug("Multicast listener joined multicast group {}:{}", GC_MULTICAST_GROUP, GC_MULTICAST_PORT);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
logger.debug("Multicast listener closing down multicast socket");
|
||||
socket.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait on the multicast socket for an announcement beacon. Return false on socket timeout or error.
|
||||
* Otherwise, parse the beacon for information about the device.
|
||||
*/
|
||||
public boolean waitForBeacon() throws IOException {
|
||||
byte[] bytes = new byte[600];
|
||||
boolean beaconFound;
|
||||
|
||||
// Wait for a device to announce itself
|
||||
logger.trace("Multicast listener waiting for datagram on multicast port");
|
||||
DatagramPacket msgPacket = new DatagramPacket(bytes, bytes.length);
|
||||
try {
|
||||
socket.receive(msgPacket);
|
||||
beaconFound = true;
|
||||
logger.trace("Multicast listener got datagram of length {} from multicast port: {}", msgPacket.getLength(),
|
||||
msgPacket.toString());
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
beaconFound = false;
|
||||
}
|
||||
|
||||
if (beaconFound) {
|
||||
// Get the device properties from the announcement beacon
|
||||
parseAnnouncementBeacon(msgPacket);
|
||||
}
|
||||
|
||||
return beaconFound;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the announcement beacon into the elements needed to create the thing.
|
||||
*
|
||||
* Example iTach beacon:
|
||||
*
|
||||
* AMXB<-UUID=GlobalCache_000C1E021777><-SDKClass=Utility><-Make=GlobalCache><-Model=iTachWF2IR>
|
||||
* <-Revision=710-1001-05><-Pkg_Level=GCPK002><-Config-URL=http://192.168.1.90><-PCB_PN=025-0026-06>
|
||||
* <-Status=Ready>CR
|
||||
*
|
||||
* Example GC-100 beacon:
|
||||
*
|
||||
* AMXB<-UUID=GC100_000C1E00F0E9_GlobalCache><-SDKClass=Utility><-Make=GlobalCache><-Model=GC-100-06>
|
||||
* <-Revision=1.0.0><Config-Name=GC-100><Config-URL=http://192.168.1.70>CR
|
||||
*
|
||||
*/
|
||||
private void parseAnnouncementBeacon(DatagramPacket packet) {
|
||||
String beacon = (new String(packet.getData())).trim();
|
||||
|
||||
logger.trace("Multicast listener parsing announcement packet: {}", beacon);
|
||||
|
||||
clearProperties();
|
||||
|
||||
if (beacon.contains(GC_MODEL_ITACH)) {
|
||||
parseItachAnnouncementBeacon(beacon);
|
||||
} else if (beacon.contains(GC_MODEL_GC_100)) {
|
||||
parseGC100AnnouncementBeacon(beacon);
|
||||
} else if (beacon.contains(GC_MODEL_ZMOTE)) {
|
||||
parseZmoteAnnouncementBeacon(beacon);
|
||||
} else {
|
||||
logger.debug("Multicast listener doesn't know how to parse beacon: {}", beacon);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseItachAnnouncementBeacon(String beacon) {
|
||||
String[] parameterList = beacon.split("<-");
|
||||
|
||||
for (String parameter : parameterList) {
|
||||
String[] keyValue = parameter.split("=");
|
||||
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keyValue[0].contains("UUID")) {
|
||||
uid = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
macAddress = uid.substring(uid.indexOf("_") + 1);
|
||||
serialNumber = macAddress;
|
||||
} else if (keyValue[0].contains("Make")) {
|
||||
vendor = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Model")) {
|
||||
model = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Revision")) {
|
||||
softwareRevision = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Config-URL")) {
|
||||
ipAddress = keyValue[1].substring(keyValue[1].indexOf("://") + 3, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("PCB_PN")) {
|
||||
hardwareRevision = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
}
|
||||
}
|
||||
lastUpdate = new Date();
|
||||
}
|
||||
|
||||
/*
|
||||
* AMXB<-UUID=GC100_000C1E00F0E9_GlobalCache><-SDKClass=Utility><-Make=GlobalCache><-Model=GC-100-06>
|
||||
* <-Revision=1.0.0><Config-Name=GC-100><Config-URL=http://192.168.1.70>CR
|
||||
*/
|
||||
private void parseGC100AnnouncementBeacon(String beacon) {
|
||||
String[] parameterList = beacon.split("<");
|
||||
|
||||
for (String parameter : parameterList) {
|
||||
String[] keyValue = parameter.split("=");
|
||||
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keyValue[0].contains("UUID")) {
|
||||
uid = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
macAddress = uid.subSequence(6, 18).toString();
|
||||
serialNumber = macAddress;
|
||||
} else if (keyValue[0].contains("Make")) {
|
||||
vendor = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Model")) {
|
||||
model = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Revision")) {
|
||||
softwareRevision = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Config-URL")) {
|
||||
ipAddress = keyValue[1].substring(keyValue[1].indexOf("://") + 3, keyValue[1].length() - 1);
|
||||
}
|
||||
}
|
||||
hardwareRevision = "N/A";
|
||||
lastUpdate = new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/*
|
||||
* AMXB<-UUID=CI00a1b2c3><-Type=ZMT2><-Make=zmote.io><-Model=ZV-2><-Revision=2.1.4><-Config-URL=http://192.168.1.12>
|
||||
*/
|
||||
private void parseZmoteAnnouncementBeacon(String beacon) {
|
||||
String[] parameterList = beacon.split("<-");
|
||||
|
||||
for (String parameter : parameterList) {
|
||||
String[] keyValue = parameter.split("=");
|
||||
if (keyValue.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (keyValue[0].contains("UUID")) {
|
||||
uid = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
serialNumber = uid;
|
||||
} else if (keyValue[0].contains("Make")) {
|
||||
vendor = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Model")) {
|
||||
model = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Revision")) {
|
||||
softwareRevision = keyValue[1].substring(0, keyValue[1].length() - 1);
|
||||
} else if (keyValue[0].contains("Config-URL")) {
|
||||
ipAddress = keyValue[1].substring(keyValue[1].indexOf("://") + 3, keyValue[1].length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
hardwareRevision = "N/A";
|
||||
lastUpdate = new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
private void clearProperties() {
|
||||
serialNumber = "";
|
||||
vendor = "";
|
||||
model = "";
|
||||
softwareRevision = "";
|
||||
hardwareRevision = "";
|
||||
uid = "";
|
||||
ipAddress = "";
|
||||
macAddress = "";
|
||||
}
|
||||
|
||||
public String getSerialNumber() {
|
||||
return serialNumber;
|
||||
}
|
||||
|
||||
public String getVendor() {
|
||||
return vendor;
|
||||
}
|
||||
|
||||
public String getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public String getSoftwareRevision() {
|
||||
return softwareRevision;
|
||||
}
|
||||
|
||||
public String getHardwareRevision() {
|
||||
return hardwareRevision;
|
||||
}
|
||||
|
||||
public String getUID() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public String getIPAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
public String getMACAddress() {
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
public Date getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
|
||||
public boolean isITach() {
|
||||
return model.contains(GC_MODEL_ITACH);
|
||||
}
|
||||
|
||||
public boolean isGC100() {
|
||||
return model.contains(GC_MODEL_GC_100);
|
||||
}
|
||||
|
||||
public ThingTypeUID getThingTypeUID() {
|
||||
logger.trace("Multicast listener looking up thing type for model {} at IP {}", model, ipAddress);
|
||||
|
||||
switch (model) {
|
||||
case GC_MODEL_ITACHIP2IR:
|
||||
case GC_MODEL_ITACHWF2IR:
|
||||
return THING_TYPE_ITACH_IR;
|
||||
|
||||
case GC_MODEL_ITACHIP2CC:
|
||||
case GC_MODEL_ITACHWF2CC:
|
||||
return THING_TYPE_ITACH_CC;
|
||||
|
||||
case GC_MODEL_ITACHIP2SL:
|
||||
case GC_MODEL_ITACHWF2SL:
|
||||
return THING_TYPE_ITACH_SL;
|
||||
|
||||
case GC_MODEL_ITACHFLEXETH:
|
||||
case GC_MODEL_ITACHFLEXETHPOE:
|
||||
case GC_MODEL_ITACHFLEXWIFI:
|
||||
return THING_TYPE_ITACH_FLEX;
|
||||
|
||||
case GC_MODEL_GC_100_06:
|
||||
return THING_TYPE_GC_100_06;
|
||||
|
||||
case GC_MODEL_GC_100_12:
|
||||
return THING_TYPE_GC_100_12;
|
||||
|
||||
case GC_MODEL_ZMOTE:
|
||||
return THING_TYPE_ZMOTE;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1188
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="globalcache" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>GlobalCache Binding</name>
|
||||
<description>Binding for GlobalCache iTach and GC-100 devices supporting infrared, serial, and contact closure
|
||||
interfaces.</description>
|
||||
<author>Mark Hilbush</author>
|
||||
|
||||
</binding:binding>
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache Channel Types -->
|
||||
|
||||
<channel-type id="channel-type-ir">
|
||||
<item-type>String</item-type>
|
||||
<label>Infrared</label>
|
||||
<description>Transmits infrared command on module:connector</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="channel-type-cc">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Contact Closure</label>
|
||||
<description>Transmits contact closure command on module:connector</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="channel-type-sl">
|
||||
<item-type>String</item-type>
|
||||
<label>Serial</label>
|
||||
<description>Transmits serial command on module:connector</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="channel-type-sl-direct" advanced="false">
|
||||
<item-type>String</item-type>
|
||||
<label>Serial</label>
|
||||
<description>Transmits serial command on module:connector bypassing MAP transform</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="channel-type-sl-receive" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Serial Receive</label>
|
||||
<description>Data received on the serial port from the device</description>
|
||||
<state readOnly="true"></state>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,287 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache Channel Groups -->
|
||||
|
||||
<channel-group-type id="sl-m1">
|
||||
<label>Module 1</label>
|
||||
<description>Serial Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-sl">
|
||||
<label>Connector 1 (mapped)</label>
|
||||
<description>Mapped commands to serial port</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c1-direct" typeId="channel-type-sl-direct">
|
||||
<label>Connector 1 (direct)</label>
|
||||
<description>Direct commands to serial port</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c1-receive" typeId="channel-type-sl-receive">
|
||||
<label>Connector 1 (receive)</label>
|
||||
<description>Data received on serial port</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="sl-m2">
|
||||
<label>Module 2</label>
|
||||
<description>Serial Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-sl">
|
||||
<label>Connector 1 (mapped)</label>
|
||||
<description>Mapped commands to serial port</description>
|
||||
<properties>
|
||||
<property name="module">2</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c1-direct" typeId="channel-type-sl-direct">
|
||||
<label>Connector 1 (direct)</label>
|
||||
<description>Direct commands to serial port</description>
|
||||
<properties>
|
||||
<property name="module">2</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c1-receive" typeId="channel-type-sl-receive">
|
||||
<label>Connector 1 (receive)</label>
|
||||
<description>Data received on serial port</description>
|
||||
<properties>
|
||||
<property name="module">2</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="ir-m1">
|
||||
<label>Module 1</label>
|
||||
<description>Infrared Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-ir">
|
||||
<label>Connector 1</label>
|
||||
<description>Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c2" typeId="channel-type-ir">
|
||||
<label>Connector 2</label>
|
||||
<description>Infrared emitter on connector 2.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">2</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c3" typeId="channel-type-ir">
|
||||
<label>Connector 3</label>
|
||||
<description>Infrared emitter/blaster on connector 3.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">3</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="ir-m1-c1">
|
||||
<label>Module 1</label>
|
||||
<description>Infrared Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-ir">
|
||||
<label>Connector 1</label>
|
||||
<description>ZMote infrared emitter.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="ir-m2">
|
||||
<label>Module 2</label>
|
||||
<description>Infrared Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-ir">
|
||||
<label>Connector 1</label>
|
||||
<description>Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug.</description>
|
||||
<properties>
|
||||
<property name="module">2</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c2" typeId="channel-type-ir">
|
||||
<label>Connector 2</label>
|
||||
<description>Infrared emitter on connector 2.</description>
|
||||
<properties>
|
||||
<property name="module">2</property>
|
||||
<property name="connector">2</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c3" typeId="channel-type-ir">
|
||||
<label>Connector 3</label>
|
||||
<description>Infrared emitter/blaster on connector 3.</description>
|
||||
<properties>
|
||||
<property name="module">2</property>
|
||||
<property name="connector">3</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="ir-m4">
|
||||
<label>Module 4</label>
|
||||
<description>Infrared Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-ir">
|
||||
<label>Connector 1</label>
|
||||
<description>Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug.</description>
|
||||
<properties>
|
||||
<property name="module">4</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c2" typeId="channel-type-ir">
|
||||
<label>Connector 2</label>
|
||||
<description>Infrared emitter on connector 2.</description>
|
||||
<properties>
|
||||
<property name="module">4</property>
|
||||
<property name="connector">2</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c3" typeId="channel-type-ir">
|
||||
<label>Connector 3</label>
|
||||
<description>Infrared emitter/blaster on connector 3.</description>
|
||||
<properties>
|
||||
<property name="module">4</property>
|
||||
<property name="connector">3</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="ir-m5">
|
||||
<label>Module 5</label>
|
||||
<description>Infrared Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-ir">
|
||||
<label>Connector 1</label>
|
||||
<description>Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug.</description>
|
||||
<properties>
|
||||
<property name="module">5</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c2" typeId="channel-type-ir">
|
||||
<label>Connector 2</label>
|
||||
<description>Infrared emitter on connector 2.</description>
|
||||
<properties>
|
||||
<property name="module">5</property>
|
||||
<property name="connector">2</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c3" typeId="channel-type-ir">
|
||||
<label>Connector 3</label>
|
||||
<description>Infrared emitter/blaster on connector 3.</description>
|
||||
<properties>
|
||||
<property name="module">5</property>
|
||||
<property name="connector">3</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="cc-m1">
|
||||
<label>Module 1</label>
|
||||
<description>Contact Closure Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-cc">
|
||||
<label>Connector 1</label>
|
||||
<description>Contact closure on connector 1.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c2" typeId="channel-type-cc">
|
||||
<label>Connector 2</label>
|
||||
<description>Contact closure on connector 2.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">2</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c3" typeId="channel-type-cc">
|
||||
<label>Connector 3</label>
|
||||
<description>Contact closure on connector 3.</description>
|
||||
<properties>
|
||||
<property name="module">1</property>
|
||||
<property name="connector">3</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="cc-m3">
|
||||
<label>Module 3</label>
|
||||
<description>Contact Closure Module</description>
|
||||
<channels>
|
||||
<channel id="c1" typeId="channel-type-cc">
|
||||
<label>Connector 1</label>
|
||||
<description>Contact closure on connector 1.</description>
|
||||
<properties>
|
||||
<property name="module">3</property>
|
||||
<property name="connector">1</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c2" typeId="channel-type-cc">
|
||||
<label>Connector 2</label>
|
||||
<description>Contact closure on connector 2.</description>
|
||||
<properties>
|
||||
<property name="module">3</property>
|
||||
<property name="connector">2</property>
|
||||
</properties>
|
||||
</channel>
|
||||
|
||||
<channel id="c3" typeId="channel-type-cc">
|
||||
<label>Connector 3</label>
|
||||
<description>Contact closure on connector 3.</description>
|
||||
<properties>
|
||||
<property name="module">3</property>
|
||||
<property name="connector">3</property>
|
||||
</properties>
|
||||
</channel>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache GC-100-06 device contains one SL module, one IR module -->
|
||||
<thing-type id="gc100_06">
|
||||
|
||||
<label>GlobalCache GC-100-06</label>
|
||||
<description>GC-100-06 Infrared and Serial Device</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="sl-m1" typeId="sl-m1"/>
|
||||
<channel-group id="ir-m2" typeId="ir-m2"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the iTach CC device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
|
||||
<parameter name="mapFilename" type="text">
|
||||
<label>Map File</label>
|
||||
<description>Enter name of file containing mapping of commands to IR and Serial codes</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="enableTwoWay1" type="boolean">
|
||||
<label>Enable Two Way</label>
|
||||
<description>Enable two-way serial communication</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="eomDelimiter1" type="text">
|
||||
<label>End-of-message Delimiter</label>
|
||||
<description>URL encoded end-of-message delimiter string for receiving messages</description>
|
||||
<default>%0A</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache GC-100-12 device contains two IR modules, two SL modules, one CC module -->
|
||||
<thing-type id="gc100_12">
|
||||
|
||||
<label>GlobalCache GC-100-12</label>
|
||||
<description>GC-100-12 Infrared, Serial, and Contact Closure Device</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="sl-m1" typeId="sl-m1"/>
|
||||
<channel-group id="sl-m2" typeId="sl-m2"/>
|
||||
<channel-group id="cc-m3" typeId="cc-m3"/>
|
||||
<channel-group id="ir-m4" typeId="ir-m4"/>
|
||||
<channel-group id="ir-m5" typeId="ir-m5"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the iTach CC device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
|
||||
<parameter name="mapFilename" type="text">
|
||||
<label>Map File</label>
|
||||
<description>Enter name of file containing mapping of commands to IR and Serial codes</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="enableTwoWay1" type="boolean">
|
||||
<label>Enable Two Way Port 1</label>
|
||||
<description>Enable two-way serial communication on serial port 1</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="eomDelimiter1" type="text">
|
||||
<label>End-of-message Delimiter Port 1</label>
|
||||
<description>URL encoded end-of-message delimiter string for receiving messages on serial port 1</description>
|
||||
<default>%0A</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="enableTwoWay2" type="boolean">
|
||||
<label>Enable Two Way Port 2</label>
|
||||
<description>Enable two-way serial communication on serial port 2</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="eomDelimiter2" type="text">
|
||||
<label>End-of-message Delimiter Port 2</label>
|
||||
<description>URL encoded end-of-message delimiter string for receiving messages on serial port 2</description>
|
||||
<default>%0A</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache iTach CC (relay) device contains one CC module -->
|
||||
<thing-type id="itachCC">
|
||||
|
||||
<label>GlobalCache iTach CC</label>
|
||||
<description>iTach Contact Closure Device (WF2CC or IP2CC)</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="cc-m1" typeId="cc-m1"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the iTach CC device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache iTach Flex device -->
|
||||
<thing-type id="itachFlex">
|
||||
|
||||
<label>GlobalCache iTach Flex</label>
|
||||
<description>iTach Flex Device</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="sl-m1" typeId="sl-m1"/>
|
||||
<channel-group id="ir-m1" typeId="ir-m1"/>
|
||||
<channel-group id="cc-m1" typeId="cc-m1"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the iTach Flex device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
|
||||
<parameter name="mapFilename" type="text">
|
||||
<label>Map File</label>
|
||||
<description>Enter name of file containing mapping of commands to IR and Serial codes</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="activeCable" type="text" required="true">
|
||||
<label>Active Cable</label>
|
||||
<description>This setting should match the Current Active Cable in the Flex configuration</description>
|
||||
<options>
|
||||
<option value="FLEX_INFRARED">Infrared</option>
|
||||
<option value="FLEX_SERIAL">Serial</option>
|
||||
<option value="FLEX_RELAY">Relay/Sensor</option>
|
||||
</options>
|
||||
<default>FLEX_INFRARED</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="enableTwoWay1" type="boolean">
|
||||
<label>Enable Two Way</label>
|
||||
<description>Enable two-way serial communication</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="eomDelimiter1" type="text">
|
||||
<label>End-of-message Delimiter</label>
|
||||
<description>URL encoded end-of-message delimiter string for receiving messages</description>
|
||||
<default>%0A</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache iTach IR (infrared) device contains one IR module -->
|
||||
<thing-type id="itachIR">
|
||||
|
||||
<label>GlobalCache iTach IR</label>
|
||||
<description>iTach Infrared Device (WF2IR or IP2IR)</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="ir-m1" typeId="ir-m1"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the iTach IR device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
|
||||
<parameter name="mapFilename" type="text">
|
||||
<label>Map File</label>
|
||||
<description>Enter name of file containing mapping of commands to IR and Serial codes</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- GlobalCache iTach SL (serial) device contains one SL module -->
|
||||
<thing-type id="itachSL">
|
||||
|
||||
<label>GlobalCache iTach SL</label>
|
||||
<description>iTach Serial Device (WF2SL or IP2SL)</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="sl-m1" typeId="sl-m1"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the iTach SL device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
|
||||
<parameter name="mapFilename" type="text">
|
||||
<label>Map File</label>
|
||||
<description>Enter namer of file containing mapping of commands to IR and Serial codes</description>
|
||||
</parameter>
|
||||
|
||||
<parameter name="enableTwoWay1" type="boolean">
|
||||
<label>Enable Two Way</label>
|
||||
<description>Enable two-way serial communication</description>
|
||||
<default>false</default>
|
||||
</parameter>
|
||||
|
||||
<parameter name="eomDelimiter1" type="text">
|
||||
<label>End-of-message Delimiter</label>
|
||||
<description>URL encoded end-of-message delimiter string for receiving messages</description>
|
||||
<default>%0A</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="globalcache"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<!-- Zmote IR (infrared) device contains one IR module -->
|
||||
<thing-type id="zmote">
|
||||
|
||||
<label>Zmote IR</label>
|
||||
<description>Zmote Infrared Device</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="ir-m1-c1" typeId="ir-m1-c1"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text" required="true">
|
||||
<label>Network Address</label>
|
||||
<description>Enter the IP address of the Zmote device</description>
|
||||
<context>network-address</context>
|
||||
</parameter>
|
||||
|
||||
<parameter name="mapFilename" type="text">
|
||||
<label>Map File</label>
|
||||
<description>Enter name of file containing mapping of commands to IR codes</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user