mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[ekey] initial contribution / oh1 migration (#10996)
* [ekey] initial contribution / oh1 migration Signed-off-by: Hans-Jörg Merk <github@hmerk.de>
This commit is contained in:
parent
4b13a26f15
commit
f1e7f19d4e
@ -74,6 +74,7 @@
|
|||||||
/bundles/org.openhab.binding.dwdunwetter/ @limdul79
|
/bundles/org.openhab.binding.dwdunwetter/ @limdul79
|
||||||
/bundles/org.openhab.binding.ecobee/ @mhilbush
|
/bundles/org.openhab.binding.ecobee/ @mhilbush
|
||||||
/bundles/org.openhab.binding.ecotouch/ @sibbi77
|
/bundles/org.openhab.binding.ecotouch/ @sibbi77
|
||||||
|
/bundles/org.openhab.binding.ekey/ @hmerk
|
||||||
/bundles/org.openhab.binding.elerotransmitterstick/ @vbier
|
/bundles/org.openhab.binding.elerotransmitterstick/ @vbier
|
||||||
/bundles/org.openhab.binding.energenie/ @hmerk
|
/bundles/org.openhab.binding.energenie/ @hmerk
|
||||||
/bundles/org.openhab.binding.enigma2/ @gdolfen
|
/bundles/org.openhab.binding.enigma2/ @gdolfen
|
||||||
|
@ -356,6 +356,11 @@
|
|||||||
<artifactId>org.openhab.binding.ecotouch</artifactId>
|
<artifactId>org.openhab.binding.ecotouch</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.binding.ekey</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.binding.elerotransmitterstick</artifactId>
|
<artifactId>org.openhab.binding.elerotransmitterstick</artifactId>
|
||||||
|
13
bundles/org.openhab.binding.ekey/NOTICE
Normal file
13
bundles/org.openhab.binding.ekey/NOTICE
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
This content is produced and maintained by the openHAB project.
|
||||||
|
|
||||||
|
* Project home: https://www.openhab.org
|
||||||
|
|
||||||
|
== Declared Project Licenses
|
||||||
|
|
||||||
|
This program and the accompanying materials are made available under the terms
|
||||||
|
of the Eclipse Public License 2.0 which is available at
|
||||||
|
https://www.eclipse.org/legal/epl-2.0/.
|
||||||
|
|
||||||
|
== Source Code
|
||||||
|
|
||||||
|
https://github.com/openhab/openhab-addons
|
135
bundles/org.openhab.binding.ekey/README.md
Normal file
135
bundles/org.openhab.binding.ekey/README.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
# ekey Binding
|
||||||
|
|
||||||
|
This binding connects to [ekey](https://ekey.net/) converter UDP (CV-LAN) using the RARE/MULTI/HOME protocols.
|
||||||
|
|
||||||
|
## Supported Things
|
||||||
|
|
||||||
|
This binding only supports one thing type:
|
||||||
|
|
||||||
|
| Thing | Thing Type | Description |
|
||||||
|
|-------------|------------|---------------------------------------------|
|
||||||
|
| cvlan | Thing | Represents a single ekey converter UDP |
|
||||||
|
|
||||||
|
## Thing Configuration
|
||||||
|
|
||||||
|
The binding uses the following configuration parameters.
|
||||||
|
|
||||||
|
| Parameter | Description |
|
||||||
|
|-----------|----------------------------------------------------------------|
|
||||||
|
| ipAddress | IPv4 address of the eKey udp converter. A static IP address is recommended.|
|
||||||
|
| port | The port as configured during the UDP Converter configuration. e.g. 56000 (Binding default) |
|
||||||
|
| protocol | Can be RARE, MULTI or HOME depending on what the system supports. Binding defaults to RARE |
|
||||||
|
| delimiter | The delimiter is also defined on the ekey UDP converter - use the ekey configuration software to determine which delimiter is used or to change it. Binding default is `_` (underscore) |
|
||||||
|
|
||||||
|
## Channels
|
||||||
|
|
||||||
|
| Channel ID | Item Type | Protocol | Description | Possible Values |
|
||||||
|
|------------|-----------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
|
||||||
|
| action | Number | R/M/H | This indicates whether access was granted (value=0) or denied (value=-1). | 0,-1 (136 and 137 with RARE protocol |
|
||||||
|
| fingerId | Number | R/M/H | This indicates the finger that was used by a person. | 0-9,-1 |
|
||||||
|
| fsName | String | M | This returns the 4-character-long name that was specified on the controller for the specific terminals. | |
|
||||||
|
| fsSerial | Number | R/M/H | This returns the serial number for the specific terminal. |
|
||||||
|
| inputId | Number | M | This indicates which of the four digital inputs was triggered. Value is number of Input. "-1" indicates that no input was triggered. | 0-4,-1 |
|
||||||
|
| keyId | Number | M | This indicates which of the four keys was used. See ekey documentation on "keys". | 0-4,-1 |
|
||||||
|
| relayId | Number | R/H | This indicates which relay has been switched. | 0-3,-1 |
|
||||||
|
| termId | Number | R | This provides the serial number of the packet source. The source can be a fingerprint terminal or the controller (in case of digital inputs). The Serial number has a length of 13. When using RARE mode, only the trailing 8 digits can be returned. | |
|
||||||
|
| userId | Number | R/M/H | This indicates which user has been detected on the terminal. The value is the numerical order of the user as it was specified on the controller. | 0-99,-1 |
|
||||||
|
| userName | String | M | This returns the ten-character-long name of the person that has been recognized on the terminal. The name that is returned must have been previously specified on the controller. | |
|
||||||
|
| userStatus | Number | M | This indicates the status of the user (-1=undefined, 1=enabled, 0= disabled) | 0,1,-1 |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
example.things
|
||||||
|
|
||||||
|
```
|
||||||
|
Thing ekey:cvlan:de3b8db06e "Ekey Udp Converter" @ "Control Panel" [ ipAddress="xxx.xxx.xxx.xxx", port="56000", protocol="RARE", delimiter="_" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
rare.items
|
||||||
|
|
||||||
|
```
|
||||||
|
Number Action "Last action [MAP(ekey_action.map):%d]" { channel="ekey:cvlan:de3b8db06e:action" }
|
||||||
|
Number FingerID "User used finger [MAP(ekey_finger.map):%d]" { channel="ekey:cvlan:de3b8db06e:fingerId" }
|
||||||
|
Number RelayID "Last relay that has been swiched [%d]" { channel="ekey:cvlan:de3b8db06e:relayId" }
|
||||||
|
Number Serialnumber "Serialnumber [%d]" { channel="ekey:cvlan:de3b8db06e:fsSerial" }
|
||||||
|
Number TerminalID "Last used terminal [MAP(ekey_terminal.map):%d]" { channel="ekey:cvlan:de3b8db06e:termId" }
|
||||||
|
Number UserID "Last user that accessed the house was [MAP(ekey_names.map):%d]" { channel="ekey:cvlan:de3b8db06e:userId" }
|
||||||
|
```
|
||||||
|
|
||||||
|
multi.items
|
||||||
|
|
||||||
|
```
|
||||||
|
Number Action "Last action [MAP(ekey_action.map):%d]" { channel="ekey:cvlan:de3b8db06e:action" }
|
||||||
|
Number FingerID "User used finger [MAP(ekey_finger.map):%d]" { channel="ekey:cvlan:de3b8db06e:fingerId" }
|
||||||
|
String FsName "Name of Scanner [%s] { channel="ekey:cvlan:de3b8db06e:fsName" }
|
||||||
|
Number FsSerial "Serialnumber [%d]" { channel="ekey:cvlan:de3b8db06e:fsSerial" }
|
||||||
|
Number InputID "Last input that has been triggered [%d]" { channel="ekey:cvlan:de3b8db06e:inputId" }
|
||||||
|
Number KeyID "Last key that has been used [%d]" { channel="ekey:cvlan:de3b8db06e:keyId" }
|
||||||
|
Number UserID "Last user that accessed the house was [MAP(ekey_names.map):%d]" { channel="ekey:cvlan:de3b8db06e:userId" }
|
||||||
|
String UserName " Name of Last user that accessed the house was : [%d]" { channel="ekey:cvlan:de3b8db06e:userName" }
|
||||||
|
Number UserStatus "Last user that accessed the house was [MAP(ekey_names.map):%d]" { channel="ekey:cvlan:de3b8db06e:userStatus" }
|
||||||
|
```
|
||||||
|
|
||||||
|
home.items
|
||||||
|
|
||||||
|
```
|
||||||
|
Number Action "Last action [MAP(ekey_action.map):%d]" { channel="ekey:cvlan:de3b8db06e:action" }
|
||||||
|
Number FingerID "User used finger [MAP(ekey_finger.map):%d]" { channel="ekey:cvlan:de3b8db06e:fingerId" }
|
||||||
|
Number RelayID "Last relay that has been swiched [%d]" { channel="ekey:cvlan:de3b8db06e:relayId" }
|
||||||
|
Number Serialnumber "Serialnumber [%d]" { channel="ekey:cvlan:de3b8db06e:fsSerial" }
|
||||||
|
Number UserID "Last user that accessed the house was [MAP(ekey_names.map):%d]" { channel="ekey:cvlan:de3b8db06e:userId" }
|
||||||
|
```
|
||||||
|
|
||||||
|
transform/ekey_finger.map [This is just an example, as there is no strict rule what finger belongs to what number]
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
0=leftlittle
|
||||||
|
1=leftring
|
||||||
|
2=leftmiddle
|
||||||
|
3=leftindex
|
||||||
|
4=leftthumb
|
||||||
|
5=rightthumb
|
||||||
|
6=rightindex
|
||||||
|
7=rightmiddle
|
||||||
|
8=rightring
|
||||||
|
9=rightlittle
|
||||||
|
-1=unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
transform/ekey_names.map [NO spaces allowed]
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
-1=Unspecified
|
||||||
|
1=JohnDoe
|
||||||
|
2=JaneDoe
|
||||||
|
```
|
||||||
|
|
||||||
|
transform/ekey_terminal.map
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
80156839130911=Front
|
||||||
|
80156839130914=Back
|
||||||
|
```
|
||||||
|
|
||||||
|
transform/ekey_multi_action.map
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
0=granted
|
||||||
|
-1=rejected
|
||||||
|
1=timeoutA
|
||||||
|
2=timeoutB
|
||||||
|
3=inactive
|
||||||
|
4=alwaysuser
|
||||||
|
5=notcoupled
|
||||||
|
6=digitalinput
|
||||||
|
```
|
||||||
|
|
||||||
|
transform/ekey_rare_action.map
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
136=granted
|
||||||
|
137=rejected
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
17
bundles/org.openhab.binding.ekey/pom.xml
Normal file
17
bundles/org.openhab.binding.ekey/pom.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
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.2.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>org.openhab.binding.ekey</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: Ekey Binding</name>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<features name="org.openhab.binding.ekey-${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-ekey" description="Ekey Binding" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.ekey/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link EkeyBindingConstants} class defines common constants, which are
|
||||||
|
* used across the whole binding.
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class EkeyBindingConstants {
|
||||||
|
|
||||||
|
public static final String BINDING_ID = "ekey";
|
||||||
|
|
||||||
|
// List of all Thing Type UIDs
|
||||||
|
public static final ThingTypeUID THING_TYPE_CVLAN = new ThingTypeUID(BINDING_ID, "cvlan");
|
||||||
|
|
||||||
|
// List of all Channel ids
|
||||||
|
public static final String CHANNEL_TYPE_USERID = "userId";
|
||||||
|
public static final String CHANNEL_TYPE_USERNAME = "userName";
|
||||||
|
public static final String CHANNEL_TYPE_USERSTATUS = "userStatus";
|
||||||
|
public static final String CHANNEL_TYPE_FINGERID = "fingerId";
|
||||||
|
public static final String CHANNEL_TYPE_KEYID = "keyId";
|
||||||
|
public static final String CHANNEL_TYPE_FSSERIAL = "fsSerial";
|
||||||
|
public static final String CHANNEL_TYPE_FSNAME = "fsName";
|
||||||
|
public static final String CHANNEL_TYPE_ACTION = "action";
|
||||||
|
public static final String CHANNEL_TYPE_INPUTID = "inputId";
|
||||||
|
public static final String CHANNEL_TYPE_RELAYID = "relayId";
|
||||||
|
public static final String CHANNEL_TYPE_TERMID = "termId";
|
||||||
|
public static final String CHANNEL_TYPE_RESERVED = "relayId";
|
||||||
|
public static final String CHANNEL_TYPE_EVENT = "event";
|
||||||
|
public static final String CHANNEL_TYPE_TIMESTAMP = "timestamp";
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link EkeyConfiguration} class contains fields mapping thing configuration parameters.
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class EkeyConfiguration {
|
||||||
|
|
||||||
|
public String ipAddress = "";
|
||||||
|
public int port;
|
||||||
|
public String protocol = "";
|
||||||
|
public String delimiter = "";
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.events.EventPublisher;
|
||||||
|
import org.openhab.core.thing.binding.BaseDynamicStateDescriptionProvider;
|
||||||
|
import org.openhab.core.thing.i18n.ChannelTypeI18nLocalizationService;
|
||||||
|
import org.openhab.core.thing.link.ItemChannelLinkRegistry;
|
||||||
|
import org.openhab.core.thing.type.DynamicStateDescriptionProvider;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@Component(service = { DynamicStateDescriptionProvider.class, EkeyDynamicStateDescriptionProvider.class })
|
||||||
|
@NonNullByDefault
|
||||||
|
public class EkeyDynamicStateDescriptionProvider extends BaseDynamicStateDescriptionProvider {
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public EkeyDynamicStateDescriptionProvider(final @Reference EventPublisher eventPublisher, //
|
||||||
|
final @Reference ItemChannelLinkRegistry itemChannelLinkRegistry, //
|
||||||
|
final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
|
||||||
|
this.eventPublisher = eventPublisher;
|
||||||
|
this.itemChannelLinkRegistry = itemChannelLinkRegistry;
|
||||||
|
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal;
|
||||||
|
|
||||||
|
import static org.openhab.binding.ekey.internal.EkeyBindingConstants.THING_TYPE_CVLAN;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.ekey.internal.handler.EkeyHandler;
|
||||||
|
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.ComponentContext;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link EkeyHandlerFactory} is responsible for creating things and thing
|
||||||
|
* handlers.
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(configurationPid = "binding.ekey", service = ThingHandlerFactory.class)
|
||||||
|
public class EkeyHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
|
||||||
|
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_CVLAN);
|
||||||
|
|
||||||
|
private final EkeyDynamicStateDescriptionProvider ekeyStateDescriptionProvider;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public EkeyHandlerFactory(ComponentContext componentContext,
|
||||||
|
final @Reference EkeyDynamicStateDescriptionProvider dynamicStateDescriptionProvider) {
|
||||||
|
this.ekeyStateDescriptionProvider = dynamicStateDescriptionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 (THING_TYPE_CVLAN.equals(thingTypeUID)) {
|
||||||
|
return new EkeyHandler(thing, ekeyStateDescriptionProvider);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal.api;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link EkeyPacketListener} is in interface for a Ekey packet received consumer
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public interface EkeyPacketListener {
|
||||||
|
/**
|
||||||
|
* This method will be called in case a message was received.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void messageReceived(byte[] message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will be called in case the connection status has changed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void connectionStatusChanged(ThingStatus status, byte @Nullable [] message);
|
||||||
|
}
|
@ -0,0 +1,158 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.ekey.internal.handler.EkeyHandler;
|
||||||
|
import org.openhab.core.thing.ThingStatus;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Class provides the DatagramSocket that listens for eKey packets on the network
|
||||||
|
* This will run in a thread and can be interrupted by calling <code>stopListener()<code>
|
||||||
|
* Before starting the thread initialization is required (mode, ip, port and deliminator)
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class EkeyUdpPacketReceiver {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(EkeyUdpPacketReceiver.class);
|
||||||
|
|
||||||
|
private final int buffersize = 1024;
|
||||||
|
private final String ipAddress;
|
||||||
|
private final int port;
|
||||||
|
private final String readerThreadName;
|
||||||
|
|
||||||
|
private @Nullable DatagramSocket socket;
|
||||||
|
|
||||||
|
private @Nullable EkeyPacketListener packetListener;
|
||||||
|
|
||||||
|
private boolean connected = false;
|
||||||
|
|
||||||
|
public EkeyUdpPacketReceiver(final String ipAddress, final int port, final String readerThreadName) {
|
||||||
|
this.ipAddress = ipAddress;
|
||||||
|
this.port = port;
|
||||||
|
this.readerThreadName = readerThreadName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openConnection() throws IOException {
|
||||||
|
closeConnection();
|
||||||
|
|
||||||
|
EkeyPacketListener listener = this.packetListener;
|
||||||
|
|
||||||
|
socket = new DatagramSocket(port);
|
||||||
|
|
||||||
|
Thread udpListener = new Thread(new UDPListener());
|
||||||
|
udpListener.setName(readerThreadName);
|
||||||
|
udpListener.setDaemon(true);
|
||||||
|
udpListener.start();
|
||||||
|
|
||||||
|
setConnected(true);
|
||||||
|
if (listener != null) {
|
||||||
|
listener.connectionStatusChanged(ThingStatus.ONLINE, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeConnection() {
|
||||||
|
setConnected(false);
|
||||||
|
try {
|
||||||
|
DatagramSocket localSocket = socket;
|
||||||
|
if (localSocket != null) {
|
||||||
|
localSocket.close();
|
||||||
|
localSocket = null;
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
logger.debug("closeConnection(): Error closing connection - {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UDPListener implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run method. Runs the MessageListener thread
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
logger.debug("Starting ekey Packet Receiver");
|
||||||
|
|
||||||
|
DatagramSocket localSocket = socket;
|
||||||
|
|
||||||
|
if (localSocket == null) {
|
||||||
|
throw new IllegalStateException("Cannot access socket.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] lastPacket = null;
|
||||||
|
DatagramPacket packet = new DatagramPacket(new byte[buffersize], buffersize);
|
||||||
|
packet.setData(new byte[buffersize]);
|
||||||
|
|
||||||
|
while (isConnected()) {
|
||||||
|
try {
|
||||||
|
logger.trace("Listen for incoming packet");
|
||||||
|
localSocket.receive(packet);
|
||||||
|
logger.trace("Packet received - {}", packet.getData());
|
||||||
|
} catch (IOException exception) {
|
||||||
|
logger.debug("Exception during packet read - {}", exception.getMessage());
|
||||||
|
}
|
||||||
|
InetAddress sourceIp;
|
||||||
|
try {
|
||||||
|
sourceIp = InetAddress.getByName(ipAddress);
|
||||||
|
if (packet.getAddress().equals(sourceIp)) {
|
||||||
|
lastPacket = packet.getData();
|
||||||
|
readMessage(lastPacket);
|
||||||
|
} else {
|
||||||
|
logger.warn("Packet received from unknown source- {}", packet.getData());
|
||||||
|
}
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
logger.debug("Exception during address conversion - {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readMessage(byte[] message) {
|
||||||
|
EkeyPacketListener listener = this.packetListener;
|
||||||
|
|
||||||
|
if (listener != null && message.length != 0) {
|
||||||
|
listener.messageReceived(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEkeyPacketListener(EkeyPacketListener listener) {
|
||||||
|
if (this.packetListener == null) {
|
||||||
|
this.packetListener = listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConnected(boolean connected) {
|
||||||
|
this.connected = connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return this.connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeEkeyPacketListener(EkeyHandler ekeyHandler) {
|
||||||
|
if (this.packetListener != null) {
|
||||||
|
this.packetListener = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,364 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010-2021 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.ekey.internal.handler;
|
||||||
|
|
||||||
|
import static org.openhab.binding.ekey.internal.EkeyBindingConstants.*;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.ekey.internal.EkeyConfiguration;
|
||||||
|
import org.openhab.binding.ekey.internal.EkeyDynamicStateDescriptionProvider;
|
||||||
|
import org.openhab.binding.ekey.internal.api.EkeyPacketListener;
|
||||||
|
import org.openhab.binding.ekey.internal.api.EkeyUdpPacketReceiver;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
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.thing.binding.builder.ChannelBuilder;
|
||||||
|
import org.openhab.core.thing.binding.builder.ThingBuilder;
|
||||||
|
import org.openhab.core.thing.type.ChannelKind;
|
||||||
|
import org.openhab.core.thing.type.ChannelTypeUID;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.State;
|
||||||
|
import org.openhab.core.types.StateOption;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link EkeyHandler} is responsible for handling commands, which are
|
||||||
|
* sent to one of the channels.
|
||||||
|
*
|
||||||
|
* @author Hans-Jörg Merk - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class EkeyHandler extends BaseThingHandler implements EkeyPacketListener {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(EkeyHandler.class);
|
||||||
|
|
||||||
|
private final EkeyDynamicStateDescriptionProvider ekeyStateDescriptionProvider;
|
||||||
|
|
||||||
|
private EkeyConfiguration config = new EkeyConfiguration();
|
||||||
|
private @Nullable EkeyUdpPacketReceiver receiver;
|
||||||
|
|
||||||
|
public EkeyHandler(Thing thing, EkeyDynamicStateDescriptionProvider ekeyStateDescriptionProvider) {
|
||||||
|
super(thing);
|
||||||
|
this.ekeyStateDescriptionProvider = ekeyStateDescriptionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
// The binding does not handle any command
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
logger.debug("ekey handler initializing");
|
||||||
|
config = getConfigAs(EkeyConfiguration.class);
|
||||||
|
|
||||||
|
if (!config.ipAddress.isEmpty() && config.port != 0) {
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
|
||||||
|
scheduler.submit(() -> {
|
||||||
|
populateChannels(config.protocol);
|
||||||
|
String readerThreadName = "OH-binding-" + getThing().getUID().getAsString();
|
||||||
|
|
||||||
|
EkeyUdpPacketReceiver localReceiver = receiver = new EkeyUdpPacketReceiver(config.ipAddress,
|
||||||
|
config.port, readerThreadName);
|
||||||
|
localReceiver.addEkeyPacketListener(this);
|
||||||
|
try {
|
||||||
|
localReceiver.openConnection();
|
||||||
|
} catch (IOException e) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Cannot open connection)");
|
||||||
|
}
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No IP address specified)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
EkeyUdpPacketReceiver localReceiver = this.receiver;
|
||||||
|
|
||||||
|
if (localReceiver != null) {
|
||||||
|
localReceiver.closeConnection();
|
||||||
|
localReceiver.removeEkeyPacketListener(this);
|
||||||
|
}
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageReceived(byte[] message) {
|
||||||
|
logger.debug("messageReceived() : {}", message);
|
||||||
|
config = getConfigAs(EkeyConfiguration.class);
|
||||||
|
String delimiter = config.delimiter;
|
||||||
|
|
||||||
|
switch (config.protocol) {
|
||||||
|
case "RARE":
|
||||||
|
parseRare(message, delimiter);
|
||||||
|
break;
|
||||||
|
case "MULTI":
|
||||||
|
parseMulti(message, delimiter);
|
||||||
|
break;
|
||||||
|
case "HOME":
|
||||||
|
parseHome(message, delimiter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectionStatusChanged(ThingStatus status, byte @Nullable [] message) {
|
||||||
|
if (message != null) {
|
||||||
|
this.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, null);
|
||||||
|
}
|
||||||
|
this.updateStatus(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseRare(byte[] message, String delimiter) {
|
||||||
|
logger.debug("parse RARE packet");
|
||||||
|
if (message.length >= 72) {
|
||||||
|
byte[] newMessage = Arrays.copyOf(message, 72);
|
||||||
|
String messageString = new String(newMessage);
|
||||||
|
long action = getIntValueFrom(newMessage, 4, 4);
|
||||||
|
long terminalid = getIntValueFrom(newMessage, 8, 4);
|
||||||
|
String terminalSerial = getStringValueFrom(newMessage, 12, 14);
|
||||||
|
long relayid = getIntValueFrom(newMessage, 26, 1);
|
||||||
|
long userid = getIntValueFrom(newMessage, 28, 4);
|
||||||
|
long fingerid = getIntValueFrom(newMessage, 32, 4);
|
||||||
|
int serial = reconstructFsSerial(terminalid);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("messageString received() : {}", messageString);
|
||||||
|
logger.trace("AKTION : {}", action);
|
||||||
|
logger.trace("TERMINAL SERIAL : {}", terminalSerial);
|
||||||
|
logger.trace("RESERVED : {}", getStringValueFrom(newMessage, 27, 1));
|
||||||
|
logger.trace("RELAY ID : {}", relayid);
|
||||||
|
logger.trace("USER ID : {}", userid);
|
||||||
|
logger.trace("FINGER ID : {}", fingerid);
|
||||||
|
logger.trace("EVENT : {}", getStringValueFrom(newMessage, 36, 16));
|
||||||
|
logger.trace("FS SERIAL : {}", serial);
|
||||||
|
}
|
||||||
|
updateState(CHANNEL_TYPE_ACTION, new DecimalType(action));
|
||||||
|
if (!terminalSerial.isEmpty()) {
|
||||||
|
updateState(CHANNEL_TYPE_TERMID, DecimalType.valueOf(terminalSerial));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_TERMID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
updateState(CHANNEL_TYPE_RESERVED, StringType.valueOf(getStringValueFrom(newMessage, 27, 1)));
|
||||||
|
updateState(CHANNEL_TYPE_RELAYID, new DecimalType(relayid));
|
||||||
|
updateState(CHANNEL_TYPE_USERID, new DecimalType(userid));
|
||||||
|
updateState(CHANNEL_TYPE_FINGERID, new DecimalType(fingerid));
|
||||||
|
updateState(CHANNEL_TYPE_EVENT, StringType.valueOf(getStringValueFrom(newMessage, 36, 16)));
|
||||||
|
updateState(CHANNEL_TYPE_FSSERIAL, new DecimalType(serial));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseMulti(byte[] message, String delimiter) {
|
||||||
|
logger.debug("parse MULTI packet");
|
||||||
|
if (message.length >= 46) {
|
||||||
|
byte[] newMessage = Arrays.copyOf(message, 46);
|
||||||
|
String messageString = new String(newMessage);
|
||||||
|
String[] array = messageString.split(delimiter);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("messageString received() : {}", messageString);
|
||||||
|
logger.trace("USER ID : {}", array[1]);
|
||||||
|
logger.trace("USER ID : {}", array[1]);
|
||||||
|
logger.trace("USER NAME : {}", array[2]);
|
||||||
|
logger.trace("USER STATUS : {}", array[3]);
|
||||||
|
logger.trace("FINGER ID : {}", array[4]);
|
||||||
|
logger.trace("KEY ID : {}", array[5]);
|
||||||
|
logger.trace("SERIENNR FS : {}", array[6]);
|
||||||
|
logger.trace("NAME FS : {}", new String(array[7]).replace("-", ""));
|
||||||
|
logger.trace("AKTION : {}", array[8]);
|
||||||
|
logger.trace("INPUT ID : {}", array[9]);
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!"-".equals(array[1])) {
|
||||||
|
updateState(CHANNEL_TYPE_USERID, DecimalType.valueOf((array[1])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_USERID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
String userName = (array[2]).toString();
|
||||||
|
if (!userName.isEmpty()) {
|
||||||
|
userName = userName.replace("-", "");
|
||||||
|
userName = userName.replace(" ", "");
|
||||||
|
updateState(CHANNEL_TYPE_USERNAME, StringType.valueOf(userName));
|
||||||
|
}
|
||||||
|
if (!"-".equals(array[3])) {
|
||||||
|
updateState(CHANNEL_TYPE_USERSTATUS, DecimalType.valueOf((array[3])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_USERSTATUS, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
if (!"-".equals(array[4])) {
|
||||||
|
updateState(CHANNEL_TYPE_FINGERID, DecimalType.valueOf((array[4])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_FINGERID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
if (!"-".equals(array[5])) {
|
||||||
|
updateState(CHANNEL_TYPE_KEYID, DecimalType.valueOf((array[5])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_KEYID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
updateState(CHANNEL_TYPE_FSSERIAL, DecimalType.valueOf((array[6])));
|
||||||
|
updateState(CHANNEL_TYPE_FSNAME, new StringType(new String(array[7]).replace("-", "")));
|
||||||
|
updateState(CHANNEL_TYPE_ACTION, DecimalType.valueOf((array[8])));
|
||||||
|
if (!"-".equals(array[9])) {
|
||||||
|
updateState(CHANNEL_TYPE_INPUTID, DecimalType.valueOf((array[9])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_INPUTID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.trace("received packet is to short : {}", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void parseHome(byte[] message, String delimiter) {
|
||||||
|
logger.debug("parse HOME packet");
|
||||||
|
if (message.length >= 27) {
|
||||||
|
byte[] newMessage = Arrays.copyOf(message, 27);
|
||||||
|
String messageString = new String(newMessage);
|
||||||
|
String[] array = messageString.split(delimiter);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("messageString received() : {}", messageString);
|
||||||
|
logger.trace("USER ID : {}", array[1]);
|
||||||
|
logger.trace("FINGER ID : {}", array[2]);
|
||||||
|
logger.trace("SERIENNR FS : {}", array[3]);
|
||||||
|
logger.trace("AKTION : {}", array[4]);
|
||||||
|
logger.trace("RELAY ID : {}", array[5]);
|
||||||
|
}
|
||||||
|
if (!"-".equals(array[1])) {
|
||||||
|
updateState(CHANNEL_TYPE_USERID, DecimalType.valueOf((array[1])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_USERID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
if (!"-".equals(array[2])) {
|
||||||
|
updateState(CHANNEL_TYPE_FINGERID, DecimalType.valueOf((array[2])));
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_FINGERID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
updateState(CHANNEL_TYPE_FSSERIAL, DecimalType.valueOf((array[3])));
|
||||||
|
updateState(CHANNEL_TYPE_ACTION, DecimalType.valueOf((array[4])));
|
||||||
|
if (!"-".equals(array[5])) {
|
||||||
|
State relayId = DecimalType.valueOf((array[5]));
|
||||||
|
updateState(CHANNEL_TYPE_RELAYID, relayId);
|
||||||
|
} else {
|
||||||
|
updateState(CHANNEL_TYPE_RELAYID, DecimalType.valueOf("-1"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.trace("received packet is to short : {}", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChannel(String channelId, String itemType, @Nullable final Collection<String> options) {
|
||||||
|
if (thing.getChannel(channelId) == null) {
|
||||||
|
logger.debug("Channel '{}' for UID to be added", channelId);
|
||||||
|
ThingBuilder thingBuilder = editThing();
|
||||||
|
final ChannelTypeUID channelTypeUID = new ChannelTypeUID(BINDING_ID, channelId);
|
||||||
|
Channel channel = ChannelBuilder.create(new ChannelUID(getThing().getUID(), channelId), itemType)
|
||||||
|
.withType(channelTypeUID).withKind(ChannelKind.STATE).build();
|
||||||
|
thingBuilder.withChannel(channel);
|
||||||
|
updateThing(thingBuilder.build());
|
||||||
|
}
|
||||||
|
if (options != null) {
|
||||||
|
final List<StateOption> stateOptions = options.stream()
|
||||||
|
.map(e -> new StateOption(e, e.substring(0, 1) + e.substring(1).toLowerCase()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
logger.debug("StateOptions : '{}'", stateOptions);
|
||||||
|
ekeyStateDescriptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), channelId), stateOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void populateChannels(String protocol) {
|
||||||
|
String channelId = "";
|
||||||
|
String itemType = "Number";
|
||||||
|
|
||||||
|
switch (protocol) {
|
||||||
|
case "HOME":
|
||||||
|
channelId = CHANNEL_TYPE_RELAYID;
|
||||||
|
addChannel(channelId, itemType, null);
|
||||||
|
break;
|
||||||
|
case "MULTI":
|
||||||
|
channelId = CHANNEL_TYPE_USERNAME;
|
||||||
|
addChannel(channelId, "String", null);
|
||||||
|
channelId = CHANNEL_TYPE_USERSTATUS;
|
||||||
|
addChannel(channelId, itemType, null);
|
||||||
|
channelId = CHANNEL_TYPE_KEYID;
|
||||||
|
addChannel(channelId, itemType, null);
|
||||||
|
channelId = CHANNEL_TYPE_FSNAME;
|
||||||
|
addChannel(channelId, "String", null);
|
||||||
|
channelId = CHANNEL_TYPE_INPUTID;
|
||||||
|
addChannel(channelId, itemType, null);
|
||||||
|
break;
|
||||||
|
case "RARE":
|
||||||
|
channelId = CHANNEL_TYPE_TERMID;
|
||||||
|
addChannel(channelId, itemType, null);
|
||||||
|
channelId = CHANNEL_TYPE_RELAYID;
|
||||||
|
addChannel(channelId, itemType, null);
|
||||||
|
channelId = CHANNEL_TYPE_RESERVED;
|
||||||
|
addChannel(channelId, "String", null);
|
||||||
|
channelId = CHANNEL_TYPE_EVENT;
|
||||||
|
addChannel(channelId, "String", null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getIntValueFrom(byte[] bytes, int start, int length) {
|
||||||
|
if (start + length > bytes.length) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
long value = 0;
|
||||||
|
int bits = 0;
|
||||||
|
for (int i = start; i < start + length; i++) {
|
||||||
|
value |= (bytes[i] & 0xFF) << bits;
|
||||||
|
bits += 8;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStringValueFrom(byte[] bytes, int start, int length) {
|
||||||
|
if (start + length > bytes.length) {
|
||||||
|
logger.debug("Could not get String from bytes");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuffer value = new StringBuffer();
|
||||||
|
for (int i = start + length - 1; i >= start; i--) {
|
||||||
|
if (bytes[i] > (byte) ' ' && bytes[i] < (byte) '~') {
|
||||||
|
value.append((char) bytes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int reconstructFsSerial(long termID) {
|
||||||
|
long s = termID;
|
||||||
|
s ^= 0x70000000;
|
||||||
|
int ssss = (int) (s & 0xFFFF);
|
||||||
|
s >>= 16;
|
||||||
|
int yy = (int) s % 53;
|
||||||
|
int ww = (int) s / 53;
|
||||||
|
yy *= 1000000;
|
||||||
|
ww *= 10000;
|
||||||
|
return ww + yy + ssss;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<binding:binding id="ekey" 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>Ekey Binding</name>
|
||||||
|
<description>This is the binding for connecting openHAB to Ekey fingerprint scanners.</description>
|
||||||
|
|
||||||
|
</binding:binding>
|
@ -0,0 +1,46 @@
|
|||||||
|
# binding
|
||||||
|
binding.ekey.name = Ekey Binding
|
||||||
|
binding.ekey.description = This Binding integrates Ekey CV-LAN UDP adapters
|
||||||
|
|
||||||
|
# thing types
|
||||||
|
thing-type.ekey.label = CV-LAN
|
||||||
|
thing-type.ekey.description = CV-LAN UDP adapter
|
||||||
|
|
||||||
|
# thing type config description
|
||||||
|
thing-type.config.ekey.ipAddress.label = IP Address
|
||||||
|
thing-type.config.ekey.ipAddress.description = IPv4 address of the eKey udp converter. A static IP address is recommended.
|
||||||
|
thing-type.config.ekey.port.label = Port
|
||||||
|
thing-type.config.ekey.port.description = The port as configured during the UDP Converter configuration. e.g. 56000
|
||||||
|
thing-type.config.ekey.protocol.label = Protocol
|
||||||
|
thing-type.config.ekey.protocol.description = Can be RARE, MULTI or HOME depending on what the system supports
|
||||||
|
thing-type.config.ekey.delimiter.label = Delimiter
|
||||||
|
thing-type.config.ekey.delimiter.description = The delimiter is also defined on the ekey UDP converter - use the ekey configuration software to determine which delimiter is used or to change it. Another option is _ (underscore)
|
||||||
|
|
||||||
|
# channel types
|
||||||
|
channel-type.ekey.userId.label = User ID
|
||||||
|
channel-type.ekey.userId.description = This indicates which user has been detected on the terminal. The value is the numerical order of the user as it was specified on the controller.
|
||||||
|
channel-type.ekey.userName.label = Username
|
||||||
|
channel-type.ekey.userName.description = Returns the ten-character-long name of the person that has been recognized on the terminal
|
||||||
|
channel-type.ekey.userStatus.label = User status
|
||||||
|
channel-type.ekey.userStatus.description = Indicates the status of the user (-1=undefined, 1=enabled, 0= disabled)
|
||||||
|
channel-type.ekey.fingerId.label = Finger ID
|
||||||
|
channel-type.ekey.fingerId.description = Indicates which finger has been detected on the terminal. (0-9,-1)
|
||||||
|
channel-type.ekey.keyId.label = Key ID
|
||||||
|
channel-type.ekey.keyId.description = Indicates which of the four keys was used. See ekey documentation on "keys".
|
||||||
|
channel-type.ekey.fsSerial.label = Serialnumber
|
||||||
|
channel-type.ekey.fsSerial.description = This returns the 4-character-long name that was specified on the controller for the specific terminals
|
||||||
|
channel-type.ekey.fsName.label = Terminal Name
|
||||||
|
channel-type.ekey.fsName.description = This returns the terminal name
|
||||||
|
channel-type.ekey.action.label = Action
|
||||||
|
channel-type.ekey.action.description = Indicates whether access was granted (value=0) or denied (value=-1). According to the ekey documentation there are six more values possible
|
||||||
|
channel-type.ekey.inputId.label = Input ID
|
||||||
|
channel-type.ekey.inputId.description = Indicates which of the four digital inputs was triggered. Value is number of Input. "-1" indicates that no input was triggered.
|
||||||
|
channel-type.ekey.relayId.label = Relay ID
|
||||||
|
channel-type.ekey.relayId.description = Indicates which relay has been switched.
|
||||||
|
channel-type.ekey.termId.label = Terminal ID
|
||||||
|
channel-type.ekey.termId.description = This provides the serial number of the packet source. The source can be a fingerprint terminal or the controller (in case of digital inputs). The Serial number has a length of 13.
|
||||||
|
channel-type.ekey.reserved.label = Reserved
|
||||||
|
channel-type.ekey.reserved.description = Reserved
|
||||||
|
channel-type.ekey.event.label = Event
|
||||||
|
channel-type.ekey.event.description = Event
|
||||||
|
|
@ -0,0 +1,46 @@
|
|||||||
|
# binding
|
||||||
|
binding.ekey.name = Ekey Binding
|
||||||
|
binding.ekey.description = Dieses Binding integriert die ekey CV-LAN converter UDP.
|
||||||
|
|
||||||
|
# thing types
|
||||||
|
thing-type.ekey.label = CV-LAN
|
||||||
|
thing-type.ekey.description = eKey CV-LAN converter UDP
|
||||||
|
|
||||||
|
# thing type config description
|
||||||
|
thing-type.config.ekey.ipAddress.label = IP-Adresse
|
||||||
|
thing-type.config.ekey.ipAddress.description = IPv4 Adresse des eKey converter UDP. Eine statische IPv4 Adresse wird empfohlen.
|
||||||
|
thing-type.config.ekey.port.label = Empfänger Port
|
||||||
|
thing-type.config.ekey.port.description = Der während der Konfiguration des ekey converter UDP festgelegte Empfänger Port, z.B. 56000
|
||||||
|
thing-type.config.ekey.protocol.label = Protokoll
|
||||||
|
thing-type.config.ekey.protocol.description = Das vom ekey converter UDP verwendete Protokoll (RARE, MULTI oder HOME, abhängig vom verwendeten System).
|
||||||
|
thing-type.config.ekey.delimiter.label = Abstandshalter
|
||||||
|
thing-type.config.ekey.delimiter.description = Der im ekey converter UDP Protokoll verwendete Feldtrenner.
|
||||||
|
|
||||||
|
# channel types
|
||||||
|
channel-type.ekey.userId.label = Benutzer ID
|
||||||
|
channel-type.ekey.userId.description = Zeigt an, welcher Benutzer vom Terminal erkannt wurde. Es handelt sich um den im Konverter festgelegten numerischen Wert (0-99).
|
||||||
|
channel-type.ekey.userName.label = Benutzername
|
||||||
|
channel-type.ekey.userName.description = Zeigt den 10-stelligen Benutzernamen des vom Terminal erkannten Benutzers.
|
||||||
|
channel-type.ekey.userStatus.label = Benutzerstatus
|
||||||
|
channel-type.ekey.userStatus.description = Zeigt den Status der vom Terminal erkannten Benutzers an (-1=nicht definiert, 1=nicht gesperrt, 0=gesperrt)
|
||||||
|
channel-type.ekey.fingerId.label = Finger ID
|
||||||
|
channel-type.ekey.fingerId.description = Zeigt den vom Terminal erkannten Finger an. (0-9,-)
|
||||||
|
channel-type.ekey.keyId.label = Schlüssel ID
|
||||||
|
channel-type.ekey.keyId.description = Zegt an, welcher der 4 Schlüssel verwendet wurde. Siehe ekey Dokumentation "Schlüssel".
|
||||||
|
channel-type.ekey.fsSerial.label = Seriennummer
|
||||||
|
channel-type.ekey.fsSerial.description = Zeiget die Seriennummer des Terminals.
|
||||||
|
channel-type.ekey.fsName.label = Terminalname
|
||||||
|
channel-type.ekey.fsName.description = Zeiget den im Kontrolle hinterlegten 4-stelligen Namen des Terminal.
|
||||||
|
channel-type.ekey.action.label = Aktion
|
||||||
|
channel-type.ekey.action.description = Zeigt an, ob die letzte Aktion erfolgreich war (Wert=0) oder abgewiesen wurde (Wert=-1). Nach der ekey Dokumentation sind weitere 6 Werte möglich.
|
||||||
|
channel-type.ekey.inputId.label = Eingangs ID
|
||||||
|
channel-type.ekey.inputId.description = Zeigt an, welcher der 4 digitalen Eingänge ausgelöst wurde. Der Wert entspricht dem Eingang "-1" bedeutet kein Eingang.
|
||||||
|
channel-type.ekey.relayId.label = Relais ID
|
||||||
|
channel-type.ekey.relayId.description = Zeigt an, welches der Relais geschaltet wurde. Der Wert entspricht dem Relais "-1" bedeutet kein Relais
|
||||||
|
channel-type.ekey.termId.label = Terminal ID
|
||||||
|
channel-type.ekey.termId.description = Zeigt die Seriennummer des Senders am. Sender kann ein Terminal oder Kontroller sein (Bei digitalen Eingängen). Die Seriennummer ist 13-stellig.
|
||||||
|
channel-type.ekey.reserved.label = Reserviert
|
||||||
|
channel-type.ekey.reserved.description = Reserviert
|
||||||
|
channel-type.ekey.event.label = Ereignis
|
||||||
|
channel-type.ekey.event.description = Ereignis - Beschreibung nicht verfügbar.
|
||||||
|
|
@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<thing:thing-descriptions bindingId="ekey"
|
||||||
|
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="userName">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>@text/channel-type.ekey.userName.label</label>
|
||||||
|
<description>@text/channel-type.ekey.userName.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="userStatus">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.userStatus.label</label>
|
||||||
|
<description>@text/channel-type.ekey.userStatus.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="keyId">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.keyId.label</label>
|
||||||
|
<description>@text/channel-type.ekey.keyId.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="fsName">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>@text/channel-type.ekey.fsName.label</label>
|
||||||
|
<description>@text/channel-type.ekey.fsName.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="inputId">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.inputId.label</label>
|
||||||
|
<description>@text/channel-type.ekey.inputId.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="relayId">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.relayId.label</label>
|
||||||
|
<description>@text/channel-type.ekey.relayId.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="termId">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.termId.label</label>
|
||||||
|
<description>@text/channel-type.ekey.termId.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="reserved">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>@text/channel-type.ekey.reserved.label</label>
|
||||||
|
<description>@text/channel-type.ekey.reserved.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="event">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>@text/channel-type.ekey.event.label</label>
|
||||||
|
<description>@text/channel-type.ekey.event.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
|
||||||
|
</thing:thing-descriptions>
|
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<thing:thing-descriptions bindingId="ekey"
|
||||||
|
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="cvlan">
|
||||||
|
<label>@text/thing-type.ekey.label</label>
|
||||||
|
<description>@text/thing-type.ekey.description</description>
|
||||||
|
|
||||||
|
<channels>
|
||||||
|
<channel id="userId" typeId="userId"/>
|
||||||
|
<channel id="fingerId" typeId="fingerId"/>
|
||||||
|
<channel id="fsSerial" typeId="fsSerial"/>
|
||||||
|
<channel id="action" typeId="action"/>
|
||||||
|
</channels>
|
||||||
|
|
||||||
|
<config-description>
|
||||||
|
<parameter name="ipAddress" type="text" required="true">
|
||||||
|
<context>network-address</context>
|
||||||
|
<label>@text/thing-type.config.ekey.ipAddress.label</label>
|
||||||
|
<description>@text/thing-type.config.ekey.ipAddress.description</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="port" type="integer" min="1" max="65535" required="false">
|
||||||
|
<label>@text/thing-type.config.ekey.port.label</label>
|
||||||
|
<description>@text/thing-type.config.ekey.port.description</description>
|
||||||
|
<default>56000</default>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="protocol" type="text" required="false">
|
||||||
|
<label>@text/thing-type.config.ekey.protocol.label</label>
|
||||||
|
<description>@text/thing-type.config.ekey.protocol.description</description>
|
||||||
|
<default>RARE</default>
|
||||||
|
<options>
|
||||||
|
<option value="RARE">RARE</option>
|
||||||
|
<option value="MULTI">MULTI</option>
|
||||||
|
<option value="HOME">HOME</option>
|
||||||
|
</options>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="delimiter" type="text" required="false">
|
||||||
|
<label>@text/thing-type.config.ekey.delimiter.label</label>
|
||||||
|
<description>@text/thing-type.config.ekey.delimiter.description</description>
|
||||||
|
<default>_</default>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
</thing-type>
|
||||||
|
|
||||||
|
<channel-type id="userId">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.userId.label</label>
|
||||||
|
<description>@text/channel-type.ekey.userId.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="fingerId">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.fingerId.label</label>
|
||||||
|
<description>@text/channel-type.ekey.fingerId.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="fsSerial">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.fsSerial.label</label>
|
||||||
|
<description>@text/channel-type.ekey.fsSerial.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="action">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>@text/channel-type.ekey.action.label</label>
|
||||||
|
<description>@text/channel-type.ekey.action.description</description>
|
||||||
|
<state readOnly="true"></state>
|
||||||
|
</channel-type>
|
||||||
|
</thing:thing-descriptions>
|
@ -106,6 +106,7 @@
|
|||||||
<module>org.openhab.binding.dwdunwetter</module>
|
<module>org.openhab.binding.dwdunwetter</module>
|
||||||
<module>org.openhab.binding.ecobee</module>
|
<module>org.openhab.binding.ecobee</module>
|
||||||
<module>org.openhab.binding.ecotouch</module>
|
<module>org.openhab.binding.ecotouch</module>
|
||||||
|
<module>org.openhab.binding.ekey</module>
|
||||||
<module>org.openhab.binding.elerotransmitterstick</module>
|
<module>org.openhab.binding.elerotransmitterstick</module>
|
||||||
<module>org.openhab.binding.energenie</module>
|
<module>org.openhab.binding.energenie</module>
|
||||||
<module>org.openhab.binding.enigma2</module>
|
<module>org.openhab.binding.enigma2</module>
|
||||||
|
Loading…
Reference in New Issue
Block a user