added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,38 @@
<?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 excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.ihc</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>

View File

@@ -0,0 +1,30 @@
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
== Third-party Content
Apache HttpCore
* License: Apache License, Version 2.0
* Project: https://hc.apache.org/httpcomponents-core-ga/index.html
* Source: https://github.com/apache/httpcomponents-core/tree/4.4.10
Apache HttpClient
* License: Apache License, Version 2.0
* Project: https://hc.apache.org/httpcomponents-client-ga/index.html
* Source: https://github.com/apache/httpcomponents-client/tree/4.5.6
Apache Commons Logging
* License: Apache License, Version 2.0
* Project: https://commons.apache.org/proper/commons-logging/
* Source: http://svn.apache.org/repos/asf/commons/proper/logging/

View File

@@ -0,0 +1,211 @@
# IHC / ELKO Binding
This binding is for the "Intelligent Home Control" building automation system originally made by LK, but now owned by Schneider Electric and sold as "IHC Intelligent Home Control" or "ELKO living system" depending of the country.
It is based on a star-configured topology with wires to each device.
The system is made up of a central controller and up to 8 input modules and 16 output modules.
Each input module can have 16 digital inputs and each output module 8 digital outputs, resulting in a total of 128 input and 128 outputs per controller.
Controller also support different kind of wireless devices.
User can create application logic to the controller to control inputs and outputs, but also create virtual inputs and output, and function blocks.
The binding can download the project file (application logic file) from the controller.
Binding will also listen to controller state changes, and when the controller state is changed from init to ready state (controller is reprogrammed), the project file will be download again from the controller.
IHC / ELKO LS controller communication interface is SOAP (Simple Object Access Protocol) based, limited to HTTPS transport protocol.
## Supported Things
This binding supports one ThingType: `controller`.
## Thing Configuration
The `controller` Thing has the following configuration parameters:
| Parameter | Description | Required | Default value |
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------|----------|---------------|
| hostname | Network/IP address of the IHC / ELKO controller without https prefix, but can contain TCP port if default port is not used. | yes | |
| username | User name to login to the IHC / ELKO controller. | yes | |
| password | Password to login to the IHC / ELKO controller. | yes | |
| timeout | Timeout in milliseconds to communicate to IHC / ELKO controller. | no | 5000 |
| loadProjectFile | Load project file from controller. | no | true |
| createChannelsAutomatically | Create channels automatically from project file. Project file loading parameter should be enabled as well. | no | true |
## Channels
List of default controller channels.
| Channel | Item Type | Description |
| ------------------- | ------------ | -------------------------------------------------------------- |
| controllerState | String | Displays IHC / ELKO controller state. |
| controllerUptime | Number | Displays IHC / ELKO controller uptime in seconds. |
| controllerTime | DateTime | Displays IHC / ELKO controller date and time |
When `createChannelsAutomatically` parameter is enabled, binding will automatically create channels accordingly to project file.
Binding create channels for dataline_inputs, dataline_outputs, airlink_inputs, airlink_outputs, airlink_relays, airlink_dimmings, resource_temperatures and resource_humidity_levels, and also channels for wireless device signal strengths and low battery warnings.
User can manually add other channels or disable channel auto generation and add all needed channels manually.
List of supported channel types.
| Channel Type | Item Type | Description | Supported channel parameters |
| ------------------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
| switch | Switch | Generic switch channel. | resourceId, direction, commandToReact, pulseWidth, inverted |
| contact | Contact | Generic contact channel. | resourceId, inverted |
| number | Number | Generic number channel. | resourceId, direction, commandToReact, pulseWidth |
| dimmer | Dimmer | Generic dimmer channel. | resourceId, direction, commandToReact, pulseWidth |
| datetime | DateTime | Generic datetime channel. | resourceId, direction, commandToReact, pulseWidth |
| string | String | Generic string (enum) channel. | resourceId, direction, commandToReact, pulseWidth |
| rollershutter | RollerShutter | Generic rollershutter channel. | resourceId, direction, commandToReact, pulseWidth |
| rf-device-low-battery | Switch | RF device low battery warning. | serialNumber |
| rf-device-signal-strength | String | RF device signal strength. | serialNumber |
| push-button-trigger | Trigger | Push button trigger channel. Possible trigger events: PRESSED, RELEASED, SHORT_PRESS, LONG_PRESS and value as a duration in milliseconds. | resourceId, longPressTime |
Channel parameters:
| Channel parameter | Param Type | Required | Default value | Description |
| --------------------- | ------------ | -------- | ------------- | -------------------------------------------------------------------------------------------------------- |
| resourceId | Integer | yes | | Resource Id in decimal format from project file. |
| direction | Text | no | ReadWrite | Direction of the channel (ReadWrite, WriteOnly, ReadOnly). |
| commandToReact | String | no | | Command to react. If not defined, channel react to all commands. |
| pulseWidth | Integer | no | | Pulse width in milliseconds. If defined, binding send pulse rather than command value to IHC controller. |
| inverted | Boolean | no | false | openHAB state is inverted compared to IHC output/input signal. |
| serialNumber | Integer | yes | | Serial number of RF device in decimal format. |
| longPressTime | Integer | yes | 1000 | Long press time in milliseconds. |
There are several ways to find the correct resource id's:
1. Find directly from your IHC / ELKO LS project file (.vis file).
2. Via IHC / ELKO Visual application. Hold ctrl button from keyboard while mouse over the select item in Visual.
3. Enable debug level from binding. Binding will then print basic resource ID from the project file, if `loadProjectFile` configuration variable is enabled.
The binding supports resource id's ***only*** in decimal format.
Hexadecimal values (start with 0x prefix) need to be converted to decimal format.
Conversion can be done e.g. via Calculator in Windows or Mac.
Resource id _0x3f4d14 is 0x3f4d14 in hexadecimal format, which is 4148500 in decimal format.
Mapping table between data types:
| IHC / ELKO data type | openHAB item type | Channel type | Resource id from project file |
|-------------------------|-------------------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| WSFloatingPointValue | Number | number | <resource_temperature id="_0x3f4d14" …> |
| WSIntegerValue | Number, Dimmer | number, dimmer | <airlink_dimming id="_0x3ec5d" …>, <resource_integer id="_0x97e20b" …>, <resource_counter id="_0x97df0c" …> |
| WSBooleanValue | Switch, Contact | switch, contact | <dataline_input id="_0x3f295a" …>, <dataline_output id="_0x3ce35b" …>, <airlink_input id="_0x5b555c" …>, <resource_flag id="_0x97e00a" …> |
| WSTimerValue | Number | number | <resource_timer id="_0x97de10" …> |
| WSWeekdayValue | Number | number | <resource_weekday id="_0x97e109" …> |
| WSEnumValue | String, Number | string, number | <resource_enum id="_0x98050f" …> |
| WSDateValue | DateTime | datetime | <resource_date id="_0x97dd0e" …> |
| WSTimeValue | DateTime | datetime | <resource_time id="_0x97db0d" …> |
## Profiles
Binding provides IHC / ELKO specific `ihc:pushbutton-to-command` profile for `push-button-trigger` channels.
This profile can be used to transforms trigger events to item commands without writing rules.
Profile support following configuration parameters:
| Parameter | Param Type | Required | Default value | Description |
| --------------------- | ------------ | -------- | ------------- | --------------------------------------------------------------------------------------------------------- |
| short-press-command | String | no | ON | Define the command be send when short button press is detected. |
| long-press-command | String | no | INCREASE | Define the command be send when long button press is detected. |
| long-press-time | Integer | no | 1000 | Define the long button press time in milliseconds. |
| repeat-time | Integer | no | 200 | How often long button press command is send in milliseconds. If 0, long press command is sent only ones. |
| timeout | Integer | no | 10000 | Timeout for repeated long press command. Cancel long press command sending when this limit is exceeded. |
Supported commands:
| Command | Supported Item Type |
| ----------- | ------------------- |
| ON | Switch |
| OFF | Switch |
| STOP | Player |
| PLAY | Player |
| PAUSE | Player |
| NEXT | Player |
| PREVIOUS | Player |
| FASTFORWARD | Player |
| REWIND | Player |
| INCREASE | Dimmer |
| DECREASE | Dimmer |
| UP | Rollershutter |
| DOWN | Rollershutter |
| TOGGLE | Switch |
All commands but `TOGGLE` are standard openHAB commands.
When `TOGGLE` command is specified, profile will toggle switch item state.
E.g. if item state has been OFF, profile will send ON command to item.
Example:
```xtend
Dimmer test { channel="ihc:controller:elko:my_test_trigger"[profile="ihc:pushbutton-to-command", short-press-command="TOGGLE", long-press-command="INCREASE", long-press-time=1000, repeat-time=200] }
```
Will send TOGGLE (ON/OFF) command to Dimmer test item when short button press is detected (button press less than 1000ms) and send INCREASE commands as long button is pressed over 1000ms (200ms interval).
## Examples
### example.things
```xtend
ihc:controller:elko [ hostname="192.168.1.2", username="openhab", password="secret", timeout=5000, loadProjectFile=true, createChannelsAutomatically=false ] {
Channels:
Type switch : my_test_switch "My Test Switch" [ resourceId=3988827 ]
Type contact : my_test_contact "My Test Contact" [ resourceId=3988827 ]
Type number : my_test_number "My Test Number" [ resourceId=3988827, direction="ReadOnly" ]
Type rf-device-low-battery : my_low_battery "My Low Battery Warning" [ serialNumber=123456789 ]
Type push-button-trigger : my_test_trigger "My Test Trigger" [ resourceId=3988827, longPressTime=1000 ]
Type dimmer : inc_resource "Increase resource" [ resourceId=9000001, direction="WriteOnly", commandToReact="INCREASE", pulseWidth=300 ]
Type dimmer : dec_resource "Decrease resource" [ resourceId=9000002, direction="WriteOnly", commandToReact="DECREASE", pulseWidth=300 ]
Type number : readonly_resource "Read only resource" [ resourceId=1212121, direction="ReadOnly" ]
Type number : write1_resource "Write 1 resource" [ resourceId=1111111, direction="WriteOnly", commandToReact="1", pulseWidth=300 ]
Type number : write2_resource "Write 2 resource" [ resourceId=2222222, direction="WriteOnly", commandToReact="2", pulseWidth=300 ]
Type number : write3_resource "Write 3 resource" [ resourceId=3333333, direction="WriteOnly", commandToReact="3", pulseWidth=300 ]
}
```
### example.items
```xtend
Switch test_switch "Test Switch" { channel="ihc:controller:elko:my_test_switch" }
Switch test_contact "Test Contact" { channel="ihc:controller:elko:my_test_contact" }
Number test_number "Test Number" { channel="ihc:controller:elko:my_test_number" }
Switch low_battery "Low Battery" { channel="ihc:controller:elko:my_low_battery" }
Dimmer test_dimmer "Test Dimmer" { channel="ihc:controller:elko:inc_resource", channel="ihc:controller:elko:dec_resource" }
Number multi_resource_test "Multi resource test" { channel="ihc:controller:elko:readonly_resource", channel="ihc:controller:elko:write1_resource", channel="ihc:controller:elko:write2_resource", channel="ihc:controller:elko:write3_resource" }
Dimmer dimmer { channel="ihc:controller:elko:my_test_trigger"[profile="ihc:pushbutton-to-command", short-press-command="TOGGLE", long-press-command="INCREASE", long-press-time=1000, repeat-time=200] }
```
### example.rules
```xtend
rule "My test trigger test rule"
when
Channel 'ihc:controller:elko:my_test_trigger' triggered LONG_PRESS
then
logInfo("Test","Long press detected")
end
rule "My test trigger test rule 2"
when
Channel 'ihc:controller:elko:my_test_trigger' triggered
then
val String e = receivedEvent.toString.split(' ').get(2).toString
switch e {
case "PRESSED": { logInfo("Test","Button pressed") }
case "RELEASED": { logInfo("Test","Button released") }
case "SHORT_PRESS": { logInfo("Test","Button short press") }
case "LONG_PRESS": { logInfo("Test","Button long press") }
default: { logInfo("Test","Button pressed {}ms", e) }
}
end
```
### Thing status
Check thing status for errors.

View File

