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,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

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

View File

@@ -0,0 +1,125 @@
# Jablotron Alarm Binding
This is the binding for Jablotron alarms.
https://www.jablotron.com/en/jablotron-products/alarms/
## Supported Things
| thing | note |
|---------|-------------------------------------------|
| bridge | the bridge to your Jablonet cloud account |
| JA-80 | the OASIS alarm |
| JA-100 | with the thermometer support |
| JA-100F | without the thermometer support |
## Discovery
This binding supports auto discovery. Just manually add a bridge thing and supply login & password to your Jablonet account.
## Binding Configuration
Binding itself doesn't require specific configuration.
## Thing Configuration
| thing | config parameter name | description | type |
|----------------------|-----------------------|------------------------------------------------------------------------------------|-----------------------|
| bridge | login | the login to your Jablonet account | mandatory |
| bridge | password | the password to your Jablonet account | mandatory |
| bridge | refresh | the refresh time for all alarm warnings (ALARM, TAMPER triggers and SERVICE state) | optional, default=30s |
| bridge | lang | the language of the alarm texts | optional, default=en |
| JA-80/JA-100/JA-100F | refresh | the channels refresh period in seconds | optional, default=60s |
| JA-80/JA-100/JA-100F | serviceId | the service ID which identifies the alarm | mandatory |
| JA-100/JA-100F | code | the master code for controlling sections | optional |
## Channels
| thing | channel name | item type | description |
|----------------------|------------------|--------------------|-----------------------------------------------------------|
| bridge | N/A | N/A | the bridge does not expose any channels |
| JA-80 | statusA | Switch | the status of the A section |
| JA-80 | statusB | Switch | the status of the AB/B section |
| JA-80 | statusABC | Switch | the status of the ABC section |
| JA-80 | statusPGX | Switch | the status of PGX |
| JA-80 | statusPGY | Switch | the status of PGY |
| JA-80 | command | String | the channel for sending keyboard codes to the OASIS alarm |
| JA-80/JA-100/JA-100F | lastEvent | String | the description of the last event |
| JA-80/JA-100/JA-100F | lastEventClass | String | the class of the last event - e.g. arm, disarm, ... |
| JA-80/JA-100/JA-100F | lastEventInvoker | String | the invoker of the last event |
| JA-80/JA-100/JA-100F | lastEventTime | DateTime | the time of the last event |
| JA-80/JA-100/JA-100F | lastCheckTime | DateTime | the time of the last checking |
| JA-80/JA-100/JA-100F | alarm | N/A | the alarm trigger, might fire ALARM or TAMPER events |
| JA-100/JA-100F | lastEventSection | String | the section of the last event |
| JA-100 | state_%nr% | String | the section %nr% status/control |
| JA-100 | pgm_%nr% | Switch | the PG switch %nr% status/control |
| JA-100 | thermometer_%nr% | Number:Temperature | the thermometer %nr% value |
| JA-100 | thermostat_%nr% | Number:Temperature | the thermostat %nr% value |
| JA-100F | sec-%nr% | String | the section %nr% status/control |
| JA-100F | pg-%nr% | Switch | the PG switch %nr% status/control |
The state, pgm, thermometer, thermostat, sec and pg channels for the JA-100/JA-100F alarms are dynamically created according to your configuration.
* The sections are represented by String channels (with possible values "set", "unset", "partialSet" for JA-100 and
possible values "ARM", "PARTIAL_ARM" and "DISARM" for JA100-F)
## Full Example
# items file for JA80
```
String HouseAlarm "Alarm [%s]" <alarm>
String JablotronCode { channel="jablotron:oasis:8c93a5ed:50139:command", autoupdate="false" }
Switch ArmSectionA "Garage arming" <jablotron> (Alarm) { channel="jablotron:oasis:8c93a5ed:50139:statusA" }
Switch ArmSectionAB "1st floor arming" <jablotron> (Alarm) { channel="jablotron:oasis:8c93a5ed:50139:statusB" }
Switch ArmSectionABC "2nd floor arming" <jablotron> (Alarm) { channel="jablotron:oasis:8c93a5ed:50139:statusABC" }
String LastEvent "Last event code [%s]" <jablotron> { channel="jablotron:oasis:8c93a5ed:50139:lastEvent" }
String LastEventClass "Last event class [%s]" <jablotron> { channel="jablotron:oasis:8c93a5ed:50139:lastEventClass" }
String LastEventInvoker "Last event class [%s]" <jablotron> { channel="jablotron:oasis:8c93a5ed:50139:lastEventInvoker" }
DateTime LastEventTime "Last event [%1$td.%1$tm.%1$tY %1$tR]" <clock> { channel="jablotron:oasis:8c93a5ed:50139:lastEventTime" }
DateTime LastCheckTime "Last check [%1$td.%1$tm.%1$tY %1$tR]" <clock> { channel="jablotron:oasis:8c93a5ed:50139:lastCheckTime" }
Switch ArmControlPGX "PGX" <jablotron> (Alarm) { channel="jablotron:oasis:8c93a5ed:50139:statusPGX" }
Switch ArmControlPGY "PGY" <jablotron> (Alarm) { channel="jablotron:oasis:8c93a5ed:50139:statusPGY" }
```
# sitemap example for JA80
```
Text item=HouseAlarm icon="alarm" {
Switch item=ArmSectionA
Switch item=ArmSectionAB
Switch item=ArmSectionABC
Text item=LastEvent
Text item=LastEventInvoker
Text item=LastEventClass
Text item=LastEventTime
Text item=LastCheckTime
Switch item=ArmControlPGX
Switch item=ArmControlPGY
Switch item=JablotronCode label="Arm" mappings=[1234=" A ", 2345=" B ", 3456="ABC"]
Switch item=JablotronCode label="Disarm" mappings=[9876="Disarm"]
}
```
# rule example for JA80
```
rule "Alarm"
when
Item ArmSectionA changed or Item ArmSectionAB changed or Item ArmSectionABC changed or
System started
then
if( ArmSectionA.state == ON || ArmSectionAB.state == ON || ArmSectionABC.state == ON)
{ postUpdate(HouseAlarm, "partial") }
if( ArmSectionA.state == OFF && ArmSectionAB.state == OFF && ArmSectionABC.state == OFF)
{ postUpdate(HouseAlarm, "disarmed") }
if( ArmSectionA.state == ON && ArmSectionAB.state == ON && ArmSectionABC.state == ON)
{ postUpdate(HouseAlarm, "armed") }
end
rule "Jablotron alarm trigger"
when
Channel "jablotron:oasis:8c93a5ed:50139:alarm" triggered
then
logInfo("default.rules", "Jablotron triggered " + receivedEvent.getEvent())
end
```

View File