@@ -0,0 +1,336 @@
<?xml version='1.0' encoding='UTF-8'?>
<wsdl:definitions targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsdl:types>
<xsd:schema targetNamespace="utcs" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:element name="enterRFConfiguration1" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="exitRFConfiguration1" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="enterRFTest1" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="exitRFTest1" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="testRFActuatorWithSerialNumber1" nillable="true" type="xsd:long">
</xsd:element>
<xsd:element name="testRFActuatorWithSerialNumber2" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="waitForDeviceDetected1" nillable="true" type="xsd:int">
</xsd:element>
<xsd:complexType name="WSRFDevice">
<xsd:sequence>
<xsd:element name="batteryLevel" type="xsd:int">
</xsd:element>
<xsd:element name="deviceType" type="xsd:int">
</xsd:element>
<xsd:element name="serialNumber" type="xsd:long">
</xsd:element>
<xsd:element name="signalStrength" type="xsd:int">
</xsd:element>
<xsd:element name="version" type="xsd:int">
</xsd:element>
<xsd:element name="detected" type="xsd:boolean">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="waitForDeviceDetected2" nillable="true" type="tns:WSRFDevice">
</xsd:element>
<xsd:element name="waitForDeviceTestResult1" nillable="true" type="xsd:int">
</xsd:element>
<xsd:element name="waitForDeviceTestResult2" nillable="true" type="tns:WSRFDevice">
</xsd:element>
<xsd:complexType name="ArrayOfWSRFDevice">
<xsd:sequence>
<xsd:element name="arrayItem" maxOccurs="unbounded" nillable="true" type="tns:WSRFDevice">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getDetectedDeviceList1" nillable="true" type="tns:ArrayOfWSRFDevice">
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="enterRFConfigurationRequest">
</wsdl:message>
<wsdl:message name="enterRFConfigurationResponse">
<wsdl:part name="return" element="tns:enterRFConfiguration1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="exitRFConfigurationRequest">
</wsdl:message>
<wsdl:message name="exitRFConfigurationResponse">
<wsdl:part name="return" element="tns:exitRFConfiguration1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="enterRFTestRequest">
</wsdl:message>
<wsdl:message name="enterRFTestResponse">
<wsdl:part name="return" element="tns:enterRFTest1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="exitRFTestRequest">
</wsdl:message>
<wsdl:message name="exitRFTestResponse">
<wsdl:part name="return" element="tns:exitRFTest1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="testRFActuatorWithSerialNumberRequest">
<wsdl:part name="parameter1" element="tns:testRFActuatorWithSerialNumber1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="testRFActuatorWithSerialNumberResponse">
<wsdl:part name="return" element="tns:testRFActuatorWithSerialNumber2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="waitForDeviceDetectedRequest">
<wsdl:part name="parameter2" element="tns:waitForDeviceDetected1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="waitForDeviceDetectedResponse">
<wsdl:part name="return" element="tns:waitForDeviceDetected2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="waitForDeviceTestResultRequest">
<wsdl:part name="parameter3" element="tns:waitForDeviceTestResult1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="waitForDeviceTestResultResponse">
<wsdl:part name="return" element="tns:waitForDeviceTestResult2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getDetectedDeviceListRequest">
</wsdl:message>
<wsdl:message name="getDetectedDeviceListResponse">
<wsdl:part name="return" element="tns:getDetectedDeviceList1">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="AirlinkManagementService">
<wsdl:operation name="enterRFConfiguration">
<wsdl:input name="inputMessageName1" message="tns:enterRFConfigurationRequest">
</wsdl:input>
<wsdl:output name="outputMessageName1" message="tns:enterRFConfigurationResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="exitRFConfiguration">
<wsdl:input name="inputMessageName2" message="tns:exitRFConfigurationRequest">
</wsdl:input>
<wsdl:output name="outputMessageName2" message="tns:exitRFConfigurationResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="enterRFTest">
<wsdl:input name="inputMessageName3" message="tns:enterRFTestRequest">
</wsdl:input>
<wsdl:output name="outputMessageName3" message="tns:enterRFTestResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="exitRFTest">
<wsdl:input name="inputMessageName4" message="tns:exitRFTestRequest">
</wsdl:input>
<wsdl:output name="outputMessageName4" message="tns:exitRFTestResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="testRFActuatorWithSerialNumber">
<wsdl:input name="inputMessageName5" message="tns:testRFActuatorWithSerialNumberRequest">
</wsdl:input>
<wsdl:output name="outputMessageName5" message="tns:testRFActuatorWithSerialNumberResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="waitForDeviceDetected">
<wsdl:input name="inputMessageName6" message="tns:waitForDeviceDetectedRequest">
</wsdl:input>
<wsdl:output name="outputMessageName6" message="tns:waitForDeviceDetectedResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="waitForDeviceTestResult">
<wsdl:input name="inputMessageName7" message="tns:waitForDeviceTestResultRequest">
</wsdl:input>
<wsdl:output name="outputMessageName7" message="tns:waitForDeviceTestResultResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getDetectedDeviceList">
<wsdl:input name="inputMessageName8" message="tns:getDetectedDeviceListRequest">
</wsdl:input>
<wsdl:output name="outputMessageName8" message="tns:getDetectedDeviceListResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="AirlinkManagementServiceBinding" type="tns:AirlinkManagementService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<wsdl:operation name="enterRFConfiguration">
<soap:operation soapAction="enterRFConfiguration" style="document">
</soap:operation>
<wsdl:input name="inputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="exitRFConfiguration">
<soap:operation soapAction="exitRFConfiguration" style="document">
</soap:operation>
<wsdl:input name="inputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="enterRFTest">
<soap:operation soapAction="enterRFTest" style="document">
</soap:operation>
<wsdl:input name="inputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="exitRFTest">
<soap:operation soapAction="exitRFTest" style="document">
</soap:operation>
<wsdl:input name="inputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="testRFActuatorWithSerialNumber">
<soap:operation soapAction="testRFActuatorWithSerialNumber" style="document">
</soap:operation>
<wsdl:input name="inputMessageName5">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName5">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="waitForDeviceDetected">
<soap:operation soapAction="waitForDeviceDetected" style="document">
</soap:operation>
<wsdl:input name="inputMessageName6">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName6">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="waitForDeviceTestResult">
<soap:operation soapAction="waitForDeviceTestResult" style="document">
</soap:operation>
<wsdl:input name="inputMessageName7">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName7">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getDetectedDeviceList">
<soap:operation soapAction="getDetectedDeviceList" style="document">
</soap:operation>
<wsdl:input name="inputMessageName8">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName8">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="AirlinkManagementServiceService">
<wsdl:port name="AirlinkManagementServiceBindingPort" binding="tns:AirlinkManagementServiceBinding">
<soap:address location="http://localhost/AirlinkManagementService">
</soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="utcs">
<xsd:element name="ping1" nillable="true" type="xsd:boolean" />
<xsd:complexType name="WSAuthenticationData">
<xsd:sequence>
<xsd:element name="password" type="xsd:string" />
<xsd:element name="username" type="xsd:string" />
<xsd:element name="application" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="authenticate1" nillable="true" type="tns:WSAuthenticationData" />
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="day" type="xsd:int" />
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int" />
<xsd:element name="hours" type="xsd:int" />
<xsd:element name="minutes" type="xsd:int" />
<xsd:element name="seconds" type="xsd:int" />
<xsd:element name="year" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSUserGroup">
<xsd:sequence>
<xsd:element name="type" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSUser">
<xsd:sequence>
<xsd:element name="createdDate" nillable="true" type="tns:WSDate" />
<xsd:element name="loginDate" nillable="true" type="tns:WSDate" />
<xsd:element name="username" type="xsd:string" />
<xsd:element name="password" type="xsd:string" />
<xsd:element name="email" type="xsd:string" />
<xsd:element name="firstname" type="xsd:string" />
<xsd:element name="lastname" type="xsd:string" />
<xsd:element name="phone" type="xsd:string" />
<xsd:element name="group" nillable="true" type="tns:WSUserGroup" />
<xsd:element name="project" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSLoginResult">
<xsd:sequence>
<xsd:element name="loggedInUser" nillable="true" type="tns:WSUser" />
<xsd:element name="loginWasSuccessful" type="xsd:boolean" />
<xsd:element name="loginFailedDueToConnectionRestrictions" type="xsd:boolean" />
<xsd:element name="loginFailedDueToInsufficientUserRights" type="xsd:boolean" />
<xsd:element name="loginFailedDueToAccountInvalid" type="xsd:boolean" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="authenticate2" nillable="true" type="tns:WSLoginResult" />
<xsd:element name="disconnect1" nillable="true" type="xsd:boolean" />
</xsd:schema>
</wsdl:types>
<wsdl:message name="pingRequest" />
<wsdl:message name="pingResponse">
<wsdl:part name="return" element="tns:ping1" />
</wsdl:message>
<wsdl:message name="authenticateRequest">
<wsdl:part name="parameter1" element="tns:authenticate1" />
</wsdl:message>
<wsdl:message name="authenticateResponse">
<wsdl:part name="return" element="tns:authenticate2" />
</wsdl:message>
<wsdl:message name="disconnectRequest" />
<wsdl:message name="disconnectResponse">
<wsdl:part name="return" element="tns:disconnect1" />
</wsdl:message>
<wsdl:portType name="AuthenticationService">
<wsdl:operation name="ping">
<wsdl:input name="inputMessageName1" message="tns:pingRequest" />
<wsdl:output name="outputMessageName1" message="tns:pingResponse" />
</wsdl:operation>
<wsdl:operation name="authenticate">
<wsdl:input name="inputMessageName2" message="tns:authenticateRequest" />
<wsdl:output name="outputMessageName2" message="tns:authenticateResponse" />
</wsdl:operation>
<wsdl:operation name="disconnect">
<wsdl:input name="inputMessageName3" message="tns:disconnectRequest" />
<wsdl:output name="outputMessageName3" message="tns:disconnectResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="AuthenticationServiceBinding" type="tns:AuthenticationService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="ping">
<soap:operation soapAction="ping" style="document" />
<wsdl:input name="inputMessageName1">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="authenticate">
<soap:operation soapAction="authenticate" style="document" />
<wsdl:input name="inputMessageName2">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="disconnect">
<soap:operation soapAction="disconnect" style="document" />
<wsdl:input name="inputMessageName3">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="AuthenticationServiceService">
<wsdl:port name="AuthenticationServiceBindingPort" binding="tns:AuthenticationServiceBinding">
<soap:address location="http://localhost/AuthenticationService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,288 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="utcs">
<xsd:complexType name="WSControllerState">
<xsd:sequence>
<xsd:element name="state" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getState1" nillable="true" type="tns:WSControllerState" />
<xsd:element name="enterProjectChangeMode1" nillable="true" type="xsd:boolean" />
<xsd:element name="exitProjectChangeMode1" nillable="true" type="xsd:boolean" />
<xsd:element name="isIHCProjectAvailable1" nillable="true" type="xsd:boolean" />
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="hours" type="xsd:int" />
<xsd:element name="minutes" type="xsd:int" />
<xsd:element name="seconds" type="xsd:int" />
<xsd:element name="year" type="xsd:int" />
<xsd:element name="day" type="xsd:int" />
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSProjectInfo">
<xsd:sequence>
<xsd:element name="visualMinorVersion" type="xsd:int" />
<xsd:element name="visualMajorVersion" type="xsd:int" />
<xsd:element name="projectMajorRevision" type="xsd:int" />
<xsd:element name="projectMinorRevision" type="xsd:int" />
<xsd:element name="lastmodified" nillable="true" type="tns:WSDate" />
<xsd:element name="projectNumber" type="xsd:string" />
<xsd:element name="customerName" type="xsd:string" />
<xsd:element name="installerName" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getProjectInfo1" nillable="true" type="tns:WSProjectInfo" />
<xsd:element name="getIHCProjectSegment1" nillable="true" type="xsd:int" />
<xsd:element name="getIHCProjectSegment2" nillable="true" type="xsd:int" />
<xsd:element name="getIHCProjectSegment3" nillable="true" type="xsd:int" />
<xsd:complexType name="WSFile">
<xsd:sequence>
<xsd:element name="data" type="xsd:base64Binary" />
<xsd:element name="filename" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getIHCProjectSegment4" nillable="true" type="tns:WSFile" />
<xsd:element name="storeIHCProjectSegment1" nillable="true" type="tns:WSFile" />
<xsd:element name="storeIHCProjectSegment2" nillable="true" type="xsd:int" />
<xsd:element name="storeIHCProjectSegment3" nillable="true" type="xsd:int" />
<xsd:element name="storeIHCProjectSegment4" nillable="true" type="xsd:boolean" />
<xsd:element name="getIHCProjectSegmentationSize1" nillable="true" type="xsd:int" />
<xsd:element name="getIHCProjectNumberOfSegments1" nillable="true" type="xsd:int" />
<xsd:element name="getIHCProject1" nillable="true" type="tns:WSFile" />
<xsd:element name="storeIHCProject1" nillable="true" type="tns:WSFile" />
<xsd:element name="storeIHCProject2" nillable="true" type="xsd:boolean" />
<xsd:element name="waitForControllerStateChange1" nillable="true" type="tns:WSControllerState" />
<xsd:element name="waitForControllerStateChange2" nillable="true" type="xsd:int" />
<xsd:element name="waitForControllerStateChange3" nillable="true" type="tns:WSControllerState" />
</xsd:schema>
</wsdl:types>
<wsdl:message name="getStateRequest" />
<wsdl:message name="getStateResponse">
<wsdl:part name="return" element="tns:getState1" />
</wsdl:message>
<wsdl:message name="enterProjectChangeModeRequest" />
<wsdl:message name="enterProjectChangeModeResponse">
<wsdl:part name="return" element="tns:enterProjectChangeMode1" />
</wsdl:message>
<wsdl:message name="exitProjectChangeModeRequest" />
<wsdl:message name="exitProjectChangeModeResponse">
<wsdl:part name="return" element="tns:exitProjectChangeMode1" />
</wsdl:message>
<wsdl:message name="isIHCProjectAvailableRequest" />
<wsdl:message name="isIHCProjectAvailableResponse">
<wsdl:part name="return" element="tns:isIHCProjectAvailable1" />
</wsdl:message>
<wsdl:message name="getProjectInfoRequest" />
<wsdl:message name="getProjectInfoResponse">
<wsdl:part name="return" element="tns:getProjectInfo1" />
</wsdl:message>
<wsdl:message name="getIHCProjectSegmentRequest">
<wsdl:part name="parameter1" element="tns:getIHCProjectSegment1" />
<wsdl:part name="parameter2" element="tns:getIHCProjectSegment2" />
<wsdl:part name="parameter3" element="tns:getIHCProjectSegment3" />
</wsdl:message>
<wsdl:message name="getIHCProjectSegmentResponse">
<wsdl:part name="return" element="tns:getIHCProjectSegment4" />
</wsdl:message>
<wsdl:message name="storeIHCProjectSegmentRequest">
<wsdl:part name="parameter4" element="tns:storeIHCProjectSegment1" />
<wsdl:part name="parameter5" element="tns:storeIHCProjectSegment2" />
<wsdl:part name="parameter6" element="tns:storeIHCProjectSegment3" />
</wsdl:message>
<wsdl:message name="storeIHCProjectSegmentResponse">
<wsdl:part name="return" element="tns:storeIHCProjectSegment4" />
</wsdl:message>
<wsdl:message name="getIHCProjectSegmentationSizeRequest" />
<wsdl:message name="getIHCProjectSegmentationSizeResponse">
<wsdl:part name="return" element="tns:getIHCProjectSegmentationSize1" />
</wsdl:message>
<wsdl:message name="getIHCProjectNumberOfSegmentsRequest" />
<wsdl:message name="getIHCProjectNumberOfSegmentsResponse">
<wsdl:part name="return" element="tns:getIHCProjectNumberOfSegments1" />
</wsdl:message>
<wsdl:message name="getIHCProjectRequest" />
<wsdl:message name="getIHCProjectResponse">
<wsdl:part name="return" element="tns:getIHCProject1" />
</wsdl:message>
<wsdl:message name="storeIHCProjectRequest">
<wsdl:part name="parameter7" element="tns:storeIHCProject1" />
</wsdl:message>
<wsdl:message name="storeIHCProjectResponse">
<wsdl:part name="return" element="tns:storeIHCProject2" />
</wsdl:message>
<wsdl:message name="waitForControllerStateChangeRequest">
<wsdl:part name="parameter8" element="tns:waitForControllerStateChange1" />
<wsdl:part name="parameter9" element="tns:waitForControllerStateChange2" />
</wsdl:message>
<wsdl:message name="waitForControllerStateChangeResponse">
<wsdl:part name="return" element="tns:waitForControllerStateChange3" />
</wsdl:message>
<wsdl:portType name="ControllerService">
<wsdl:operation name="getState">
<wsdl:input name="inputMessageName1" message="tns:getStateRequest" />
<wsdl:output name="outputMessageName1" message="tns:getStateResponse" />
</wsdl:operation>
<wsdl:operation name="enterProjectChangeMode">
<wsdl:input name="inputMessageName2" message="tns:enterProjectChangeModeRequest" />
<wsdl:output name="outputMessageName2" message="tns:enterProjectChangeModeResponse" />
</wsdl:operation>
<wsdl:operation name="exitProjectChangeMode">
<wsdl:input name="inputMessageName3" message="tns:exitProjectChangeModeRequest" />
<wsdl:output name="outputMessageName3" message="tns:exitProjectChangeModeResponse" />
</wsdl:operation>
<wsdl:operation name="isIHCProjectAvailable">
<wsdl:input name="inputMessageName4" message="tns:isIHCProjectAvailableRequest" />
<wsdl:output name="outputMessageName4" message="tns:isIHCProjectAvailableResponse" />
</wsdl:operation>
<wsdl:operation name="getProjectInfo">
<wsdl:input name="inputMessageName5" message="tns:getProjectInfoRequest" />
<wsdl:output name="outputMessageName5" message="tns:getProjectInfoResponse" />
</wsdl:operation>
<wsdl:operation name="getIHCProjectSegment">
<wsdl:input name="inputMessageName6" message="tns:getIHCProjectSegmentRequest" />
<wsdl:output name="outputMessageName6" message="tns:getIHCProjectSegmentResponse" />
</wsdl:operation>
<wsdl:operation name="storeIHCProjectSegment">
<wsdl:input name="inputMessageName7" message="tns:storeIHCProjectSegmentRequest" />
<wsdl:output name="outputMessageName7" message="tns:storeIHCProjectSegmentResponse" />
</wsdl:operation>
<wsdl:operation name="getIHCProjectSegmentationSize">
<wsdl:input name="inputMessageName8" message="tns:getIHCProjectSegmentationSizeRequest" />
<wsdl:output name="outputMessageName8" message="tns:getIHCProjectSegmentationSizeResponse" />
</wsdl:operation>
<wsdl:operation name="getIHCProjectNumberOfSegments">
<wsdl:input name="inputMessageName9" message="tns:getIHCProjectNumberOfSegmentsRequest" />
<wsdl:output name="outputMessageName9" message="tns:getIHCProjectNumberOfSegmentsResponse" />
</wsdl:operation>
<wsdl:operation name="getIHCProject">
<wsdl:input name="inputMessageName10" message="tns:getIHCProjectRequest" />
<wsdl:output name="outputMessageName10" message="tns:getIHCProjectResponse" />
</wsdl:operation>
<wsdl:operation name="storeIHCProject">
<wsdl:input name="inputMessageName11" message="tns:storeIHCProjectRequest" />
<wsdl:output name="outputMessageName11" message="tns:storeIHCProjectResponse" />
</wsdl:operation>
<wsdl:operation name="waitForControllerStateChange">
<wsdl:input name="inputMessageName12" message="tns:waitForControllerStateChangeRequest" />
<wsdl:output name="outputMessageName12" message="tns:waitForControllerStateChangeResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ControllerServiceBinding" type="tns:ControllerService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="getState">
<soap:operation soapAction="getState" style="document" />
<wsdl:input name="inputMessageName1">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="enterProjectChangeMode">
<soap:operation soapAction="enterProjectChangeMode" style="document" />
<wsdl:input name="inputMessageName2">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="exitProjectChangeMode">
<soap:operation soapAction="exitProjectChangeMode" style="document" />
<wsdl:input name="inputMessageName3">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="isIHCProjectAvailable">
<soap:operation soapAction="isIHCProjectAvailable" style="document" />
<wsdl:input name="inputMessageName4">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName4">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getProjectInfo">
<soap:operation soapAction="getProjectInfo" style="document" />
<wsdl:input name="inputMessageName5">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName5">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getIHCProjectSegment">
<soap:operation soapAction="getIHCProjectSegment" style="document" />
<wsdl:input name="inputMessageName6">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName6">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="storeIHCProjectSegment">
<soap:operation soapAction="storeIHCProjectSegment" style="document" />
<wsdl:input name="inputMessageName7">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName7">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getIHCProjectSegmentationSize">
<soap:operation soapAction="getIHCProjectSegmentationSize" style="document" />
<wsdl:input name="inputMessageName8">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName8">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getIHCProjectNumberOfSegments">
<soap:operation soapAction="getIHCProjectNumberOfSegments" style="document" />
<wsdl:input name="inputMessageName9">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName9">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getIHCProject">
<soap:operation soapAction="getIHCProject" style="document" />
<wsdl:input name="inputMessageName10">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName10">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="storeIHCProject">
<soap:operation soapAction="storeIHCProject" style="document" />
<wsdl:input name="inputMessageName11">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName11">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="waitForControllerStateChange">
<soap:operation soapAction="waitForControllerStateChange" style="document" />
<wsdl:input name="inputMessageName12">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName12">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ControllerServiceService">
<wsdl:port name="ControllerServiceBindingPort" binding="tns:ControllerServiceBinding">
<soap:address location="http://localhost/ControllerService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsdl:types>
<xsd:schema targetNamespace="utcs" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="day" type="xsd:int">
</xsd:element>
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int">
</xsd:element>
<xsd:element name="hours" type="xsd:int">
</xsd:element>
<xsd:element name="minutes" type="xsd:int">
</xsd:element>
<xsd:element name="seconds" type="xsd:int">
</xsd:element>
<xsd:element name="year" type="xsd:int">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSEmailAddress">
<xsd:sequence>
<xsd:element name="address" type="xsd:string">
</xsd:element>
<xsd:element name="description" type="xsd:string">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSEmailControlLogEntry">
<xsd:sequence>
<xsd:element name="date" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="logEntryType" type="xsd:int">
</xsd:element>
<xsd:element name="senderAddress" nillable="true" type="tns:WSEmailAddress">
</xsd:element>
<xsd:element name="triggerString" type="xsd:string">
</xsd:element>
<xsd:element name="authenticationTypeAsString" type="xsd:string">
</xsd:element>
<xsd:element name="actionTypeAsString" type="xsd:string">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSEmailControlLogEntry">
<xsd:sequence>
<xsd:element name="arrayItem" maxOccurs="unbounded" nillable="true" type="tns:WSEmailControlLogEntry">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getEvents1" nillable="true" type="tns:ArrayOfWSEmailControlLogEntry">
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="emptyLogRequest">
</wsdl:message>
<wsdl:message name="emptyLogResponse">
</wsdl:message>
<wsdl:message name="getEventsRequest">
</wsdl:message>
<wsdl:message name="getEventsResponse">
<wsdl:part name="return" element="tns:getEvents1">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="EmailControlLogService">
<wsdl:operation name="emptyLog">
<wsdl:input name="inputMessageName1" message="tns:emptyLogRequest">
</wsdl:input>
<wsdl:output name="outputMessageName1" message="tns:emptyLogResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getEvents">
<wsdl:input name="inputMessageName2" message="tns:getEventsRequest">
</wsdl:input>
<wsdl:output name="outputMessageName2" message="tns:getEventsResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="EmailControlLogServiceBinding" type="tns:EmailControlLogService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<wsdl:operation name="emptyLog">
<soap:operation soapAction="emptyLog" style="document">
</soap:operation>
<wsdl:input name="inputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getEvents">
<soap:operation soapAction="getEvents" style="document">
</soap:operation>
<wsdl:input name="inputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="EmailControlLogServiceService">
<wsdl:port name="EmailControlLogServiceBindingPort" binding="tns:EmailControlLogServiceBinding">
<soap:address location="http://localhost/EmailControlLogService">
</soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,349 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsdl:types>
<xsd:schema targetNamespace="utcs" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="day" type="xsd:int">
</xsd:element>
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int">
</xsd:element>
<xsd:element name="hours" type="xsd:int">
</xsd:element>
<xsd:element name="minutes" type="xsd:int">
</xsd:element>
<xsd:element name="seconds" type="xsd:int">
</xsd:element>
<xsd:element name="year" type="xsd:int">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSSceneProjectInfo">
<xsd:sequence>
<xsd:element name="version" type="xsd:string">
</xsd:element>
<xsd:element name="lastmodified" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="filepath" type="xsd:string">
</xsd:element>
<xsd:element name="remote" type="xsd:boolean">
</xsd:element>
<xsd:element name="created" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="name" type="xsd:string">
</xsd:element>
<xsd:element name="size" type="xsd:int">
</xsd:element>
<xsd:element name="description" type="xsd:string">
</xsd:element>
<xsd:element name="crc" type="xsd:long">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getSceneProjectInfo1" nillable="true" type="tns:WSSceneProjectInfo">
</xsd:element>
<xsd:element name="getSceneProject1" nillable="true" type="xsd:string">
</xsd:element>
<xsd:complexType name="WSFile">
<xsd:sequence>
<xsd:element name="filename" type="xsd:string">
</xsd:element>
<xsd:element name="data" type="xsd:base64Binary">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getSceneProject2" nillable="true" type="tns:WSFile">
</xsd:element>
<xsd:element name="storeSceneProject1" nillable="true" type="tns:WSFile">
</xsd:element>
<xsd:element name="getSceneProjectSegment1" nillable="true" type="xsd:string">
</xsd:element>
<xsd:element name="getSceneProjectSegment2" nillable="true" type="xsd:int">
</xsd:element>
<xsd:element name="getSceneProjectSegment3" nillable="true" type="tns:WSFile">
</xsd:element>
<xsd:element name="storeSceneProjectSegment1" nillable="true" type="tns:WSFile">
</xsd:element>
<xsd:element name="storeSceneProjectSegment2" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="storeSceneProjectSegment3" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="storeSceneProjectSegment4" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="getSceneProjectSegmentationSize1" nillable="true" type="xsd:int">
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="clearAllRequest">
</wsdl:message>
<wsdl:message name="clearAllResponse">
</wsdl:message>
<wsdl:message name="getSceneProjectInfoRequest">
</wsdl:message>
<wsdl:message name="getSceneProjectInfoResponse">
<wsdl:part name="return" element="tns:getSceneProjectInfo1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getSceneProjectRequest">
<wsdl:part name="parameter1" element="tns:getSceneProject1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getSceneProjectResponse">
<wsdl:part name="return" element="tns:getSceneProject2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="storeSceneProjectRequest">
<wsdl:part name="parameter2" element="tns:storeSceneProject1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="storeSceneProjectResponse">
</wsdl:message>
<wsdl:message name="getSceneProjectSegmentRequest">
<wsdl:part name="parameter3" element="tns:getSceneProjectSegment1">
</wsdl:part>
<wsdl:part name="parameter4" element="tns:getSceneProjectSegment2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getSceneProjectSegmentResponse">
<wsdl:part name="return" element="tns:getSceneProjectSegment3">
</wsdl:part>
</wsdl:message>
<wsdl:message name="storeSceneProjectSegmentRequest">
<wsdl:part name="parameter5" element="tns:storeSceneProjectSegment1">
</wsdl:part>
<wsdl:part name="parameter6" element="tns:storeSceneProjectSegment2">
</wsdl:part>
<wsdl:part name="parameter7" element="tns:storeSceneProjectSegment3">
</wsdl:part>
</wsdl:message>
<wsdl:message name="storeSceneProjectSegmentResponse">
<wsdl:part name="return" element="tns:storeSceneProjectSegment4">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getSceneProjectSegmentationSizeRequest">
</wsdl:message>
<wsdl:message name="getSceneProjectSegmentationSizeResponse">
<wsdl:part name="return" element="tns:getSceneProjectSegmentationSize1">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="ModuleService">
<wsdl:operation name="clearAll">
<wsdl:input name="inputMessageName1" message="tns:clearAllRequest">
</wsdl:input>
<wsdl:output name="outputMessageName1" message="tns:clearAllResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProjectInfo">
<wsdl:input name="inputMessageName2" message="tns:getSceneProjectInfoRequest">
</wsdl:input>
<wsdl:output name="outputMessageName2" message="tns:getSceneProjectInfoResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProject">
<wsdl:input name="inputMessageName3" message="tns:getSceneProjectRequest">
</wsdl:input>
<wsdl:output name="outputMessageName3" message="tns:getSceneProjectResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="storeSceneProject">
<wsdl:input name="inputMessageName4" message="tns:storeSceneProjectRequest">
</wsdl:input>
<wsdl:output name="outputMessageName4" message="tns:storeSceneProjectResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProjectSegment">
<wsdl:input name="inputMessageName5" message="tns:getSceneProjectSegmentRequest">
</wsdl:input>
<wsdl:output name="outputMessageName5" message="tns:getSceneProjectSegmentResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="storeSceneProjectSegment">
<wsdl:input name="inputMessageName6" message="tns:storeSceneProjectSegmentRequest">
</wsdl:input>
<wsdl:output name="outputMessageName6" message="tns:storeSceneProjectSegmentResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProjectSegmentationSize">
<wsdl:input name="inputMessageName7" message="tns:getSceneProjectSegmentationSizeRequest">
</wsdl:input>
<wsdl:output name="outputMessageName7" message="tns:getSceneProjectSegmentationSizeResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ModuleServiceBinding" type="tns:ModuleService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<wsdl:operation name="clearAll">
<soap:operation soapAction="clearAll" style="document">
</soap:operation>
<wsdl:input name="inputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProjectInfo">
<soap:operation soapAction="getSceneProjectInfo" style="document">
</soap:operation>
<wsdl:input name="inputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProject">
<soap:operation soapAction="getSceneProject" style="document">
</soap:operation>
<wsdl:input name="inputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="storeSceneProject">
<soap:operation soapAction="storeSceneProject" style="document">
</soap:operation>
<wsdl:input name="inputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProjectSegment">
<soap:operation soapAction="getSceneProjectSegment" style="document">
</soap:operation>
<wsdl:input name="inputMessageName5">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName5">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="storeSceneProjectSegment">
<soap:operation soapAction="storeSceneProjectSegment" style="document">
</soap:operation>
<wsdl:input name="inputMessageName6">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName6">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneProjectSegmentationSize">
<soap:operation soapAction="getSceneProjectSegmentationSize" style="document">
</soap:operation>
<wsdl:input name="inputMessageName7">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName7">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ModuleServiceService">
<wsdl:port name="ModuleServiceBindingPort" binding="tns:ModuleServiceBinding">
<soap:address location="http://localhost/ModuleService">
</soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsdl:types>
<xsd:schema targetNamespace="utcs" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="day" type="xsd:int">
</xsd:element>
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int">
</xsd:element>
<xsd:element name="hours" type="xsd:int">
</xsd:element>
<xsd:element name="minutes" type="xsd:int">
</xsd:element>
<xsd:element name="seconds" type="xsd:int">
</xsd:element>
<xsd:element name="year" type="xsd:int">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSNotificationMessage">
<xsd:sequence>
<xsd:element name="date" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="recipient" type="xsd:string">
</xsd:element>
<xsd:element name="sender" type="xsd:string">
</xsd:element>
<xsd:element name="subject" type="xsd:string">
</xsd:element>
<xsd:element name="body" type="xsd:string">
</xsd:element>
<xsd:element name="delivered" type="xsd:boolean">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSNotificationMessage">
<xsd:sequence>
<xsd:element name="arrayItem" maxOccurs="unbounded" nillable="true" type="tns:WSNotificationMessage">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getMessages1" nillable="true" type="tns:ArrayOfWSNotificationMessage">
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getMessagesRequest">
</wsdl:message>
<wsdl:message name="getMessagesResponse">
<wsdl:part name="return" element="tns:getMessages1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="clearMessagesRequest">
</wsdl:message>
<wsdl:message name="clearMessagesResponse">
</wsdl:message>
<wsdl:portType name="NotificationManagerService">
<wsdl:operation name="getMessages">
<wsdl:input name="inputMessageName1" message="tns:getMessagesRequest">
</wsdl:input>
<wsdl:output name="outputMessageName1" message="tns:getMessagesResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="clearMessages">
<wsdl:input name="inputMessageName2" message="tns:clearMessagesRequest">
</wsdl:input>
<wsdl:output name="outputMessageName2" message="tns:clearMessagesResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="NotificationManagerServiceBinding" type="tns:NotificationManagerService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<wsdl:operation name="getMessages">
<soap:operation soapAction="getMessages" style="document">
</soap:operation>
<wsdl:input name="inputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="clearMessages">
<soap:operation soapAction="clearMessages" style="document">
</soap:operation>
<wsdl:input name="inputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="NotificationManagerServiceService">
<wsdl:port name="NotificationManagerServiceBindingPort" binding="tns:NotificationManagerServiceBinding">
<soap:address location="http://localhost/NotificationManagerService">
</soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,588 @@
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wpNS1="utcs.values" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="utcs">
<xsd:import namespace="utcs.values" />
<xsd:element name="getRuntimeValue1" nillable="true" type="xsd:int" />
<xsd:complexType name="WSResourceValueEnvelope">
<xsd:sequence>
<xsd:element name="value" nillable="true" type="wpNS1:WSResourceValue" />
<xsd:element name="typeString" type="xsd:string" />
<xsd:element name="resourceID" type="xsd:int" />
<xsd:element name="isValueRuntime" type="xsd:boolean" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getRuntimeValue2" nillable="true" type="tns:WSResourceValueEnvelope" />
<xsd:element name="getRuntimeValues1" nillable="true" type="xsd:ArrayOfint" />
<xsd:complexType name="ArrayOfWSResourceValueEnvelope">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="arrayItem" nillable="true" type="tns:WSResourceValueEnvelope" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getRuntimeValues2" nillable="true" type="tns:ArrayOfWSResourceValueEnvelope" />
<xsd:element name="getInitialValue1" nillable="true" type="xsd:int" />
<xsd:element name="getInitialValue2" nillable="true" type="tns:WSResourceValueEnvelope" />
<xsd:element name="getInitialValues1" nillable="true" type="xsd:ArrayOfint" />
<xsd:element name="getInitialValues2" nillable="true" type="tns:ArrayOfWSResourceValueEnvelope" />
<xsd:element name="setResourceValue1" nillable="true" type="tns:WSResourceValueEnvelope" />
<xsd:element name="setResourceValue2" nillable="true" type="xsd:boolean" />
<xsd:element name="setResourceValues1" nillable="true" type="tns:ArrayOfWSResourceValueEnvelope" />
<xsd:element name="setResourceValues2" nillable="true" type="xsd:boolean" />
<xsd:element name="enableRuntimeValueNotifications1" nillable="true" type="xsd:ArrayOfint" />
<xsd:element name="enableRuntimeValueNotifications2" nillable="true" type="tns:ArrayOfWSResourceValueEnvelope" />
<xsd:element name="disableRuntimeValueNotifactions1" nillable="true" type="xsd:ArrayOfint" />
<xsd:element name="disableRuntimeValueNotifactions2" nillable="true" type="xsd:boolean" />
<xsd:element name="enableInitialValueNotifications1" nillable="true" type="xsd:ArrayOfint" />
<xsd:element name="enableInitialValueNotifications2" nillable="true" type="tns:ArrayOfWSResourceValueEnvelope" />
<xsd:element name="disableInitialValueNotifactions1" nillable="true" type="xsd:ArrayOfint" />
<xsd:element name="disableInitialValueNotifactions2" nillable="true" type="xsd:boolean" />
<xsd:element name="waitForResourceValueChanges1" nillable="true" type="xsd:int" />
<xsd:element name="waitForResourceValueChanges2" nillable="true" type="tns:ArrayOfWSResourceValueEnvelope" />
<xsd:element name="getSceneGroupResourceIdAndPositions1" nillable="true" type="xsd:int" />
<xsd:complexType name="WSSceneResourceIdAndLocationURLs">
<xsd:sequence>
<xsd:element name="scenePositionSeenFromFunctionBlock" type="xsd:string" />
<xsd:element name="sceneResourceId" type="xsd:int" />
<xsd:element name="scenePositionSeenFromProduct" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSSceneResourceIdAndLocationURLs">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="arrayItem" nillable="true" type="tns:WSSceneResourceIdAndLocationURLs" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getSceneGroupResourceIdAndPositions2" nillable="true" type="tns:ArrayOfWSSceneResourceIdAndLocationURLs" />
<xsd:element name="getScenePositionsForSceneValueResource1" nillable="true" type="xsd:int" />
<xsd:element name="getScenePositionsForSceneValueResource2" nillable="true" type="tns:WSSceneResourceIdAndLocationURLs" />
<xsd:element name="getEnumeratorDefinitions1" nillable="true" type="wpNS1:ArrayOfWSEnumDefinition" />
<xsd:element name="getResourceType1" nillable="true" type="xsd:int" />
<xsd:element name="getResourceType2" nillable="true" type="xsd:string" />
<xsd:complexType name="WSDatalineResource">
<xsd:sequence>
<xsd:element name="resourceID" type="xsd:int" />
<xsd:element name="datalineNumber" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSDatalineResource">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="arrayItem" nillable="true" type="tns:WSDatalineResource" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getExtraDatalineInputs1" nillable="true" type="tns:ArrayOfWSDatalineResource" />
<xsd:element name="getExtraDatalineOutputs1" nillable="true" type="tns:ArrayOfWSDatalineResource" />
<xsd:element name="getAllDatalineInputs1" nillable="true" type="tns:ArrayOfWSDatalineResource" />
<xsd:element name="getAllDatalineOutputs1" nillable="true" type="tns:ArrayOfWSDatalineResource" />
</xsd:schema>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="utcs.values">
<xsd:complexType name="WSResourceValue">
<xsd:sequence />
</xsd:complexType>
<xsd:complexType name="WSEnumValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="definitionTypeID" type="xsd:int" />
<xsd:element name="enumValueID" type="xsd:int" />
<xsd:element name="enumName" type="xsd:string" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSEnumValue">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="arrayItem" nillable="true" type="wpNS1:WSEnumValue" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSEnumDefinition">
<xsd:sequence>
<xsd:element name="enumeratorDefinitionID" type="xsd:int" />
<xsd:element name="enumeratorValues" nillable="true" type="wpNS1:ArrayOfWSEnumValue" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSEnumDefinition">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="arrayItem" nillable="true" type="wpNS1:WSEnumDefinition" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSWeekdayValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="weekdayNumber" type="xsd:int" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSTimeValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="hours" type="xsd:int" />
<xsd:element name="minutes" type="xsd:int" />
<xsd:element name="seconds" type="xsd:int" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSTimerValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="milliseconds" type="xsd:long" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSSceneShutterSimpleValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="delayTime" type="xsd:int" />
<xsd:element name="shutterPositionIsUp" type="xsd:boolean" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSSceneRelayValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="delayTime" type="xsd:int" />
<xsd:element name="relayValue" type="xsd:boolean" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSSceneDimmerValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="delayTime" type="xsd:int" />
<xsd:element name="dimmerPercentage" type="xsd:int" />
<xsd:element name="rampTime" type="xsd:int" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSPhoneNumberValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="number" type="xsd:string" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSIntegerValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="integer" type="xsd:int" />
<xsd:element name="maximumValue" type="xsd:int" />
<xsd:element name="minimumValue" type="xsd:int" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSFloatingPointValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="maximumValue" type="xsd:double" />
<xsd:element name="minimumValue" type="xsd:double" />
<xsd:element name="floatingPointValue" type="xsd:double" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSDateValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="month" type="xsd:byte" />
<xsd:element name="year" type="xsd:short" />
<xsd:element name="day" type="xsd:byte" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="WSBooleanValue">
<xsd:complexContent mixed="false">
<xsd:extension base="wpNS1:WSResourceValue">
<xsd:sequence>
<xsd:element name="value" type="xsd:boolean" />
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="ArrayOfint">
<xsd:sequence>
<xsd:element maxOccurs="unbounded" name="arrayItem" type="xsd:int" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getRuntimeValueRequest">
<wsdl:part name="parameter1" element="tns:getRuntimeValue1" />
</wsdl:message>
<wsdl:message name="getRuntimeValueResponse">
<wsdl:part name="return" element="tns:getRuntimeValue2" />
</wsdl:message>
<wsdl:message name="getRuntimeValuesRequest">
<wsdl:part name="parameter2" element="tns:getRuntimeValues1" />
</wsdl:message>
<wsdl:message name="getRuntimeValuesResponse">
<wsdl:part name="return" element="tns:getRuntimeValues2" />
</wsdl:message>
<wsdl:message name="getInitialValueRequest">
<wsdl:part name="parameter3" element="tns:getInitialValue1" />
</wsdl:message>
<wsdl:message name="getInitialValueResponse">
<wsdl:part name="return" element="tns:getInitialValue2" />
</wsdl:message>
<wsdl:message name="getInitialValuesRequest">
<wsdl:part name="parameter4" element="tns:getInitialValues1" />
</wsdl:message>
<wsdl:message name="getInitialValuesResponse">
<wsdl:part name="return" element="tns:getInitialValues2" />
</wsdl:message>
<wsdl:message name="setResourceValueRequest">
<wsdl:part name="parameter5" element="tns:setResourceValue1" />
</wsdl:message>
<wsdl:message name="setResourceValueResponse">
<wsdl:part name="return" element="tns:setResourceValue2" />
</wsdl:message>
<wsdl:message name="setResourceValuesRequest">
<wsdl:part name="parameter6" element="tns:setResourceValues1" />
</wsdl:message>
<wsdl:message name="setResourceValuesResponse">
<wsdl:part name="return" element="tns:setResourceValues2" />
</wsdl:message>
<wsdl:message name="enableRuntimeValueNotificationsRequest">
<wsdl:part name="parameter7" element="tns:enableRuntimeValueNotifications1" />
</wsdl:message>
<wsdl:message name="enableRuntimeValueNotificationsResponse">
<wsdl:part name="return" element="tns:enableRuntimeValueNotifications2" />
</wsdl:message>
<wsdl:message name="disableRuntimeValueNotifactionsRequest">
<wsdl:part name="parameter8" element="tns:disableRuntimeValueNotifactions1" />
</wsdl:message>
<wsdl:message name="disableRuntimeValueNotifactionsResponse">
<wsdl:part name="return" element="tns:disableRuntimeValueNotifactions2" />
</wsdl:message>
<wsdl:message name="enableInitialValueNotificationsRequest">
<wsdl:part name="parameter9" element="tns:enableInitialValueNotifications1" />
</wsdl:message>
<wsdl:message name="enableInitialValueNotificationsResponse">
<wsdl:part name="return" element="tns:enableInitialValueNotifications2" />
</wsdl:message>
<wsdl:message name="disableInitialValueNotifactionsRequest">
<wsdl:part name="parameter10" element="tns:disableInitialValueNotifactions1" />
</wsdl:message>
<wsdl:message name="disableInitialValueNotifactionsResponse">
<wsdl:part name="return" element="tns:disableInitialValueNotifactions2" />
</wsdl:message>
<wsdl:message name="waitForResourceValueChangesRequest">
<wsdl:part name="parameter11" element="tns:waitForResourceValueChanges1" />
</wsdl:message>
<wsdl:message name="waitForResourceValueChangesResponse">
<wsdl:part name="return" element="tns:waitForResourceValueChanges2" />
</wsdl:message>
<wsdl:message name="getSceneGroupResourceIdAndPositionsRequest">
<wsdl:part name="parameter12" element="tns:getSceneGroupResourceIdAndPositions1" />
</wsdl:message>
<wsdl:message name="getSceneGroupResourceIdAndPositionsResponse">
<wsdl:part name="return" element="tns:getSceneGroupResourceIdAndPositions2" />
</wsdl:message>
<wsdl:message name="getScenePositionsForSceneValueResourceRequest">
<wsdl:part name="parameter13" element="tns:getScenePositionsForSceneValueResource1" />
</wsdl:message>
<wsdl:message name="getScenePositionsForSceneValueResourceResponse">
<wsdl:part name="return" element="tns:getScenePositionsForSceneValueResource2" />
</wsdl:message>
<wsdl:message name="getEnumeratorDefinitionsRequest" />
<wsdl:message name="getEnumeratorDefinitionsResponse">
<wsdl:part name="return" element="tns:getEnumeratorDefinitions1" />
</wsdl:message>
<wsdl:message name="getResourceTypeRequest">
<wsdl:part name="parameter14" element="tns:getResourceType1" />
</wsdl:message>
<wsdl:message name="getResourceTypeResponse">
<wsdl:part name="return" element="tns:getResourceType2" />
</wsdl:message>
<wsdl:message name="getExtraDatalineInputsRequest" />
<wsdl:message name="getExtraDatalineInputsResponse">
<wsdl:part name="return" element="tns:getExtraDatalineInputs1" />
</wsdl:message>
<wsdl:message name="getExtraDatalineOutputsRequest" />
<wsdl:message name="getExtraDatalineOutputsResponse">
<wsdl:part name="return" element="tns:getExtraDatalineOutputs1" />
</wsdl:message>
<wsdl:message name="getAllDatalineInputsRequest" />
<wsdl:message name="getAllDatalineInputsResponse">
<wsdl:part name="return" element="tns:getAllDatalineInputs1" />
</wsdl:message>
<wsdl:message name="getAllDatalineOutputsRequest" />
<wsdl:message name="getAllDatalineOutputsResponse">
<wsdl:part name="return" element="tns:getAllDatalineOutputs1" />
</wsdl:message>
<wsdl:portType name="ResourceInteractionService">
<wsdl:operation name="getRuntimeValue">
<wsdl:input name="inputMessageName1" message="tns:getRuntimeValueRequest" />
<wsdl:output name="outputMessageName1" message="tns:getRuntimeValueResponse" />
</wsdl:operation>
<wsdl:operation name="getRuntimeValues">
<wsdl:input name="inputMessageName2" message="tns:getRuntimeValuesRequest" />
<wsdl:output name="outputMessageName2" message="tns:getRuntimeValuesResponse" />
</wsdl:operation>
<wsdl:operation name="getInitialValue">
<wsdl:input name="inputMessageName3" message="tns:getInitialValueRequest" />
<wsdl:output name="outputMessageName3" message="tns:getInitialValueResponse" />
</wsdl:operation>
<wsdl:operation name="getInitialValues">
<wsdl:input name="inputMessageName4" message="tns:getInitialValuesRequest" />
<wsdl:output name="outputMessageName4" message="tns:getInitialValuesResponse" />
</wsdl:operation>
<wsdl:operation name="setResourceValue">
<wsdl:input name="inputMessageName5" message="tns:setResourceValueRequest" />
<wsdl:output name="outputMessageName5" message="tns:setResourceValueResponse" />
</wsdl:operation>
<wsdl:operation name="setResourceValues">
<wsdl:input name="inputMessageName6" message="tns:setResourceValuesRequest" />
<wsdl:output name="outputMessageName6" message="tns:setResourceValuesResponse" />
</wsdl:operation>
<wsdl:operation name="enableRuntimeValueNotifications">
<wsdl:input name="inputMessageName7" message="tns:enableRuntimeValueNotificationsRequest" />
<wsdl:output name="outputMessageName7" message="tns:enableRuntimeValueNotificationsResponse" />
</wsdl:operation>
<wsdl:operation name="disableRuntimeValueNotifactions">
<wsdl:input name="inputMessageName8" message="tns:disableRuntimeValueNotifactionsRequest" />
<wsdl:output name="outputMessageName8" message="tns:disableRuntimeValueNotifactionsResponse" />
</wsdl:operation>
<wsdl:operation name="enableInitialValueNotifications">
<wsdl:input name="inputMessageName9" message="tns:enableInitialValueNotificationsRequest" />
<wsdl:output name="outputMessageName9" message="tns:enableInitialValueNotificationsResponse" />
</wsdl:operation>
<wsdl:operation name="disableInitialValueNotifactions">
<wsdl:input name="inputMessageName10" message="tns:disableInitialValueNotifactionsRequest" />
<wsdl:output name="outputMessageName10" message="tns:disableInitialValueNotifactionsResponse" />
</wsdl:operation>
<wsdl:operation name="waitForResourceValueChanges">
<wsdl:input name="inputMessageName11" message="tns:waitForResourceValueChangesRequest" />
<wsdl:output name="outputMessageName11" message="tns:waitForResourceValueChangesResponse" />
</wsdl:operation>
<wsdl:operation name="getSceneGroupResourceIdAndPositions">
<wsdl:input name="inputMessageName12" message="tns:getSceneGroupResourceIdAndPositionsRequest" />
<wsdl:output name="outputMessageName12" message="tns:getSceneGroupResourceIdAndPositionsResponse" />
</wsdl:operation>
<wsdl:operation name="getScenePositionsForSceneValueResource">
<wsdl:input name="inputMessageName13" message="tns:getScenePositionsForSceneValueResourceRequest" />
<wsdl:output name="outputMessageName13" message="tns:getScenePositionsForSceneValueResourceResponse" />
</wsdl:operation>
<wsdl:operation name="getEnumeratorDefinitions">
<wsdl:input name="inputMessageName14" message="tns:getEnumeratorDefinitionsRequest" />
<wsdl:output name="outputMessageName14" message="tns:getEnumeratorDefinitionsResponse" />
</wsdl:operation>
<wsdl:operation name="getResourceType">
<wsdl:input name="inputMessageName15" message="tns:getResourceTypeRequest" />
<wsdl:output name="outputMessageName15" message="tns:getResourceTypeResponse" />
</wsdl:operation>
<wsdl:operation name="getExtraDatalineInputs">
<wsdl:input name="inputMessageName16" message="tns:getExtraDatalineInputsRequest" />
<wsdl:output name="outputMessageName16" message="tns:getExtraDatalineInputsResponse" />
</wsdl:operation>
<wsdl:operation name="getExtraDatalineOutputs">
<wsdl:input name="inputMessageName17" message="tns:getExtraDatalineOutputsRequest" />
<wsdl:output name="outputMessageName17" message="tns:getExtraDatalineOutputsResponse" />
</wsdl:operation>
<wsdl:operation name="getAllDatalineInputs">
<wsdl:input name="inputMessageName18" message="tns:getAllDatalineInputsRequest" />
<wsdl:output name="outputMessageName18" message="tns:getAllDatalineInputsResponse" />
</wsdl:operation>
<wsdl:operation name="getAllDatalineOutputs">
<wsdl:input name="inputMessageName19" message="tns:getAllDatalineOutputsRequest" />
<wsdl:output name="outputMessageName19" message="tns:getAllDatalineOutputsResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="ResourceInteractionServiceBinding" type="tns:ResourceInteractionService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="getRuntimeValue">
<soap:operation soapAction="getRuntimeValue" style="document" />
<wsdl:input name="inputMessageName1">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getRuntimeValues">
<soap:operation soapAction="getRuntimeValues" style="document" />
<wsdl:input name="inputMessageName2">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getInitialValue">
<soap:operation soapAction="getInitialValue" style="document" />
<wsdl:input name="inputMessageName3">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getInitialValues">
<soap:operation soapAction="getInitialValues" style="document" />
<wsdl:input name="inputMessageName4">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName4">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="setResourceValue">
<soap:operation soapAction="setResourceValue" style="document" />
<wsdl:input name="inputMessageName5">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName5">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="setResourceValues">
<soap:operation soapAction="setResourceValues" style="document" />
<wsdl:input name="inputMessageName6">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName6">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="enableRuntimeValueNotifications">
<soap:operation soapAction="enableRuntimeValueNotifications" style="document" />
<wsdl:input name="inputMessageName7">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName7">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="disableRuntimeValueNotifactions">
<soap:operation soapAction="disableRuntimeValueNotifactions" style="document" />
<wsdl:input name="inputMessageName8">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName8">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="enableInitialValueNotifications">
<soap:operation soapAction="enableInitialValueNotifications" style="document" />
<wsdl:input name="inputMessageName9">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName9">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="disableInitialValueNotifactions">
<soap:operation soapAction="disableInitialValueNotifactions" style="document" />
<wsdl:input name="inputMessageName10">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName10">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="waitForResourceValueChanges">
<soap:operation soapAction="waitForResourceValueChanges" style="document" />
<wsdl:input name="inputMessageName11">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName11">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSceneGroupResourceIdAndPositions">
<soap:operation soapAction="getSceneGroupResourceIdAndPositions" style="document" />
<wsdl:input name="inputMessageName12">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName12">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getScenePositionsForSceneValueResource">
<soap:operation soapAction="getScenePositionsForSceneValueResource" style="document" />
<wsdl:input name="inputMessageName13">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName13">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getEnumeratorDefinitions">
<soap:operation soapAction="getEnumeratorDefinitions" style="document" />
<wsdl:input name="inputMessageName14">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName14">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getResourceType">
<soap:operation soapAction="getResourceType" style="document" />
<wsdl:input name="inputMessageName15">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName15">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getExtraDatalineInputs">
<soap:operation soapAction="getExtraDatalineInputs" style="document" />
<wsdl:input name="inputMessageName16">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName16">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getExtraDatalineOutputs">
<soap:operation soapAction="getExtraDatalineOutputs" style="document" />
<wsdl:input name="inputMessageName17">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName17">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getAllDatalineInputs">
<soap:operation soapAction="getAllDatalineInputs" style="document" />
<wsdl:input name="inputMessageName18">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName18">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getAllDatalineOutputs">
<soap:operation soapAction="getAllDatalineOutputs" style="document" />
<wsdl:input name="inputMessageName19">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="outputMessageName19">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="ResourceInteractionServiceService">
<wsdl:port name="ResourceInteractionServiceBindingPort" binding="tns:ResourceInteractionServiceBinding">
<soap:address location="http://localhost/ResourceInteractionService" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,260 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsdl:types>
<xsd:schema targetNamespace="utcs" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:element name="getTimeFromServer1" nillable="true" type="xsd:string">
</xsd:element>
<xsd:complexType name="WSTimeServerConnectionResult">
<xsd:sequence>
<xsd:element name="connectionWasSuccessful" type="xsd:boolean">
</xsd:element>
<xsd:element name="dateFromServer" type="xsd:long">
</xsd:element>
<xsd:element name="connectionFailedDueToUnknownHost" type="xsd:boolean">
</xsd:element>
<xsd:element name="connectionFailedDueToOtherErrors" type="xsd:boolean">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getTimeFromServer2" nillable="true" type="tns:WSTimeServerConnectionResult">
</xsd:element>
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="day" type="xsd:int">
</xsd:element>
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int">
</xsd:element>
<xsd:element name="hours" type="xsd:int">
</xsd:element>
<xsd:element name="minutes" type="xsd:int">
</xsd:element>
<xsd:element name="seconds" type="xsd:int">
</xsd:element>
<xsd:element name="year" type="xsd:int">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSTimeManagerSettings">
<xsd:sequence>
<xsd:element name="synchroniseTimeAgainstServer" type="xsd:boolean">
</xsd:element>
<xsd:element name="useDST" type="xsd:boolean">
</xsd:element>
<xsd:element name="gmtOffsetInHours" type="xsd:int">
</xsd:element>
<xsd:element name="serverName" type="xsd:string">
</xsd:element>
<xsd:element name="syncIntervalInHours" type="xsd:int">
</xsd:element>
<xsd:element name="timeAndDateInUTC" nillable="true" type="tns:WSDate">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getSettings1" nillable="true" type="tns:WSTimeManagerSettings">
</xsd:element>
<xsd:element name="setSettings1" nillable="true" type="tns:WSTimeManagerSettings">
</xsd:element>
<xsd:element name="setSettings2" nillable="true" type="xsd:boolean">
</xsd:element>
<xsd:element name="getCurrentLocalTime1" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="getUptime1" nillable="true" type="xsd:long">
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getTimeFromServerRequest">
<wsdl:part name="parameter1" element="tns:getTimeFromServer1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getTimeFromServerResponse">
<wsdl:part name="return" element="tns:getTimeFromServer2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getSettingsRequest">
</wsdl:message>
<wsdl:message name="getSettingsResponse">
<wsdl:part name="return" element="tns:getSettings1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="setSettingsRequest">
<wsdl:part name="parameter2" element="tns:setSettings1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="setSettingsResponse">
<wsdl:part name="return" element="tns:setSettings2">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getCurrentLocalTimeRequest">
</wsdl:message>
<wsdl:message name="getCurrentLocalTimeResponse">
<wsdl:part name="return" element="tns:getCurrentLocalTime1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getUptimeRequest">
</wsdl:message>
<wsdl:message name="getUptimeResponse">
<wsdl:part name="return" element="tns:getUptime1">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="TimeManagerService">
<wsdl:operation name="getTimeFromServer">
<wsdl:input name="inputMessageName1" message="tns:getTimeFromServerRequest">
</wsdl:input>
<wsdl:output name="outputMessageName1" message="tns:getTimeFromServerResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSettings">
<wsdl:input name="inputMessageName2" message="tns:getSettingsRequest">
</wsdl:input>
<wsdl:output name="outputMessageName2" message="tns:getSettingsResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="setSettings">
<wsdl:input name="inputMessageName3" message="tns:setSettingsRequest">
</wsdl:input>
<wsdl:output name="outputMessageName3" message="tns:setSettingsResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getCurrentLocalTime">
<wsdl:input name="inputMessageName4" message="tns:getCurrentLocalTimeRequest">
</wsdl:input>
<wsdl:output name="outputMessageName4" message="tns:getCurrentLocalTimeResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getUptime">
<wsdl:input name="inputMessageName5" message="tns:getUptimeRequest">
</wsdl:input>
<wsdl:output name="outputMessageName5" message="tns:getUptimeResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="TimeManagerServiceBinding" type="tns:TimeManagerService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<wsdl:operation name="getTimeFromServer">
<soap:operation soapAction="getTimeFromServer" style="document">
</soap:operation>
<wsdl:input name="inputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getSettings">
<soap:operation soapAction="getSettings" style="document">
</soap:operation>
<wsdl:input name="inputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="setSettings">
<soap:operation soapAction="setSettings" style="document">
</soap:operation>
<wsdl:input name="inputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getCurrentLocalTime">
<soap:operation soapAction="getCurrentLocalTime" style="document">
</soap:operation>
<wsdl:input name="inputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getUptime">
<soap:operation soapAction="getUptime" style="document">
</soap:operation>
<wsdl:input name="inputMessageName5">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName5">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="TimeManagerServiceService">
<wsdl:port name="TimeManagerServiceBindingPort" binding="tns:TimeManagerServiceBinding">
<soap:address location="http://localhost/TimeManagerService">
</soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="utcs" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="utcs" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsdl:types>
<xsd:schema targetNamespace="utcs" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified">
<xsd:complexType name="WSDate">
<xsd:sequence>
<xsd:element name="day" type="xsd:int">
</xsd:element>
<xsd:element name="monthWithJanuaryAsOne" type="xsd:int">
</xsd:element>
<xsd:element name="hours" type="xsd:int">
</xsd:element>
<xsd:element name="minutes" type="xsd:int">
</xsd:element>
<xsd:element name="seconds" type="xsd:int">
</xsd:element>
<xsd:element name="year" type="xsd:int">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSUserGroup">
<xsd:sequence>
<xsd:element name="type" type="xsd:string">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="WSUser">
<xsd:sequence>
<xsd:element name="createdDate" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="loginDate" nillable="true" type="tns:WSDate">
</xsd:element>
<xsd:element name="username" type="xsd:string">
</xsd:element>
<xsd:element name="password" type="xsd:string">
</xsd:element>
<xsd:element name="email" type="xsd:string">
</xsd:element>
<xsd:element name="firstname" type="xsd:string">
</xsd:element>
<xsd:element name="lastname" type="xsd:string">
</xsd:element>
<xsd:element name="phone" type="xsd:string">
</xsd:element>
<xsd:element name="group" nillable="true" type="tns:WSUserGroup">
</xsd:element>
<xsd:element name="project" type="xsd:string">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfWSUser">
<xsd:sequence>
<xsd:element name="arrayItem" maxOccurs="unbounded" nillable="true" type="tns:WSUser">
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="getUsers1" nillable="true" type="tns:ArrayOfWSUser">
</xsd:element>
<xsd:element name="addUser1" nillable="true" type="tns:WSUser">
</xsd:element>
<xsd:element name="removeUser1" nillable="true" type="xsd:string">
</xsd:element>
<xsd:element name="updateUser1" nillable="true" type="tns:WSUser">
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="getUsersRequest">
</wsdl:message>
<wsdl:message name="getUsersResponse">
<wsdl:part name="return" element="tns:getUsers1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="addUserRequest">
<wsdl:part name="parameter1" element="tns:addUser1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="addUserResponse">
</wsdl:message>
<wsdl:message name="removeUserRequest">
<wsdl:part name="parameter2" element="tns:removeUser1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="removeUserResponse">
</wsdl:message>
<wsdl:message name="updateUserRequest">
<wsdl:part name="parameter3" element="tns:updateUser1">
</wsdl:part>
</wsdl:message>
<wsdl:message name="updateUserResponse">
</wsdl:message>
<wsdl:portType name="UserManagerService">
<wsdl:operation name="getUsers">
<wsdl:input name="inputMessageName1" message="tns:getUsersRequest">
</wsdl:input>
<wsdl:output name="outputMessageName1" message="tns:getUsersResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="addUser">
<wsdl:input name="inputMessageName2" message="tns:addUserRequest">
</wsdl:input>
<wsdl:output name="outputMessageName2" message="tns:addUserResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="removeUser">
<wsdl:input name="inputMessageName3" message="tns:removeUserRequest">
</wsdl:input>
<wsdl:output name="outputMessageName3" message="tns:removeUserResponse">
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="updateUser">
<wsdl:input name="inputMessageName4" message="tns:updateUserRequest">
</wsdl:input>
<wsdl:output name="outputMessageName4" message="tns:updateUserResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="UserManagerServiceBinding" type="tns:UserManagerService">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http">
</soap:binding>
<wsdl:operation name="getUsers">
<soap:operation soapAction="getUsers" style="document">
</soap:operation>
<wsdl:input name="inputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName1">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="addUser">
<soap:operation soapAction="addUser" style="document">
</soap:operation>
<wsdl:input name="inputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName2">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="removeUser">
<soap:operation soapAction="removeUser" style="document">
</soap:operation>
<wsdl:input name="inputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName3">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="updateUser">
<soap:operation soapAction="updateUser" style="document">
</soap:operation>
<wsdl:input name="inputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:input>
<wsdl:output name="outputMessageName4">
<soap:body use="literal">
</soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="UserManagerServiceService">
<wsdl:port name="UserManagerServiceBindingPort" binding="tns:UserManagerServiceBinding">
<soap:address location="http://localhost/UserManagerService">
</soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>

View File

@@ -0,0 +1,38 @@
<?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.ihc</artifactId>
<name>openHAB Add-ons :: Bundles :: IHC Binding</name>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore-osgi</artifactId>
<version>4.4.10</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-osgi</artifactId>
<version>4.5.8</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.ihc-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
<feature name="openhab-binding-ihc" description="IHC / ELKO Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle dependency="true">mvn:org.apache.httpcomponents/httpcore-osgi/4.4.10</bundle>
<bundle dependency="true">mvn:org.apache.httpcomponents/httpclient-osgi/4.5.8</bundle>
<bundle dependency="true">mvn:commons-logging/commons-logging/1.2</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.ihc/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,73 @@
/**
* 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.ihc.internal;
import java.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class to handle button press durations
*
* @author Pauli Anttila - Initial contribution
*/
public class ButtonPressDurationDetector {
private final Logger logger = LoggerFactory.getLogger(ButtonPressDurationDetector.class);
private boolean shortPress;
private boolean longPress;
private Duration duration;
private long longPressTime;
private long longPressMaxTime;
public boolean isShortPress() {
return shortPress;
}
public boolean isLongPress() {
return longPress;
}
public ButtonPressDurationDetector(Duration duration, long longPressTime, long longPressMaxTime) {
this.duration = duration;
this.longPressTime = longPressTime;
this.longPressMaxTime = longPressMaxTime;
calculate();
}
private void calculate() {
if (duration.toMillis() < 0) {
logger.debug("Button press duration < 0ms");
} else if (isBetween(duration.toMillis(), 0, longPressTime)) {
logger.debug("Button press duration > {}ms and < {}ms", 0, longPressTime);
shortPress = true;
} else if (isBetween(duration.toMillis(), longPressTime, longPressMaxTime)) {
logger.debug("Button press duration > {}ms and < {}ms", longPressTime, longPressMaxTime);
longPress = true;
} else {
logger.debug("Button press duration > {}ms, ignore it", longPressMaxTime);
}
}
private boolean isBetween(long value, long minValue, long maxValueInclusive) {
return (value > minValue && value <= maxValueInclusive);
}
@Override
public String toString() {
return String.format("[ duration=%sms, shortPress=%b, longPress=%b ]", duration.toMillis(), shortPress,
longPress);
}
}

View File

@@ -0,0 +1,241 @@
/**
* 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.ihc.internal;
import static org.openhab.binding.ihc.internal.IhcBindingConstants.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import org.apache.commons.lang.StringUtils;
import org.openhab.binding.ihc.internal.config.ChannelParams;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.binding.builder.ChannelBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* Generic methods related to openHAB channels.
*
* @author Pauli Anttila - Initial contribution
*/
public class ChannelUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelUtils.class);
public static Set<Integer> getAllChannelsResourceIds(Thing thing) {
Set<Integer> resourceIds = new HashSet<>();
thing.getChannels().forEach(c -> {
try {
ChannelParams params = new ChannelParams(c);
if (params.getResourceId() != null && params.getResourceId() != 0) {
resourceIds.add(params.getResourceId());
}
} catch (ConversionException e) {
LOGGER.warn("Channel param error, reason: {}.", e.getMessage(), e);
}
});
return resourceIds;
}
public static Set<Integer> getAllTriggerChannelsResourceIds(Thing thing) {
Set<Integer> resourceIds = new HashSet<>();
thing.getChannels().forEach(c -> {
try {
ChannelParams params = new ChannelParams(c);
if (params.getChannelTypeId() != null) {
switch (params.getChannelTypeId()) {
case CHANNEL_TYPE_PUSH_BUTTON_TRIGGER:
if (params.getResourceId() != null && params.getResourceId() != 0) {
resourceIds.add(params.getResourceId());
}
break;
}
}
} catch (ConversionException e) {
LOGGER.warn("Channel param error, reason: {}.", e.getMessage(), e);
}
});
return resourceIds;
}
public static void addChannelsFromProjectFile(Thing thing, Document projectFile, List<Channel> thingChannels) {
if (projectFile != null) {
try {
NodeList nodes = projectFile.getElementsByTagName("product_dataline");
if (nodes != null) {
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
addChannelsFromProjectFile(thing, node.getElementsByTagName("dataline_input"), "Switch",
"input", CHANNEL_TYPE_SWITCH, thingChannels);
addChannelsFromProjectFile(thing, node.getElementsByTagName("dataline_output"), "Switch",
"output", CHANNEL_TYPE_SWITCH, thingChannels);
addChannelsFromProjectFile(thing, node.getElementsByTagName("resource_temperature"), "Number",
"temperature", CHANNEL_TYPE_NUMBER, thingChannels);
addChannelsFromProjectFile(thing, node.getElementsByTagName("resource_humidity_level"),
"Number", "humidity", CHANNEL_TYPE_NUMBER, thingChannels);
}
}
} catch (RuntimeException e) {
LOGGER.warn("Error occured when adding channels, reason: {}", e.getMessage(), e);
}
try {
NodeList nodes = projectFile.getElementsByTagName("product_airlink");
if (nodes != null) {
addRFDeviceChannels(thing, nodes, thingChannels);
for (int i = 0; i < nodes.getLength(); i++) {
Element node = (Element) nodes.item(i);
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_input"), "Switch", "input",
CHANNEL_TYPE_SWITCH, thingChannels);
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_output"), "Switch",
"output", CHANNEL_TYPE_SWITCH, thingChannels);
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_relay"), "Switch",
"output", CHANNEL_TYPE_SWITCH, thingChannels);
addChannelsFromProjectFile(thing, node.getElementsByTagName("airlink_dimming"), "Dimmer",
"output", CHANNEL_TYPE_SWITCH, thingChannels);
}
}
} catch (RuntimeException e) {
LOGGER.warn("Error occured when adding channels, reason: {}", e.getMessage(), e);
}
} else {
LOGGER.warn("Project file data doesn't exist, can't automatically create channels!");
}
}
public static void addControllerChannels(Thing thing, List<Channel> thingChannels) {
if (thing != null && thingChannels != null) {
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), CHANNEL_CONTROLLER_STATE), "String")
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_CONTROLLER_STATE)).build();
addOrUpdateChannel(channel, thingChannels);
channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), CHANNEL_CONTROLLER_UPTIME), "Number")
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_CONTROLLER_UPTIME)).build();
addOrUpdateChannel(channel, thingChannels);
channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), CHANNEL_CONTROLLER_TIME), "DateTime")
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_CONTROLLER_TIME)).build();
addOrUpdateChannel(channel, thingChannels);
}
}
private static void addRFDeviceChannels(Thing thing, NodeList nodes, List<Channel> thingChannels) {
if (thing != null && nodes != null && thingChannels != null) {
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
Long serialNumber = Long.parseLong(element.getAttribute("serialnumber").replace("_0x", ""), 16);
if (serialNumber != 0) {
String name = element.getAttribute("name");
String position = element.getAttribute("position");
String serialNumberHex = Long.toHexString(serialNumber);
Configuration configuration = new Configuration();
configuration.put("serialNumber", serialNumber);
// low battery
String channelId = String.format("%s-lowBattery", serialNumberHex);
String label = createDescription(position, name, serialNumberHex, "Low Battery");
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channelId), "Switch")
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_RF_LOW_BATTERY))
.withConfiguration(configuration).withLabel(label).build();
addOrUpdateChannel(channel, thingChannels);
// signal level
channelId = String.format("%s-signalStrength", serialNumberHex);
label = createDescription(position, name, serialNumberHex, "Signal Strength");
channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), channelId), "String")
.withType(new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_RF_SIGNAL_STRENGTH))
.withConfiguration(configuration).withLabel(label).build();
addOrUpdateChannel(channel, thingChannels);
}
}
}
}
private static void addChannelsFromProjectFile(Thing thing, NodeList nodes, String acceptedItemType, String group,
String channelType, List<Channel> thingChannels) {
if (thing != null && nodes != null && thingChannels != null) {
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
Element parent = (Element) element.getParentNode();
if ("settings".equals(parent.getNodeName())) {
// get settings element parent
parent = (Element) parent.getParentNode();
}
Element parentParent = (Element) parent.getParentNode();
String parentName = parent.getAttribute("name");
String parentPosition = parent.getAttribute("position");
String parentParentName = parentParent.getAttribute("name");
String resourceName = element.getAttribute("name");
int resourceId = Integer.parseInt(element.getAttribute("id").replace("_0x", ""), 16);
String description = createDescription(parentParentName, parentPosition, parentName, resourceName);
ChannelUID channelUID = new ChannelUID(thing.getUID(), group + resourceId);
ChannelTypeUID type = new ChannelTypeUID(BINDING_ID, channelType);
Configuration configuration = new Configuration();
configuration.put(PARAM_RESOURCE_ID, new Integer(resourceId));
Channel channel = ChannelBuilder.create(channelUID, acceptedItemType).withConfiguration(configuration)
.withLabel(description).withType(type).build();
addOrUpdateChannel(channel, thingChannels);
}
}
}
private static String createDescription(String name1, String name2, String name3, String name4) {
String description = "";
if (StringUtils.isNotEmpty(name1)) {
description = name1;
}
if (StringUtils.isNotEmpty(name2)) {
description += String.format(" - %s", name2);
}
if (StringUtils.isNotEmpty(name3)) {
description += String.format(" - %s", name3);
}
if (StringUtils.isNotEmpty(name4)) {
description += String.format(" - %s", name4);
}
return description;
}
private static void addOrUpdateChannel(Channel newChannel, List<Channel> thingChannels) {
removeChannelByUID(thingChannels, newChannel.getUID());
thingChannels.add(newChannel);
}
private static void removeChannelByUID(List<Channel> thingChannels, ChannelUID channelUIDtoRemove) {
Predicate<Channel> channelPredicate = c -> c.getUID().getId().equals(channelUIDtoRemove.getId());
thingChannels.removeIf(channelPredicate);
}
}

View File

@@ -0,0 +1,43 @@
/**
* 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.ihc.internal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
/**
* Class for holding enumerations from IHC / ELKO project file.
*
* @author Pauli Anttila - Initial contribution
*/
public class EnumDictionary {
private Map<Integer, List<IhcEnumValue>> enumDictionary = new HashMap<>();
public EnumDictionary(Map<Integer, List<IhcEnumValue>> enums) {
this.enumDictionary = enums;
}
/**
* Returns all possible enumerated values for corresponding enum type.
*
* @param typeDefinititonId Enum type definition identifier.
* @return list of enum values.
*/
public List<IhcEnumValue> getEnumValues(int typeDefinititonId) {
return enumDictionary.get(typeDefinititonId);
}
}

View File

@@ -0,0 +1,86 @@
/**
* 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.ihc.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link IhcBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Pauli Anttila - Initial contribution
*/
@NonNullByDefault
public class IhcBindingConstants {
public static final String BINDING_ID = "ihc";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_CONTROLLER = new ThingTypeUID(BINDING_ID, "controller");
public static final String PROPERTY_MANUFACTURER = "controllerManufacturer";
public static final String PROPERTY_SERIALNUMBER = "controllerSerialNumber";
public static final String PROPERTY_SW_VERSION = "controllerSwVersion";
public static final String PROPERTY_FW_VERSION = "controllerHwVersion";
public static final String PROPERTY_APP_WITHOUT_VIEWER = "controllerIsWithoutViewer";
public static final String PROPERTY_SW_DATE = "controllerSwDate";
public static final String PROPERTY_PRODUCTION_DATE = "controllerProductionDate";
public static final String PROPERTY_PROJECT_DATE = "projectDate";
public static final String PROPERTY_PROJECT_NUMBER = "projectNumber";
public static final String PROPERTY_DATALINE_VERSION = "controllerDatalineVersion";
public static final String PROPERTY_RF_MODULE_VERSION = "controllerRfModSwVersion";
public static final String PROPERTY_RF_MODULE_SERIALNUMBER = "controllerRfModSerialNumber";
// List of all Channel ids
public static final String CHANNEL_CONTROLLER_STATE = "controllerState";
public static final String CHANNEL_CONTROLLER_UPTIME = "controllerUptime";
public static final String CHANNEL_CONTROLLER_TIME = "controllerTime";
// List of all Channel type ids
public static final String CHANNEL_TYPE_CONTROLLER_STATE = "controller-state";
public static final String CHANNEL_TYPE_CONTROLLER_SW_VER = "controller-sw-version";
public static final String CHANNEL_TYPE_CONTROLLER_HW_VER = "controller-hw-version";
public static final String CHANNEL_TYPE_CONTROLLER_UPTIME = "controller-uptime";
public static final String CHANNEL_TYPE_CONTROLLER_TIME = "controller-time";
public static final String CHANNEL_TYPE_NUMBER = "number";
public static final String CHANNEL_TYPE_SWITCH = "switch";
public static final String CHANNEL_TYPE_CONTACT = "contact";
public static final String CHANNEL_TYPE_DIMMER = "dimmer";
public static final String CHANNEL_TYPE_DATETIME = "datetime";
public static final String CHANNEL_TYPE_STRING = "string";
public static final String CHANNEL_TYPE_ROLLERSHUTTER = "rollershutter";
public static final String CHANNEL_TYPE_RF_SIGNAL_STRENGTH = "rf-device-signal-strength";
public static final String CHANNEL_TYPE_RF_LOW_BATTERY = "rf-device-low-battery";
public static final String CHANNEL_TYPE_PUSH_BUTTON_TRIGGER = "push-button-trigger";
// List of all channel parameters
public static final String PARAM_RESOURCE_ID = "resourceId";
public static final String PARAM_DIRECTION = "direction";
public static final String PARAM_CMD_TO_REACT = "commandToReact";
public static final String PARAM_SERIAL_NUMBER = "serialNumber";
public static final String PARAM_PULSE_WIDTH = "pulseWidth";
public static final String PARAM_LONG_PRESS_TIME = "longPressTime";
public static final String PARAM_INVERTED = "inverted";
public static final String PARAM_ON_LEVEL = "onLevel";
public static final String DIRECTION_READ_WRITE = "ReadWrite";
public static final String DIRECTION_WRITE_ONLY = "WriteOnly";
public static final String DIRECTION_READ_ONLY = "ReadOnly";
public static final String EVENT_PRESSED = "PRESSED";
public static final String EVENT_RELEASED = "RELEASED";
public static final String EVENT_SHORT_PRESS = "SHORT_PRESS";
public static final String EVENT_LONG_PRESS = "LONG_PRESS";
}

View File

@@ -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.ihc.internal;
import static org.openhab.binding.ihc.internal.IhcBindingConstants.THING_CONTROLLER;
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.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.ihc.internal.handler.IhcHandler;
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.Component;
/**
* The {@link IhcHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Pauli Anttila - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.ihc")
@NonNullByDefault
public class IhcHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_CONTROLLER).collect(Collectors.toSet()));
@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 (thingTypeUID.equals(THING_CONTROLLER)) {
return new IhcHandler(thing);
}
return null;
}
}

View File

@@ -0,0 +1,85 @@
/**
* 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.ihc.internal;
/**
* Class to convert IHC RF signal level value to openHAB signal level.
*
* @author Pauli Anttila - Initial contribution
*/
public class SignalLevelConverter {
int signalLevel;
public SignalLevelConverter(int signalLevel) {
this.signalLevel = signalLevel;
}
public int getSystemWideSignalLevel() {
return convertSignalLevelToSystemWideLevel(signalLevel);
}
/**
* Convert internal signal level (0-18) to system wide signal level (0-4).
*
* @param signalLevel Internal signal level
* @return Signal level in system wide level
*/
private int convertSignalLevelToSystemWideLevel(int signalLevel) {
int newLevel;
/*
* IHC signal levels are always between 0-18.
*
* Use switch case to make level adaption easier in future if needed.
*/
switch (signalLevel) {
case 0:
case 1:
newLevel = 0;
break;
case 2:
case 3:
case 4:
newLevel = 1;
break;
case 5:
case 6:
case 7:
case 8:
newLevel = 2;
break;
case 9:
case 10:
case 11:
case 12:
case 13:
newLevel = 3;
break;
case 14:
case 15:
case 16:
case 17:
case 18:
default:
newLevel = 4;
}
return newLevel;
}
}

View File

@@ -0,0 +1,170 @@
/**
* 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.ihc.internal.config;
import static org.openhab.binding.ihc.internal.IhcBindingConstants.*;
import java.math.BigDecimal;
import java.util.Map;
import java.util.function.Function;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.type.ChannelTypeUID;
/**
* Class for holding channel parameterization.
*
* @author Pauli Anttila - Initial contribution
*/
public class ChannelParams {
private String channelTypeId;
private Integer resourceId;
private String direction;
private String commandToReact;
private Integer pulseWidth;
private Boolean inverted;
private Long serialNumber;
private Integer longPressTime;
private Integer onLevel;
public ChannelParams(@NonNull Channel channel) throws ConversionException {
ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
if (channelTypeUID != null) {
channelTypeId = channelTypeUID.getId();
}
Map<String, Object> map = channel.getConfiguration().getProperties();
for (Map.Entry<String, Object> entry : map.entrySet()) {
switch (entry.getKey()) {
case PARAM_RESOURCE_ID:
resourceId = getChannelParameterAsInteger(entry.getValue());
break;
case PARAM_DIRECTION:
direction = getChannelParameterAsString(entry.getValue());
break;
case PARAM_CMD_TO_REACT:
commandToReact = getChannelParameterAsString(entry.getValue());
break;
case PARAM_SERIAL_NUMBER:
serialNumber = getChannelParameterAsLong(entry.getValue());
break;
case PARAM_PULSE_WIDTH:
pulseWidth = getChannelParameterAsInteger(entry.getValue());
break;
case PARAM_LONG_PRESS_TIME:
longPressTime = getChannelParameterAsInteger(entry.getValue());
break;
case PARAM_INVERTED:
inverted = getChannelParameterAsBoolean(entry.getValue());
break;
case PARAM_ON_LEVEL:
onLevel = getChannelParameterAsInteger(entry.getValue());
break;
}
}
}
public String getChannelTypeId() {
return channelTypeId;
}
public Integer getResourceId() {
return resourceId;
}
public String getDirection() {
return direction;
}
public boolean isDirectionBoth() {
return direction != null && DIRECTION_READ_WRITE.equals(direction);
}
public boolean isDirectionReadOnly() {
return direction != null && DIRECTION_READ_ONLY.equals(direction);
}
public boolean isDirectionWriteOnly() {
return direction != null && DIRECTION_WRITE_ONLY.equals(direction);
}
public String getCommandToReact() {
return commandToReact;
}
public Integer getPulseWidth() {
return pulseWidth;
}
public Boolean getInverted() {
return inverted;
}
public boolean isInverted() {
if (inverted != null) {
return inverted;
}
return false;
}
public Long getSerialNumber() {
return serialNumber;
}
public Integer getLongPressTime() {
return longPressTime;
}
public Integer getOnLevel() {
return onLevel;
}
private static Boolean getChannelParameterAsBoolean(Object value) throws ConversionException {
return convert(value, (v) -> (Boolean) v);
}
private Integer getChannelParameterAsInteger(Object value) throws ConversionException {
return convert(value, (v) -> ((BigDecimal) v).intValue());
}
private Long getChannelParameterAsLong(Object value) throws ConversionException {
return convert(value, (v) -> ((BigDecimal) v).longValue());
}
private String getChannelParameterAsString(Object value) throws ConversionException {
return convert(value, (v) -> (String) v);
}
private static <T> T convert(Object value, Function<Object, T> f) throws ConversionException {
if (value == null) {
return null;
}
try {
return f.apply(value);
} catch (ClassCastException e) {
throw new ConversionException(String.format("Failed to convert, reason %s.", e.getMessage()), e);
}
}
@Override
public String toString() {
return String.format(
"[ channelTypeId=%s, resourceId=%d, direction=%s, commandToReact=%s, pulseWidth=%d, inverted=%b, serialNumber=%d, longPressTime=%d, onLevel=%d ]",
channelTypeId, resourceId, direction, commandToReact, pulseWidth, inverted, serialNumber, longPressTime,
onLevel);
}
}

View File

@@ -0,0 +1,34 @@
/**
* 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.ihc.internal.config;
/**
* Configuration class for {@link IhcBinding} binding.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcConfiguration {
public String hostname;
public String username;
public String password;
public int timeout;
public boolean loadProjectFile;
public boolean createChannelsAutomatically;
@Override
public String toString() {
return "[" + "hostname=" + hostname + ", username=" + username + ", password=******" + ", timeout=" + timeout
+ ", loadProjectFile=" + loadProjectFile + ", createChannelsAutomatically="
+ createChannelsAutomatically + "]";
}
}

View File

@@ -0,0 +1,29 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
/**
* IHC / ELKO <-> openHAB data type converter interface.
*
* @author Pauli Anttila - Initial contribution
*/
public interface Converter<R, T> {
T convertFromResourceValue(@NonNull R from, @NonNull ConverterAdditionalInfo convertData)
throws ConversionException;
R convertFromOHType(@NonNull T from, @NonNull R value, @NonNull ConverterAdditionalInfo convertData)
throws ConversionException;
}

View File

@@ -0,0 +1,49 @@
/**
* 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.ihc.internal.converters;
import java.util.List;
import java.util.Map;
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
import org.openhab.core.types.Command;
/**
* Class to hold additional information which is needed for data conversion.
*
* @author Pauli Anttila - Initial contribution
*/
public class ConverterAdditionalInfo {
private List<IhcEnumValue> enumValues;
private Boolean inverted;
private Map<Command, Object> commandLevels;
public ConverterAdditionalInfo(List<IhcEnumValue> enumValues, Boolean inverted,
Map<Command, Object> commandLevels) {
this.enumValues = enumValues;
this.inverted = inverted;
this.commandLevels = commandLevels;
}
public List<IhcEnumValue> getEnumValues() {
return enumValues;
}
public Boolean getInverted() {
return inverted;
}
public Map<Command, Object> getCommandLevels() {
return commandLevels;
}
}

View File