@@ -0,0 +1,18 @@
<?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/maven-v4_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.jablotron</artifactId>
<name>openHAB Add-ons :: Bundles :: Jablotron Binding</name>
</project>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.jablotron-${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-jablotron" description="Jablotron Alarm Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-http</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.jablotron/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,72 @@
/**
* 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.jablotron;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link JablotronBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronBindingConstants {
private static final String BINDING_ID = "jablotron";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge");
public static final ThingTypeUID THING_TYPE_OASIS = new ThingTypeUID(BINDING_ID, "oasis");
public static final ThingTypeUID THING_TYPE_JA100 = new ThingTypeUID(BINDING_ID, "ja100");
public static final ThingTypeUID THING_TYPE_JA100F = new ThingTypeUID(BINDING_ID, "ja100f");
// Common alarm channels
public static final String CHANNEL_ALARM = "alarm";
public static final String CHANNEL_LAST_CHECK_TIME = "lastCheckTime";
public static final String CHANNEL_LAST_EVENT = "lastEvent";
public static final String CHANNEL_LAST_EVENT_CLASS = "lastEventClass";
public static final String CHANNEL_LAST_EVENT_TIME = "lastEventTime";
public static final String CHANNEL_LAST_EVENT_INVOKER = "lastEventInvoker";
public static final String CHANNEL_LAST_EVENT_SECTION = "lastEventSection";
// List of all OASIS Channel ids
public static final String CHANNEL_COMMAND = "command";
public static final String CHANNEL_STATUS_A = "statusA";
public static final String CHANNEL_STATUS_B = "statusB";
public static final String CHANNEL_STATUS_ABC = "statusABC";
public static final String CHANNEL_STATUS_PGX = "statusPGX";
public static final String CHANNEL_STATUS_PGY = "statusPGY";
// Constants
public static final String JABLOTRON_API_URL = "https://api.jablonet.net/api/1.6/";
public static final String AGENT = "Swagger-Codegen/1.0.0/android";
public static final int TIMEOUT_SEC = 10;
public static final String SYSTEM = "openHAB";
public static final String VENDOR = "JABLOTRON:Jablotron";
public static final String APPLICATION_JSON = "application/json";
public static final String WWW_FORM_URLENCODED = "application/x-www-form-urlencoded; charset=UTF-8";
public static final String AUTHENTICATION_CHALLENGE = "Authentication challenge without WWW-Authenticate header";
public static final String PROPERTY_SERVICE_ID = "serviceId";
public static final int DISCOVERY_TIMEOUT_SEC = 10;
public static final int CACHE_TIMEOUT_MS = 10000;
// supported thing types for discovery
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = new HashSet<>(
Arrays.asList(THING_TYPE_OASIS, THING_TYPE_JA100, THING_TYPE_JA100F));
}

View File

@@ -0,0 +1,71 @@
/**
* 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.jablotron.internal;
import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.jablotron.internal.handler.JablotronBridgeHandler;
import org.openhab.binding.jablotron.internal.handler.JablotronJa100FHandler;
import org.openhab.binding.jablotron.internal.handler.JablotronJa100Handler;
import org.openhab.binding.jablotron.internal.handler.JablotronOasisHandler;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
* The {@link JablotronHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.jablotron", service = ThingHandlerFactory.class)
public class JablotronHandlerFactory extends BaseThingHandlerFactory {
private final HttpClientFactory httpClientFactory;
@Activate
public JablotronHandlerFactory(@Reference HttpClientFactory httpClientFactory) {
this.httpClientFactory = httpClientFactory;
}
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return THING_TYPE_BRIDGE.equals(thingTypeUID) || SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_BRIDGE)) {
return new JablotronBridgeHandler((Bridge) thing, httpClientFactory.getCommonHttpClient());
} else if (thingTypeUID.equals(THING_TYPE_OASIS)) {
return new JablotronOasisHandler(thing, "OASIS");
} else if (thingTypeUID.equals(THING_TYPE_JA100)) {
return new JablotronJa100Handler(thing, "JA100");
} else if (thingTypeUID.equals(THING_TYPE_JA100F)) {
return new JablotronJa100FHandler(thing, "JA100F");
}
return null;
}
}

View File

@@ -0,0 +1,45 @@
/**
* 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.jablotron.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronBridgeConfig} class defines the bridge configuration
* object.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronBridgeConfig {
private String login = "";
private String password = "";
private int refresh = 30;
private String lang = "en";
public String getLogin() {
return login;
}
public String getPassword() {
return password;
}
public String getLang() {
return lang;
}
public int getRefresh() {
return refresh;
}
}

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.jablotron.internal.config;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronDeviceConfig} class defines the thing configuration
* object.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronDeviceConfig {
private int refresh = 60;
private String code = "";
private String serviceId = "";
public int getRefresh() {
return refresh;
}
public String getCode() {
return code;
}
public String getServiceId() {
return serviceId;
}
}

View File

@@ -0,0 +1,187 @@
/**
* 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.jablotron.internal.discovery;
import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.jablotron.internal.handler.JablotronBridgeHandler;
import org.openhab.binding.jablotron.internal.model.JablotronDiscoveredService;
import org.openhab.core.config.discovery.*;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link JablotronDiscoveryService} is responsible for the thing discovery
* process.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronDiscoveryService extends AbstractDiscoveryService
implements DiscoveryService, ThingHandlerService {
private final Logger logger = LoggerFactory.getLogger(JablotronDiscoveryService.class);
private @Nullable JablotronBridgeHandler bridgeHandler;
private @Nullable ScheduledFuture<?> discoveryJob = null;
public JablotronDiscoveryService() {
super(DISCOVERY_TIMEOUT_SEC);
logger.debug("Creating discovery service");
}
private void startDiscovery() {
JablotronBridgeHandler localBridgeHandler = bridgeHandler;
if (localBridgeHandler != null && ThingStatus.ONLINE == localBridgeHandler.getThing().getStatus()) {
discoverServices();
}
}
@Override
public void setThingHandler(@Nullable ThingHandler thingHandler) {
if (thingHandler instanceof JablotronBridgeHandler) {
bridgeHandler = (JablotronBridgeHandler) thingHandler;
}
}
@Override
public @Nullable ThingHandler getThingHandler() {
return bridgeHandler;
}
@Override
protected void stopBackgroundDiscovery() {
super.stopBackgroundDiscovery();
ScheduledFuture<?> localDiscoveryJob = discoveryJob;
if (localDiscoveryJob != null) {
localDiscoveryJob.cancel(true);
}
}
@Override
protected void startBackgroundDiscovery() {
logger.debug("Starting Jablotron background discovery");
ScheduledFuture<?> localDiscoveryJob = discoveryJob;
if (localDiscoveryJob == null || localDiscoveryJob.isCancelled()) {
discoveryJob = scheduler.scheduleWithFixedDelay(this::startDiscovery, 10, 3600, TimeUnit.SECONDS);
}
}
@Override
public void activate() {
super.activate(null);
}
@Override
public void deactivate() {
super.deactivate();
}
@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
return SUPPORTED_THING_TYPES_UIDS;
}
@Override
protected void startScan() {
logger.debug("Starting scanning for items...");
startDiscovery();
}
public void oasisDiscovered(String label, String serviceId) {
JablotronBridgeHandler localBridgeHandler = bridgeHandler;
if (localBridgeHandler != null) {
ThingUID thingUID = new ThingUID(THING_TYPE_OASIS, localBridgeHandler.getThing().getUID(), serviceId);
Map<String, Object> properties = new HashMap<>();
properties.put(PROPERTY_SERVICE_ID, serviceId);
logger.debug("Detected an OASIS alarm with service id: {}", serviceId);
thingDiscovered(DiscoveryResultBuilder.create(thingUID).withThingType(THING_TYPE_OASIS).withLabel(label)
.withProperties(properties).withRepresentationProperty(PROPERTY_SERVICE_ID)
.withBridge(localBridgeHandler.getThing().getUID()).build());
}
}
public void ja100Discovered(String label, String serviceId) {
JablotronBridgeHandler localBridgeHandler = bridgeHandler;
if (localBridgeHandler != null) {
ThingUID thingUID = new ThingUID(THING_TYPE_JA100, localBridgeHandler.getThing().getUID(), serviceId);
Map<String, Object> properties = new HashMap<>();
properties.put(PROPERTY_SERVICE_ID, serviceId);
logger.debug("Detected a JA100 alarm with service id: {}", serviceId);
thingDiscovered(DiscoveryResultBuilder.create(thingUID).withThingType(THING_TYPE_JA100).withLabel(label)
.withProperties(properties).withRepresentationProperty(PROPERTY_SERVICE_ID)
.withBridge(localBridgeHandler.getThing().getUID()).build());
}
}
public void ja100fDiscovered(String label, String serviceId) {
JablotronBridgeHandler localBridgeHandler = bridgeHandler;
if (localBridgeHandler != null) {
ThingUID thingUID = new ThingUID(THING_TYPE_JA100F, localBridgeHandler.getThing().getUID(), serviceId);
Map<String, Object> properties = new HashMap<>();
properties.put(PROPERTY_SERVICE_ID, serviceId);
logger.debug("Detected a JA100+ alarm with service id: {}", serviceId);
thingDiscovered(DiscoveryResultBuilder.create(thingUID).withThingType(THING_TYPE_JA100F).withLabel(label)
.withProperties(properties).withRepresentationProperty(PROPERTY_SERVICE_ID)
.withBridge(localBridgeHandler.getThing().getUID()).build());
}
}
private synchronized void discoverServices() {
JablotronBridgeHandler localBridgeHandler = bridgeHandler;
if (localBridgeHandler != null) {
List<JablotronDiscoveredService> services = localBridgeHandler.discoverServices();
if (services == null || services.isEmpty()) {
logger.debug("Cannot find any Jablotron device");
return;
}
for (JablotronDiscoveredService service : services) {
String serviceId = String.valueOf(service.getId());
logger.debug("Found Jablotron service: {} id: {}", service.getName(), serviceId);
String serviceType = service.getServiceType().toLowerCase();
if (serviceType.equals(THING_TYPE_OASIS.getId())) {
oasisDiscovered("Jablotron OASIS Alarm : " + service.getName(), serviceId);
} else if (serviceType.equals(THING_TYPE_JA100.getId())) {
ja100Discovered("Jablotron JA100 Alarm : " + service.getName(), serviceId);
} else if (serviceType.equals(THING_TYPE_JA100F.getId())) {
ja100fDiscovered("Jablotron JA100+ Alarm : " + service.getName(), serviceId);
} else {
logger.info("Unsupported device type discovered: {} with serviceId: {} and type: {}",
service.getName(), serviceId, service.getServiceType());
logger.info("Please create a new issue and attach the above information");
}
}
}
}
}

View File

@@ -0,0 +1,265 @@
/**
* 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.jablotron.internal.handler;
import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
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.jablotron.internal.config.JablotronDeviceConfig;
import org.openhab.binding.jablotron.internal.model.*;
import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.*;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**
* The {@link JablotronAlarmHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public abstract class JablotronAlarmHandler extends BaseThingHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
protected final Gson gson = new Gson();
protected JablotronDeviceConfig thingConfig = new JablotronDeviceConfig();
private String lastWarningTime = "";
protected String alarmName = "";
private boolean inService = false;
protected @Nullable ScheduledFuture<?> future = null;
protected @Nullable ExpiringCache<JablotronDataUpdateResponse> dataCache;
protected ExpiringCache<List<JablotronHistoryDataEvent>> eventCache;
public JablotronAlarmHandler(Thing thing, String alarmName) {
super(thing);
this.alarmName = alarmName;
eventCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetEventHistory);
}
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
super.bridgeStatusChanged(bridgeStatusInfo);
if (ThingStatus.UNINITIALIZED == bridgeStatusInfo.getStatus()) {
cleanup();
}
}
@Override
public void dispose() {
super.dispose();
cleanup();
}
@Override
public void initialize() {
thingConfig = getConfigAs(JablotronDeviceConfig.class);
future = scheduler.scheduleWithFixedDelay(this::updateAlarmStatus, 1, thingConfig.getRefresh(),
TimeUnit.SECONDS);
updateStatus(ThingStatus.ONLINE);
}
public boolean isInService() {
return inService;
}
public String getAlarmName() {
return alarmName;
}
protected abstract void updateSegmentStatus(JablotronServiceDetailSegment segment);
protected void updateSegmentStatus(String segmentName, @Nullable JablotronDataUpdateResponse dataUpdate) {
if (dataUpdate == null || !dataUpdate.isStatus()) {
return;
}
List<JablotronServiceData> serviceData = dataUpdate.getData().getServiceData();
for (JablotronServiceData data : serviceData) {
if (!thingConfig.getServiceId().equals(data.getServiceId())) {
continue;
}
List<JablotronService> services = data.getData();
for (JablotronService service : services) {
JablotronServiceDetail detail = service.getData();
for (JablotronServiceDetailSegment segment : detail.getSegments()) {
if (segmentName.toUpperCase().equals(segment.getSegmentId())) {
updateSegmentStatus(segment);
}
}
}
}
}
private void cleanup() {
logger.debug("doing cleanup...");
ScheduledFuture<?> localFuture = future;
if (localFuture != null) {
localFuture.cancel(true);
}
}
protected State getCheckTime() {
ZonedDateTime zdt = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
return new DateTimeType(zdt);
}
protected synchronized @Nullable JablotronDataUpdateResponse sendGetStatusRequest() {
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
return handler.sendGetStatusRequest(getThing());
}
return null;
}
protected synchronized boolean updateAlarmStatus() {
JablotronDataUpdateResponse dataUpdate = sendGetStatusRequest();
if (dataUpdate == null) {
return false;
}
if (dataUpdate.isStatus()) {
updateState(CHANNEL_LAST_CHECK_TIME, getCheckTime());
List<JablotronServiceData> serviceData = dataUpdate.getData().getServiceData();
for (JablotronServiceData data : serviceData) {
if (!thingConfig.getServiceId().equals(data.getServiceId())) {
continue;
}
List<JablotronService> services = data.getData();
for (JablotronService service : services) {
JablotronServiceDetail detail = service.getData();
for (JablotronServiceDetailSegment segment : detail.getSegments()) {
updateSegmentStatus(segment);
}
}
}
} else {
logger.debug("Error during alarm status update: {}", dataUpdate.getErrorMessage());
}
List<JablotronHistoryDataEvent> events = sendGetEventHistory();
if (events != null && events.size() > 0) {
JablotronHistoryDataEvent event = events.get(0);
updateLastEvent(event);
}
return true;
}
protected @Nullable List<JablotronHistoryDataEvent> sendGetEventHistory() {
return sendGetEventHistory(alarmName);
}
private @Nullable List<JablotronHistoryDataEvent> sendGetEventHistory(String alarm) {
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
return handler.sendGetEventHistory(getThing(), alarm);
}
return null;
}
protected void updateLastEvent(JablotronHistoryDataEvent event) {
updateState(CHANNEL_LAST_EVENT_TIME, new DateTimeType(getZonedDateTime(event.getDate())));
updateState(CHANNEL_LAST_EVENT, new StringType(event.getEventText()));
updateState(CHANNEL_LAST_EVENT_CLASS, new StringType(event.getIconType()));
updateState(CHANNEL_LAST_EVENT_INVOKER, new StringType(event.getInvokerName()));
// oasis does not have sections
if (getThing().getChannel(CHANNEL_LAST_EVENT_SECTION) != null) {
updateState(CHANNEL_LAST_EVENT_SECTION, new StringType(event.getSectionName()));
}
}
protected void updateEventChannel(String channel) {
List<JablotronHistoryDataEvent> events = eventCache.getValue();
if (events != null && events.size() > 0) {
JablotronHistoryDataEvent event = events.get(0);
switch (channel) {
case CHANNEL_LAST_EVENT_TIME:
updateState(CHANNEL_LAST_EVENT_TIME, new DateTimeType(getZonedDateTime(event.getDate())));
break;
case CHANNEL_LAST_EVENT:
updateState(CHANNEL_LAST_EVENT, new StringType(event.getEventText()));
break;
case CHANNEL_LAST_EVENT_CLASS:
updateState(CHANNEL_LAST_EVENT_CLASS, new StringType(event.getIconType()));
break;
case CHANNEL_LAST_EVENT_INVOKER:
updateState(CHANNEL_LAST_EVENT_INVOKER, new StringType(event.getInvokerName()));
break;
case CHANNEL_LAST_EVENT_SECTION:
updateState(CHANNEL_LAST_EVENT_SECTION, new StringType(event.getSectionName()));
break;
}
}
}
public ZonedDateTime getZonedDateTime(String date) {
return ZonedDateTime.parse(date.substring(0, 22) + ":" + date.substring(22, 24),
DateTimeFormatter.ISO_DATE_TIME);
}
protected @Nullable JablotronControlResponse sendUserCode(String section, String key, String status, String code) {
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
return handler.sendUserCode(getThing(), section, key, status, code);
}
return null;
}
protected @Nullable JablotronBridgeHandler getBridgeHandler() {
Bridge br = getBridge();
if (br != null && br.getHandler() != null) {
return (JablotronBridgeHandler) br.getHandler();
}
return null;
}
public void setStatus(ThingStatus status, ThingStatusDetail detail, String message) {
updateStatus(status, detail, message);
}
public void triggerAlarm(JablotronDiscoveredService service) {
if (!service.getWarningTime().equals(lastWarningTime)) {
logger.debug("Service id: {} is triggering an alarm: {}", thing.getUID().getId(), service.getWarning());
lastWarningTime = service.getWarningTime();
triggerChannel(CHANNEL_ALARM, service.getWarning());
}
}
public void setInService(boolean inService) {
this.inService = inService;
}
}

View File

@@ -0,0 +1,369 @@
/**
* 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.jablotron.internal.handler;
import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.jablotron.internal.config.JablotronBridgeConfig;
import org.openhab.binding.jablotron.internal.discovery.JablotronDiscoveryService;
import org.openhab.binding.jablotron.internal.model.*;
import org.openhab.binding.jablotron.internal.model.ja100f.JablotronGetPGResponse;
import org.openhab.binding.jablotron.internal.model.ja100f.JablotronGetSectionsResponse;
import org.openhab.core.thing.*;
import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.thing.binding.ThingHandlerService;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
/**
* The {@link JablotronBridgeHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronBridgeHandler extends BaseBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(JablotronBridgeHandler.class);
private final Gson gson = new Gson();
final HttpClient httpClient;
private @Nullable ScheduledFuture<?> future = null;
/**
* Our configuration
*/
public JablotronBridgeConfig bridgeConfig = new JablotronBridgeConfig();
public JablotronBridgeHandler(Bridge thing, HttpClient httpClient) {
super(thing);
this.httpClient = httpClient;
}
@Override
public Collection<Class<? extends ThingHandlerService>> getServices() {
return Collections.singleton(JablotronDiscoveryService.class);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
}
@Override
public void initialize() {
bridgeConfig = getConfigAs(JablotronBridgeConfig.class);
scheduler.execute(this::login);
future = scheduler.scheduleWithFixedDelay(this::updateAlarmThings, 30, bridgeConfig.getRefresh(),
TimeUnit.SECONDS);
}
private void updateAlarmThings() {
@Nullable
List<JablotronDiscoveredService> services = discoverServices();
if (services != null) {
for (JablotronDiscoveredService service : services) {
updateAlarmThing(service);
}
}
}
private void updateAlarmThing(JablotronDiscoveredService service) {
for (Thing th : getThing().getThings()) {
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
continue;
}
if (String.valueOf(service.getId()).equals(handler.thingConfig.getServiceId())) {
if ("ENABLED".equals(service.getStatus())) {
if (!service.getWarning().isEmpty()) {
logger.debug("Alarm with service id: {} warning: {}", service.getId(), service.getWarning());
}
handler.setStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, service.getWarning());
if ("ALARM".equals(service.getWarning()) || "TAMPER".equals(service.getWarning())) {
handler.triggerAlarm(service);
}
handler.setInService("SERVICE".equals(service.getWarning()));
} else {
logger.debug("Alarm with service id: {} is offline", service.getId());
handler.setStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, service.getStatus());
}
}
}
}
@Override
public void dispose() {
super.dispose();
ScheduledFuture<?> localFuture = future;
if (localFuture != null) {
localFuture.cancel(true);
}
logout();
}
private @Nullable <T> T sendJsonMessage(String url, String urlParameters, Class<T> classOfT) {
return sendMessage(url, urlParameters, classOfT, APPLICATION_JSON, true);
}
private @Nullable <T> T sendJsonMessage(String url, String urlParameters, Class<T> classOfT, boolean relogin) {
return sendMessage(url, urlParameters, classOfT, APPLICATION_JSON, relogin);
}
private @Nullable <T> T sendUrlEncodedMessage(String url, String urlParameters, Class<T> classOfT) {
return sendMessage(url, urlParameters, classOfT, WWW_FORM_URLENCODED, true);
}
private @Nullable <T> T sendMessage(String url, String urlParameters, Class<T> classOfT, String encoding,
boolean relogin) {
try {
ContentResponse resp = createRequest(url).content(new StringContentProvider(urlParameters), encoding)
.send();
logger.trace("Request: {} with data: {}", url, urlParameters);
String line = resp.getContentAsString();
logger.trace("Response: {}", line);
return gson.fromJson(line, classOfT);
} catch (TimeoutException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Timeout during calling url: " + url);
} catch (InterruptedException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Interrupt during calling url: " + url);
Thread.currentThread().interrupt();
} catch (JsonSyntaxException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Syntax error during calling url: " + url);
} catch (ExecutionException e) {
if (relogin) {
if (e.getMessage().contains(AUTHENTICATION_CHALLENGE)) {
relogin();
return null;
}
}
logger.debug("Error during calling url: {}", url, e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Error during calling url: " + url);
}
return null;
}
protected synchronized void login() {
String url = JABLOTRON_API_URL + "userAuthorize.json";
String urlParameters = "{\"login\":\"" + bridgeConfig.getLogin() + "\", \"password\":\""
+ bridgeConfig.getPassword() + "\"}";
JablotronLoginResponse response = sendJsonMessage(url, urlParameters, JablotronLoginResponse.class, false);
if (response == null) {
return;
}
if (response.getHttpCode() != 200) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Http error: " + response.getHttpCode());
} else {
updateStatus(ThingStatus.ONLINE);
}
}
protected void logout() {
String url = JABLOTRON_API_URL + "logout.json";
String urlParameters = "system=" + SYSTEM;
try {
ContentResponse resp = createRequest(url)
.content(new StringContentProvider(urlParameters), WWW_FORM_URLENCODED).send();
if (logger.isTraceEnabled()) {
String line = resp.getContentAsString();
logger.trace("logout response: {}", line);
}
} catch (ExecutionException | TimeoutException | InterruptedException e) {
// Silence
}
}
public @Nullable List<JablotronDiscoveredService> discoverServices() {
String url = JABLOTRON_API_URL + "serviceListGet.json";
String urlParameters = "{\"list-type\": \"EXTENDED\",\"visibility\": \"VISIBLE\"}";
JablotronGetServiceResponse response = sendJsonMessage(url, urlParameters, JablotronGetServiceResponse.class);
if (response == null) {
return null;
}
if (response.getHttpCode() != 200) {
logger.debug("Error during service discovery, got http code: {}", response.getHttpCode());
}
return response.getData().getServices();
}
protected @Nullable JablotronControlResponse sendUserCode(Thing th, String section, String key, String status,
String code) {
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
return null;
}
if (handler.isInService()) {
logger.debug("Cannot send command because the alarm is in the service mode");
return null;
}
String url = JABLOTRON_API_URL + "controlSegment.json";
String urlParameters = "service=" + th.getThingTypeUID().getId() + "&serviceId="
+ handler.thingConfig.getServiceId() + "&segmentId=" + section + "&segmentKey=" + key
+ "&expected_status=" + status + "&control_time=0&control_code=" + code + "&system=" + SYSTEM;
JablotronControlResponse response = sendUrlEncodedMessage(url, urlParameters, JablotronControlResponse.class);
if (response == null) {
return null;
}
if (!response.isStatus()) {
logger.debug("Error during sending user code: {}", response.getErrorMessage());
}
return response;
}
protected @Nullable List<JablotronHistoryDataEvent> sendGetEventHistory(Thing th, String alarm) {
String url = JABLOTRON_API_URL + alarm + "/eventHistoryGet.json";
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
return null;
}
String urlParameters = "{\"limit\":1, \"service-id\":" + handler.thingConfig.getServiceId() + "}";
JablotronGetEventHistoryResponse response = sendJsonMessage(url, urlParameters,
JablotronGetEventHistoryResponse.class);
if (response == null) {
return null;
}
if (200 != response.getHttpCode()) {
logger.debug("Got error while getting history with http code: {}", response.getHttpCode());
}
return response.getData().getEvents();
}
protected @Nullable JablotronDataUpdateResponse sendGetStatusRequest(Thing th) {
String url = JABLOTRON_API_URL + "dataUpdate.json";
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
return null;
}
String urlParameters = "data=[{ \"filter_data\":[{\"data_type\":\"section\"},{\"data_type\":\"pgm\"},{\"data_type\":\"thermometer\"},{\"data_type\":\"thermostat\"}],\"service_type\":\""
+ th.getThingTypeUID().getId() + "\",\"service_id\":" + handler.thingConfig.getServiceId()
+ ",\"data_group\":\"serviceData\"}]&system=" + SYSTEM;
return sendUrlEncodedMessage(url, urlParameters, JablotronDataUpdateResponse.class);
}
protected @Nullable JablotronGetPGResponse sendGetProgrammableGates(Thing th, String alarm) {
String url = JABLOTRON_API_URL + alarm + "/programmableGatesGet.json";
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
return null;
}
String urlParameters = "{\"connect-device\":false,\"list-type\":\"FULL\",\"service-id\":"
+ handler.thingConfig.getServiceId() + ",\"service-states\":true}";
return sendJsonMessage(url, urlParameters, JablotronGetPGResponse.class);
}
protected @Nullable JablotronGetSectionsResponse sendGetSections(Thing th, String alarm) {
String url = JABLOTRON_API_URL + alarm + "/sectionsGet.json";
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
return null;
}
String urlParameters = "{\"connect-device\":false,\"list-type\":\"FULL\",\"service-id\":"
+ handler.thingConfig.getServiceId() + ",\"service-states\":true}";
return sendJsonMessage(url, urlParameters, JablotronGetSectionsResponse.class);
}
protected @Nullable JablotronGetSectionsResponse controlComponent(Thing th, String code, String action,
String value, String componentId) throws SecurityException {
JablotronAlarmHandler handler = (JablotronAlarmHandler) th.getHandler();
if (handler == null) {
logger.debug("Thing handler is null");
return null;
}
if (handler.isInService()) {
logger.debug("Cannot control component because the alarm is in the service mode");
return null;
}
String url = JABLOTRON_API_URL + handler.getAlarmName() + "/controlComponent.json";
String urlParameters = "{\"authorization\":{\"authorization-code\":\"" + code
+ "\"},\"control-components\":[{\"actions\":{\"action\":\"" + action + "\",\"value\":\"" + value
+ "\"},\"component-id\":\"" + componentId + "\"}],\"service-id\":" + handler.thingConfig.getServiceId()
+ "}";
return sendJsonMessage(url, urlParameters, JablotronGetSectionsResponse.class);
}
private Request createRequest(String url) {
return httpClient.newRequest(url).method(HttpMethod.POST).header(HttpHeader.ACCEPT, APPLICATION_JSON)
.header(HttpHeader.ACCEPT_LANGUAGE, bridgeConfig.getLang()).header(HttpHeader.ACCEPT_ENCODING, "*")
.header("x-vendor-id", VENDOR).agent(AGENT).timeout(TIMEOUT_SEC, TimeUnit.SECONDS);
}
private void relogin() {
logger.debug("doing relogin");
login();
}
}

View File

@@ -0,0 +1,252 @@
/**
* 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.jablotron.internal.handler;
import static org.openhab.binding.jablotron.JablotronBindingConstants.CACHE_TIMEOUT_MS;
import static org.openhab.binding.jablotron.JablotronBindingConstants.CHANNEL_LAST_CHECK_TIME;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.jablotron.internal.model.JablotronHistoryDataEvent;
import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegment;
import org.openhab.binding.jablotron.internal.model.ja100f.JablotronGetPGResponse;
import org.openhab.binding.jablotron.internal.model.ja100f.JablotronGetSectionsResponse;
import org.openhab.binding.jablotron.internal.model.ja100f.JablotronSection;
import org.openhab.binding.jablotron.internal.model.ja100f.JablotronState;
import org.openhab.core.cache.ExpiringCache;
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.binding.builder.ChannelBuilder;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link JablotronJa100FHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronJa100FHandler extends JablotronAlarmHandler {
private final Logger logger = LoggerFactory.getLogger(JablotronJa100FHandler.class);
private ExpiringCache<JablotronGetSectionsResponse> sectionCache;
private ExpiringCache<JablotronGetPGResponse> pgCache;
public JablotronJa100FHandler(Thing thing, String alarmName) {
super(thing, alarmName);
sectionCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetSections);
pgCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetProgrammableGates);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (RefreshType.REFRESH.equals(command)) {
logger.debug("refreshing channel: {}", channelUID.getId());
updateChannel(channelUID.getId());
} else {
if (channelUID.getId().startsWith("sec-") && command instanceof StringType) {
if ("PARTIAL_ARM".equals(command.toString())) {
controlComponent(channelUID.getId(), "CONTROL-SECTION", "DISARM");
}
scheduler.execute(() -> controlComponent(channelUID.getId().toUpperCase(), "CONTROL-SECTION",
command.toString()));
}
if (channelUID.getId().startsWith("pg-") && command instanceof OnOffType) {
scheduler.execute(
() -> controlComponent(channelUID.getId().toUpperCase(), "CONTROL-PG", command.toString()));
}
}
}
private void updateChannel(String channel) {
if (channel.startsWith("sec-")) {
JablotronGetSectionsResponse sections = sectionCache.getValue();
if (sections != null) {
updateSectionState(channel, sections.getData().getStates());
}
} else if (channel.startsWith("pg-")) {
JablotronGetPGResponse pgs = pgCache.getValue();
if (pgs != null) {
updateSectionState(channel, pgs.getData().getStates());
}
} else if (CHANNEL_LAST_CHECK_TIME.equals(channel)) {
// not updating
} else {
updateEventChannel(channel);
}
}
@Override
protected void updateSegmentStatus(JablotronServiceDetailSegment segment) {
// nothing
}
private void controlComponent(String componentId, String action, String value) {
logger.debug("Controlling component: {} with action: {} and value: {}", componentId, action, value);
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
JablotronGetSectionsResponse response;
try {
response = handler.controlComponent(getThing(), thingConfig.getCode(), action, value, componentId);
} catch (SecurityException se) {
response = handler.controlComponent(getThing(), thingConfig.getCode(), action, value, componentId);
}
if (response != null) {
updateSectionState(response.getData().getStates());
} else {
logger.debug("null response/status received during the control of component: {}", componentId);
updateAlarmStatus();
}
}
}
private void createPGChannel(String name, String label) {
ThingBuilder thingBuilder = editThing();
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Switch").withLabel(label)
.build();
thingBuilder.withChannel(channel);
updateThing(thingBuilder.build());
}
private void createStateChannel(String name, String label) {
ChannelTypeUID alarmStatus = new ChannelTypeUID("jablotron", "ja100f_alarm_state");
ThingBuilder thingBuilder = editThing();
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "String").withLabel(label)
.withType(alarmStatus).build();
thingBuilder.withChannel(channel);
updateThing(thingBuilder.build());
}
private @Nullable JablotronGetSectionsResponse sendGetSections() {
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
return handler.sendGetSections(getThing(), alarmName);
}
return null;
}
protected @Nullable JablotronGetPGResponse sendGetProgrammableGates() {
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
return handler.sendGetProgrammableGates(getThing(), alarmName);
}
return null;
}
@Override
protected synchronized boolean updateAlarmStatus() {
JablotronBridgeHandler handler = getBridgeHandler();
if (handler != null) {
updateState(CHANNEL_LAST_CHECK_TIME, getCheckTime());
// sections
JablotronGetSectionsResponse response = handler.sendGetSections(getThing(), alarmName);
if (response != null) {
createSectionChannels(response.getData().getSections());
updateSectionState(response.getData().getStates());
}
// PGs
JablotronGetPGResponse resp = handler.sendGetProgrammableGates(getThing(), alarmName);
if (resp != null) {
createPGChannels(resp.getData().getProgrammableGates());
updateSectionState(resp.getData().getStates());
}
// update events
List<JablotronHistoryDataEvent> events = sendGetEventHistory();
if (events != null && events.size() > 0) {
JablotronHistoryDataEvent event = events.get(0);
updateLastEvent(event);
}
return true;
} else {
return false;
}
}
private void createPGChannels(List<JablotronSection> programmableGates) {
for (JablotronSection gate : programmableGates) {
String id = gate.getCloudComponentId().toLowerCase();
logger.trace("component id: {} with name: {}", id, gate.getName());
Channel channel = getThing().getChannel(id);
if (channel == null) {
logger.debug("Creating a new channel: {}", id);
createPGChannel(id, gate.getName());
}
}
}
private void createSectionChannels(List<JablotronSection> sections) {
for (JablotronSection section : sections) {
String id = section.getCloudComponentId().toLowerCase();
logger.trace("component id: {} with name: {}", id, section.getName());
Channel channel = getThing().getChannel(id);
if (channel == null) {
logger.debug("Creating a new channel: {}", id);
createStateChannel(id, section.getName());
}
}
}
private void updateSectionState(String section, List<JablotronState> states) {
for (JablotronState state : states) {
String id = state.getCloudComponentId();
if (id.equals(section.toUpperCase())) {
updateSection(id, state);
break;
}
}
}
private void updateSectionState(List<JablotronState> states) {
for (JablotronState state : states) {
String id = state.getCloudComponentId();
updateSection(id, state);
}
}
private void updateSection(String id, JablotronState state) {
logger.debug("component id: {} with state: {}", id, state.getState());
State newState;
if (id.startsWith("SEC-")) {
newState = new StringType(state.getState());
} else if (id.startsWith("PG-")) {
newState = "ON".equals(state.getState()) ? OnOffType.ON : OnOffType.OFF;
} else {
logger.debug("unknown component id: {}", id);
return;
}
Channel channel = getThing().getChannel(id.toLowerCase());
if (channel != null) {
updateState(channel.getUID(), newState);
} else {
logger.debug("The channel: {} still doesn't exist!", id);
}
}
}

View File

@@ -0,0 +1,224 @@
/**
* 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.jablotron.internal.handler;
import static org.openhab.binding.jablotron.JablotronBindingConstants.CACHE_TIMEOUT_MS;
import static org.openhab.binding.jablotron.JablotronBindingConstants.CHANNEL_LAST_CHECK_TIME;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.jablotron.internal.model.JablotronControlResponse;
import org.openhab.binding.jablotron.internal.model.JablotronDataUpdateResponse;
import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegment;
import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegmentInfo;
import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.unit.SIUnits;
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.binding.builder.ThingBuilder;
import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link JablotronJa100Handler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronJa100Handler extends JablotronAlarmHandler {
private final Logger logger = LoggerFactory.getLogger(JablotronJa100Handler.class);
public JablotronJa100Handler(Thing thing, String alarmName) {
super(thing, alarmName);
dataCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetStatusRequest);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (RefreshType.REFRESH.equals(command)) {
logger.debug("refreshing channel: {}", channelUID.getId());
updateChannel(channelUID.getId());
} else {
if (channelUID.getId().startsWith("state_") && command instanceof StringType) {
scheduler.execute(() -> {
controlSTATESection(channelUID.getId().toUpperCase(), command.toString());
});
}
if (channelUID.getId().startsWith("pgm_") && command instanceof OnOffType) {
scheduler.execute(() -> {
controlPGMSection(channelUID.getId().toUpperCase(), command.equals(OnOffType.ON) ? "set" : "unset");
});
}
}
}
private void updateChannel(String channel) {
ExpiringCache<JablotronDataUpdateResponse> localDataCache = dataCache;
if (localDataCache != null) {
if (channel.startsWith("state_") || channel.startsWith("pgm_") || channel.startsWith("thermometer_")
|| channel.startsWith("thermostat_")) {
updateSegmentStatus(channel, localDataCache.getValue());
} else if (CHANNEL_LAST_CHECK_TIME.equals(channel)) {
// not updating
} else {
updateEventChannel(channel);
}
}
}
private void createChannel(JablotronServiceDetailSegment section) {
if (section.getSegmentId().startsWith("PGM_")) {
createPGMChannel(section.getSegmentId().toLowerCase(), section.getSegmentName());
} else {
createStateChannel(section.getSegmentId().toLowerCase(), section.getSegmentName());
}
}
private void createTempChannel(String name, String label) {
ChannelTypeUID temperature = new ChannelTypeUID("jablotron", "temperature");
ThingBuilder thingBuilder = editThing();
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Number:Temperature")
.withLabel(label).withType(temperature).build();
thingBuilder.withChannel(channel);
updateThing(thingBuilder.build());
}
private void createThermostatChannel(String name, String label) {
ChannelTypeUID temperature = new ChannelTypeUID("jablotron", "thermostat");
ThingBuilder thingBuilder = editThing();
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Number:Temperature")
.withLabel(label).withType(temperature).build();
thingBuilder.withChannel(channel);
updateThing(thingBuilder.build());
}
private void createPGMChannel(String name, String label) {
ThingBuilder thingBuilder = editThing();
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "Switch").withLabel(label)
.build();
thingBuilder.withChannel(channel);
updateThing(thingBuilder.build());
}
private void createStateChannel(String name, String label) {
ChannelTypeUID alarmStatus = new ChannelTypeUID("jablotron", "alarm_state");
ThingBuilder thingBuilder = editThing();
Channel channel = ChannelBuilder.create(new ChannelUID(thing.getUID(), name), "String").withLabel(label)
.withType(alarmStatus).build();
thingBuilder.withChannel(channel);
updateThing(thingBuilder.build());
}
@Override
protected void updateSegmentStatus(JablotronServiceDetailSegment segment) {
logger.debug("Segment id: {} and status: {}", segment.getSegmentId(), segment.getSegmentState());
String segmentId = segment.getSegmentId();
if (segmentId.startsWith("STATE_") || segmentId.startsWith("PGM_")) {
processSection(segment);
} else if (segmentId.startsWith("THERMOMETER_")) {
processThermometer(segment);
} else if (segmentId.startsWith("THERMOSTAT_")) {
processThermostat(segment);
} else {
logger.debug("Unknown segment received: {} with state: {}", segment.getSegmentId(),
segment.getSegmentState());
}
}
private void processSection(JablotronServiceDetailSegment segment) {
String segmentId = segment.getSegmentId().toLowerCase();
Channel channel = getThing().getChannel(segmentId);
if (channel == null) {
logger.debug("Creating a new channel: {}", segmentId);
createChannel(segment);
}
channel = getThing().getChannel(segmentId);
if (channel != null) {
logger.debug("Updating channel: {} to value: {}", channel.getUID(), segment.getSegmentState());
State newState;
if (segmentId.startsWith("PGM_")) {
newState = "unset".equals(segment.getSegmentState()) ? OnOffType.OFF : OnOffType.ON;
} else {
newState = new StringType(segment.getSegmentState());
}
updateState(channel.getUID(), newState);
} else {
logger.debug("The channel: {} still doesn't exist!", segmentId);
}
}
private void processThermometer(JablotronServiceDetailSegment segment) {
String segmentId = segment.getSegmentId().toLowerCase();
Channel channel = getThing().getChannel(segmentId);
if (channel == null) {
logger.debug("Creating a new temperature channel: {}", segmentId);
createTempChannel(segmentId, segment.getSegmentName());
}
updateTemperatureChannel(channel, segment);
}
private void processThermostat(JablotronServiceDetailSegment segment) {
String segmentId = segment.getSegmentId().toLowerCase();
Channel channel = getThing().getChannel(segmentId);
if (channel == null) {
logger.debug("Creating a new thermostat channel: {}", segmentId);
createThermostatChannel(segmentId, segment.getSegmentName());
}
updateTemperatureChannel(channel, segment);
}
private void updateTemperatureChannel(Channel channel, JablotronServiceDetailSegment segment) {
List<JablotronServiceDetailSegmentInfo> infos = segment.getSegmentInfos();
if (infos.size() > 0) {
logger.debug("Found value: {} and type: {}", infos.get(0).getValue(), infos.get(0).getType());
updateState(channel.getUID(), QuantityType.valueOf(infos.get(0).getValue(), SIUnits.CELSIUS));
} else {
logger.debug("No segment information received");
}
}
public synchronized void controlPGMSection(String section, String status) {
logger.debug("Controlling section: {} with status: {}", section, status);
JablotronControlResponse response = sendUserCode(section, section.toLowerCase(), status, thingConfig.getCode());
updateAlarmStatus();
if (response == null) {
logger.debug("null response/status received during the control of PGM section: {}", section);
}
}
public synchronized void controlSTATESection(String section, String status) {
logger.debug("Controlling section: {} with status: {}", section, status);
JablotronControlResponse response = sendUserCode(section, section.toLowerCase().replace("state", "section"),
status, thingConfig.getCode());
updateAlarmStatus();
if (response == null) {
logger.debug("null response/status received during the control of STATE section: {}", section);
}
}
}

View File

@@ -0,0 +1,159 @@
/**
* 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.jablotron.internal.handler;
import static org.openhab.binding.jablotron.JablotronBindingConstants.*;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.jablotron.internal.model.JablotronControlResponse;
import org.openhab.binding.jablotron.internal.model.JablotronDataUpdateResponse;
import org.openhab.binding.jablotron.internal.model.JablotronServiceDetailSegment;
import org.openhab.core.cache.ExpiringCache;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link JablotronOasisHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronOasisHandler extends JablotronAlarmHandler {
private final Logger logger = LoggerFactory.getLogger(JablotronOasisHandler.class);
public JablotronOasisHandler(Thing thing, String alarmName) {
super(thing, alarmName);
dataCache = new ExpiringCache<>(CACHE_TIMEOUT_MS, this::sendGetStatusRequest);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (RefreshType.REFRESH.equals(command)) {
logger.debug("refreshing channel: {}", channelUID.getId());
updateChannel(channelUID.getId());
} else {
switch (channelUID.getId()) {
case CHANNEL_COMMAND:
if (command instanceof StringType) {
scheduler.execute(() -> {
sendCommand(command.toString());
});
}
break;
case CHANNEL_STATUS_PGX:
if (command instanceof OnOffType) {
scheduler.execute(() -> {
controlSection("PGM_1", command.equals(OnOffType.ON) ? "set" : "unset");
});
}
break;
case CHANNEL_STATUS_PGY:
if (command instanceof OnOffType) {
scheduler.execute(() -> {
controlSection("PGM_2", command.equals(OnOffType.ON) ? "set" : "unset");
});
}
break;
}
}
}
private void updateChannel(String channel) {
ExpiringCache<JablotronDataUpdateResponse> localDataCache = dataCache;
if (localDataCache != null) {
switch (channel) {
case CHANNEL_STATUS_A:
updateSegmentStatus("STATE_1", localDataCache.getValue());
break;
case CHANNEL_STATUS_B:
updateSegmentStatus("STATE_2", localDataCache.getValue());
break;
case CHANNEL_STATUS_ABC:
updateSegmentStatus("STATE_3", localDataCache.getValue());
break;
case CHANNEL_STATUS_PGX:
updateSegmentStatus("PGM_1", localDataCache.getValue());
break;
case CHANNEL_STATUS_PGY:
updateSegmentStatus("PGM_2", localDataCache.getValue());
break;
case CHANNEL_LAST_CHECK_TIME:
// not updating
break;
default:
updateEventChannel(channel);
}
}
}
@Override
protected void updateSegmentStatus(JablotronServiceDetailSegment segment) {
logger.debug("Segment id: {} and status: {}", segment.getSegmentId(), segment.getSegmentState());
State newState = "unset".equals(segment.getSegmentState()) ? OnOffType.OFF : OnOffType.ON;
switch (segment.getSegmentId()) {
case "STATE_1":
updateState(CHANNEL_STATUS_A, newState);
break;
case "STATE_2":
updateState(CHANNEL_STATUS_B, newState);
break;
case "STATE_3":
updateState(CHANNEL_STATUS_ABC, newState);
break;
case "PGM_1":
updateState(CHANNEL_STATUS_PGX, newState);
break;
case "PGM_2":
updateState(CHANNEL_STATUS_PGY, newState);
break;
default:
logger.debug("Unknown segment received: {} with state: {}", segment.getSegmentId(),
segment.getSegmentState());
}
}
public synchronized void controlSection(String section, String status) {
logger.debug("Controlling section: {} with status: {}", section, status);
JablotronControlResponse response = sendUserCode(section, section.toLowerCase(), status, "");
updateAlarmStatus();
if (response == null) {
logger.debug("null response/status received during the control of section: {}", section);
}
}
public synchronized void sendCommand(String code) {
JablotronControlResponse response = sendUserCode(code);
scheduler.schedule(this::updateAlarmStatus, 1, TimeUnit.SECONDS);
if (response == null) {
logger.debug("null response/status received during sending a code");
}
}
private synchronized @Nullable JablotronControlResponse sendUserCode(String code) {
return sendUserCode("sections", "button_1", "partialSet", code);
}
}

View File

@@ -0,0 +1,39 @@
/**
* 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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronControlResponse} class defines the control command
* response for Jablotron alarm.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronControlResponse {
private boolean status = false;
@SerializedName(value = "error_message", alternate = "error_status")
String errorMessage = "";
public boolean isStatus() {
return status;
}
public String getErrorMessage() {
return errorMessage;
}
}

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.jablotron.internal.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronData} class defines the data object
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronData {
@SerializedName("service_data")
List<JablotronServiceData> serviceData = new ArrayList<>();
public List<JablotronServiceData> getServiceData() {
return serviceData;
}
}

View File

@@ -0,0 +1,44 @@
/**
* 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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronDataUpdateResponse} class defines the data update call
* response.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronDataUpdateResponse {
boolean status = false;
JablotronData data = new JablotronData();
@SerializedName("error_message")
String errorMessage = "";
public boolean isStatus() {
return status;
}
public JablotronData getData() {
return data;
}
public String getErrorMessage() {
return errorMessage;
}
}

View File

@@ -0,0 +1,63 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronDiscoveredService} class defines the discovered service
* object
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronDiscoveredService {
@SerializedName("service-id")
int id = 0;
String name = "";
String status = "";
String warning = "";
@SerializedName("warning-time")
String warningTime = "";
@SerializedName("service-type")
String serviceType = "";
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getServiceType() {
return serviceType;
}
public String getStatus() {
return status;
}
public String getWarning() {
return warning;
}
public String getWarningTime() {
return warningTime;
}
}

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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronGetEventHistoryResponse} class defines the response for the
* getEventHistory operation
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetEventHistoryResponse {
@SerializedName("http-code")
int httpCode = -1;
JablotronHistoryData data = new JablotronHistoryData();
public int getHttpCode() {
return httpCode;
}
public JablotronHistoryData getData() {
return data;
}
}

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.jablotron.internal.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronGetServiceData} class defines the data object for the
* getServiceList response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetServiceData {
List<JablotronDiscoveredService> services = new ArrayList<>();
public List<JablotronDiscoveredService> getServices() {
return services;
}
}

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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronGetServiceResponse} class defines the response for the
* getServiceList operation
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetServiceResponse {
@SerializedName("http-code")
int httpCode = -1;
JablotronGetServiceData data = new JablotronGetServiceData();
public int getHttpCode() {
return httpCode;
}
public JablotronGetServiceData getData() {
return data;
}
}

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.jablotron.internal.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronHistoryData} class defines the data object for the
* getEventHistory response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronHistoryData {
List<JablotronHistoryDataEvent> events = new ArrayList<>();
public List<JablotronHistoryDataEvent> getEvents() {
return events;
}
}

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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronHistoryDataEvent} class defines the event object for the
* getEventHistory response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronHistoryDataEvent {
@SerializedName("icon-type")
String iconType = "";
@SerializedName("event-text")
String eventText = "";
@SerializedName("invoker-name")
String invokerName = "";
@SerializedName("section-name")
String sectionName = "";
String date = "";
public String getIconType() {
return iconType;
}
public String getEventText() {
return eventText;
}
public String getDate() {
return date;
}
public String getInvokerName() {
return invokerName;
}
public String getSectionName() {
return sectionName;
}
}

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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronLoginResponse} class defines the login call
* response.
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronLoginResponse {
@SerializedName("http-code")
int httpCode = -1;
public int getHttpCode() {
return httpCode;
}
}

View File

@@ -0,0 +1,39 @@
/**
* 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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronService} class defines the service object
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronService {
@SerializedName("data_type")
String dataType = "";
JablotronServiceDetail data = new JablotronServiceDetail();
public String getDataType() {
return dataType;
}
public JablotronServiceDetail getData() {
return data;
}
}

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.jablotron.internal.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronServiceData} class defines the service data object
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronServiceData {
@SerializedName("service_id")
String serviceId = "";
List<JablotronService> data = new ArrayList<>();
public String getServiceId() {
return serviceId;
}
public List<JablotronService> getData() {
return data;
}
}

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.jablotron.internal.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronServiceDetail} class defines the service detail object
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronServiceDetail {
List<JablotronServiceDetailSegment> segments = new ArrayList<>();
public List<JablotronServiceDetailSegment> getSegments() {
return segments;
}
}

View File

@@ -0,0 +1,57 @@
/**
* 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.jablotron.internal.model;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronServiceDetailSegment} class defines the service segment detail object
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronServiceDetailSegment {
@SerializedName("segment_id")
String segmentId = "";
@SerializedName("segment_state")
String segmentState = "";
@SerializedName("segment_name")
String segmentName = "";
@SerializedName("segment_informations")
List<JablotronServiceDetailSegmentInfo> segmentInfos = new ArrayList<>();
public String getSegmentId() {
return segmentId;
}
public String getSegmentState() {
return segmentState;
}
public String getSegmentName() {
return segmentName;
}
public List<JablotronServiceDetailSegmentInfo> getSegmentInfos() {
return segmentInfos;
}
}

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.jablotron.internal.model;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronServiceDetailSegmentInfo} class defines the service segment detail object
* information
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronServiceDetailSegmentInfo {
float value = 0;
String type = "";
public float getValue() {
return value;
}
public String getType() {
return type;
}
}

View File

@@ -0,0 +1,39 @@
/**
* 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.jablotron.internal.model.ja100f;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronGetPGData} class defines the data object for the
* getProgrammableGates response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetPGData {
List<JablotronState> states = new ArrayList<>();
List<JablotronSection> programmableGates = new ArrayList<>();
public List<JablotronState> getStates() {
return states;
}
public List<JablotronSection> getProgrammableGates() {
return programmableGates;
}
}

View File

@@ -0,0 +1,30 @@
/**
* 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.jablotron.internal.model.ja100f;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronGetPGResponse} class defines the response object for the
* getProgrammableGates call
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetPGResponse {
JablotronGetPGData data = new JablotronGetPGData();
public JablotronGetPGData getData() {
return data;
}
}

View File

@@ -0,0 +1,39 @@
/**
* 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.jablotron.internal.model.ja100f;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronGetSectionsData} class defines the data object for the
* getSections response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetSectionsData {
List<JablotronState> states = new ArrayList<>();
List<JablotronSection> sections = new ArrayList<>();
public List<JablotronState> getStates() {
return states;
}
public List<JablotronSection> getSections() {
return sections;
}
}

View File

@@ -0,0 +1,30 @@
/**
* 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.jablotron.internal.model.ja100f;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link JablotronGetSectionsResponse} class defines the response object for the
* getSections call
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronGetSectionsResponse {
JablotronGetSectionsData data = new JablotronGetSectionsData();
public JablotronGetSectionsData getData() {
return data;
}
}

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.jablotron.internal.model.ja100f;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronSection} class defines the section object for the
* getSections response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronSection {
@SerializedName("cloud-component-id")
String cloudComponentId = "";
String name = "";
public String getCloudComponentId() {
return cloudComponentId;
}
public String getName() {
return name;
}
}

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.jablotron.internal.model.ja100f;
import org.eclipse.jdt.annotation.NonNullByDefault;
import com.google.gson.annotations.SerializedName;
/**
* The {@link JablotronState} class defines the state object for the
* getSections response
*
* @author Ondrej Pecta - Initial contribution
*/
@NonNullByDefault
public class JablotronState {
@SerializedName(value = "cloud-component-id", alternate = "component-id")
String cloudComponentId = "";
String state = "";
public String getCloudComponentId() {
return cloudComponentId;
}
public String getState() {
return state;
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="jablotron" 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>Jablotron Binding</name>
<description>This is the binding for Jablotron Alarm Systems.</description>
<author>Ondrej Pecta</author>
</binding:binding>

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
<config-description uri="thing-type:jablotron:device">
<parameter name="refresh" type="integer" required="false" min="10" unit="s">
<label>Refresh</label>
<description>Specifies the refresh time of thing channels in seconds</description>
<default>60</default>
</parameter>
<parameter name="serviceId" type="text" required="true">
<label>Alarm Service ID</label>
<description>The service ID of the Oasis alarm</description>
</parameter>
</config-description>
<config-description uri="thing-type:jablotron:ja100device">
<parameter name="refresh" type="integer" required="false" min="10" unit="s">
<label>Refresh</label>
<description>Specifies the refresh time of thing channels in seconds</description>
<default>60</default>
</parameter>
<parameter name="code" type="text" required="false">
<context>password</context>
<label>Code</label>
<description>Master code for the JA100 alarm</description>
</parameter>
<parameter name="serviceId" type="text" required="true">
<label>Alarm Service ID</label>
<description>The service ID of the JA100 alarm</description>
</parameter>
</config-description>
<config-description uri="bridge-type:jablotron:bridge">
<parameter name="login" type="text" required="true">
<label>Login</label>
<description>Login for Jablonet portal</description>
</parameter>
<parameter name="password" type="text" required="true">
<context>password</context>
<label>Password</label>
<description>Password for Jablonet portal</description>
</parameter>
<parameter name="lang" type="text" required="true">
<default>en</default>
<label>Language</label>
<description>Language for Jablonet portal</description>
<options>
<option value="cs">Česky</option>
<option value="da">Dansk</option>
<option value="de">Deutsch</option>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
<option value="hr">Hrvatski</option>
<option value="it">Italiano</option>
<option value="hu">Magyar</option>
<option value="nl">Nederlands</option>
<option value="vi">Người việt nam</option>
<option value="no">Norsk</option>
<option value="pl">Polski</option>
<option value="pt">Portugues</option>
<option value="ro">Română</option>
<option value="sl">Slovenski</option>
<option value="sk">Slovensky</option>
<option value="sr">Srpski</option>
<option value="fi">Suomi</option>
<option value="sv">Svenska</option>
<option value="tr">Türkçe</option>
</options>
</parameter>
<parameter name="refresh" type="integer" required="false" min="10" unit="s">
<label>Refresh</label>
<description>Specifies the refresh time for all alarm warnings (alarm, service mode, ...)</description>
<default>30</default>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="jablotron"
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">
<!-- Jablonet -->
<bridge-type id="bridge">
<label>Jablonet Bridge</label>
<description>A bridge to the Jablonet cloud service.</description>
<config-description-ref uri="bridge-type:jablotron:bridge"/>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="jablotron"
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">
<!-- Oasis -->
<!-- StatusA -->
<channel-type id="statusA">
<item-type>Switch</item-type>
<label>Alarm Zone A Status</label>
<description>Status of the A zone of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- StatusB -->
<channel-type id="statusB">
<item-type>Switch</item-type>
<label>Alarm B Status</label>
<description>Status of the B zone of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- StatusABC -->
<channel-type id="statusABC">
<item-type>Switch</item-type>
<label>Alarm Zone ABC Status</label>
<description>Status of the ABC zone of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- StatusPGX -->
<channel-type id="statusPGX">
<item-type>Switch</item-type>
<label>OASIS PGX Status</label>
<description>Status of the PGX switch of your OASIS alarm</description>
</channel-type>
<!-- StatusPGY -->
<channel-type id="statusPGY">
<item-type>Switch</item-type>
<label>OASIS PGY Status</label>
<description>Status of the PGY switch of your OASIS alarm</description>
</channel-type>
<!-- JA100 -->
<channel-type id="status">
<item-type>Number</item-type>
<label>Alarm Section Status</label>
<description>Status of the section of your alarm</description>
</channel-type>
<!-- StatusPGM -->
<channel-type id="statusPGM">
<item-type>Switch</item-type>
<label>JA-100 PGM Status</label>
<description>Status of the PGM switch of your JA-100 alarm</description>
</channel-type>
<!-- Alarm -->
<channel-type id="alarm">
<kind>trigger</kind>
<label>Alarm</label>
<description>Status of the alarm of your alarm</description>
<state readOnly="true"/>
<event>
<options>
<option value="TAMPER">tamper</option>
<option value="ALARM">alarm</option>
</options>
</event>
</channel-type>
<!-- Command -->
<channel-type id="command">
<item-type>String</item-type>
<label>Alarm Command</label>
<description>Channel for sending commands to your alarm</description>
</channel-type>
<!-- LastEvent -->
<channel-type id="lastEvent">
<item-type>String</item-type>
<label>Alarm Last Event Text Description</label>
<description>Text description of the last event of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- LastEventClass -->
<channel-type id="lastEventClass">
<item-type>String</item-type>
<label>Alarm Last Event Class</label>
<description>Class of the last event of your alarm (arm, disarm, ...)</description>
<state readOnly="true"/>
</channel-type>
<!-- LastEventSection -->
<channel-type id="lastEventSection">
<item-type>String</item-type>
<label>Alarm Last Event Section</label>
<description>The last event section of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- LastEventInvoker -->
<channel-type id="lastEventInvoker">
<item-type>String</item-type>
<label>Alarm Last Event Invoker</label>
<description>The last event invoker</description>
<state readOnly="true"/>
</channel-type>
<!-- LastEventTime -->
<channel-type id="lastEventTime">
<item-type>DateTime</item-type>
<label>Alarm Last Event Time</label>
<description>Date and time of the last event of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- LastCheckTime -->
<channel-type id="lastCheckTime">
<item-type>DateTime</item-type>
<label>Alarm Last Check Time</label>
<description>Date and time of last status check of your alarm</description>
<state readOnly="true"/>
</channel-type>
<!-- alarm_state -->
<channel-type id="alarm_state">
<item-type>String</item-type>
<label>Alarm State</label>
<description>A channel used for controlling the alarm state</description>
<state>
<options>
<option value="set">ARMED</option>
<option value="partialSet">PARTIAL</option>
<option value="unset">DISARMED</option>
</options>
</state>
</channel-type>
<!-- ja100f_alarm_state -->
<channel-type id="ja100f_alarm_state">
<item-type>String</item-type>
<label>Alarm State</label>
<description>A channel used for controlling the alarm state</description>
<state>
<options>
<option value="ARM">ARMED</option>
<option value="PARTIAL_ARM">PARTIAL</option>
<option value="DISARM">DISARMED</option>
</options>
</state>
</channel-type>
<!-- temperature -->
<channel-type id="temperature">
<item-type>Number:Temperature</item-type>
<label>Sensor Temperature</label>
<description>The current temperature reported by the sensor</description>
<state pattern="%.1f %unit%" readOnly="true"/>
</channel-type>
<!-- thermostat -->
<channel-type id="thermostat">
<item-type>Number:Temperature</item-type>
<label>Thermostat Temperature</label>
<description>The current temperature reported by the thermostat</description>
<state pattern="%.1f %unit%" readOnly="true"/>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="jablotron"
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">
<!-- ja100 alarm -->
<thing-type id="ja100">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>JA100 Alarm</label>
<description>A Jablotron JA100 alarm device.</description>
<channels>
<channel id="lastEvent" typeId="lastEvent"/>
<channel id="lastEventClass" typeId="lastEventClass"/>
<channel id="lastEventTime" typeId="lastEventTime"/>
<channel id="lastEventInvoker" typeId="lastEventInvoker"/>
<channel id="lastEventSection" typeId="lastEventSection"/>
<channel id="lastCheckTime" typeId="lastCheckTime"/>
<channel id="alarm" typeId="alarm"/>
</channels>
<config-description-ref uri="thing-type:jablotron:ja100device"/>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="jablotron"
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">
<!-- ja100 alarm -->
<thing-type id="ja100f">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>JA100F Alarm</label>
<description>A Jablotron JA100F alarm device.</description>
<channels>
<channel id="lastEvent" typeId="lastEvent"/>
<channel id="lastEventClass" typeId="lastEventClass"/>
<channel id="lastEventTime" typeId="lastEventTime"/>
<channel id="lastEventInvoker" typeId="lastEventInvoker"/>
<channel id="lastEventSection" typeId="lastEventSection"/>
<channel id="lastCheckTime" typeId="lastCheckTime"/>
<channel id="alarm" typeId="alarm"/>
</channels>
<config-description-ref uri="thing-type:jablotron:ja100device"/>
</thing-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="jablotron"
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">
<!-- Oasis alarm -->
<thing-type id="oasis">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>
<label>Oasis Alarm</label>
<description>A Jablotron Oasis alarm device.</description>
<channels>
<channel id="statusA" typeId="statusA"/>
<channel id="statusB" typeId="statusB"/>
<channel id="statusABC" typeId="statusABC"/>
<channel id="statusPGX" typeId="statusPGX"/>
<channel id="statusPGY" typeId="statusPGY"/>
<channel id="command" typeId="command"/>
<channel id="lastEvent" typeId="lastEvent"/>
<channel id="lastEventClass" typeId="lastEventClass"/>
<channel id="lastEventInvoker" typeId="lastEventInvoker"/>
<channel id="lastEventTime" typeId="lastEventTime"/>
<channel id="lastCheckTime" typeId="lastCheckTime"/>
<channel id="alarm" typeId="alarm"/>
</channels>
<config-description-ref uri="thing-type:jablotron:device"/>
</thing-type>
</thing:thing-descriptions>