@@ -0,0 +1,143 @@
/**
* 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.ihc.internal.converters;
import java.util.HashMap;
import java.util.Map;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.Type;
/**
* IHC / ELKO <-> openHAB data type converter factory.
*
* @author Pauli Anttila - Initial contribution
*/
public enum ConverterFactory {
INSTANCE;
private static final String ITEM_TYPE_NUMBER = "Number";
private static final String ITEM_TYPE_SWITCH = "Switch";
private static final String ITEM_TYPE_CONTACT = "Contact";
private static final String ITEM_TYPE_DIMMER = "Dimmer";
private static final String ITEM_TYPE_DATETIME = "DateTime";
private static final String ITEM_TYPE_STRING = "String";
private static final String ITEM_TYPE_ROLLERSHUTTER = "Rollershutter";
private class Key {
Class<? extends WSResourceValue> ihcType;
Class<? extends Type> openhabType;
Key(Class<? extends WSResourceValue> ihcType, Class<? extends Type> openhabType) {
this.ihcType = ihcType;
this.openhabType = openhabType;
}
@Override
public int hashCode() {
return ihcType.getClass().hashCode() + openhabType.getClass().hashCode();
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Key)) {
return false;
}
Key key = (Key) o;
return key.ihcType.equals(ihcType) && key.openhabType.equals(openhabType);
}
}
private Map<Key, Converter<? extends WSResourceValue, ? extends Type>> converters;
private ConverterFactory() {
converters = new HashMap<>();
converters.put(new Key(WSDateValue.class, DateTimeType.class), new DateTimeTypeWSDateValueConverter());
converters.put(new Key(WSTimeValue.class, DateTimeType.class), new DateTimeTypeWSTimeValueConverter());
converters.put(new Key(WSBooleanValue.class, DecimalType.class), new DecimalTypeWSBooleanValueConverter());
converters.put(new Key(WSEnumValue.class, DecimalType.class), new DecimalTypeWSEnumValueConverter());
converters.put(new Key(WSFloatingPointValue.class, DecimalType.class),
new DecimalTypeWSFloatingPointValueConverter());
converters.put(new Key(WSIntegerValue.class, DecimalType.class), new DecimalTypeWSIntegerValueConverter());
converters.put(new Key(WSTimerValue.class, DecimalType.class), new DecimalTypeWSTimerValueConverter());
converters.put(new Key(WSWeekdayValue.class, DecimalType.class), new DecimalTypeWSWeekdayValueConverter());
converters.put(new Key(WSBooleanValue.class, OnOffType.class), new OnOffTypeWSBooleanValueConverter());
converters.put(new Key(WSIntegerValue.class, OnOffType.class), new OnOffTypeWSIntegerValueConverter());
converters.put(new Key(WSBooleanValue.class, OpenClosedType.class),
new OpenClosedTypeWSBooleanValueConverter());
converters.put(new Key(WSIntegerValue.class, OpenClosedType.class),
new OpenClosedTypeWSIntegerValueConverter());
converters.put(new Key(WSIntegerValue.class, PercentType.class), new PercentTypeWSIntegerValueConverter());
converters.put(new Key(WSEnumValue.class, StringType.class), new StringTypeWSEnumValueConverter());
converters.put(new Key(WSBooleanValue.class, UpDownType.class), new UpDownTypeWSBooleanValueConverter());
converters.put(new Key(WSIntegerValue.class, UpDownType.class), new UpDownTypeWSIntegerValueConverter());
}
public static ConverterFactory getInstance() {
return INSTANCE;
}
@SuppressWarnings("unchecked")
public Converter<WSResourceValue, Type> getConverter(Class<? extends WSResourceValue> resourceValueType,
Class<? extends Type> type) {
return (Converter<WSResourceValue, Type>) converters.get(new Key(resourceValueType, type));
}
@SuppressWarnings("unchecked")
public Converter<WSResourceValue, Type> getConverter(Class<? extends WSResourceValue> resourceValueType,
String itemType) {
Class<? extends Type> type = null;
switch (itemType) {
case ITEM_TYPE_SWITCH:
type = OnOffType.class;
break;
case ITEM_TYPE_ROLLERSHUTTER:
case ITEM_TYPE_DIMMER:
type = PercentType.class;
break;
case ITEM_TYPE_CONTACT:
type = OpenClosedType.class;
break;
case ITEM_TYPE_STRING:
type = StringType.class;
break;
case ITEM_TYPE_NUMBER:
type = DecimalType.class;
break;
case ITEM_TYPE_DATETIME:
type = DateTimeType.class;
break;
}
return (Converter<WSResourceValue, Type>) converters.get(new Key(resourceValueType, type));
}
}

View File

@@ -0,0 +1,66 @@
/**
* 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.ihc.internal.converters;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
import org.openhab.core.library.types.DateTimeType;
/**
* DateTimeType <-> WSDateValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DateTimeTypeWSDateValueConverter implements Converter<WSDateValue, DateTimeType> {
@Override
public DateTimeType convertFromResourceValue(@NonNull WSDateValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
Calendar cal = dateTimeToCalendar(from, null);
return new DateTimeType(ZonedDateTime.ofInstant(cal.toInstant(), TimeZone.getDefault().toZoneId()));
}
@Override
public WSDateValue convertFromOHType(@NonNull DateTimeType from, @NonNull WSDateValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
Calendar cal = GregorianCalendar.from(from.getZonedDateTime());
short year = (short) cal.get(Calendar.YEAR);
byte month = (byte) (cal.get(Calendar.MONTH) + 1);
byte day = (byte) cal.get(Calendar.DAY_OF_MONTH);
return new WSDateValue(value.resourceID, year, month, day);
}
private Calendar dateTimeToCalendar(WSDateValue date, WSTimeValue time) {
Calendar cal = new GregorianCalendar(2000, 01, 01);
if (date != null) {
short year = date.year;
short month = date.month;
short day = date.day;
cal.set(year, month - 1, day, 0, 0, 0);
}
if (time != null) {
int hour = time.hours;
int minute = time.minutes;
int second = time.seconds;
cal.set(2000, 0, 1, hour, minute, second);
}
return cal;
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.ihc.internal.converters;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
import org.openhab.core.library.types.DateTimeType;
/**
* DateTimeType <-> WSTimeValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DateTimeTypeWSTimeValueConverter implements Converter<WSTimeValue, DateTimeType> {
@Override
public DateTimeType convertFromResourceValue(@NonNull WSTimeValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
Calendar cal = dateTimeToCalendar(null, from);
return new DateTimeType(ZonedDateTime.ofInstant(cal.toInstant(), TimeZone.getDefault().toZoneId()));
}
@Override
public WSTimeValue convertFromOHType(@NonNull DateTimeType from, @NonNull WSTimeValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
Calendar cal = GregorianCalendar.from(from.getZonedDateTime());
return new WSTimeValue(value.resourceID, cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE),
cal.get(Calendar.SECOND));
}
private Calendar dateTimeToCalendar(WSDateValue date, WSTimeValue time) {
Calendar cal = new GregorianCalendar(2000, 01, 01);
if (date != null) {
short year = date.year;
short month = date.month;
short day = date.day;
cal.set(year, month - 1, day, 0, 0, 0);
}
if (time != null) {
int hour = time.hours;
int minute = time.minutes;
int second = time.seconds;
cal.set(2000, 0, 1, hour, minute, second);
}
return cal;
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.core.library.types.DecimalType;
/**
* DecimalType <-> WSBooleanValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSBooleanValueConverter implements Converter<WSBooleanValue, DecimalType> {
@Override
public DecimalType convertFromResourceValue(@NonNull WSBooleanValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new DecimalType(from.value ? 1 : 0);
}
@Override
public WSBooleanValue convertFromOHType(@NonNull DecimalType from, @NonNull WSBooleanValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSBooleanValue(value.resourceID, from.intValue() > 0);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
import org.openhab.core.library.types.DecimalType;
/**
* DecimalType <-> WSEnumValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSEnumValueConverter implements Converter<WSEnumValue, DecimalType> {
@Override
public DecimalType convertFromResourceValue(@NonNull WSEnumValue from, @NonNull ConverterAdditionalInfo convertData)
throws ConversionException {
return new DecimalType(from.enumValueID);
}
@Override
public WSEnumValue convertFromOHType(@NonNull DecimalType from, @NonNull WSEnumValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSEnumValue(value.resourceID, value.definitionTypeID, from.intValue(), value.enumName);
}
}

View File

@@ -0,0 +1,48 @@
/**
* 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.ihc.internal.converters;
import java.math.BigDecimal;
import java.math.RoundingMode;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
import org.openhab.core.library.types.DecimalType;
/**
* DecimalType <-> WSFloatingPointValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSFloatingPointValueConverter implements Converter<WSFloatingPointValue, DecimalType> {
@Override
public DecimalType convertFromResourceValue(@NonNull WSFloatingPointValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
BigDecimal bd = new BigDecimal(from.value).setScale(2, RoundingMode.HALF_EVEN);
return new DecimalType(bd);
}
@Override
public WSFloatingPointValue convertFromOHType(@NonNull DecimalType from, @NonNull WSFloatingPointValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
if (from.doubleValue() >= value.minimumValue && from.doubleValue() <= value.maximumValue) {
return new WSFloatingPointValue(value.resourceID, from.doubleValue(), value.minimumValue,
value.maximumValue);
} else {
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
+ value.maximumValue + ")");
}
}
}

View File

@@ -0,0 +1,43 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.core.library.types.DecimalType;
/**
* DecimalType <-> WSIntegerValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSIntegerValueConverter implements Converter<WSIntegerValue, DecimalType> {
@Override
public DecimalType convertFromResourceValue(@NonNull WSIntegerValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new DecimalType(from.value);
}
@Override
public WSIntegerValue convertFromOHType(@NonNull DecimalType from, @NonNull WSIntegerValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
if (from.intValue() >= value.minimumValue && from.intValue() <= value.maximumValue) {
return new WSIntegerValue(value.resourceID, from.intValue(), value.minimumValue, value.maximumValue);
} else {
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
+ value.maximumValue + ")");
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
import org.openhab.core.library.types.DecimalType;
/**
* DecimalType <-> WSTimerValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSTimerValueConverter implements Converter<WSTimerValue, DecimalType> {
@Override
public DecimalType convertFromResourceValue(@NonNull WSTimerValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new DecimalType(from.milliseconds);
}
@Override
public WSTimerValue convertFromOHType(@NonNull DecimalType from, @NonNull WSTimerValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSTimerValue(value.resourceID, from.longValue());
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
import org.openhab.core.library.types.DecimalType;
/**
* DecimalType <-> WSWeekdayValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSWeekdayValueConverter implements Converter<WSWeekdayValue, DecimalType> {
@Override
public DecimalType convertFromResourceValue(@NonNull WSWeekdayValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new DecimalType(from.weekdayNumber);
}
@Override
public WSWeekdayValue convertFromOHType(@NonNull DecimalType from, @NonNull WSWeekdayValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSWeekdayValue(value.resourceID, from.intValue());
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.core.library.types.OnOffType;
/**
* OnOffType <-> WSBooleanValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class OnOffTypeWSBooleanValueConverter implements Converter<WSBooleanValue, OnOffType> {
@Override
public OnOffType convertFromResourceValue(@NonNull WSBooleanValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return from.value ^ convertData.getInverted() ? OnOffType.ON : OnOffType.OFF;
}
@Override
public WSBooleanValue convertFromOHType(@NonNull OnOffType from, @NonNull WSBooleanValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSBooleanValue(value.resourceID, from == OnOffType.ON ^ convertData.getInverted());
}
}

View File

@@ -0,0 +1,62 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.types.Command;
/**
* OnOffType <-> WSIntegerValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class OnOffTypeWSIntegerValueConverter implements Converter<WSIntegerValue, OnOffType> {
@Override
public OnOffType convertFromResourceValue(@NonNull WSIntegerValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return from.value > 0 ^ convertData.getInverted() ? OnOffType.ON : OnOffType.OFF;
}
@Override
public WSIntegerValue convertFromOHType(@NonNull OnOffType from, @NonNull WSIntegerValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
int onLevel = Math.min(value.maximumValue, getCommandLevel(value, convertData, OnOffType.ON));
int newVal = from == OnOffType.ON ? onLevel : value.minimumValue;
if (convertData.getInverted()) {
newVal = newVal == value.maximumValue ? value.minimumValue : value.maximumValue;
}
if (newVal >= value.minimumValue && newVal <= value.maximumValue) {
return new WSIntegerValue(value.resourceID, newVal, value.minimumValue, value.maximumValue);
} else {
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
+ value.maximumValue + ")");
}
}
private int getCommandLevel(@NonNull WSIntegerValue value, @NonNull ConverterAdditionalInfo convertData,
Command command) throws ConversionException {
try {
if (convertData.getCommandLevels() != null) {
return (int) convertData.getCommandLevels().get(command);
}
return value.maximumValue;
} catch (RuntimeException e) {
throw new ConversionException(e);
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.core.library.types.OpenClosedType;
/**
* OpenClosedType <-> WSBooleanValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class OpenClosedTypeWSBooleanValueConverter implements Converter<WSBooleanValue, OpenClosedType> {
@Override
public OpenClosedType convertFromResourceValue(@NonNull WSBooleanValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return from.value ^ convertData.getInverted() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
}
@Override
public WSBooleanValue convertFromOHType(@NonNull OpenClosedType from, @NonNull WSBooleanValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSBooleanValue(value.resourceID, from == OpenClosedType.OPEN ^ convertData.getInverted());
}
}

View File

@@ -0,0 +1,48 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.core.library.types.OpenClosedType;
/**
* OpenClosedType <-> WSIntegerValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class OpenClosedTypeWSIntegerValueConverter implements Converter<WSIntegerValue, OpenClosedType> {
@Override
public OpenClosedType convertFromResourceValue(@NonNull WSIntegerValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return from.value > 0 ^ convertData.getInverted() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
}
@Override
public WSIntegerValue convertFromOHType(@NonNull OpenClosedType from, @NonNull WSIntegerValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
int newVal = from == OpenClosedType.OPEN ? value.maximumValue : value.minimumValue;
if (convertData.getInverted()) {
newVal = newVal == value.maximumValue ? value.minimumValue : value.maximumValue;
}
if (newVal >= value.minimumValue && newVal <= value.maximumValue) {
return new WSIntegerValue(value.resourceID, newVal, value.minimumValue, value.maximumValue);
} else {
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
+ value.maximumValue + ")");
}
}
}

View File

@@ -0,0 +1,43 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.core.library.types.PercentType;
/**
* PercentType <-> WSIntegerValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class PercentTypeWSIntegerValueConverter implements Converter<WSIntegerValue, PercentType> {
@Override
public PercentType convertFromResourceValue(@NonNull WSIntegerValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new PercentType(from.value);
}
@Override
public WSIntegerValue convertFromOHType(@NonNull PercentType from, @NonNull WSIntegerValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
if (from.intValue() >= value.minimumValue && from.intValue() <= value.maximumValue) {
return new WSIntegerValue(value.resourceID, from.intValue(), value.minimumValue, value.maximumValue);
} else {
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
+ value.maximumValue + ")");
}
}
}

View File

@@ -0,0 +1,48 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
import org.openhab.core.library.types.StringType;
/**
* StringType <-> WSEnumValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class StringTypeWSEnumValueConverter implements Converter<WSEnumValue, StringType> {
@Override
public StringType convertFromResourceValue(@NonNull WSEnumValue from, @NonNull ConverterAdditionalInfo convertData)
throws ConversionException {
return new StringType(from.enumName);
}
@Override
public WSEnumValue convertFromOHType(@NonNull StringType from, @NonNull WSEnumValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
if (convertData.getEnumValues() != null) {
for (IhcEnumValue item : convertData.getEnumValues()) {
if (item.getName().equals(from.toString())) {
return new WSEnumValue(value.resourceID, value.definitionTypeID, item.getId(), item.getName());
}
}
throw new ConversionException("Can't find enum value for string " + value.toString());
} else {
throw new ConversionException("Enum list is null");
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.core.library.types.UpDownType;
/**
* UpDownType <-> WSBooleanValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class UpDownTypeWSBooleanValueConverter implements Converter<WSBooleanValue, UpDownType> {
@Override
public UpDownType convertFromResourceValue(@NonNull WSBooleanValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return from.value ^ convertData.getInverted() ? UpDownType.UP : UpDownType.DOWN;
}
@Override
public WSBooleanValue convertFromOHType(@NonNull UpDownType from, @NonNull WSBooleanValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return new WSBooleanValue(value.resourceID, from == UpDownType.UP ^ convertData.getInverted());
}
}

View File

@@ -0,0 +1,48 @@
/**
* 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.ihc.internal.converters;
import org.eclipse.jdt.annotation.NonNull;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.core.library.types.UpDownType;
/**
* UpDownType <-> WSIntegerValue converter.
*
* @author Pauli Anttila - Initial contribution
*/
public class UpDownTypeWSIntegerValueConverter implements Converter<WSIntegerValue, UpDownType> {
@Override
public UpDownType convertFromResourceValue(@NonNull WSIntegerValue from,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
return from.value > 0 ^ convertData.getInverted() ? UpDownType.UP : UpDownType.DOWN;
}
@Override
public WSIntegerValue convertFromOHType(@NonNull UpDownType from, @NonNull WSIntegerValue value,
@NonNull ConverterAdditionalInfo convertData) throws ConversionException {
int newVal = from == UpDownType.UP ? value.maximumValue : value.minimumValue;
if (convertData.getInverted()) {
newVal = newVal == value.maximumValue ? value.minimumValue : value.maximumValue;
}
if (newVal >= value.minimumValue && newVal <= value.maximumValue) {
return new WSIntegerValue(value.resourceID, newVal, value.minimumValue, value.maximumValue);
} else {
throw new ConversionException("Value is not between acceptable limits (min=" + value.minimumValue + ", max="
+ value.maximumValue + ")");
}
}
}

View File

@@ -0,0 +1,979 @@
/**
* 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.ihc.internal.handler;
import static org.openhab.binding.ihc.internal.IhcBindingConstants.*;
import java.io.File;
import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.openhab.binding.ihc.internal.ButtonPressDurationDetector;
import org.openhab.binding.ihc.internal.ChannelUtils;
import org.openhab.binding.ihc.internal.EnumDictionary;
import org.openhab.binding.ihc.internal.SignalLevelConverter;
import org.openhab.binding.ihc.internal.config.ChannelParams;
import org.openhab.binding.ihc.internal.config.IhcConfiguration;
import org.openhab.binding.ihc.internal.converters.Converter;
import org.openhab.binding.ihc.internal.converters.ConverterAdditionalInfo;
import org.openhab.binding.ihc.internal.converters.ConverterFactory;
import org.openhab.binding.ihc.internal.ws.IhcClient;
import org.openhab.binding.ihc.internal.ws.IhcClient.ConnectionState;
import org.openhab.binding.ihc.internal.ws.IhcEventListener;
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
import org.openhab.binding.ihc.internal.ws.datatypes.WSTimeManagerSettings;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.projectfile.IhcEnumValue;
import org.openhab.binding.ihc.internal.ws.projectfile.ProjectFileUtils;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.openhab.core.types.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
/**
* The {@link IhcHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcHandler extends BaseThingHandler implements IhcEventListener {
private final Logger logger = LoggerFactory.getLogger(IhcHandler.class);
/** Maximum pulse width in milliseconds. */
private static final int MAX_PULSE_WIDTH_IN_MS = 4000;
/** Maximum long press time in milliseconds. */
private static final int MAX_LONG_PRESS_IN_MS = 5000;
/** Name of the local IHC / ELKO project file */
private static final String LOCAL_IHC_PROJECT_FILE_NAME_TEMPLATE = "ihc-project-file-%s.xml";
/** Holds runtime notification reorder timeout in milliseconds */
private static final int NOTIFICATIONS_REORDER_WAIT_TIME = 1000;
/** IHC / ELKO LS Controller client */
private IhcClient ihc;
/**
* Reminder to slow down resource value notification ordering from
* controller.
*/
private ScheduledFuture<?> notificationsRequestReminder;
/** Holds local IHC / ELKO project file */
private Document projectFile;
/**
* Store current state of the controller, use to recognize when controller
* state is changed
*/
private String controllerState = "";
private IhcConfiguration conf;
private final Set<Integer> linkedResourceIds = Collections.synchronizedSet(new HashSet<>());
private Map<Integer, LocalDateTime> lastUpdate = new HashMap<>();
private EnumDictionary enumDictionary;
private boolean connecting = false;
private boolean reconnectRequest = false;
private boolean valueNotificationRequest = false;
private ScheduledFuture<?> controlJob;
private ScheduledFuture<?> pollingJobRf;
private Map<String, ScheduledFuture<?>> longPressFutures = new HashMap<>();
public IhcHandler(Thing thing) {
super(thing);
}
protected boolean isValueNotificationRequestActivated() {
synchronized (this) {
return valueNotificationRequest;
}
}
protected void setValueNotificationRequest(boolean valueNotificationRequest) {
synchronized (this) {
this.valueNotificationRequest = valueNotificationRequest;
}
}
protected boolean isReconnectRequestActivated() {
synchronized (this) {
return reconnectRequest;
}
}
protected void setReconnectRequest(boolean reconnect) {
synchronized (this) {
this.reconnectRequest = reconnect;
}
}
protected boolean isConnecting() {
synchronized (this) {
return connecting;
}
}
protected void setConnectingState(boolean value) {
synchronized (this) {
this.connecting = value;
}
}
private String getFilePathInUserDataFolder(String fileName) {
String progArg = System.getProperty("smarthome.userdata");
if (progArg != null) {
return progArg + File.separator + fileName;
}
return fileName;
}
@Override
public void initialize() {
conf = getConfigAs(IhcConfiguration.class);
logger.debug("Using configuration: {}", conf);
linkedResourceIds.clear();
linkedResourceIds.addAll(getAllLinkedChannelsResourceIds());
logger.debug("Linked resources {}: {}", linkedResourceIds.size(), linkedResourceIds);
if (controlJob == null || controlJob.isCancelled()) {
logger.debug("Start control task, interval={}sec", 1);
controlJob = scheduler.scheduleWithFixedDelay(this::reconnectCheck, 0, 1, TimeUnit.SECONDS);
}
}
@Override
public void dispose() {
logger.debug("Stopping thing");
if (controlJob != null && !controlJob.isCancelled()) {
controlJob.cancel(true);
controlJob = null;
}
disconnect();
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Received channel: {}, command: {}", channelUID, command);
if (ihc == null) {
logger.warn("Connection is not initialized, abort resource value update for channel '{}'!", channelUID);
return;
}
if (ihc.getConnectionState() != ConnectionState.CONNECTED) {
logger.warn("Connection to controller is not open, abort resource value update for channel '{}'!",
channelUID);
return;
}
switch (channelUID.getId()) {
case CHANNEL_CONTROLLER_STATE:
if (command.equals(RefreshType.REFRESH)) {
updateControllerStateChannel();
}
break;
case CHANNEL_CONTROLLER_UPTIME:
if (command.equals(RefreshType.REFRESH)) {
updateControllerInformationChannels();
}
break;
case CHANNEL_CONTROLLER_TIME:
if (command.equals(RefreshType.REFRESH)) {
updateControllerTimeChannels();
}
break;
default:
if (command.equals(RefreshType.REFRESH)) {
refreshChannel(channelUID);
} else {
updateResourceChannel(channelUID, command);
}
break;
}
}
private void refreshChannel(ChannelUID channelUID) {
logger.debug("REFRESH channel {}", channelUID);
Channel channel = thing.getChannel(channelUID.getId());
if (channel != null) {
try {
ChannelParams params = new ChannelParams(channel);
logger.debug("Channel params: {}", params);
if (params.isDirectionWriteOnly()) {
logger.warn("Write only channel, skip refresh command to {}", channelUID);
return;
}
WSResourceValue value = ihc.resourceQuery(params.getResourceId());
resourceValueUpdateReceived(value);
} catch (IhcExecption e) {
logger.warn("Can't update channel '{}' value, reason: {}", channelUID, e.getMessage(), e);
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
}
}
}
private void updateControllerStateChannel() {
try {
String state = ihc.getControllerState().getState();
String value;
switch (state) {
case IhcClient.CONTROLLER_STATE_INITIALIZE:
value = "Initialize";
break;
case IhcClient.CONTROLLER_STATE_READY:
value = "Ready";
break;
default:
value = "Unknown state: " + state;
}
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_STATE), new StringType(value));
} catch (IhcExecption e) {
logger.warn("Controller state information fetch failed, reason: {}", e.getMessage(), e);
}
}
private void updateControllerProperties() {
try {
WSSystemInfo systemInfo = ihc.getSystemInfo();
logger.debug("Controller information: {}", systemInfo);
WSProjectInfo projectInfo = ihc.getProjectInfo();
logger.debug("Project information: {}", projectInfo);
Map<String, String> properties = editProperties();
properties.put(PROPERTY_MANUFACTURER, systemInfo.getBrand());
properties.put(PROPERTY_SERIALNUMBER, systemInfo.getSerialNumber());
properties.put(PROPERTY_SW_VERSION, systemInfo.getVersion());
properties.put(PROPERTY_FW_VERSION, systemInfo.getHwRevision());
properties.put(PROPERTY_APP_WITHOUT_VIEWER, Boolean.toString(systemInfo.getApplicationIsWithoutViewer()));
properties.put(PROPERTY_SW_DATE,
systemInfo.getSwDate().withZoneSameInstant(ZoneId.systemDefault()).toString());
properties.put(PROPERTY_PRODUCTION_DATE, systemInfo.getProductionDate());
if (!systemInfo.getDatalineVersion().isEmpty()) {
properties.put(PROPERTY_DATALINE_VERSION, systemInfo.getDatalineVersion());
}
if (!systemInfo.getRfModuleSerialNumber().isEmpty()) {
properties.put(PROPERTY_RF_MODULE_SERIALNUMBER, systemInfo.getRfModuleSerialNumber());
}
if (!systemInfo.getRfModuleSoftwareVersion().isEmpty()) {
properties.put(PROPERTY_RF_MODULE_VERSION, systemInfo.getRfModuleSoftwareVersion());
}
properties.put(PROPERTY_PROJECT_DATE,
projectInfo.getLastmodified().getAsLocalDateTime().atZone(ZoneId.systemDefault()).toString());
properties.put(PROPERTY_PROJECT_NUMBER, projectInfo.getProjectNumber());
updateProperties(properties);
} catch (IhcExecption e) {
logger.warn("Controller information fetch failed, reason: {}", e.getMessage(), e);
}
}
private void updateControllerInformationChannels() {
try {
WSSystemInfo systemInfo = ihc.getSystemInfo();
logger.debug("Controller information: {}", systemInfo);
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_UPTIME),
new DecimalType((double) systemInfo.getUptime() / 1000));
} catch (IhcExecption e) {
logger.warn("Controller uptime information fetch failed, reason: {}.", e.getMessage(), e);
}
}
private void updateControllerTimeChannels() {
try {
WSTimeManagerSettings timeSettings = ihc.getTimeSettings();
logger.debug("Controller time settings: {}", timeSettings);
ZonedDateTime time = timeSettings.getTimeAndDateInUTC().getAsZonedDateTime(ZoneId.of("Z"))
.withZoneSameInstant(ZoneId.systemDefault());
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_TIME), new DateTimeType(time));
} catch (IhcExecption e) {
logger.warn("Controller uptime information fetch failed, reason: {}.", e.getMessage(), e);
}
}
private void updateResourceChannel(ChannelUID channelUID, Command command) {
Channel channel = thing.getChannel(channelUID.getId());
if (channel != null) {
try {
ChannelParams params = new ChannelParams(channel);
logger.debug("Channel params: {}", params);
if (params.isDirectionReadOnly()) {
logger.debug("Read only channel, skip the update to {}", channelUID);
return;
}
updateChannel(channelUID, params, command);
} catch (IhcExecption e) {
logger.warn("Can't update channel '{}' value, cause {}", channelUID, e.getMessage());
} catch (ConversionException e) {
logger.debug("Conversion error for channel {}, reason: {}", channelUID, e.getMessage());
}
}
}
private void updateChannel(ChannelUID channelUID, ChannelParams params, Command command)
throws IhcExecption, ConversionException {
if (params.getCommandToReact() != null) {
if (command.toString().equals(params.getCommandToReact())) {
logger.debug("Command '{}' equal to channel reaction parameter '{}', execute it", command,
params.getCommandToReact());
} else {
logger.debug("Command '{}' doesn't equal to reaction trigger parameter '{}', skip it", command,
params.getCommandToReact());
return;
}
}
WSResourceValue value = ihc.getResourceValueInformation(params.getResourceId());
if (value != null) {
if (params.getPulseWidth() != null) {
sendPulseCommand(channelUID, params, value, Math.min(params.getPulseWidth(), MAX_PULSE_WIDTH_IN_MS));
} else {
sendNormalCommand(channelUID, params, command, value);
}
}
}
private void sendNormalCommand(ChannelUID channelUID, ChannelParams params, Command command, WSResourceValue value)
throws IhcExecption, ConversionException {
logger.debug("Send command '{}' to resource '{}'", command, value.resourceID);
ConverterAdditionalInfo converterAdditionalInfo = new ConverterAdditionalInfo(getEnumValues(value),
params.isInverted(), getCommandLevels(params));
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(value.getClass(),
command.getClass());
if (converter != null) {
WSResourceValue val = converter.convertFromOHType(command, value, converterAdditionalInfo);
logger.debug("Update resource value (inverted output={}): {}", params.isInverted(), val);
if (!updateResource(val)) {
logger.warn("Channel {} update to resource '{}' failed.", channelUID, val);
}
} else {
logger.debug("No converter implemented for {} <-> {}", value.getClass(), command.getClass());
}
}
private List<IhcEnumValue> getEnumValues(WSResourceValue value) {
if (value instanceof WSEnumValue) {
return enumDictionary.getEnumValues(((WSEnumValue) value).definitionTypeID);
}
return null;
}
private void sendPulseCommand(ChannelUID channelUID, ChannelParams params, WSResourceValue value,
Integer pulseWidth) throws IhcExecption, ConversionException {
logger.debug("Send {}ms pulse to resource: {}", pulseWidth, value.resourceID);
logger.debug("Channel params: {}", params);
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(value.getClass(),
OnOffType.class);
if (converter != null) {
ConverterAdditionalInfo converterAdditionalInfo = new ConverterAdditionalInfo(null, params.isInverted(),
getCommandLevels(params));
WSResourceValue valOn = converter.convertFromOHType(OnOffType.ON, value, converterAdditionalInfo);
WSResourceValue valOff = converter.convertFromOHType(OnOffType.OFF, value, converterAdditionalInfo);
// set resource to ON
logger.debug("Update resource value (inverted output={}): {}", params.isInverted(), valOn);
if (updateResource(valOn)) {
logger.debug("Sleeping: {}ms", pulseWidth);
scheduler.schedule(new Runnable() {
@Override
public void run() {
// set resource back to OFF
logger.debug("Update resource value (inverted output={}): {}", params.isInverted(), valOff);
try {
if (!updateResource(valOff)) {
logger.warn("Channel {} update to resource '{}' failed.", channelUID, valOff);
}
} catch (IhcExecption e) {
logger.warn("Can't update channel '{}' value, cause {}", channelUID, e.getMessage());
}
}
}, pulseWidth, TimeUnit.MILLISECONDS);
} else {
logger.warn("Channel {} update failed.", channelUID);
}
} else {
logger.debug("No converter implemented for {} <-> {}", value.getClass(), OnOffType.class);
}
}
/**
* Update resource value to IHC controller.
*/
private boolean updateResource(WSResourceValue value) throws IhcExecption {
boolean result = false;
try {
result = ihc.resourceUpdate(value);
} catch (IhcExecption e) {
logger.warn("Value could not be updated - retrying one time: {}.", e.getMessage(), e);
result = ihc.resourceUpdate(value);
}
return result;
}
@Override
public void channelLinked(ChannelUID channelUID) {
logger.debug("channelLinked: {}", channelUID);
switch (channelUID.getId()) {
case CHANNEL_CONTROLLER_STATE:
updateControllerStateChannel();
break;
case CHANNEL_CONTROLLER_UPTIME:
updateControllerInformationChannels();
break;
case CHANNEL_CONTROLLER_TIME:
updateControllerTimeChannels();
break;
default:
Channel channel = thing.getChannel(channelUID.getId());
if (channel != null) {
try {
ChannelParams params = new ChannelParams(channel);
if (params.getResourceId() != null) {
if (!linkedResourceIds.contains(params.getResourceId())) {
logger.debug("New channel '{}' found, resource id '{}'", channelUID.getAsString(),
params.getResourceId());
linkedResourceIds.add(params.getResourceId());
updateNotificationsRequestReminder();
}
}
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
}
}
}
}
@Override
public void channelUnlinked(ChannelUID channelUID) {
logger.debug("channelUnlinked: {}", channelUID);
switch (channelUID.getId()) {
case CHANNEL_CONTROLLER_STATE:
case CHANNEL_CONTROLLER_UPTIME:
case CHANNEL_CONTROLLER_TIME:
break;
default:
Channel channel = thing.getChannel(channelUID.getId());
if (channel != null) {
try {
ChannelParams params = new ChannelParams(channel);
if (params.getResourceId() != null) {
linkedResourceIds.removeIf(c -> c.equals(params.getResourceId()));
updateNotificationsRequestReminder();
}
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
}
}
}
}
/**
* Initialize IHC client and open connection to IHC / ELKO LS controller.
*
*/
private void connect() throws IhcExecption {
try {
setConnectingState(true);
logger.debug("Connecting to IHC / ELKO LS controller [hostname='{}', username='{}'].", conf.hostname,
conf.username);
ihc = new IhcClient(conf.hostname, conf.username, conf.password, conf.timeout);
ihc.openConnection();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
"Initializing communication to the IHC / ELKO controller");
loadProject();
createChannels();
updateControllerProperties();
updateControllerStateChannel();
updateControllerInformationChannels();
updateControllerTimeChannels();
ihc.addEventListener(this);
ihc.startControllerEventListeners();
updateNotificationsRequestReminder();
startRFPolling();
updateStatus(ThingStatus.ONLINE);
} finally {
setConnectingState(false);
}
}
private void loadProject() throws IhcExecption {
if (conf.loadProjectFile) {
String fileName = String.format(LOCAL_IHC_PROJECT_FILE_NAME_TEMPLATE, thing.getUID().getId());
String filePath = getFilePathInUserDataFolder(fileName);
boolean loadProject = false;
if (projectFile == null) {
// try first load project file from local cache file.
try {
projectFile = ProjectFileUtils.readFromFile(filePath);
} catch (IhcExecption e) {
logger.debug("Error occured when read project file from file '{}', reason {}", filePath,
e.getMessage(), e);
loadProject = true;
}
}
if (!ProjectFileUtils.projectEqualsToControllerProject(projectFile, ihc.getProjectInfo())) {
logger.debug(
"Local project file is not same as in the controller, reload project file from controller!");
loadProject = true;
}
if (loadProject) {
logger.debug("Loading IHC /ELKO LS project file from controller...");
byte[] data = ihc.getProjectFileFromController();
logger.debug("Saving project file to local file '{}'", filePath);
try {
ProjectFileUtils.saveToFile(filePath, data);
} catch (IhcExecption e) {
logger.warn("Error occured when trying to write data to file '{}', reason {}", filePath,
e.getMessage(), e);
}
projectFile = ProjectFileUtils.converteBytesToDocument(data);
}
}
enumDictionary = new EnumDictionary(ProjectFileUtils.parseEnums(projectFile));
}
private void createChannels() {
if (conf.loadProjectFile && conf.createChannelsAutomatically) {
logger.debug("Creating channels");
List<Channel> thingChannels = new ArrayList<>();
thingChannels.addAll(getThing().getChannels());
ChannelUtils.addControllerChannels(getThing(), thingChannels);
ChannelUtils.addChannelsFromProjectFile(getThing(), projectFile, thingChannels);
printChannels(thingChannels);
updateThing(editThing().withChannels(thingChannels).build());
} else {
logger.debug("Automatic channel creation disabled");
}
}
private void printChannels(List<Channel> thingChannels) {
if (logger.isDebugEnabled()) {
thingChannels.forEach(channel -> {
if (channel != null) {
String resourceId;
try {
Object id = channel.getConfiguration().get(PARAM_RESOURCE_ID);
resourceId = id != null ? "0x" + Integer.toHexString(((BigDecimal) id).intValue()) : "";
} catch (IllegalArgumentException e) {
resourceId = "";
}
String channelType = channel.getAcceptedItemType() != null ? channel.getAcceptedItemType() : "";
String channelLabel = channel.getLabel() != null ? channel.getLabel() : "";
logger.debug("Channel: {}", String.format("%-55s | %-10s | %-10s | %s", channel.getUID(),
resourceId, channelType, channelLabel));
}
});
}
}
private void startRFPolling() {
if (pollingJobRf == null || pollingJobRf.isCancelled()) {
logger.debug("Start RF device refresh task, interval={}sec", 60);
pollingJobRf = scheduler.scheduleWithFixedDelay(this::updateRfDeviceStates, 10, 60, TimeUnit.SECONDS);
}
}
/**
* Disconnect connection to IHC / ELKO LS controller.
*
*/
private void disconnect() {
cancelAllLongPressTasks();
if (pollingJobRf != null && !pollingJobRf.isCancelled()) {
pollingJobRf.cancel(true);
pollingJobRf = null;
}
if (ihc != null) {
try {
ihc.removeEventListener(this);
ihc.closeConnection();
ihc = null;
} catch (IhcExecption e) {
logger.warn("Couldn't close connection to IHC controller", e);
}
}
clearLastUpdateTimeCache();
}
private void clearLastUpdateTimeCache() {
lastUpdate.clear();
}
@Override
public void errorOccured(IhcExecption e) {
logger.warn("Error occurred on communication to IHC controller: {}", e.getMessage(), e);
logger.debug("Reconnection request");
setReconnectRequest(true);
}
@Override
public void statusUpdateReceived(WSControllerState newState) {
logger.debug("Controller state: {}", newState.getState());
if (!controllerState.equals(newState.getState())) {
logger.debug("Controller state change detected ({} -> {})", controllerState, newState.getState());
switch (newState.getState()) {
case IhcClient.CONTROLLER_STATE_INITIALIZE:
logger.info("Controller state changed to initializing state, waiting for ready state");
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_STATE),
new StringType("initialize"));
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE,
"Controller is in initializing state");
break;
case IhcClient.CONTROLLER_STATE_READY:
logger.info("Controller state changed to ready state");
updateState(new ChannelUID(getThing().getUID(), CHANNEL_CONTROLLER_STATE), new StringType("ready"));
updateStatus(ThingStatus.ONLINE);
break;
default:
}
if (controllerState.equals(IhcClient.CONTROLLER_STATE_INITIALIZE)
&& newState.getState().equals(IhcClient.CONTROLLER_STATE_READY)) {
logger.debug("Reconnection request");
projectFile = null;
setReconnectRequest(true);
}
}
controllerState = newState.getState();
}
@Override
public void resourceValueUpdateReceived(WSResourceValue value) {
logger.debug("resourceValueUpdateReceived: {}", value);
thing.getChannels().forEach(channel -> {
try {
ChannelParams params = new ChannelParams(channel);
if (params.getResourceId() != null && params.getResourceId().intValue() == value.resourceID) {
updateChannelState(channel, params, value);
}
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
} catch (RuntimeException e) {
logger.warn("Unknown error occured, reason: {}.", e.getMessage(), e);
}
});
checkPotentialButtonPresses(value);
}
private void updateChannelState(Channel channel, ChannelParams params, WSResourceValue value) {
if (params.isDirectionWriteOnly()) {
logger.debug("Write only channel, skip update to {}", channel.getUID());
} else {
if (params.getChannelTypeId() != null) {
switch (params.getChannelTypeId()) {
case CHANNEL_TYPE_PUSH_BUTTON_TRIGGER:
break;
default:
try {
logger.debug("Update channel '{}' state, channel params: {}", channel.getUID(), params);
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance()
.getConverter(value.getClass(), channel.getAcceptedItemType());
if (converter != null) {
State state = (State) converter.convertFromResourceValue(value,
new ConverterAdditionalInfo(null, params.isInverted(),
getCommandLevels(params)));
updateState(channel.getUID(), state);
} else {
logger.debug("No converter implemented for {} <-> {}", value.getClass(),
channel.getAcceptedItemType());
}
} catch (ConversionException e) {
logger.debug("Can't convert resource value '{}' to item type {}, reason: {}.", value,
channel.getAcceptedItemType(), e.getMessage(), e);
}
}
}
}
}
private void checkPotentialButtonPresses(WSResourceValue value) {
if (value instanceof WSBooleanValue) {
if (((WSBooleanValue) value).value) {
// potential button press
lastUpdate.put(value.resourceID, LocalDateTime.now());
updateTriggers(value.resourceID, Duration.ZERO);
} else {
// potential button release
LocalDateTime lastUpdateTime = lastUpdate.get(value.resourceID);
if (lastUpdateTime != null) {
Duration duration = Duration.between(lastUpdateTime, LocalDateTime.now());
logger.debug("Time between uddates: {}", duration);
updateTriggers(value.resourceID, duration);
}
}
}
}
private void updateTriggers(int resourceId, Duration duration) {
thing.getChannels().forEach(channel -> {
try {
ChannelParams params = new ChannelParams(channel);
if (params.getResourceId() != null && params.getResourceId().intValue() == resourceId) {
if (params.getChannelTypeId() != null) {
switch (params.getChannelTypeId()) {
case CHANNEL_TYPE_PUSH_BUTTON_TRIGGER:
logger.debug("Update trigger channel '{}', channel params: {}",
channel.getUID().getId(), params);
if (duration.toMillis() == 0) {
triggerChannel(channel.getUID().getId(), EVENT_PRESSED);
createLongPressTask(channel.getUID().getId(), params.getLongPressTime());
} else {
cancelLongPressTask(channel.getUID().getId());
triggerChannel(channel.getUID().getId(), EVENT_RELEASED);
triggerChannel(channel.getUID().getId(), String.valueOf(duration.toMillis()));
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration,
params.getLongPressTime(), MAX_LONG_PRESS_IN_MS);
logger.debug("resourceId={}, ButtonPressDurationDetector={}", resourceId, button);
if (button.isShortPress()) {
triggerChannel(channel.getUID().getId(), EVENT_SHORT_PRESS);
}
break;
}
}
}
}
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}", e.getMessage(), e);
}
});
}
private void createLongPressTask(String channelId, long longPressTimeInMs) {
if (longPressFutures.containsKey(channelId)) {
cancelLongPressTask(channelId);
}
logger.debug("Create long press task for channel '{}'", channelId);
longPressFutures.put(channelId, scheduler.schedule(() -> triggerChannel(channelId, EVENT_LONG_PRESS),
longPressTimeInMs, TimeUnit.MILLISECONDS));
}
private void cancelLongPressTask(String channelId) {
if (longPressFutures.containsKey(channelId)) {
logger.debug("Cancel long press task for channel '{}'", channelId);
longPressFutures.get(channelId).cancel(false);
longPressFutures.remove(channelId);
}
}
private void cancelAllLongPressTasks() {
longPressFutures.entrySet().parallelStream().forEach(e -> e.getValue().cancel(true));
longPressFutures.clear();
}
private void updateRfDeviceStates() {
if (ihc != null) {
if (ihc.getConnectionState() != ConnectionState.CONNECTED) {
logger.debug("Controller is connecting, abort subscribe");
return;
}
logger.debug("Update RF device data");
try {
List<WSRFDevice> devs = ihc.getDetectedRFDevices();
logger.debug("RF data: {}", devs);
devs.forEach(dev -> {
thing.getChannels().forEach(channel -> {
try {
ChannelParams params = new ChannelParams(channel);
if (params.getSerialNumber() != null
&& params.getSerialNumber().longValue() == dev.getSerialNumber()) {
String channelId = channel.getUID().getId();
if (params.getChannelTypeId() != null) {
switch (params.getChannelTypeId()) {
case CHANNEL_TYPE_RF_LOW_BATTERY:
updateState(channelId,
dev.getBatteryLevel() == 1 ? OnOffType.OFF : OnOffType.ON);
break;
case CHANNEL_TYPE_RF_SIGNAL_STRENGTH:
int signalLevel = new SignalLevelConverter(dev.getSignalStrength())
.getSystemWideSignalLevel();
updateState(channelId, new StringType(String.valueOf(signalLevel)));
break;
}
}
}
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}", e.getMessage(), e);
}
});
});
} catch (IhcExecption e) {
logger.debug("Error occured when fetching RF device information, reason: : {} ", e.getMessage(), e);
return;
}
}
}
private void reconnectCheck() {
if (ihc == null || isReconnectRequestActivated()) {
try {
if (ihc != null) {
disconnect();
}
connect();
setReconnectRequest(false);
} catch (IhcExecption e) {
logger.debug("Can't open connection to controller {}", e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
setReconnectRequest(true);
return;
}
}
if (isValueNotificationRequestActivated() && !isConnecting()) {
try {
enableResourceValueNotifications();
} catch (IhcExecption e) {
logger.warn("Can't enable resource value notifications from controller. ", e);
}
}
}
private Set<Integer> getAllLinkedChannelsResourceIds() {
Set<Integer> resourceIds = Collections.synchronizedSet(new HashSet<>());
resourceIds.addAll(this.getThing().getChannels().stream().filter(c -> isLinked(c.getUID())).map(c -> {
try {
ChannelParams params = new ChannelParams(c);
logger.debug("Linked channel '{}' found, resource id '{}'", c.getUID().getAsString(),
params.getResourceId());
return params.getResourceId();
} catch (ConversionException e) {
logger.warn("Channel param error, reason: {}.", e.getMessage(), e);
return null;
}
}).filter(c -> c != null && c != 0).collect(Collectors.toSet()));
return resourceIds;
}
/**
* Order resource value notifications from IHC controller.
*/
private void enableResourceValueNotifications() throws IhcExecption {
logger.debug("Subscribe resource runtime value notifications");
if (ihc != null) {
if (ihc.getConnectionState() != ConnectionState.CONNECTED) {
logger.debug("Controller is connecting, abort subscribe");
return;
}
setValueNotificationRequest(false);
Set<Integer> resourceIds = ChannelUtils.getAllTriggerChannelsResourceIds(getThing());
logger.debug("Enable runtime notfications for {} trigger(s)", resourceIds.size());
logger.debug("Enable runtime notfications for {} channel(s)", linkedResourceIds.size());
resourceIds.addAll(linkedResourceIds);
resourceIds.addAll(getAllLinkedChannelsResourceIds());
logger.debug("Enable runtime notfications for {} resources: {}", resourceIds.size(), resourceIds);
if (!resourceIds.isEmpty()) {
try {
ihc.enableRuntimeValueNotifications(resourceIds);
} catch (IhcExecption e) {
logger.debug("Reconnection request");
setReconnectRequest(true);
}
}
} else {
logger.warn("Controller is not initialized!");
logger.debug("Reconnection request");
setReconnectRequest(true);
}
}
private synchronized void updateNotificationsRequestReminder() {
if (notificationsRequestReminder != null) {
notificationsRequestReminder.cancel(false);
}
logger.debug("Rechedule resource runtime value notifications order by {}ms", NOTIFICATIONS_REORDER_WAIT_TIME);
notificationsRequestReminder = scheduler.schedule(new Runnable() {
@Override
public void run() {
logger.debug("Delayed resource value notifications request is now enabled");
setValueNotificationRequest(true);
}
}, NOTIFICATIONS_REORDER_WAIT_TIME, TimeUnit.MILLISECONDS);
}
private Map<Command, Object> getCommandLevels(ChannelParams params) {
if (params.getOnLevel() != null) {
Map<Command, Object> commandLevels = new HashMap<>();
commandLevels.put(OnOffType.ON, params.getOnLevel());
return Collections.unmodifiableMap(commandLevels);
}
return null;
}
}

View File

@@ -0,0 +1,67 @@
/**
* 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.ihc.internal.profiles;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.profiles.Profile;
import org.openhab.core.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileContext;
import org.openhab.core.thing.profiles.ProfileFactory;
import org.openhab.core.thing.profiles.ProfileType;
import org.openhab.core.thing.profiles.ProfileTypeProvider;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.osgi.service.component.annotations.Component;
/**
* A factory for IHC / ELKO profiles.
*
* @author Pauli Anttila - initial contribution.
*
*/
@NonNullByDefault
@Component(service = { ProfileFactory.class, ProfileTypeProvider.class })
public class IhcProfileFactory implements ProfileFactory, ProfileTypeProvider {
private static final Set<ProfileType> SUPPORTED_PROFILE_TYPES = Stream.of(IhcProfiles.PUSHBUTTON_COMMAND_TYPE)
.collect(Collectors.toSet());
private static final Set<ProfileTypeUID> SUPPORTED_PROFILE_TYPE_UIDS = Stream.of(IhcProfiles.PUSHBUTTON_COMMAND)
.collect(Collectors.toSet());
@Nullable
@Override
public Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback, ProfileContext context) {
if (IhcProfiles.PUSHBUTTON_COMMAND.equals(profileTypeUID)) {
return new PushButtonToCommandProfile(callback, context);
} else {
return null;
}
}
@Override
public Collection<ProfileType> getProfileTypes(@Nullable Locale locale) {
return SUPPORTED_PROFILE_TYPES;
}
@Override
public Collection<ProfileTypeUID> getSupportedProfileTypeUIDs() {
return SUPPORTED_PROFILE_TYPE_UIDS;
}
}

View File

@@ -0,0 +1,37 @@
/**
* 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.ihc.internal.profiles;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.CoreItemFactory;
import org.openhab.core.thing.profiles.ProfileTypeBuilder;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.openhab.core.thing.profiles.TriggerProfileType;
/**
* IHC / ELKO profile constants.
*
* @author Pauli Anttila - initial contribution.
*
*/
@NonNullByDefault
public interface IhcProfiles {
ProfileTypeUID PUSHBUTTON_COMMAND = new ProfileTypeUID("ihc", "pushbutton-to-command");
TriggerProfileType PUSHBUTTON_COMMAND_TYPE = ProfileTypeBuilder
.newTrigger(PUSHBUTTON_COMMAND, "Push Button To Command")
.withSupportedItemTypes(CoreItemFactory.DIMMER, CoreItemFactory.ROLLERSHUTTER, CoreItemFactory.CONTACT,
CoreItemFactory.SWITCH, CoreItemFactory.PLAYER)
.build();
}

View File

@@ -0,0 +1,249 @@
/**
* 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.ihc.internal.profiles;
import java.math.BigDecimal;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.ihc.internal.IhcBindingConstants;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.NextPreviousType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PlayPauseType;
import org.openhab.core.library.types.RewindFastforwardType;
import org.openhab.core.library.types.StopMoveType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.thing.profiles.ProfileCallback;
import org.openhab.core.thing.profiles.ProfileContext;
import org.openhab.core.thing.profiles.ProfileTypeUID;
import org.openhab.core.thing.profiles.TriggerProfile;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link PushButtonToCommandProfile} transforms push button channel events to commands.
*
* @author Pauli Anttila - Initial contribution
*/
@NonNullByDefault
public class PushButtonToCommandProfile implements TriggerProfile {
private final Logger logger = LoggerFactory.getLogger(PushButtonToCommandProfile.class);
private static final String PARAM_SHORT_PRESS_COMMAND = "short-press-command";
private static final String PARAM_LONG_PRESS_COMMAND = "long-press-command";
private static final String PARAM_LONG_PRESS_TIME = "long-press-time";
private static final String PARAM_REPEAT_TIME = "repeat-time";
private static final String PARAM_TIMEOUT_TIME = "timeout";
private static final Command DEF_SHORT_PRESS_COMMAND = OnOffType.ON;
private static final Command DEF_LONG_PRESS_COMMAND = IncreaseDecreaseType.INCREASE;
private static final long DEF_LONG_PRESS_TIME = 1000;
private static final long DEF_REPEAT_TIME = 200;
private static final long DEF_TIMEOUT_TIME = 10000;
private final ProfileCallback callback;
private final ProfileContext context;
@Nullable
private Command shortPressCommand;
@Nullable
private Command longPressCommand;
@Nullable
private ScheduledFuture<?> dimmFuture;
@Nullable
private ScheduledFuture<?> timeoutFuture;
@Nullable
private State previousState;
private long pressedTime = 0;
private long longPressTime;
private long repeatTime;
private long timeout;
PushButtonToCommandProfile(ProfileCallback callback, ProfileContext context) {
this.callback = callback;
this.context = context;
shortPressCommand = getParamAsCommand(PARAM_SHORT_PRESS_COMMAND, DEF_SHORT_PRESS_COMMAND);
longPressCommand = getParamAsCommand(PARAM_LONG_PRESS_COMMAND, DEF_LONG_PRESS_COMMAND);
longPressTime = getParamAsLong(PARAM_LONG_PRESS_TIME, DEF_LONG_PRESS_TIME);
repeatTime = getParamAsLong(PARAM_REPEAT_TIME, DEF_REPEAT_TIME);
timeout = getParamAsLong(PARAM_TIMEOUT_TIME, DEF_TIMEOUT_TIME);
}
private long getParamAsLong(String param, long defValue) {
long retval;
Object paramValue = context.getConfiguration().get(param);
logger.debug("Configuring profile with {} parameter '{}'", param, paramValue);
if (paramValue instanceof BigDecimal) {
retval = ((BigDecimal) paramValue).longValue();
} else {
logger.debug("Parameter '{}' is not of type BigDecimal, using default value '{}'", param, defValue);
retval = defValue;
}
return retval;
}
private @Nullable Command getParamAsCommand(String param, Command defValue) {
Command retval;
Object paramValue = context.getConfiguration().get(param);
logger.debug("Configuring profile with {} parameter '{}'", param, paramValue);
if (paramValue instanceof String) {
try {
retval = convertStringToCommand(String.valueOf(paramValue));
} catch (IllegalArgumentException e) {
logger.warn("Parameter '{}' is not a valid command type, using default value '{}'", param, defValue);
retval = defValue;
}
} else {
logger.debug("Parameter '{}' is not of type String, using default value '{}'", param, defValue);
retval = defValue;
}
return retval;
}
private @Nullable Command convertStringToCommand(String str) throws IllegalArgumentException {
Command retval = null;
switch (str) {
case "ON":
retval = OnOffType.ON;
break;
case "OFF":
retval = OnOffType.OFF;
break;
case "STOP":
retval = StopMoveType.STOP;
break;
case "MOVE":
retval = StopMoveType.MOVE;
break;
case "PLAY":
retval = PlayPauseType.PLAY;
break;
case "PAUSE":
retval = PlayPauseType.PAUSE;
break;
case "NEXT":
retval = NextPreviousType.NEXT;
break;
case "PREVIOUS":
retval = NextPreviousType.PREVIOUS;
break;
case "FASTFORWARD":
retval = RewindFastforwardType.FASTFORWARD;
break;
case "REWIND":
retval = RewindFastforwardType.REWIND;
break;
case "INCREASE":
retval = IncreaseDecreaseType.INCREASE;
break;
case "DECREASE":
retval = IncreaseDecreaseType.DECREASE;
break;
case "UP":
retval = UpDownType.UP;
break;
case "DOWN":
retval = UpDownType.DOWN;
break;
case "TOGGLE":
break; // return null
default:
throw new IllegalArgumentException("Illegal argument '" + str + "'");
}
return retval;
}
@Override
public ProfileTypeUID getProfileTypeUID() {
return IhcProfiles.PUSHBUTTON_COMMAND;
}
@Override
public void onStateUpdateFromItem(State state) {
previousState = state;
}
@Override
public void onTriggerFromHandler(String event) {
if (IhcBindingConstants.EVENT_PRESSED.equals(event)) {
buttonPressed(toggleCommandIfNeeded(longPressCommand));
} else if (IhcBindingConstants.EVENT_RELEASED.equals(event)) {
buttonReleased(toggleCommandIfNeeded(shortPressCommand));
}
}
private Command toggleCommandIfNeeded(@Nullable Command command) {
if (command == null) {
logger.debug("Toggling command: previous state is '{}'", previousState);
return OnOffType.ON.equals(previousState) ? OnOffType.OFF : OnOffType.ON;
}
return command;
}
private synchronized void buttonPressed(Command commandToSend) {
cancelTimeoutFuture();
cancelDimmFuture();
if (repeatTime > 0) {
// run repeatedly
dimmFuture = context.getExecutorService().scheduleWithFixedDelay(() -> callback.sendCommand(commandToSend),
longPressTime + 50, repeatTime, TimeUnit.MILLISECONDS);
timeoutFuture = context.getExecutorService().schedule(() -> this.cancelDimmFuture(), timeout,
TimeUnit.MILLISECONDS);
} else {
// run only ones
dimmFuture = context.getExecutorService().schedule(() -> callback.sendCommand(commandToSend),
longPressTime + 50, TimeUnit.MILLISECONDS);
}
pressedTime = System.currentTimeMillis();
}
private synchronized void buttonReleased(Command commandToSend) {
cancelTimeoutFuture();
cancelDimmFuture();
if (System.currentTimeMillis() - pressedTime <= longPressTime) {
callback.sendCommand(commandToSend);
}
}
private synchronized void cancelDimmFuture() {
if (dimmFuture != null) {
dimmFuture.cancel(false);
}
}
private synchronized void cancelTimeoutFuture() {
if (timeoutFuture != null) {
timeoutFuture.cancel(false);
}
}
}

View File

@@ -0,0 +1,566 @@
/**
* 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.ihc.internal.ws;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import org.apache.commons.io.IOUtils;
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
import org.openhab.binding.ihc.internal.ws.datatypes.WSLoginResult;
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
import org.openhab.binding.ihc.internal.ws.datatypes.WSTimeManagerSettings;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.binding.ihc.internal.ws.services.IhcAirlinkManagementService;
import org.openhab.binding.ihc.internal.ws.services.IhcAuthenticationService;
import org.openhab.binding.ihc.internal.ws.services.IhcConfigurationService;
import org.openhab.binding.ihc.internal.ws.services.IhcControllerService;
import org.openhab.binding.ihc.internal.ws.services.IhcResourceInteractionService;
import org.openhab.binding.ihc.internal.ws.services.IhcTimeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* IhcClient provides interface to communicate IHC / ELKO LS Controller.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcClient {
/** Current state of the connection */
public enum ConnectionState {
DISCONNECTED,
CONNECTING,
CONNECTED
}
public static final String CONTROLLER_STATE_READY = "text.ctrl.state.ready";
public static final String CONTROLLER_STATE_INITIALIZE = "text.ctrl.state.initialize";
private static final int NOTIFICATION_WAIT_TIMEOUT_IN_SEC = 5;
private final Logger logger = LoggerFactory.getLogger(IhcClient.class);
private ConnectionState connState = ConnectionState.DISCONNECTED;
private IhcConnectionPool ihcConnectionPool;
/** Controller services */
private IhcAuthenticationService authenticationService;
private IhcResourceInteractionService resourceInteractionService;
private IhcControllerService controllerService;
private IhcConfigurationService configurationService;
private IhcAirlinkManagementService airlinkManagementService;
private IhcTimeService timeService;
/** Thread to handle resource value notifications from the controller */
private IhcResourceValueNotificationListener resourceValueNotificationListener;
/** Thread to handle controller's state change notifications */
private IhcControllerStateListener controllerStateListener;
private String username;
private String password;
private String host;
/** Timeout in milliseconds */
private int timeout;
private Map<Integer, WSResourceValue> resourceValues = new HashMap<>();
private List<IhcEventListener> eventListeners = new ArrayList<>();
public IhcClient(String host, String username, String password) {
this(host, username, password, 5000);
}
public IhcClient(String host, String username, String password, int timeout) {
this.host = host;
this.username = username;
this.password = password;
this.timeout = timeout;
}
public synchronized ConnectionState getConnectionState() {
return connState;
}
private synchronized void setConnectionState(ConnectionState newState) {
connState = newState;
}
public void addEventListener(IhcEventListener listener) {
eventListeners.add(listener);
}
public void removeEventListener(IhcEventListener listener) {
eventListeners.remove(listener);
}
/**
* Open connection and authenticate session to IHC / ELKO LS controller.
*
* @throws IhcExecption
*/
public void closeConnection() throws IhcExecption {
logger.debug("Closing connection");
// interrupt
if (resourceValueNotificationListener != null) {
resourceValueNotificationListener.setInterrupted(true);
}
if (controllerStateListener != null) {
controllerStateListener.setInterrupted(true);
}
// wait to stop
if (resourceValueNotificationListener != null) {
logger.debug("Waiting resource value notification listener to stop");
try {
resourceValueNotificationListener.join(NOTIFICATION_WAIT_TIMEOUT_IN_SEC * 1000);
} catch (InterruptedException e) {
// do nothing
}
}
if (controllerStateListener != null) {
logger.debug("Waiting controller state listener to stop");
try {
controllerStateListener.join(NOTIFICATION_WAIT_TIMEOUT_IN_SEC * 1000);
} catch (InterruptedException e) {
// do nothing
}
}
logger.debug("Connection closed");
setConnectionState(ConnectionState.DISCONNECTED);
}
/**
* Open connection and authenticate session to IHC / ELKO LS controller.
*
* @throws IhcExecption
*/
public void openConnection() throws IhcExecption {
logger.debug("Opening connection");
setConnectionState(ConnectionState.CONNECTING);
ihcConnectionPool = new IhcConnectionPool();
authenticationService = new IhcAuthenticationService(host, timeout, ihcConnectionPool);
WSLoginResult loginResult = authenticationService.authenticate(username, password, "treeview");
if (!loginResult.isLoginWasSuccessful()) {
// Login failed
setConnectionState(ConnectionState.DISCONNECTED);
if (loginResult.isLoginFailedDueToAccountInvalid()) {
throw new IhcExecption("login failed because of invalid account");
}
if (loginResult.isLoginFailedDueToConnectionRestrictions()) {
throw new IhcExecption("login failed because of connection restrictions");
}
if (loginResult.isLoginFailedDueToInsufficientUserRights()) {
throw new IhcExecption("login failed because of insufficient user rights");
}
throw new IhcExecption("login failed because of unknown reason");
}
logger.debug("Connection successfully opened");
resourceInteractionService = new IhcResourceInteractionService(host, timeout, ihcConnectionPool);
controllerService = new IhcControllerService(host, timeout, ihcConnectionPool);
configurationService = new IhcConfigurationService(host, timeout, ihcConnectionPool);
airlinkManagementService = new IhcAirlinkManagementService(host, timeout, ihcConnectionPool);
timeService = new IhcTimeService(host, timeout, ihcConnectionPool);
setConnectionState(ConnectionState.CONNECTED);
}
/**
* Start event listener to get notifications from IHC / ELKO LS controller.
*
* @throws IhcExecption
*
*/
public void startControllerEventListeners() throws IhcExecption {
if (getConnectionState() == ConnectionState.CONNECTED) {
logger.debug("Start IHC / ELKO listeners");
resourceValueNotificationListener = new IhcResourceValueNotificationListener();
resourceValueNotificationListener.start();
controllerStateListener = new IhcControllerStateListener();
controllerStateListener.start();
} else {
throw new IhcExecption("Connection to controller not open");
}
}
/**
* Query project information from the controller.
*
* @return project information.
* @throws IhcExecption
*/
public synchronized WSProjectInfo getProjectInfo() throws IhcExecption {
return controllerService.getProjectInfo();
}
/**
* Query system information from the controller.
*
* @return system information.
* @throws IhcExecption
*/
public synchronized WSSystemInfo getSystemInfo() throws IhcExecption {
return configurationService.getSystemInfo();
}
/**
* Query time settings from the controller.
*
* @return time settings.
* @throws IhcExecption
*/
public synchronized WSTimeManagerSettings getTimeSettings() throws IhcExecption {
return timeService.getTimeSettings();
}
/**
* Query detected RF devices from the controller.
*
* @return List of RF devices.
* @throws IhcExecption
*/
public synchronized List<WSRFDevice> getDetectedRFDevices() throws IhcExecption {
return airlinkManagementService.getDetectedDeviceList();
}
/**
* Query controller current state.
*
* @return controller's current state.
*/
public WSControllerState getControllerState() throws IhcExecption {
return controllerService.getControllerState();
}
/**
* Query project number of segments.
*
* @return number of segments.
*/
public int getProjectNumberOfSegments() throws IhcExecption {
return controllerService.getProjectNumberOfSegments();
}
/**
* Query project segmentation size.
*
* @return segmentation size in bytes.
*/
public int getProjectSegmentationSize() throws IhcExecption {
return controllerService.getProjectSegmentationSize();
}
/**
* Query project segments data.
*
* @return segments data.
*/
public WSFile getProjectSegment(int index, int major, int minor) throws IhcExecption {
return controllerService.getProjectSegment(index, major, minor);
}
/**
* Fetch project file from controller.
*
* @return project file.
*/
public byte[] getProjectFileFromController() throws IhcExecption {
try {
WSProjectInfo projectInfo = getProjectInfo();
int numberOfSegments = getProjectNumberOfSegments();
int segmentationSize = getProjectSegmentationSize();
logger.debug("Number of segments: {}", numberOfSegments);
logger.debug("Segmentation size: {}", segmentationSize);
try (ByteArrayOutputStream byteStream = new ByteArrayOutputStream()) {
for (int i = 0; i < numberOfSegments; i++) {
logger.debug("Downloading segment {}", i);
WSFile data = getProjectSegment(i, projectInfo.getProjectMajorRevision(),
projectInfo.getProjectMinorRevision());
byteStream.write(data.getData());
}
if (logger.isDebugEnabled()) {
logger.debug("File size before base64 encoding: {} bytes", byteStream.size());
}
byte[] decodedBytes = Base64.getDecoder().decode(byteStream.toString());
logger.debug("File size after base64 encoding: {} bytes", decodedBytes.length);
try (GZIPInputStream gzis = new GZIPInputStream(new ByteArrayInputStream(decodedBytes))) {
try (InputStreamReader in = new InputStreamReader(gzis, "ISO-8859-1")) {
return IOUtils.toByteArray(in, "ISO-8859-1");
}
}
}
} catch (IOException | IllegalArgumentException e) {
throw new IhcExecption(e);
}
}
/**
* Wait controller state change notification.
*
* @param previousState Previous controller state.
* @param timeoutInSecondscHow many seconds to wait notifications.
* @return current controller state.
*/
private WSControllerState waitStateChangeNotifications(WSControllerState previousState, int timeoutInSeconds)
throws IhcExecption {
return controllerService.waitStateChangeNotifications(previousState, timeoutInSeconds);
}
/**
* Enable resources runtime value notifications.
*
* @param resourceIdList List of resource Identifiers.
* @return True is connection successfully opened.
*/
public synchronized void enableRuntimeValueNotifications(Set<Integer> resourceIdList) throws IhcExecption {
resourceInteractionService.enableRuntimeValueNotifications(resourceIdList);
}
/**
* Wait runtime value notifications.
*
* Runtime value notification should firstly be activated by
* enableRuntimeValueNotifications function.
*
* @param timeoutInSeconds How many seconds to wait notifications.
* @return List of received runtime value notifications.
* @throws SocketTimeoutException
*/
private List<WSResourceValue> waitResourceValueNotifications(int timeoutInSeconds) throws IhcExecption {
List<WSResourceValue> list = resourceInteractionService.waitResourceValueNotifications(timeoutInSeconds);
for (WSResourceValue val : list) {
resourceValues.put(val.resourceID, val);
}
return list;
}
/**
* Query resource value from controller.
*
*
* @param resoureId Resource Identifier.
* @return Resource value.
*/
public WSResourceValue resourceQuery(int resoureId) throws IhcExecption {
return resourceInteractionService.resourceQuery(resoureId);
}
/**
* Get resource value information.
*
* Function return resource value from internal memory, if data is not
* available information is read from the controller.
*
* Resource value's value field (e.g. floatingPointValue) could be old
* information.
*
* @param resoureId Resource Identifier.
* @return Resource value.
*/
public WSResourceValue getResourceValueInformation(int resourceId) throws IhcExecption {
if (resourceId != 0) {
WSResourceValue data = resourceValues.get(resourceId);
if (data == null) {
// data is not available, read it from the controller
data = resourceInteractionService.resourceQuery(resourceId);
}
return data;
} else {
return null;
}
}
/**
* Update resource value to controller.
*
*
* @param value Resource value.
* @return True if value is successfully updated.
*/
public boolean resourceUpdate(WSResourceValue value) throws IhcExecption {
return resourceInteractionService.resourceUpdate(value);
}
/**
* The IhcReader runs as a separate thread.
*
* Thread listen resource value notifications from IHC / ELKO LS controller.
*/
private class IhcResourceValueNotificationListener extends Thread {
private volatile boolean interrupted = false;
public void setInterrupted(boolean interrupted) {
this.interrupted = interrupted;
this.interrupt();
}
@Override
public void run() {
logger.debug("IHC resource value listener started");
// as long as no interrupt is requested, continue running
while (!interrupted) {
waitResourceNotifications();
}
logger.debug("IHC resource value listener stopped");
}
private void waitResourceNotifications() {
try {
logger.trace("Wait new resource value notifications from controller");
List<WSResourceValue> resourceValueList = waitResourceValueNotifications(
NOTIFICATION_WAIT_TIMEOUT_IN_SEC);
logger.debug("{} new notifications received from controller", resourceValueList.size());
for (WSResourceValue value : resourceValueList) {
sendResourceValueUpdateEvent(value);
}
} catch (IhcExecption e) {
if (!interrupted) {
logger.warn("New notifications wait failed...", e);
sendErrorEvent(e);
mysleep(1000L);
}
}
}
private void mysleep(long milli) {
try {
sleep(milli);
} catch (InterruptedException e) {
interrupted = true;
}
}
}
/**
* The IhcReader runs as a separate thread.
*
* Thread listen controller state change notifications from IHC / ELKO LS
* controller.
*
*/
private class IhcControllerStateListener extends Thread {
private volatile boolean interrupted = false;
public void setInterrupted(boolean interrupted) {
this.interrupted = interrupted;
this.interrupt();
}
@Override
public void run() {
logger.debug("IHC controller state listener started");
WSControllerState previousState = null;
// as long as no interrupt is requested, continue running
while (!interrupted) {
try {
if (previousState == null) {
// initialize previous state
previousState = controllerService.getControllerState();
logger.debug("Controller initial state {}", previousState.getState());
}
logger.trace("Wait new state change notification from controller");
WSControllerState currentState = waitStateChangeNotifications(previousState,
NOTIFICATION_WAIT_TIMEOUT_IN_SEC);
logger.trace("Controller state {}", currentState.getState());
if (!previousState.getState().equals(currentState.getState())) {
logger.debug("Controller state change detected ({} -> {})", previousState.getState(),
currentState.getState());
sendControllerStateUpdateEvent(currentState);
previousState.setState(currentState.getState());
}
} catch (IhcExecption e) {
if (!interrupted) {
logger.error("New controller state change notification wait failed...", e);
sendErrorEvent(e);
mysleep(1000L);
}
}
}
logger.debug("IHC controller state listener stopped");
}
private void mysleep(long milli) {
try {
sleep(milli);
} catch (InterruptedException e) {
interrupted = true;
}
}
}
private void sendErrorEvent(IhcExecption err) {
eventListeners.forEach(listener -> {
try {
listener.errorOccured(err);
} catch (RuntimeException e) {
logger.debug("Event listener invoking error.", e);
}
});
}
private void sendControllerStateUpdateEvent(WSControllerState state) {
eventListeners.forEach(listener -> {
try {
listener.statusUpdateReceived(state);
} catch (RuntimeException e) {
logger.debug("Event listener invoking error.", e);
}
});
}
private void sendResourceValueUpdateEvent(WSResourceValue value) {
eventListeners.forEach(listener -> {
try {
listener.resourceValueUpdateReceived(value);
} catch (RuntimeException e) {
logger.debug("Event listener invoking error.", e);
}
});
}
}

View File

@@ -0,0 +1,46 @@
/**
* 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.ihc.internal.ws;
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
/**
* This interface defines interface to receive updates from IHC controller.
*
* @author Pauli Anttila - Initial contribution
*/
public interface IhcEventListener {
/**
* Event for receive status update from IHC controller.
*
* @param status Received status update from controller.
*/
void statusUpdateReceived(WSControllerState status);
/**
* Event for receive resource value updates from IHC controller.
*
* @param value Received value update from controller.
*/
void resourceValueUpdateReceived(WSResourceValue value);
/**
* Event for fatal error on communication to IHC controller.
*
* @param e IhcException occurred.
*/
void errorOccured(IhcExecption e);
}

View File

@@ -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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSControllerState complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSControllerState {
private String state;
public WSControllerState() {
}
public WSControllerState(String state) {
this.state = state;
}
/**
* Gets the state value for this WSControllerState.
*
* @return state
*/
public String getState() {
return state;
}
/**
* Sets the state value for this WSControllerState.
*
* @param state
*/
public void setState(String state) {
this.state = state;
}
public WSControllerState parseXMLData(String data) throws IhcExecption {
try {
if (data.contains("getState1")) {
state = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getState1/ns1:state");
} else if (data.contains("waitForControllerStateChange3")) {
state = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:waitForControllerStateChange3/ns1:state");
} else {
throw new IhcExecption("Encoding error, unsupported data");
}
return this;
} catch (IOException | XPathExpressionException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
}

View File

@@ -0,0 +1,169 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* Class for WSDate complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSDate {
private int hours;
private int minutes;
private int seconds;
private int year;
private int day;
private int monthWithJanuaryAsOne;
public WSDate() {
}
public WSDate(int hours, int minutes, int seconds, int year, int day, int monthWithJanuaryAsOne) {
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
this.year = year;
this.day = day;
this.monthWithJanuaryAsOne = monthWithJanuaryAsOne;
}
/**
* Gets the hours value for this WSDate.
*
* @return hours
*/
public int getHours() {
return hours;
}
/**
* Sets the hours value for this WSDate.
*
* @param hours
*/
public void setHours(int hours) {
this.hours = hours;
}
/**
* Gets the minutes value for this WSDate.
*
* @return minutes
*/
public int getMinutes() {
return minutes;
}
/**
* Sets the minutes value for this WSDate.
*
* @param minutes
*/
public void setMinutes(int minutes) {
this.minutes = minutes;
}
/**
* Gets the seconds value for this WSDate.
*
* @return seconds
*/
public int getSeconds() {
return seconds;
}
/**
* Sets the seconds value for this WSDate.
*
* @param seconds
*/
public void setSeconds(int seconds) {
this.seconds = seconds;
}
/**
* Gets the year value for this WSDate.
*
* @return year
*/
public int getYear() {
return year;
}
/**
* Sets the year value for this WSDate.
*
* @param year
*/
public void setYear(int year) {
this.year = year;
}
/**
* Gets the day value for this WSDate.
*
* @return day
*/
public int getDay() {
return day;
}
/**
* Sets the day value for this WSDate.
*
* @param day
*/
public void setDay(int day) {
this.day = day;
}
/**
* Gets the monthWithJanuaryAsOne value for this WSDate.
*
* @return monthWithJanuaryAsOne
*/
public int getMonthWithJanuaryAsOne() {
return monthWithJanuaryAsOne;
}
/**
* Sets the monthWithJanuaryAsOne value for this WSDate.
*
* @param monthWithJanuaryAsOne
*/
public void setMonthWithJanuaryAsOne(int monthWithJanuaryAsOne) {
this.monthWithJanuaryAsOne = monthWithJanuaryAsOne;
}
/**
* Gets WSDate as LocalDateTime.
*
* @return LocalDateTime
*/
public LocalDateTime getAsLocalDateTime() {
return LocalDateTime.of(year, monthWithJanuaryAsOne, day, hours, minutes, seconds);
}
/**
* Gets WSDate as ZonedDateTime.
*
* @return LocalDateTime
*/
public ZonedDateTime getAsZonedDateTime(ZoneId zoneId) {
return ZonedDateTime.of(getAsLocalDateTime(), zoneId);
}
}

View File

@@ -0,0 +1,86 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSFile complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSFile {
private byte[] data;
private String filename;
public WSFile() {
}
public WSFile(byte[] data, String filename) {
this.data = data;
this.filename = filename;
}
/**
* Gets the data value for this WSFile.
*
* @return data
*/
public byte[] getData() {
return data;
}
/**
* Sets the data value for this WSFile.
*
* @param data
*/
public void setData(byte[] data) {
this.data = data;
}
/**
* Gets the filename value for this WSFile.
*
* @return filename
*/
public String getFilename() {
return filename;
}
/**
* Sets the filename value for this WSFile.
*
* @param filename
*/
public void setFilename(String filename) {
this.filename = filename;
}
public WSFile parseXMLData(String data) throws IhcExecption {
try {
filename = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectSegment4/ns1:filename");
this.data = XPathUtils
.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectSegment4/ns1:data")
.getBytes();
return this;
} catch (IOException | XPathExpressionException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
}

View File

@@ -0,0 +1,150 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSLoginResult complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSLoginResult {
protected WSUser loggedInUser;
protected boolean loginWasSuccessful;
protected boolean loginFailedDueToConnectionRestrictions;
protected boolean loginFailedDueToInsufficientUserRights;
protected boolean loginFailedDueToAccountInvalid;
public WSLoginResult() {
}
public WSLoginResult(WSUser loggedInUser, boolean loginWasSuccessful,
boolean loginFailedDueToConnectionRestrictions, boolean loginFailedDueToInsufficientUserRights,
boolean loginFailedDueToAccountInvalid) {
this.loggedInUser = loggedInUser;
this.loginWasSuccessful = loginWasSuccessful;
this.loginFailedDueToConnectionRestrictions = loginFailedDueToConnectionRestrictions;
this.loginFailedDueToInsufficientUserRights = loginFailedDueToInsufficientUserRights;
this.loginFailedDueToAccountInvalid = loginFailedDueToAccountInvalid;
}
/**
* Gets the value of the loggedInUser property.
*
* @return possible object is {@link WSUser }
*
*/
public WSUser getLoggedInUser() {
return loggedInUser;
}
/**
* Sets the value of the loggedInUser property.
*
* @param value allowed object is {@link WSUser }
*
*/
public void setLoggedInUser(WSUser value) {
this.loggedInUser = value;
}
/**
* Gets the value of the loginWasSuccessful property.
*
*/
public boolean isLoginWasSuccessful() {
return loginWasSuccessful;
}
/**
* Sets the value of the loginWasSuccessful property.
*
*/
public void setLoginWasSuccessful(boolean value) {
this.loginWasSuccessful = value;
}
/**
* Gets the value of the loginFailedDueToConnectionRestrictions property.
*
*/
public boolean isLoginFailedDueToConnectionRestrictions() {
return loginFailedDueToConnectionRestrictions;
}
/**
* Sets the value of the loginFailedDueToConnectionRestrictions property.
*
*/
public void setLoginFailedDueToConnectionRestrictions(boolean value) {
this.loginFailedDueToConnectionRestrictions = value;
}
/**
* Gets the value of the loginFailedDueToInsufficientUserRights property.
*
*/
public boolean isLoginFailedDueToInsufficientUserRights() {
return loginFailedDueToInsufficientUserRights;
}
/**
* Sets the value of the loginFailedDueToInsufficientUserRights property.
*
*/
public void setLoginFailedDueToInsufficientUserRights(boolean value) {
this.loginFailedDueToInsufficientUserRights = value;
}
/**
* Gets the value of the loginFailedDueToAccountInvalid property.
*
*/
public boolean isLoginFailedDueToAccountInvalid() {
return loginFailedDueToAccountInvalid;
}
/**
* Sets the value of the loginFailedDueToAccountInvalid property.
*
*/
public void setLoginFailedDueToAccountInvalid(boolean value) {
this.loginFailedDueToAccountInvalid = value;
}
public WSLoginResult parseXMLData(String data) throws IhcExecption {
try {
loginWasSuccessful = XPathUtils.parseValueToBoolean(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginWasSuccessful");
loginFailedDueToConnectionRestrictions = XPathUtils.parseValueToBoolean(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginFailedDueToConnectionRestrictions");
loginFailedDueToInsufficientUserRights = XPathUtils.parseValueToBoolean(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginFailedDueToInsufficientUserRights");
loginFailedDueToAccountInvalid = XPathUtils.parseValueToBoolean(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:authenticate2/ns1:loginFailedDueToAccountInvalid");
return this;
} catch (IOException | XPathExpressionException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSNumberOfSegments complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSNumberOfSegments {
private int segments;
public WSNumberOfSegments() {
}
public WSNumberOfSegments(int segments) {
this.segments = segments;
}
/**
* Gets the number of segments.
*
* @return segmentation size
*/
public int getNumberOfSegments() {
return segments;
}
/**
* Sets the number of segmentations.
*
* @param value
*/
public void setNumberOfSegments(int segments) {
this.segments = segments;
}
public WSNumberOfSegments parseXMLData(String data) throws IhcExecption {
try {
String value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectNumberOfSegments1");
setNumberOfSegments(Integer.parseInt(value));
return this;
} catch (IOException | XPathExpressionException | NumberFormatException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
}

View File

@@ -0,0 +1,268 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSProjectInfo complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSProjectInfo {
private int visualMinorVersion;
private int visualMajorVersion;
private int projectMajorRevision;
private int projectMinorRevision;
private WSDate lastmodified;
private String projectNumber;
private String customerName;
private String installerName;
public WSProjectInfo() {
}
public WSProjectInfo(int visualMinorVersion, int visualMajorVersion, int projectMajorRevision,
int projectMinorRevision, WSDate lastmodified, String projectNumber, String customerName,
String installerName) {
this.visualMinorVersion = visualMinorVersion;
this.visualMajorVersion = visualMajorVersion;
this.projectMajorRevision = projectMajorRevision;
this.projectMinorRevision = projectMinorRevision;
this.lastmodified = lastmodified;
this.projectNumber = projectNumber;
this.customerName = customerName;
this.installerName = installerName;
}
/**
* Gets the visualMinorVersion value for this WSProjectInfo.
*
* @return visualMinorVersion
*/
public int getVisualMinorVersion() {
return visualMinorVersion;
}
/**
* Sets the visualMinorVersion value for this WSProjectInfo.
*
* @param visualMinorVersion
*/
public void setVisualMinorVersion(int visualMinorVersion) {
this.visualMinorVersion = visualMinorVersion;
}
/**
* Gets the visualMajorVersion value for this WSProjectInfo.
*
* @return visualMajorVersion
*/
public int getVisualMajorVersion() {
return visualMajorVersion;
}
/**
* Sets the visualMajorVersion value for this WSProjectInfo.
*
* @param visualMajorVersion
*/
public void setVisualMajorVersion(int visualMajorVersion) {
this.visualMajorVersion = visualMajorVersion;
}
/**
* Gets the projectMajorRevision value for this WSProjectInfo.
*
* @return projectMajorRevision
*/
public int getProjectMajorRevision() {
return projectMajorRevision;
}
/**
* Sets the projectMajorRevision value for this WSProjectInfo.
*
* @param projectMajorRevision
*/
public void setProjectMajorRevision(int projectMajorRevision) {
this.projectMajorRevision = projectMajorRevision;
}
/**
* Gets the projectMinorRevision value for this WSProjectInfo.
*
* @return projectMinorRevision
*/
public int getProjectMinorRevision() {
return projectMinorRevision;
}
/**
* Sets the projectMinorRevision value for this WSProjectInfo.
*
* @param projectMinorRevision
*/
public void setProjectMinorRevision(int projectMinorRevision) {
this.projectMinorRevision = projectMinorRevision;
}
/**
* Gets the lastmodified value for this WSProjectInfo.
*
* @return lastmodified
*/
public WSDate getLastmodified() {
return lastmodified;
}
/**
* Sets the lastmodified value for this WSProjectInfo.
*
* @param lastmodified
*/
public void setLastmodified(WSDate lastmodified) {
this.lastmodified = lastmodified;
}
/**
* Gets the projectNumber value for this WSProjectInfo.
*
* @return projectNumber
*/
public java.lang.String getProjectNumber() {
return projectNumber;
}
/**
* Sets the projectNumber value for this WSProjectInfo.
*
* @param projectNumber
*/
public void setProjectNumber(String projectNumber) {
this.projectNumber = projectNumber;
}
/**
* Gets the customerName value for this WSProjectInfo.
*
* @return customerName
*/
public java.lang.String getCustomerName() {
return customerName;
}
/**
* Sets the customerName value for this WSProjectInfo.
*
* @param customerName
*/
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
/**
* Gets the installerName value for this WSProjectInfo.
*
* @return installerName
*/
public java.lang.String getInstallerName() {
return installerName;
}
/**
* Sets the installerName value for this WSProjectInfo.
*
* @param installerName
*/
public void setInstallerName(String installerName) {
this.installerName = installerName;
}
public WSProjectInfo parseXMLData(String data) throws IhcExecption {
try {
String value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:visualMinorVersion");
setVisualMinorVersion(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:visualMajorVersion");
setVisualMajorVersion(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:projectMajorRevision");
setProjectMajorRevision(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:projectMinorRevision");
setProjectMinorRevision(Integer.parseInt(value));
WSDate lastmodified = new WSDate();
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:day");
lastmodified.setDay(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:monthWithJanuaryAsOne");
lastmodified.setMonthWithJanuaryAsOne(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:hours");
lastmodified.setHours(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:minutes");
lastmodified.setMinutes(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:seconds");
lastmodified.setSeconds(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:lastmodified/ns1:year");
lastmodified.setYear(Integer.parseInt(value));
setLastmodified(lastmodified);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:projectNumber");
setProjectNumber(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:customerName");
setCustomerName(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getProjectInfo1/ns1:installerName");
setInstallerName(value);
return this;
} catch (IOException | XPathExpressionException | NumberFormatException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
@Override
public String toString() {
return String.format(
"[ visualMinorVersion=%d, visualMajorVersion=%d, projectMajorRevision=%d, projectMinorRevision=%d, lastmodified=%s, projectNumber=%s, customerName=%s, installerName=%s ]",
visualMinorVersion, visualMajorVersion, projectMajorRevision, projectMinorRevision,
lastmodified.getAsLocalDateTime(), projectNumber, customerName, installerName);
}
}

View File

@@ -0,0 +1,156 @@
/**
* 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.ihc.internal.ws.datatypes;
/**
* Class for WSRFDevice complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSRFDevice {
private int batteryLevel;
private int deviceType;
private long serialNumber;
private int signalStrength;
private int version;
private boolean detected;
public WSRFDevice() {
}
public WSRFDevice(int batteryLevel, int deviceType, long serialNumber, int signalStrength, int version,
boolean detected) {
this.batteryLevel = batteryLevel;
this.deviceType = deviceType;
this.serialNumber = serialNumber;
this.signalStrength = signalStrength;
this.version = version;
this.detected = detected;
}
/**
* Gets the battery level value for this WSRFDevice.
*
* @return Battery Level
*/
public int getBatteryLevel() {
return batteryLevel;
}
/**
* Sets the battery level value for this WSRFDevice.
*
* @param batteryLevel battery level
*/
public void setBatteryLevel(int batteryLevel) {
this.batteryLevel = batteryLevel;
}
/**
* Gets the device type value for this WSRFDevice.
*
* @return device type
*/
public int getDeviceType() {
return deviceType;
}
/**
* Sets the device type value for this WSRFDevice.
*
* @param device type
*/
public void setDeviceType(int deviceType) {
this.deviceType = deviceType;
}
/**
* Gets the serial number value for this WSRFDevice.
*
* @return Serial number
*/
public long getSerialNumber() {
return serialNumber;
}
/**
* Sets the serial number value for this WSRFDevice.
*
* @param Serial number
*/
public void setSerialNumber(long serialNumber) {
this.serialNumber = serialNumber;
}
/**
* Gets the signal strength value for this WSRFDevice.
*
* @return Signal strength
*/
public int getSignalStrength() {
return signalStrength;
}
/**
* Sets the signal strength value for this WSRFDevice.
*
* @param signalStrength Signal strength
*/
public void setSignalStrength(int signalStrength) {
this.signalStrength = signalStrength;
}
/**
* Gets the version value for this WSRFDevice.
*
* @return version
*/
public int getVersion() {
return version;
}
/**
* Sets the version value for this WSRFDevice.
*
* @param version
*/
public void setVersion(int version) {
this.version = version;
}
/**
* Gets the detected value for this WSRFDevice.
*
* @return Detected
*/
public boolean getDetected() {
return detected;
}
/**
* Sets the detected value for this WSRFDevice.
*
* @param detected
*/
public void setdetected(boolean detected) {
this.detected = detected;
}
@Override
public String toString() {
return String.format(
"[ batteryLevel=%d, deviceType=%d, serialNumber=%d, signalStrength=%d, version=%d, detected=%b ]",
batteryLevel, deviceType, serialNumber, signalStrength, version, detected);
}
}

View File

@@ -0,0 +1,65 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSSegmentationSize complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSSegmentationSize {
private int size;
public WSSegmentationSize() {
}
public WSSegmentationSize(int size) {
this.size = size;
}
/**
* Gets the segmentation size value.
*
* @return segmentation size
*/
public int getSegmentationSize() {
return size;
}
/**
* Sets the segmentation size value.
*
* @param size
*/
public void setSegmentationSize(int size) {
this.size = size;
}
public WSSegmentationSize parseXMLData(String data) throws IhcExecption {
try {
String value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getIHCProjectSegmentationSize1");
setSegmentationSize(Integer.parseInt(value));
return this;
} catch (IOException | XPathExpressionException | NumberFormatException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
}

View File

@@ -0,0 +1,339 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import java.time.ZonedDateTime;
import java.time.format.DateTimeParseException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSProjectInfo complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSSystemInfo {
private long uptime;
private ZonedDateTime realtimeclock;
private String serialNumber;
private String brand;
private String version;
private String hwRevision;
private ZonedDateTime swDate;
private boolean applicationIsWithoutViewer;
private String productionDate;
private String datalineVersion;
private String rfModuleSoftwareVersion;
private String rfModuleSerialNumber;
public WSSystemInfo() {
}
public WSSystemInfo(long uptime, ZonedDateTime realtimeclock, String serialNumber, String brand, String version,
String hwRevision, ZonedDateTime swDate, boolean applicationIsWithoutViewer, String productionDate,
String datalineVersion, String rfModuleSoftwareVersion, String rfModuleSerialNumber) {
this.uptime = uptime;
this.realtimeclock = realtimeclock;
this.serialNumber = serialNumber;
this.brand = brand;
this.version = version;
this.hwRevision = hwRevision;
this.swDate = swDate;
this.applicationIsWithoutViewer = applicationIsWithoutViewer;
this.productionDate = productionDate;
this.datalineVersion = datalineVersion;
this.rfModuleSoftwareVersion = rfModuleSoftwareVersion;
this.rfModuleSerialNumber = rfModuleSerialNumber;
}
/**
* Gets the uptime value for this WSSystemInfo.
*
* @return uptime in milliseconds
*/
public long getUptime() {
return uptime;
}
/**
* Sets the uptime value for this WSSystemInfo.
*
* @param uptime uptime in milliseconds
*/
public void setUptime(long uptime) {
this.uptime = uptime;
}
/**
* Gets the RealTimeClock value for this WSSystemInfo.
*
* @return Real Time Clock
*/
public ZonedDateTime getRealTimeClock() {
return realtimeclock;
}
/**
* Sets the RealTimeClock value for this WSSystemInfo.
*
* @param RealTimeClock
*/
public void setRealTimeClock(ZonedDateTime realtimeclock) {
this.realtimeclock = realtimeclock;
}
/**
* Gets the SerialNumber value for this WSSystemInfo.
*
* @return SerialNumber
*/
public String getSerialNumber() {
return serialNumber;
}
/**
* Sets the SerialNumber value for this WSSystemInfo.
*
* @param SerialNumber
*/
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
/**
* Gets the brand value for this WSSystemInfo.
*
* @return brand
*/
public String getBrand() {
return brand;
}
/**
* Sets the brand value for this WSSystemInfo.
*
* @param brand
*/
public void setBrand(String brand) {
this.brand = brand;
}
/**
* Gets the version value for this WSSystemInfo.
*
* @return version
*/
public String getVersion() {
return version;
}
/**
* Sets the version value for this WSSystemInfo.
*
* @param version
*/
public void setVersion(String version) {
this.version = version;
}
/**
* Gets the hwRevision value for this WSSystemInfo.
*
* @return hwRevision
*/
public String getHwRevision() {
return hwRevision;
}
/**
* Sets the hwRevision value for this WSSystemInfo.
*
* @param hwRevision
*/
public void setHwRevision(String hwRevision) {
this.hwRevision = hwRevision;
}
/**
* Gets the swDate value for this WSSystemInfo.
*
* @return swDate
*/
public ZonedDateTime getSwDate() {
return swDate;
}
/**
* Sets the swDate value for this WSSystemInfo.
*
* @param swDate
*/
public void setSwDate(ZonedDateTime swDate) {
this.swDate = swDate;
}
/**
* Gets the applicationIsWithoutViewer value for this WSSystemInfo.
*
* @return applicationIsWithoutViewer
*/
public boolean getApplicationIsWithoutViewer() {
return applicationIsWithoutViewer;
}
/**
* Sets the applicationIsWithoutViewer value for this WSSystemInfo.
*
* @param applicationIsWithoutViewer
*/
public void setApplicationIsWithoutViewer(boolean applicationIsWithoutViewer) {
this.applicationIsWithoutViewer = applicationIsWithoutViewer;
}
/**
* Gets the productionDate value for this WSSystemInfo.
*
* @return productionDate
*/
public String getProductionDate() {
return productionDate;
}
/**
* Sets the productionDate value for this WSSystemInfo.
*
* @param productionDate
*/
public void setProductionDate(String productionDate) {
this.productionDate = productionDate;
}
/**
* Gets the datalineVersion value for this WSSystemInfo.
*
* @return datalineVersion
*/
public String getDatalineVersion() {
return datalineVersion;
}
/**
* Sets the datalineVersion value for this WSSystemInfo.
*
* @param datalineVersion
*/
public void setDatalineVersion(String datalineVersion) {
this.datalineVersion = datalineVersion;
}
/**
* Gets the rfModuleSoftwareVersion value for this WSSystemInfo.
*
* @return rfModuleSoftwareVersion
*/
public String getRfModuleSoftwareVersion() {
return rfModuleSoftwareVersion;
}
/**
* Sets the rfModuleSoftwareVersion value for this WSSystemInfo.
*
* @param rfModuleSoftwareVersion
*/
public void setRfModuleSoftwareVersion(String rfModuleSoftwareVersion) {
this.rfModuleSoftwareVersion = rfModuleSoftwareVersion;
}
/**
* Gets the rfModuleSerialNumber value for this WSSystemInfo.
*
* @return rfModuleSerialNumber
*/
public String getRfModuleSerialNumber() {
return rfModuleSerialNumber;
}
/**
* Sets the rfModuleSerialNumber value for this WSSystemInfo.
*
* @param rfModuleSerialNumber
*/
public void setRfModuleSerialNumber(String rfModuleSerialNumber) {
this.rfModuleSerialNumber = rfModuleSerialNumber;
}
public WSSystemInfo parseXMLData(String data) throws IhcExecption {
try {
String value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:uptime");
setUptime(Long.parseLong(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:serialNumber");
setSerialNumber(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:realtimeclock");
setRealTimeClock(ZonedDateTime.parse(value));
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:brand");
setBrand(value);
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:version");
setVersion(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:hwRevision");
setHwRevision(value);
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:swDate");
setSwDate(ZonedDateTime.parse(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:applicationIsWithoutViewer");
setApplicationIsWithoutViewer(Boolean.parseBoolean(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:productionDate");
setProductionDate(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:datalineVersion");
setDatalineVersion(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:rfModuleSoftwareVersion");
setRfModuleSoftwareVersion(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSystemInfo1/ns1:rfModuleSerialNumber");
setRfModuleSerialNumber(value);
return this;
} catch (IOException | XPathExpressionException | NumberFormatException | DateTimeParseException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
@Override
public String toString() {
return String.format(
"[ uptime=%d, realtimeclock=%s, serialNumber=%s, brand=%s, version=%s, hwRevision=%s, swDate=%s, applicationIsWithoutViewer=%b, productionDate=%s, datalineVersion=%s, rfModuleSoftwareVersion=%s, rfModuleSerialNumber=%s ]",
uptime, realtimeclock, serialNumber, brand, version, hwRevision, swDate, applicationIsWithoutViewer,
productionDate, datalineVersion, rfModuleSoftwareVersion, rfModuleSerialNumber);
}
}

View File

@@ -0,0 +1,157 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.IOException;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
/**
* Class for WSTimeManagerSettings complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSTimeManagerSettings {
private boolean synchroniseTimeAgainstServer;
private boolean useDST;
private int gmtOffsetInHours;
private String serverName;
private int syncIntervalInHours;
private WSDate timeAndDateInUTC;
public WSTimeManagerSettings() {
}
public WSTimeManagerSettings(boolean synchroniseTimeAgainstServer, boolean useDST, int gmtOffsetInHours,
String serverName, int syncIntervalInHours, WSDate timeAndDateInUTC) {
this.synchroniseTimeAgainstServer = synchroniseTimeAgainstServer;
this.useDST = useDST;
this.gmtOffsetInHours = gmtOffsetInHours;
this.serverName = serverName;
this.syncIntervalInHours = syncIntervalInHours;
this.timeAndDateInUTC = timeAndDateInUTC;
}
public boolean getSynchroniseTimeAgainstServer() {
return synchroniseTimeAgainstServer;
}
public void setSynchroniseTimeAgainstServer(boolean synchroniseTimeAgainstServer) {
this.synchroniseTimeAgainstServer = synchroniseTimeAgainstServer;
}
public boolean getUseDST() {
return useDST;
}
public void setUseDST(boolean useDST) {
this.useDST = useDST;
}
public int getGmtOffsetInHours() {
return gmtOffsetInHours;
}
public void setGmtOffsetInHours(int gmtOffsetInHours) {
this.gmtOffsetInHours = gmtOffsetInHours;
}
public String getServerName() {
return serverName;
}
public void setServerName(String serverName) {
this.serverName = serverName;
}
public int getSyncIntervalInHours() {
return syncIntervalInHours;
}
public void setSyncIntervalInHours(int syncIntervalInHours) {
this.syncIntervalInHours = syncIntervalInHours;
}
public WSDate getTimeAndDateInUTC() {
return timeAndDateInUTC;
}
public void setTimeAndDateInUTC(WSDate timeAndDateInUTC) {
this.timeAndDateInUTC = timeAndDateInUTC;
}
public WSTimeManagerSettings parseXMLData(String data) throws IhcExecption {
try {
String value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:synchroniseTimeAgainstServer");
setSynchroniseTimeAgainstServer(Boolean.parseBoolean(value));
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:useDST");
setUseDST(Boolean.parseBoolean(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:gmtOffsetInHours");
setGmtOffsetInHours(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:serverName");
setServerName(value);
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:syncIntervalInHours");
setSyncIntervalInHours(Integer.parseInt(value));
WSDate timeAndDateInUTC = new WSDate();
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:day");
timeAndDateInUTC.setDay(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:monthWithJanuaryAsOne");
timeAndDateInUTC.setMonthWithJanuaryAsOne(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:hours");
timeAndDateInUTC.setHours(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:minutes");
timeAndDateInUTC.setMinutes(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:seconds");
timeAndDateInUTC.setSeconds(Integer.parseInt(value));
value = XPathUtils.parseXMLValue(data,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getSettings1/ns1:timeAndDateInUTC/ns1:year");
timeAndDateInUTC.setYear(Integer.parseInt(value));
setTimeAndDateInUTC(timeAndDateInUTC);
return this;
} catch (IOException | XPathExpressionException | NumberFormatException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
@Override
public String toString() {
return String.format(
"[ synchroniseTimeAgainstServer=%b, useDST=%b, gmtOffsetInHours=%d, serverName=%s, syncIntervalInHours=%d, timeAndDateInUTC=%s ]",
synchroniseTimeAgainstServer, useDST, gmtOffsetInHours, serverName, syncIntervalInHours,
timeAndDateInUTC.getAsLocalDateTime());
}
}

View File

@@ -0,0 +1,250 @@
/**
* 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.ihc.internal.ws.datatypes;
/**
* Class for WSUser complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSUser {
protected WSDate createdDate;
protected WSDate loginDate;
protected String username;
protected String password;
protected String email;
protected String firstname;
protected String lastname;
protected String phone;
protected WSUserGroup group;
protected String project;
public WSUser() {
}
public WSUser(WSDate createdDate, WSDate loginDate, String username, String password, String email,
String firstname, String lastname, String phone, WSUserGroup group, String project) {
this.createdDate = createdDate;
this.loginDate = loginDate;
this.username = username;
this.password = password;
this.email = email;
this.firstname = firstname;
this.lastname = lastname;
this.phone = phone;
this.group = group;
this.project = project;
}
/**
* Gets the value of the createdDate property.
*
* @return possible object is {@link WSDate }
*
*/
public WSDate getCreatedDate() {
return createdDate;
}
/**
* Sets the value of the createdDate property.
*
* @param value allowed object is {@link WSDate }
*
*/
public void setCreatedDate(WSDate value) {
this.createdDate = value;
}
/**
* Gets the value of the loginDate property.
*
* @return possible object is {@link WSDate }
*
*/
public WSDate getLoginDate() {
return loginDate;
}
/**
* Sets the value of the loginDate property.
*
* @param value allowed object is {@link WSDate }
*
*/
public void setLoginDate(WSDate value) {
this.loginDate = value;
}
/**
* Gets the value of the username property.
*
* @return possible object is {@link String }
*
*/
public String getUsername() {
return username;
}
/**
* Sets the value of the username property.
*
* @param value allowed object is {@link String }
*
*/
public void setUsername(String value) {
this.username = value;
}
/**
* Gets the value of the password property.
*
* @return possible object is {@link String }
*
*/
public String getPassword() {
return password;
}
/**
* Sets the value of the password property.
*
* @param value allowed object is {@link String }
*
*/
public void setPassword(String value) {
this.password = value;
}
/**
* Gets the value of the email property.
*
* @return possible object is {@link String }
*
*/
public String getEmail() {
return email;
}
/**
* Sets the value of the email property.
*
* @param value allowed object is {@link String }
*
*/
public void setEmail(String value) {
this.email = value;
}
/**
* Gets the value of the firstname property.
*
* @return possible object is {@link String }
*
*/
public String getFirstname() {
return firstname;
}
/**
* Sets the value of the firstname property.
*
* @return possible object is {@link String }
*
*/
public void setFirstname(String value) {
this.firstname = value;
}
/**
* Gets the value of the lastname property.
*
* @return possible object is {@link String }
*
*/
public String getLastname() {
return lastname;
}
/**
* Sets the value of the lastname property.
*
* @param value allowed object is {@link String }
*
*/
public void setLastname(String value) {
this.lastname = value;
}
/**
* Gets the value of the phone property.
*
* @param value allowed object is {@link String }
*
*/
public String getPhone() {
return phone;
}
/**
* Sets the value of the phone property.
*
* @param value allowed object is {@link String }
* {@link String }
*
*/
public void setPhone(String value) {
this.phone = value;
}
/**
* Gets the value of the group property.
*
* @return possible object is {@link WSUserGroup }
*
*/
public WSUserGroup getGroup() {
return group;
}
/**
* Sets the value of the group property.
*
* @param value allowed object is {@link WSUserGroup }
*
*/
public void setGroup(WSUserGroup value) {
this.group = value;
}
/**
* Gets the value of the project property.
*
* @return possible object is {@link String }
*
*/
public String getProject() {
return project;
}
/**
* Sets the value of the project property.
*
* @param value allowed object is {@link String }
*
*/
public void setProject(String value) {
this.project = value;
}
}

View File

@@ -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.ihc.internal.ws.datatypes;
/**
* Class for WSUserGroup complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSUserGroup {
protected String type;
public WSUserGroup() {
}
public WSUserGroup(String type) {
this.type = type;
}
/**
* Gets the value of the type property.
*
* @return possible object is {@link String }
*
*/
public String getType() {
return type;
}
/**
* Sets the value of the type property.
*
* @param value allowed object is {@link String }
*
*/
public void setType(String value) {
this.type = value;
}
}

View File

@@ -0,0 +1,103 @@
/**
* 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.ihc.internal.ws.datatypes;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* Class for XPath utils.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class XPathUtils {
private static NamespaceContext ihcNamespaceContext = new NamespaceContext() {
@Override
public String getNamespaceURI(String prefix) {
if (prefix == null) {
throw new IllegalArgumentException("Prefix argument can't be null");
} else if ("SOAP-ENV".equals(prefix)) {
return "http://schemas.xmlsoap.org/soap/envelope/";
} else if ("ns1".equals(prefix)) {
return "utcs";
}
return "utcs.values";
}
@Override
public String getPrefix(String uri) {
return null;
}
@Override
@SuppressWarnings("rawtypes")
public Iterator getPrefixes(String uri) {
throw new UnsupportedOperationException();
}
};
public static String parseXMLValue(String xml, String xpathExpression)
throws IOException, XPathExpressionException {
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8.name()))) {
XPath xpath = XPathFactory.newInstance().newXPath();
InputSource inputSource = new InputSource(is);
xpath.setNamespaceContext(ihcNamespaceContext);
return (String) xpath.evaluate(xpathExpression, inputSource, XPathConstants.STRING);
}
}
public static boolean parseValueToBoolean(String xml, String xpathExpression)
throws IOException, XPathExpressionException {
return Boolean.parseBoolean(parseXMLValue(xml, xpathExpression));
}
public static String createIgnoreNameSpaceSyntaxExpr(String name) {
return "*[local-name() = '" + name + "']";
}
public static String getSpeficValueFromNode(Node n, String xpathExpr) throws XPathExpressionException {
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(ihcNamespaceContext);
XPathExpression pathExpr = xpath.compile(xpathExpr);
return (String) pathExpr.evaluate(n, XPathConstants.STRING);
}
public static NodeList parseList(String xml, String xpathExpression) throws XPathExpressionException, IOException {
try (InputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8.name()))) {
XPath xpath = XPathFactory.newInstance().newXPath();
InputSource inputSource = new InputSource(is);
xpath.setNamespaceContext(ihcNamespaceContext);
return (NodeList) xpath.evaluate(xpathExpression, inputSource, XPathConstants.NODESET);
}
}
public static String getValueFromNode(Node n, String value) throws XPathExpressionException {
return getSpeficValueFromNode(n, XPathUtils.createIgnoreNameSpaceSyntaxExpr(value));
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.exeptions;
/**
* Exception for conversion errors.
*
* @author Pauli Anttila - Initial contribution
*/
public class ConversionException extends Exception {
private static final long serialVersionUID = 1;
public ConversionException() {
}
public ConversionException(String message) {
super(message);
}
public ConversionException(String message, Throwable cause) {
super(message, cause);
}
public ConversionException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.exeptions;
/**
* Exception for handling communication errors to controller.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcExecption extends Exception {
private static final long serialVersionUID = -8048415193494625295L;
public IhcExecption() {
}
public IhcExecption(String message) {
super(message);
}
public IhcExecption(String message, Throwable cause) {
super(message, cause);
}
public IhcExecption(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,147 @@
/**
* 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.ihc.internal.ws.http;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Custom HTTP connection pool, which install all-trusting trust manager.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcConnectionPool {
private final Logger logger = LoggerFactory.getLogger(IhcConnectionPool.class);
/**
* Controller TLS certificate is self signed, which means that certificate
* need to be manually added to java key store as a trusted certificate.
* This is special SSL context which will be configured to trust all
* certificates and manual work is not required.
*/
private SSLContext sslContext;
/** Holds and share cookie information (session id) from authentication procedure */
private CookieStore cookieStore;
private HttpClientBuilder httpClientBuilder;
private HttpClientContext localContext;
public IhcConnectionPool() {
init();
}
private void init() {
// Create a local instance of cookie store
cookieStore = new BasicCookieStore();
// Create local HTTP context
localContext = HttpClientContext.create();
// Bind custom cookie store to the local context
localContext.setCookieStore(cookieStore);
httpClientBuilder = HttpClientBuilder.create();
// Setup a Trust Strategy that allows all certificates.
logger.debug("Initialize SSL context");
// Create a trust manager that does not validate certificate chains, but accept all.
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
@Override
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] certs, String authType) {
logger.trace("Trusting server cert: {}", certs[0].getIssuerDN());
}
} };
// Install the all-trusting trust manager
try {
// Controller supports only SSLv3 and TLSv1
sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(null, trustAllCerts, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
logger.warn("Exception", e);
} catch (KeyManagementException e) {
logger.warn("Exception", e);
}
// Controller accepts only HTTPS connections and because normally IP address are used on home network rather
// than DNS names, create custom host name verifier.
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
logger.trace("HostnameVerifier: arg0 = {}, arg1 = {}", arg0, arg1);
return true;
}
};
// Create an SSL Socket Factory, to use our weakened "trust strategy"
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[] { "TLSv1" }, null, hostnameVerifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslSocketFactory).build();
// Create connection-manager using our Registry. Allows multi-threaded use
PoolingHttpClientConnectionManager connMngr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// Increase max connection counts
connMngr.setMaxTotal(20);
connMngr.setDefaultMaxPerRoute(6);
httpClientBuilder.setConnectionManager(connMngr);
}
public HttpClient getHttpClient() {
return httpClientBuilder.build();
}
public HttpClientContext getHttpContext() {
return localContext;
}
}

View File

@@ -0,0 +1,135 @@
/**
* 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.ihc.internal.ws.http;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Simple HTTP Client for IHC / ELKO LS Controller connection purposes.
*
* @author Pauli Anttila - Initial contribution
*/
public abstract class IhcHttpsClient {
private final Logger logger = LoggerFactory.getLogger(IhcHttpsClient.class);
private IhcConnectionPool ihcConnectionPool;
private HttpClient client;
private HttpPost postReq;
private AtomicInteger counter = new AtomicInteger();
public IhcHttpsClient(IhcConnectionPool ihcConnectionPool) {
this.ihcConnectionPool = ihcConnectionPool;
}
/**
* Init HTTP connection.
*
* @param url Url to connect.
*/
private void initConnection(String url) throws IhcExecption {
if (client == null) {
client = ihcConnectionPool.getHttpClient();
}
postReq = new HttpPost(url);
}
/**
* Send HTTP request and wait response from the server.
*
*/
public String sendQuery(String url, Map<String, String> requestProperties, String query, int timeout)
throws IhcExecption {
initConnection(url);
setRequestProperty(requestProperties);
try {
return sendQ(query, timeout);
} catch (NoHttpResponseException | SocketTimeoutException e) {
try {
logger.debug("No response received, resend query");
return sendQ(query, timeout);
} catch (IOException ee) {
throw new IhcExecption(ee);
}
} catch (IOException e) {
throw new IhcExecption(e);
}
}
private String sendQ(String query, int timeout)
throws ClientProtocolException, IOException, NoHttpResponseException {
postReq.setEntity(new StringEntity(query, StandardCharsets.UTF_8.name()));
postReq.addHeader("content-type", "text/xml");
int requestId = 0;
if (logger.isTraceEnabled()) {
requestId = counter.getAndIncrement();
logger.trace("Send query (url={}, connectionPool={}, clientId={} requestId={}, timeout={}, headers={}): {}",
postReq.getURI(), ihcConnectionPool.hashCode(), client.hashCode(), requestId, timeout,
postReq.getAllHeaders(), query);
}
final RequestConfig params = RequestConfig.custom().setConnectTimeout(timeout)
.setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();
postReq.setConfig(params);
// Execute POST
LocalDateTime start = LocalDateTime.now();
try {
HttpResponse response = client.execute(postReq, ihcConnectionPool.getHttpContext());
String resp = EntityUtils.toString(response.getEntity());
if (logger.isTraceEnabled()) {
logger.trace("Received response (connectionPool={}, clientId={} requestId={}, in {}, headers={}): {}",
ihcConnectionPool.hashCode(), client.hashCode(), requestId,
Duration.between(start, LocalDateTime.now()), response.getAllHeaders(), resp);
}
return resp;
} catch (Exception e) {
if (logger.isTraceEnabled()) {
logger.trace("Exception occured (connectionPool={}, clientId={} requestId={}, in {}): {}",
ihcConnectionPool.hashCode(), client.hashCode(), requestId,
Duration.between(start, LocalDateTime.now()), e.getMessage());
}
throw (e);
}
}
/**
* Set request properties.
*
*/
private void setRequestProperty(Map<String, String> requestProperties) {
if (postReq != null && requestProperties != null) {
requestProperties.forEach((k, v) -> postReq.setHeader(k, v));
}
}
}

View File

@@ -0,0 +1,41 @@
/**
* 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.ihc.internal.ws.projectfile;
/**
* Class to store IHC / ELKO LS controller's enum value information.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcEnumValue {
private final int id;
private final String name;
public IhcEnumValue(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
@Override
public String toString() {
return String.format("[ id=%d, name='%s' ]", id, name);
}
}

View File

@@ -0,0 +1,173 @@
/**
* 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.ihc.internal.ws.projectfile;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.io.FileUtils;
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Generic methods related to IHC / ELKO project file handling.
*
* @author Pauli Anttila - Initial contribution
*/
public class ProjectFileUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ProjectFileUtils.class);
/**
* Read IHC project file from local file.
*
* @param filePath File to read.
* @return XML document.
* @throws IhcExecption when file read fails.
*/
public static Document readFromFile(String filePath) throws IhcExecption {
File fXmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
return doc;
} catch (IOException | ParserConfigurationException | SAXException e) {
throw new IhcExecption(e);
}
}
/**
* Save IHC project file to local file.
*
* @param filePath File path.
* @param data Data to write
* @throws IhcExecption when file write fails.
*/
public static void saveToFile(String filePath, byte[] data) throws IhcExecption {
try {
FileUtils.writeByteArrayToFile(new File(filePath), data);
} catch (IOException e) {
throw new IhcExecption(e);
}
}
/**
* Convert bytes to XML document.
*
* @return XML document or null if conversion fails.
*/
public static Document converteBytesToDocument(byte[] data) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(data));
} catch (ParserConfigurationException | SAXException | IOException e) {
LOGGER.warn("Error occured when trying to convert data to XML, reason {}", e.getMessage());
}
return null;
}
/**
* Compare XML document header information to project info.
*
* @return true if information is equal and false if not.
*/
public static boolean projectEqualsToControllerProject(Document projectfile, WSProjectInfo projectInfo) {
if (projectInfo != null) {
try {
NodeList nodes = projectfile.getElementsByTagName("modified");
if (nodes.getLength() == 1) {
Element node = (Element) nodes.item(0);
int year = Integer.parseInt(node.getAttribute("year"));
int month = Integer.parseInt(node.getAttribute("month"));
int day = Integer.parseInt(node.getAttribute("day"));
int hour = Integer.parseInt(node.getAttribute("hour"));
int minute = Integer.parseInt(node.getAttribute("minute"));
LOGGER.debug("Project file from file, date: {}.{}.{} {}:{}", year, month, day, hour, minute);
LOGGER.debug("Project file in controller, date: {}.{}.{} {}:{}",
projectInfo.getLastmodified().getYear(),
projectInfo.getLastmodified().getMonthWithJanuaryAsOne(),
projectInfo.getLastmodified().getDay(), projectInfo.getLastmodified().getHours(),
projectInfo.getLastmodified().getMinutes());
if (projectInfo.getLastmodified().getYear() == year
&& projectInfo.getLastmodified().getMonthWithJanuaryAsOne() == month
&& projectInfo.getLastmodified().getDay() == day
&& projectInfo.getLastmodified().getHours() == hour
&& projectInfo.getLastmodified().getMinutes() == minute) {
return true;
}
}
} catch (RuntimeException e) {
LOGGER.debug("Error occured during project file date comparasion, reason {}.", e.getMessage(), e);
// There is no documentation available for XML content. This is part of inessential feature, so do
// nothing, but return false
}
}
return false;
}
/**
* Parse all enum values from IHC project file.
*
* @param doc IHC project file in XML format.
* @return enum dictionary.
*/
public static Map<Integer, List<IhcEnumValue>> parseEnums(Document doc) {
Map<Integer, List<IhcEnumValue>> enumDictionary = new HashMap<>();
if (doc != null) {
NodeList nodes = doc.getElementsByTagName("enum_definition");
// iterate enum definitions from project
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
int typedefId = Integer.parseInt(element.getAttribute("id").replace("_0x", ""), 16);
String enumName = element.getAttribute("name");
List<IhcEnumValue> enumValues = new ArrayList<>();
NodeList name = element.getElementsByTagName("enum_value");
for (int j = 0; j < name.getLength(); j++) {
Element val = (Element) name.item(j);
int id = Integer.parseInt(val.getAttribute("id").replace("_0x", ""), 16);
String n = val.getAttribute("name");
IhcEnumValue enumVal = new IhcEnumValue(id, n);
enumValues.add(enumVal);
}
LOGGER.debug("Enum values found: typedefId={}, name={}: {}", typedefId, enumName, enumValues);
enumDictionary.put(typedefId, enumValues);
}
}
return enumDictionary;
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSBooleanValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSBooleanValue extends WSResourceValue {
public final boolean value;
public WSBooleanValue(int resourceID, boolean value) {
super(resourceID);
this.value = value;
}
@Override
public String toString() {
return String.format("[resourceId=%d, value=%b]", super.resourceID, value);
}
}

View File

@@ -0,0 +1,37 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSDateValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSDateValue extends WSResourceValue {
public final short year;
public final byte month;
public final byte day;
public WSDateValue(int resourceID, short year, byte month, byte day) {
super(resourceID);
this.year = year;
this.month = month;
this.day = day;
}
@Override
public String toString() {
return String.format("[resourceId=%d, year=%d, month=%d, day=%d]", super.resourceID, year, month, day);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSEnumValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSEnumValue extends WSResourceValue {
public final int definitionTypeID;
public final int enumValueID;
public final String enumName;
public WSEnumValue(int resourceID, int definitionTypeID, int enumValueID, String enumName) {
super(resourceID);
this.definitionTypeID = definitionTypeID;
this.enumValueID = enumValueID;
this.enumName = enumName;
}
@Override
public String toString() {
return String.format("[resourceId=%d, definitionTypeID=%d, enumValueID=%d, enumName=%s]", super.resourceID,
definitionTypeID, enumValueID, enumName);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSFloatingPointValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSFloatingPointValue extends WSResourceValue {
public final double maximumValue;
public final double minimumValue;
public final double value;
public WSFloatingPointValue(int resourceID, double value, double minimumValue, double maximumValue) {
super(resourceID);
this.value = value;
this.minimumValue = minimumValue;
this.maximumValue = maximumValue;
}
@Override
public String toString() {
return String.format("[resourceId=%d, value=%.2f, min=%.2f, max=%.2f]", super.resourceID, value, minimumValue,
maximumValue);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSIntegerValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSIntegerValue extends WSResourceValue {
public final int value;
public final int maximumValue;
public final int minimumValue;
public WSIntegerValue(int resourceID, int value, int minimumValue, int maximumValue) {
super(resourceID);
this.value = value;
this.minimumValue = minimumValue;
this.maximumValue = maximumValue;
}
@Override
public String toString() {
return String.format("[resourceId=%d, value=%d, min=%d, max=%d]", super.resourceID, value, minimumValue,
maximumValue);
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSPhoneNumberValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSPhoneNumberValue extends WSResourceValue {
public final String number;
public WSPhoneNumberValue(int resourceID, String number) {
super(resourceID);
this.number = number;
}
@Override
public String toString() {
return String.format("[resourceId=%d, number=%s]", super.resourceID, number);
}
}

View File

@@ -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.ihc.internal.ws.resourcevalues;
/**
* Class for WSResourceValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSResourceValue {
public final int resourceID;
public WSResourceValue(int resourceID) {
this.resourceID = resourceID;
}
@Override
public String toString() {
return String.format("[resourceId=%d]", resourceID);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSSceneDimmerValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSSceneDimmerValue extends WSResourceValue {
public final int delayTime;
public final int dimmerPercentage;
public final int rampTime;
public WSSceneDimmerValue(int resourceID, int delayTime, int dimmerPercentage, int rampTime) {
super(resourceID);
this.delayTime = delayTime;
this.dimmerPercentage = dimmerPercentage;
this.rampTime = rampTime;
}
@Override
public String toString() {
return String.format("[resourceId=%d, delayTime=%d, dimmerPercentage=%d, rampTime=%d]", super.resourceID,
delayTime, dimmerPercentage, rampTime);
}
}

View File

@@ -0,0 +1,35 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSSceneRelayValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSSceneRelayValue extends WSResourceValue {
public final int delayTime;
public final boolean relayValue;
public WSSceneRelayValue(int resourceID, int delayTime, boolean relayValue) {
super(resourceID);
this.delayTime = delayTime;
this.relayValue = relayValue;
}
@Override
public String toString() {
return String.format("[resourceId=%d, value=%b, delayTime=%d]", super.resourceID, relayValue, delayTime);
}
}

View File

@@ -0,0 +1,36 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSSceneShutterSimpleValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSSceneShutterSimpleValue extends WSResourceValue {
public final int delayTime;
public final boolean shutterPositionIsUp;
public WSSceneShutterSimpleValue(int resourceID, int delayTime, boolean shutterPositionIsUp) {
super(resourceID);
this.delayTime = delayTime;
this.shutterPositionIsUp = shutterPositionIsUp;
}
@Override
public String toString() {
return String.format("[resourceId=%d, shutterPositionIsUp=%b, delayTime=%d]", super.resourceID,
shutterPositionIsUp, delayTime);
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSTimeValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSTimeValue extends WSResourceValue {
public final int hours;
public final int minutes;
public final int seconds;
public WSTimeValue(int resourceID, int hours, int minutes, int seconds) {
super(resourceID);
this.hours = hours;
this.minutes = minutes;
this.seconds = seconds;
}
@Override
public String toString() {
return String.format("[resourceId=%d, hours=%d, minutes=%d, seconds=%d]", super.resourceID, hours, minutes,
seconds);
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSTimerValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSTimerValue extends WSResourceValue {
public final long milliseconds;
public WSTimerValue(int resourceID, long milliseconds) {
super(resourceID);
this.milliseconds = milliseconds;
}
@Override
public String toString() {
return String.format("[resourceId=%d, milliseconds=%b]", super.resourceID, milliseconds);
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.ihc.internal.ws.resourcevalues;
/**
* Class for WSWeekdayValue complex type.
*
* @author Pauli Anttila - Initial contribution
*/
public class WSWeekdayValue extends WSResourceValue {
public final int weekdayNumber;
public WSWeekdayValue(int resourceID, int weekdayNumber) {
super(resourceID);
this.weekdayNumber = weekdayNumber;
}
@Override
public String toString() {
return String.format("[resourceId=%d, weekdayNumber=%d]", super.resourceID, weekdayNumber);
}
}

View File

@@ -0,0 +1,87 @@
/**
* 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.ihc.internal.ws.services;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
import org.openhab.binding.ihc.internal.ws.datatypes.WSRFDevice;
import org.openhab.binding.ihc.internal.ws.datatypes.XPathUtils;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Class to handle IHC / ELKO LS Controller's airlink management service.
*
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcAirlinkManagementService extends IhcBaseService {
public IhcAirlinkManagementService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
super(ihcConnectionPool, timeout, host, "AirlinkManagementService");
}
/**
* Query system information from the controller.
*
* @return system information.
* @throws IhcExecption
*/
public synchronized List<WSRFDevice> getDetectedDeviceList() throws IhcExecption {
String response = sendSoapQuery("getDetectedDeviceList", EMPTY_QUERY);
List<WSRFDevice> resourceValueList = new ArrayList<>();
try {
NodeList nodeList = XPathUtils.parseList(response,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getDetectedDeviceList1/ns1:arrayItem");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node != null) {
WSRFDevice dev = parseResourceValue(node);
if (dev != null) {
resourceValueList.add(dev);
}
}
}
} else {
throw new IhcExecption("Illegal resource value notification response received");
}
return resourceValueList;
} catch (IOException | XPathExpressionException | NumberFormatException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
private WSRFDevice parseResourceValue(Node n) throws XPathExpressionException, NumberFormatException {
try {
int batteryLevel = Integer.parseInt(XPathUtils.getValueFromNode(n, "batteryLevel"));
int deviceType = Integer.parseInt(XPathUtils.getValueFromNode(n, "deviceType"));
long serialNumber = Long.parseLong(XPathUtils.getValueFromNode(n, "serialNumber"));
int signalStrength = Integer.parseInt(XPathUtils.getValueFromNode(n, "signalStrength"));
int version = Integer.parseInt(XPathUtils.getValueFromNode(n, "version"));
boolean detected = Boolean.valueOf(XPathUtils.getValueFromNode(n, "detected"));
return new WSRFDevice(batteryLevel, deviceType, serialNumber, signalStrength, version, detected);
} catch (NumberFormatException e) {
return null;
}
}
}

View File

@@ -0,0 +1,58 @@
/**
* 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.ihc.internal.ws.services;
import org.openhab.binding.ihc.internal.ws.datatypes.WSLoginResult;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class to handle IHC / ELKO LS Controller's authentication service.
*
* Communication to controller need to be authenticated. On successful
* authentication Controller returns session id which need to be used further
* communication.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcAuthenticationService extends IhcBaseService {
private final Logger logger = LoggerFactory.getLogger(IhcAuthenticationService.class);
public IhcAuthenticationService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
super(ihcConnectionPool, timeout, host, "AuthenticationService");
}
public WSLoginResult authenticate(String username, String password, String application) throws IhcExecption {
logger.debug("Authenticate");
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
+ " <soapenv:Body>\n"
+ " <authenticate1 xmlns=\"utcs\">\n"
+ " <password>%s</password>\n"
+ " <username>%s</username>\n"
+ " <application>%s</application>\n"
+ " </authenticate1>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
// @formatter:on
String query = String.format(soapQuery, password, username, application);
String response = sendSoapQuery(null, query);
return new WSLoginResult().parseXMLData(response);
}
}

View File

@@ -0,0 +1,68 @@
/**
* 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.ihc.internal.ws.services;
import java.util.HashMap;
import java.util.Map;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
import org.openhab.binding.ihc.internal.ws.http.IhcHttpsClient;
/**
* Base class for all IHC / ELKO services.
*
*
* @author Pauli Anttila - Initial contribution
*/
public abstract class IhcBaseService extends IhcHttpsClient {
// @formatter:off
protected static final String EMPTY_QUERY =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soapenv:Body>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
// @formatter:on
private String url;
private int timeout;
public IhcBaseService(IhcConnectionPool ihcConnectionPool, int timeout, String host, String service) {
super(ihcConnectionPool);
this.timeout = timeout;
this.url = createUrl(host, service);
}
private String createUrl(String host, String service) {
return "https://" + host + "/ws/" + service;
}
protected String sendSoapQuery(String soapAction, String query) throws IhcExecption {
return sendSoapQuery(soapAction, query, timeout);
}
protected String sendSoapQuery(String soapAction, String query, int timeout) throws IhcExecption {
Map<String, String> reqProperties = null;
if (soapAction != null) {
reqProperties = new HashMap<>();
reqProperties.put("SOAPAction", soapAction);
}
return sendQuery(url, reqProperties, query, timeout);
}
protected int getTimeout() {
return timeout;
}
}

View File

@@ -0,0 +1,42 @@
/**
* 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.ihc.internal.ws.services;
import org.openhab.binding.ihc.internal.ws.datatypes.WSSystemInfo;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
/**
* Class to handle IHC / ELKO LS Controller's configuration service.
*
* Controller service is used to fetch system information from the controller.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcConfigurationService extends IhcBaseService {
public IhcConfigurationService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
super(ihcConnectionPool, timeout, host, "ConfigurationService");
}
/**
* Query system information from the controller.
*
* @return system information.
* @throws IhcExecption
*/
public synchronized WSSystemInfo getSystemInfo() throws IhcExecption {
String response = sendSoapQuery("getSystemInfo", EMPTY_QUERY);
return new WSSystemInfo().parseXMLData(response);
}
}

View File

@@ -0,0 +1,135 @@
/**
* 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.ihc.internal.ws.services;
import org.openhab.binding.ihc.internal.ws.datatypes.WSControllerState;
import org.openhab.binding.ihc.internal.ws.datatypes.WSFile;
import org.openhab.binding.ihc.internal.ws.datatypes.WSNumberOfSegments;
import org.openhab.binding.ihc.internal.ws.datatypes.WSProjectInfo;
import org.openhab.binding.ihc.internal.ws.datatypes.WSSegmentationSize;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
/**
* Class to handle IHC / ELKO LS Controller's controller service.
*
* Controller service is used to fetch information from the controller.
* E.g. Project file or controller status.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcControllerService extends IhcBaseService {
public IhcControllerService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
super(ihcConnectionPool, timeout, host, "ControllerService");
}
/**
* Query project information from the controller.
*
* @return project information.
* @throws IhcExecption
*/
public synchronized WSProjectInfo getProjectInfo() throws IhcExecption {
String response = sendSoapQuery("getProjectInfo", EMPTY_QUERY);
return new WSProjectInfo().parseXMLData(response);
}
/**
* Query number of segments project contains.
*
* @return number of segments.
* @throws IhcExecption
*/
public synchronized int getProjectNumberOfSegments() throws IhcExecption {
String response = sendSoapQuery("getIHCProjectNumberOfSegments", EMPTY_QUERY);
return new WSNumberOfSegments().parseXMLData(response).getNumberOfSegments();
}
/**
* Query segmentation size.
*
* @return segmentation size in bytes.
* @throws IhcExecption
*/
public synchronized int getProjectSegmentationSize() throws IhcExecption {
String response = sendSoapQuery("getIHCProjectSegmentationSize", EMPTY_QUERY);
return new WSSegmentationSize().parseXMLData(response).getSegmentationSize();
}
/**
* Query project segment data.
*
* @param index segments index.
* @param major project major revision number.
* @param minor project minor revision number.
* @return segments data.
* @throws IhcExecption
*/
public synchronized WSFile getProjectSegment(int index, int major, int minor) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <ns1:getIHCProjectSegment1 xmlns:ns1=\"utcs\" xsi:type=\"xsd:int\">%s</ns1:getIHCProjectSegment1>\n"
+ " <ns2:getIHCProjectSegment2 xmlns:ns2=\"utcs\" xsi:type=\"xsd:int\">%s</ns2:getIHCProjectSegment2>\n"
+ " <ns3:getIHCProjectSegment3 xmlns:ns3=\"utcs\" xsi:type=\"xsd:int\">%s</ns3:getIHCProjectSegment3>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, index, major, minor);
String response = sendSoapQuery("getIHCProjectSegment", query);
return new WSFile().parseXMLData(response);
}
/**
* Query controller current state.
*
* @return controller's current state.
* @throws IhcExecption
*/
public synchronized WSControllerState getControllerState() throws IhcExecption {
String response = sendSoapQuery("getState", EMPTY_QUERY);
return new WSControllerState().parseXMLData(response);
}
/**
* Wait controller state change notification.
*
* @param previousState Previous controller state.
* @param timeoutInSeconds How many seconds to wait notifications.
* @return current controller state.
* @throws IhcExecption
*/
public synchronized WSControllerState waitStateChangeNotifications(WSControllerState previousState,
int timeoutInSeconds) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soapenv:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soapenv:Body>\n"
+ " <ns1:waitForControllerStateChange1 xmlns:ns1=\"utcs\" xsi:type=\"ns1:WSControllerState\">\n"
+ " <ns1:state xsi:type=\"xsd:string\">%s</ns1:state>\n"
+ " </ns1:waitForControllerStateChange1>\n"
+ " <ns2:waitForControllerStateChange2 xmlns:ns2=\"utcs\" xsi:type=\"xsd:int\">%s</ns2:waitForControllerStateChange2>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
// @formatter:on
String query = String.format(soapQuery, previousState.getState(), timeoutInSeconds);
String response = sendSoapQuery("waitForControllerStateChange", query, getTimeout() + timeoutInSeconds * 1000);
return new WSControllerState().parseXMLData(response);
}
}

View File

@@ -0,0 +1,470 @@
/**
* 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.ihc.internal.ws.services;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.xml.xpath.XPathExpressionException;
import org.apache.commons.lang.StringUtils;
import org.openhab.binding.ihc.internal.ws.datatypes.XPathUtils;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimerValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSWeekdayValue;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Class to handle IHC / ELKO LS Controller's resource interaction service.
*
* Service is used to fetch or update resource values from/to controller.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcResourceInteractionService extends IhcBaseService {
public IhcResourceInteractionService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
super(ihcConnectionPool, timeout, host, "ResourceInteractionService");
}
/**
* Query resource value from controller.
*
* @param resoureId Resource Identifier.
* @return Resource value.
*/
public WSResourceValue resourceQuery(int resoureId) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soapenv:Body>\n"
+ " <ns1:getRuntimeValue1 xmlns:ns1=\"utcs\">%s</ns1:getRuntimeValue1>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
// @formatter:on
String query = String.format(soapQuery, String.valueOf(resoureId));
String response = sendSoapQuery(null, query);
NodeList nodeList;
try {
nodeList = XPathUtils.parseList(response, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:getRuntimeValue2");
if (nodeList != null && nodeList.getLength() == 1) {
WSResourceValue val = parseResourceValue(nodeList.item(0));
if (val != null && val.resourceID == resoureId) {
return val;
} else {
throw new IhcExecption("No resource id found");
}
} else {
throw new IhcExecption("No resource value found");
}
} catch (XPathExpressionException | NumberFormatException | IOException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
private WSResourceValue parseResourceValue(Node n) throws XPathExpressionException, NumberFormatException {
// parse resource id
String resourceId = XPathUtils.getSpeficValueFromNode(n, "ns1:resourceID");
if (StringUtils.isNotBlank(resourceId)) {
int id = Integer.parseInt(resourceId);
// Parse floating point value
String floatingPointValue = getValue(n, "floatingPointValue");
if (StringUtils.isNotBlank(floatingPointValue)) {
String min = getValue(n, "minimumValue");
String max = getValue(n, "maximumValue");
return new WSFloatingPointValue(id, Double.valueOf(floatingPointValue), Double.valueOf(min),
Double.valueOf(max));
}
// Parse boolean value
String value = getValue(n, "value");
if (StringUtils.isNotBlank(value)) {
return new WSBooleanValue(id, Boolean.valueOf(value));
}
// Parse integer value
String integer = getValue(n, "integer");
if (StringUtils.isNotBlank(integer)) {
String min = getValue(n, "minimumValue");
String max = getValue(n, "maximumValue");
return new WSIntegerValue(id, Integer.valueOf(integer), Integer.valueOf(min), Integer.valueOf(max));
}
// Parse timer value
String milliseconds = getValue(n, "milliseconds");
if (StringUtils.isNotBlank(milliseconds)) {
return new WSTimerValue(id, Integer.valueOf(milliseconds));
}
// Parse time value
String hours = getValue(n, "hours");
if (StringUtils.isNotBlank(hours)) {
String minutes = getValue(n, "minutes");
String seconds = getValue(n, "seconds");
return new WSTimeValue(id, Integer.valueOf(hours), Integer.valueOf(minutes), Integer.valueOf(seconds));
}
// Parse date value
String year = getValue(n, "year");
if (StringUtils.isNotBlank(year)) {
String month = getValue(n, "month");
String day = getValue(n, "day");
return new WSDateValue(id, Short.valueOf(year), Byte.valueOf(month), Byte.valueOf(day));
}
// Parse enum value
String definitionTypeID = getValue(n, "definitionTypeID");
if (StringUtils.isNotBlank(definitionTypeID)) {
String enumValueID = getValue(n, "enumValueID");
String enumName = getValue(n, "enumName");
return new WSEnumValue(id, Integer.valueOf(definitionTypeID), Integer.valueOf(enumValueID), enumName);
}
// Parse week day value
value = getValue(n, "weekdayNumber");
if (StringUtils.isNotBlank(value)) {
return new WSWeekdayValue(id, Integer.valueOf(value));
}
// Unknown value type
throw new IllegalArgumentException("Unsupported value type");
}
return null;
}
private String getValue(Node n, String value) throws XPathExpressionException {
return XPathUtils.getSpeficValueFromNode(n, "ns1:value/" + XPathUtils.createIgnoreNameSpaceSyntaxExpr(value));
}
/**
* Update resource value to controller.
*
*
* @param value Resource value.
* @return True if value is successfully updated.
*/
public boolean resourceUpdate(WSResourceValue value) throws IhcExecption {
boolean retval = false;
if (value instanceof WSFloatingPointValue) {
retval = resourceUpdate((WSFloatingPointValue) value);
} else if (value instanceof WSBooleanValue) {
retval = resourceUpdate((WSBooleanValue) value);
} else if (value instanceof WSIntegerValue) {
retval = resourceUpdate((WSIntegerValue) value);
} else if (value instanceof WSTimerValue) {
retval = resourceUpdate((WSTimerValue) value);
} else if (value instanceof WSWeekdayValue) {
retval = resourceUpdate((WSWeekdayValue) value);
} else if (value instanceof WSEnumValue) {
retval = resourceUpdate((WSEnumValue) value);
} else if (value instanceof WSTimeValue) {
retval = resourceUpdate((WSTimeValue) value);
} else if (value instanceof WSDateValue) {
retval = resourceUpdate((WSDateValue) value);
} else {
throw new IhcExecption("Unsupported value type " + value.getClass().toString());
}
return retval;
}
public boolean resourceUpdate(WSBooleanValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSBooleanValue\">\n"
+ " <q1:value>%s</q1:value>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.value ? "true" : "false", value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSFloatingPointValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSFloatingPointValue\">\n"
+ " <q1:maximumValue>%s</q1:maximumValue>\n"
+ " <q1:minimumValue>%s</q1:minimumValue>\n"
+ " <q1:floatingPointValue>%s</q1:floatingPointValue>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.maximumValue, value.minimumValue, value.value, value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSIntegerValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSIntegerValue\">\n"
+ " <q1:maximumValue>%s</q1:maximumValue>\n"
+ " <q1:minimumValue>%s</q1:minimumValue>\n"
+ " <q1:integer>%s</q1:integer>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.maximumValue, value.minimumValue, value.value, value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSTimerValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSTimerValue\">\n"
+ " <q1:milliseconds>%s</q1:milliseconds>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.milliseconds, value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSWeekdayValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSWeekdayValue\">\n"
+ " <q1:weekdayNumber>%s</q1:weekdayNumber>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.weekdayNumber, value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSEnumValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSEnumValue\">\n"
+ " <q1:definitionTypeID>%s</q1:definitionTypeID>\n"
+ " <q1:enumValueID>%s</q1:enumValueID>\n"
+ " <q1:enumName>%s</q1:enumName>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.definitionTypeID, value.enumValueID, value.enumName,
value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSTimeValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSTimeValue\">\n"
+ " <q1:hours>%s</q1:hours>\n"
+ " <q1:minutes>%s</q1:minutes>\n"
+ " <q1:seconds>%s</q1:seconds>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.hours, value.minutes, value.seconds, value.resourceID);
return doResourceUpdate(query);
}
public boolean resourceUpdate(WSDateValue value) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <setResourceValue1 xmlns=\"utcs\">\n"
+ " <value xmlns:q1=\"utcs.values\" xsi:type=\"q1:WSDateValue\">\n"
+ " <q1:month>%s</q1:month>\n"
+ " <q1:year>%s</q1:year>\n"
+ " <q1:day>%s</q1:day>\n"
+ " </value>\n"
+ " <resourceID>%s</resourceID>\n"
+ " <isValueRuntime>true</isValueRuntime>\n"
+ " </setResourceValue1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = String.format(soapQuery, value.month, value.year, value.day, value.resourceID);
return doResourceUpdate(query);
}
private boolean doResourceUpdate(String query) throws IhcExecption {
String response = sendSoapQuery(null, query);
try {
return Boolean.parseBoolean(
XPathUtils.parseXMLValue(response, "/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:setResourceValue2"));
} catch (IOException | XPathExpressionException e) {
throw new IhcExecption(e);
}
}
/**
* Enable resources runtime value notifications.
*
* @param resourceIdList List of resource Identifiers.
* @return True is connection successfully opened.
*/
public void enableRuntimeValueNotifications(Set<Integer> resourceIdList) throws IhcExecption {
// @formatter:off
final String soapQueryPrefix =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
+ " <soap:Body>\n"
+ " <enableRuntimeValueNotifications1 xmlns=\"utcs\">\n";
final String soapQuerySuffix =
" </enableRuntimeValueNotifications1>\n"
+ " </soap:Body>\n"
+ "</soap:Envelope>";
// @formatter:on
String query = soapQueryPrefix;
for (int i : resourceIdList) {
query += " <xsd:arrayItem>" + i + "</xsd:arrayItem>\n";
}
query += soapQuerySuffix;
sendSoapQuery(null, query);
}
/**
* Wait runtime value notifications.
*
* Runtime value notification should firstly be activated by
* enableRuntimeValueNotifications function.
*
* @param timeoutInSeconds How many seconds to wait notifications.
* @return List of received runtime value notifications.
* @throws SocketTimeoutException
* @throws IhcTimeoutExecption
*/
public List<WSResourceValue> waitResourceValueNotifications(int timeoutInSeconds) throws IhcExecption {
// @formatter:off
final String soapQuery =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:utcs=\"utcs\">\n"
+ " <soapenv:Body>\n"
+ " <utcs:waitForResourceValueChanges1>%s</utcs:waitForResourceValueChanges1>\n"
+ " </soapenv:Body>\n"
+ "</soapenv:Envelope>";
// @formatter:on
String query = String.format(soapQuery, timeoutInSeconds);
String response = sendSoapQuery(null, query, getTimeout() + timeoutInSeconds * 1000);
List<WSResourceValue> resourceValueList = new ArrayList<>();
try {
NodeList nodeList = XPathUtils.parseList(response,
"/SOAP-ENV:Envelope/SOAP-ENV:Body/ns1:waitForResourceValueChanges2/ns1:arrayItem");
if (nodeList != null) {
if (nodeList.getLength() == 1) {
String resourceId = XPathUtils.getSpeficValueFromNode(nodeList.item(0), "ns1:resourceID");
if (resourceId == null || resourceId.isEmpty()) {
// IHC controller indicates timeout, return empty list
return resourceValueList;
}
}
for (int i = 0; i < nodeList.getLength(); i++) {
WSResourceValue newVal = parseResourceValue(nodeList.item(i));
if (newVal != null) {
resourceValueList.add(newVal);
}
}
} else {
throw new IhcExecption("Illegal resource value notification response received");
}
return resourceValueList;
} catch (XPathExpressionException | NumberFormatException | IOException e) {
throw new IhcExecption("Error occured during XML data parsing", e);
}
}
}

View File

@@ -0,0 +1,40 @@
/**
* 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.ihc.internal.ws.services;
import org.openhab.binding.ihc.internal.ws.datatypes.WSTimeManagerSettings;
import org.openhab.binding.ihc.internal.ws.exeptions.IhcExecption;
import org.openhab.binding.ihc.internal.ws.http.IhcConnectionPool;
/**
* Class to handle IHC / ELKO LS Controller's time service.
*
* @author Pauli Anttila - Initial contribution
*/
public class IhcTimeService extends IhcBaseService {
public IhcTimeService(String host, int timeout, IhcConnectionPool ihcConnectionPool) {
super(ihcConnectionPool, timeout, host, "TimeManagerService");
}
/**
* Query time settings from the controller.
*
* @return time settings.
* @throws IhcExecption
*/
public synchronized WSTimeManagerSettings getTimeSettings() throws IhcExecption {
String response = sendSoapQuery("getSettings", EMPTY_QUERY);
return new WSTimeManagerSettings().parseXMLData(response);
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="ihc" 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>IHC / ELKO Binding</name>
<description>Binding to communicate IHC / ELKO controller</description>
<author>Pauli Anttila</author>
</binding:binding>

View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="ihc" 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">
<channel-type id="controller-state" advanced="true">
<item-type>String</item-type>
<label>Controller State</label>
<description>Displays IHC / ELKO controller state</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="controller-uptime" advanced="true">
<item-type>Number</item-type>
<label>Controller Uptime</label>
<description>Displays IHC / ELKO controller uptime in seconds</description>
<state readOnly="true" pattern="%.3f sec"></state>
</channel-type>
<channel-type id="controller-time" advanced="true">
<item-type>DateTime</item-type>
<label>Controller Date and Time</label>
<description>Displays IHC / ELKO controller date and time</description>
<state readOnly="true"></state>
</channel-type>
<channel-type id="switch">
<item-type>Switch</item-type>
<label>Generic Switch</label>
<description>Generic switch channel</description>
<state readOnly="false"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="direction" type="text" required="false">
<label>Channel Direction</label>
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
<default>ReadWrite</default>
<options>
<option value="ReadWrite">Read Write</option>
<option value="WriteOnly">Write only</option>
<option value="ReadOnly">Read only</option>
</options>
</parameter>
<parameter name="commandToReact" type="text" required="false">
<label>Command to React</label>
<description>Command to react. If not defined, channel react to all commands.</description>
</parameter>
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
<label>Pulse Width</label>
<description>Pulse width in milliseconds. If defined, binding send pulse rather than command value to IHC
controller.</description>
</parameter>
<parameter name="inverted" type="boolean" required="false">
<label>Inverted Signal</label>
<description>openHAB state is inverted compared to IHC output/input signal</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="contact">
<item-type>Contact</item-type>
<label>Generic Contact</label>
<description>Generic contact channel</description>
<state readOnly="true"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="inverted" type="boolean" required="false">
<label>Inverted Signal</label>
<description>openHAB state is inverted compared to IHC output/input signal</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="number">
<item-type>Number</item-type>
<label>Generic Number</label>
<description>Generic number channel</description>
<state readOnly="false"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="direction" type="text" required="false">
<label>Channel Direction</label>
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
<default>ReadWrite</default>
<options>
<option value="ReadWrite">Read Write</option>
<option value="WriteOnly">Write only</option>
<option value="ReadOnly">Read only</option>
</options>
</parameter>
<parameter name="commandToReact" type="text" required="false">
<label>Command to React</label>
<description>Command to react. If not defined, channel react to all commands.</description>
</parameter>
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
<label>Pulse Width</label>
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="dimmer">
<item-type>Dimmer</item-type>
<label>Generic Dimmer</label>
<description>Generic dimmer channel</description>
<state readOnly="false"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="direction" type="text" required="false">
<label>Channel Direction</label>
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
<default>ReadWrite</default>
<options>
<option value="ReadWrite">Read Write</option>
<option value="WriteOnly">Write only</option>
<option value="ReadOnly">Read only</option>
</options>
</parameter>
<parameter name="commandToReact" type="text" required="false">
<label>Command to React</label>
<description>Command to react. If not defined, channel react to all commands.</description>
</parameter>
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
<label>Pulse Width</label>
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
</parameter>
<parameter name="onLevel" type="integer" required="false" min="0" max="100" step="1">
<label>ON Command Level</label>
<description>If defined, binding use this level when ON command is received rather than resource maximum value.
Level is anyhow limited to resource maximum value.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="datetime">
<item-type>DateTime</item-type>
<label>Generic Datetime</label>
<description>Generic datetime channel</description>
<state readOnly="false"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="direction" type="text" required="false">
<label>Channel Direction</label>
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
<default>ReadWrite</default>
<options>
<option value="ReadWrite">Read Write</option>
<option value="WriteOnly">Write only</option>
<option value="ReadOnly">Read only</option>
</options>
</parameter>
<parameter name="commandToReact" type="text" required="false">
<label>Command to React</label>
<description>Command to react. If not defined, channel react to all commands.</description>
</parameter>
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
<label>Pulse Width</label>
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="string">
<item-type>String</item-type>
<label>Generic String</label>
<description>Generic string channel</description>
<state readOnly="false"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="direction" type="text" required="false">
<label>Channel Direction</label>
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
<default>ReadWrite</default>
<options>
<option value="ReadWrite">Read Write</option>
<option value="WriteOnly">Write only</option>
<option value="ReadOnly">Read only</option>
</options>
</parameter>
<parameter name="commandToReact" type="text" required="false">
<label>Command to React</label>
<description>Command to react. If not defined, channel react to all commands.</description>
</parameter>
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
<label>Pulse Width</label>
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="rollershutter">
<item-type>RollerShutter</item-type>
<label>Generic Roller Shutter</label>
<description>Generic roller shutter channel</description>
<state readOnly="false"></state>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="direction" type="text" required="false">
<label>Channel Direction</label>
<description>Direction of the channel. By default, channel is synchronized in both directions.</description>
<default>ReadWrite</default>
<options>
<option value="ReadWrite">Read Write</option>
<option value="WriteOnly">Write only</option>
<option value="ReadOnly">Read only</option>
</options>
</parameter>
<parameter name="commandToReact" type="text" required="false">
<label>Command to React</label>
<description>Command to react. If not defined, channel react to all commands.</description>
</parameter>
<parameter name="pulseWidth" type="integer" required="false" min="0" max="4000" step="100" unit="ms">
<label>Pulse Width</label>
<description>If defined, binding send pulse rather than command value to IHC controller.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="rf-device-low-battery">
<item-type>Switch</item-type>
<label>RF Device Low Battery Warning</label>
<description>RF device low battery warning.</description>
<category>Battery</category>
<state readOnly="true"></state>
<config-description>
<parameter name="serialNumber" type="integer" required="true">
<label>RF Device Serial Number</label>
<description>Serial Number of RF device in decimal format.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="rf-device-signal-strength">
<item-type>String</item-type>
<label>RF Device Signal Strength</label>
<description>RF device signal strength.</description>
<category>QualityOfService</category>
<state readOnly="true" min="0" max="4">
<options>
<option value="0">No signal</option>
<option value="1">Weak</option>
<option value="2">Average</option>
<option value="3">Good</option>
<option value="4">Excellent</option>
</options>
</state>
<config-description>
<parameter name="serialNumber" type="integer" required="true">
<label>RF Device Serial Number</label>
<description>Serial number of RF device in decimal format.</description>
</parameter>
</config-description>
</channel-type>
<channel-type id="push-button-trigger">
<kind>trigger</kind>
<label>Push Button Trigger Channel</label>
<event>
<options>
<option value="PRESSED">Pressed</option>
<option value="RELEASED">Released</option>
<option value="SHORT_PRESS">Short press</option>
<option value="LONG_PRESS">Long press</option>
</options>
</event>
<config-description>
<parameter name="resourceId" type="integer" required="true">
<label>Resource Id</label>
<description></description>
</parameter>
<parameter name="longPressTime" type="integer" required="true" step="1000" min="0" max="5000" unit="ms">
<label>Long Press Time</label>
<description>Long press time in milliseconds.</description>
<default>1000</default>
</parameter>
</config-description>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="ihc" 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">
<thing-type id="controller"
extensible="switch, contact, number, dimmmer, datetime, string, rollershutter, pulse-output, rf-device-battery-level, rf-device-signal-strength, push-button-trigger">
<label>IHC / ELKO Controller</label>
<description></description>
<channels>
<channel typeId="controller-state" id="controllerState"/>
<channel typeId="controller-uptime" id="controllerUptime"/>
<channel typeId="controller-time" id="controllerTime"/>
</channels>
<properties>
<property name="controllerManufacturer"/>
<property name="controllerSerialNumber"/>
<property name="controllerSwVersion"/>
<property name="controllerHwVersion"/>
<property name="controllerIsWithoutViewer"/>
<property name="controllerSwDate"/>
<property name="controllerProductionDate"/>
<property name="projectDate"/>
<property name="projectNumber"/>
</properties>
<config-description>
<parameter name="hostname" type="text" required="true">
<context>network-address</context>
<label>Network Address</label>
<description>Network/IP address of the IHC / ELKO controller without https prefix, but can contain TCP port if
default port is not used</description>
</parameter>
<parameter name="username" type="text" required="true">
<label>User Name</label>
<description>User name to login to the IHC / ELKO controller.</description>
</parameter>
<parameter name="password" type="text" required="true">
<context>password</context>
<label>Password</label>
<description>Password to login to the IHC / ELKO controller.</description>
</parameter>
<parameter name="timeout" type="integer" required="false" step="1000" unit="ms">
<label>Timeout</label>
<description>Timeout to communicate to IHC / ELKO controller.</description>
<default>5000</default>
</parameter>
<parameter name="loadProjectFile" type="boolean" required="false">
<label>Load Project File</label>
<description>Load project file from controller.</description>
<default>true</default>
</parameter>
<parameter name="createChannelsAutomatically" type="boolean" required="false">
<label>Create Channels Automatically</label>
<description>Create channels automatically from project file. Project file loading parameter should be enabled as
well.</description>
<default>true</default>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,75 @@
/**
* 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.ihc.internal;
import static org.junit.Assert.*;
import java.time.Duration;
import org.junit.Test;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class ButtonPressDurationDetectorTest {
@Test
public void testShortPress() {
Duration duration = Duration.ofMillis(450);
long longPressTime = 1000;
long longPressMaxTime = 2000;
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
assertTrue(button.isShortPress());
assertFalse(button.isLongPress());
}
@Test
public void testLongPress() {
Duration duration = Duration.ofMillis(1003);
long longPressTime = 1000;
long longPressMaxTime = 2000;
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
assertFalse(button.isShortPress());
assertTrue(button.isLongPress());
}
@Test
public void testExtraLongPress() {
Duration duration = Duration.ofMillis(2423);
long longPressTime = 1000;
long longPressMaxTime = 2000;
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
assertFalse(button.isShortPress());
assertFalse(button.isLongPress());
}
@Test
public void testTooLongPress() {
Duration duration = Duration.ofMillis(5001);
long longPressTime = 1000;
long longPressMaxTime = 2000;
ButtonPressDurationDetector button = new ButtonPressDurationDetector(duration, longPressTime, longPressMaxTime);
assertFalse(button.isShortPress());
assertFalse(button.isLongPress());
}
}

View File

@@ -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.ihc.internal;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class SignalLevelConverterTest {
@Test
public void checkSignalLevelConverter() {
// IHC signal levels are between 0-18.
assertEquals(0, new SignalLevelConverter(0).getSystemWideSignalLevel());
assertEquals(0, new SignalLevelConverter(1).getSystemWideSignalLevel());
assertEquals(1, new SignalLevelConverter(2).getSystemWideSignalLevel());
assertEquals(1, new SignalLevelConverter(3).getSystemWideSignalLevel());
assertEquals(1, new SignalLevelConverter(4).getSystemWideSignalLevel());
assertEquals(2, new SignalLevelConverter(5).getSystemWideSignalLevel());
assertEquals(2, new SignalLevelConverter(6).getSystemWideSignalLevel());
assertEquals(2, new SignalLevelConverter(7).getSystemWideSignalLevel());
assertEquals(2, new SignalLevelConverter(8).getSystemWideSignalLevel());
assertEquals(3, new SignalLevelConverter(9).getSystemWideSignalLevel());
assertEquals(3, new SignalLevelConverter(10).getSystemWideSignalLevel());
assertEquals(3, new SignalLevelConverter(11).getSystemWideSignalLevel());
assertEquals(3, new SignalLevelConverter(12).getSystemWideSignalLevel());
assertEquals(3, new SignalLevelConverter(13).getSystemWideSignalLevel());
assertEquals(4, new SignalLevelConverter(14).getSystemWideSignalLevel());
assertEquals(4, new SignalLevelConverter(15).getSystemWideSignalLevel());
assertEquals(4, new SignalLevelConverter(16).getSystemWideSignalLevel());
assertEquals(4, new SignalLevelConverter(17).getSystemWideSignalLevel());
assertEquals(4, new SignalLevelConverter(18).getSystemWideSignalLevel());
}
}

View File

@@ -0,0 +1,59 @@
/**
* 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.ihc.internal.converters;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSDateValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.types.Type;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class DateTimeTypeWSDateValueConverterTest {
@Test
public void testConversion() throws ConversionException {
final DateTimeType dateTimeType = new DateTimeType("2000-12-30T00:00:00");
WSDateValue val = new WSDateValue(12345, (short) 1999, (byte) 1, (byte) 1);
val = convertFromOHType(val, dateTimeType, null);
assertEquals(12345, val.resourceID);
assertEquals(2000, val.year);
assertEquals(12, val.month);
assertEquals(30, val.day);
DateTimeType type = convertFromResourceValue(val, null);
assertEquals(dateTimeType.format("yyyy-MM-dd"), type.format("yyyy-MM-dd"));
}
private WSDateValue convertFromOHType(WSDateValue IHCvalue, Type OHval,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DateTimeType.class);
return (WSDateValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
}
private DateTimeType convertFromResourceValue(WSDateValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DateTimeType.class);
return (DateTimeType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
}
}

View File

@@ -0,0 +1,59 @@
/**
* 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.ihc.internal.converters;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSTimeValue;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.types.Type;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class DateTimeTypeWSTimeValueConverterTest {
@Test
public void testConversion() throws ConversionException {
final DateTimeType dateTimeType = new DateTimeType("2000-12-30T13:59:30");
WSTimeValue val = new WSTimeValue(12345, 0, 0, 0);
val = convertFromOHType(val, dateTimeType, null);
assertEquals(12345, val.resourceID);
assertEquals(13, val.hours);
assertEquals(59, val.minutes);
assertEquals(30, val.seconds);
DateTimeType type = convertFromResourceValue(val, null);
assertEquals(dateTimeType.format("HH:mm:ss"), type.format("HH:mm:ss"));
}
private WSTimeValue convertFromOHType(WSTimeValue IHCvalue, Type OHval,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DateTimeType.class);
return (WSTimeValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
}
private DateTimeType convertFromResourceValue(WSTimeValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DateTimeType.class);
return (DateTimeType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
}
}

View File

@@ -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.ihc.internal.converters;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSBooleanValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Type;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSBooleanValueConverterTest {
@Test
public void testOn() throws ConversionException {
final boolean inverted = false;
WSBooleanValue val = new WSBooleanValue(12345, false);
val = convertFromOHType(val, new DecimalType(1), new ConverterAdditionalInfo(null, inverted, null));
assertEquals(12345, val.resourceID);
assertEquals(true, val.value);
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
assertEquals(new DecimalType(1), type);
}
@Test
public void testOff() throws ConversionException {
final boolean inverted = false;
WSBooleanValue val = new WSBooleanValue(12345, true);
val = convertFromOHType(val, new DecimalType(0), new ConverterAdditionalInfo(null, inverted, null));
assertEquals(12345, val.resourceID);
assertEquals(false, val.value);
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, inverted, null));
assertEquals(new DecimalType(0), type);
}
private WSBooleanValue convertFromOHType(WSBooleanValue IHCvalue, Type OHval,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (WSBooleanValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
}
private DecimalType convertFromResourceValue(WSBooleanValue IHCvalue,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
}
}

View File

@@ -0,0 +1,58 @@
/**
* 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.ihc.internal.converters;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSEnumValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Type;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSEnumValueConverterTest {
@Test
public void testConversion() throws ConversionException {
WSEnumValue val = new WSEnumValue(12345, 100, 0, "testB");
val = convertFromOHType(val, new DecimalType(2), new ConverterAdditionalInfo(null, false, null));
assertEquals(12345, val.resourceID);
assertEquals(100, val.definitionTypeID);
assertEquals(2, val.enumValueID);
assertEquals("testB", val.enumName);
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
assertEquals(new DecimalType(2), type);
}
private WSEnumValue convertFromOHType(WSEnumValue IHCvalue, Type OHval,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (WSEnumValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
}
private DecimalType convertFromResourceValue(WSEnumValue IHCvalue, ConverterAdditionalInfo converterAdditionalInfo)
throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
}
}

View File

@@ -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.ihc.internal.converters;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSFloatingPointValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Type;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSFloatingPointValueConverterTest {
@Test
public void testConversion() throws ConversionException {
WSFloatingPointValue val = new WSFloatingPointValue(12345, 0, -100, 100);
val = convertFromOHType(val, new DecimalType(2.54), new ConverterAdditionalInfo(null, false, null));
assertEquals(12345, val.resourceID);
assertEquals(-100, val.minimumValue, 0.001);
assertEquals(100, val.maximumValue, 0.001);
assertEquals(2.54, val.value, 0.001);
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
assertEquals(new DecimalType(2.54), type);
}
@Test(expected = ConversionException.class)
public void testMinExceed() throws ConversionException {
WSFloatingPointValue val = new WSFloatingPointValue(12345, 0, -100, 100);
val = convertFromOHType(val, new DecimalType(-101.5), new ConverterAdditionalInfo(null, false, null));
}
@Test(expected = ConversionException.class)
public void testMaxExceed() throws ConversionException {
WSFloatingPointValue val = new WSFloatingPointValue(12345, 0, -100, 100);
val = convertFromOHType(val, new DecimalType(101.5), new ConverterAdditionalInfo(null, false, null));
}
private WSFloatingPointValue convertFromOHType(WSFloatingPointValue IHCvalue, Type OHval,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (WSFloatingPointValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
}
private DecimalType convertFromResourceValue(WSFloatingPointValue IHCvalue,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
}
}

View File

@@ -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.ihc.internal.converters;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.openhab.binding.ihc.internal.ws.exeptions.ConversionException;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSIntegerValue;
import org.openhab.binding.ihc.internal.ws.resourcevalues.WSResourceValue;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.types.Type;
/**
* Test for IHC / ELKO binding
*
* @author Pauli Anttila - Initial contribution
*/
public class DecimalTypeWSIntegerValueConverterTest {
@Test
public void testConversion() throws ConversionException {
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
val = convertFromOHType(val, new DecimalType(2), new ConverterAdditionalInfo(null, false, null));
assertEquals(12345, val.resourceID);
assertEquals(2, val.value);
assertEquals(-100, val.minimumValue);
assertEquals(100, val.maximumValue);
DecimalType type = convertFromResourceValue(val, new ConverterAdditionalInfo(null, false, null));
assertEquals(new DecimalType(2), type);
}
@Test(expected = ConversionException.class)
public void testMinExceed() throws ConversionException {
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
val = convertFromOHType(val, new DecimalType(-101.5), new ConverterAdditionalInfo(null, false, null));
}
@Test(expected = ConversionException.class)
public void testMaxExceed() throws ConversionException {
WSIntegerValue val = new WSIntegerValue(12345, 0, -100, 100);
val = convertFromOHType(val, new DecimalType(101.5), new ConverterAdditionalInfo(null, false, null));
}
private WSIntegerValue convertFromOHType(WSIntegerValue IHCvalue, Type OHval,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (WSIntegerValue) converter.convertFromOHType(OHval, IHCvalue, converterAdditionalInfo);
}
private DecimalType convertFromResourceValue(WSIntegerValue IHCvalue,
ConverterAdditionalInfo converterAdditionalInfo) throws ConversionException {
Converter<WSResourceValue, Type> converter = ConverterFactory.getInstance().getConverter(IHCvalue.getClass(),
DecimalType.class);
return (DecimalType) converter.convertFromResourceValue(IHCvalue, converterAdditionalInfo);
}
}

Some files were not shown because too many files have changed in this diff Show More