) of the sun at the requested instant.
+Thing method applies to Sun and Moon.
+
+* `timeStamp` (ZonedDateTime) - defaulted to now() if null.
+
+Example :
+
+```
+ val azimuth = sunActions.getAzimuth(sunEventTime)
+ val elevation = sunActions.getElevation(sunEventTime)
+ logInfo("AstroActions", "{} will be positioned at elevation {} - azimuth {}",sunEvent, elevation.toString,azimuth.toString)
+```
+
+
## Tips
Do not worry if for example the "astro dawn" is undefined at your location.
diff --git a/bundles/org.openhab.binding.astro/pom.xml b/bundles/org.openhab.binding.astro/pom.xml
index 0108eb2afc91b..976c332bf7d2e 100644
--- a/bundles/org.openhab.binding.astro/pom.xml
+++ b/bundles/org.openhab.binding.astro/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.astro
diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/action/AstroActions.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/action/AstroActions.java
new file mode 100644
index 0000000000000..74001613b20fa
--- /dev/null
+++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/action/AstroActions.java
@@ -0,0 +1,158 @@
+/**
+ * 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.astro.internal.action;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.time.ZonedDateTime;
+
+import javax.measure.quantity.Angle;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.library.types.QuantityType;
+import org.eclipse.smarthome.core.thing.binding.ThingActions;
+import org.eclipse.smarthome.core.thing.binding.ThingActionsScope;
+import org.eclipse.smarthome.core.thing.binding.ThingHandler;
+import org.openhab.binding.astro.internal.AstroBindingConstants;
+import org.openhab.binding.astro.internal.handler.AstroThingHandler;
+import org.openhab.binding.astro.internal.handler.SunHandler;
+import org.openhab.binding.astro.internal.model.SunPhaseName;
+import org.openhab.core.automation.annotation.ActionInput;
+import org.openhab.core.automation.annotation.ActionOutput;
+import org.openhab.core.automation.annotation.RuleAction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {AstroActions } defines rule actions for the Astro binding.
+ *
+ * Note:The static method invokeMethodOf handles the case where
+ * the test actions instanceof AstroActions fails. This test can fail
+ * due to an issue in openHAB core v2.5.0 where the {@link AstroActions} class
+ * can be loaded by a different classloader than the actions instance.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@ThingActionsScope(name = "astro")
+@NonNullByDefault
+public class AstroActions implements ThingActions, IAstroActions {
+
+ private final Logger logger = LoggerFactory.getLogger(AstroActions.class);
+ protected @Nullable AstroThingHandler handler;
+
+ public AstroActions() {
+ logger.debug("Astro actions service instanciated");
+ }
+
+ @Override
+ public void setThingHandler(@Nullable ThingHandler handler) {
+ if (handler instanceof AstroThingHandler) {
+ this.handler = (AstroThingHandler) handler;
+ }
+ }
+
+ @Override
+ public @Nullable ThingHandler getThingHandler() {
+ return this.handler;
+ }
+
+ @Override
+ @RuleAction(label = "Astro : Get Azimuth", description = "Get the azimuth of the sun for a given time")
+ public @Nullable @ActionOutput(name = "getAzimuth", label = "Azimuth", type = "org.eclipse.smarthome.core.library.types.QuantityType") QuantityType getAzimuth(
+ @ActionInput(name = "date", label = "Date", required = false, description = "Considered date") @Nullable ZonedDateTime date) {
+ logger.debug("Astro action 'getAzimuth' called");
+ AstroThingHandler theHandler = this.handler;
+ if (theHandler != null) {
+ return theHandler.getAzimuth(date != null ? date : ZonedDateTime.now());
+ } else {
+ logger.info("Astro Action service ThingHandler is null!");
+ }
+ return null;
+ }
+
+ @Override
+ @RuleAction(label = "Astro : Get Elevation", description = "Get the Elevation of the sun for a given time")
+ public @Nullable @ActionOutput(name = "getElevation", label = "Elevation", type = "org.eclipse.smarthome.core.library.types.QuantityType") QuantityType getElevation(
+ @ActionInput(name = "date", label = "Date", required = false, description = "Considered date") @Nullable ZonedDateTime date) {
+ logger.debug("Astro action 'getElevation' called");
+ AstroThingHandler theHandler = this.handler;
+ if (theHandler != null) {
+ return theHandler.getElevation(date != null ? date : ZonedDateTime.now());
+ } else {
+ logger.info("Astro Action service ThingHandler is null!");
+ }
+ return null;
+ }
+
+ @Override
+ @RuleAction(label = "Sun : Get Event Time", description = "Get the date time of a given planet event")
+ public @Nullable @ActionOutput(name = "getEventTime", type = "java.time.ZonedDateTime") ZonedDateTime getEventTime(
+ @ActionInput(name = "phaseName", label = "Phase", required = true, description = "Requested phase") String phaseName,
+ @ActionInput(name = "date", label = "Date", required = false, description = "Considered date") @Nullable ZonedDateTime date,
+ @ActionInput(name = "moment", label = "Moment", required = false, defaultValue = "START", description = "Either START or END") @Nullable String moment) {
+ logger.debug("Sun action 'getEventTime' called");
+ try {
+ if (handler instanceof SunHandler) {
+ SunHandler handler = (SunHandler) this.handler;
+ SunPhaseName phase = SunPhaseName.valueOf(phaseName.toUpperCase());
+ return handler.getEventTime(phase, date != null ? date : ZonedDateTime.now(),
+ moment == null || AstroBindingConstants.EVENT_START.equalsIgnoreCase(moment));
+ } else {
+ logger.info("Astro Action service ThingHandler is not a SunHandler!");
+ }
+ } catch (IllegalArgumentException e) {
+ logger.info("Parameter {} is not a valid phase name", phaseName);
+ }
+ return null;
+ }
+
+ public static @Nullable QuantityType getElevation(@Nullable ThingActions actions,
+ @Nullable ZonedDateTime date) {
+ return invokeMethodOf(actions).getElevation(date);
+ }
+
+ public static @Nullable QuantityType getAzimuth(@Nullable ThingActions actions,
+ @Nullable ZonedDateTime date) {
+ return invokeMethodOf(actions).getAzimuth(date);
+ }
+
+ public static @Nullable ZonedDateTime getEventTime(@Nullable ThingActions actions, @Nullable String phaseName,
+ @Nullable ZonedDateTime date, @Nullable String moment) {
+ if (phaseName != null) {
+ return invokeMethodOf(actions).getEventTime(phaseName, date, moment);
+ } else {
+ throw new IllegalArgumentException("phaseName can not be null");
+ }
+ }
+
+ private static IAstroActions invokeMethodOf(@Nullable ThingActions actions) {
+ if (actions == null) {
+ throw new IllegalArgumentException("actions cannot be null");
+ }
+ if (actions.getClass().getName().equals(AstroActions.class.getName())) {
+ if (actions instanceof IAstroActions) {
+ return (IAstroActions) actions;
+ } else {
+ return (IAstroActions) Proxy.newProxyInstance(IAstroActions.class.getClassLoader(),
+ new Class[] { IAstroActions.class }, (Object proxy, Method method, Object[] args) -> {
+ Method m = actions.getClass().getDeclaredMethod(method.getName(),
+ method.getParameterTypes());
+ return m.invoke(actions, args);
+ });
+ }
+ }
+ throw new IllegalArgumentException("Actions is not an instance of AstroActions");
+ }
+
+}
diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/action/IAstroActions.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/action/IAstroActions.java
new file mode 100644
index 0000000000000..df0dbd06a7700
--- /dev/null
+++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/action/IAstroActions.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.astro.internal.action;
+
+import java.time.ZonedDateTime;
+
+import javax.measure.quantity.Angle;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.library.types.QuantityType;
+
+/**
+ * The {@link IAstroActions} defines the interface for all thing actions supported by the binding.
+ *
+ * @author Gaël L'hopital - Initial contribution
+ */
+@NonNullByDefault
+public interface IAstroActions {
+ public @Nullable ZonedDateTime getEventTime(String phaseName, @Nullable ZonedDateTime date,
+ @Nullable String moment);
+
+ public @Nullable QuantityType getAzimuth(@Nullable ZonedDateTime date);
+
+ public @Nullable QuantityType getElevation(@Nullable ZonedDateTime date);
+}
diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java
index fc8eb7492d204..42ded68a19ede 100644
--- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java
+++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java
@@ -17,7 +17,10 @@
import static org.eclipse.smarthome.core.types.RefreshType.REFRESH;
import java.lang.invoke.MethodHandles;
+import java.time.ZonedDateTime;
import java.util.Calendar;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
@@ -27,12 +30,15 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import javax.measure.quantity.Angle;
+
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.i18n.TimeZoneProvider;
+import org.eclipse.smarthome.core.library.types.QuantityType;
import org.eclipse.smarthome.core.scheduler.CronScheduler;
import org.eclipse.smarthome.core.scheduler.ScheduledCompletableFuture;
import org.eclipse.smarthome.core.thing.Channel;
@@ -40,12 +46,15 @@
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
+import org.eclipse.smarthome.core.thing.binding.ThingHandlerService;
import org.eclipse.smarthome.core.types.Command;
+import org.openhab.binding.astro.internal.action.AstroActions;
import org.openhab.binding.astro.internal.config.AstroChannelConfig;
import org.openhab.binding.astro.internal.config.AstroThingConfig;
import org.openhab.binding.astro.internal.job.Job;
import org.openhab.binding.astro.internal.job.PositionalJob;
import org.openhab.binding.astro.internal.model.Planet;
+import org.openhab.binding.astro.internal.model.Position;
import org.openhab.binding.astro.internal.util.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -318,7 +327,9 @@ private void tidyScheduledFutures() {
/**
* Calculates and publishes the daily Astro data.
*/
- public abstract void publishDailyInfo();
+ public void publishDailyInfo() {
+ publishPositionalInfo();
+ }
/**
* Calculates and publishes the interval Astro data.
@@ -339,4 +350,22 @@ private void tidyScheduledFutures() {
* Returns the daily calculation {@link Job} (cannot be {@code null})
*/
protected abstract Job getDailyJob();
+
+ protected abstract @Nullable Position getPositionAt(ZonedDateTime date);
+
+ public @Nullable QuantityType getAzimuth(ZonedDateTime date) {
+ Position position = getPositionAt(date);
+ return position != null ? position.getAzimuth() : null;
+ }
+
+ public @Nullable QuantityType getElevation(ZonedDateTime date) {
+ Position position = getPositionAt(date);
+ return position != null ? position.getElevation() : null;
+ }
+
+ @Override
+ public Collection> getServices() {
+ return Collections.singletonList(AstroActions.class);
+ }
+
}
diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java
index 737bfbd0475ae..d3c8f5d0cf71d 100644
--- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java
+++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java
@@ -14,8 +14,10 @@
import static org.openhab.binding.astro.internal.AstroBindingConstants.THING_TYPE_MOON;
+import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
@@ -30,6 +32,7 @@
import org.openhab.binding.astro.internal.job.Job;
import org.openhab.binding.astro.internal.model.Moon;
import org.openhab.binding.astro.internal.model.Planet;
+import org.openhab.binding.astro.internal.model.Position;
/**
* The MoonHandler is responsible for updating calculated moon data.
@@ -54,15 +57,9 @@ public MoonHandler(Thing thing, final CronScheduler scheduler, final TimeZonePro
super(thing, scheduler, timeZoneProvider);
}
- @Override
- public void publishDailyInfo() {
- initializeMoon();
- publishPositionalInfo();
- }
-
@Override
public void publishPositionalInfo() {
- initializeMoon();
+ moon = getMoonAt(ZonedDateTime.now());
Double latitude = thingConfig.latitude;
Double longitude = thingConfig.longitude;
moonCalc.setPositionalInfo(Calendar.getInstance(), latitude != null ? latitude : 0,
@@ -91,10 +88,21 @@ protected Job getDailyJob() {
return new DailyJobMoon(thing.getUID().getAsString(), this);
}
- private void initializeMoon() {
+ private Moon getMoonAt(ZonedDateTime date) {
Double latitude = thingConfig.latitude;
Double longitude = thingConfig.longitude;
- moon = moonCalc.getMoonInfo(Calendar.getInstance(), latitude != null ? latitude : 0,
+ return moonCalc.getMoonInfo(GregorianCalendar.from(date), latitude != null ? latitude : 0,
longitude != null ? longitude : 0);
}
+
+ @Override
+ protected @Nullable Position getPositionAt(ZonedDateTime date) {
+ Moon localMoon = getMoonAt(date);
+ Double latitude = thingConfig.latitude;
+ Double longitude = thingConfig.longitude;
+ moonCalc.setPositionalInfo(GregorianCalendar.from(date), latitude != null ? latitude : 0,
+ longitude != null ? longitude : 0, localMoon);
+ return localMoon.getPosition();
+ }
+
}
diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java
index ccab3cabee083..29ca6982dd898 100644
--- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java
+++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java
@@ -14,8 +14,10 @@
import static org.openhab.binding.astro.internal.AstroBindingConstants.THING_TYPE_SUN;
+import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
@@ -29,7 +31,10 @@
import org.openhab.binding.astro.internal.job.DailyJobSun;
import org.openhab.binding.astro.internal.job.Job;
import org.openhab.binding.astro.internal.model.Planet;
+import org.openhab.binding.astro.internal.model.Position;
+import org.openhab.binding.astro.internal.model.Range;
import org.openhab.binding.astro.internal.model.Sun;
+import org.openhab.binding.astro.internal.model.SunPhaseName;
/**
* The SunHandler is responsible for updating calculated sun data.
@@ -54,19 +59,14 @@ public SunHandler(Thing thing, final CronScheduler scheduler, final TimeZoneProv
super(thing, scheduler, timeZoneProvider);
}
- @Override
- public void publishDailyInfo() {
- initializeSun();
- publishPositionalInfo();
- }
-
@Override
public void publishPositionalInfo() {
- initializeSun();
+ sun = getSunAt(ZonedDateTime.now());
Double latitude = thingConfig.latitude;
Double longitude = thingConfig.longitude;
+ Double altitude = thingConfig.altitude;
sunCalc.setPositionalInfo(Calendar.getInstance(), latitude != null ? latitude : 0,
- longitude != null ? longitude : 0, thingConfig.altitude, sun);
+ longitude != null ? longitude : 0, altitude != null ? altitude : 0, sun);
publishPlanet();
}
@@ -91,10 +91,30 @@ protected Job getDailyJob() {
return new DailyJobSun(thing.getUID().getAsString(), this);
}
- private void initializeSun() {
+ private Sun getSunAt(ZonedDateTime date) {
Double latitude = thingConfig.latitude;
Double longitude = thingConfig.longitude;
- sun = sunCalc.getSunInfo(Calendar.getInstance(), latitude != null ? latitude : 0,
- longitude != null ? longitude : 0, thingConfig.altitude, thingConfig.useMeteorologicalSeason);
+ Double altitude = thingConfig.altitude;
+ return sunCalc.getSunInfo(GregorianCalendar.from(date), latitude != null ? latitude : 0,
+ longitude != null ? longitude : 0, altitude != null ? altitude : 0,
+ thingConfig.useMeteorologicalSeason);
}
+
+ public @Nullable ZonedDateTime getEventTime(SunPhaseName sunPhase, ZonedDateTime date, boolean begin) {
+ Range eventRange = getSunAt(date).getAllRanges().get(sunPhase);
+ Calendar cal = begin ? eventRange.getStart() : eventRange.getEnd();
+ return ZonedDateTime.ofInstant(cal.toInstant(), date.getZone());
+ }
+
+ @Override
+ protected @Nullable Position getPositionAt(ZonedDateTime date) {
+ Sun localSun = getSunAt(date);
+ Double latitude = thingConfig.latitude;
+ Double longitude = thingConfig.longitude;
+ Double altitude = thingConfig.altitude;
+ sunCalc.setPositionalInfo(GregorianCalendar.from(date), latitude != null ? latitude : 0,
+ longitude != null ? longitude : 0, altitude != null ? altitude : 0, localSun);
+ return localSun.getPosition();
+ }
+
}
diff --git a/bundles/org.openhab.binding.atlona/pom.xml b/bundles/org.openhab.binding.atlona/pom.xml
index 8f331dc3676c6..cb6ba0a2b89cb 100644
--- a/bundles/org.openhab.binding.atlona/pom.xml
+++ b/bundles/org.openhab.binding.atlona/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.atlona
diff --git a/bundles/org.openhab.binding.autelis/pom.xml b/bundles/org.openhab.binding.autelis/pom.xml
index 9956f5e312401..aaf2b29dc481f 100644
--- a/bundles/org.openhab.binding.autelis/pom.xml
+++ b/bundles/org.openhab.binding.autelis/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.autelis
diff --git a/bundles/org.openhab.binding.avmfritz/pom.xml b/bundles/org.openhab.binding.avmfritz/pom.xml
index ff37aa0024edd..bd68f0cd7dca2 100644
--- a/bundles/org.openhab.binding.avmfritz/pom.xml
+++ b/bundles/org.openhab.binding.avmfritz/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.avmfritz
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzDynamicStateDescriptionProvider.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzDynamicCommandDescriptionProvider.java
similarity index 50%
rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzDynamicStateDescriptionProvider.java
rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzDynamicCommandDescriptionProvider.java
index 04644aca9cfba..59e85d5915429 100644
--- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzDynamicStateDescriptionProvider.java
+++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzDynamicCommandDescriptionProvider.java
@@ -13,29 +13,25 @@
package org.openhab.binding.avmfritz.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.smarthome.core.thing.binding.BaseDynamicStateDescriptionProvider;
+import org.eclipse.smarthome.core.thing.binding.BaseDynamicCommandDescriptionProvider;
import org.eclipse.smarthome.core.thing.i18n.ChannelTypeI18nLocalizationService;
-import org.eclipse.smarthome.core.thing.type.DynamicStateDescriptionProvider;
+import org.eclipse.smarthome.core.thing.type.DynamicCommandDescriptionProvider;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
- * Dynamic provider of state options while leaving other state description fields as original.
+ * Dynamic provider of command options.
*
* @author Christoph Weitkamp - Initial contribution
*/
-@Component(service = { DynamicStateDescriptionProvider.class, AVMFritzDynamicStateDescriptionProvider.class })
+@Component(service = { DynamicCommandDescriptionProvider.class, AVMFritzDynamicCommandDescriptionProvider.class })
@NonNullByDefault
-public class AVMFritzDynamicStateDescriptionProvider extends BaseDynamicStateDescriptionProvider {
+public class AVMFritzDynamicCommandDescriptionProvider extends BaseDynamicCommandDescriptionProvider {
- @Reference
- protected void setChannelTypeI18nLocalizationService(
- final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
+ @Activate
+ public AVMFritzDynamicCommandDescriptionProvider(
+ final @Reference ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService;
}
-
- protected void unsetChannelTypeI18nLocalizationService(
- final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) {
- this.channelTypeI18nLocalizationService = null;
- }
}
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java
index ec9e208ecce00..c3d75d0eb83a0 100644
--- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java
+++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java
@@ -47,13 +47,13 @@ public class AVMFritzHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(AVMFritzHandlerFactory.class);
private final HttpClient httpClient;
- private final AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider;
+ private final AVMFritzDynamicCommandDescriptionProvider commandDescriptionProvider;
@Activate
public AVMFritzHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
- final @Reference AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) {
+ final @Reference AVMFritzDynamicCommandDescriptionProvider stateDescriptionProvider) {
this.httpClient = httpClientFactory.getCommonHttpClient();
- this.stateDescriptionProvider = stateDescriptionProvider;
+ this.commandDescriptionProvider = stateDescriptionProvider;
}
/**
@@ -71,9 +71,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (BRIDGE_THING_TYPE.equals(thingTypeUID)) {
- return new BoxHandler((Bridge) thing, httpClient, stateDescriptionProvider);
+ return new BoxHandler((Bridge) thing, httpClient, commandDescriptionProvider);
} else if (PL546E_STANDALONE_THING_TYPE.equals(thingTypeUID)) {
- return new Powerline546EHandler((Bridge) thing, httpClient, stateDescriptionProvider);
+ return new Powerline546EHandler((Bridge) thing, httpClient, commandDescriptionProvider);
} else if (SUPPORTED_BUTTON_THING_TYPES_UIDS.contains(thingTypeUID)) {
return new AVMFritzButtonHandler(thing);
} else if (SUPPORTED_DEVICE_THING_TYPES_UIDS.contains(thingTypeUID)) {
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java
index 75822a89f0560..d804b1c86fc5b 100644
--- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java
+++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java
@@ -18,6 +18,8 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
+import org.eclipse.smarthome.core.types.CommandOption;
+
/**
* See {@link TemplateListModel}.
*
@@ -68,6 +70,10 @@ public ApplyMaskListModel getApplyMaskList() {
return applyMaskList;
}
+ public CommandOption toCommandOption() {
+ return new CommandOption(getIdentifier(), getName());
+ }
+
@Override
public String toString() {
return new StringBuilder().append("[identifier=").append(identifier).append(",id=").append(templateId)
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java
index c7617c99a4b38..dd45a5f561486 100644
--- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java
+++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java
@@ -15,7 +15,6 @@
import static org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants.*;
import static org.openhab.binding.avmfritz.internal.dto.DeviceModel.ETSUnitInfoModel.*;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -44,10 +43,8 @@
import org.eclipse.smarthome.core.thing.binding.ThingHandlerService;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.RefreshType;
-import org.eclipse.smarthome.core.types.StateOption;
-import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants;
-import org.openhab.binding.avmfritz.internal.AVMFritzDynamicStateDescriptionProvider;
+import org.openhab.binding.avmfritz.internal.AVMFritzDynamicCommandDescriptionProvider;
import org.openhab.binding.avmfritz.internal.config.AVMFritzBoxConfiguration;
import org.openhab.binding.avmfritz.internal.discovery.AVMFritzDiscoveryService;
import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel;
@@ -95,7 +92,7 @@ public abstract class AVMFritzBaseBridgeHandler extends BaseBridgeHandler {
*/
private final HttpClient httpClient;
- private final AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider;
+ private final AVMFritzDynamicCommandDescriptionProvider commandDescriptionProvider;
protected final List listeners = new CopyOnWriteArrayList<>();
@@ -110,10 +107,10 @@ public abstract class AVMFritzBaseBridgeHandler extends BaseBridgeHandler {
* @param bridge Bridge object representing a FRITZ!Box
*/
public AVMFritzBaseBridgeHandler(Bridge bridge, HttpClient httpClient,
- AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) {
+ AVMFritzDynamicCommandDescriptionProvider commandDescriptionProvider) {
super(bridge);
this.httpClient = httpClient;
- this.stateDescriptionProvider = stateDescriptionProvider;
+ this.commandDescriptionProvider = commandDescriptionProvider;
applyTemplateChannelUID = new ChannelUID(bridge.getUID(), CHANNEL_APPLY_TEMPLATE);
}
@@ -241,12 +238,8 @@ public void setStatusInfo(ThingStatus status, ThingStatusDetail statusDetail, @N
* @param templateList list of template models
*/
public void addTemplateList(List templateList) {
- List options = new ArrayList<>();
- for (TemplateModel template : templateList) {
- logger.debug("Process template model: {}", template);
- options.add(new StateOption(template.getIdentifier(), template.getName()));
- }
- stateDescriptionProvider.setStateOptions(applyTemplateChannelUID, options);
+ commandDescriptionProvider.setCommandOptions(applyTemplateChannelUID,
+ templateList.stream().map(TemplateModel::toCommandOption).collect(Collectors.toList()));
}
/**
@@ -350,21 +343,13 @@ public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Cannot handle command '{}' because connection is missing", command);
return;
}
- switch (channelId) {
- case CHANNEL_APPLY_TEMPLATE:
- applyTemplate(command, fritzBox);
- break;
- default:
- logger.debug("Received unknown channel {}", channelId);
- break;
- }
- }
-
- protected void applyTemplate(Command command, FritzAhaWebInterface fritzBox) {
- if (command instanceof StringType) {
- fritzBox.applyTemplate(command.toString());
+ if (CHANNEL_APPLY_TEMPLATE.equals(channelId)) {
+ if (command instanceof StringType) {
+ fritzBox.applyTemplate(command.toString());
+ }
+ } else {
+ logger.debug("Received unknown channel {}", channelId);
}
- updateState(CHANNEL_APPLY_TEMPLATE, UnDefType.UNDEF);
}
/**
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/BoxHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/BoxHandler.java
index f364e36013be7..862b454ed7872 100644
--- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/BoxHandler.java
+++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/BoxHandler.java
@@ -15,7 +15,7 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.smarthome.core.thing.Bridge;
-import org.openhab.binding.avmfritz.internal.AVMFritzDynamicStateDescriptionProvider;
+import org.openhab.binding.avmfritz.internal.AVMFritzDynamicCommandDescriptionProvider;
/**
* Handler for a FRITZ!Box device. Handles polling of values from AHA devices.
@@ -32,7 +32,7 @@ public class BoxHandler extends AVMFritzBaseBridgeHandler {
* @param bridge Bridge object representing a FRITZ!Box
*/
public BoxHandler(Bridge bridge, HttpClient httpClient,
- AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) {
- super(bridge, httpClient, stateDescriptionProvider);
+ AVMFritzDynamicCommandDescriptionProvider commandDescriptionProvider) {
+ super(bridge, httpClient, commandDescriptionProvider);
}
}
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java
index 74c6f297ee0d4..ea2b1f7eb6783 100644
--- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java
+++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java
@@ -45,7 +45,7 @@
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.avmfritz.internal.AVMFritzBindingConstants;
-import org.openhab.binding.avmfritz.internal.AVMFritzDynamicStateDescriptionProvider;
+import org.openhab.binding.avmfritz.internal.AVMFritzDynamicCommandDescriptionProvider;
import org.openhab.binding.avmfritz.internal.config.AVMFritzBoxConfiguration;
import org.openhab.binding.avmfritz.internal.config.AVMFritzDeviceConfiguration;
import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel;
@@ -80,8 +80,8 @@ public class Powerline546EHandler extends AVMFritzBaseBridgeHandler implements F
* @param bridge Bridge object representing a FRITZ!Powerline 546E
*/
public Powerline546EHandler(Bridge bridge, HttpClient httpClient,
- AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) {
- super(bridge, httpClient, stateDescriptionProvider);
+ AVMFritzDynamicCommandDescriptionProvider commandDescriptionProvider) {
+ super(bridge, httpClient, commandDescriptionProvider);
}
@Override
@@ -287,7 +287,9 @@ public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Channel {} is a read-only channel and cannot handle command '{}'", channelId, command);
break;
case CHANNEL_APPLY_TEMPLATE:
- applyTemplate(command, fritzBox);
+ if (command instanceof StringType) {
+ fritzBox.applyTemplate(command.toString());
+ }
break;
case CHANNEL_OUTLET:
fritzBox.setSwitch(ain, OnOffType.ON.equals(command));
diff --git a/bundles/org.openhab.binding.bigassfan/pom.xml b/bundles/org.openhab.binding.bigassfan/pom.xml
index c2b6fd91f9441..90d12221627e1 100644
--- a/bundles/org.openhab.binding.bigassfan/pom.xml
+++ b/bundles/org.openhab.binding.bigassfan/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bigassfan
diff --git a/bundles/org.openhab.binding.bluetooth.airthings/pom.xml b/bundles/org.openhab.binding.bluetooth.airthings/pom.xml
index 8b12d6eb14d22..facfeb032fc74 100644
--- a/bundles/org.openhab.binding.bluetooth.airthings/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.airthings/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.airthings
diff --git a/bundles/org.openhab.binding.bluetooth.am43/pom.xml b/bundles/org.openhab.binding.bluetooth.am43/pom.xml
index 013007527909b..a6fcfd3b6059d 100644
--- a/bundles/org.openhab.binding.bluetooth.am43/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.am43/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.am43
diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml b/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml
index ac17a68067f8e..3090b015b86ec 100644
--- a/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.bluegiga
diff --git a/bundles/org.openhab.binding.bluetooth.bluez/pom.xml b/bundles/org.openhab.binding.bluetooth.bluez/pom.xml
index beb6749f04ac8..1be86a1024cb4 100644
--- a/bundles/org.openhab.binding.bluetooth.bluez/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.bluez/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.bluez
diff --git a/bundles/org.openhab.binding.bluetooth.blukii/pom.xml b/bundles/org.openhab.binding.bluetooth.blukii/pom.xml
index e4dcb8b876eb0..866b1208a8882 100644
--- a/bundles/org.openhab.binding.bluetooth.blukii/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.blukii/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.blukii
diff --git a/bundles/org.openhab.binding.bluetooth.daikinmadoka/pom.xml b/bundles/org.openhab.binding.bluetooth.daikinmadoka/pom.xml
index 12228de0b2146..787c2476b66d9 100644
--- a/bundles/org.openhab.binding.bluetooth.daikinmadoka/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.daikinmadoka/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.daikinmadoka
diff --git a/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml b/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml
index 4f40e6a2e1776..93aeac5bf401f 100644
--- a/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth.ruuvitag
diff --git a/bundles/org.openhab.binding.bluetooth/pom.xml b/bundles/org.openhab.binding.bluetooth/pom.xml
index 79220c998685e..0e45c74f67356 100644
--- a/bundles/org.openhab.binding.bluetooth/pom.xml
+++ b/bundles/org.openhab.binding.bluetooth/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bluetooth
diff --git a/bundles/org.openhab.binding.boschindego/pom.xml b/bundles/org.openhab.binding.boschindego/pom.xml
index 9dca59c07cdb1..bdb94f44386b0 100644
--- a/bundles/org.openhab.binding.boschindego/pom.xml
+++ b/bundles/org.openhab.binding.boschindego/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.boschindego
diff --git a/bundles/org.openhab.binding.bosesoundtouch/pom.xml b/bundles/org.openhab.binding.bosesoundtouch/pom.xml
index d456c1cee955e..bf18bd3fbf14e 100644
--- a/bundles/org.openhab.binding.bosesoundtouch/pom.xml
+++ b/bundles/org.openhab.binding.bosesoundtouch/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bosesoundtouch
diff --git a/bundles/org.openhab.binding.bsblan/pom.xml b/bundles/org.openhab.binding.bsblan/pom.xml
index 7c2f127f06107..f14026ad76bee 100644
--- a/bundles/org.openhab.binding.bsblan/pom.xml
+++ b/bundles/org.openhab.binding.bsblan/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bsblan
diff --git a/bundles/org.openhab.binding.bticinosmarther/pom.xml b/bundles/org.openhab.binding.bticinosmarther/pom.xml
index 07ec8975d5265..c878f47ebd2c4 100644
--- a/bundles/org.openhab.binding.bticinosmarther/pom.xml
+++ b/bundles/org.openhab.binding.bticinosmarther/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.bticinosmarther
diff --git a/bundles/org.openhab.binding.buienradar/pom.xml b/bundles/org.openhab.binding.buienradar/pom.xml
index 57cc49a6634b8..24f6192536f3d 100644
--- a/bundles/org.openhab.binding.buienradar/pom.xml
+++ b/bundles/org.openhab.binding.buienradar/pom.xml
@@ -3,7 +3,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.buienradar
openHAB Add-ons :: Bundles :: Buienradar Binding
diff --git a/bundles/org.openhab.binding.caddx/.classpath b/bundles/org.openhab.binding.caddx/.classpath
new file mode 100644
index 0000000000000..a5d95095ccaaf
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/.classpath
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.caddx/.project b/bundles/org.openhab.binding.caddx/.project
new file mode 100644
index 0000000000000..368a86586e338
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/.project
@@ -0,0 +1,23 @@
+
+
+ org.openhab.binding.caddx
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/bundles/org.openhab.binding.caddx/NOTICE b/bundles/org.openhab.binding.caddx/NOTICE
new file mode 100644
index 0000000000000..4c20ef446c1e4
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/NOTICE
@@ -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/openhab2-addons
diff --git a/bundles/org.openhab.binding.caddx/README.md b/bundles/org.openhab.binding.caddx/README.md
new file mode 100644
index 0000000000000..bef6eb45a9bdb
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/README.md
@@ -0,0 +1,273 @@
+# Caddx Binding
+
+The Caddx binding is used for communicating with the Caddx alarm panels. Also known as Interlogix.
+
+It provides connectivity to the NetworX alarm panels via a RS-232 serial connection to the NX-584E interface or directly to the NX-8E.
+
+## Supported Things
+
+This binding supports the following Thing types
+
+| Thing | Thing Type | Description |
+|------------|------------|------------------------------------------------------------------------|
+| bridge | Bridge | The RS-232 interface. |
+| panel | Thing | The basic representation of the alarm System. |
+| partition | Thing | Represents a controllable area within the alarm system. |
+| zone | Thing | Represents a physical device such as a door, window, or motion sensor. |
+| keypad | Thing | Represents a keypad. (Not yet functional) |
+
+## Discovery
+
+First the bridge must be **manually** defined. The serial port, baud rate and protocol have to be set correctly to match the respective configuration of the panel (see below Prerequisites section).
+After the bridge is manually added and available to openHAB, the binding will automatically start to discover partitions and zones and add them to the discovery inbox.
+
+Note:
+There is currently no support to discover the available keypads.
+
+## Prerequisites
+
+For the binding to work the panel has also to be programmed appropriately.
+
+### Programming locations for the NX-8E control panel
+
+| Location | Segment | Value | Description |
+|----------|---------|-------------|--------------------------------------------------------------------------------------------------------|
+| 207 | 1 | 1 | Serial Port selector |
+| 208 | 1 | 0 - 4 | Baud rate table
0 = 2400 Baud
1 = 4800 Baud
2 = 9600 Baud
3 = 19200 Baud
4 = 38400 Baud |
+| 209 | 1 | Off/On | Home automation protocol
1 = Off: Binary. On: ASCII. |
+| 210 | 1 | 2,5,6,7,8 | Enabling the Transitions |
+| 210 | 2 | 1,2,3,4 | |
+| 211 | 1 | 2,4,5,6,7,8 | Programming the Command/Request enables |
+| 211 | 2 | 1,2,3,4,5 | (Flags 4 and 5 are not yet functional. Can be ignored.) |
+| 211 | 3 | | |
+| 211 | 4 | 5,7,8 | |
+| 212 | 1 | 192 | Programming the LCD keypad address. (Not yet functional. Can be ignored.) |
+
+### Programming locations for the NX-584E home automation module
+
+| Location | Segment | Value | Description |
+|----------|---------|-------------|--------------------------------------------------------------------------------------------------------|
+| 0 | 1 | Off/On | Home automation protocol
1 = Off: Binary. On: ASCII. |
+| 1 | 1 | 0 - 4 | Baud rate table
0 = 600 Baud
1 = 1200 Baud
2 = 2400 Baud
3 = 4800 Baud
4 = 9600 Baud
5 = 19200 Baud
6 = 38400 Baud
7 = 76800 Baud |
+| 2 | 1 | 2,5,6,7,8 | Enabling the Transitions |
+| 2 | 2 | 1,2,3,4 | |
+| 3 | 1 | 2,4,5,6,7,8 | Programming the Command/Request enables |
+| 3 | 2 | 1,2,3,4,5 | (Flags 4 and 5 are not yet functional. Can be ignored.) |
+| 3 | 3 | | |
+| 3 | 4 | 5,7,8 | |
+| 4 | 1 | 192 | Programming the LCD keypad address. (Not yet functional. Can be ignored.) |
+
+## Thing Configuration
+
+The things can be configured either through the online configuration utility via discovery, or manually through the configuration file.
+The following table shows the available configuration parameters for each thing.
+
+| Thing | Configuration Parameters |
+|-----------|------------------------------------------------------------------------------------------------|
+| bridge | `serialPort` - Serial port for the bridge - Required |
+| | `protocol` - Protocol used for the communication (Binary, Ascii) - Required - Default = Binary |
+| | `baud` - Baud rate of the bridge - Required - Default = 9600 |
+| partition | `partitionNumber` - Partition number (1-8) - Required |
+| zone | `zoneNumber` - Zone number (1-192) - Required |
+| keypad | `keypadAddress` - Keypad address (192-255) - Required |
+
+A full example is further below.
+
+## Channels
+
+Caddx Alarm things support a variety of channels as seen below in the following table:
+
+| Channel | Item Type | Type | Description |
+|--------------------------------------------------|-----------|---------------------|--------------------------------------------|
+| send_Command | String | Command | Send a command to the panel |
+| panel_firmware_version | String | Configuration | Firmware version |
+| panel_log_message_n_0 | String | Runtime | Log message 10 |
+| panel_log_message_n_1 | String | Runtime | Log message 9 |
+| panel_log_message_n_2 | String | Runtime | Log message 8 |
+| panel_log_message_n_3 | String | Runtime | Log message 7 |
+| panel_log_message_n_4 | String | Runtime | Log message 6 |
+| panel_log_message_n_5 | String | Runtime | Log message 5 |
+| panel_log_message_n_6 | String | Runtime | Log message 4 |
+| panel_log_message_n_7 | String | Runtime | Log message 3 |
+| panel_log_message_n_8 | String | Runtime | Log message 2 |
+| panel_log_message_n_9 | String | Runtime | Log message 1 |
+| panel_interface_configuration_message | Switch | Configuration | Interface Configuration Message |
+| panel_zone_status_message | Switch | Configuration | Zone Status Message |
+| panel_zones_snapshot_message | Switch | Configuration | Zones Snapshot Message |
+| panel_partition_status_message | Switch | Configuration | Partition Status Message |
+| panel_partitions_snapshot_message | Switch | Configuration | Partitions Snapshot Message |
+| panel_system_status_message | Switch | Configuration | System Status Message |
+| panel_x10_message_received | Switch | Configuration | X-10 Message Received |
+| panel_log_event_message | Switch | Configuration | Log Event Message |
+| panel_keypad_message_received | Switch | Configuration | Keypad Message Received |
+| panel_interface_configuration_request | Switch | Configuration | Interface Configuration Request |
+| panel_zone_name_request | Switch | Configuration | Zone Name Request |
+| panel_zone_status_request | Switch | Configuration | Zone Status Request |
+| panel_zones_snapshot_request | Switch | Configuration | Zones Snapshot Request |
+| panel_partition_status_request | Switch | Configuration | Partition Status Request |
+| panel_partitions_snapshot_request | Switch | Configuration | Partitions Snapshot Request |
+| panel_system_status_request | Switch | Configuration | System Status Request |
+| panel_send_x10_message | Switch | Configuration | Send X-10 Message |
+| panel_log_event_request | Switch | Configuration | Log Event Request |
+| panel_send_keypad_text_message | Switch | Configuration | Send Keypad Text Message |
+| panel_keypad_terminal_mode_request | Switch | Configuration | Keypad Terminal Mode Request |
+| panel_program_data_request | Switch | Configuration | Program Data Request |
+| panel_program_data_command | Switch | Configuration | Program Data Command |
+| panel_user_information_request_with_pin | Switch | Configuration | User Information Request with PIN |
+| panel_user_information_request_without_pin | Switch | Configuration | User Information Request without PIN |
+| panel_set_user_code_command_with_pin | Switch | Configuration | Set User Code Command with PIN |
+| panel_set_user_code_command_without_pin | Switch | Configuration | Set User Code Command without PIN |
+| panel_set_user_authorization_command_with_pin | Switch | Configuration | Set User Authorization Command with PIN |
+| panel_set_user_authorization_command_without_pin | Switch | Configuration | Set User Authorization Command without PIN |
+| panel_store_communication_event_command | Switch | Configuration | Store Communication Event Command |
+| panel_set_clock_calendar_command | Switch | Configuration | Set Clock / Calendar Command |
+| panel_primary_keypad_function_with_pin | Switch | Configuration | Primary Keypad Function with PIN |
+| panel_primary_keypad_function_without_pin | Switch | Configuration | Primary Keypad Function without PIN |
+| panel_secondary_keypad_function | Switch | Configuration | Secondary Keypad Function |
+| panel_zone_bypass_toggle | Switch | Configuration | Zone Bypass Toggle |
+| partition_bypass_code_required | Switch | Partition Condition | Bypass code required |
+| partition_fire_trouble | Switch | Partition Condition | Fire trouble |
+| partition_fire | Switch | Partition Condition | Fire |
+| partition_pulsing_buzzer | Switch | Partition Condition | Pulsing Buzzer |
+| partition_tlm_fault_memory | Switch | Partition Condition | TLM fault memory |
+| partition_armed | Switch | Partition Condition | Armed |
+| partition_instant | Switch | Partition Condition | Instant |
+| partition_previous_alarm | Switch | Partition Condition | Previous Alarm |
+| partition_siren_on | Switch | Partition Condition | Siren on |
+| partition_steady_siren_on | Switch | Partition Condition | Steady siren on |
+| partition_alarm_memory | Switch | Partition Condition | Alarm memory |
+| partition_tamper | Switch | Partition Condition | Tamper |
+| partition_cancel_command_entered | Switch | Partition Condition | Cancel command entered |
+| partition_code_entered | Switch | Partition Condition | Code entered |
+| partition_cancel_pending | Switch | Partition Condition | Cancel pending |
+| partition_silent_exit_enabled | Switch | Partition Condition | Silent exit enabled |
+| partition_entryguard | Switch | Partition Condition | Entryguard (stay mode) |
+| partition_chime_mode_on | Switch | Partition Condition | Chime mode on |
+| partition_entry | Switch | Partition Condition | Entry |
+| partition_delay_expiration_warning | Switch | Partition Condition | Delay expiration warning |
+| partition_exit1 | Switch | Partition Condition | Exit1 |
+| partition_exit2 | Switch | Partition Condition | Exit2 |
+| partition_led_extinguish | Switch | Partition Condition | LED extinguish |
+| partition_cross_timing | Switch | Partition Condition | Cross timing |
+| partition_recent_closing_being_timed | Switch | Partition Condition | Recent closing being timed |
+| partition_exit_error_triggered | Switch | Partition Condition | Exit error triggered |
+| partition_auto_home_inhibited | Switch | Partition Condition | Auto home inhibited |
+| partition_sensor_low_battery | Switch | Partition Condition | Sensor low battery |
+| partition_sensor_lost_supervision | Switch | Partition Condition | Sensor lost supervision |
+| partition_zone_bypassed | Switch | Partition Condition | Zone bypassed |
+| partition_force_arm_triggered_by_auto_arm | Switch | Partition Condition | Force arm triggered by auto arm |
+| partition_ready_to_arm | Switch | Partition Condition | Ready to arm |
+| partition_ready_to_force_arm | Switch | Partition Condition | Ready to force arm |
+| partition_valid_pin_accepted | Switch | Partition Condition | Valid PIN accepted |
+| partition_chime_on | Switch | Partition Condition | Chime on (sounding) |
+| partition_error_beep | Switch | Partition Condition | Error beep (triple beep) |
+| partition_tone_on | Switch | Partition Condition | Tone on (activation tone) |
+| partition_entry1 | Switch | Partition Condition | Entry 1 |
+| partition_open_period | Switch | Partition Condition | Open period |
+| partition_alarm_sent_using_phone_number_1 | Switch | Partition Condition | Alarm sent using phone number 1 |
+| partition_alarm_sent_using_phone_number_2 | Switch | Partition Condition | Alarm sent using phone number 2 |
+| partition_alarm_sent_using_phone_number_3 | Switch | Partition Condition | Alarm sent using phone number 3 |
+| partition_cancel_report_is_in_the_stack | Switch | Partition Condition | Cancel report is in the stack |
+| partition_keyswitch_armed | Switch | Partition Condition | Keyswitch armed |
+| partition_delay_trip_in_progress | Switch | Partition Condition | Delay Trip in progress (common zone) |
+| partition_secondary_command | Number | Command | Partition Secondary Command |
+| zone_partition2 | Switch | Configuration | Partition 2 |
+| zone_partition3 | Switch | Configuration | Partition 3 |
+| zone_partition1 | Switch | Configuration | Partition 1 |
+| zone_partition4 | Switch | Configuration | Partition 4 |
+| zone_partition5 | Switch | Configuration | Partition 5 |
+| zone_partition6 | Switch | Configuration | Partition 6 |
+| zone_partition7 | Switch | Configuration | Partition 7 |
+| zone_partition8 | Switch | Configuration | Partition 8 |
+| zone_name | String | Configuration | Name |
+| zone_fire | Switch | Configuration | Fire |
+| zone_24hour | Switch | Configuration | 24 Hour |
+| zone_key_switch | Switch | Configuration | Key-switch |
+| zone_follower | Switch | Configuration | Follower |
+| zone_entry_exit_delay_1 | Switch | Configuration | Entry / exit delay 1 |
+| zone_entry_exit_delay_2 | Switch | Configuration | Entry / exit delay 2 |
+| zone_interior | Switch | Configuration | Interior |
+| zone_local_only | Switch | Configuration | Local only |
+| zone_keypad_sounder | Switch | Configuration | Keypad Sounder |
+| zone_yelping_siren | Switch | Configuration | Yelping siren |
+| zone_steady_siren | Switch | Configuration | Steady siren |
+| zone_chime | Switch | Configuration | Chime |
+| zone_bypassable | Switch | Configuration | Bypassable |
+| zone_group_bypassable | Switch | Configuration | Group bypassable |
+| zone_force_armable | Switch | Configuration | Force armable |
+| zone_entry_guard | Switch | Configuration | Entry guard |
+| zone_fast_loop_response | Switch | Configuration | Fast loop response |
+| zone_double_eol_tamper | Switch | Configuration | Double EOL tamper |
+| zone_type_trouble | Switch | Configuration | Trouble |
+| zone_cross_zone | Switch | Configuration | Cross zone |
+| zone_dialer_delay | Switch | Configuration | Dialer delay |
+| zone_swinger_shutdown | Switch | Configuration | Swinger shutdown |
+| zone_restorable | Switch | Configuration | Restorable |
+| zone_listen_in | Switch | Configuration | Listen in |
+| zone_faulted | Contact | Zone Condition | Faulted (or delayed trip) |
+| zone_tampered | Switch | Zone Condition | Tampered |
+| zone_trouble | Switch | Zone Condition | Trouble |
+| zone_bypassed | Switch | Zone Condition | Bypassed |
+| zone_inhibited | Switch | Zone Condition | Inhibited (force armed) |
+| zone_low_battery | Switch | Zone Condition | Low battery |
+| zone_loss_of_supervision | Switch | Zone Condition | Loss of supervision |
+| zone_alarm_memory | Switch | Zone Condition | Alarm memory |
+| zone_bypass_memory | Switch | Zone Condition | Bypass memory |
+
+## Full Example
+
+The following is an example of a things file (caddx.things):
+
+```
+Bridge caddx:bridge:thebridge "Bridge" [ protocol="Binary", serialPort="/dev/ttyUSB0", baudrate=38400 ] {
+ Thing partition partition1 "Groundfloor alarm" [ partitionNumber=1 ]
+ Thing zone zone1 "Livingroom motion sensor" [ zoneNumber=1 ]
+ Thing zone zone2 "Bedroom motion sensor" [ zoneNumber=2 ]
+ Thing zone zone3 "Guestroom motion sensor" [ zoneNumber=3 ]
+ Thing zone zone4 "Livingroom window" [ zoneNumber=4 ]
+ Thing zone zone5 "Bedroom window" [ zoneNumber=5 ]
+ Thing zone zone6 "Guestroom window" [ zoneNumber=6 ]
+}
+```
+
+The following is an example of an items file (caddx.items):
+
+```
+Group:Contact:OR(OPEN,CLOSED) MotionSensors "Motion Sensors [%s]"
+Group:Contact:OR(OPEN,CLOSED) Windows "Windows open [%s]"
+
+Contact Bedroom_Motion "Bedroom [%s]" (MotionSensors) { channel="caddx:zone:thebridge:zone1:zone_faulted" }
+Contact Livingroom_Motion "Livingroom [%s]" (MotionSensors) { channel="caddx:zone:thebridge:zone2:zone_faulted" }
+Contact Guestroom_Motion "Guestroom [%s]" (MotionSensors) { channel="caddx:zone:thebridge:zone3:zone_faulted" }
+Contact Bedroom_Window "Bedroom Window [%s]" (Windows) { channel="caddx:zone:thebridge:zone4:zone_faulted" }
+Contact Livingroom_Window "Livinroom Window [%s]" (Windows) { channel="caddx:zone:thebridge:zone5:zone_faulted" }
+Contact Guestroom_Window "Guestroom Window [%s]" (Windows) { channel="caddx:zone:thebridge:zone6:zone_faulted" }
+
+Switch Partition1_Armed "Armed [%s]" { channel="caddx:partition:thebridge:partition1:partition_armed" }
+Switch Partition1_EntryGuard "Entry Guard [%s]" { channel="caddx:partition:thebridge:partition1:partition_entryguard" }
+```
+
+The following is an example of a sitemap file (home.sitemap):
+
+```
+sitemap home label="Home" {
+ Frame label="Ground floor" {
+ Text item=Partition1_Armed
+ Text item=Partition1_EntryGuard
+
+ Text item=MotionSensors
+ Text label="Motion Sensors (detailed)" {
+ Text item=Bedroom_Motion
+ Text item=Livingroom_Motion
+ Text item=Guestroom_Motion
+ }
+
+ Text item=Windows
+ Text label="Windows (detailed)" {
+ Text item=Bedroom_Window
+ Text item=Livingroom_Window
+ Text item=Guestroom_Window
+ }
+ }
+}
+```
diff --git a/bundles/org.openhab.binding.caddx/pom.xml b/bundles/org.openhab.binding.caddx/pom.xml
new file mode 100644
index 0000000000000..afb1bafbd340e
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/pom.xml
@@ -0,0 +1,15 @@
+
+
+ 4.0.0
+
+
+ org.openhab.addons.bundles
+ org.openhab.addons.reactor.bundles
+ 2.5.8-SNAPSHOT
+
+
+ org.openhab.binding.caddx
+
+ openHAB Add-ons :: Bundles :: Caddx Binding
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/feature/feature.xml b/bundles/org.openhab.binding.caddx/src/main/feature/feature.xml
new file mode 100644
index 0000000000000..cacd59d6466de
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/feature/feature.xml
@@ -0,0 +1,10 @@
+
+
+ mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features
+
+
+ openhab-runtime-base
+ openhab-transport-serial
+ mvn:org.openhab.addons.bundles/org.openhab.binding.caddx/${project.version}
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxBindingConstants.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxBindingConstants.java
new file mode 100644
index 0000000000000..e75e2145a2dab
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxBindingConstants.java
@@ -0,0 +1,95 @@
+/**
+ * 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.caddx.internal;
+
+import java.util.Collections;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.thing.ThingTypeUID;
+
+/**
+ * The {@link CaddxBindingConstants} class is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxBindingConstants {
+ // Binding ID
+ private static final String BINDING_ID = "caddx";
+
+ // List of bridge device types
+ public static final String CADDX_BRIDGE = "bridge";
+
+ // List of device types
+ public static final String PANEL = "panel";
+ public static final String PARTITION = "partition";
+ public static final String ZONE = "zone";
+ public static final String KEYPAD = "keypad";
+
+ // List of all Bridge Thing Type UIDs
+ public static final ThingTypeUID CADDXBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, CADDX_BRIDGE);
+
+ // List of all Thing Type UIDs
+ public static final ThingTypeUID PANEL_THING_TYPE = new ThingTypeUID(BINDING_ID, PANEL);
+ public static final ThingTypeUID PARTITION_THING_TYPE = new ThingTypeUID(BINDING_ID, PARTITION);
+ public static final ThingTypeUID ZONE_THING_TYPE = new ThingTypeUID(BINDING_ID, ZONE);
+ public static final ThingTypeUID KEYPAD_THING_TYPE = new ThingTypeUID(BINDING_ID, KEYPAD);
+
+ // Bridge
+ // Commands
+ // Channels
+ public static final String SEND_COMMAND = "send_command";
+
+ // Panel
+ // Commands
+ public static final String PANEL_INTERFACE_CONFIGURATION_REQUEST = "panel_interface_configuration_request";
+ public static final String PANEL_SYSTEM_STATUS_REQUEST = "panel_system_status_request";
+ public static final String PANEL_LOG_EVENT_REQUEST = "panel_log_event_request";
+ // Channels
+ public static final String PANEL_FIRMWARE_VERSION = "panel_firmware_version";
+ public static final String PANEL_LOG_MESSAGE_N_0 = "panel_log_message_n_0";
+
+ // Partition
+ // Commands
+ public static final String PARTITION_STATUS_REQUEST = "partition_status_request";
+ public static final String PARTITION_PRIMARY_COMMAND_WITH_PIN = "partition_primary_command_with_pin";
+ public static final String PARTITION_SECONDARY_COMMAND = "partition_secondary_command";
+ // Channels
+ public static final String PARTITION_ARMED = "partition_armed";
+ public static final String PARTITION_PRIMARY = "partition_primary";
+ public static final String PARTITION_SECONDARY = "partition_secondary";
+
+ // Zone
+ // Commands
+ public static final String ZONE_STATUS_REQUEST = "zone_status_request";
+ public static final String ZONE_NAME_REQUEST = "zone_name_request";
+ // Channels
+ public static final String ZONE_NAME = "zone_name";
+ public static final String ZONE_FAULTED = "zone_faulted";
+ public static final String ZONE_BYPASSED = "zone_bypassed";
+
+ // Keypad
+
+ // Set of all supported Thing Type UIDs
+ public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
+ .of(CADDXBRIDGE_THING_TYPE, PANEL_THING_TYPE, PARTITION_THING_TYPE, ZONE_THING_TYPE, KEYPAD_THING_TYPE)
+ .collect(Collectors.toSet()));
+
+ // Set of all supported Bridge Type UIDs
+ public static final Set SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections
+ .unmodifiableSet(Stream.of(CADDXBRIDGE_THING_TYPE).collect(Collectors.toSet()));
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java
new file mode 100644
index 0000000000000..1bec266567a61
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxCommunicator.java
@@ -0,0 +1,477 @@
+/**
+ * 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.caddx.internal;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TooManyListenersException;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.util.HexUtils;
+import org.eclipse.smarthome.io.transport.serial.PortInUseException;
+import org.eclipse.smarthome.io.transport.serial.SerialPort;
+import org.eclipse.smarthome.io.transport.serial.SerialPortEvent;
+import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener;
+import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier;
+import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
+import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link CaddxCommunicator} is responsible for the asynchronous serial communication
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxCommunicator implements SerialPortEventListener {
+ private final Logger logger = LoggerFactory.getLogger(CaddxCommunicator.class);
+
+ private final SerialPortManager portManager;
+ private final Set listenerQueue = new HashSet<>();
+ private final Deque messages = new LinkedBlockingDeque<>();
+ private final SynchronousQueue exchanger = new SynchronousQueue<>();
+ private final Thread communicator;
+ private final CaddxProtocol protocol;
+ private final String serialPortName;
+ private final int baudRate;
+ private final SerialPort serialPort;
+ private final InputStream in;
+ private final OutputStream out;
+
+ // Receiver state variables
+ private boolean inMessage = false;
+ private boolean haveFirstByte = false;
+ private int messageBufferLength = 0;
+ private byte[] message;
+ private int messageBufferIndex = 0;
+ private boolean unStuff = false;
+ private int tempAsciiByte = 0;
+
+ public CaddxCommunicator(SerialPortManager portManager, CaddxProtocol protocol, String serialPortName, int baudRate)
+ throws UnsupportedCommOperationException, PortInUseException, IOException, TooManyListenersException {
+ this.portManager = portManager;
+ this.protocol = protocol;
+ this.serialPortName = serialPortName;
+ this.baudRate = baudRate;
+
+ SerialPortIdentifier portIdentifier = this.portManager.getIdentifier(serialPortName);
+ if (portIdentifier == null) {
+ throw new IOException("Cannot get the port identifier.");
+ }
+ serialPort = portIdentifier.open(this.getClass().getName(), 2000);
+ serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
+ serialPort.enableReceiveThreshold(1);
+ serialPort.disableReceiveTimeout();
+
+ InputStream localIn = serialPort.getInputStream();
+ if (localIn == null) {
+ logger.warn("Cannot get the input stream of the serial port");
+ throw new IOException("Input stream is null");
+ }
+ in = localIn;
+
+ OutputStream localOut = serialPort.getOutputStream();
+ if (localOut == null) {
+ logger.warn("Cannot get the output stream of the serial port");
+ throw new IOException("Output stream is null");
+ }
+ out = localOut;
+
+ serialPort.notifyOnDataAvailable(true);
+ serialPort.addEventListener(this);
+
+ communicator = new Thread(this::messageDispatchLoop, "Caddx Communicator");
+ communicator.setDaemon(true);
+ communicator.start();
+
+ message = new byte[0];
+
+ logger.trace("CaddxCommunicator communication thread started successfully for {}", serialPortName);
+ }
+
+ public CaddxProtocol getProtocol() {
+ return protocol;
+ }
+
+ public String getSerialPortName() {
+ return serialPortName;
+ }
+
+ public int getBaudRate() {
+ return baudRate;
+ }
+
+ public void addListener(CaddxPanelListener listener) {
+ listenerQueue.add(listener);
+ }
+
+ /**
+ * Send message to panel. Asynchronous, i.e. returns immediately.
+ * Messages are sent only when panel is ready (i.e. sent an
+ * acknowledgment to last message), but no checks are implemented that
+ * the message was correctly received and executed.
+ *
+ * @param msg Data to be sent to panel. First byte is message type.
+ * Fletcher sum is computed and appended by transmit.
+ */
+ public void transmit(CaddxMessage msg) {
+ messages.add(msg);
+ }
+
+ /**
+ * Adds this message before any others in the queue.
+ * Used by receiver to send ACKs.
+ *
+ * @param msg The message
+ */
+ public void transmitFirst(CaddxMessage msg) {
+ messages.addFirst(msg);
+ }
+
+ public void stop() {
+ logger.trace("CaddxCommunicator stopping");
+
+ // kick thread out of waiting for FIFO
+ communicator.interrupt();
+
+ // Close the streams first to unblock blocked reads and writes
+ try {
+ in.close();
+ } catch (IOException e) {
+ }
+ try {
+ out.close();
+ } catch (IOException e) {
+ }
+
+ // Wait until communication thread exits
+ try {
+ communicator.join(3000);
+ } catch (InterruptedException e) {
+ }
+
+ // Also close the serial port
+ serialPort.removeEventListener();
+ serialPort.close();
+ }
+
+ @SuppressWarnings("null")
+ private void messageDispatchLoop() {
+ int @Nullable [] expectedMessageNumbers = null;
+
+ @Nullable
+ CaddxMessage outgoingMessage = null;
+ boolean skipTransmit = true;
+
+ try {
+ // loop until the thread is interrupted, sending out messages
+ while (!Thread.currentThread().isInterrupted()) {
+ // Initialize the state
+ outgoingMessage = null;
+ expectedMessageNumbers = null;
+
+ if (!skipTransmit) {
+ // send next outgoing message if we have one
+ outgoingMessage = messages.poll();
+ if (outgoingMessage != null) {
+ logger.trace("CaddxCommunicator.run() Outgoing message: {}", outgoingMessage.getMessageType());
+
+ byte[] msg = outgoingMessage.getMessageFrameBytes(protocol);
+ out.write(msg);
+ out.flush();
+
+ expectedMessageNumbers = outgoingMessage.getReplyMessageNumbers();
+
+ // Log message
+ if (logger.isDebugEnabled()) {
+ logger.debug("->: {}", outgoingMessage.getName());
+ logger.debug("->: {}", HexUtils
+ .bytesToHex(outgoingMessage.getMessageFrameBytes(CaddxProtocol.Binary), " "));
+ }
+ }
+ } else {
+ logger.trace("CaddxCommunicator.run() skipTransmit: true");
+ skipTransmit = false;
+ }
+
+ // Check for an incoming message
+ CaddxMessage incomingMessage = null;
+ try {
+ incomingMessage = exchanger.poll(3, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ logger.debug("CaddxCommunicator.run() InterruptedException caught.");
+ Thread.currentThread().interrupt();
+ }
+
+ // Log
+ if (incomingMessage == null) {
+ if (expectedMessageNumbers == null) { // Nothing expected, Nothing received we continue
+ logger.trace("CaddxCommunicator.run(): Nothing expected, Nothing received we continue");
+ continue;
+ }
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("<-: {}", incomingMessage.getName());
+ logger.debug("<-: {}",
+ HexUtils.bytesToHex(incomingMessage.getMessageFrameBytes(CaddxProtocol.Binary), " "));
+ }
+ }
+
+ // Check if we wait for a reply
+ if (expectedMessageNumbers == null) {
+ if (incomingMessage != null) { // Nothing expected. Message received.
+ logger.trace("CaddxCommunicator.run() Nothing expected, Message received");
+
+ // Check if Acknowledgement handling is required.
+ if (incomingMessage.hasAcknowledgementFlag()) {
+ if (incomingMessage.isChecksumCorrect()) {
+ // send ACK
+ transmitFirst(new CaddxMessage(CaddxMessageType.POSITIVE_ACKNOWLEDGE, ""));
+ } else {
+ // Send NAK
+ transmitFirst(new CaddxMessage(CaddxMessageType.NEGATIVE_ACKNOWLEDGE, ""));
+ }
+ }
+ }
+ } else {
+ if (incomingMessage == null) {
+ logger.trace("CaddxCommunicator.run() Message expected. Nothing received");
+
+ // Message expected. Nothing received
+ if (outgoingMessage != null) {
+ transmitFirst(outgoingMessage); // put message in queue again
+ continue;
+ }
+ } else {
+ logger.trace("CaddxCommunicator.run() Message expected. Message received");
+
+ // Message expected. Message received.
+ int receivedMessageType = incomingMessage.getMessageType();
+ boolean isMessageExpected = IntStream.of(expectedMessageNumbers)
+ .anyMatch(x -> x == receivedMessageType);
+
+ if (!isMessageExpected) {
+ logger.trace("Non expected message received exp:{}, recv: {}", expectedMessageNumbers,
+ receivedMessageType);
+
+ // Non expected reply received
+ if (outgoingMessage != null) {
+ transmitFirst(outgoingMessage); // put message in queue again
+ skipTransmit = true; // Skip the transmit on the next cycle to receive the panel message
+ }
+ }
+ }
+ }
+
+ // Inform the listeners
+ if (incomingMessage != null) {
+ if (incomingMessage.isChecksumCorrect()) {
+ for (CaddxPanelListener listener : listenerQueue) {
+ listener.caddxMessage(this, incomingMessage);
+ }
+ } else {
+ logger.warn(
+ "CaddxCommunicator.run() Received packet checksum does not match. in: {} {}, calc {} {}",
+ incomingMessage.getChecksum1In(), incomingMessage.getChecksum2In(),
+ incomingMessage.getChecksum1Calc(), incomingMessage.getChecksum2Calc());
+ }
+ }
+ }
+ } catch (IOException e) {
+ logger.debug("CaddxCommunicator.run() IOException. Stopping sender thread. {}", getSerialPortName());
+ Thread.currentThread().interrupt();
+ }
+
+ logger.warn("CaddxCommunicator.run() Sender thread stopped. {}", getSerialPortName());
+ }
+
+ /**
+ * Event handler to receive the data from the serial port
+ *
+ * @param SerialPortEvent serialPortEvent The event that occurred on the serial port
+ */
+ @Override
+ public void serialEvent(@Nullable SerialPortEvent serialPortEvent) {
+ if (serialPortEvent == null) {
+ return;
+ }
+
+ if (serialPortEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
+ logger.trace("Data receiving from the serial port");
+ if (protocol == CaddxProtocol.Binary) {
+ receiveInBinaryProtocol(serialPortEvent);
+ } else {
+ receiveInAsciiProtocol(serialPortEvent);
+ }
+ }
+ }
+
+ private int readByte(InputStream stream) throws IOException {
+ int b = -1;
+
+ if (stream.available() > 0) {
+ b = stream.read();
+ }
+ if (b == -1) {
+ throw new EOFException();
+ }
+ return b;
+ }
+
+ private int readAsciiByte(InputStream stream) throws IOException {
+ if (!haveFirstByte) { // this is the 1st digit
+ int b = readByte(in);
+ tempAsciiByte = (b >= 0x30 && b <= 0x39) ? (b - 0x30) * 0x10 : (b - 0x37) * 0x10;
+ haveFirstByte = true;
+ }
+
+ if (haveFirstByte) { // this is the 2nd digit
+ int b = readByte(in);
+ tempAsciiByte += (b >= 0x30 && b <= 0x39) ? (b - 0x30) : (b - 0x37);
+ haveFirstByte = false;
+ }
+
+ return tempAsciiByte;
+ }
+
+ private void loopUntilByteIsRead(InputStream stream, int byteToRead) throws IOException {
+ int b = 0;
+ do {
+ b = readByte(in);
+ } while (b != byteToRead);
+ }
+
+ private void offerCaddxMessage() throws InterruptedException {
+ logger.trace("Offering received message");
+
+ // Full message received in data byte array
+ CaddxMessage caddxMessage = new CaddxMessage(message, true);
+ if (!exchanger.offer(caddxMessage, 3, TimeUnit.SECONDS)) {
+ logger.debug("Offered message was not received");
+ }
+ }
+
+ private void receiveInBinaryProtocol(SerialPortEvent serialPortEvent) {
+ try {
+ // Read the start byte
+ if (!inMessage) // skip until 0x7E
+ {
+ loopUntilByteIsRead(in, 0x7e);
+
+ inMessage = true;
+ messageBufferLength = 0;
+ }
+ logger.trace("CaddxCommunicator.handleBinaryProtocol() Got start byte");
+
+ // Read the message length
+ if (messageBufferLength == 0) {
+ int b = readByte(in);
+ messageBufferLength = b + 2; // add two bytes for the checksum
+ message = new byte[messageBufferLength];
+ messageBufferIndex = 0;
+ }
+ logger.trace("CaddxCommunicator.handleBinaryProtocol() Got message length {}", messageBufferLength);
+
+ // Read the message
+ do {
+ int b = readByte(in);
+ message[messageBufferIndex] = (byte) b;
+
+ if (message[messageBufferIndex] == 0x7D) {
+ unStuff = true;
+ continue;
+ }
+
+ if (unStuff) {
+ message[messageBufferIndex] |= 0x20;
+ unStuff = false;
+ }
+
+ messageBufferIndex++;
+ } while (messageBufferIndex < messageBufferLength);
+
+ // Offer the message
+ offerCaddxMessage();
+
+ logger.trace("CaddxCommunicator.handleBinaryProtocol() Got message {}", message[0]);
+ } catch (EOFException e) {
+ return;
+ } catch (IOException e) {
+ } catch (InterruptedException e) {
+ logger.trace("InterruptedException caught.");
+ Thread.currentThread().interrupt();
+ }
+
+ // Initialize state for a new reception
+ inMessage = false;
+ messageBufferLength = 0;
+ messageBufferIndex = 0;
+ unStuff = false;
+ }
+
+ private void receiveInAsciiProtocol(SerialPortEvent serialPortEvent) {
+ try {
+ // Read the start byte
+ if (!inMessage) {
+ loopUntilByteIsRead(in, 0x0a);
+
+ inMessage = true;
+ haveFirstByte = false;
+ messageBufferLength = 0;
+ }
+ logger.trace("CaddxCommunicator.handleAsciiProtocol() Got start byte");
+
+ // Read the message length
+ if (messageBufferLength == 0) {
+ int b = readAsciiByte(in);
+ messageBufferLength = b + 2; // add 2 bytes for the checksum
+ message = new byte[messageBufferLength];
+ }
+ logger.trace("CaddxCommunicator.handleAsciiProtocol() Got message length {}", messageBufferLength);
+
+ // Read the message
+ do {
+ int b = readAsciiByte(in);
+ message[messageBufferIndex] = (byte) b;
+ messageBufferIndex++;
+ } while (messageBufferIndex < messageBufferLength);
+
+ // Offer the message
+ offerCaddxMessage();
+
+ logger.trace("CaddxCommunicator.handleAsciiProtocol() Got message {}", message[0]);
+ } catch (EOFException e) {
+ return;
+ } catch (IOException e) {
+ } catch (InterruptedException e) {
+ logger.trace("InterruptedException caught.");
+ Thread.currentThread().interrupt();
+ }
+
+ // Initialize state for a new reception
+ inMessage = false;
+ messageBufferLength = 0;
+ messageBufferIndex = 0;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxDirection.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxDirection.java
new file mode 100644
index 0000000000000..d25e77ca91c45
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxDirection.java
@@ -0,0 +1,26 @@
+/**
+ * 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.caddx.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Message Direction enumeration.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum CaddxDirection {
+ IN,
+ OUT
+};
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java
new file mode 100644
index 0000000000000..ca5edefa0caed
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxEvent.java
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.caddx.internal;
+
+import java.util.EventObject;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Event for Receiving API Messages.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxEvent extends EventObject {
+ private static final long serialVersionUID = 1L;
+ private final CaddxMessage caddxMessage;
+ private final @Nullable Integer partition;
+ private final @Nullable Integer zone;
+ private final @Nullable Integer keypad;
+
+ /**
+ * Constructor.
+ *
+ * @param source
+ */
+ public CaddxEvent(CaddxMessage caddxMessage, @Nullable Integer partition, @Nullable Integer zone,
+ @Nullable Integer keypad) {
+ super(caddxMessage);
+
+ this.caddxMessage = caddxMessage;
+ this.partition = partition;
+ this.zone = zone;
+ this.keypad = keypad;
+ }
+
+ /**
+ * Returns the Message event from the Caddx Alarm System.
+ *
+ * @return message
+ */
+ public CaddxMessage getCaddxMessage() {
+ return caddxMessage;
+ }
+
+ public @Nullable Integer getPartition() {
+ return partition;
+ }
+
+ public @Nullable Integer getZone() {
+ return zone;
+ }
+
+ public @Nullable Integer getKeypad() {
+ return keypad;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java
new file mode 100644
index 0000000000000..698f0d8ace8c2
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessage.java
@@ -0,0 +1,411 @@
+/**
+ * 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.caddx.internal;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.util.HexUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A class that represents the Caddx Alarm Messages.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxMessage {
+ private final Logger logger = LoggerFactory.getLogger(CaddxMessage.class);
+ private final CaddxMessageType caddxMessageType;
+ private final Map propertyMap = new HashMap<>();
+ private final Map idMap = new HashMap<>();
+ private final byte[] message;
+ private final boolean hasAcknowledgementFlag;
+ private final byte checksum1In;
+ private final byte checksum2In;
+ private final byte checksum1Calc;
+ private final byte checksum2Calc;
+
+ /**
+ * Constructor.
+ *
+ * @param message
+ * - the message received
+ */
+ public CaddxMessage(byte[] message, boolean withChecksum) {
+ if (withChecksum && message.length < 3) {
+ logger.debug("CaddxMessage: The message should be at least 3 bytes long.");
+ throw new IllegalArgumentException("The message should be at least 3 bytes long");
+ }
+ if (!withChecksum && message.length < 1) {
+ logger.debug("CaddxMessage: The message should be at least 1 byte long.");
+ throw new IllegalArgumentException("The message should be at least 1 byte long");
+ }
+
+ // Received data
+ byte[] msg = message;
+
+ // Fill in the checksum
+ if (withChecksum) {
+ checksum1In = message[message.length - 2];
+ checksum2In = message[message.length - 1];
+ msg = Arrays.copyOf(message, message.length - 2);
+
+ byte[] fletcherSum = fletcher(msg);
+ checksum1Calc = fletcherSum[0];
+ checksum2Calc = fletcherSum[1];
+ } else {
+ byte[] fletcherSum = fletcher(msg);
+ checksum1Calc = fletcherSum[0];
+ checksum2Calc = fletcherSum[1];
+
+ checksum1In = checksum1Calc;
+ checksum2In = checksum2Calc;
+ }
+
+ // Fill in the message
+ this.message = msg;
+
+ // Fill-in the acknowledgement flag
+ if ((message[0] & 0x80) != 0) {
+ hasAcknowledgementFlag = true;
+ message[0] = (byte) (message[0] & 0x7f);
+ } else {
+ hasAcknowledgementFlag = false;
+ }
+
+ // Fill-in the message type
+ CaddxMessageType mt = CaddxMessageType.valueOfMessageType(message[0]);
+ if (mt == null) {
+ throw new IllegalArgumentException("Unknown message");
+ }
+ caddxMessageType = mt;
+
+ // Fill-in the properties
+ processCaddxMessage();
+ }
+
+ public CaddxMessage(CaddxMessageType type, String data) {
+ int length = type.length;
+ String[] tokens = data.split("\\,");
+ if (length != 1 && tokens.length != length - 1) {
+ logger.debug("token.length should be length-1. token.length={}, length={}", tokens.length, length);
+ throw new IllegalArgumentException("CaddxMessage: data has not the correct format.");
+ }
+
+ byte[] msg = new byte[length];
+ msg[0] = (byte) type.number;
+ for (int i = 0; i < length - 1; i++) {
+ msg[i + 1] = (byte) Integer.decode(tokens[i]).intValue();
+ }
+
+ // Fill-in the checksum
+ byte[] fletcherSum = fletcher(msg);
+ checksum1Calc = fletcherSum[0];
+ checksum2Calc = fletcherSum[1];
+ checksum1In = checksum1Calc;
+ checksum2In = checksum2Calc;
+
+ // Fill-in the message
+ this.message = msg;
+
+ // Fill-in the acknowledgement flag
+ if ((message[0] & 0x80) != 0) {
+ hasAcknowledgementFlag = true;
+ message[0] = (byte) (message[0] & 0x7f);
+ } else {
+ hasAcknowledgementFlag = false;
+ }
+
+ // Fill-in the message type
+ this.caddxMessageType = type;
+
+ // Fill-in the properties
+ processCaddxMessage();
+ }
+
+ public byte getChecksum1In() {
+ return checksum1In;
+ }
+
+ public byte getChecksum2In() {
+ return checksum2In;
+ }
+
+ public byte getChecksum1Calc() {
+ return checksum1Calc;
+ }
+
+ public byte getChecksum2Calc() {
+ return checksum2Calc;
+ }
+
+ public CaddxMessageType getCaddxMessageType() {
+ return caddxMessageType;
+ }
+
+ public byte getMessageType() {
+ return message[0];
+ }
+
+ public String getName() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(caddxMessageType.name);
+ switch (caddxMessageType) {
+ case ZONE_STATUS_REQUEST:
+ case ZONE_STATUS_MESSAGE:
+ sb.append(" [Zone: ");
+ sb.append(getPropertyById("zone_number"));
+ sb.append("]");
+ break;
+ case LOG_EVENT_REQUEST:
+ case LOG_EVENT_MESSAGE:
+ sb.append(" [Event: ");
+ sb.append(getPropertyById("panel_log_event_number"));
+ sb.append("]");
+ break;
+ case PARTITION_STATUS_REQUEST:
+ case PARTITION_STATUS_MESSAGE:
+ sb.append(" [Partition: ");
+ sb.append(getPropertyById("partition_number"));
+ sb.append("]");
+ break;
+ default:
+ break;
+ }
+ return sb.toString();
+ }
+
+ public String getPropertyValue(String property) {
+ if (!propertyMap.containsKey(property)) {
+ logger.debug("Message does not contain property [{}]", property);
+ return "";
+ }
+ return propertyMap.get(property);
+ }
+
+ public String getPropertyById(String id) {
+ if (!idMap.containsKey(id)) {
+ logger.debug("Message does not contain id [{}]", id);
+ return "";
+ }
+ return idMap.get(id);
+ }
+
+ public int @Nullable [] getReplyMessageNumbers() {
+ return caddxMessageType.replyMessageNumbers;
+ }
+
+ public CaddxSource getSource() {
+ return getCaddxMessageType().source;
+ }
+
+ public boolean isChecksumCorrect() {
+ return checksum1In == checksum1Calc && checksum2In == checksum2Calc;
+ }
+
+ public boolean isLengthCorrect() {
+ return message.length == caddxMessageType.length;
+ }
+
+ public boolean hasAcknowledgementFlag() {
+ return hasAcknowledgementFlag;
+ }
+
+ public byte[] getMessageFrameBytes(CaddxProtocol protocol) {
+ if (protocol == CaddxProtocol.Binary) {
+ return getMessageFrameBytesInBinary();
+ } else {
+ return getMessageFrameBytesInAscii();
+ }
+ }
+
+ public byte[] getMessageBytes() {
+ return message;
+ }
+
+ /**
+ * Returns a string representation of a CaddxMessage.
+ *
+ * @return CaddxMessage string
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+
+ CaddxMessageType mt = CaddxMessageType.valueOfMessageType(message[0]);
+ if (mt == null) {
+ return "Unknown message type";
+ }
+
+ sb.append("Message: ");
+ sb.append(String.format("%2s", Integer.toHexString(message[0])));
+ sb.append(" ");
+ sb.append(mt.name);
+ sb.append(System.lineSeparator());
+
+ for (CaddxProperty p : mt.properties) {
+ sb.append("\t").append(p.toString(message));
+ sb.append(System.lineSeparator());
+ }
+
+ return sb.toString();
+ }
+
+ private void putByteInBuffer(ByteBuffer frame, byte b) {
+ if (b == 0x7e) {
+ frame.put((byte) 0x7d);
+ frame.put((byte) 0x5e);
+ } else if (b == 0x7d) {
+ frame.put((byte) 0x7d);
+ frame.put((byte) 0x5d);
+ } else {
+ frame.put(b);
+ }
+ }
+
+ private byte[] getByteBufferArray(ByteBuffer frame) {
+ if (frame.hasArray()) {
+ return frame.array();
+ } else {
+ byte[] byteArray = new byte[frame.capacity()];
+ frame.position(0);
+ frame.get(byteArray);
+ return byteArray;
+ }
+ }
+
+ private byte[] getMessageFrameBytesInBinary() {
+ // Calculate bytes
+ // 1 for the startbyte
+ // 1 for the length
+ // 2 for the checksum
+ // n for the count of 0x7d and 0x7e occurrences in the message and checksum
+ int additional = 4;
+ for (int i = 0; i < message.length; i++) {
+ if (message[i] == 0x7d || message[i] == 0x7e) {
+ additional++;
+ }
+ }
+ if (checksum1Calc == 0x7d || checksum1Calc == 0x7e) {
+ additional++;
+ }
+ if (checksum2Calc == 0x7d || checksum2Calc == 0x7e) {
+ additional++;
+ }
+
+ ByteBuffer frame = ByteBuffer.allocate(message.length + additional);
+
+ // start character
+ frame.put((byte) 0x7e);
+
+ // message length
+ frame.put((byte) message.length);
+
+ // message
+ for (int i = 0; i < message.length; i++) {
+ putByteInBuffer(frame, message[i]);
+ }
+
+ // 1st checksum byte
+ putByteInBuffer(frame, checksum1Calc);
+
+ // 2nd checksum byte
+ putByteInBuffer(frame, checksum2Calc);
+
+ return getByteBufferArray(frame);
+ }
+
+ private byte[] getMessageFrameBytesInAscii() {
+ // Calculate additional bytes
+ // 1 for the start byte
+ // 2 for the length
+ // 4 for the checksum
+ // 1 for the stop byte
+ int additional = 8;
+
+ ByteBuffer frame = ByteBuffer.allocate(2 * message.length + additional);
+
+ // start character
+ frame.put((byte) 0x0a);
+
+ // message length
+ frame.put(HexUtils.byteToHex((byte) message.length));
+
+ // message
+ for (int i = 0; i < message.length; i++) {
+ frame.put(HexUtils.byteToHex(message[i]));
+ }
+
+ // Checksum 1st byte
+ frame.put(HexUtils.byteToHex(checksum1Calc));
+
+ // Checksum 2nd byte
+ frame.put(HexUtils.byteToHex(checksum2Calc));
+
+ // Stop character
+ frame.put((byte) 0x0d);
+
+ return getByteBufferArray(frame);
+ }
+
+ /**
+ * Processes the incoming Caddx message and extracts the information.
+ */
+ private void processCaddxMessage() {
+ // fill the property lookup hashmaps
+ for (CaddxProperty p : caddxMessageType.properties) {
+ propertyMap.put(p.getName(), p.getValue(message));
+ }
+ for (CaddxProperty p : caddxMessageType.properties) {
+ if (!"".equals(p.getId())) {
+ idMap.put(p.getId(), p.getValue(message));
+ }
+ }
+ }
+
+ /**
+ * Calculates the Fletcher checksum of the byte array.
+ *
+ * @param data The input byte array
+ * @return Byte array with two elements. Checksum1 and Checksum2
+ */
+ private byte[] fletcher(byte data[]) {
+ int len = data.length;
+ int sum1 = len, sum2 = len;
+ for (int i = 0; i < len; i++) {
+ int d = data[i] & 0xff;
+ if (0xff - sum1 < d) {
+ sum1 = (sum1 + 1) & 0xff;
+ }
+ sum1 = (sum1 + d) & 0xff;
+ if (sum1 == 0xff) {
+ sum1 = 0;
+ }
+ if (0xff - sum2 < sum1) {
+ sum2 = (sum2 + 1) & 0xff;
+ }
+ sum2 = (sum2 + sum1) & 0xff;
+ if (sum2 == 0xff) {
+ sum2 = 0;
+ }
+ }
+
+ return new byte[] { (byte) sum1, (byte) sum2 };
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java
new file mode 100644
index 0000000000000..c45072a95a16a
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxMessageType.java
@@ -0,0 +1,1349 @@
+/**
+ * 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.caddx.internal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * All the panel message types
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum CaddxMessageType {
+
+ INTERFACE_CONFIGURATION_MESSAGE(0x01, null, 12, "Interface Configuration Message",
+ "This message will contain the firmware version number and other information about features currently enabled. It will be sent each time the unit is reset or programmed.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ new CaddxProperty("panel_firmware_version", 2, 4, 0, 0, CaddxPropertyType.STRING, "Firmware version",
+ false),
+
+ // Byte 6 Supported transition message flags (1)
+ new CaddxProperty("panel_interface_configuration_message", 6, 1, 1, 1, CaddxPropertyType.BIT,
+ "Interface Configuration Message", false),
+ new CaddxProperty("panel_zone_status_message", 6, 1, 4, 1, CaddxPropertyType.BIT, "Zone Status Message",
+ false),
+ new CaddxProperty("panel_zones_snapshot_message", 6, 1, 5, 1, CaddxPropertyType.BIT,
+ "Zones Snapshot Message", false),
+ new CaddxProperty("panel_partition_status_message", 6, 1, 6, 1, CaddxPropertyType.BIT,
+ "Partition Status Message", false),
+ new CaddxProperty("panel_partitions_snapshot_message", 6, 1, 7, 1, CaddxPropertyType.BIT,
+ "Partitions Snapshot Message", false),
+
+ // Byte 7 Supported transition message flags (2)
+ new CaddxProperty("panel_system_status_message", 7, 1, 0, 1, CaddxPropertyType.BIT, "System Status Message",
+ false),
+ new CaddxProperty("panel_x10_message_received", 7, 1, 1, 1, CaddxPropertyType.BIT, "X-10 Message Received",
+ false),
+ new CaddxProperty("panel_log_event_message", 7, 1, 2, 1, CaddxPropertyType.BIT, "Log Event Message", false),
+ new CaddxProperty("panel_keypad_message_received", 7, 1, 3, 1, CaddxPropertyType.BIT,
+ "Keypad Message Received", false),
+
+ // Byte 8 Supported request / command flags (1)
+ new CaddxProperty("panel_interface_configuration_request", 8, 1, 1, 1, CaddxPropertyType.BIT,
+ "Interface Configuration Request", false),
+ new CaddxProperty("panel_zone_name_request", 8, 1, 3, 1, CaddxPropertyType.BIT, "Zone Name Request", false),
+ new CaddxProperty("panel_zone_status_request", 8, 1, 4, 1, CaddxPropertyType.BIT, "Zone Status Request",
+ false),
+ new CaddxProperty("panel_zones_snapshot_request", 8, 1, 5, 1, CaddxPropertyType.BIT,
+ "Zones Snapshot Request", false),
+ new CaddxProperty("panel_partition_status_request", 8, 1, 6, 1, CaddxPropertyType.BIT,
+ "Partition Status Request", false),
+ new CaddxProperty("panel_partitions_snapshot_request", 8, 1, 7, 1, CaddxPropertyType.BIT,
+ "Partitions Snapshot Request", false),
+
+ // Byte 9 Supported request / command flags (2)
+ new CaddxProperty("panel_system_status_request", 9, 1, 0, 1, CaddxPropertyType.BIT, "System Status Request",
+ false),
+ new CaddxProperty("panel_send_x10_message", 9, 1, 1, 1, CaddxPropertyType.BIT, "Send X-10 Message", false),
+ new CaddxProperty("panel_log_event_request", 9, 1, 2, 1, CaddxPropertyType.BIT, "Log Event Request", false),
+ new CaddxProperty("panel_send_keypad_text_message", 9, 1, 3, 1, CaddxPropertyType.BIT,
+ "Send Keypad Text Message", false),
+ new CaddxProperty("panel_keypad_terminal_mode_request", 9, 1, 4, 1, CaddxPropertyType.BIT,
+ "Keypad Terminal Mode Request", false),
+
+ // Byte 10 Supported request / command flags (3)
+ new CaddxProperty("panel_program_data_request", 10, 1, 0, 1, CaddxPropertyType.BIT, "Program Data Request",
+ false),
+ new CaddxProperty("panel_program_data_command", 10, 1, 1, 1, CaddxPropertyType.BIT, "Program Data Command",
+ false),
+ new CaddxProperty("panel_user_information_request_with_pin", 10, 1, 2, 1, CaddxPropertyType.BIT,
+ "User Information Request with PIN", false),
+ new CaddxProperty("panel_user_information_request_without_pin", 10, 1, 3, 1, CaddxPropertyType.BIT,
+ "User Information Request without PIN", false),
+ new CaddxProperty("panel_set_user_code_command_with_pin", 10, 1, 4, 1, CaddxPropertyType.BIT,
+ "Set User Code Command with PIN", false),
+ new CaddxProperty("panel_set_user_code_command_without_pin", 10, 1, 5, 1, CaddxPropertyType.BIT,
+ "Set User Code Command without PIN", false),
+ new CaddxProperty("panel_set_user_authorization_command_with_pin", 10, 1, 6, 1, CaddxPropertyType.BIT,
+ "Set User Authorization Command with PIN", false),
+ new CaddxProperty("panel_set_user_authorization_command_without_pin", 10, 1, 7, 1, CaddxPropertyType.BIT,
+ "Set User Authorization Command without PIN", false),
+
+ // Byte 11 Supported request / command flags (4)
+ new CaddxProperty("panel_store_communication_event_command", 11, 1, 2, 1, CaddxPropertyType.BIT,
+ "Store Communication Event Command", false),
+ new CaddxProperty("panel_set_clock_calendar_command", 11, 1, 3, 1, CaddxPropertyType.BIT,
+ "Set Clock / Calendar Command", false),
+ new CaddxProperty("panel_primary_keypad_function_with_pin", 11, 1, 4, 1, CaddxPropertyType.BIT,
+ "Primary Keypad Function with PIN", false),
+ new CaddxProperty("panel_primary_keypad_function_without_pin", 11, 1, 5, 1, CaddxPropertyType.BIT,
+ "Primary Keypad Function without PIN", false),
+ new CaddxProperty("panel_secondary_keypad_function", 11, 1, 6, 1, CaddxPropertyType.BIT,
+ "Secondary Keypad Function", false),
+ new CaddxProperty("panel_zone_bypass_toggle", 11, 1, 7, 1, CaddxPropertyType.BIT, "Zone Bypass Toggle",
+ false)),
+
+ ZONE_NAME_MESSAGE(0x03, null, 18, "Zone Name Message",
+ "This message will contain the 16-character name for the zone number that was requested (via Zone Name Request (23h)).",
+ CaddxDirection.IN, CaddxSource.ZONE,
+
+ // Properties
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ new CaddxProperty("zone_number", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone number", false),
+ new CaddxProperty("zone_name", 3, 16, 0, 0, CaddxPropertyType.STRING, "Zone name", false)),
+
+ ZONE_STATUS_MESSAGE(0x04, null, 8, "Zone Status Message",
+ "This message will contain all information relevant to a zone in the system.", CaddxDirection.IN,
+ CaddxSource.ZONE,
+
+ // Properties
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ new CaddxProperty("zone_number", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone number", false),
+
+ // Byte 3 Partition mask
+ new CaddxProperty("zone_partition1", 3, 1, 0, 1, CaddxPropertyType.BIT, "Partition 1 enable", false),
+ new CaddxProperty("zone_partition2", 3, 1, 1, 1, CaddxPropertyType.BIT, "Partition 2 enable", false),
+ new CaddxProperty("zone_partition3", 3, 1, 2, 1, CaddxPropertyType.BIT, "Partition 3 enable", false),
+ new CaddxProperty("zone_partition4", 3, 1, 3, 1, CaddxPropertyType.BIT, "Partition 4 enable", false),
+ new CaddxProperty("zone_partition5", 3, 1, 4, 1, CaddxPropertyType.BIT, "Partition 5 enable", false),
+ new CaddxProperty("zone_partition6", 3, 1, 5, 1, CaddxPropertyType.BIT, "Partition 6 enable", false),
+ new CaddxProperty("zone_partition7", 3, 1, 6, 1, CaddxPropertyType.BIT, "Partition 7 enable", false),
+ new CaddxProperty("zone_partition8", 3, 1, 7, 1, CaddxPropertyType.BIT, "Partition 8 enable", false),
+
+ // Byte 4 Zone type flags (1)
+ new CaddxProperty("zone_fire", 4, 1, 0, 1, CaddxPropertyType.BIT, "Fire", false),
+ new CaddxProperty("zone_24hour", 4, 1, 1, 1, CaddxPropertyType.BIT, "24 Hour", false),
+ new CaddxProperty("zone_key_switch", 4, 1, 2, 1, CaddxPropertyType.BIT, "Key-switch", false),
+ new CaddxProperty("zone_follower", 4, 1, 3, 1, CaddxPropertyType.BIT, "Follower", false),
+ new CaddxProperty("zone_entry_exit_delay_1", 4, 1, 4, 1, CaddxPropertyType.BIT, "Entry / exit delay 1",
+ false),
+ new CaddxProperty("zone_entry_exit_delay_2", 4, 1, 5, 1, CaddxPropertyType.BIT, "Entry / exit delay 2",
+ false),
+ new CaddxProperty("zone_interior", 4, 1, 6, 1, CaddxPropertyType.BIT, "Interior", false),
+ new CaddxProperty("zone_local_only", 4, 1, 7, 1, CaddxPropertyType.BIT, "Local only", false),
+
+ // Byte 5 Zone type flags (2)
+ new CaddxProperty("zone_keypad_sounder", 5, 1, 0, 1, CaddxPropertyType.BIT, "Keypad sounder", false),
+ new CaddxProperty("zone_yelping_siren", 5, 1, 1, 1, CaddxPropertyType.BIT, "Yelping siren", false),
+ new CaddxProperty("zone_steady_siren", 5, 1, 2, 1, CaddxPropertyType.BIT, "Steady siren", false),
+ new CaddxProperty("zone_chime", 5, 1, 3, 1, CaddxPropertyType.BIT, "Chime", false),
+ new CaddxProperty("zone_bypassable", 5, 1, 4, 1, CaddxPropertyType.BIT, "Bypassable", false),
+ new CaddxProperty("zone_group_bypassable", 5, 1, 5, 1, CaddxPropertyType.BIT, "Group bypassable", false),
+ new CaddxProperty("zone_force_armable", 5, 1, 6, 1, CaddxPropertyType.BIT, "Force armable", false),
+ new CaddxProperty("zone_entry_guard", 5, 1, 7, 1, CaddxPropertyType.BIT, "Entry guard", false),
+
+ // Byte 6 Zone type flags (3)
+ new CaddxProperty("zone_fast_loop_response", 6, 1, 0, 1, CaddxPropertyType.BIT, "Fast loop response",
+ false),
+ new CaddxProperty("zone_double_eol_tamper", 6, 1, 1, 1, CaddxPropertyType.BIT, "Double EOL tamper", false),
+ new CaddxProperty("zone_type_trouble", 6, 1, 2, 1, CaddxPropertyType.BIT, "Trouble", false),
+ new CaddxProperty("zone_cross_zone", 6, 1, 3, 1, CaddxPropertyType.BIT, "Cross zone", false),
+ new CaddxProperty("zone_dialer_delay", 6, 1, 4, 1, CaddxPropertyType.BIT, "Dialer delay", false),
+ new CaddxProperty("zone_swinger_shutdown", 6, 1, 5, 1, CaddxPropertyType.BIT, "Swinger shutdown", false),
+ new CaddxProperty("zone_restorable", 6, 1, 6, 1, CaddxPropertyType.BIT, "Restorable", false),
+ new CaddxProperty("zone_listen_in", 6, 1, 7, 1, CaddxPropertyType.BIT, "Listen in", false),
+
+ // Byte 7 Zone condition flags (1)
+ new CaddxProperty("zone_faulted", 7, 1, 0, 1, CaddxPropertyType.BIT, "Faulted (or delayed trip)", false),
+ new CaddxProperty("zone_tampered", 7, 1, 1, 1, CaddxPropertyType.BIT, "Tampered", false),
+ new CaddxProperty("zone_trouble", 7, 1, 2, 1, CaddxPropertyType.BIT, "Trouble", false),
+ new CaddxProperty("zone_bypassed", 7, 1, 3, 1, CaddxPropertyType.BIT, "Bypassed", false),
+ new CaddxProperty("zone_inhibited", 7, 1, 4, 1, CaddxPropertyType.BIT, "Inhibited (force armed)", false),
+ new CaddxProperty("zone_low_battery", 7, 1, 5, 1, CaddxPropertyType.BIT, "Low battery", false),
+ new CaddxProperty("zone_loss_of_supervision", 7, 1, 6, 1, CaddxPropertyType.BIT, "Loss of supervision",
+ false),
+
+ // Byte 8 Zone condition flags (2)
+ new CaddxProperty("zone_alarm_memory", 8, 1, 0, 1, CaddxPropertyType.BIT, "Alarm memory", false),
+ new CaddxProperty("zone_bypass_memory", 8, 1, 1, 1, CaddxPropertyType.BIT, "Bypass memory", false)),
+
+ ZONES_SNAPSHOT_MESSAGE(0x05, null, 10, "Zones Snapshot Message",
+ "This message will contain an abbreviated set of information for any group of 16 zones possible on the system. (A zone offset number will set the range of zones)",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ new CaddxProperty("zone_offset", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone offset (0= start at zone 1)",
+ false),
+
+ // Byte 3 Zone 1 & 2 (+offset) status flags
+ new CaddxProperty("", 3, 1, 0, 1, CaddxPropertyType.BIT, "Zone 1 faulted (or delayed trip)", false),
+ new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT, "Zone 1 bypass (or inhibited)", false),
+ new CaddxProperty("zone_1_trouble", 3, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 1 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT, "Zone 1 alarm memory", false),
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Zone 2 faulted (or delayed trip)", false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Zone 2 bypass (or inhibited)", false),
+ new CaddxProperty("zone_2_trouble", 3, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 2 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Zone 2 alarm memory", false),
+
+ // Byte 4 Zone 3 & 4 status flags (see byte 3)
+ new CaddxProperty("", 4, 1, 0, 1, CaddxPropertyType.BIT, "Zone 3 faulted (or delayed trip)", false),
+ new CaddxProperty("", 4, 1, 1, 1, CaddxPropertyType.BIT, "Zone 3 bypass (or inhibited)", false),
+ new CaddxProperty("zone_3_trouble", 4, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 3 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 4, 1, 3, 1, CaddxPropertyType.BIT, "Zone 3 alarm memory", false),
+ new CaddxProperty("", 4, 1, 4, 1, CaddxPropertyType.BIT, "Zone 4 faulted (or delayed trip)", false),
+ new CaddxProperty("", 4, 1, 5, 1, CaddxPropertyType.BIT, "Zone 4 bypass (or inhibited)", false),
+ new CaddxProperty("zone_4_trouble", 4, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 4 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 4, 1, 7, 1, CaddxPropertyType.BIT, "Zone 4 alarm memory", false),
+
+ // Byte 5 Zone 5 & 6 status flags (see byte 3)
+ new CaddxProperty("", 5, 1, 0, 1, CaddxPropertyType.BIT, "Zone 5 faulted (or delayed trip)", false),
+ new CaddxProperty("", 5, 1, 1, 1, CaddxPropertyType.BIT, "Zone 5 bypass (or inhibited)", false),
+ new CaddxProperty("zone_5_trouble", 5, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 5 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 5, 1, 3, 1, CaddxPropertyType.BIT, "Zone 5 alarm memory", false),
+ new CaddxProperty("", 5, 1, 4, 1, CaddxPropertyType.BIT, "Zone 6 faulted (or delayed trip)", false),
+ new CaddxProperty("", 5, 1, 5, 1, CaddxPropertyType.BIT, "Zone 6 bypass (or inhibited)", false),
+ new CaddxProperty("zone_6_trouble", 5, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 6 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 5, 1, 7, 1, CaddxPropertyType.BIT, "Zone 6 alarm memory", false),
+
+ // Byte 6 Zone 7 & 8 status flags (see byte 3)
+ new CaddxProperty("", 6, 1, 0, 1, CaddxPropertyType.BIT, "Zone 7 faulted (or delayed trip)", false),
+ new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT, "Zone 7 bypass (or inhibited)", false),
+ new CaddxProperty("zone_7_trouble", 6, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 7 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT, "Zone 7 alarm memory", false),
+ new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT, "Zone 8 faulted (or delayed trip)", false),
+ new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT, "Zone 8 bypass (or inhibited)", false),
+ new CaddxProperty("zone_8_trouble", 6, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 8 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT, "Zone 8 alarm memory", false),
+
+ // Byte 7 Zone 9 & 10 status flags (see byte 3)
+ new CaddxProperty("", 7, 1, 0, 1, CaddxPropertyType.BIT, "Zone 9 faulted (or delayed trip)", false),
+ new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "Zone 9 bypass (or inhibited)", false),
+ new CaddxProperty("zone_9_trouble", 7, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 9 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Zone 9 alarm memory", false),
+ new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Zone 10 faulted (or delayed trip)", false),
+ new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Zone 10 bypass (or inhibited)", false),
+ new CaddxProperty("zone_10_trouble", 7, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 10 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 7, 1, 7, 1, CaddxPropertyType.BIT, "Zone 10 alarm memory", false),
+
+ // Byte 8 Zone 11 & 12 status flags (see byte 3)
+ new CaddxProperty("", 8, 1, 0, 1, CaddxPropertyType.BIT, "Zone 11 faulted (or delayed trip)", false),
+ new CaddxProperty("", 8, 1, 1, 1, CaddxPropertyType.BIT, "Zone 11 bypass (or inhibited)", false),
+ new CaddxProperty("zone_11_trouble", 8, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 11 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 8, 1, 3, 1, CaddxPropertyType.BIT, "Zone 11 alarm memory", false),
+ new CaddxProperty("", 8, 1, 4, 1, CaddxPropertyType.BIT, "Zone 12 faulted (or delayed trip)", false),
+ new CaddxProperty("", 8, 1, 5, 1, CaddxPropertyType.BIT, "Zone 12 bypass (or inhibited)", false),
+ new CaddxProperty("zone_12_trouble", 8, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 12 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 8, 1, 7, 1, CaddxPropertyType.BIT, "Zone 12 alarm memory", false),
+
+ // Byte 9 Zone 13 & 14 status flags (see byte 3)
+ new CaddxProperty("", 9, 1, 0, 1, CaddxPropertyType.BIT, "Zone 13 faulted (or delayed trip)", false),
+ new CaddxProperty("", 9, 1, 1, 1, CaddxPropertyType.BIT, "Zone 13 bypass (or inhibited)", false),
+ new CaddxProperty("zone_13_trouble", 9, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 13 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 9, 1, 3, 1, CaddxPropertyType.BIT, "Zone 13 alarm memory", false),
+ new CaddxProperty("", 9, 1, 4, 1, CaddxPropertyType.BIT, "Zone 14 faulted (or delayed trip)", false),
+ new CaddxProperty("", 9, 1, 5, 1, CaddxPropertyType.BIT, "Zone 14 bypass (or inhibited)", false),
+ new CaddxProperty("zone_14_trouble", 9, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 14 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 9, 1, 7, 1, CaddxPropertyType.BIT, "Zone 14 alarm memory", false),
+
+ // Byte 10 Zone 15 & 16 status flags (see byte 3)
+ new CaddxProperty("", 10, 1, 0, 1, CaddxPropertyType.BIT, "Zone 15 faulted (or delayed trip)", false),
+ new CaddxProperty("", 10, 1, 1, 1, CaddxPropertyType.BIT, "Zone 15 bypass (or inhibited)", false),
+ new CaddxProperty("zone_15_trouble", 10, 1, 2, 1, CaddxPropertyType.BIT,
+ "Zone 15 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 10, 1, 3, 1, CaddxPropertyType.BIT, "Zone 15 alarm memory", false),
+ new CaddxProperty("", 10, 1, 4, 1, CaddxPropertyType.BIT, "Zone 16 faulted (or delayed trip)", false),
+ new CaddxProperty("", 10, 1, 5, 1, CaddxPropertyType.BIT, "Zone 16 bypass (or inhibited)", false),
+ new CaddxProperty("zone_16_trouble", 10, 1, 6, 1, CaddxPropertyType.BIT,
+ "Zone 16 trouble (tamper, low battery, or lost)", false),
+ new CaddxProperty("", 10, 1, 7, 1, CaddxPropertyType.BIT, "Zone 16 alarm memory", false)),
+
+ PARTITION_STATUS_MESSAGE(0x06, null, 9, "Partition Status Message",
+ "This message will contain all information relevant to a single partition in the system.",
+ CaddxDirection.IN, CaddxSource.PARTITION,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ new CaddxProperty("partition_number", 2, 1, 0, 0, CaddxPropertyType.INT,
+ "Partition number (0= partition 1)", false),
+
+ // Byte 3 Partition condition flags (1)
+ new CaddxProperty("partition_bypass_code_required", 3, 1, 0, 1, CaddxPropertyType.BIT,
+ "Bypass code required", false),
+ new CaddxProperty("partition_fire_trouble", 3, 1, 1, 1, CaddxPropertyType.BIT, "Fire trouble", false),
+ new CaddxProperty("partition_fire", 3, 1, 2, 1, CaddxPropertyType.BIT, "Fire", false),
+ new CaddxProperty("partition_pulsing_buzzer", 3, 1, 3, 1, CaddxPropertyType.BIT, "Pulsing Buzzer", false),
+ new CaddxProperty("partition_tlm_fault_memory", 3, 1, 4, 1, CaddxPropertyType.BIT, "TLM fault memory",
+ false),
+ new CaddxProperty("partition_armed", 3, 1, 6, 1, CaddxPropertyType.BIT, "Armed", false),
+ new CaddxProperty("partition_instant", 3, 1, 7, 1, CaddxPropertyType.BIT, "Instant", false),
+
+ // Byte 4 Partition condition flags (2)
+ new CaddxProperty("partition_previous_alarm", 4, 1, 0, 1, CaddxPropertyType.BIT, "Previous Alarm", false),
+ new CaddxProperty("partition_siren_on", 4, 1, 1, 1, CaddxPropertyType.BIT, "Siren on", false),
+ new CaddxProperty("partition_steady_siren_on", 4, 1, 2, 1, CaddxPropertyType.BIT, "Steady siren on", false),
+ new CaddxProperty("partition_alarm_memory", 4, 1, 3, 1, CaddxPropertyType.BIT, "Alarm memory", false),
+ new CaddxProperty("partition_tamper", 4, 1, 4, 1, CaddxPropertyType.BIT, "Tamper", false),
+ new CaddxProperty("partition_cancel_command_entered", 4, 1, 5, 1, CaddxPropertyType.BIT,
+ "Cancel command entered", false),
+ new CaddxProperty("partition_code_entered", 4, 1, 6, 1, CaddxPropertyType.BIT, "Code entered", false),
+ new CaddxProperty("partition_cancel_pending", 4, 1, 7, 1, CaddxPropertyType.BIT, "Cancel pending", false),
+
+ // Byte 5 Partition condition flags (3)
+ new CaddxProperty("partition_silent_exit_enabled", 5, 1, 1, 1, CaddxPropertyType.BIT, "Silent exit enabled",
+ false),
+ new CaddxProperty("partition_entryguard", 5, 1, 2, 1, CaddxPropertyType.BIT, "Entryguard (stay mode)",
+ false),
+ new CaddxProperty("partition_chime_mode_on", 5, 1, 3, 1, CaddxPropertyType.BIT, "Chime mode on", false),
+ new CaddxProperty("partition_entry", 5, 1, 4, 1, CaddxPropertyType.BIT, "Entry", false),
+ new CaddxProperty("partition_delay_expiration_warning", 5, 1, 5, 1, CaddxPropertyType.BIT,
+ "Delay expiration warning", false),
+ new CaddxProperty("partition_exit1", 5, 1, 6, 1, CaddxPropertyType.BIT, "Exit1", false),
+ new CaddxProperty("partition_exit2", 5, 1, 7, 1, CaddxPropertyType.BIT, "Exit2", false),
+
+ // Byte 6 Partition condition flags (4)
+ new CaddxProperty("partition_led_extinguish", 6, 1, 0, 1, CaddxPropertyType.BIT, "LED extinguish", false),
+ new CaddxProperty("partition_cross_timing", 6, 1, 1, 1, CaddxPropertyType.BIT, "Cross timing", false),
+ new CaddxProperty("partition_recent_closing_being_timed", 6, 1, 2, 1, CaddxPropertyType.BIT,
+ "Recent closing being timed", false),
+ new CaddxProperty("partition_exit_error_triggered", 6, 1, 4, 1, CaddxPropertyType.BIT,
+ "Exit error triggered", false),
+ new CaddxProperty("partition_auto_home_inhibited", 6, 1, 5, 1, CaddxPropertyType.BIT, "Auto home inhibited",
+ false),
+ new CaddxProperty("partition_sensor_low_battery", 6, 1, 6, 1, CaddxPropertyType.BIT, "Sensor low battery",
+ false),
+ new CaddxProperty("partition_sensor_lost_supervision", 6, 1, 7, 1, CaddxPropertyType.BIT,
+ "Sensor lost supervision", false),
+
+ new CaddxProperty("", 7, 1, 0, 0, CaddxPropertyType.INT, "Last user number", false),
+
+ // Byte 8 Partition condition flags (5)
+ new CaddxProperty("partition_zone_bypassed", 8, 1, 0, 1, CaddxPropertyType.BIT, "Zone bypassed", false),
+ new CaddxProperty("partition_force_arm_triggered_by_auto_arm", 8, 1, 1, 1, CaddxPropertyType.BIT,
+ "Force arm triggered by auto arm", false),
+ new CaddxProperty("partition_ready_to_arm", 8, 1, 2, 1, CaddxPropertyType.BIT, "Ready to arm", false),
+ new CaddxProperty("partition_ready_to_force_arm", 8, 1, 3, 1, CaddxPropertyType.BIT, "Ready to force arm",
+ false),
+ new CaddxProperty("partition_valid_pin_accepted", 8, 1, 4, 1, CaddxPropertyType.BIT, "Valid PIN accepted",
+ false),
+ new CaddxProperty("partition_chime_on", 8, 1, 5, 1, CaddxPropertyType.BIT, "Chime on (sounding)", false),
+ new CaddxProperty("partition_error_beep", 8, 1, 6, 1, CaddxPropertyType.BIT, "Error beep (triple beep)",
+ false),
+ new CaddxProperty("partition_tone_on", 8, 1, 7, 1, CaddxPropertyType.BIT, "Tone on (activation tone)",
+ false),
+
+ // Byte 9 Partition condition flags (6)
+ new CaddxProperty("partition_entry1", 9, 1, 0, 1, CaddxPropertyType.BIT, "Entry 1", false),
+ new CaddxProperty("partition_open_period", 9, 1, 1, 1, CaddxPropertyType.BIT, "Open period", false),
+ new CaddxProperty("partition_alarm_sent_using_phone_number_1", 9, 1, 2, 1, CaddxPropertyType.BIT,
+ "Alarm sent using phone number 1", false),
+ new CaddxProperty("partition_alarm_sent_using_phone_number_2", 9, 1, 3, 1, CaddxPropertyType.BIT,
+ "Alarm sent using phone number 2", false),
+ new CaddxProperty("partition_alarm_sent_using_phone_number_3", 9, 1, 4, 1, CaddxPropertyType.BIT,
+ "Alarm sent using phone number 3", false),
+ new CaddxProperty("partition_cancel_report_is_in_the_stack", 9, 1, 5, 1, CaddxPropertyType.BIT,
+ "Cancel report is in the stack", false),
+ new CaddxProperty("partition_keyswitch_armed", 9, 1, 6, 1, CaddxPropertyType.BIT, "Keyswitch armed", false),
+ new CaddxProperty("partition_delay_trip_in_progress", 9, 1, 7, 1, CaddxPropertyType.BIT,
+ "Delay Trip in progress (common zone)", false)),
+
+ PARTITIONS_SNAPSHOT_MESSAGE(0x07, null, 9, "Partitions Snapshot Message",
+ "This message will contain an abbreviated set of information for all 8 partitions on the system.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 Partition 1 condition flags
+ new CaddxProperty("partition_1_valid", 2, 1, 0, 1, CaddxPropertyType.BIT, "Partition 1 valid partition",
+ false),
+ new CaddxProperty("", 2, 1, 1, 1, CaddxPropertyType.BIT, "Partition 1 ready", false),
+ new CaddxProperty("", 2, 1, 2, 1, CaddxPropertyType.BIT, "Partition 1 armed", false),
+ new CaddxProperty("", 2, 1, 3, 1, CaddxPropertyType.BIT, "Partition 1 stay mode", false),
+ new CaddxProperty("", 2, 1, 4, 1, CaddxPropertyType.BIT, "Partition 1 chime mode", false),
+ new CaddxProperty("", 2, 1, 5, 1, CaddxPropertyType.BIT, "Partition 1 any entry delay", false),
+ new CaddxProperty("", 2, 1, 6, 1, CaddxPropertyType.BIT, "Partition 1 any exit delay", false),
+ new CaddxProperty("", 2, 1, 7, 1, CaddxPropertyType.BIT, "Partition 1 previous alarm", false),
+
+ // Byte 3 Partition 2 condition flags
+ new CaddxProperty("partition_2_valid", 3, 1, 0, 1, CaddxPropertyType.BIT, "Partition 2 valid partition",
+ false),
+ new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT, "Partition 2 ready", false),
+ new CaddxProperty("", 3, 1, 2, 1, CaddxPropertyType.BIT, "Partition 2 armed", false),
+ new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT, "Partition 2 stay mode", false),
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Partition 2 chime mode", false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Partition 2 any entry delay", false),
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT, "Partition 2 any exit delay", false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Partition 2 previous alarm", false),
+
+ // Byte 4 Partition 3 condition flags
+ new CaddxProperty("partition_3_valid", 4, 1, 0, 1, CaddxPropertyType.BIT, "Partition 3 valid partition",
+ false),
+ new CaddxProperty("", 4, 1, 1, 1, CaddxPropertyType.BIT, "Partition 3 ready", false),
+ new CaddxProperty("", 4, 1, 2, 1, CaddxPropertyType.BIT, "Partition 3 armed", false),
+ new CaddxProperty("", 4, 1, 3, 1, CaddxPropertyType.BIT, "Partition 3 stay mode", false),
+ new CaddxProperty("", 4, 1, 4, 1, CaddxPropertyType.BIT, "Partition 3 chime mode", false),
+ new CaddxProperty("", 4, 1, 5, 1, CaddxPropertyType.BIT, "Partition 3 any entry delay", false),
+ new CaddxProperty("", 4, 1, 6, 1, CaddxPropertyType.BIT, "Partition 3 any exit delay", false),
+ new CaddxProperty("", 4, 1, 7, 1, CaddxPropertyType.BIT, "Partition 3 previous alarm", false),
+
+ // Byte 5 Partition 4 condition flags
+ new CaddxProperty("partition_4_valid", 5, 1, 0, 1, CaddxPropertyType.BIT, "Partition 4 valid partition",
+ false),
+ new CaddxProperty("", 5, 1, 1, 1, CaddxPropertyType.BIT, "Partition 4 ready", false),
+ new CaddxProperty("", 5, 1, 2, 1, CaddxPropertyType.BIT, "Partition 4 armed", false),
+ new CaddxProperty("", 5, 1, 3, 1, CaddxPropertyType.BIT, "Partition 4 stay mode", false),
+ new CaddxProperty("", 5, 1, 4, 1, CaddxPropertyType.BIT, "Partition 4 chime mode", false),
+ new CaddxProperty("", 5, 1, 5, 1, CaddxPropertyType.BIT, "Partition 4 any entry delay", false),
+ new CaddxProperty("", 5, 1, 6, 1, CaddxPropertyType.BIT, "Partition 4 any exit delay", false),
+ new CaddxProperty("", 5, 1, 7, 1, CaddxPropertyType.BIT, "Partition 4 previous alarm", false),
+
+ // Byte 6 Partition 5 condition flags
+ new CaddxProperty("partition_5_valid", 6, 1, 0, 1, CaddxPropertyType.BIT, "Partition 5 valid partition",
+ false),
+ new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT, "Partition 5 ready", false),
+ new CaddxProperty("", 6, 1, 2, 1, CaddxPropertyType.BIT, "Partition 5 armed", false),
+ new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT, "Partition 5 stay mode", false),
+ new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT, "Partition 5 chime mode", false),
+ new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT, "Partition 5 any entry delay", false),
+ new CaddxProperty("", 6, 1, 6, 1, CaddxPropertyType.BIT, "Partition 5 any exit delay", false),
+ new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT, "Partition 5 previous alarm", false),
+
+ // Byte 7 Partition 6 condition flags
+ new CaddxProperty("partition_6_valid", 7, 1, 0, 1, CaddxPropertyType.BIT, "Partition 6 valid partition",
+ false),
+ new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "Partition 6 ready", false),
+ new CaddxProperty("", 7, 1, 2, 1, CaddxPropertyType.BIT, "Partition 6 armed", false),
+ new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Partition 6 stay mode", false),
+ new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Partition 6 chime mode", false),
+ new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Partition 6 any entry delay", false),
+ new CaddxProperty("", 7, 1, 6, 1, CaddxPropertyType.BIT, "Partition 6 any exit delay", false),
+ new CaddxProperty("", 7, 1, 7, 1, CaddxPropertyType.BIT, "Partition 6 previous alarm", false),
+
+ // Byte 8 Partition 7 condition flags
+ new CaddxProperty("partition_7_valid", 8, 1, 0, 1, CaddxPropertyType.BIT, "Partition 7 valid partition",
+ false),
+ new CaddxProperty("", 8, 1, 1, 1, CaddxPropertyType.BIT, "Partition 7 ready", false),
+ new CaddxProperty("", 8, 1, 2, 1, CaddxPropertyType.BIT, "Partition 7 armed", false),
+ new CaddxProperty("", 8, 1, 3, 1, CaddxPropertyType.BIT, "Partition 7 stay mode", false),
+ new CaddxProperty("", 8, 1, 4, 1, CaddxPropertyType.BIT, "Partition 7 chime mode", false),
+ new CaddxProperty("", 8, 1, 5, 1, CaddxPropertyType.BIT, "Partition 7 any entry delay", false),
+ new CaddxProperty("", 8, 1, 6, 1, CaddxPropertyType.BIT, "Partition 7 any exit delay", false),
+ new CaddxProperty("", 8, 1, 7, 1, CaddxPropertyType.BIT, "Partition 7 previous alarm", false),
+
+ // Byte 9 Partition 8 condition flags
+ new CaddxProperty("partition_8_valid", 9, 1, 0, 1, CaddxPropertyType.BIT, "Partition 8 valid partition",
+ false),
+ new CaddxProperty("", 9, 1, 1, 1, CaddxPropertyType.BIT, "Partition 8 ready", false),
+ new CaddxProperty("", 9, 1, 2, 1, CaddxPropertyType.BIT, "Partition 8 armed", false),
+ new CaddxProperty("", 9, 1, 3, 1, CaddxPropertyType.BIT, "Partition 8 stay mode", false),
+ new CaddxProperty("", 9, 1, 4, 1, CaddxPropertyType.BIT, "Partition 8 chime mode", false),
+ new CaddxProperty("", 9, 1, 5, 1, CaddxPropertyType.BIT, "Partition 8 any entry delay", false),
+ new CaddxProperty("", 9, 1, 6, 1, CaddxPropertyType.BIT, "Partition 8 any exit delay", false),
+ new CaddxProperty("", 9, 1, 8, 1, CaddxPropertyType.BIT, "Partition 8 previous alarm", false)),
+
+ SYSTEM_STATUS_MESSAGE(0x08, null, 12, "System Status Message",
+ "This message will contain all information relevant to the entire system.", CaddxDirection.IN,
+ CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Panel ID number", false),
+
+ // Byte 3
+ new CaddxProperty("", 3, 1, 0, 1, CaddxPropertyType.BIT, "Line seizure", false),
+ new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT, "Off hook", false),
+ new CaddxProperty("", 3, 1, 2, 1, CaddxPropertyType.BIT, "Initial handshake received", false),
+ new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT, "Download in progress", false),
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Dialer delay in progress", false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Using backup phone", false),
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT, "Listen in active", false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Two way lockout", false),
+
+ // Byte 4
+ new CaddxProperty("", 4, 1, 0, 1, CaddxPropertyType.BIT, "Ground fault", false),
+ new CaddxProperty("", 4, 1, 1, 1, CaddxPropertyType.BIT, "Phone fault", false),
+ new CaddxProperty("", 4, 1, 2, 1, CaddxPropertyType.BIT, "Fail to communicate", false),
+ new CaddxProperty("", 4, 1, 3, 1, CaddxPropertyType.BIT, "Fuse fault", false),
+ new CaddxProperty("", 4, 1, 4, 1, CaddxPropertyType.BIT, "Box tamper", false),
+ new CaddxProperty("", 4, 1, 5, 1, CaddxPropertyType.BIT, "Siren tamper / trouble", false),
+ new CaddxProperty("", 4, 1, 6, 1, CaddxPropertyType.BIT, "Low Battery", false),
+ new CaddxProperty("", 4, 1, 7, 1, CaddxPropertyType.BIT, "AC fail", false),
+
+ // Byte 5
+ new CaddxProperty("", 5, 1, 0, 1, CaddxPropertyType.BIT, "Expander box tamper", false),
+ new CaddxProperty("", 5, 1, 1, 1, CaddxPropertyType.BIT, "Expander AC failure", false),
+ new CaddxProperty("", 5, 1, 2, 1, CaddxPropertyType.BIT, "Expander low battery", false),
+ new CaddxProperty("", 5, 1, 3, 1, CaddxPropertyType.BIT, "Expander loss of supervision", false),
+ new CaddxProperty("", 5, 1, 4, 1, CaddxPropertyType.BIT, "Expander auxiliary output over current", false),
+ new CaddxProperty("", 5, 1, 5, 1, CaddxPropertyType.BIT, "Auxiliary communication channel failure", false),
+ new CaddxProperty("", 5, 1, 6, 1, CaddxPropertyType.BIT, "Expander bell fault", false),
+
+ // Byte 6
+ new CaddxProperty("", 6, 1, 0, 1, CaddxPropertyType.BIT, "6 digit PIN enabled", false),
+ new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT, "Programming token in use", false),
+ new CaddxProperty("", 6, 1, 2, 1, CaddxPropertyType.BIT, "PIN required for local download", false),
+ new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT, "Global pulsing buzzer", false),
+ new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT, "Global Siren on", false),
+ new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT, "Global steady siren", false),
+ new CaddxProperty("", 6, 1, 6, 1, CaddxPropertyType.BIT, "Bus device has line seized", false),
+ new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT, "Bus device has requested sniff mode", false),
+
+ // Byte 7
+ new CaddxProperty("", 7, 1, 0, 1, CaddxPropertyType.BIT, "Dynamic battery test", false),
+ new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "AC power on", false),
+ new CaddxProperty("", 7, 1, 2, 1, CaddxPropertyType.BIT, "Low battery memory", false),
+ new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Ground fault memory", false),
+ new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Fire alarm verification being timed", false),
+ new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Smoke power reset", false),
+ new CaddxProperty("", 7, 1, 6, 1, CaddxPropertyType.BIT, "50 Hz line power detected", false),
+ new CaddxProperty("", 7, 1, 7, 1, CaddxPropertyType.BIT, "Timing a high voltage battery charge", false),
+
+ // Byte 8
+ new CaddxProperty("", 8, 1, 0, 1, CaddxPropertyType.BIT, "Communication since last autotest", false),
+ new CaddxProperty("", 8, 1, 1, 1, CaddxPropertyType.BIT, "Power up delay in progress", false),
+ new CaddxProperty("", 8, 1, 2, 1, CaddxPropertyType.BIT, "Walk test mode", false),
+ new CaddxProperty("", 8, 1, 3, 1, CaddxPropertyType.BIT, "Loss of system time", false),
+ new CaddxProperty("", 8, 1, 4, 1, CaddxPropertyType.BIT, "Enroll requested", false),
+ new CaddxProperty("", 8, 1, 5, 1, CaddxPropertyType.BIT, "Test fixture mode", false),
+ new CaddxProperty("", 8, 1, 6, 1, CaddxPropertyType.BIT, "Control shutdown mode", false),
+ new CaddxProperty("", 8, 1, 7, 1, CaddxPropertyType.BIT, "Timing a cancel window", false),
+
+ // Byte 9
+ new CaddxProperty("", 9, 1, 7, 1, CaddxPropertyType.BIT, "Call back in progress", false),
+
+ // Byte 10
+ new CaddxProperty("", 10, 1, 0, 1, CaddxPropertyType.BIT, "Phone line faulted", false),
+ new CaddxProperty("", 10, 1, 1, 1, CaddxPropertyType.BIT, "Voltage present interrupt active", false),
+ new CaddxProperty("", 10, 1, 2, 1, CaddxPropertyType.BIT, "House phone off hook", false),
+ new CaddxProperty("", 10, 1, 3, 1, CaddxPropertyType.BIT, "Phone line monitor enabled", false),
+ new CaddxProperty("", 10, 1, 4, 1, CaddxPropertyType.BIT, "Sniffing", false),
+ new CaddxProperty("", 10, 1, 5, 1, CaddxPropertyType.BIT, "Last read was off hook", false),
+ new CaddxProperty("", 10, 1, 6, 1, CaddxPropertyType.BIT, "Listen in requested", false),
+ new CaddxProperty("", 10, 1, 7, 1, CaddxPropertyType.BIT, "Listen in trigger", false),
+
+ // Byte 11
+ new CaddxProperty("", 11, 1, 0, 1, CaddxPropertyType.BIT, "Valid partition 1", false),
+ new CaddxProperty("", 11, 1, 1, 1, CaddxPropertyType.BIT, "Valid partition 2", false),
+ new CaddxProperty("", 11, 1, 2, 1, CaddxPropertyType.BIT, "Valid partition 3", false),
+ new CaddxProperty("", 11, 1, 3, 1, CaddxPropertyType.BIT, "Valid partition 4", false),
+ new CaddxProperty("", 11, 1, 4, 1, CaddxPropertyType.BIT, "Valid partition 5", false),
+ new CaddxProperty("", 11, 1, 5, 1, CaddxPropertyType.BIT, "Valid partition 6", false),
+ new CaddxProperty("", 11, 1, 6, 1, CaddxPropertyType.BIT, "Valid partition 7", false),
+ new CaddxProperty("", 11, 1, 7, 1, CaddxPropertyType.BIT, "Valid partition 8", false),
+
+ // Byte 12 Communicator stack pointer
+ new CaddxProperty("panel_communicator_stack_pointer", 12, 1, 0, 0, CaddxPropertyType.INT,
+ "Communicator stack pointer", false)),
+
+ X10_MESSAGE_RECEIVED(0x09, null, 4, "X-10 Message Received",
+ "This message contains information about an X-10 command that was requested by any device on the system bus.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "House code (0=house A)", false),
+
+ // Byte 3
+ new CaddxProperty("", 3, 1, 0, 0, CaddxPropertyType.INT, "Unit code (0=unit 1)", false),
+
+ // Byte 4
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "X-10 function code", false)),
+
+ LOG_EVENT_MESSAGE(0x0a, null, 10, "Log Event Message",
+ "This message will contain all information relating to an event in the log memory.", CaddxDirection.IN,
+ CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2
+ new CaddxProperty("panel_log_event_number", 2, 1, 0, 0, CaddxPropertyType.INT,
+ "Event number of this message", false),
+ // Byte 3
+ new CaddxProperty("panel_log_event_size", 3, 1, 0, 0, CaddxPropertyType.INT,
+ "Total log size (number of log entries allowed)", false),
+
+ // Byte 4
+ new CaddxProperty("panel_log_event_type", 4, 1, 0, 7, CaddxPropertyType.INT, "Event type", false),
+ // Bits 0-6 See type definitions in table that follows
+ // Bit 7 Non-reporting event if not set
+
+ // Byte 5
+ new CaddxProperty("panel_log_event_zud", 5, 1, 0, 0, CaddxPropertyType.INT, "Zone / User / Device number",
+ false),
+ // Byte 6
+ new CaddxProperty("panel_log_event_partition", 6, 1, 0, 0, CaddxPropertyType.INT,
+ "Partition number (0=partition 1, if relevant)", false),
+ // Byte 7
+ new CaddxProperty("panel_log_event_month", 7, 1, 0, 0, CaddxPropertyType.INT, "Month (1-12)", false),
+ // Byte 8
+ new CaddxProperty("panel_log_event_day", 8, 1, 0, 0, CaddxPropertyType.INT, "Day (1-31)", false),
+ // Byte 9
+ new CaddxProperty("panel_log_event_hour", 9, 1, 0, 0, CaddxPropertyType.INT, "Hour (0-23)", false),
+ // Byte 10
+ new CaddxProperty("panel_log_event_minute", 10, 1, 0, 0, CaddxPropertyType.INT, "Minute (0-59)", false)),
+
+ KEYPAD_MESSAGE_RECEIVED(0x0b, null, 3, "Keypad Message Received",
+ "This message contains a keystroke from a keypad that is in a Terminal Mode.", CaddxDirection.IN,
+ CaddxSource.KEYPAD,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("keypad_address", 1, 2, 0, 0, CaddxPropertyType.INT, "Keypad address", false),
+
+ // Byte 3
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Key value", false)),
+
+ PROGRAM_DATA_REPLY(0x10, null, 13, "Program Data Reply",
+ "This message will contain a system device’s buss address, logical location, and program data that was previously requested (via Program Data Request (3Ch)).",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Device’s buss address", false),
+
+ // Byte 3 Upper logical location / offset
+ new CaddxProperty("", 3, 1, 0, 3, CaddxPropertyType.INT, "Bits 8-11 of logical location", false),
+ new CaddxProperty("", 3, 1, 4, 4, CaddxPropertyType.INT, "Segment size (0=byte, 1=nibble)", false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Must be 0", false),
+ new CaddxProperty("", 3, 1, 6, 6, CaddxPropertyType.INT, "Segment offset (0-none, 1=8 bytes)", false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Must be 0", false),
+
+ // Byte 4 Bits 0-7 of logical location
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "Bits 0-7 of logical location", false),
+
+ // Byte 5 Location length / data type
+ new CaddxProperty("", 5, 1, 0, 4, CaddxPropertyType.INT, "Number of segments in location (0=1 segment)",
+ false),
+ new CaddxProperty("", 5, 1, 5, 7, CaddxPropertyType.INT,
+ "Data type : 0=Binary 1=Decimal 2=Hexadecimal 3=ASCII 4=unused 5=unused 6=unused 7=unused", false),
+
+ // Byte 6 Data byte
+ new CaddxProperty("", 6, 1, 0, 0, CaddxPropertyType.INT, "Data byte 0", false),
+ // Byte 7 Data byte
+ new CaddxProperty("", 7, 1, 0, 0, CaddxPropertyType.INT, "Data byte 1", false),
+ // Byte 8 Data byte
+ new CaddxProperty("", 8, 1, 0, 0, CaddxPropertyType.INT, "Data byte 2", false),
+ // Byte 9 Data byte
+ new CaddxProperty("", 9, 1, 0, 0, CaddxPropertyType.INT, "Data byte 3", false),
+ // Byte 10 Data byte
+ new CaddxProperty("", 10, 1, 0, 0, CaddxPropertyType.INT, "Data byte 4", false),
+ // Byte 11 Data byte
+ new CaddxProperty("", 11, 1, 0, 0, CaddxPropertyType.INT, "Data byte 5", false),
+ // Byte 12 Data byte
+ new CaddxProperty("", 12, 1, 0, 0, CaddxPropertyType.INT, "Data byte 6", false),
+ // Byte 13 Data byte
+ new CaddxProperty("", 13, 1, 0, 0, CaddxPropertyType.INT, "Data byte 7", false)),
+
+ USER_INFORMATION_REPLY(0x12, null, 7, "User Information Reply",
+ "This message will contain all digits, attributes and partitions for the requested user PIN number that was previously requested (via User Information Request with(out) PIN (32h,33h)).",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "User Number (1=user 1)", false),
+
+ // Byte 3 PIN digits 1 & 2
+ new CaddxProperty("", 3, 1, 0, 3, CaddxPropertyType.INT, "PIN digit 1", false),
+ new CaddxProperty("", 3, 1, 4, 7, CaddxPropertyType.INT, "PIN digit 2", false),
+
+ // Byte 4 PIN digits 3 & 4
+ new CaddxProperty("", 4, 1, 0, 3, CaddxPropertyType.INT, "PIN digit 3", false),
+ new CaddxProperty("", 4, 1, 4, 7, CaddxPropertyType.INT, "PIN digit 4", false),
+
+ // Byte 5 PIN digits 5 & 6
+ new CaddxProperty("", 5, 1, 0, 3, CaddxPropertyType.INT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ new CaddxProperty("", 5, 1, 4, 7, CaddxPropertyType.INT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false),
+
+ // Byte 6* Authority flags
+ new CaddxProperty("", 6, 1, 0, 1, CaddxPropertyType.BIT,
+ "Reserved (if bit 7 is clear) || Output 1 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT,
+ "Arm only (if bit 7 is clear) || Output 2 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 2, 1, CaddxPropertyType.BIT,
+ "Arm only (during close window) (if bit 7 is clear) || Output 3 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT,
+ "Master / program (if bit 7 is clear) || Output 4 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT,
+ "Arm / Disarm (if bit 7 is clear) || Arm / Disarm (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT,
+ "Bypass enable (if bit 7 is clear) || Bypass enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 6, 1, CaddxPropertyType.BIT,
+ "Open / close report enable (if bit 7 is clear) || Open / close report enable (if bit 7 is set)",
+ false),
+ new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT,
+ "Must be a 0 (if bit 7 is clear) || Must be a 1 (if bit 7 is set)", false),
+
+ // Byte 7 Authorized partition(s) mask
+ new CaddxProperty("", 7, 1, 0, 1, CaddxPropertyType.BIT, "Authorized for partition 1", false),
+ new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "Authorized for partition 2", false),
+ new CaddxProperty("", 7, 1, 2, 1, CaddxPropertyType.BIT, "Authorized for partition 3", false),
+ new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Authorized for partition 4", false),
+ new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Authorized for partition 5", false),
+ new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Authorized for partition 6", false),
+ new CaddxProperty("", 7, 1, 6, 1, CaddxPropertyType.BIT, "Authorized for partition 7", false),
+ new CaddxProperty("", 7, 1, 7, 1, CaddxPropertyType.BIT, "Authorized for partition 8", false)),
+
+ REQUEST_FAILED(0x1c, null, 1, "Command / Request Failed",
+ "This message is sent in place of a ‘Positive Acknowledge’ message when a command or request was received properly, but the system was unable to carry out the task correctly. This would normally occur 2.5 seconds after receiving the initial command or request.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ POSITIVE_ACKNOWLEDGE(0x1d, null, 1, "Positive Acknowledge",
+ "This message will acknowledge receipt of a message that had the ‘Acknowledge Required’ flag set in the command byte.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ NEGATIVE_ACKNOWLEDGE(0x1e, null, 1, "Negative Acknowledge",
+ "This message is sent in place of a ‘Positive Acknowledge’ message when the message received was not properly formatted. It will also be sent if an additional message is received before a reply has been returned during the 2.5 second allowable reply period of a previous message. An ‘Implied Negative Acknowledge’ is assumed when no acknowledge is returned with 3 seconds.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ MESSAGE_REJECTED(0x1f, null, 1, "Message Rejected",
+ "This message is sent in place of a ‘Positive Acknowledge’ message when the message was received properly formatted, but not supported or disabled.",
+ CaddxDirection.IN, CaddxSource.PANEL,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ INTERFACE_CONFIGURATION_REQUEST(0x21, new int[] { 0x01, 0x1c, 0x1f }, 1, "Interface Configuration Request",
+ "This request will cause the return of the Interface Configuration Message (01h) containing information about the options selected on the interface.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ ZONE_NAME_REQUEST(0x23, new int[] { 0x03, 0x1c, 0x1f }, 2, "Zone Name Request",
+ "This request will cause the return of the Zone Name Message (03h) for the zone number that was requested.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone number (0= zone 1)", true)),
+
+ ZONE_STATUS_REQUEST(0x24, new int[] { 0x04, 0x1c, 0x1f }, 2, "Zone Status Request",
+ "This request will cause the return of the Zone Status Message (04h) for the zone number that was requested.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("zone_number", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone number (0= zone 1)", true)),
+
+ ZONES_SNAPSHOT_REQUEST(0x25, new int[] { 0x05, 0x1c, 0x1f }, 2, "Zones Snapshot Request",
+ "This request will cause the return of the Zones Snapshot Message (05h) with the group of zones starting at the zone 1 plus the offset value.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone number offset (0= start at zone 1)", true)),
+
+ PARTITION_STATUS_REQUEST(0x26, new int[] { 0x06, 0x1c, 0x1f }, 2, "Partition Status Request",
+ "This request will cause the return of the Partition Status Message (06h) for the partition number that was requested.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("partition_number", 2, 1, 0, 0, CaddxPropertyType.INT,
+ "Partition number (0= partition 1)", true)),
+
+ PARTITIONS_SNAPSHOT_REQUEST(0x27, new int[] { 0x07, 0x1c, 0x1f }, 1, "Partitions Snapshot Request",
+ "This request will cause the return of the Partitions Snapshot Message (07h) containing all partitions.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ SYSTEM_STATUS_REQUEST(0x28, new int[] { 0x08, 0x1c, 0x1f }, 1, "System Status Request",
+ "This request will cause the return of the System Status Message (08h).", CaddxDirection.OUT,
+ CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false)),
+
+ SEND_X_10_MESSAGE(0x29, new int[] { 0x1d, 0x1c, 0x1f }, 4, "Send X-10 Message",
+ "This message will contain information about an X-10 command that should be resent on the system bus.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "House code (0=house A) ", true),
+
+ // Byte 3
+ new CaddxProperty("", 3, 1, 0, 0, CaddxPropertyType.INT, "Unit code (0=unit 1)", true),
+
+ // Byte 4
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "X-10 function code (see table at message # 0Ah)",
+ true)),
+
+ LOG_EVENT_REQUEST(0x2a, new int[] { 0x0a, 0x1c, 0x1f }, 2, "Log Event Request",
+ "This request will cause the return of the Log Event Message (0Ah).", CaddxDirection.OUT, CaddxSource.NONE,
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ new CaddxProperty("panel_log_event_number", 2, 1, 0, 0, CaddxPropertyType.INT, "Event number requested",
+ true)),
+
+ SEND_KEYPAD_TEXT_MESSAGE(0x2b, new int[] { 0x1d, 0x1c, 0x1f }, 12, "Send Keypad Text Message",
+ "This message will contain ASCII text for a specific keypad on the bus that will be displayed during Terminal Mode.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 Keypad address
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Keypad address", false),
+ // Byte 3 Keypad type (0=NX-148e)(all others not supported)
+ new CaddxProperty("", 3, 1, 0, 0, CaddxPropertyType.INT, "Keypad type", false),
+ // Byte 4 Display storage location (0=top left corner
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "Display storage location", false),
+ // Byte 5 ASCII character for location +0
+ new CaddxProperty("", 5, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +0", false),
+ // Byte 6 ASCII character for location +1
+ new CaddxProperty("", 6, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +1", false),
+ // Byte 7 ASCII character for location +2
+ new CaddxProperty("", 7, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +2", false),
+ // Byte 8 ASCII character for location +3
+ new CaddxProperty("", 8, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +3", false),
+ // Byte 9 ASCII character for location +4
+ new CaddxProperty("", 9, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +4", false),
+ // Byte 10 ASCII character for location +5
+ new CaddxProperty("", 10, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +5", false),
+ // Byte 11 ASCII character for location +6
+ new CaddxProperty("", 11, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +6", false),
+ // Byte 12 ASCII character for location +7
+ new CaddxProperty("", 12, 1, 0, 0, CaddxPropertyType.INT, "ASCII character for location +7", false)),
+
+ KEYPAD_TERMINAL_MODE_REQUEST(0x2c, new int[] { 0x1d, 0x1c, 0x1f }, 3, "Keypad Terminal Mode Request",
+ "This message will contain the address of a keypad that should enter a Terminal Mode for the time contained. Only one keypad should be in the Terminal Mode at a time.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 Keypad address
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Keypad address", false),
+ // Byte 3
+ new CaddxProperty("", 3, 1, 0, 0, CaddxPropertyType.INT, "Number of seconds for Terminal Mode", false)),
+
+ PROGRAM_DATA_REQUEST(0x30, new int[] { 0x10, 0x1c, 0x1f }, 4, "Program Data Request",
+ "This message will contain a system device’s buss address and the logical location of program data that will be returned in a Program Data Reply message (10h).",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 Device’s buss address
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Device’s buss address", false),
+ // Byte 3 Upper logical location / offset
+ // Bits 0-3 Bits 8-11 of logical location
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.INT, "Bits 8-11 of logical location", false),
+ // Bits 4,5 Must be 0
+ new CaddxProperty("", 3, 1, 4, 2, CaddxPropertyType.BIT, "Must be 0", false),
+ // Bit 6 Segment offset (0-none, 1=8 bytes)
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT, "Segment offset (0-none, 1=8 bytes)", false),
+ // Bit 7
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Must be 0", false),
+ // Byte 4 Bits 0-7 of logical location
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "Bits 0-7 of logical location", false)),
+
+ PROGRAM_DATA_COMMAND(0x31, new int[] { 0x1d, 0x1c, 0x1f }, 13, "Program Data Command",
+ "This message will contain a system device’s buss address and the logical location where the included data should be stored.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 Device’s buss address
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Device’s buss address", false),
+ // Byte 3 Upper logical location / offset
+ // Bits 0-3 Bits 8-11 of logical location
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.BIT, "Bits 8-11 of logical location", false),
+ // Bit 4 Segment size (0=byte, 1=nibble)
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Segment size (0=byte, 1=nibble)", false),
+ // Bit 5 Must be 1
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Must be 1", false),
+ // Bit 6 Segment offset (0-none, 1=8 bytes)
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT, "Segment offset (0-none, 1=8 bytes)", false),
+ // Bit 7 Must be 0
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Must be 0", false),
+ // Byte 4 Bits 0-7 of logical location
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "Bits 0-7 of logical location", false),
+ // Byte 5 Location length / data type
+ // Bits 0-4 Number of segments in location (0=1 segment)
+ new CaddxProperty("", 5, 1, 0, 5, CaddxPropertyType.BIT, "Number of segments in location (0=1 segment)",
+ false),
+ // Bits 5-7 Data type : 5=unused
+ new CaddxProperty("", 5, 1, 5, 3, CaddxPropertyType.BIT,
+ "Data type: 0=Binary, 1=Decimal, 2=Hexadecimal, 3=ASCII, 4=unused, 5=unused, 6=unused, 7=unused",
+ false),
+ // Byte 6 Data byte 1 to store
+ new CaddxProperty("", 6, 1, 0, 0, CaddxPropertyType.INT, "Data byte 1 to store", false),
+ // Byte 7 Data byte 2 to store
+ new CaddxProperty("", 7, 1, 0, 0, CaddxPropertyType.INT, "Data byte 2 to store", false),
+ // Byte 8 Data byte 3 to store
+ new CaddxProperty("", 8, 1, 0, 0, CaddxPropertyType.INT, "Data byte 3 to store", false),
+ // Byte 9 Data byte 4 to store
+ new CaddxProperty("", 9, 1, 0, 0, CaddxPropertyType.INT, "Data byte 4 to store", false),
+ // Byte 10 Data byte 5 to store
+ new CaddxProperty("", 10, 1, 0, 0, CaddxPropertyType.INT, "Data byte 5 to store", false),
+ // Byte 11 Data byte 6 to store
+ new CaddxProperty("", 11, 1, 0, 0, CaddxPropertyType.INT, "Data byte 6 to store", false),
+ // Byte 12 Data byte 7 to store
+ new CaddxProperty("", 12, 1, 0, 0, CaddxPropertyType.INT, "Data byte 7 to store", false),
+ // Byte 13 Data byte 8 to store
+ new CaddxProperty("", 13, 1, 0, 0, CaddxPropertyType.INT, "Data byte 8 to store", false)),
+
+ USER_INFORMATION_REQUEST_WITH_PIN(0x32, new int[] { 0x12, 0x1c, 0x1f }, 5, "User Information Request with PIN",
+ "This message will contain a user number for which information is being requested and a PIN that will be checked for Master capability before proceeding. The information will be returned in a User Information Reply message (12h).",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 (Master) PIN digits 1 & 2
+ // Bits 0-3 PIN digit 1
+ new CaddxProperty("", 2, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 1", false),
+ // Bits 4-7 PIN digit 2
+ new CaddxProperty("", 2, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 2", false),
+ // Byte 3 (Master) PIN digits 3 & 4
+ // Bits 0-3 PIN digit 3
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 3", false),
+ // Bits 4-7 PIN digit 4
+ new CaddxProperty("", 3, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 4", false),
+ // Byte 4 (Master) PIN digits 5 & 6
+ // Bits 0-3 PIN digit 5 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 4, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ // Bits 4-7 PIN digit 6 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 4, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false),
+ // Byte 5 User number (1=user 1)
+ new CaddxProperty("", 5, 1, 0, 0, CaddxPropertyType.INT, "User number (1=user 1)", false)),
+
+ USER_INFORMATION_REQUEST_WITHOUT_PIN(0x33, new int[] { 0x12, 0x1c, 0x1f }, 2,
+ "User Information Request without PIN",
+ "This message will contain a user number for which information is being requested, no authentication will be performed. The information will be returned in a User Information Reply message (12h).",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 User number (1=user 1)
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "User number (1=user 1)", false)),
+
+ SET_USER_CODE_COMMAND_WITH_PIN(0x34, new int[] { 0x12, 0x1c, 0x1f }, 8, "Set User Code Command with PIN",
+ "This message will contain all digits that should be stored as the new code for the designated User number. A PIN will be checked for Master capability before proceeding. A successful programming of the user code will result in the User Information Reply (12h) returned in place of the acknowledge.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 (Master) PIN digits 1 & 2
+ // Bits 0-3 PIN digit 1
+ new CaddxProperty("", 2, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 1", false),
+ // Bits 4-7 PIN digit 2
+ new CaddxProperty("", 2, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 2", false),
+ // Byte 3 (Master) PIN digits 3 & 4
+ // Bits 0-3 PIN digit 3
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 3", false),
+ // Bits 4-7 PIN digit 4
+ new CaddxProperty("", 3, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 4", false),
+ // Byte 4 (Master) PIN digits 5 & 6
+ // Bits 0-3 PIN digit 5 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 4, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ // Bits 4-7 PIN digit 6 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 4, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false),
+ // Byte 5 User number (1=user 1)
+ new CaddxProperty("", 5, 1, 0, 0, CaddxPropertyType.INT, "User number (1=user 1)", false),
+ // Byte 6 PIN digits 1 & 2
+ // Bits 0-3 PIN digit 1
+ new CaddxProperty("", 6, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 1", false),
+ // Bits 4-7 PIN digit 2
+ new CaddxProperty("", 6, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 2", false),
+ // Byte 7 PIN digits 3 & 4
+ // Bits 0-3 PIN digit 3
+ new CaddxProperty("", 7, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 3", false),
+ // Bits 4-7 PIN digit 4
+ new CaddxProperty("", 7, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 4", false),
+ // Byte 8 PIN digits 5 & 6
+ // Bits 0-3 PIN digit 5 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 8, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ // Bits 4-7 PIN digit 6 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 8, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false)),
+
+ SET_USER_CODE_COMMAND_WITHOUT_PIN(0x35, new int[] { 0x12, 0x1c, 0x1f }, 5, "Set User Code Command without PIN",
+ "This message will contain all digits that should be stored as the new code for the designated User number. No authentication will be performed. A successful programming of the user code will result in the User Information Reply (12h) returned in place of the acknowledge.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+ // Byte 2 User number (1=user 1)
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "User number (1=user 1)", false),
+ // Byte 3 PIN digits 1 & 2
+ // Bits 0-3 PIN digit 1
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 1", false),
+ // Bits 4-7 PIN digit 2
+ new CaddxProperty("", 3, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 2", false),
+ // Byte 4 PIN digits 3 & 4
+ // Bits 0-3 PIN digit 3
+ new CaddxProperty("", 4, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 3", false),
+ // Bits 4-7 PIN digit 4
+ new CaddxProperty("", 4, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 4", false),
+ // Byte 5 PIN digits 5 & 6
+ // Bits 0-3 PIN digit 5 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 5, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ // Bits 4-7 PIN digit 6 (pad with 0 if 4 digit PIN)
+ new CaddxProperty("", 5, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false)),
+
+ SET_USER_AUTHORIZATION_COMMAND_WITH_PIN(0x36, new int[] { 0x1d, 0x1c, 0x1f }, 7,
+ "Set User Authorization Command with PIN",
+ "This message will contain all attributes and partitions that should be stored as the new information for the designated User number. A PIN will be checked for Master capability before proceeding.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 (Master) PIN digits 1 & 2
+ new CaddxProperty("", 2, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 1", false),
+ new CaddxProperty("", 2, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 2", false),
+
+ // Byte 3 (Master) PIN digits 3 & 4
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 3", false),
+ new CaddxProperty("", 3, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 4", false),
+
+ // Byte 4 (Master) PIN digits 5 & 6
+ new CaddxProperty("", 4, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ new CaddxProperty("", 4, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false),
+
+ // Byte 5 User number (1=user 1)
+ new CaddxProperty("", 5, 1, 0, 0, CaddxPropertyType.INT, "User number (1=user 1)", false),
+
+ // Byte 6 Authority flags
+ new CaddxProperty("", 6, 1, 0, 1, CaddxPropertyType.BIT,
+ "Reserved (if bit 7 is clear) || Output 1 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT,
+ "Arm only (if bit 7 is clear) || Output 2 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 2, 1, CaddxPropertyType.BIT,
+ "Arm only (during close window) (if bit 7 is clear) || Output 3 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT,
+ "Master / program (if bit 7 is clear) || Output 4 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT,
+ "Arm / Disarm (if bit 7 is clear) || Arm / Disarm (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT,
+ "Bypass enable (if bit 7 is clear) || Bypass enable (if bit 7 is set)", false),
+ new CaddxProperty("", 6, 1, 6, 1, CaddxPropertyType.BIT,
+ "Open / close report enable (if bit 7 is clear) || Open / close report enable (if bit 7 is set)",
+ false),
+ new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT,
+ "Must be a 0 (if bit 7 is clear) || Must be a 1 (if bit 7 is set)", false),
+
+ // Byte 7 Authorized partition(s) mask
+ new CaddxProperty("", 7, 1, 0, 1, CaddxPropertyType.BIT, "Authorized for partition 1", false),
+ new CaddxProperty("", 7, 1, 1, 1, CaddxPropertyType.BIT, "Authorized for partition 2", false),
+ new CaddxProperty("", 7, 1, 2, 1, CaddxPropertyType.BIT, "Authorized for partition 3", false),
+ new CaddxProperty("", 7, 1, 3, 1, CaddxPropertyType.BIT, "Authorized for partition 4", false),
+ new CaddxProperty("", 7, 1, 4, 1, CaddxPropertyType.BIT, "Authorized for partition 5", false),
+ new CaddxProperty("", 7, 1, 5, 1, CaddxPropertyType.BIT, "Authorized for partition 6", false),
+ new CaddxProperty("", 7, 1, 6, 1, CaddxPropertyType.BIT, "Authorized for partition 7", false),
+ new CaddxProperty("", 7, 1, 7, 1, CaddxPropertyType.BIT, "Authorized for partition 8", false)),
+
+ SET_USER_AUTHORIZATION_COMMAND_WITHOUT_PIN(0x37, new int[] { 0x1d, 0x1c, 0x1f }, 4,
+ "Set User Authorization Command without PIN",
+ "This message will contain all attributes and partitions that should be stored as the new information for the designated User number. No authentication will be performed.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 User number (1=user 1)
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "User number (1=user 1)", false),
+
+ // Byte 3 Authority flags
+ new CaddxProperty("", 3, 1, 0, 1, CaddxPropertyType.BIT,
+ "Reserved (if bit 7 is clear) || Output 1 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT,
+ "Arm only (if bit 7 is clear) || Output 2 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 3, 1, 2, 1, CaddxPropertyType.BIT,
+ "Arm only (during close window) (if bit 7 is clear) || Output 3 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT,
+ "Master / program (if bit 7 is clear) || Output 4 enable (if bit 7 is set)", false),
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT,
+ "Arm / Disarm (if bit 7 is clear) || Arm / Disarm (if bit 7 is set)", false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT,
+ "Bypass enable (if bit 7 is clear) || Bypass enable (if bit 7 is set)", false),
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT,
+ "Open / close report enable (if bit 7 is clear) || Open / close report enable (if bit 7 is set)",
+ false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT,
+ "Must be a 0 (if bit 7 is clear) || Must be a 1 (if bit 7 is set)", false),
+
+ // Byte 4 Authorized partition(s) mask
+ new CaddxProperty("", 4, 1, 0, 1, CaddxPropertyType.BIT, "Authorized for partition 1", false),
+ new CaddxProperty("", 4, 1, 1, 1, CaddxPropertyType.BIT, "Authorized for partition 2", false),
+ new CaddxProperty("", 4, 1, 2, 1, CaddxPropertyType.BIT, "Authorized for partition 3", false),
+ new CaddxProperty("", 4, 1, 3, 1, CaddxPropertyType.BIT, "Authorized for partition 4", false),
+ new CaddxProperty("", 4, 1, 4, 1, CaddxPropertyType.BIT, "Authorized for partition 5", false),
+ new CaddxProperty("", 4, 1, 5, 1, CaddxPropertyType.BIT, "Authorized for partition 6", false),
+ new CaddxProperty("", 4, 1, 6, 1, CaddxPropertyType.BIT, "Authorized for partition 7", false),
+ new CaddxProperty("", 4, 1, 7, 1, CaddxPropertyType.BIT, "Authorized for partition 8", false)),
+
+ STORE_COMMUNICATION_EVENT_COMMAND(0x3a, new int[] { 0x1d, 0x1c, 0x1f }, 6, "Store Communication Event Command",
+ "This message will submit an event to the control’s communication stack for possible transmission over its telephone or alternate communications path.",
+ CaddxDirection.OUT, CaddxSource.NONE),
+
+ SET_CLOCK_CALENDAR_COMMAND(0x3b, new int[] { 0x1d, 0x1c, 0x1f }, 7, "Set Clock / Calendar Command",
+ "This message will set the clock / calendar in the system.", CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 Year (00-99)
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Year (00-99)", false),
+
+ // Byte 3 Month (1-12)
+ new CaddxProperty("", 3, 1, 0, 0, CaddxPropertyType.INT, "Month (1-12)", false),
+
+ // Byte 4 Day (1-31)
+ new CaddxProperty("", 4, 1, 0, 0, CaddxPropertyType.INT, "Day (1-31)", false),
+
+ // Byte 5 Hour (0-23)
+ new CaddxProperty("", 5, 1, 0, 0, CaddxPropertyType.INT, "Hour (0-23)", false),
+
+ // Byte 6 Minute (0-59)
+ new CaddxProperty("", 6, 1, 0, 0, CaddxPropertyType.INT, "Minute (0-59)", false),
+
+ // Byte 7 Day
+ new CaddxProperty("", 7, 1, 0, 0, CaddxPropertyType.INT, "Day", false)),
+
+ PRIMARY_KEYPAD_FUNCTION_WITH_PIN(0x3c, new int[] { 0x1d, 0x1c, 0x1f }, 6, "Primary Keypad Function with PIN",
+ "This message will contain a value that defines with function to perform, the partitions to use and a PIN value for the validation.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 PIN digits 1 & 2
+ new CaddxProperty("", 2, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 1", false),
+ new CaddxProperty("", 2, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 2", false),
+
+ // Byte 3 PIN digits 3 & 4
+ new CaddxProperty("", 3, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 3", false),
+ new CaddxProperty("", 3, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 4", false),
+
+ // Byte 4 PIN digits 5 & 6
+ new CaddxProperty("", 4, 1, 0, 4, CaddxPropertyType.BIT, "PIN digit 5 (pad with 0 if 4 digit PIN)", false),
+ new CaddxProperty("", 4, 1, 4, 4, CaddxPropertyType.BIT, "PIN digit 6 (pad with 0 if 4 digit PIN)", false),
+
+ // Byte 5 Keypad function [00h Turn off any sounder or alarm, 01h Disarm, 02h Arm in away mode, 03h Arm
+ // in stay mode, 04h Cancel, 05h Initiate auto-arm, 06h Start walk-test mode, 07h Stop walk-test mode,
+ // 08h-FFh Reserved]
+ new CaddxProperty("", 5, 1, 0, 0, CaddxPropertyType.INT,
+ "Keypad function [00h Turn off any sounder or alarm, 01h Disarm, 02h Arm in away mode, 03h Arm in stay mode, 04h Cancel, 05h Initiate auto-arm, 06h Start walk-test mode, 07h Stop walk-test mode, 08h-FFh Reserved]",
+ false),
+
+ // Byte 6 Partition mask
+ new CaddxProperty("", 6, 1, 0, 1, CaddxPropertyType.BIT, "Perform on partition 1 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 1, 1, CaddxPropertyType.BIT, "Perform on partition 2 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 2, 1, CaddxPropertyType.BIT, "Perform on partition 3 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 3, 1, CaddxPropertyType.BIT, "Perform on partition 4 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 4, 1, CaddxPropertyType.BIT, "Perform on partition 5 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 5, 1, CaddxPropertyType.BIT, "Perform on partition 6 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 6, 1, CaddxPropertyType.BIT, "Perform on partition 7 (if PIN has access)",
+ false),
+ new CaddxProperty("", 6, 1, 7, 1, CaddxPropertyType.BIT, "Perform on partition 8 (if PIN has access)",
+ false)),
+
+ PRIMARY_KEYPAD_FUNCTION_WITHOUT_PIN(0x3d, new int[] { 0x1d, 0x1c, 0x1f }, 4, "Primary Keypad Function without PIN",
+ "This message will contain a value that defines with function to perform, the partitions and user number to assign to the function.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 "Keypad function [00h Turn off any sounder or alarm, 01h Disarm, 02h Arm in away mode, 03h Arm
+ // in stay mode, 04h Cancel, 05h Initiate auto-arm, 06h Start walk-test mode, 07h Stop walk-test mode,
+ // 08h-FFh Reserved]",
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT,
+ "Keypad function [00h Turn off any sounder or alarm, 01h Disarm, 02h Arm in away mode, 03h Arm in stay mode, 04h Cancel, 05h Initiate auto-arm, 06h Start walk-test mode, 07h Stop walk-test mode, 08h-FFh Reserved]",
+ false),
+
+ // Byte 3 Partition mask
+ new CaddxProperty("", 3, 1, 0, 1, CaddxPropertyType.BIT, "Perform on partition 1 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT, "Perform on partition 2 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 2, 1, CaddxPropertyType.BIT, "Perform on partition 3 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT, "Perform on partition 4 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Perform on partition 5 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Perform on partition 6 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT, "Perform on partition 7 (if PIN has access)",
+ false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Perform on partition 8 (if PIN has access)",
+ false),
+
+ // Byte 4 User number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "User number", false)),
+
+ SECONDARY_KEYPAD_FUNCTION(0x3e, new int[] { 0x1d, 0x1c, 0x1f }, 3, "Secondary Keypad Function",
+ "This message will contain a value that defines with function to perform, and the partitions to use.",
+ CaddxDirection.OUT, CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 "Keypad function [00h Stay (1 button arm / toggle interiors), 01h Chime (toggle chime mode),
+ // 02h Exit (1 button arm / toggle instant), 03h Bypass interiors, 04h Fire panic, 05h Medical panic,
+ // 06h Police panic, 07h Smoke detector reset, 08h Auto callback download, 09h Manual pickup download,
+ // 0Ah Enable silent exit (for this arm cycle), 0Bh Perform test, 0Ch Group bypass, 0Dh Auxiliary
+ // function 1, 0Eh Auxiliary function 2, 0Fh Start keypad sounder, 10h-FFh Reserved]",
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT,
+ "Keypad function [00h Stay (1 button arm / toggle interiors), 01h Chime (toggle chime mode), 02h Exit (1 button arm / toggle instant), 03h Bypass interiors, 04h Fire panic, 05h Medical panic, 06h Police panic, 07h Smoke detector reset, 08h Auto callback download, 09h Manual pickup download, 0Ah Enable silent exit (for this arm cycle), 0Bh Perform test, 0Ch Group bypass, 0Dh Auxiliary function 1, 0Eh Auxiliary function 2, 0Fh Start keypad sounder, 10h-FFh Reserved]",
+ false),
+
+ // Byte 3 Partition mask
+ new CaddxProperty("", 3, 1, 0, 1, CaddxPropertyType.BIT, "Perform on partition 1", false),
+ new CaddxProperty("", 3, 1, 1, 1, CaddxPropertyType.BIT, "Perform on partition 2", false),
+ new CaddxProperty("", 3, 1, 2, 1, CaddxPropertyType.BIT, "Perform on partition 3", false),
+ new CaddxProperty("", 3, 1, 3, 1, CaddxPropertyType.BIT, "Perform on partition 4", false),
+ new CaddxProperty("", 3, 1, 4, 1, CaddxPropertyType.BIT, "Perform on partition 5", false),
+ new CaddxProperty("", 3, 1, 5, 1, CaddxPropertyType.BIT, "Perform on partition 6", false),
+ new CaddxProperty("", 3, 1, 6, 1, CaddxPropertyType.BIT, "Perform on partition 7", false),
+ new CaddxProperty("", 3, 1, 7, 1, CaddxPropertyType.BIT, "Perform on partition 8", false)),
+
+ ZONE_BYPASS_TOGGLE(0x3f, new int[] { 0x1d, 0x1c, 0x1f }, 2, "Zone Bypass Toggle",
+ "This message will contain a number of a zone that should be (un)bypassed.", CaddxDirection.OUT,
+ CaddxSource.NONE,
+
+ // Properties
+ // Byte 1 Message number
+ new CaddxProperty("", 1, 1, 0, 0, CaddxPropertyType.INT, "Message number", false),
+
+ // Byte 2 Zone number (0= zone 1)
+ new CaddxProperty("", 2, 1, 0, 0, CaddxPropertyType.INT, "Zone number (0= zone 1)", false));
+
+ public final String name;
+ public final String description;
+ public final int number;
+ public final int @Nullable [] replyMessageNumbers;
+ public final int length;
+ public final CaddxDirection direction;
+ public final CaddxSource source;
+ public final CaddxProperty[] properties;
+
+ CaddxMessageType(int number, int @Nullable [] replyMessageNumbers, int length, String name, String description,
+ CaddxDirection direction, CaddxSource source, CaddxProperty... properties) {
+ this.name = name;
+ this.description = description;
+ this.direction = direction;
+ this.source = source;
+ this.number = number;
+ this.replyMessageNumbers = replyMessageNumbers;
+ this.length = length;
+ this.properties = properties;
+ }
+
+ private static final Map BY_MESSAGE_TYPE = new HashMap<>();
+
+ static {
+ for (CaddxMessageType mt : values()) {
+ BY_MESSAGE_TYPE.put(mt.number, mt);
+ }
+ }
+
+ public static @Nullable CaddxMessageType valueOfMessageType(int number) {
+ return BY_MESSAGE_TYPE.get(number);
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java
new file mode 100644
index 0000000000000..516cefad803f1
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPanelListener.java
@@ -0,0 +1,25 @@
+/**
+ * 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.caddx.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Panel listener interface
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public interface CaddxPanelListener {
+ public void caddxMessage(CaddxCommunicator communicator, CaddxMessage message);
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxProperty.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxProperty.java
new file mode 100644
index 0000000000000..06f57f1bc11f6
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxProperty.java
@@ -0,0 +1,190 @@
+/**
+ * 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.caddx.internal;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Arrays;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Panel message property class
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxProperty {
+ // private
+ private final String name;
+ private final CaddxPropertyType type; // 'Int', 'String', 'Bit'
+ private final int byteFrom;
+ private final int byteLength;
+ private final int bitFrom;
+ private final int bitLength;
+ private final boolean external;
+ private final String id;
+
+ // Constructor
+ public CaddxProperty(String id, int byteFrom, int byteLength, int bitFrom, int bitLength, CaddxPropertyType type,
+ String name, boolean external) {
+ this.id = id;
+ this.name = name;
+ this.type = type;
+ this.byteFrom = byteFrom;
+ this.byteLength = byteLength;
+ this.bitFrom = bitFrom;
+ this.bitLength = bitLength;
+ this.external = external;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public CaddxPropertyType getType() {
+ return type;
+ }
+
+ public boolean getExternal() {
+ return external;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getValue(byte[] message) {
+ int mask;
+ int val;
+
+ switch (type) {
+ case INT:
+ if (bitFrom == 0 && bitLength == 0) {
+ mask = 255;
+ val = message[byteFrom - 1] & mask;
+ } else {
+ mask = ((1 << ((bitLength - bitFrom))) - 1) << bitFrom;
+ val = (message[byteFrom - 1] & mask) >> bitFrom;
+ }
+
+ return Integer.toString(val);
+ case STRING:
+ byte[] str = Arrays.copyOfRange(message, byteFrom - 1, byteFrom + byteLength);
+ return mapCaddxString(new String(str, StandardCharsets.US_ASCII));
+ case BIT:
+ return (((message[byteFrom - 1] & (1 << bitFrom)) > 0) ? "true" : "false");
+ default:
+ throw new IllegalArgumentException("type is unknown.");
+ }
+ }
+
+ public String toString(byte[] message) {
+ int mask;
+ int val;
+ StringWriter sWriter = new StringWriter();
+ PrintWriter pWriter = new PrintWriter(sWriter);
+
+ switch (type) {
+ case INT:
+ if (bitFrom == 0 && bitLength == 0) {
+ mask = 255;
+ val = message[byteFrom - 1];
+ } else {
+ mask = ((1 << ((bitLength - bitFrom) + 1)) - 1) << bitFrom;
+ val = (message[byteFrom - 1] & mask) >> bitFrom;
+ }
+
+ pWriter.printf("%s: %02x - %d - %c", name, val, val, Character.isValidCodePoint(val) ? val : 32);
+ pWriter.flush();
+
+ return sWriter.toString();
+ case STRING:
+ pWriter.print(name);
+ pWriter.print(": ");
+
+ byte[] a = Arrays.copyOfRange(message, byteFrom - 1, byteFrom + byteLength);
+ pWriter.println(mapCaddxString(new String(a, StandardCharsets.US_ASCII)));
+ pWriter.println();
+ for (int i = 0; i < byteLength; i++) {
+ pWriter.printf("%02x", message[byteFrom - 1 + i]);
+ pWriter.print(" - ");
+ pWriter.println((char) message[byteFrom - 1 + i]);
+ }
+ pWriter.flush();
+
+ return sWriter.toString();
+ case BIT:
+ pWriter.print(name);
+ pWriter.print(": ");
+ pWriter.print(((message[byteFrom - 1] & (1 << bitFrom)) > 0));
+ pWriter.flush();
+
+ return sWriter.toString();
+ default:
+ pWriter.print("Unknown type: ");
+ pWriter.print(type.toString());
+ pWriter.flush();
+
+ return sWriter.toString();
+ }
+ }
+
+ private String mapCaddxString(String str) {
+ StringBuilder s = new StringBuilder(str.length());
+
+ CharacterIterator it = new StringCharacterIterator(str);
+ for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
+ switch (ch) {
+ case 0xb7:
+ s.append('Γ');
+ break;
+ case 0x10:
+ s.append('Δ');
+ break;
+ case 0x13:
+ s.append('Θ');
+ break;
+ case 0x14:
+ s.append('Λ');
+ break;
+ case 0x12:
+ s.append('Ξ');
+ break;
+ case 0xc8:
+ s.append('Π');
+ break;
+ case 0x16:
+ s.append('Σ');
+ break;
+ case 0xcc:
+ s.append('Φ');
+ break;
+ case 0x17:
+ s.append('Ψ');
+ break;
+ case 0x15:
+ s.append('Ω');
+ break;
+ default:
+ s.append(ch);
+ break;
+ }
+ }
+
+ return s.toString();
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPropertyType.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPropertyType.java
new file mode 100644
index 0000000000000..bdb3596ad106d
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxPropertyType.java
@@ -0,0 +1,27 @@
+/**
+ * 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.caddx.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Message property types enumeration.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum CaddxPropertyType {
+ INT,
+ STRING,
+ BIT
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxProtocol.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxProtocol.java
new file mode 100644
index 0000000000000..18ab7787eb692
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxProtocol.java
@@ -0,0 +1,26 @@
+/**
+ * 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.caddx.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Panel Protocol enumeration.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum CaddxProtocol {
+ Binary,
+ Ascii
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxSource.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxSource.java
new file mode 100644
index 0000000000000..20be604cf8d06
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/CaddxSource.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.caddx.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Alarm component Source enumeration.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum CaddxSource {
+ NONE,
+ PANEL,
+ KEYPAD,
+ PARTITION,
+ ZONE
+};
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java
new file mode 100644
index 0000000000000..e50f0a64f433c
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxBridgeConfiguration.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.caddx.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.caddx.internal.CaddxProtocol;
+
+/**
+ * Configuration class for the Caddx RS232 Serial interface bridge.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+
+@NonNullByDefault
+public class CaddxBridgeConfiguration {
+
+ // Caddx Bridge Thing constants
+ public static final String PROTOCOL = "protocol";
+ public static final String SERIAL_PORT = "serialPort";
+ public static final String BAUD = "baud";
+
+ private CaddxProtocol protocol = CaddxProtocol.Binary;
+ private @Nullable String serialPort;
+ private int baudrate = 9600;
+
+ public CaddxProtocol getProtocol() {
+ return protocol;
+ }
+
+ public @Nullable String getSerialPort() {
+ return serialPort;
+ }
+
+ public int getBaudrate() {
+ return baudrate;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxKeypadConfiguration.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxKeypadConfiguration.java
new file mode 100644
index 0000000000000..807efcc8257af
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxKeypadConfiguration.java
@@ -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.caddx.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Configuration class for the Caddx Keypad Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+
+@NonNullByDefault
+public class CaddxKeypadConfiguration {
+
+ // Keypad Thing constants
+ public static final String KEYPAD_ADDRESS = "keypadAddress";
+
+ private int keypadAddress;
+
+ public int getKeypadAddress() {
+ return keypadAddress;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java
new file mode 100644
index 0000000000000..8bd743f4dac89
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxPartitionConfiguration.java
@@ -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.caddx.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Configuration class for the Caddx Partition Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxPartitionConfiguration {
+
+ // Partition Thing constants
+ public static final String PARTITION_NUMBER = "partitionNumber";
+
+ /**
+ * The Partition Number. Can be in the range of 1-8. This is a required parameter for a partition.
+ */
+ private int partitionNumber;
+
+ /**
+ * The User Number of the user that will execute commands against the partition.
+ */
+ private int userNumber;
+
+ public int getPartitionNumber() {
+ return partitionNumber;
+ }
+
+ public int getUserNumber() {
+ return userNumber;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxZoneConfiguration.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxZoneConfiguration.java
new file mode 100644
index 0000000000000..00ad1a1e6a7ef
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/config/CaddxZoneConfiguration.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.caddx.internal.config;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Configuration class for the Caddx Zone Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxZoneConfiguration {
+
+ // Zone Thing constants
+ public static final String ZONE_NUMBER = "zoneNumber";
+
+ /**
+ * The Zone Number. Can be in the range of 1-192. Depends on the Panel model. This is a required parameter for a
+ * zone.
+ */
+ private int zoneNumber;
+
+ public int getZoneNumber() {
+ return zoneNumber;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/discovery/CaddxDiscoveryService.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/discovery/CaddxDiscoveryService.java
new file mode 100644
index 0000000000000..201cb1894c4b5
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/discovery/CaddxDiscoveryService.java
@@ -0,0 +1,166 @@
+/**
+ * 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.caddx.internal.discovery;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService;
+import org.eclipse.smarthome.config.discovery.DiscoveryResult;
+import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder;
+import org.eclipse.smarthome.config.discovery.DiscoveryService;
+import org.eclipse.smarthome.core.thing.Bridge;
+import org.eclipse.smarthome.core.thing.ThingUID;
+import org.eclipse.smarthome.core.thing.binding.ThingHandler;
+import org.eclipse.smarthome.core.thing.binding.ThingHandlerService;
+import org.openhab.binding.caddx.internal.CaddxBindingConstants;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+import org.openhab.binding.caddx.internal.config.CaddxKeypadConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxPartitionConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxZoneConfiguration;
+import org.openhab.binding.caddx.internal.handler.CaddxBridgeHandler;
+import org.openhab.binding.caddx.internal.handler.CaddxThingType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is responsible for discovering the supported Things.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService, DiscoveryService {
+ private final Logger logger = LoggerFactory.getLogger(CaddxDiscoveryService.class);
+
+ private @Nullable CaddxBridgeHandler caddxBridgeHandler = null;
+
+ public CaddxDiscoveryService() {
+ super(CaddxBindingConstants.SUPPORTED_THING_TYPES_UIDS, 15, false);
+ }
+
+ @Override
+ protected void startScan() {
+ // Discovery is performed implicitly via the CadxBridgeHandler
+ }
+
+ /**
+ * Method to add a Thing to the Smarthome Inbox.
+ *
+ * @param bridge
+ * @param caddxThingType
+ * @param event
+ */
+ public void addThing(Bridge bridge, CaddxThingType caddxThingType, CaddxEvent event) {
+ ThingUID thingUID = null;
+ String thingID = "";
+ String thingLabel = "";
+ Map properties = null;
+
+ Integer partition = event.getPartition();
+ Integer zone = event.getZone();
+ Integer keypad = event.getKeypad();
+ String representationProperty = null;
+
+ switch (caddxThingType) {
+ case PANEL:
+ thingID = "panel";
+ thingLabel = "Panel";
+ thingUID = new ThingUID(CaddxBindingConstants.PANEL_THING_TYPE, bridge.getUID(), thingID);
+ break;
+ case PARTITION:
+ thingID = "partition" + partition;
+ thingLabel = "Partition " + partition;
+ thingUID = new ThingUID(CaddxBindingConstants.PARTITION_THING_TYPE, bridge.getUID(), thingID);
+
+ if (partition != null) {
+ properties = Collections.singletonMap(CaddxPartitionConfiguration.PARTITION_NUMBER, partition);
+ representationProperty = CaddxPartitionConfiguration.PARTITION_NUMBER;
+ }
+
+ break;
+ case ZONE:
+ thingID = "zone" + zone;
+ thingLabel = "Zone " + zone;
+ thingUID = new ThingUID(CaddxBindingConstants.ZONE_THING_TYPE, bridge.getUID(), thingID);
+
+ if (zone != null) {
+ properties = Collections.singletonMap(CaddxZoneConfiguration.ZONE_NUMBER, zone);
+ representationProperty = CaddxZoneConfiguration.ZONE_NUMBER;
+ }
+ break;
+ case KEYPAD:
+ thingID = "keypad";
+ thingLabel = "Keypad";
+ thingUID = new ThingUID(CaddxBindingConstants.KEYPAD_THING_TYPE, bridge.getUID(), thingID);
+
+ if (keypad != null) {
+ properties = Collections.singletonMap(CaddxKeypadConfiguration.KEYPAD_ADDRESS, keypad);
+ representationProperty = CaddxKeypadConfiguration.KEYPAD_ADDRESS;
+ }
+ break;
+ }
+
+ if (thingUID != null) {
+ DiscoveryResult discoveryResult;
+
+ if (properties != null && representationProperty != null) {
+ discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
+ .withRepresentationProperty(representationProperty).withBridge(bridge.getUID())
+ .withLabel(thingLabel).build();
+ } else {
+ discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridge.getUID())
+ .withLabel(thingLabel).build();
+ }
+
+ thingDiscovered(discoveryResult);
+ } else {
+ logger.warn("addThing(): Unable to Add Caddx Alarm Thing to Inbox!");
+ }
+ }
+
+ /**
+ * Activates the Discovery Service.
+ */
+ @Override
+ public void activate() {
+ CaddxBridgeHandler handler = caddxBridgeHandler;
+ if (handler != null) {
+ handler.registerDiscoveryService(this);
+ }
+ }
+
+ /**
+ * Deactivates the Discovery Service.
+ */
+ @Override
+ public void deactivate() {
+ CaddxBridgeHandler handler = caddxBridgeHandler;
+ if (handler != null) {
+ handler.unregisterDiscoveryService();
+ }
+ }
+
+ @Override
+ public void setThingHandler(@Nullable ThingHandler handler) {
+ if (handler instanceof CaddxBridgeHandler) {
+ caddxBridgeHandler = (CaddxBridgeHandler) handler;
+ }
+ }
+
+ @Override
+ public @Nullable ThingHandler getThingHandler() {
+ return caddxBridgeHandler;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/factory/CaddxHandlerFactory.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/factory/CaddxHandlerFactory.java
new file mode 100644
index 0000000000000..4964159aac4ed
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/factory/CaddxHandlerFactory.java
@@ -0,0 +1,80 @@
+/**
+ * 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.caddx.internal.factory;
+
+import static org.openhab.binding.caddx.internal.CaddxBindingConstants.SUPPORTED_THING_TYPES_UIDS;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.thing.Bridge;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingTypeUID;
+import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory;
+import org.eclipse.smarthome.core.thing.binding.ThingHandler;
+import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory;
+import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
+import org.openhab.binding.caddx.internal.CaddxBindingConstants;
+import org.openhab.binding.caddx.internal.handler.CaddxBridgeHandler;
+import org.openhab.binding.caddx.internal.handler.ThingHandlerKeypad;
+import org.openhab.binding.caddx.internal.handler.ThingHandlerPanel;
+import org.openhab.binding.caddx.internal.handler.ThingHandlerPartition;
+import org.openhab.binding.caddx.internal.handler.ThingHandlerZone;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link CaddxHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@Component(configurationPid = "binding.caddx", service = ThingHandlerFactory.class)
+@NonNullByDefault
+public class CaddxHandlerFactory extends BaseThingHandlerFactory {
+ private final Logger logger = LoggerFactory.getLogger(CaddxHandlerFactory.class);
+ private final SerialPortManager portManager;
+
+ @Activate
+ public CaddxHandlerFactory(@Reference SerialPortManager portManager) {
+ this.portManager = portManager;
+ }
+
+ @Override
+ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+ return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
+ }
+
+ @Override
+ protected @Nullable ThingHandler createHandler(Thing thing) {
+ ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+
+ if (thingTypeUID.equals(CaddxBindingConstants.CADDXBRIDGE_THING_TYPE)) {
+ return new CaddxBridgeHandler(portManager, (Bridge) thing);
+ } else if (thingTypeUID.equals(CaddxBindingConstants.PANEL_THING_TYPE)) {
+ return new ThingHandlerPanel(thing);
+ } else if (thingTypeUID.equals(CaddxBindingConstants.PARTITION_THING_TYPE)) {
+ return new ThingHandlerPartition(thing);
+ } else if (thingTypeUID.equals(CaddxBindingConstants.ZONE_THING_TYPE)) {
+ return new ThingHandlerZone(thing);
+ } else if (thingTypeUID.equals(CaddxBindingConstants.KEYPAD_THING_TYPE)) {
+ return new ThingHandlerKeypad(thing);
+ } else {
+ logger.debug("createHandler(): ThingHandler not found for {}", thingTypeUID);
+
+ return null;
+ }
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java
new file mode 100644
index 0000000000000..84c8e5ea51308
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBaseThingHandler.java
@@ -0,0 +1,248 @@
+/**
+ * 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.caddx.internal.handler;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.thing.Bridge;
+import org.eclipse.smarthome.core.thing.Channel;
+import org.eclipse.smarthome.core.thing.ChannelUID;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingStatus;
+import org.eclipse.smarthome.core.thing.binding.BaseThingHandler;
+import org.eclipse.smarthome.core.thing.binding.ThingHandler;
+import org.eclipse.smarthome.core.types.Command;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+import org.openhab.binding.caddx.internal.config.CaddxKeypadConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxPartitionConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxZoneConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class for a Caddx Thing Handler.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public abstract class CaddxBaseThingHandler extends BaseThingHandler {
+
+ private final Logger logger = LoggerFactory.getLogger(CaddxBaseThingHandler.class);
+
+ /** Bridge Handler for the Thing. */
+ private @Nullable CaddxBridgeHandler caddxBridgeHandler = null;
+
+ /** Caddx Alarm Thing type. */
+ private CaddxThingType caddxThingType;
+
+ /** Partition Number. */
+ private int partitionNumber;
+
+ /** User Number. */
+ private int userNumber;
+
+ /** Zone Number. */
+ private int zoneNumber;
+
+ /** Keypad Address. */
+ private int keypadAddress;
+
+ public CaddxBaseThingHandler(Thing thing, CaddxThingType caddxThingType) {
+ super(thing);
+ this.caddxThingType = caddxThingType;
+ }
+
+ @Override
+ public void initialize() {
+ getConfiguration(caddxThingType);
+
+ // set the Thing offline for now
+ updateStatus(ThingStatus.OFFLINE);
+ }
+
+ /**
+ * Get the Bridge Handler for the Caddx system.
+ *
+ * @return CaddxBridgeHandler
+ */
+ public @Nullable CaddxBridgeHandler getCaddxBridgeHandler() {
+ if (this.caddxBridgeHandler == null) {
+ Bridge bridge = getBridge();
+
+ if (bridge == null) {
+ logger.debug("getCaddxBridgeHandler(): Unable to get bridge!");
+ return null;
+ }
+
+ logger.trace("getCaddxBridgeHandler(): Bridge for '{}' - '{}'", getThing().getUID(), bridge.getUID());
+
+ ThingHandler handler = bridge.getHandler();
+
+ if (handler instanceof CaddxBridgeHandler) {
+ this.caddxBridgeHandler = (CaddxBridgeHandler) handler;
+ } else {
+ logger.debug("getCaddxBridgeHandler(): Unable to get bridge handler!");
+ }
+ }
+
+ return this.caddxBridgeHandler;
+ }
+
+ /**
+ * Method to Update a Channel
+ *
+ * @param channel
+ * @param state
+ * @param description
+ */
+ public abstract void updateChannel(ChannelUID channel, String data);
+
+ /**
+ * Receives Events from the bridge.
+ *
+ * @param event.
+ * @param thing
+ */
+ public abstract void caddxEventReceived(CaddxEvent event, Thing thing);
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ }
+
+ /**
+ * Get the thing configuration.
+ *
+ * @param caddxThingType The Thing type
+ */
+ private void getConfiguration(CaddxThingType caddxThingType) {
+ switch (caddxThingType) {
+ case PARTITION:
+ CaddxPartitionConfiguration partitionConfiguration = getConfigAs(CaddxPartitionConfiguration.class);
+ setPartitionNumber(partitionConfiguration.getPartitionNumber());
+ setUserNumber(partitionConfiguration.getUserNumber());
+ break;
+ case ZONE:
+ CaddxZoneConfiguration zoneConfiguration = getConfigAs(CaddxZoneConfiguration.class);
+ setZoneNumber(zoneConfiguration.getZoneNumber());
+ break;
+ case KEYPAD:
+ CaddxKeypadConfiguration keypadConfiguration = getConfigAs(CaddxKeypadConfiguration.class);
+ setKeypadAddress(keypadConfiguration.getKeypadAddress());
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Get the Thing type.
+ *
+ * @return caddxThingType
+ */
+ public CaddxThingType getCaddxThingType() {
+ return caddxThingType;
+ }
+
+ /**
+ * Get Partition Number.
+ *
+ * @return partitionNumber
+ */
+ public int getPartitionNumber() {
+ return partitionNumber;
+ }
+
+ /**
+ * Set Partition Number.
+ *
+ * @param partitionNumber
+ */
+ public void setPartitionNumber(int partitionNumber) {
+ this.partitionNumber = partitionNumber;
+ }
+
+ /**
+ * Get User Number.
+ *
+ * @return userNumber
+ */
+ public int getUserNumber() {
+ return userNumber;
+ }
+
+ /**
+ * Set User Number.
+ *
+ * @param userNumber
+ */
+ public void setUserNumber(int userNumber) {
+ this.userNumber = userNumber;
+ }
+
+ /**
+ * Get Zone Number.
+ *
+ * @return zoneNumber
+ */
+ public int getZoneNumber() {
+ return zoneNumber;
+ }
+
+ /**
+ * Set Zone Number.
+ *
+ * @param zoneNumber
+ */
+ public void setZoneNumber(int zoneNumber) {
+ this.zoneNumber = zoneNumber;
+ }
+
+ /**
+ * Get Keypad Address.
+ *
+ * @return keypadAddress
+ */
+ public int getKeypadAddress() {
+ return keypadAddress;
+ }
+
+ /**
+ * Set Keypad Address.
+ *
+ * @param keypadAddress
+ */
+ public void setKeypadAddress(int keypadAddress) {
+ this.keypadAddress = keypadAddress;
+ }
+
+ /**
+ * Get Channel by ChannelUID.
+ *
+ * @param channelUID
+ */
+ public @Nullable Channel getChannel(ChannelUID channelUID) {
+ Channel channel = null;
+
+ List channels = getThing().getChannels();
+
+ for (Channel ch : channels) {
+ if (channelUID == ch.getUID()) {
+ channel = ch;
+ break;
+ }
+ }
+
+ return channel;
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java
new file mode 100644
index 0000000000000..b778fcf844ca2
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxBridgeHandler.java
@@ -0,0 +1,417 @@
+/**
+ * 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.caddx.internal.handler;
+
+import static org.openhab.binding.caddx.internal.CaddxBindingConstants.SEND_COMMAND;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.TooManyListenersException;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.library.types.StringType;
+import org.eclipse.smarthome.core.thing.Bridge;
+import org.eclipse.smarthome.core.thing.Channel;
+import org.eclipse.smarthome.core.thing.ChannelUID;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingStatus;
+import org.eclipse.smarthome.core.thing.ThingStatusDetail;
+import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler;
+import org.eclipse.smarthome.core.thing.binding.ThingHandler;
+import org.eclipse.smarthome.core.thing.binding.ThingHandlerService;
+import org.eclipse.smarthome.core.types.Command;
+import org.eclipse.smarthome.io.transport.serial.PortInUseException;
+import org.eclipse.smarthome.io.transport.serial.SerialPortManager;
+import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException;
+import org.openhab.binding.caddx.internal.CaddxBindingConstants;
+import org.openhab.binding.caddx.internal.CaddxCommunicator;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+import org.openhab.binding.caddx.internal.CaddxMessage;
+import org.openhab.binding.caddx.internal.CaddxMessageType;
+import org.openhab.binding.caddx.internal.CaddxPanelListener;
+import org.openhab.binding.caddx.internal.CaddxProtocol;
+import org.openhab.binding.caddx.internal.CaddxSource;
+import org.openhab.binding.caddx.internal.config.CaddxBridgeConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxKeypadConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxPartitionConfiguration;
+import org.openhab.binding.caddx.internal.config.CaddxZoneConfiguration;
+import org.openhab.binding.caddx.internal.discovery.CaddxDiscoveryService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The bridge handler for the Caddx RS232 Serial interface.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class CaddxBridgeHandler extends BaseBridgeHandler implements CaddxPanelListener {
+ private final Logger logger = LoggerFactory.getLogger(CaddxBridgeHandler.class);
+
+ static final byte[] DISCOVERY_PARTITION_STATUS_REQUEST_0 = { 0x26, 0x00 };
+ static final byte[] DISCOVERY_ZONES_SNAPSHOT_REQUEST_00 = { 0x25, 0x00 };
+ static final byte[] DISCOVERY_ZONES_SNAPSHOT_REQUEST_10 = { 0x25, 0x10 };
+ static final byte[] DISCOVERY_ZONES_SNAPSHOT_REQUEST_20 = { 0x25, 0x20 };
+ static final byte[] DISCOVERY_PARTITIONS_SNAPSHOT_REQUEST = { 0x27 };
+
+ private final SerialPortManager portManager;
+ private @Nullable CaddxDiscoveryService discoveryService = null;
+ private CaddxProtocol protocol = CaddxProtocol.Binary;
+ private String serialPortName = "";
+ private int baudRate;
+ private @Nullable CaddxCommunicator communicator = null;
+
+ // Things served by the bridge
+ private Map thingZonesMap = new ConcurrentHashMap<>();
+ private Map thingPartitionsMap = new ConcurrentHashMap<>();
+ private Map thingKeypadsMap = new ConcurrentHashMap<>();
+ private @Nullable Thing thingPanel = null;
+
+ public @Nullable CaddxDiscoveryService getDiscoveryService() {
+ return discoveryService;
+ }
+
+ public void setDiscoveryService(CaddxDiscoveryService discoveryService) {
+ this.discoveryService = discoveryService;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param bridge
+ */
+ public CaddxBridgeHandler(SerialPortManager portManager, Bridge bridge) {
+ super(bridge);
+
+ this.portManager = portManager;
+ }
+
+ @Override
+ public void initialize() {
+ CaddxBridgeConfiguration configuration = getConfigAs(CaddxBridgeConfiguration.class);
+
+ String portName = configuration.getSerialPort();
+ if (portName == null) {
+ logger.debug("Serial port is not defined in the configuration");
+ return;
+ }
+ serialPortName = portName;
+ protocol = configuration.getProtocol();
+ baudRate = configuration.getBaudrate();
+ updateStatus(ThingStatus.OFFLINE);
+
+ // create & start panel interface
+ logger.debug("Starting interface at port {} with baudrate {} and protocol {}", serialPortName, baudRate,
+ protocol);
+
+ try {
+ communicator = new CaddxCommunicator(portManager, protocol, serialPortName, baudRate);
+ } catch (IOException | TooManyListenersException | UnsupportedCommOperationException | PortInUseException e) {
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+ "Communication cannot be initialized. " + e.toString());
+
+ return;
+ }
+
+ CaddxCommunicator comm = communicator;
+ if (comm != null) {
+ comm.addListener(this);
+
+ // Send discovery commands for the things
+ comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_00, false));
+ comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_10, false));
+ comm.transmit(new CaddxMessage(DISCOVERY_ZONES_SNAPSHOT_REQUEST_20, false));
+ comm.transmit(new CaddxMessage(DISCOVERY_PARTITION_STATUS_REQUEST_0, false));
+ comm.transmit(new CaddxMessage(DISCOVERY_PARTITIONS_SNAPSHOT_REQUEST, false));
+ }
+
+ // list all channels
+ if (logger.isTraceEnabled()) {
+ logger.trace("list all {} channels:", getThing().getChannels().size());
+ for (Channel c : getThing().getChannels()) {
+ logger.trace("Channel Type {} UID {}", c.getChannelTypeUID(), c.getUID());
+ }
+ }
+ }
+
+ @Override
+ public void dispose() {
+ CaddxCommunicator comm = communicator;
+ if (comm != null) {
+ comm.stop();
+ comm = null;
+ }
+
+ if (discoveryService != null) {
+ unregisterDiscoveryService();
+ }
+
+ super.dispose();
+ }
+
+ public @Nullable Thing findThing(CaddxThingType caddxThingType, @Nullable Integer partition, @Nullable Integer zone,
+ @Nullable Integer keypad) {
+ switch (caddxThingType) {
+ case PARTITION:
+ if (partition != null) {
+ return thingPartitionsMap.get(BigDecimal.valueOf(partition));
+ }
+ case ZONE:
+ if (zone != null) {
+ return thingZonesMap.get(BigDecimal.valueOf(zone));
+ }
+ case KEYPAD:
+ if (keypad != null) {
+ return thingKeypadsMap.get(BigDecimal.valueOf(keypad));
+ }
+ case PANEL:
+ return thingPanel;
+ }
+ return null;
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ logger.trace("handleCommand(), channelUID: {}, command: {}", channelUID, command);
+
+ switch (channelUID.getId()) {
+ case SEND_COMMAND:
+ if (!command.toString().isEmpty()) {
+ String[] tokens = command.toString().split("\\|");
+
+ String cmd = tokens[0];
+ String data = "";
+ if (tokens.length > 1) {
+ data = tokens[1];
+ }
+
+ sendCommand(cmd, data);
+
+ updateState(channelUID, new StringType(""));
+ }
+ break;
+ default:
+ logger.debug("Unknown command {}", command);
+ break;
+ }
+ }
+
+ /**
+ * Sends a command to the panel
+ *
+ * @param command The command to be send
+ * @param data The associated command data
+ */
+ public boolean sendCommand(String command, String data) {
+ logger.trace("sendCommand(): Attempting to send Command: command - {} - data: {}", command, data);
+
+ CaddxMessage msg = null;
+
+ switch (command) {
+ case CaddxBindingConstants.ZONE_BYPASSED:
+ msg = new CaddxMessage(CaddxMessageType.ZONE_BYPASS_TOGGLE, data);
+ break;
+ case CaddxBindingConstants.ZONE_STATUS_REQUEST:
+ msg = new CaddxMessage(CaddxMessageType.ZONE_STATUS_REQUEST, data);
+ break;
+ case CaddxBindingConstants.ZONE_NAME_REQUEST:
+ msg = new CaddxMessage(CaddxMessageType.ZONE_NAME_REQUEST, data);
+ break;
+ case CaddxBindingConstants.PARTITION_STATUS_REQUEST:
+ msg = new CaddxMessage(CaddxMessageType.PARTITION_STATUS_REQUEST, data);
+ break;
+ case CaddxBindingConstants.PARTITION_PRIMARY_COMMAND_WITH_PIN:
+ msg = new CaddxMessage(CaddxMessageType.PRIMARY_KEYPAD_FUNCTION_WITH_PIN, data);
+ break;
+ case CaddxBindingConstants.PARTITION_SECONDARY_COMMAND:
+ msg = new CaddxMessage(CaddxMessageType.SECONDARY_KEYPAD_FUNCTION, data);
+ break;
+ case CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST:
+ msg = new CaddxMessage(CaddxMessageType.SYSTEM_STATUS_REQUEST, data);
+ break;
+ case CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST:
+ msg = new CaddxMessage(CaddxMessageType.INTERFACE_CONFIGURATION_REQUEST, data);
+ break;
+ case CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST:
+ msg = new CaddxMessage(CaddxMessageType.LOG_EVENT_REQUEST, data);
+ break;
+ default:
+ logger.debug("Unknown command {}", command);
+ return false;
+ }
+
+ CaddxCommunicator comm = communicator;
+ if (comm != null) {
+ comm.transmit(msg);
+ }
+
+ return true;
+ }
+
+ /**
+ * Register the Discovery Service.
+ *
+ * @param discoveryService
+ */
+ public void registerDiscoveryService(CaddxDiscoveryService discoveryService) {
+ this.discoveryService = discoveryService;
+ logger.trace("registerDiscoveryService(): Discovery Service Registered!");
+ }
+
+ /**
+ * Unregister the Discovery Service.
+ */
+ public void unregisterDiscoveryService() {
+ logger.trace("unregisterDiscoveryService(): Discovery Service Unregistered!");
+ discoveryService = null;
+ }
+
+ @Override
+ public void caddxMessage(CaddxCommunicator communicator, CaddxMessage caddxMessage) {
+ CaddxSource source = caddxMessage.getSource();
+
+ if (source != CaddxSource.NONE) {
+ CaddxThingType caddxThingType = null;
+ @Nullable
+ Integer partition = null;
+ @Nullable
+ Integer zone = null;
+ @Nullable
+ Integer keypad = null;
+
+ switch (source) {
+ case PANEL:
+ caddxThingType = CaddxThingType.PANEL;
+ break;
+ case PARTITION:
+ caddxThingType = CaddxThingType.PARTITION;
+ partition = Integer.parseInt(caddxMessage.getPropertyById("partition_number")) + 1;
+ break;
+ case ZONE:
+ caddxThingType = CaddxThingType.ZONE;
+ zone = Integer.parseInt(caddxMessage.getPropertyById("zone_number")) + 1;
+ break;
+ case KEYPAD:
+ caddxThingType = CaddxThingType.KEYPAD;
+ keypad = Integer.parseInt(caddxMessage.getPropertyById("keypad_address"));
+ break;
+ default:
+ logger.debug("Source has illegal value");
+ return;
+ }
+
+ CaddxEvent event = new CaddxEvent(caddxMessage, partition, zone, keypad);
+
+ // Find the thing
+ Thing thing = findThing(caddxThingType, partition, zone, keypad);
+ CaddxDiscoveryService discoveryService = getDiscoveryService();
+ if (thing != null) {
+ CaddxBaseThingHandler thingHandler = (CaddxBaseThingHandler) thing.getHandler();
+ if (thingHandler != null) {
+ thingHandler.caddxEventReceived(event, thing);
+ }
+ } else {
+ if (discoveryService != null) {
+ discoveryService.addThing(getThing(), caddxThingType, event);
+ }
+ }
+
+ // Handle specific messages that add multiple discovered things
+ if (discoveryService != null) {
+ switch (caddxMessage.getCaddxMessageType()) {
+ case PARTITIONS_SNAPSHOT_MESSAGE:
+ for (int i = 1; i <= 8; i++) {
+ if (caddxMessage.getPropertyById("partition_" + i + "_valid").equals("true")) {
+ thing = findThing(CaddxThingType.PARTITION, i, null, null);
+ if (thing != null) {
+ continue;
+ }
+
+ event = new CaddxEvent(caddxMessage, i, null, null);
+ discoveryService.addThing(getThing(), CaddxThingType.PARTITION, event);
+ }
+ }
+ break;
+ case ZONES_SNAPSHOT_MESSAGE:
+ int zoneOffset = Integer.parseInt(caddxMessage.getPropertyById("zone_offset"));
+ for (int i = 1; i <= 16; i++) {
+ if (caddxMessage.getPropertyById("zone_" + i + "_trouble").equals("false")) {
+ thing = findThing(CaddxThingType.ZONE, null, zoneOffset + i, null);
+ if (thing != null) {
+ continue;
+ }
+
+ event = new CaddxEvent(caddxMessage, null, zoneOffset + i, null);
+ discoveryService.addThing(getThing(), CaddxThingType.ZONE, event);
+ } else {
+ logger.debug("troubled zone: {}", zoneOffset + i);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ updateStatus(ThingStatus.ONLINE);
+ }
+
+ @Override
+ public Collection> getServices() {
+ return Collections.singleton(CaddxDiscoveryService.class);
+ }
+
+ @Override
+ public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) {
+ if (childHandler instanceof ThingHandlerPartition) {
+ BigDecimal id = (BigDecimal) childThing.getConfiguration()
+ .get(CaddxPartitionConfiguration.PARTITION_NUMBER);
+ thingPartitionsMap.put(id, childThing);
+ } else if (childHandler instanceof ThingHandlerZone) {
+ BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxZoneConfiguration.ZONE_NUMBER);
+ thingZonesMap.put(id, childThing);
+ } else if (childHandler instanceof ThingHandlerKeypad) {
+ BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxKeypadConfiguration.KEYPAD_ADDRESS);
+ thingKeypadsMap.put(id, childThing);
+ } else if (childHandler instanceof ThingHandlerPanel) {
+ thingPanel = childThing;
+ }
+
+ super.childHandlerInitialized(childHandler, childThing);
+ }
+
+ @Override
+ public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) {
+ if (childHandler instanceof ThingHandlerPartition) {
+ BigDecimal id = (BigDecimal) childThing.getConfiguration()
+ .get(CaddxPartitionConfiguration.PARTITION_NUMBER);
+ thingPartitionsMap.remove(id);
+ } else if (childHandler instanceof ThingHandlerZone) {
+ BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxZoneConfiguration.ZONE_NUMBER);
+ thingZonesMap.remove(id);
+ } else if (childHandler instanceof ThingHandlerKeypad) {
+ BigDecimal id = (BigDecimal) childThing.getConfiguration().get(CaddxKeypadConfiguration.KEYPAD_ADDRESS);
+ thingKeypadsMap.remove(id);
+ } else if (childHandler instanceof ThingHandlerPanel) {
+ thingPanel = null;
+ }
+
+ super.childHandlerDisposed(childHandler, childThing);
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxThingType.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxThingType.java
new file mode 100644
index 0000000000000..9bc820103d737
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/CaddxThingType.java
@@ -0,0 +1,28 @@
+/**
+ * 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.caddx.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Used to map thing types from the binding string to a ENUM value.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum CaddxThingType {
+ PANEL,
+ PARTITION,
+ ZONE,
+ KEYPAD;
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/LogEventMessage.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/LogEventMessage.java
new file mode 100644
index 0000000000000..d24be620b04c4
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/LogEventMessage.java
@@ -0,0 +1,94 @@
+/**
+ * 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.caddx.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.caddx.internal.CaddxMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Used to parse panel log event messages.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class LogEventMessage {
+ private final Logger logger = LoggerFactory.getLogger(LogEventMessage.class);
+
+ public final String number;
+ public final String size;
+ public final String type;
+ public final String zud;
+ public final String partition;
+ public final String month;
+ public final String day;
+ public final String hour;
+ public final String minute;
+
+ LogEventMessage(CaddxMessage message) {
+ this.number = message.getPropertyById("panel_log_event_number");
+ this.size = message.getPropertyById("panel_log_event_size");
+ this.type = message.getPropertyById("panel_log_event_type");
+ this.zud = message.getPropertyById("panel_log_event_zud");
+ this.partition = message.getPropertyById("panel_log_event_partition");
+ this.month = message.getPropertyById("panel_log_event_month");
+ this.day = message.getPropertyById("panel_log_event_day");
+ this.hour = message.getPropertyById("panel_log_event_hour");
+ this.minute = message.getPropertyById("panel_log_event_minute");
+ }
+
+ @Override
+ public String toString() {
+ try {
+ StringBuilder sb = new StringBuilder();
+
+ int eventType = Integer.parseInt(type);
+ logger.trace("eventType received: {}", eventType);
+ LogEventType logEventType = LogEventType.valueOfLogEventType(eventType);
+ if (logEventType == null) {
+ return "Unknown log event type received";
+ }
+
+ // Date
+ sb.append(String.format("%02d", Integer.parseInt(day))).append('-')
+ .append(String.format("%02d", Integer.parseInt(month))).append(' ')
+ .append(String.format("%02d", Integer.parseInt(hour))).append(':')
+ .append(String.format("%02d", Integer.parseInt(minute))).append(' ');
+
+ sb.append(logEventType.description);
+ if (logEventType.isPartitionValid) {
+ sb.append(" Partition ").append(Integer.parseInt(partition) + 1);
+ }
+
+ switch (logEventType.zud) {
+ case None:
+ break;
+ case Zone:
+ sb.append(" Zone ").append(Integer.parseInt(zud) + 1);
+ break;
+ case User:
+ sb.append(" User ").append(Integer.parseInt(zud) + 1);
+ break;
+ case Device:
+ sb.append(" Device ").append(zud);
+ break;
+ }
+
+ return sb.toString();
+ } catch (NumberFormatException e) {
+ logger.debug("LogEventMessage error. {}", e.getMessage(), e);
+ return "logmessage cannot be constructed";
+ }
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/LogEventType.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/LogEventType.java
new file mode 100644
index 0000000000000..8cfb457a70c69
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/LogEventType.java
@@ -0,0 +1,112 @@
+/**
+ * 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.caddx.internal.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * All the log event types
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public enum LogEventType {
+ ALARM(0, ZoneUserDevice.Zone, true, "Alarm"),
+ ALARM_RESTORE(1, ZoneUserDevice.Zone, true, "Alarm restore"),
+ BYPASS(2, ZoneUserDevice.Zone, true, "Bypass"),
+ BYPASS_RESTORE(3, ZoneUserDevice.Zone, true, "Bypass restore"),
+ TAMPER(4, ZoneUserDevice.Zone, true, "Tamper"),
+ TAMPER_RESTORE(5, ZoneUserDevice.Zone, true, "Tamper restore"),
+ TROUBLE(6, ZoneUserDevice.Zone, true, "Trouble"),
+ TROUBLE_RESTORE(7, ZoneUserDevice.Zone, true, "Trouble restore"),
+ TX_LOW_BATTERY(8, ZoneUserDevice.Zone, true, "TX low battery"),
+ TX_LOW_BATTERY_RESTORE(9, ZoneUserDevice.Zone, true, "TX low battery restore"),
+ ZONE_LOST(10, ZoneUserDevice.Zone, true, "Zone lost"),
+ ZONE_LOST_RESTORE(11, ZoneUserDevice.Zone, true, "Zone lost restore"),
+ START_OF_CROSS_TIME(12, ZoneUserDevice.Zone, true, "Start of cross time"),
+ SPECIAL_EXPANSION_EVENT(17, ZoneUserDevice.None, false, "Special expansion event"),
+ DURESS(18, ZoneUserDevice.None, true, "Duress"),
+ MANUAL_FIRE(19, ZoneUserDevice.None, true, "Manual fire"),
+ AUXILIARY2_PANIC(20, ZoneUserDevice.None, true, "Auxiliary 2 panic"),
+ PANIC(22, ZoneUserDevice.None, true, "Panic"),
+ KEYPAD_TAMPER(23, ZoneUserDevice.None, true, "Keypad tamper"),
+ CONTROL_BOX_TAMPER(24, ZoneUserDevice.Device, false, "Control box tamper"),
+ CONTROL_BOX_TAMPER_RESTORE(25, ZoneUserDevice.Device, false, "Control box tamper restore"),
+ AC_FAIL(26, ZoneUserDevice.Device, false, "AC fail"),
+ AC_FAIL_RESTORE(27, ZoneUserDevice.Device, false, "AC fail restore"),
+ LOW_BATTERY(28, ZoneUserDevice.Device, false, "Low battery"),
+ LOW_BATTERY_RESTORE(29, ZoneUserDevice.Device, false, "Low battery restore"),
+ OVER_CURRENT(30, ZoneUserDevice.Device, false, "Over-current"),
+ OVER_CURRENT_RESTORE(31, ZoneUserDevice.Device, false, "Over-current restore"),
+ SIREN_TAMPER(32, ZoneUserDevice.Device, false, "Siren tamper"),
+ SIREN_TAMPER_RESTORE(33, ZoneUserDevice.Device, false, "Siren tamper restore"),
+ TELEPHONE_FAULT(34, ZoneUserDevice.None, false, "Telephone fault"),
+ TELEPHONE_FAULT_RESTORE(35, ZoneUserDevice.None, false, "Telephone fault restore"),
+ EXPANDER_TROUBLE(36, ZoneUserDevice.Device, false, "Expander trouble"),
+ EXPANDER_TROUBLE_RESTORE(37, ZoneUserDevice.Device, false, "Expander trouble restore"),
+ FAIL_TO_COMMUNICATE(38, ZoneUserDevice.None, false, "Fail to communicate"),
+ LOG_FULL(39, ZoneUserDevice.None, false, "Log full"),
+ OPENING(40, ZoneUserDevice.User, true, "Opening"),
+ CLOSING(41, ZoneUserDevice.User, true, "Closing"),
+ EXIT_ERROR(42, ZoneUserDevice.User, true, "Exit error"),
+ RECENT_CLOSING(43, ZoneUserDevice.User, true, "Recent closing"),
+ AUTO_TEST(44, ZoneUserDevice.None, false, "Auto-test"),
+ START_PROGRAM(45, ZoneUserDevice.None, false, "Start program"),
+ END_PROGRAM(46, ZoneUserDevice.None, false, "End program"),
+ START_DOWNLOAD(47, ZoneUserDevice.None, false, "Start download"),
+ END_DOWNLOAD(48, ZoneUserDevice.None, false, "End download"),
+ CANCEL(49, ZoneUserDevice.User, true, "Cancel"),
+ GROUND_FAULT(50, ZoneUserDevice.None, false, "Ground fault"),
+ GROUND_FAULT_RESTORE(51, ZoneUserDevice.None, false, "Ground fault restore"),
+ MANUAL_TEST(52, ZoneUserDevice.None, false, "Manual test"),
+ CLOSED_WITH_ZONES_BYPASSED(53, ZoneUserDevice.User, true, "Closed with zones bypassed"),
+ START_OF_LISTEN_IN(54, ZoneUserDevice.None, false, "Start of listen in"),
+ TECHNICIAN_ON_SITE(55, ZoneUserDevice.None, false, "Technician on site"),
+ TECHNICIAN_LEFT(56, ZoneUserDevice.None, false, "Technician left"),
+ CONTROL_POWER_UP(57, ZoneUserDevice.None, false, "Control power up"),
+ FIRST_TO_OPEN(120, ZoneUserDevice.User, true, "First to open"),
+ LAST_TO_CLOSE(121, ZoneUserDevice.User, true, "Last toC close"),
+ PIN_ENTERED_WITH_BIT7_SET(122, ZoneUserDevice.User, true, "PIN entered with bit 7 set"),
+ BEGIN_WALK_TEST(123, ZoneUserDevice.None, false, "Begin walk-test"),
+ END_WALK_TEST(124, ZoneUserDevice.None, false, "End walk-test"),
+ RE_EXIT(125, ZoneUserDevice.None, true, "Re-exit"),
+ OUTPUT_TRIP(126, ZoneUserDevice.User, false, "Output trip"),
+ DATA_LOST(127, ZoneUserDevice.None, false, "Data Lost");
+
+ private static final Map BY_LOG_EVENT_TYPE = new HashMap<>();
+ public final int eventType;
+ public final ZoneUserDevice zud;
+ public final boolean isPartitionValid;
+ public final String description;
+
+ LogEventType(int eventType, ZoneUserDevice zud, boolean isPartitionValid, String description) {
+ this.eventType = eventType;
+ this.zud = zud;
+ this.isPartitionValid = isPartitionValid;
+ this.description = description;
+ }
+
+ static {
+ for (LogEventType logEventType : values()) {
+ BY_LOG_EVENT_TYPE.put(logEventType.eventType, logEventType);
+ }
+ }
+
+ public static @Nullable LogEventType valueOfLogEventType(int eventType) {
+ return BY_LOG_EVENT_TYPE.get(eventType);
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java
new file mode 100644
index 0000000000000..c76ae16d03519
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerKeypad.java
@@ -0,0 +1,50 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.caddx.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.thing.ChannelUID;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingStatus;
+import org.eclipse.smarthome.core.types.Command;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+
+/**
+ * This is a class for handling a Keypad type Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class ThingHandlerKeypad extends CaddxBaseThingHandler {
+ /**
+ * Constructor.
+ *
+ * @param thing
+ */
+ public ThingHandlerKeypad(Thing thing) {
+ super(thing, CaddxThingType.KEYPAD);
+ }
+
+ @Override
+ public void updateChannel(ChannelUID channelUID, String data) {
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ }
+
+ @Override
+ public void caddxEventReceived(CaddxEvent event, Thing thing) {
+ updateStatus(ThingStatus.ONLINE);
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java
new file mode 100644
index 0000000000000..964766b7d5354
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPanel.java
@@ -0,0 +1,196 @@
+/**
+ * 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.caddx.internal.handler;
+
+import java.util.HashMap;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.smarthome.core.library.types.OnOffType;
+import org.eclipse.smarthome.core.library.types.StringType;
+import org.eclipse.smarthome.core.thing.ChannelUID;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingStatus;
+import org.eclipse.smarthome.core.types.Command;
+import org.eclipse.smarthome.core.types.RefreshType;
+import org.openhab.binding.caddx.internal.CaddxBindingConstants;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+import org.openhab.binding.caddx.internal.CaddxMessage;
+import org.openhab.binding.caddx.internal.CaddxMessageType;
+import org.openhab.binding.caddx.internal.CaddxProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a class for handling a Panel type Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class ThingHandlerPanel extends CaddxBaseThingHandler {
+ private final Logger logger = LoggerFactory.getLogger(ThingHandlerPanel.class);
+ private @Nullable HashMap panelLogMessagesMap = null;
+ private @Nullable String communicatorStackPointer = null;
+
+ /**
+ * Constructor.
+ *
+ * @param thing
+ */
+ public ThingHandlerPanel(Thing thing) {
+ super(thing, CaddxThingType.PANEL);
+ }
+
+ @Override
+ public void updateChannel(ChannelUID channelUID, String data) {
+ if (channelUID.getId().equals(CaddxBindingConstants.PANEL_FIRMWARE_VERSION)
+ || channelUID.getId().startsWith("panel_log_message_")) {
+ updateState(channelUID, new StringType(data));
+ } else {
+ // All Panel channels are OnOffType
+ OnOffType onOffType;
+
+ onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
+ updateState(channelUID, onOffType);
+ }
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ logger.trace("handleCommand(): Command Received - {} {}.", channelUID, command);
+
+ String cmd = null;
+ String data = null;
+ CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
+ if (bridgeHandler == null) {
+ return;
+ }
+
+ if (command instanceof RefreshType) {
+ if (CaddxBindingConstants.PANEL_FIRMWARE_VERSION.equals(channelUID.getId())) {
+ cmd = CaddxBindingConstants.PANEL_INTERFACE_CONFIGURATION_REQUEST;
+ data = "";
+ } else if (CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0.equals(channelUID.getId())) {
+ cmd = CaddxBindingConstants.PANEL_SYSTEM_STATUS_REQUEST;
+ data = "";
+ } else {
+ return;
+ }
+
+ bridgeHandler.sendCommand(cmd, data);
+ } else {
+ logger.debug("Unknown command {}", command);
+ }
+ }
+
+ @Override
+ public void caddxEventReceived(CaddxEvent event, Thing thing) {
+ logger.trace("caddxEventReceived(): Event Received - {}.", event);
+
+ if (getThing().equals(thing)) {
+ CaddxMessage message = event.getCaddxMessage();
+ CaddxMessageType mt = message.getCaddxMessageType();
+ ChannelUID channelUID = null;
+
+ // Log event messages have special handling
+ if (CaddxMessageType.SYSTEM_STATUS_MESSAGE.equals(mt)) {
+ handleSystemStatusMessage(message);
+ } else if (CaddxMessageType.LOG_EVENT_MESSAGE.equals(mt)) {
+ handleLogEventMessage(message);
+ } else {
+ for (CaddxProperty p : mt.properties) {
+ if (!p.getId().isEmpty()) {
+ String value = message.getPropertyById(p.getId());
+ channelUID = new ChannelUID(getThing().getUID(), p.getId());
+ updateChannel(channelUID, value);
+ }
+ }
+ }
+
+ updateStatus(ThingStatus.ONLINE);
+ }
+ }
+
+ /*
+ * Gets the pointer into the panel's log messages ring buffer
+ * and sends the command for the retrieval of the last event_message
+ */
+ private void handleSystemStatusMessage(CaddxMessage message) {
+ // Get the bridge handler
+ CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
+ if (bridgeHandler == null) {
+ return;
+ }
+
+ String pointer = message.getPropertyById("panel_communicator_stack_pointer");
+ communicatorStackPointer = pointer;
+
+ // build map of log message channels to event numbers
+ HashMap map = new HashMap();
+ map.put(pointer, CaddxBindingConstants.PANEL_LOG_MESSAGE_N_0);
+ bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, pointer);
+ panelLogMessagesMap = map;
+ }
+
+ /*
+ * This function handles the panel log messages.
+ * If the received event_number matches our communication stack pointer then this is the last panel message. The
+ * channel gets updated and the required log message requests are generated for the update of the other log message
+ * channels
+ */
+ private void handleLogEventMessage(CaddxMessage message) {
+ // Get the bridge handler
+ CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
+ if (bridgeHandler == null) {
+ return;
+ }
+
+ String eventNumberString = message.getPropertyById("panel_log_event_number");
+ String eventSizeString = message.getPropertyById("panel_log_event_size");
+
+ // build the message
+ LogEventMessage logEventMessage = new LogEventMessage(message);
+
+ logger.trace("Log_event: {}", logEventMessage);
+
+ // get the channel id from the map
+ HashMap logMap = panelLogMessagesMap;
+ if (logMap != null && logMap.containsKey(eventNumberString)) {
+ String id = logMap.get(eventNumberString);
+ ChannelUID channelUID = new ChannelUID(getThing().getUID(), id);
+ updateChannel(channelUID, logEventMessage.toString());
+ }
+
+ if (communicatorStackPointer != null && eventNumberString.equals(communicatorStackPointer)) {
+ HashMap map = new HashMap();
+
+ int eventNumber = Integer.parseInt(eventNumberString);
+ int eventSize = Integer.parseInt(eventSizeString);
+
+ // Retrieve at maximum the 10 last log messages from the panel
+ int messagesToRetrieve = Math.min(eventSize, 10);
+ for (int i = 1; i < messagesToRetrieve; i++) {
+ eventNumber--;
+ if (eventNumber < 0) {
+ eventNumber = eventSize;
+ }
+
+ map.put(Integer.toString(eventNumber), "panel_log_message_n_" + i);
+ bridgeHandler.sendCommand(CaddxBindingConstants.PANEL_LOG_EVENT_REQUEST, Integer.toString(eventNumber));
+ }
+
+ communicatorStackPointer = null;
+ panelLogMessagesMap = map;
+ }
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java
new file mode 100644
index 0000000000000..5a9ec37de49f0
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerPartition.java
@@ -0,0 +1,116 @@
+/**
+ * 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.caddx.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.library.types.DecimalType;
+import org.eclipse.smarthome.core.library.types.OnOffType;
+import org.eclipse.smarthome.core.thing.ChannelUID;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingStatus;
+import org.eclipse.smarthome.core.types.Command;
+import org.eclipse.smarthome.core.types.RefreshType;
+import org.openhab.binding.caddx.internal.CaddxBindingConstants;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+import org.openhab.binding.caddx.internal.CaddxMessage;
+import org.openhab.binding.caddx.internal.CaddxMessageType;
+import org.openhab.binding.caddx.internal.CaddxProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a class for handling a Partition type Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class ThingHandlerPartition extends CaddxBaseThingHandler {
+
+ private final Logger logger = LoggerFactory.getLogger(ThingHandlerPartition.class);
+
+ /**
+ * Constructor.
+ *
+ * @param thing
+ */
+ public ThingHandlerPartition(Thing thing) {
+ super(thing, CaddxThingType.PARTITION);
+ }
+
+ @Override
+ public void updateChannel(ChannelUID channelUID, String data) {
+ if (CaddxBindingConstants.PARTITION_SECONDARY_COMMAND.equals(channelUID.getId())) {
+ updateState(channelUID, new DecimalType(data));
+ } else {
+ OnOffType onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
+ updateState(channelUID, onOffType);
+ }
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ logger.debug("handleCommand(): Command Received - {} {}.", channelUID, command);
+
+ String cmd = null;
+ String data = null;
+ CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
+ if (bridgeHandler == null) {
+ return;
+ }
+
+ if (command instanceof RefreshType) {
+ if (channelUID.getId().equals(CaddxBindingConstants.PARTITION_ARMED)) {
+ cmd = CaddxBindingConstants.PARTITION_STATUS_REQUEST;
+ data = String.format("%d", getPartitionNumber() - 1);
+ } else {
+ return;
+ }
+ } else if (channelUID.getId().equals(CaddxBindingConstants.PARTITION_SECONDARY_COMMAND)) {
+ cmd = channelUID.getId();
+ data = String.format("%s,%d", command.toString(), (1 << getPartitionNumber() - 1));
+ } else {
+ logger.debug("Unknown command {}", command);
+ return;
+ }
+
+ if (!data.startsWith("-")) {
+ bridgeHandler.sendCommand(cmd, data);
+ }
+ }
+
+ @Override
+ public void caddxEventReceived(CaddxEvent event, Thing thing) {
+ logger.trace("caddxEventReceived(): Event Received - {}", event);
+
+ if (getThing().equals(thing)) {
+ CaddxMessage message = event.getCaddxMessage();
+ CaddxMessageType mt = message.getCaddxMessageType();
+ ChannelUID channelUID = null;
+
+ for (CaddxProperty p : mt.properties) {
+ if (!p.getId().isEmpty()) {
+ String value = message.getPropertyById(p.getId());
+ channelUID = new ChannelUID(getThing().getUID(), p.getId());
+ updateChannel(channelUID, value);
+ }
+ }
+
+ // Reset the command
+ String value = "-1";
+ channelUID = new ChannelUID(getThing().getUID(), CaddxBindingConstants.PARTITION_SECONDARY_COMMAND);
+ updateChannel(channelUID, value);
+
+ updateStatus(ThingStatus.ONLINE);
+ }
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java
new file mode 100644
index 0000000000000..32580811fcf8c
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ThingHandlerZone.java
@@ -0,0 +1,128 @@
+/**
+ * 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.caddx.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.core.library.types.OnOffType;
+import org.eclipse.smarthome.core.library.types.OpenClosedType;
+import org.eclipse.smarthome.core.library.types.StringType;
+import org.eclipse.smarthome.core.thing.ChannelUID;
+import org.eclipse.smarthome.core.thing.Thing;
+import org.eclipse.smarthome.core.thing.ThingStatus;
+import org.eclipse.smarthome.core.types.Command;
+import org.eclipse.smarthome.core.types.RefreshType;
+import org.openhab.binding.caddx.internal.CaddxBindingConstants;
+import org.openhab.binding.caddx.internal.CaddxEvent;
+import org.openhab.binding.caddx.internal.CaddxMessage;
+import org.openhab.binding.caddx.internal.CaddxMessageType;
+import org.openhab.binding.caddx.internal.CaddxProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is a class for handling a Zone type Thing.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+public class ThingHandlerZone extends CaddxBaseThingHandler {
+
+ private final Logger logger = LoggerFactory.getLogger(ThingHandlerZone.class);
+
+ /**
+ * Constructor.
+ *
+ * @param thing
+ */
+ public ThingHandlerZone(Thing thing) {
+ super(thing, CaddxThingType.ZONE);
+ }
+
+ @Override
+ public void updateChannel(ChannelUID channelUID, String data) {
+ if (channelUID.getId().equals(CaddxBindingConstants.ZONE_NAME)) {
+ getThing().setLabel(data);
+ updateState(channelUID, new StringType(data));
+
+ logger.trace(" updateChannel: {} = {}", channelUID, data);
+ } else if (channelUID.getId().equals(CaddxBindingConstants.ZONE_FAULTED)) {
+ OpenClosedType openClosedType = ("true".equals(data)) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
+ updateState(channelUID, openClosedType);
+
+ logger.trace(" updateChannel: {} = {}", channelUID, data);
+ } else {
+ OnOffType onOffType = ("true".equals(data)) ? OnOffType.ON : OnOffType.OFF;
+ updateState(channelUID, onOffType);
+
+ logger.trace(" updateChannel: {} = {}", channelUID, onOffType);
+ }
+ }
+
+ @Override
+ public void handleCommand(ChannelUID channelUID, Command command) {
+ logger.trace("handleCommand(): Command Received - {} {}.", channelUID, command);
+
+ String cmd1 = null;
+ String cmd2 = null;
+ String data = null;
+
+ if (command instanceof RefreshType) {
+ if (channelUID.getId().equals(CaddxBindingConstants.ZONE_FAULTED)) {
+ cmd1 = CaddxBindingConstants.ZONE_STATUS_REQUEST;
+ cmd2 = CaddxBindingConstants.ZONE_NAME_REQUEST;
+ data = String.format("%d", getZoneNumber() - 1);
+ } else {
+ return;
+ }
+ } else if (channelUID.getId().equals(CaddxBindingConstants.ZONE_BYPASSED)) {
+ cmd1 = channelUID.getId();
+ cmd2 = CaddxBindingConstants.ZONE_STATUS_REQUEST;
+ data = String.format("%d", getZoneNumber() - 1);
+ } else {
+ logger.debug("Unknown command {}", command);
+ return;
+ }
+
+ CaddxBridgeHandler bridgeHandler = getCaddxBridgeHandler();
+ if (bridgeHandler == null) {
+ return;
+ }
+ bridgeHandler.sendCommand(cmd1, data);
+ bridgeHandler.sendCommand(cmd2, data);
+ }
+
+ @Override
+ public void caddxEventReceived(CaddxEvent event, Thing thing) {
+ logger.trace("caddxEventReceived(): Event Received - {}", event);
+
+ if (getThing().equals(thing)) {
+ CaddxMessage message = event.getCaddxMessage();
+ CaddxMessageType mt = message.getCaddxMessageType();
+ ChannelUID channelUID = null;
+
+ for (CaddxProperty p : mt.properties) {
+ logger.trace(" Checking property: {}", p.getName());
+
+ if (!p.getId().isEmpty()) {
+ String value = message.getPropertyById(p.getId());
+ channelUID = new ChannelUID(getThing().getUID(), p.getId());
+ updateChannel(channelUID, value);
+
+ logger.trace(" updateChannel: {} = {}", channelUID, value);
+ }
+ }
+
+ updateStatus(ThingStatus.ONLINE);
+ }
+ }
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ZoneUserDevice.java b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ZoneUserDevice.java
new file mode 100644
index 0000000000000..83539634df35c
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/java/org/openhab/binding/caddx/internal/handler/ZoneUserDevice.java
@@ -0,0 +1,28 @@
+/**
+ * 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.caddx.internal.handler;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * Zone, User, Device enumeration.
+ *
+ * @author Georgios Moutsos - Initial contribution
+ */
+@NonNullByDefault
+enum ZoneUserDevice {
+ None,
+ Zone,
+ User,
+ Device
+}
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/binding/binding.xml
new file mode 100644
index 0000000000000..27713623935ee
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/binding/binding.xml
@@ -0,0 +1,9 @@
+
+
+
+ Caddx Security Binding
+ Binding for Caddx security system with RS232 serial interface.
+ Georgios Moutsos
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/bridge.xml
new file mode 100644
index 0000000000000..96e4d779165b4
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/bridge.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+ This bridge represents the Caddx Serial interface.
+
+
+
+
+ Sends an Alarm Panel Command
+
+
+
+
+
+ serial-port
+
+ The serial port name for the communication. Valid values
+ are e.g. COM1 for Windows and /dev/ttyS0 or
+ /dev/ttyUSB0 for Linux.
+
+
+
+
+ The baud rate of the serial port. Valid values for the NX-584E are 600, 1200, 2400, 4800, 9600
+ (default), 19200, 38400, and 76800. Valid values for the NX-8E are 2400, 4800, 9600
+ (default), 19200 and 38400.
+ 9600
+
+
+
+
+
+
+
+
+
+
+
+
+
+ protocol
+
+ The configured panel protocol. Valid values
+ are Binary and Ascii.
+ Binary
+
+
+
+
+
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/channels.xml
new file mode 100644
index 0000000000000..86d06e2e13ed2
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/channels.xml
@@ -0,0 +1,126 @@
+
+
+
+
+
+ Switch
+
+ Reset Switch
+
+
+
+ String
+
+ Sends a Command
+
+
+
+
+ String
+
+ Panel text
+
+
+
+
+ Switch
+
+ Panel flag
+
+
+
+
+
+ Switch
+
+ Partition Condition
+
+
+
+
+ Number
+
+ Partition secondary command
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ String
+
+ Zone text
+
+
+
+
+ Switch
+
+ Zone Partition
+
+
+
+
+ Switch
+
+ Zone Type
+
+
+
+
+ Switch
+
+ Zone Condition
+
+
+
+
+ Contact
+
+ Zone Status (Open/Closed)
+
+
+
+
+ Switch
+
+ Bypass Mode (OFF=Armed, ON=Bypassed)
+
+
+
+
+ Number
+
+ Keypad Led (0=Off, 1=On, 2=Flashing)
+
+
+
+
+
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/keypad.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/keypad.xml
new file mode 100644
index 0000000000000..b339f196825c9
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/keypad.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+ Represents any of the keypads of the Caddx Alarm System.
+
+ keypadAddress
+
+
+
+
+ The Keypad Address.
+
+
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/panel.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/panel.xml
new file mode 100644
index 0000000000000..4cce0123e59a0
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/panel.xml
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+ The basic representation of the Caddx Alarm System.
+
+
+
+
+ Firmware version
+
+
+
+
+ Log message 10
+
+
+
+ Log message 9
+
+
+
+ Log message 8
+
+
+
+ Log message 7
+
+
+
+ Log message 6
+
+
+
+ Log message 5
+
+
+
+ Log message 4
+
+
+
+ Log message 3
+
+
+
+ Log message 2
+
+
+
+ Log message 1
+
+
+
+
+ Interface Configuration Message
+
+
+
+ Zone Status Message
+
+
+
+ Zones Snapshot Message
+
+
+
+ Partition Status Message
+
+
+
+ Partitions Snapshot Message
+
+
+
+
+ System Status Message
+
+
+
+ X-10 Message Received
+
+
+
+ Log Event Message
+
+
+
+ Keypad Message Received
+
+
+
+
+ Interface Configuration Request
+
+
+
+ Zone Name Request
+
+
+
+ Zone Status Request
+
+
+
+ Zones Snapshot Request
+
+
+
+ Partition Status Request
+
+
+
+ Partitions Snapshot Request
+
+
+
+
+ System Status Request
+
+
+
+ Send X-10 Message
+
+
+
+ Log Event Request
+
+
+
+ Send Keypad Text Message
+
+
+
+ Keypad Terminal Mode Request
+
+
+
+
+ Program Data Request
+
+
+
+ Program Data Command
+
+
+
+ User Information Request with PIN
+
+
+
+ User Information Request without PIN
+
+
+
+ Set User Code Command with PIN
+
+
+
+ Set User Code Command without PIN
+
+
+
+ Set User Authorization Command with PIN
+
+
+
+ Set User Authorization Command without PIN
+
+
+
+
+ Store Communication Event Command
+
+
+
+ Set Clock / Calendar Command
+
+
+
+ Primary Keypad Function with PIN
+
+
+
+ Primary Keypad Function without PIN
+
+
+
+ Secondary Keypad Function
+
+
+
+ Zone Bypass Toggle
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/partition.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/partition.xml
new file mode 100644
index 0000000000000..b91e60518d557
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/partition.xml
@@ -0,0 +1,224 @@
+
+
+
+
+
+
+
+
+
+ Represents a controllable area within a Caddx Alarm System.
+
+
+
+
+ Bypass code required
+
+
+
+ Fire trouble
+
+
+
+ Fire
+
+
+
+ Pulsing Buzzer
+
+
+
+ TLM fault memory
+
+
+
+ Armed
+
+
+
+ Instant
+
+
+
+
+ Previous Alarm
+
+
+
+ Siren on
+
+
+
+ Steady siren on
+
+
+
+ Alarm memory
+
+
+
+ Tamper
+
+
+
+ Cancel command entered
+
+
+
+ Code entered
+
+
+
+ Cancel pending
+
+
+
+
+ Silent exit enabled
+
+
+
+ Entryguard (stay mode)
+
+
+
+ Chime mode on
+
+
+
+ Entry
+
+
+
+ Delay expiration warning
+
+
+
+ Exit1
+
+
+
+ Exit2
+
+
+
+
+ Led extinguish
+
+
+
+ Cross timing
+
+
+
+ Recent closing being timed
+
+
+
+ Exit error triggered
+
+
+
+ Auto home inhibited
+
+
+
+ Sensor low battery
+
+
+
+ Sensor lost supervision
+
+
+
+
+ Zone bypassed
+
+
+
+ Force arm triggered by auto arm
+
+
+
+ Ready to arm
+
+
+
+ Ready to force arm
+
+
+
+ Valid PIN accepted
+
+
+
+ Chime on (sounding)
+
+
+
+ Error beep (triple beep)
+
+
+
+ Tone on (activation tone)
+
+
+
+
+ Entry 1
+
+
+
+ Open period
+
+
+
+ Alarm sent using phone number 1
+
+
+
+ Alarm sent using phone number 2
+
+
+
+ Alarm sent using phone number 3
+
+
+
+ Cancel report is in the stack
+
+
+
+ Keyswitch armed
+
+
+
+ Delay Trip in progress (common zone)
+
+
+
+
+ Partition Secondary Command
+
+
+
+ partitionNumber
+
+
+
+
+ The Partition Number.
+ 1
+
+
+
+ The User Number.
+ 1
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/zone.xml b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/zone.xml
new file mode 100644
index 0000000000000..a83f024e1b84d
--- /dev/null
+++ b/bundles/org.openhab.binding.caddx/src/main/resources/ESH-INF/thing/zone.xml
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+ Represents a physical device such as a door, window, or motion sensor.
+
+
+
+
+
+ Partition 1
+
+
+
+ Partition 2
+
+
+
+ Partition 3
+
+
+
+ Partition 4
+
+
+
+ Partition 5
+
+
+
+ Partition 6
+
+
+
+ Partition 7
+
+
+
+ Partition 8
+
+
+
+
+
+ Name
+
+
+
+
+
+ Fire
+
+
+
+ 24 Hour
+
+
+
+ Key-switch
+
+
+
+ Follower
+
+
+
+ Entry / exit delay 1
+
+
+
+ Entry / exit delay 2
+
+
+
+ Interior
+
+
+
+ Local only
+
+
+
+
+ Keypad Sounder
+
+
+
+ Yelping siren
+
+
+
+ Steady siren
+
+
+
+ Chime
+
+
+
+ Bypassable
+
+
+
+ Group bypassable
+
+
+
+ Force armable
+
+
+
+ Entry guard
+
+
+
+
+ Fast loop response
+
+
+
+ Double EOL tamper
+
+
+
+ Trouble
+
+
+
+ Cross zone
+
+
+
+ Dialer delay
+
+
+
+ Swinger shutdown
+
+
+
+ Restorable
+
+
+
+ Listen in
+
+
+
+
+
+ Faulted (or delayed trip)
+
+
+
+ Tampered
+
+
+
+ Trouble
+
+
+
+ Bypassed
+
+
+
+ Inhibited (force armed)
+
+
+
+ Low Battery
+
+
+
+ Loss of supervision
+
+
+
+ Alarm memory
+
+
+
+ Bypass memory
+
+
+
+ zoneNumber
+
+
+
+
+ The Zone Number.
+
+
+
+
+
+
diff --git a/bundles/org.openhab.binding.cbus/pom.xml b/bundles/org.openhab.binding.cbus/pom.xml
index 8322e90119a5a..26f20f12cd378 100644
--- a/bundles/org.openhab.binding.cbus/pom.xml
+++ b/bundles/org.openhab.binding.cbus/pom.xml
@@ -6,7 +6,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.cbus
diff --git a/bundles/org.openhab.binding.chromecast/pom.xml b/bundles/org.openhab.binding.chromecast/pom.xml
index 50a93f10cd44d..8088c14d7a403 100644
--- a/bundles/org.openhab.binding.chromecast/pom.xml
+++ b/bundles/org.openhab.binding.chromecast/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.chromecast
diff --git a/bundles/org.openhab.binding.cm11a/pom.xml b/bundles/org.openhab.binding.cm11a/pom.xml
index afd4a5a55df12..a02a1df730af7 100644
--- a/bundles/org.openhab.binding.cm11a/pom.xml
+++ b/bundles/org.openhab.binding.cm11a/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.cm11a
diff --git a/bundles/org.openhab.binding.coolmasternet/pom.xml b/bundles/org.openhab.binding.coolmasternet/pom.xml
index 87267f3bc043e..54ae0d5d735f1 100644
--- a/bundles/org.openhab.binding.coolmasternet/pom.xml
+++ b/bundles/org.openhab.binding.coolmasternet/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.coolmasternet
diff --git a/bundles/org.openhab.binding.coronastats/pom.xml b/bundles/org.openhab.binding.coronastats/pom.xml
index f6348b1878dc5..bfbd8fa2f6a25 100644
--- a/bundles/org.openhab.binding.coronastats/pom.xml
+++ b/bundles/org.openhab.binding.coronastats/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.coronastats
diff --git a/bundles/org.openhab.binding.daikin/pom.xml b/bundles/org.openhab.binding.daikin/pom.xml
index 175f8bde29f6b..b962bbfd7e794 100644
--- a/bundles/org.openhab.binding.daikin/pom.xml
+++ b/bundles/org.openhab.binding.daikin/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.daikin
diff --git a/bundles/org.openhab.binding.danfossairunit/pom.xml b/bundles/org.openhab.binding.danfossairunit/pom.xml
index 5b89503f32e60..fb95c688d01c1 100644
--- a/bundles/org.openhab.binding.danfossairunit/pom.xml
+++ b/bundles/org.openhab.binding.danfossairunit/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.danfossairunit
diff --git a/bundles/org.openhab.binding.darksky/pom.xml b/bundles/org.openhab.binding.darksky/pom.xml
index 3d15c1c88ae61..20fd662ef9a2d 100644
--- a/bundles/org.openhab.binding.darksky/pom.xml
+++ b/bundles/org.openhab.binding.darksky/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.darksky
diff --git a/bundles/org.openhab.binding.deconz/pom.xml b/bundles/org.openhab.binding.deconz/pom.xml
index b6bc8130c15c3..7c5862a85b352 100644
--- a/bundles/org.openhab.binding.deconz/pom.xml
+++ b/bundles/org.openhab.binding.deconz/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.deconz
diff --git a/bundles/org.openhab.binding.denonmarantz/pom.xml b/bundles/org.openhab.binding.denonmarantz/pom.xml
index 894ce99b4c903..85c07b048dc40 100644
--- a/bundles/org.openhab.binding.denonmarantz/pom.xml
+++ b/bundles/org.openhab.binding.denonmarantz/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.denonmarantz
diff --git a/bundles/org.openhab.binding.digiplex/pom.xml b/bundles/org.openhab.binding.digiplex/pom.xml
index 0963420b956ae..88ae0e2bcaa70 100644
--- a/bundles/org.openhab.binding.digiplex/pom.xml
+++ b/bundles/org.openhab.binding.digiplex/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.digiplex
diff --git a/bundles/org.openhab.binding.digitalstrom/pom.xml b/bundles/org.openhab.binding.digitalstrom/pom.xml
index a436cd673a79c..d3f8afdcadb40 100644
--- a/bundles/org.openhab.binding.digitalstrom/pom.xml
+++ b/bundles/org.openhab.binding.digitalstrom/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.digitalstrom
diff --git a/bundles/org.openhab.binding.dlinksmarthome/pom.xml b/bundles/org.openhab.binding.dlinksmarthome/pom.xml
index 32677d945698c..40bbd2eb6c448 100644
--- a/bundles/org.openhab.binding.dlinksmarthome/pom.xml
+++ b/bundles/org.openhab.binding.dlinksmarthome/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.dlinksmarthome
diff --git a/bundles/org.openhab.binding.dmx/pom.xml b/bundles/org.openhab.binding.dmx/pom.xml
index ff32f6fcfaa07..ab17b432365c0 100644
--- a/bundles/org.openhab.binding.dmx/pom.xml
+++ b/bundles/org.openhab.binding.dmx/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.dmx
diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/DmxActions.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/DmxActions.java
index 942b96c56bf47..7c79a9466e342 100644
--- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/DmxActions.java
+++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/DmxActions.java
@@ -12,6 +12,9 @@
*/
package org.openhab.binding.dmx.action;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.binding.ThingActions;
@@ -25,20 +28,26 @@
/**
* The {@link DmxActions} provides actions for DMX Bridges
+ *
+ * Note:The static method invokeMethodOf handles the case where
+ * the test actions instanceof DmxActions fails. This test can fail
+ * due to an issue in openHAB core v2.5.0 where the {@link DmxActions} class
+ * can be loaded by a different classloader than the actions instance.
*
* @author Jan N. Klug - Initial contribution
*/
@ThingActionsScope(name = "dmx")
@NonNullByDefault
-public class DmxActions implements ThingActions {
+public class DmxActions implements ThingActions, IDmxActions {
private final Logger logger = LoggerFactory.getLogger(DmxActions.class);
private @Nullable DmxBridgeHandler handler;
+ @Override
@RuleAction(label = "DMX Output", description = "immediately performs fade on selected DMX channels")
- void sendFade(@ActionInput(name = "channels") @Nullable String channels,
+ public void sendFade(@ActionInput(name = "channels") @Nullable String channels,
@ActionInput(name = "fade") @Nullable String fade,
@ActionInput(name = "resumeAfter") @Nullable Boolean resumeAfter) {
logger.debug("thingHandlerAction called with inputs: {} {} {}", channels, fade, resumeAfter);
@@ -68,11 +77,26 @@ void sendFade(@ActionInput(name = "channels") @Nullable String channels,
public static void sendFade(@Nullable ThingActions actions, @Nullable String channels, @Nullable String fade,
@Nullable Boolean resumeAfter) {
- if (actions instanceof DmxActions) {
- ((DmxActions) actions).sendFade(channels, fade, resumeAfter);
- } else {
- throw new IllegalArgumentException("Instance is not an DmxActions class.");
+ invokeMethodOf(actions).sendFade(channels, fade, resumeAfter);
+ }
+
+ private static IDmxActions invokeMethodOf(@Nullable ThingActions actions) {
+ if (actions == null) {
+ throw new IllegalArgumentException("actions cannot be null");
+ }
+ if (actions.getClass().getName().equals(DmxActions.class.getName())) {
+ if (actions instanceof IDmxActions) {
+ return (IDmxActions) actions;
+ } else {
+ return (IDmxActions) Proxy.newProxyInstance(IDmxActions.class.getClassLoader(),
+ new Class[] { IDmxActions.class }, (Object proxy, Method method, Object[] args) -> {
+ Method m = actions.getClass().getDeclaredMethod(method.getName(),
+ method.getParameterTypes());
+ return m.invoke(actions, args);
+ });
+ }
}
+ throw new IllegalArgumentException("Actions is not an instance of DmxActions");
}
@Override
diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/IDmxActions.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/IDmxActions.java
new file mode 100644
index 0000000000000..9444044263e8c
--- /dev/null
+++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/action/IDmxActions.java
@@ -0,0 +1,27 @@
+/**
+ * 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.dmx.action;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link IDmxActions} defines the actions for DMX Bridges
+ *
+ * @author Laurent Garnier - Initial contribution
+ */
+@NonNullByDefault
+public interface IDmxActions {
+
+ public void sendFade(@Nullable String channels, @Nullable String fade, @Nullable Boolean resumeAfter);
+}
diff --git a/bundles/org.openhab.binding.doorbird/pom.xml b/bundles/org.openhab.binding.doorbird/pom.xml
index dd02f8810ec4f..d5514cb484dad 100644
--- a/bundles/org.openhab.binding.doorbird/pom.xml
+++ b/bundles/org.openhab.binding.doorbird/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.doorbird
diff --git a/bundles/org.openhab.binding.dscalarm/pom.xml b/bundles/org.openhab.binding.dscalarm/pom.xml
index 571b3247f9db8..0e82cfc8ddaed 100644
--- a/bundles/org.openhab.binding.dscalarm/pom.xml
+++ b/bundles/org.openhab.binding.dscalarm/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.dscalarm
diff --git a/bundles/org.openhab.binding.dsmr/pom.xml b/bundles/org.openhab.binding.dsmr/pom.xml
index 069d363ace6d1..1bc1a7b109d23 100644
--- a/bundles/org.openhab.binding.dsmr/pom.xml
+++ b/bundles/org.openhab.binding.dsmr/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.dsmr
diff --git a/bundles/org.openhab.binding.dwdpollenflug/pom.xml b/bundles/org.openhab.binding.dwdpollenflug/pom.xml
index d78308d799dff..1cb0cf9d5d062 100644
--- a/bundles/org.openhab.binding.dwdpollenflug/pom.xml
+++ b/bundles/org.openhab.binding.dwdpollenflug/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.dwdpollenflug
diff --git a/bundles/org.openhab.binding.dwdunwetter/pom.xml b/bundles/org.openhab.binding.dwdunwetter/pom.xml
index 45800a42ef324..1ce459b8048e8 100644
--- a/bundles/org.openhab.binding.dwdunwetter/pom.xml
+++ b/bundles/org.openhab.binding.dwdunwetter/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.dwdunwetter
diff --git a/bundles/org.openhab.binding.ecobee/pom.xml b/bundles/org.openhab.binding.ecobee/pom.xml
index b6612c2fd98c0..c110364a2da27 100644
--- a/bundles/org.openhab.binding.ecobee/pom.xml
+++ b/bundles/org.openhab.binding.ecobee/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.ecobee
diff --git a/bundles/org.openhab.binding.elerotransmitterstick/pom.xml b/bundles/org.openhab.binding.elerotransmitterstick/pom.xml
index 1ef3270453344..1de0a262c0691 100644
--- a/bundles/org.openhab.binding.elerotransmitterstick/pom.xml
+++ b/bundles/org.openhab.binding.elerotransmitterstick/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.elerotransmitterstick
diff --git a/bundles/org.openhab.binding.energenie/pom.xml b/bundles/org.openhab.binding.energenie/pom.xml
index f895cfe1e927d..3e98672fcf919 100644
--- a/bundles/org.openhab.binding.energenie/pom.xml
+++ b/bundles/org.openhab.binding.energenie/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.energenie
diff --git a/bundles/org.openhab.binding.enigma2/pom.xml b/bundles/org.openhab.binding.enigma2/pom.xml
index 17cd84b918f0b..fc35f8edc9488 100644
--- a/bundles/org.openhab.binding.enigma2/pom.xml
+++ b/bundles/org.openhab.binding.enigma2/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.enigma2
diff --git a/bundles/org.openhab.binding.enocean/pom.xml b/bundles/org.openhab.binding.enocean/pom.xml
index e4d0c6ed77f64..c75a01adb1760 100644
--- a/bundles/org.openhab.binding.enocean/pom.xml
+++ b/bundles/org.openhab.binding.enocean/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.enocean
diff --git a/bundles/org.openhab.binding.enturno/pom.xml b/bundles/org.openhab.binding.enturno/pom.xml
index a1d41b48d5f07..272da948d336a 100644
--- a/bundles/org.openhab.binding.enturno/pom.xml
+++ b/bundles/org.openhab.binding.enturno/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.enturno
diff --git a/bundles/org.openhab.binding.etherrain/pom.xml b/bundles/org.openhab.binding.etherrain/pom.xml
index 857e33fcdf5db..89754b90c586b 100644
--- a/bundles/org.openhab.binding.etherrain/pom.xml
+++ b/bundles/org.openhab.binding.etherrain/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.etherrain
diff --git a/bundles/org.openhab.binding.evohome/pom.xml b/bundles/org.openhab.binding.evohome/pom.xml
index c608c53e56cf1..16bb42ea9317f 100644
--- a/bundles/org.openhab.binding.evohome/pom.xml
+++ b/bundles/org.openhab.binding.evohome/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.evohome
diff --git a/bundles/org.openhab.binding.exec/pom.xml b/bundles/org.openhab.binding.exec/pom.xml
index 062fcb19f7fdf..b3e73dfeb407f 100644
--- a/bundles/org.openhab.binding.exec/pom.xml
+++ b/bundles/org.openhab.binding.exec/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.exec
diff --git a/bundles/org.openhab.binding.feed/pom.xml b/bundles/org.openhab.binding.feed/pom.xml
index f96cea39750f3..de353e43aad6c 100644
--- a/bundles/org.openhab.binding.feed/pom.xml
+++ b/bundles/org.openhab.binding.feed/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.feed
diff --git a/bundles/org.openhab.binding.feican/pom.xml b/bundles/org.openhab.binding.feican/pom.xml
index b36b62e9b012e..91f695a0a6505 100644
--- a/bundles/org.openhab.binding.feican/pom.xml
+++ b/bundles/org.openhab.binding.feican/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.feican
diff --git a/bundles/org.openhab.binding.fmiweather/pom.xml b/bundles/org.openhab.binding.fmiweather/pom.xml
index 3afa2f49a911e..7b3ce2fbc5c6d 100644
--- a/bundles/org.openhab.binding.fmiweather/pom.xml
+++ b/bundles/org.openhab.binding.fmiweather/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.fmiweather
diff --git a/bundles/org.openhab.binding.folding/pom.xml b/bundles/org.openhab.binding.folding/pom.xml
index d68475a08e7da..35ec3d38ddbbf 100644
--- a/bundles/org.openhab.binding.folding/pom.xml
+++ b/bundles/org.openhab.binding.folding/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.folding
diff --git a/bundles/org.openhab.binding.foobot/pom.xml b/bundles/org.openhab.binding.foobot/pom.xml
index 9bacc0a561610..3b0ea62350b18 100644
--- a/bundles/org.openhab.binding.foobot/pom.xml
+++ b/bundles/org.openhab.binding.foobot/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.foobot
diff --git a/bundles/org.openhab.binding.freebox/pom.xml b/bundles/org.openhab.binding.freebox/pom.xml
index 8ae72e026ca28..5d3aef4d2f001 100644
--- a/bundles/org.openhab.binding.freebox/pom.xml
+++ b/bundles/org.openhab.binding.freebox/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.freebox
diff --git a/bundles/org.openhab.binding.fronius/pom.xml b/bundles/org.openhab.binding.fronius/pom.xml
index 0d50e0acf215e..1e40308f20d4e 100644
--- a/bundles/org.openhab.binding.fronius/pom.xml
+++ b/bundles/org.openhab.binding.fronius/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.fronius
diff --git a/bundles/org.openhab.binding.fsinternetradio/pom.xml b/bundles/org.openhab.binding.fsinternetradio/pom.xml
index 19f291323692b..8429d5987d3e0 100644
--- a/bundles/org.openhab.binding.fsinternetradio/pom.xml
+++ b/bundles/org.openhab.binding.fsinternetradio/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.fsinternetradio
diff --git a/bundles/org.openhab.binding.ftpupload/pom.xml b/bundles/org.openhab.binding.ftpupload/pom.xml
index 66e3613d666a6..6d8bc718cd929 100644
--- a/bundles/org.openhab.binding.ftpupload/pom.xml
+++ b/bundles/org.openhab.binding.ftpupload/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.ftpupload
diff --git a/bundles/org.openhab.binding.gardena/pom.xml b/bundles/org.openhab.binding.gardena/pom.xml
index 4c89d5e4828aa..7709b50f00045 100644
--- a/bundles/org.openhab.binding.gardena/pom.xml
+++ b/bundles/org.openhab.binding.gardena/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.gardena
diff --git a/bundles/org.openhab.binding.globalcache/pom.xml b/bundles/org.openhab.binding.globalcache/pom.xml
index 54ba9c9ca1dfc..647f04cdb4d45 100644
--- a/bundles/org.openhab.binding.globalcache/pom.xml
+++ b/bundles/org.openhab.binding.globalcache/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.globalcache
diff --git a/bundles/org.openhab.binding.goecharger/pom.xml b/bundles/org.openhab.binding.goecharger/pom.xml
index ca935e9693bbb..4e7c3bf71ec2e 100644
--- a/bundles/org.openhab.binding.goecharger/pom.xml
+++ b/bundles/org.openhab.binding.goecharger/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.goecharger
diff --git a/bundles/org.openhab.binding.gpstracker/pom.xml b/bundles/org.openhab.binding.gpstracker/pom.xml
index 3d4c6327dd39b..dd193a056e470 100644
--- a/bundles/org.openhab.binding.gpstracker/pom.xml
+++ b/bundles/org.openhab.binding.gpstracker/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.gpstracker
diff --git a/bundles/org.openhab.binding.gree/README.md b/bundles/org.openhab.binding.gree/README.md
index 7f9d7af8a5ef7..fe2294e84b97e 100644
--- a/bundles/org.openhab.binding.gree/README.md
+++ b/bundles/org.openhab.binding.gree/README.md
@@ -70,7 +70,7 @@ Thing gree:airconditioner:a1234561 [ ipAddress="192.168.1.111", refresh=2 ]
```
Switch AirconPower { channel="gree:airconditioner:a1234561:power" }
-Number AirconMode { channel="gree:airconditioner:a1234561:mode" }
+String AirconMode { channel="gree:airconditioner:a1234561:mode" }
Switch AirconTurbo { channel="gree:airconditioner:a1234561:turbo" }
Switch AirconLight { channel="gree:airconditioner:a1234561:light" }
Number AirconTemp "Temperature [%.1f °C]" {channel="gree:airconditioner:a1234561:temperature" }
@@ -122,7 +122,7 @@ This example shows how to make a GREE Air Conditioner controllable by Google HA
```
Group Gree_Modechannel "Gree" { ga="Thermostat" } // allows mapping for Google Home Assistent
Switch GreeAirConditioner_Power "Aircon" {channel="gree:airconditioner:a1234561:power", ga="Switch"}
-Number GreeAirConditioner_Mode "Aircon Mode" {channel="gree:airconditioner:a1234561:mode", ga="thermostatMode"}
+String GreeAirConditioner_Mode "Aircon Mode" {channel="gree:airconditioner:a1234561:mode", ga="thermostatMode"}
Number GreeAirConditioner_Temp "Aircon Temperature" {channel="gree:airconditioner:a1234561:temperature}
Switch GreeAirConditioner_Lightl "Light" {channel="gree:airconditioner:a1234561:light"}
```
diff --git a/bundles/org.openhab.binding.gree/pom.xml b/bundles/org.openhab.binding.gree/pom.xml
index 8e0e96b29b4c9..1a0549035ddaa 100644
--- a/bundles/org.openhab.binding.gree/pom.xml
+++ b/bundles/org.openhab.binding.gree/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.gree
diff --git a/bundles/org.openhab.binding.groheondus/pom.xml b/bundles/org.openhab.binding.groheondus/pom.xml
index 0530478a245d9..6c83bdd00265a 100644
--- a/bundles/org.openhab.binding.groheondus/pom.xml
+++ b/bundles/org.openhab.binding.groheondus/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.groheondus
diff --git a/bundles/org.openhab.binding.harmonyhub/pom.xml b/bundles/org.openhab.binding.harmonyhub/pom.xml
index 20e5cd281b6a5..b91dd2685c52c 100644
--- a/bundles/org.openhab.binding.harmonyhub/pom.xml
+++ b/bundles/org.openhab.binding.harmonyhub/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.harmonyhub
diff --git a/bundles/org.openhab.binding.hdanywhere/pom.xml b/bundles/org.openhab.binding.hdanywhere/pom.xml
index f3463004c1bfb..aa1c86d7b924b 100644
--- a/bundles/org.openhab.binding.hdanywhere/pom.xml
+++ b/bundles/org.openhab.binding.hdanywhere/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.hdanywhere
diff --git a/bundles/org.openhab.binding.hdpowerview/pom.xml b/bundles/org.openhab.binding.hdpowerview/pom.xml
index c39aeb64fd33e..1d864e63d27d4 100644
--- a/bundles/org.openhab.binding.hdpowerview/pom.xml
+++ b/bundles/org.openhab.binding.hdpowerview/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.hdpowerview
diff --git a/bundles/org.openhab.binding.helios/pom.xml b/bundles/org.openhab.binding.helios/pom.xml
index 0dd0ef673beca..69187a5667acd 100644
--- a/bundles/org.openhab.binding.helios/pom.xml
+++ b/bundles/org.openhab.binding.helios/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.helios
diff --git a/bundles/org.openhab.binding.heliosventilation/pom.xml b/bundles/org.openhab.binding.heliosventilation/pom.xml
index 85cb9ed2b8622..fca759f31300c 100644
--- a/bundles/org.openhab.binding.heliosventilation/pom.xml
+++ b/bundles/org.openhab.binding.heliosventilation/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.heliosventilation
diff --git a/bundles/org.openhab.binding.heos/pom.xml b/bundles/org.openhab.binding.heos/pom.xml
index eb8029d468b11..77be0b4de9f9a 100644
--- a/bundles/org.openhab.binding.heos/pom.xml
+++ b/bundles/org.openhab.binding.heos/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.heos
diff --git a/bundles/org.openhab.binding.homematic/pom.xml b/bundles/org.openhab.binding.homematic/pom.xml
index 026f824f08382..f223e2bcdf5e4 100644
--- a/bundles/org.openhab.binding.homematic/pom.xml
+++ b/bundles/org.openhab.binding.homematic/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.homematic
diff --git a/bundles/org.openhab.binding.hpprinter/pom.xml b/bundles/org.openhab.binding.hpprinter/pom.xml
index 0ccf8de1703f0..f4023c3d9c894 100644
--- a/bundles/org.openhab.binding.hpprinter/pom.xml
+++ b/bundles/org.openhab.binding.hpprinter/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.hpprinter
diff --git a/bundles/org.openhab.binding.hue/pom.xml b/bundles/org.openhab.binding.hue/pom.xml
index 810e523cbd064..fcc489f2f8b90 100644
--- a/bundles/org.openhab.binding.hue/pom.xml
+++ b/bundles/org.openhab.binding.hue/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.hue
diff --git a/bundles/org.openhab.binding.hydrawise/pom.xml b/bundles/org.openhab.binding.hydrawise/pom.xml
index 43c7588f169e4..0be1bfa11fc15 100644
--- a/bundles/org.openhab.binding.hydrawise/pom.xml
+++ b/bundles/org.openhab.binding.hydrawise/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.hydrawise
diff --git a/bundles/org.openhab.binding.hyperion/pom.xml b/bundles/org.openhab.binding.hyperion/pom.xml
index 2b359356a1ec6..f6bf2a45d0231 100644
--- a/bundles/org.openhab.binding.hyperion/pom.xml
+++ b/bundles/org.openhab.binding.hyperion/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.hyperion
diff --git a/bundles/org.openhab.binding.iaqualink/pom.xml b/bundles/org.openhab.binding.iaqualink/pom.xml
index 3204fb692ca93..afe1ddac5f955 100644
--- a/bundles/org.openhab.binding.iaqualink/pom.xml
+++ b/bundles/org.openhab.binding.iaqualink/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.iaqualink
diff --git a/bundles/org.openhab.binding.icalendar/pom.xml b/bundles/org.openhab.binding.icalendar/pom.xml
index 182a702f2707b..0f2b5b6130fbc 100644
--- a/bundles/org.openhab.binding.icalendar/pom.xml
+++ b/bundles/org.openhab.binding.icalendar/pom.xml
@@ -3,7 +3,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.icalendar
openHAB Add-ons :: Bundles :: iCalendar Binding
diff --git a/bundles/org.openhab.binding.icloud/pom.xml b/bundles/org.openhab.binding.icloud/pom.xml
index dfad1654bf4ee..3ab69b6a3ac5a 100644
--- a/bundles/org.openhab.binding.icloud/pom.xml
+++ b/bundles/org.openhab.binding.icloud/pom.xml
@@ -4,7 +4,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.icloud
diff --git a/bundles/org.openhab.binding.ihc/pom.xml b/bundles/org.openhab.binding.ihc/pom.xml
index 152d926090f3d..d0c43c4f28f74 100644
--- a/bundles/org.openhab.binding.ihc/pom.xml
+++ b/bundles/org.openhab.binding.ihc/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.ihc
diff --git a/bundles/org.openhab.binding.innogysmarthome/pom.xml b/bundles/org.openhab.binding.innogysmarthome/pom.xml
index 9eeebbb89e409..92289b0fe6b78 100644
--- a/bundles/org.openhab.binding.innogysmarthome/pom.xml
+++ b/bundles/org.openhab.binding.innogysmarthome/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.innogysmarthome
diff --git a/bundles/org.openhab.binding.insteon/pom.xml b/bundles/org.openhab.binding.insteon/pom.xml
index e8ce56c33fa8c..5ac2198016be6 100644
--- a/bundles/org.openhab.binding.insteon/pom.xml
+++ b/bundles/org.openhab.binding.insteon/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.insteon
diff --git a/bundles/org.openhab.binding.ipp/pom.xml b/bundles/org.openhab.binding.ipp/pom.xml
index 266ffe8298475..a89d66f64e461 100644
--- a/bundles/org.openhab.binding.ipp/pom.xml
+++ b/bundles/org.openhab.binding.ipp/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.ipp
diff --git a/bundles/org.openhab.binding.irtrans/pom.xml b/bundles/org.openhab.binding.irtrans/pom.xml
index 8f509b4390fd0..176a1d9847d96 100644
--- a/bundles/org.openhab.binding.irtrans/pom.xml
+++ b/bundles/org.openhab.binding.irtrans/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.irtrans
diff --git a/bundles/org.openhab.binding.jeelink/pom.xml b/bundles/org.openhab.binding.jeelink/pom.xml
index 08315df0a7bb0..a4719b0b9c3d2 100644
--- a/bundles/org.openhab.binding.jeelink/pom.xml
+++ b/bundles/org.openhab.binding.jeelink/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.jeelink
diff --git a/bundles/org.openhab.binding.keba/pom.xml b/bundles/org.openhab.binding.keba/pom.xml
index 5ac4a1a44c25a..e724c9bfc9209 100644
--- a/bundles/org.openhab.binding.keba/pom.xml
+++ b/bundles/org.openhab.binding.keba/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.keba
diff --git a/bundles/org.openhab.binding.km200/pom.xml b/bundles/org.openhab.binding.km200/pom.xml
index 3880d38e283e1..69f2d24a53882 100644
--- a/bundles/org.openhab.binding.km200/pom.xml
+++ b/bundles/org.openhab.binding.km200/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.km200
diff --git a/bundles/org.openhab.binding.knx/pom.xml b/bundles/org.openhab.binding.knx/pom.xml
index 108269cbe5408..7931787f1d694 100644
--- a/bundles/org.openhab.binding.knx/pom.xml
+++ b/bundles/org.openhab.binding.knx/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.knx
diff --git a/bundles/org.openhab.binding.kodi/pom.xml b/bundles/org.openhab.binding.kodi/pom.xml
index 8775aab30ea90..7391839092ea5 100644
--- a/bundles/org.openhab.binding.kodi/pom.xml
+++ b/bundles/org.openhab.binding.kodi/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.kodi
diff --git a/bundles/org.openhab.binding.konnected/pom.xml b/bundles/org.openhab.binding.konnected/pom.xml
index 7bca10799c0ed..efe229da573e3 100644
--- a/bundles/org.openhab.binding.konnected/pom.xml
+++ b/bundles/org.openhab.binding.konnected/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.konnected
diff --git a/bundles/org.openhab.binding.kostalinverter/pom.xml b/bundles/org.openhab.binding.kostalinverter/pom.xml
index 735f4b0e53e3f..a2e87c9df9daa 100644
--- a/bundles/org.openhab.binding.kostalinverter/pom.xml
+++ b/bundles/org.openhab.binding.kostalinverter/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.kostalinverter
diff --git a/bundles/org.openhab.binding.lametrictime/pom.xml b/bundles/org.openhab.binding.lametrictime/pom.xml
index 83a00b4fb9fac..3b1287a0f2192 100644
--- a/bundles/org.openhab.binding.lametrictime/pom.xml
+++ b/bundles/org.openhab.binding.lametrictime/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lametrictime
diff --git a/bundles/org.openhab.binding.lcn/pom.xml b/bundles/org.openhab.binding.lcn/pom.xml
index ae8894d181b55..e67c66e2e2dc5 100644
--- a/bundles/org.openhab.binding.lcn/pom.xml
+++ b/bundles/org.openhab.binding.lcn/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lcn
diff --git a/bundles/org.openhab.binding.leapmotion/pom.xml b/bundles/org.openhab.binding.leapmotion/pom.xml
index 4d40ae43cc2c8..fd609fc4cab31 100644
--- a/bundles/org.openhab.binding.leapmotion/pom.xml
+++ b/bundles/org.openhab.binding.leapmotion/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.leapmotion
diff --git a/bundles/org.openhab.binding.lghombot/pom.xml b/bundles/org.openhab.binding.lghombot/pom.xml
index cbaee24e24b4c..5f857711083f1 100644
--- a/bundles/org.openhab.binding.lghombot/pom.xml
+++ b/bundles/org.openhab.binding.lghombot/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lghombot
diff --git a/bundles/org.openhab.binding.lgtvserial/pom.xml b/bundles/org.openhab.binding.lgtvserial/pom.xml
index 39b127fbf1ea6..9e28e8154286b 100644
--- a/bundles/org.openhab.binding.lgtvserial/pom.xml
+++ b/bundles/org.openhab.binding.lgtvserial/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lgtvserial
diff --git a/bundles/org.openhab.binding.lgwebos/pom.xml b/bundles/org.openhab.binding.lgwebos/pom.xml
index 81801cbc36fdc..8c9dcfb3b484f 100644
--- a/bundles/org.openhab.binding.lgwebos/pom.xml
+++ b/bundles/org.openhab.binding.lgwebos/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lgwebos
diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java
deleted file mode 100644
index d297fe9d00ccf..0000000000000
--- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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.lgwebos.action;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * This represents id and name of a WebOS application.
- *
- * @author Sebastian Prehn - Initial contribution
- */
-@NonNullByDefault
-public class Application {
- private String id;
- private String name;
-
- public Application(String id, String name) {
- this.id = id;
- this.name = name;
- }
-
- public String getId() {
- return id;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public String toString() {
- return "Application [id=" + id + ", name=" + name + "]";
- }
-}
diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/ILGWebOSActions.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/ILGWebOSActions.java
new file mode 100644
index 0000000000000..6de651eb8c775
--- /dev/null
+++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/ILGWebOSActions.java
@@ -0,0 +1,47 @@
+/**
+ * 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.lgwebos.action;
+
+import java.io.IOException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link ILGWebOSActions} defines the interface for all thing actions supported by the binding.
+ *
+ * @author Laurent Garnier - Initial contribution
+ */
+@NonNullByDefault
+public interface ILGWebOSActions {
+
+ public void showToast(String text) throws IOException;
+
+ public void showToast(String icon, String text) throws IOException;
+
+ public void launchBrowser(String url);
+
+ public void launchApplication(String appId);
+
+ public void launchApplication(String appId, String params);
+
+ public void sendText(String text);
+
+ public void sendButton(String button);
+
+ public void increaseChannel();
+
+ public void decreaseChannel();
+
+ public void sendRCButton(String rcButton);
+
+}
diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java
index 656d9a0c6c527..2a9b019978b35 100644
--- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java
+++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java
@@ -16,6 +16,8 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@@ -50,14 +52,19 @@
import com.google.gson.JsonParser;
/**
- * This is the automation engine action handler service for the
- * lgwebos action.
+ * The {@link LGWebOSActions} defines the thing actions for the LGwebOS binding.
+ *
+ * Note:The static method invokeMethodOf handles the case where
+ * the test actions instanceof LGWebOSActions fails. This test can fail
+ * due to an issue in openHAB core v2.5.0 where the {@link LGWebOSActions} class
+ * can be loaded by a different classloader than the actions instance.
*
* @author Sebastian Prehn - Initial contribution
+ * @author Laurent Garnier - new method invokeMethodOf + interface ILGWebOSActions
*/
@ThingActionsScope(name = "lgwebos")
@NonNullByDefault
-public class LGWebOSActions implements ThingActions {
+public class LGWebOSActions implements ThingActions, ILGWebOSActions {
private final Logger logger = LoggerFactory.getLogger(LGWebOSActions.class);
private final ResponseListener textInputListener = createTextInputStatusListener();
private @Nullable LGWebOSHandler handler;
@@ -94,6 +101,7 @@ private enum Button {
OK
}
+ @Override
@RuleAction(label = "@text/actionShowToastLabel", description = "@text/actionShowToastDesc")
public void showToast(
@ActionInput(name = "text", label = "@text/actionShowToastInputTextLabel", description = "@text/actionShowToastInputTextDesc") String text)
@@ -101,6 +109,7 @@ public void showToast(
getConnectedSocket().ifPresent(control -> control.showToast(text, createResponseListener()));
}
+ @Override
@RuleAction(label = "@text/actionShowToastWithIconLabel", description = "@text/actionShowToastWithIconLabel")
public void showToast(
@ActionInput(name = "icon", label = "@text/actionShowToastInputIconLabel", description = "@text/actionShowToastInputIconDesc") String icon,
@@ -114,6 +123,7 @@ public void showToast(
}
}
+ @Override
@RuleAction(label = "@text/actionLaunchBrowserLabel", description = "@text/actionLaunchBrowserDesc")
public void launchBrowser(
@ActionInput(name = "url", label = "@text/actionLaunchBrowserInputUrlLabel", description = "@text/actionLaunchBrowserInputUrlDesc") String url) {
@@ -136,11 +146,7 @@ private List getAppInfos() {
return appInfos;
}
- public List getApplications() {
- return getAppInfos().stream().map(appInfo -> new Application(appInfo.getId(), appInfo.getName()))
- .collect(Collectors.toList());
- }
-
+ @Override
@RuleAction(label = "@text/actionLaunchApplicationLabel", description = "@text/actionLaunchApplicationDesc")
public void launchApplication(
@ActionInput(name = "appId", label = "@text/actionLaunchApplicationInputAppIDLabel", description = "@text/actionLaunchApplicationInputAppIDDesc") String appId) {
@@ -154,6 +160,7 @@ public void launchApplication(
}
}
+ @Override
@RuleAction(label = "@text/actionLaunchApplicationWithParamsLabel", description = "@text/actionLaunchApplicationWithParamsDesc")
public void launchApplication(
@ActionInput(name = "appId", label = "@text/actionLaunchApplicationInputAppIDLabel", description = "@text/actionLaunchApplicationInputAppIDDesc") String appId,
@@ -177,6 +184,7 @@ public void launchApplication(
}
}
+ @Override
@RuleAction(label = "@text/actionSendTextLabel", description = "@text/actionSendTextDesc")
public void sendText(
@ActionInput(name = "text", label = "@text/actionSendTextInputTextLabel", description = "@text/actionSendTextInputTextDesc") String text) {
@@ -187,6 +195,7 @@ public void sendText(
});
}
+ @Override
@RuleAction(label = "@text/actionSendButtonLabel", description = "@text/actionSendButtonDesc")
public void sendButton(
@ActionInput(name = "text", label = "@text/actionSendButtonInputButtonLabel", description = "@text/actionSendButtonInputButtonDesc") String button) {
@@ -226,16 +235,19 @@ public void sendButton(
}
}
+ @Override
@RuleAction(label = "@text/actionIncreaseChannelLabel", description = "@text/actionIncreaseChannelDesc")
public void increaseChannel() {
getConnectedSocket().ifPresent(control -> control.channelUp(createResponseListener()));
}
+ @Override
@RuleAction(label = "@text/actionDecreaseChannelLabel", description = "@text/actionDecreaseChannelDesc")
public void decreaseChannel() {
getConnectedSocket().ifPresent(control -> control.channelDown(createResponseListener()));
}
+ @Override
@RuleAction(label = "@text/actionSendRCButtonLabel", description = "@text/actionSendRCButtonDesc")
public void sendRCButton(
@ActionInput(name = "text", label = "@text/actionSendRCButtonInputTextLabel", description = "@text/actionSendRCButtonInputTextDesc") String rcButton) {
@@ -286,91 +298,62 @@ public void onSuccess(@Nullable O object) {
// delegation methods for "legacy" rule support
- public static void showToast(@Nullable ThingActions actions, String text) throws IOException {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).showToast(text);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
+ private static ILGWebOSActions invokeMethodOf(@Nullable ThingActions actions) {
+ if (actions == null) {
+ throw new IllegalArgumentException("actions cannot be null");
+ }
+ if (actions.getClass().getName().equals(LGWebOSActions.class.getName())) {
+ if (actions instanceof ILGWebOSActions) {
+ return (ILGWebOSActions) actions;
+ } else {
+ return (ILGWebOSActions) Proxy.newProxyInstance(ILGWebOSActions.class.getClassLoader(),
+ new Class[] { ILGWebOSActions.class }, (Object proxy, Method method, Object[] args) -> {
+ Method m = actions.getClass().getDeclaredMethod(method.getName(),
+ method.getParameterTypes());
+ return m.invoke(actions, args);
+ });
+ }
}
+ throw new IllegalArgumentException("Actions is not an instance of LGWebOSActions");
}
- public static void showToast(@Nullable ThingActions actions, String icon, String text) throws IOException {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).showToast(icon, text);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ public static void showToast(@Nullable ThingActions actions, String text) throws IOException {
+ invokeMethodOf(actions).showToast(text);
}
- public static void launchBrowser(@Nullable ThingActions actions, String url) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).launchBrowser(url);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ public static void showToast(@Nullable ThingActions actions, String icon, String text) throws IOException {
+ invokeMethodOf(actions).showToast(icon, text);
}
- public static List getApplications(@Nullable ThingActions actions) {
- if (actions instanceof LGWebOSActions) {
- return ((LGWebOSActions) actions).getApplications();
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ public static void launchBrowser(@Nullable ThingActions actions, String url) {
+ invokeMethodOf(actions).launchBrowser(url);
}
public static void launchApplication(@Nullable ThingActions actions, String appId) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).launchApplication(appId);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).launchApplication(appId);
}
public static void launchApplication(@Nullable ThingActions actions, String appId, String param) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).launchApplication(appId, param);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).launchApplication(appId, param);
}
public static void sendText(@Nullable ThingActions actions, String text) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).sendText(text);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).sendText(text);
}
public static void sendButton(@Nullable ThingActions actions, String button) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).sendButton(button);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).sendButton(button);
}
public static void increaseChannel(@Nullable ThingActions actions) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).increaseChannel();
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).increaseChannel();
}
public static void decreaseChannel(@Nullable ThingActions actions) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).decreaseChannel();
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).decreaseChannel();
}
public static void sendRCButton(@Nullable ThingActions actions, String rcButton) {
- if (actions instanceof LGWebOSActions) {
- ((LGWebOSActions) actions).sendRCButton(rcButton);
- } else {
- throw new IllegalArgumentException("Instance is not an LGWebOSActions class.");
- }
+ invokeMethodOf(actions).sendRCButton(rcButton);
}
}
diff --git a/bundles/org.openhab.binding.lifx/pom.xml b/bundles/org.openhab.binding.lifx/pom.xml
index b1e77fb22ffd4..00a879d3d8d21 100644
--- a/bundles/org.openhab.binding.lifx/pom.xml
+++ b/bundles/org.openhab.binding.lifx/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lifx
diff --git a/bundles/org.openhab.binding.linky/pom.xml b/bundles/org.openhab.binding.linky/pom.xml
index e1458ac1ec5fe..edf1fb8bba4ac 100644
--- a/bundles/org.openhab.binding.linky/pom.xml
+++ b/bundles/org.openhab.binding.linky/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.linky
diff --git a/bundles/org.openhab.binding.linuxinput/pom.xml b/bundles/org.openhab.binding.linuxinput/pom.xml
index 4ec1aef7fb65d..f401f0453f73f 100644
--- a/bundles/org.openhab.binding.linuxinput/pom.xml
+++ b/bundles/org.openhab.binding.linuxinput/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.linuxinput
diff --git a/bundles/org.openhab.binding.lirc/pom.xml b/bundles/org.openhab.binding.lirc/pom.xml
index 943e8f52988b7..707514fa25676 100644
--- a/bundles/org.openhab.binding.lirc/pom.xml
+++ b/bundles/org.openhab.binding.lirc/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lirc
diff --git a/bundles/org.openhab.binding.logreader/pom.xml b/bundles/org.openhab.binding.logreader/pom.xml
index 9e5ec8791d1c7..f2e045b6b367e 100644
--- a/bundles/org.openhab.binding.logreader/pom.xml
+++ b/bundles/org.openhab.binding.logreader/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.logreader
diff --git a/bundles/org.openhab.binding.loxone/pom.xml b/bundles/org.openhab.binding.loxone/pom.xml
index 33627469aee64..152e0b858e33d 100644
--- a/bundles/org.openhab.binding.loxone/pom.xml
+++ b/bundles/org.openhab.binding.loxone/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.loxone
diff --git a/bundles/org.openhab.binding.lutron/pom.xml b/bundles/org.openhab.binding.lutron/pom.xml
index 392b133e3f719..a00e62b32341e 100644
--- a/bundles/org.openhab.binding.lutron/pom.xml
+++ b/bundles/org.openhab.binding.lutron/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.lutron
diff --git a/bundles/org.openhab.binding.mail/pom.xml b/bundles/org.openhab.binding.mail/pom.xml
index 4b777edebd1b4..9a9182be2a20c 100644
--- a/bundles/org.openhab.binding.mail/pom.xml
+++ b/bundles/org.openhab.binding.mail/pom.xml
@@ -1,12 +1,10 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mail
diff --git a/bundles/org.openhab.binding.max/pom.xml b/bundles/org.openhab.binding.max/pom.xml
index dba7f22f868a3..1e8aab2b9a40b 100644
--- a/bundles/org.openhab.binding.max/pom.xml
+++ b/bundles/org.openhab.binding.max/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.max
diff --git a/bundles/org.openhab.binding.mcp23017/pom.xml b/bundles/org.openhab.binding.mcp23017/pom.xml
index 25accad4fefdd..16ad255d28d39 100644
--- a/bundles/org.openhab.binding.mcp23017/pom.xml
+++ b/bundles/org.openhab.binding.mcp23017/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mcp23017
diff --git a/bundles/org.openhab.binding.melcloud/pom.xml b/bundles/org.openhab.binding.melcloud/pom.xml
index f1d577575029e..4072c7d3b8f03 100644
--- a/bundles/org.openhab.binding.melcloud/pom.xml
+++ b/bundles/org.openhab.binding.melcloud/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.melcloud
diff --git a/bundles/org.openhab.binding.meteoalerte/pom.xml b/bundles/org.openhab.binding.meteoalerte/pom.xml
index a865566c83a21..a32f2204bf985 100644
--- a/bundles/org.openhab.binding.meteoalerte/pom.xml
+++ b/bundles/org.openhab.binding.meteoalerte/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.meteoalerte
diff --git a/bundles/org.openhab.binding.meteoblue/pom.xml b/bundles/org.openhab.binding.meteoblue/pom.xml
index 5960ac8e19a35..7576386fb52ee 100644
--- a/bundles/org.openhab.binding.meteoblue/pom.xml
+++ b/bundles/org.openhab.binding.meteoblue/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.meteoblue
diff --git a/bundles/org.openhab.binding.meteostick/pom.xml b/bundles/org.openhab.binding.meteostick/pom.xml
index 61bfa2f1610e4..83a0b47a9aabb 100644
--- a/bundles/org.openhab.binding.meteostick/pom.xml
+++ b/bundles/org.openhab.binding.meteostick/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.meteostick
diff --git a/bundles/org.openhab.binding.miele/pom.xml b/bundles/org.openhab.binding.miele/pom.xml
index 08cd204072e68..803634e8374c7 100644
--- a/bundles/org.openhab.binding.miele/pom.xml
+++ b/bundles/org.openhab.binding.miele/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.miele
diff --git a/bundles/org.openhab.binding.mihome/pom.xml b/bundles/org.openhab.binding.mihome/pom.xml
index 254a58499b3c4..8bc783c19b98b 100644
--- a/bundles/org.openhab.binding.mihome/pom.xml
+++ b/bundles/org.openhab.binding.mihome/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mihome
diff --git a/bundles/org.openhab.binding.miio/pom.xml b/bundles/org.openhab.binding.miio/pom.xml
index fca6b1e77a6ff..9cdbe1b1b519a 100644
--- a/bundles/org.openhab.binding.miio/pom.xml
+++ b/bundles/org.openhab.binding.miio/pom.xml
@@ -3,7 +3,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.miio
openHAB Add-ons :: Bundles :: Xiaomi Mi IO Binding
diff --git a/bundles/org.openhab.binding.milight/pom.xml b/bundles/org.openhab.binding.milight/pom.xml
index eae1044f01a4e..e0f21f3cc534e 100644
--- a/bundles/org.openhab.binding.milight/pom.xml
+++ b/bundles/org.openhab.binding.milight/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.milight
diff --git a/bundles/org.openhab.binding.millheat/pom.xml b/bundles/org.openhab.binding.millheat/pom.xml
index bef30f86fb682..5e8715f4667b2 100644
--- a/bundles/org.openhab.binding.millheat/pom.xml
+++ b/bundles/org.openhab.binding.millheat/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.millheat
diff --git a/bundles/org.openhab.binding.minecraft/pom.xml b/bundles/org.openhab.binding.minecraft/pom.xml
index 33e3cee19606c..081e5758b535e 100644
--- a/bundles/org.openhab.binding.minecraft/pom.xml
+++ b/bundles/org.openhab.binding.minecraft/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.minecraft
diff --git a/bundles/org.openhab.binding.modbus.sunspec/pom.xml b/bundles/org.openhab.binding.modbus.sunspec/pom.xml
index 218e1e8643c30..f07af970da0e1 100644
--- a/bundles/org.openhab.binding.modbus.sunspec/pom.xml
+++ b/bundles/org.openhab.binding.modbus.sunspec/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.modbus.sunspec
diff --git a/bundles/org.openhab.binding.modbus/pom.xml b/bundles/org.openhab.binding.modbus/pom.xml
index 2de8a8f2898a2..b37a91cf91343 100644
--- a/bundles/org.openhab.binding.modbus/pom.xml
+++ b/bundles/org.openhab.binding.modbus/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.modbus
diff --git a/bundles/org.openhab.binding.mqtt.generic/pom.xml b/bundles/org.openhab.binding.mqtt.generic/pom.xml
index 7bb2ba6a16cb7..71971f95ae004 100644
--- a/bundles/org.openhab.binding.mqtt.generic/pom.xml
+++ b/bundles/org.openhab.binding.mqtt.generic/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mqtt.generic
diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml b/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml
index bfa06cef7dee8..29094a347eb1e 100644
--- a/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml
+++ b/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mqtt.homeassistant
diff --git a/bundles/org.openhab.binding.mqtt.homie/pom.xml b/bundles/org.openhab.binding.mqtt.homie/pom.xml
index dcebad45e9f24..f7234c74c2265 100644
--- a/bundles/org.openhab.binding.mqtt.homie/pom.xml
+++ b/bundles/org.openhab.binding.mqtt.homie/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mqtt.homie
diff --git a/bundles/org.openhab.binding.mqtt/README.md b/bundles/org.openhab.binding.mqtt/README.md
index 389ee3cabbcc9..c947aef6fa34a 100644
--- a/bundles/org.openhab.binding.mqtt/README.md
+++ b/bundles/org.openhab.binding.mqtt/README.md
@@ -54,6 +54,11 @@ For more security, the following optional parameters can be altered:
* __certificate__: The certificate hash. If **certificatepin** is set this hash is used to verify the connection. Clear to allow a new certificate pinning on the next connection attempt. If empty will be filled automatically by the next successful connection. An example input would be `SHA-256:83F9171E06A313118889F7D79302BD1B7A2042EE0CFD029ABF8DD06FFA6CD9D3`.
* __publickey__: The public key hash. If **publickeypin** is set this hash is used to verify the connection. Clear to allow a new public key pinning on the next connection attempt. If empty will be filled automatically by the next successful connection. An example input would be `SHA-256:83F9171E06A313118889F7D79302BD1B7A2042EE0CFD029ABF8DD06FFA6CD9D3`.
+By default discovery services (like homie or homeassistant) are enabled on a broker.
+This behaviour can be controlled with a configuration parameter.
+
+* __enableDiscovery__:If set to true, enables discovery on this broker, if set to false, disables discovery services on this broker.
+
## Supported Channels
You can extend your broker connection bridges with a channel:
diff --git a/bundles/org.openhab.binding.mqtt/pom.xml b/bundles/org.openhab.binding.mqtt/pom.xml
index 4fbbe89cd3e53..94a79a86b973d 100644
--- a/bundles/org.openhab.binding.mqtt/pom.xml
+++ b/bundles/org.openhab.binding.mqtt/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.mqtt
diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/TopicSubscribe.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/TopicSubscribe.java
index 99b51d4b7cc20..1adaed91eb894 100644
--- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/TopicSubscribe.java
+++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/TopicSubscribe.java
@@ -32,6 +32,8 @@ public class TopicSubscribe implements MqttMessageSubscriber {
final String topic;
final MQTTTopicDiscoveryParticipant topicDiscoveredListener;
+ private boolean isStarted = false;
+
/**
* Creates a {@link TopicSubscribe} object.
*
@@ -66,7 +68,10 @@ public void processMessage(String topic, byte[] payload) {
* @return Completes with true if successful. Completes with false if not connected yet. Exceptionally otherwise.
*/
public CompletableFuture start() {
- return connection == null ? CompletableFuture.completedFuture(true) : connection.subscribe(topic, this);
+ CompletableFuture startFuture = connection == null ? CompletableFuture.completedFuture(true)
+ : connection.subscribe(topic, this);
+ isStarted = true;
+ return startFuture;
}
/**
@@ -75,6 +80,18 @@ public CompletableFuture start() {
* @return Completes with true if successful. Exceptionally otherwise.
*/
public CompletableFuture stop() {
- return connection == null ? CompletableFuture.completedFuture(true) : connection.unsubscribe(topic, this);
+ CompletableFuture stopFuture = connection == null ? CompletableFuture.completedFuture(true)
+ : connection.unsubscribe(topic, this);
+ isStarted = false;
+ return stopFuture;
+ }
+
+ /**
+ * status of this topic subscription
+ *
+ * @return true if started
+ */
+ public boolean isStarted() {
+ return isStarted;
}
}
diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java
index 5b8fe39d3c319..7cf72707ae6b0 100644
--- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java
+++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java
@@ -118,17 +118,23 @@ public void initialize() {
discoveryTopics.forEach((topic, listenerMap) -> {
listenerMap.replaceAll((listener, oldTopicSubscribe) -> {
+ if (oldTopicSubscribe.isStarted()) {
+ oldTopicSubscribe.stop();
+ }
+
TopicSubscribe topicSubscribe = new TopicSubscribe(connection, topic, listener, thing.getUID());
- topicSubscribe.start().handle((result, ex) -> {
- if (ex != null) {
- logger.warn("Failed to subscribe {} to discovery topic {} on broker {}", listener, topic,
- thing.getUID());
- } else {
- logger.trace("Subscribed {} to discovery topic {} on broker {}", listener, topic,
- thing.getUID());
- }
- return null;
- });
+ if (discoveryEnabled()) {
+ topicSubscribe.start().handle((result, ex) -> {
+ if (ex != null) {
+ logger.warn("Failed to subscribe {} to discovery topic {} on broker {}", listener, topic,
+ thing.getUID());
+ } else {
+ logger.trace("Subscribed {} to discovery topic {} on broker {}", listener, topic,
+ thing.getUID());
+ }
+ return null;
+ });
+ }
return topicSubscribe;
});
});
@@ -197,15 +203,18 @@ public final void registerDiscoveryListener(MQTTTopicDiscoveryParticipant listen
}
TopicSubscribe topicSubscribe = new TopicSubscribe(connection, topic, listener, thing.getUID());
- topicSubscribe.start().handle((result, ex) -> {
- if (ex != null) {
- logger.warn("Failed to subscribe {} to discovery topic {} on broker {}", listener, topic,
- thing.getUID());
- } else {
- logger.trace("Subscribed {} to discovery topic {} on broker {}", listener, topic, thing.getUID());
- }
- return null;
- });
+ if (discoveryEnabled()) {
+ topicSubscribe.start().handle((result, ex) -> {
+ if (ex != null) {
+ logger.warn("Failed to subscribe {} to discovery topic {} on broker {}", listener, topic,
+ thing.getUID());
+ } else {
+ logger.trace("Subscribed {} to discovery topic {} on broker {}", listener, topic,
+ thing.getUID());
+ }
+ return null;
+ });
+ }
return topicSubscribe;
});
}
@@ -240,4 +249,11 @@ public final void unregisterDiscoveryListener(MQTTTopicDiscoveryParticipant list
return v.isEmpty() ? null : v;
});
}
+
+ /**
+ * check whether discovery is disabled on this broker
+ *
+ * @return true if discovery disabled
+ */
+ public abstract boolean discoveryEnabled();
}
diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java
index 21a6000b2c893..ed74295ba7e6a 100644
--- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java
+++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandler.java
@@ -123,6 +123,11 @@ public void dispose() {
super.dispose();
}
+ @Override
+ public boolean discoveryEnabled() {
+ return config.enableDiscovery;
+ }
+
/**
* Reads the thing configuration related to public key or certificate pinning, creates an appropriate a
* {@link PinningSSLContextProvider} and assigns it to the {@link MqttBrokerConnection} instance.
diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java
index 77744ae079974..64580bc697c83 100644
--- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java
+++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/BrokerHandlerConfig.java
@@ -34,4 +34,6 @@ public class BrokerHandlerConfig extends MqttBrokerConnectionConfig {
public boolean publickeypin = false;
public String certificate = "";
public String publickey = "";
+
+ public boolean enableDiscovery = true;
}
diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/SystemBrokerHandler.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/SystemBrokerHandler.java
index 9d3ff2d65e7e6..32e44f5ba8c99 100644
--- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/SystemBrokerHandler.java
+++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/SystemBrokerHandler.java
@@ -50,6 +50,7 @@ public class SystemBrokerHandler extends AbstractBrokerHandler implements MqttSe
protected final MqttService service;
protected String brokerID = "";
+ protected boolean discoveryEnabled = true;
public SystemBrokerHandler(Bridge thing, MqttService service) {
super(thing);
@@ -116,6 +117,8 @@ public void brokerRemoved(String connectionName, MqttBrokerConnection removedCon
@Override
public void initialize() {
this.brokerID = getThing().getConfiguration().get("brokerid").toString();
+ this.discoveryEnabled = (Boolean) getThing().getConfiguration().get("enableDiscovery");
+
service.addBrokersListener(this);
connection = service.getBrokerConnection(brokerID);
@@ -132,4 +135,9 @@ public void dispose() {
service.removeBrokersListener(this);
super.dispose();
}
+
+ @Override
+ public boolean discoveryEnabled() {
+ return discoveryEnabled;
+ }
}
diff --git a/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml
index 19ca98f5f8c5f..f629873720a7f 100644
--- a/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml
+++ b/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml
@@ -155,6 +155,12 @@
`SHA-256:83F9171E06A313118889F7D79302BD1B7A2042EE0CFD029ABF8DD06FFA6CD9D3`
true
+
+
+ If set to true enables this broker for all discovery services.
+ true
+ true
+
@@ -181,6 +187,12 @@
Each system wide configured MQTT broker has a unique broker ID.
+
+
+ If set to true enables this broker for all discovery services.
+ true
+ true
+
diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java
index 6eaf6c3740610..33b3ecdef8a54 100644
--- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java
+++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java
@@ -104,7 +104,7 @@ public void firstSubscribeThenHandler() {
}
@Test
- public void firstHandlerThanSubscribe() {
+ public void firstHandlerThenSubscribe() {
handler.initialize();
BrokerHandlerEx.verifyCreateBrokerConnection(handler, 1);
diff --git a/bundles/org.openhab.binding.nanoleaf/pom.xml b/bundles/org.openhab.binding.nanoleaf/pom.xml
index 821b212618a54..745198dd4875f 100644
--- a/bundles/org.openhab.binding.nanoleaf/pom.xml
+++ b/bundles/org.openhab.binding.nanoleaf/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nanoleaf
diff --git a/bundles/org.openhab.binding.neato/pom.xml b/bundles/org.openhab.binding.neato/pom.xml
index 4c46731ac5651..52b8127d2918d 100644
--- a/bundles/org.openhab.binding.neato/pom.xml
+++ b/bundles/org.openhab.binding.neato/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.neato
diff --git a/bundles/org.openhab.binding.neeo/pom.xml b/bundles/org.openhab.binding.neeo/pom.xml
index cfd2c494dc839..8212e2d84d931 100644
--- a/bundles/org.openhab.binding.neeo/pom.xml
+++ b/bundles/org.openhab.binding.neeo/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.neeo
diff --git a/bundles/org.openhab.binding.neohub/pom.xml b/bundles/org.openhab.binding.neohub/pom.xml
index 828cbdfec102a..0fa2aed529779 100644
--- a/bundles/org.openhab.binding.neohub/pom.xml
+++ b/bundles/org.openhab.binding.neohub/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.neohub
diff --git a/bundles/org.openhab.binding.nest/pom.xml b/bundles/org.openhab.binding.nest/pom.xml
index 4f26614d22bd2..92e9bd199e619 100644
--- a/bundles/org.openhab.binding.nest/pom.xml
+++ b/bundles/org.openhab.binding.nest/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nest
diff --git a/bundles/org.openhab.binding.netatmo/pom.xml b/bundles/org.openhab.binding.netatmo/pom.xml
index 86ae9367f04f0..4fc4bc8631a21 100644
--- a/bundles/org.openhab.binding.netatmo/pom.xml
+++ b/bundles/org.openhab.binding.netatmo/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.netatmo
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java
index 6e48a7c6e46e1..99001f589a36e 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java
@@ -24,7 +24,9 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.discovery.DiscoveryService;
+import org.eclipse.smarthome.core.i18n.LocaleProvider;
import org.eclipse.smarthome.core.i18n.TimeZoneProvider;
+import org.eclipse.smarthome.core.i18n.TranslationProvider;
import org.eclipse.smarthome.core.thing.Bridge;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
@@ -71,15 +73,20 @@ public class NetatmoHandlerFactory extends BaseThingHandlerFactory {
private final HttpService httpService;
private final NATherm1StateDescriptionProvider stateDescriptionProvider;
private final TimeZoneProvider timeZoneProvider;
+ private final LocaleProvider localeProvider;
+ private final TranslationProvider translationProvider;
private boolean backgroundDiscovery;
@Activate
public NetatmoHandlerFactory(final @Reference HttpService httpService,
final @Reference NATherm1StateDescriptionProvider stateDescriptionProvider,
- final @Reference TimeZoneProvider timeZoneProvider) {
+ final @Reference TimeZoneProvider timeZoneProvider, final @Reference LocaleProvider localeProvider,
+ final @Reference TranslationProvider translationProvider) {
this.httpService = httpService;
this.stateDescriptionProvider = stateDescriptionProvider;
this.timeZoneProvider = timeZoneProvider;
+ this.localeProvider = localeProvider;
+ this.translationProvider = translationProvider;
}
@Override
@@ -149,7 +156,8 @@ protected void removeHandler(ThingHandler thingHandler) {
private synchronized void registerDeviceDiscoveryService(NetatmoBridgeHandler netatmoBridgeHandler) {
if (bundleContext != null) {
- NetatmoModuleDiscoveryService discoveryService = new NetatmoModuleDiscoveryService(netatmoBridgeHandler);
+ NetatmoModuleDiscoveryService discoveryService = new NetatmoModuleDiscoveryService(netatmoBridgeHandler,
+ localeProvider, translationProvider);
Map configProperties = new HashMap<>();
configProperties.put(DiscoveryService.CONFIG_PROPERTY_BACKGROUND_DISCOVERY,
Boolean.valueOf(backgroundDiscovery));
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java
index 3d0fa2a37b8ac..2f73483f66311 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java
@@ -22,16 +22,17 @@
import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService;
import org.eclipse.smarthome.config.discovery.DiscoveryResult;
import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder;
+import org.eclipse.smarthome.core.i18n.LocaleProvider;
+import org.eclipse.smarthome.core.i18n.TranslationProvider;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.ThingUID;
import org.openhab.binding.netatmo.internal.handler.NetatmoBridgeHandler;
import org.openhab.binding.netatmo.internal.handler.NetatmoDataListener;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
-import io.swagger.client.model.NAHealthyHomeCoach;
-import io.swagger.client.model.NAMain;
-import io.swagger.client.model.NAPlug;
-import io.swagger.client.model.NAWelcomeHome;
+import io.swagger.client.model.*;
/**
* The {@link NetatmoModuleDiscoveryService} searches for available Netatmo
@@ -46,9 +47,12 @@ public class NetatmoModuleDiscoveryService extends AbstractDiscoveryService impl
private static final int SEARCH_TIME = 5;
private final NetatmoBridgeHandler netatmoBridgeHandler;
- public NetatmoModuleDiscoveryService(NetatmoBridgeHandler netatmoBridgeHandler) {
+ public NetatmoModuleDiscoveryService(NetatmoBridgeHandler netatmoBridgeHandler, LocaleProvider localeProvider,
+ TranslationProvider translationProvider) {
super(SUPPORTED_DEVICE_THING_TYPES_UIDS, SEARCH_TIME);
this.netatmoBridgeHandler = netatmoBridgeHandler;
+ this.localeProvider = localeProvider;
+ this.i18nProvider = translationProvider;
}
@Override
@@ -131,11 +135,13 @@ private void discoverHomeCoach(NAHealthyHomeCoach homecoach) {
}
private void discoverWeatherStation(NAMain station) {
- onDeviceAddedInternal(station.getId(), null, station.getType(), station.getStationName(),
- station.getFirmware());
+ final boolean isFavorite = station.getFavorite() != null && station.getFavorite();
+ final String weatherStationName = createWeatherStationName(station, isFavorite);
+
+ onDeviceAddedInternal(station.getId(), null, station.getType(), weatherStationName, station.getFirmware());
station.getModules().forEach(module -> {
- onDeviceAddedInternal(module.getId(), station.getId(), module.getType(), module.getModuleName(),
- module.getFirmware());
+ onDeviceAddedInternal(module.getId(), station.getId(), module.getType(),
+ createWeatherModuleName(station, module, isFavorite), module.getFirmware());
});
}
@@ -195,4 +201,45 @@ private ThingUID findThingUID(String thingType, String thingId) throws IllegalAr
throw new IllegalArgumentException("Unsupported device type discovered : " + thingType);
}
+
+ private String createWeatherStationName(NAMain station, boolean isFavorite) {
+ StringBuilder nameBuilder = new StringBuilder();
+ nameBuilder.append(localizeType(station.getType()));
+ if (station.getStationName() != null) {
+ nameBuilder.append(' ');
+ nameBuilder.append(station.getStationName());
+ }
+ if (isFavorite) {
+ nameBuilder.append(" (favorite)");
+ }
+ return nameBuilder.toString();
+ }
+
+ private String createWeatherModuleName(NAMain station, NAStationModule module, boolean isFavorite) {
+ StringBuilder nameBuilder = new StringBuilder();
+ if (module.getModuleName() != null) {
+ nameBuilder.append(module.getModuleName());
+ } else {
+ nameBuilder.append(localizeType(module.getType()));
+ }
+ if (station.getStationName() != null) {
+ nameBuilder.append(' ');
+ nameBuilder.append(station.getStationName());
+ }
+ if (isFavorite) {
+ nameBuilder.append(" (favorite)");
+ }
+ return nameBuilder.toString();
+ }
+
+ private String localizeType(String typeName) {
+ Bundle bundle = FrameworkUtil.getBundle(this.getClass());
+ @Nullable
+ String localizedType = i18nProvider.getText(bundle, "thing-type.netatmo." + typeName + ".label", typeName,
+ localeProvider.getLocale());
+ if (localizedType != null) {
+ return localizedType;
+ }
+ return typeName;
+ }
}
diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java
index 64d474d078f71..de69e67e60961 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java
+++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java
@@ -168,6 +168,10 @@ private void scheduleTokenInitAndRefresh() {
return;
}
}
+ } catch (RuntimeException e) {
+ logger.warn("Unable to connect Netatmo API : {}", e.getMessage(), e);
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+ "Netatmo Access Failed, will retry in " + configuration.reconnectInterval + " seconds.");
}
// We'll do this every x seconds to guaranty token refresh
}, 2, configuration.reconnectInterval, TimeUnit.SECONDS);
@@ -272,8 +276,7 @@ public void dispose() {
}
public Optional getStationsDataBody(@Nullable String equipmentId) {
- Optional data = getStationApi()
- .map(api -> api.getstationsdata(equipmentId, false).getBody());
+ Optional data = getStationApi().map(api -> api.getstationsdata(equipmentId, true).getBody());
updateStatus(ThingStatus.ONLINE);
return data;
}
diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml
index c3a9ec2cb6043..ced55dc798a80 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml
+++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml
@@ -11,7 +11,8 @@
- If set to true, the device and its associated modules are updated in the discovery inbox at each API call run to refresh device data. Default is false.
+ If set to true, the device and its associated modules are updated in the discovery inbox at each API
+ call run to refresh device data. Default is false.
false
false
diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml
index 0cda714c6d15e..9c6b59e1a546b 100644
--- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml
+++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml
@@ -32,7 +32,7 @@
-
+
diff --git a/bundles/org.openhab.binding.netatmo/src/test/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryServiceTest.java b/bundles/org.openhab.binding.netatmo/src/test/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryServiceTest.java
new file mode 100644
index 0000000000000..1e1857a33a1fb
--- /dev/null
+++ b/bundles/org.openhab.binding.netatmo/src/test/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryServiceTest.java
@@ -0,0 +1,279 @@
+/**
+ * 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.netatmo.internal.discovery;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.smarthome.config.discovery.DiscoveryResult;
+import org.eclipse.smarthome.core.i18n.LocaleProvider;
+import org.eclipse.smarthome.core.i18n.TranslationProvider;
+import org.eclipse.smarthome.core.thing.Bridge;
+import org.eclipse.smarthome.core.thing.ThingUID;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.openhab.binding.netatmo.internal.handler.NetatmoBridgeHandler;
+
+import io.swagger.client.model.NAMain;
+import io.swagger.client.model.NAStationDataBody;
+import io.swagger.client.model.NAStationModule;
+
+/**
+ * @author Sven Strohschein - Initial contribution
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class NetatmoModuleDiscoveryServiceTest {
+
+ private NetatmoModuleDiscoveryServiceAccessible service;
+ private NetatmoBridgeHandler bridgeHandlerSpy;
+
+ @Before
+ public void before() {
+ Bridge bridgeMock = mock(Bridge.class);
+ when(bridgeMock.getUID()).thenReturn(new ThingUID("netatmo", "bridge"));
+
+ bridgeHandlerSpy = spy(new NetatmoBridgeHandler(bridgeMock, null));
+
+ LocaleProvider localeProviderMock = mock(LocaleProvider.class);
+ TranslationProvider translationProvider = mock(TranslationProvider.class);
+
+ service = new NetatmoModuleDiscoveryServiceAccessible(bridgeHandlerSpy, localeProviderMock,
+ translationProvider);
+ }
+
+ @Test
+ public void testStartScanNothingActivated() {
+ service.startScan();
+
+ assertEquals(0, service.getDiscoveredThings().size());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationNoStationsBody() {
+ activateDiscoveryWeatherStation();
+
+ service.startScan();
+
+ assertEquals(0, service.getDiscoveredThings().size());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationNoStations() {
+ activateDiscoveryWeatherStation();
+
+ when(bridgeHandlerSpy.getStationsDataBody(null)).thenReturn(Optional.of(new NAStationDataBody()));
+ service.startScan();
+
+ assertEquals(0, service.getDiscoveredThings().size());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationNoStationName() {
+ recordStationBody(createStation());
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(1, discoveredThings.size());
+ // Expected is only the type name, because a station name isn't available
+ assertEquals("NAMain", discoveredThings.get(0).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStation() {
+ NAMain station = createStation();
+ station.setStationName("Neu Wulmstorf");
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(1, discoveredThings.size());
+ // Expected is the type name + station name, because both are available
+ // and the station name contains only the city name by default which wouldn't be sufficient.
+ assertEquals("NAMain Neu Wulmstorf", discoveredThings.get(0).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationNoStationNameFavorite() {
+ NAMain station = createStation();
+ station.setFavorite(true);
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(1, discoveredThings.size());
+ // Expected is "(favorite)" within the label to make clear that it is favorite station
+ // (and not the station of the user)
+ assertEquals("NAMain (favorite)", discoveredThings.get(0).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationFavorite() {
+ NAMain station = createStation();
+ station.setStationName("Neu Wulmstorf");
+ station.setFavorite(true);
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(1, discoveredThings.size());
+ // Expected is "(favorite)" within the label to make clear that it is favorite station
+ // (and not the station of the user)
+ assertEquals("NAMain Neu Wulmstorf (favorite)", discoveredThings.get(0).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationModuleNoModuleName() {
+ NAMain station = createStation(createModule());
+ station.setStationName("Neu Wulmstorf");
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(2, discoveredThings.size());
+ assertEquals("NAMain Neu Wulmstorf", discoveredThings.get(0).getLabel());
+ // Expected is the type name + station name to make clear that the module belongs to the station.
+ // The module name isn't available, therefore the type name of the module is used.
+ assertEquals("NAModule1 Neu Wulmstorf", discoveredThings.get(1).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationModule() {
+ NAStationModule module = createModule();
+ module.setModuleName("Outdoor-Module");
+
+ NAMain station = createStation(module);
+ station.setStationName("Neu Wulmstorf");
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(2, discoveredThings.size());
+ assertEquals("NAMain Neu Wulmstorf", discoveredThings.get(0).getLabel());
+ // Expected is the module name + station name to make clear that the module belongs to the station.
+ // Because an explicit module name is available, the module type name isn't required.
+ assertEquals("Outdoor-Module Neu Wulmstorf", discoveredThings.get(1).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationModuleNoModuleNameFavorite() {
+ NAMain station = createStation(createModule());
+ station.setStationName("Neu Wulmstorf");
+ station.setFavorite(true);
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(2, discoveredThings.size());
+ assertEquals("NAMain Neu Wulmstorf (favorite)", discoveredThings.get(0).getLabel());
+ // Expected is "(favorite)" within the label to make clear that it is favorite station
+ // (and not the station of the user)
+ assertEquals("NAModule1 Neu Wulmstorf (favorite)", discoveredThings.get(1).getLabel());
+ }
+
+ @Test
+ public void testStartScanDiscoverWeatherStationModuleFavorite() {
+ NAStationModule module = createModule();
+ module.setModuleName("Outdoor-Module");
+
+ NAMain station = createStation(module);
+ station.setStationName("Neu Wulmstorf");
+ station.setFavorite(true);
+
+ recordStationBody(station);
+
+ service.startScan();
+
+ List discoveredThings = service.getDiscoveredThings();
+ assertEquals(2, discoveredThings.size());
+ assertEquals("NAMain Neu Wulmstorf (favorite)", discoveredThings.get(0).getLabel());
+ // Expected is "(favorite)" within the label to make clear that it is favorite station
+ // (and not the station of the user)
+ assertEquals("Outdoor-Module Neu Wulmstorf (favorite)", discoveredThings.get(1).getLabel());
+ }
+
+ private void recordStationBody(NAMain station) {
+ activateDiscoveryWeatherStation();
+
+ NAStationDataBody stationsBody = new NAStationDataBody();
+ stationsBody.setDevices(Collections.singletonList(station));
+
+ when(bridgeHandlerSpy.getStationsDataBody(null)).thenReturn(Optional.of(stationsBody));
+ }
+
+ private void activateDiscoveryWeatherStation() {
+ bridgeHandlerSpy.configuration.readStation = true;
+ }
+
+ private static NAMain createStation() {
+ NAMain station = new NAMain();
+ station.setId("01:00:00:00:00:aa");
+ station.setType("NAMain");
+ return station;
+ }
+
+ private static NAMain createStation(NAStationModule module) {
+ NAMain station = createStation();
+ station.setModules(Collections.singletonList(module));
+ return station;
+ }
+
+ private static NAStationModule createModule() {
+ NAStationModule module = new NAStationModule();
+ module.setId("01:00:00:00:01:aa");
+ module.setType("NAModule1");
+ return module;
+ }
+
+ @NonNullByDefault
+ private static class NetatmoModuleDiscoveryServiceAccessible extends NetatmoModuleDiscoveryService {
+
+ private final List discoveredThings;
+
+ private NetatmoModuleDiscoveryServiceAccessible(NetatmoBridgeHandler netatmoBridgeHandler,
+ LocaleProvider localeProvider, TranslationProvider translationProvider) {
+ super(netatmoBridgeHandler, localeProvider, translationProvider);
+ discoveredThings = new ArrayList<>();
+ }
+
+ @Override
+ protected void thingDiscovered(DiscoveryResult discoveryResult) {
+ super.thingDiscovered(discoveryResult);
+ discoveredThings.add(discoveryResult);
+ }
+
+ private List getDiscoveredThings() {
+ return discoveredThings;
+ }
+ }
+}
diff --git a/bundles/org.openhab.binding.network/pom.xml b/bundles/org.openhab.binding.network/pom.xml
index e34852ec5ebc1..60da48f406790 100644
--- a/bundles/org.openhab.binding.network/pom.xml
+++ b/bundles/org.openhab.binding.network/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.network
diff --git a/bundles/org.openhab.binding.networkupstools/pom.xml b/bundles/org.openhab.binding.networkupstools/pom.xml
index fe322fea33b2e..75362bdd9810b 100644
--- a/bundles/org.openhab.binding.networkupstools/pom.xml
+++ b/bundles/org.openhab.binding.networkupstools/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.networkupstools
diff --git a/bundles/org.openhab.binding.nibeheatpump/pom.xml b/bundles/org.openhab.binding.nibeheatpump/pom.xml
index 9c6a982254f52..adb8746c69dc3 100644
--- a/bundles/org.openhab.binding.nibeheatpump/pom.xml
+++ b/bundles/org.openhab.binding.nibeheatpump/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nibeheatpump
diff --git a/bundles/org.openhab.binding.nibeuplink/pom.xml b/bundles/org.openhab.binding.nibeuplink/pom.xml
index 94743f9ea220a..2c186bd2544a9 100644
--- a/bundles/org.openhab.binding.nibeuplink/pom.xml
+++ b/bundles/org.openhab.binding.nibeuplink/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nibeuplink
diff --git a/bundles/org.openhab.binding.nikobus/pom.xml b/bundles/org.openhab.binding.nikobus/pom.xml
index 27d88af5d1b3d..fb763a7ba5ad7 100644
--- a/bundles/org.openhab.binding.nikobus/pom.xml
+++ b/bundles/org.openhab.binding.nikobus/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nikobus
diff --git a/bundles/org.openhab.binding.nikohomecontrol/pom.xml b/bundles/org.openhab.binding.nikohomecontrol/pom.xml
index 24b8c4f9c722f..9a082ceabe48a 100644
--- a/bundles/org.openhab.binding.nikohomecontrol/pom.xml
+++ b/bundles/org.openhab.binding.nikohomecontrol/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nikohomecontrol
diff --git a/bundles/org.openhab.binding.novafinedust/pom.xml b/bundles/org.openhab.binding.novafinedust/pom.xml
index 3d540d095168b..0a51ab44fa911 100644
--- a/bundles/org.openhab.binding.novafinedust/pom.xml
+++ b/bundles/org.openhab.binding.novafinedust/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.novafinedust
diff --git a/bundles/org.openhab.binding.ntp/pom.xml b/bundles/org.openhab.binding.ntp/pom.xml
index d831b0bb4760b..a68340233361a 100644
--- a/bundles/org.openhab.binding.ntp/pom.xml
+++ b/bundles/org.openhab.binding.ntp/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.ntp
diff --git a/bundles/org.openhab.binding.nuki/pom.xml b/bundles/org.openhab.binding.nuki/pom.xml
index f9a7c98248927..c51cc8024ffa6 100644
--- a/bundles/org.openhab.binding.nuki/pom.xml
+++ b/bundles/org.openhab.binding.nuki/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.nuki
diff --git a/bundles/org.openhab.binding.oceanic/pom.xml b/bundles/org.openhab.binding.oceanic/pom.xml
index 929b164797dc8..7191d420dddb7 100644
--- a/bundles/org.openhab.binding.oceanic/pom.xml
+++ b/bundles/org.openhab.binding.oceanic/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.oceanic
diff --git a/bundles/org.openhab.binding.ojelectronics/pom.xml b/bundles/org.openhab.binding.ojelectronics/pom.xml
index add24ff8da2ae..edef14b4d6fa5 100644
--- a/bundles/org.openhab.binding.ojelectronics/pom.xml
+++ b/bundles/org.openhab.binding.ojelectronics/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.ojelectronics
diff --git a/bundles/org.openhab.binding.omnikinverter/pom.xml b/bundles/org.openhab.binding.omnikinverter/pom.xml
index 98dc7517876c8..094ce18e4d807 100644
--- a/bundles/org.openhab.binding.omnikinverter/pom.xml
+++ b/bundles/org.openhab.binding.omnikinverter/pom.xml
@@ -4,7 +4,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.omnikinverter
diff --git a/bundles/org.openhab.binding.onebusaway/pom.xml b/bundles/org.openhab.binding.onebusaway/pom.xml
index 9ab9c2dfb3177..c4313d28279cb 100644
--- a/bundles/org.openhab.binding.onebusaway/pom.xml
+++ b/bundles/org.openhab.binding.onebusaway/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.onebusaway
diff --git a/bundles/org.openhab.binding.onewire/pom.xml b/bundles/org.openhab.binding.onewire/pom.xml
index 339c536478183..a8a5ba6dd054b 100644
--- a/bundles/org.openhab.binding.onewire/pom.xml
+++ b/bundles/org.openhab.binding.onewire/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.onewire
diff --git a/bundles/org.openhab.binding.onewiregpio/pom.xml b/bundles/org.openhab.binding.onewiregpio/pom.xml
index 646ffa252643c..eaa4d44ab7665 100644
--- a/bundles/org.openhab.binding.onewiregpio/pom.xml
+++ b/bundles/org.openhab.binding.onewiregpio/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.onewiregpio
diff --git a/bundles/org.openhab.binding.onkyo/pom.xml b/bundles/org.openhab.binding.onkyo/pom.xml
index bb6fc5e7e63f8..1c626a8a6b5fe 100644
--- a/bundles/org.openhab.binding.onkyo/pom.xml
+++ b/bundles/org.openhab.binding.onkyo/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.onkyo
diff --git a/bundles/org.openhab.binding.opengarage/pom.xml b/bundles/org.openhab.binding.opengarage/pom.xml
index 89b80ae6d7620..2aea2a6607df1 100644
--- a/bundles/org.openhab.binding.opengarage/pom.xml
+++ b/bundles/org.openhab.binding.opengarage/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.opengarage
diff --git a/bundles/org.openhab.binding.opensprinkler/pom.xml b/bundles/org.openhab.binding.opensprinkler/pom.xml
index 0f12738b1c56d..350f62762a80e 100644
--- a/bundles/org.openhab.binding.opensprinkler/pom.xml
+++ b/bundles/org.openhab.binding.opensprinkler/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.opensprinkler
diff --git a/bundles/org.openhab.binding.openthermgateway/pom.xml b/bundles/org.openhab.binding.openthermgateway/pom.xml
index 8c31229e2bee5..5092ce66dd8c2 100644
--- a/bundles/org.openhab.binding.openthermgateway/pom.xml
+++ b/bundles/org.openhab.binding.openthermgateway/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.openthermgateway
diff --git a/bundles/org.openhab.binding.openuv/pom.xml b/bundles/org.openhab.binding.openuv/pom.xml
index 49d079baca284..99481741584c0 100644
--- a/bundles/org.openhab.binding.openuv/pom.xml
+++ b/bundles/org.openhab.binding.openuv/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.openuv
diff --git a/bundles/org.openhab.binding.openweathermap/pom.xml b/bundles/org.openhab.binding.openweathermap/pom.xml
index 9fa0e807c7837..5d9eaf196e6c5 100644
--- a/bundles/org.openhab.binding.openweathermap/pom.xml
+++ b/bundles/org.openhab.binding.openweathermap/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.openweathermap
diff --git a/bundles/org.openhab.binding.orvibo/pom.xml b/bundles/org.openhab.binding.orvibo/pom.xml
index bf5cbfc144a62..705bbc325afcf 100644
--- a/bundles/org.openhab.binding.orvibo/pom.xml
+++ b/bundles/org.openhab.binding.orvibo/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.orvibo
diff --git a/bundles/org.openhab.binding.paradoxalarm/pom.xml b/bundles/org.openhab.binding.paradoxalarm/pom.xml
index 234997b938b95..a09467d85580e 100644
--- a/bundles/org.openhab.binding.paradoxalarm/pom.xml
+++ b/bundles/org.openhab.binding.paradoxalarm/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.reactor.bundles
org.openhab.addons.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.paradoxalarm
diff --git a/bundles/org.openhab.binding.pentair/pom.xml b/bundles/org.openhab.binding.pentair/pom.xml
index 8967fafe839c5..052ea40b6ba5a 100644
--- a/bundles/org.openhab.binding.pentair/pom.xml
+++ b/bundles/org.openhab.binding.pentair/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.pentair
diff --git a/bundles/org.openhab.binding.phc/pom.xml b/bundles/org.openhab.binding.phc/pom.xml
index 51db6027d7de7..e5b848c1d69aa 100644
--- a/bundles/org.openhab.binding.phc/pom.xml
+++ b/bundles/org.openhab.binding.phc/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.phc
diff --git a/bundles/org.openhab.binding.pioneeravr/pom.xml b/bundles/org.openhab.binding.pioneeravr/pom.xml
index fdc2801aea4d9..1147ba7582199 100644
--- a/bundles/org.openhab.binding.pioneeravr/pom.xml
+++ b/bundles/org.openhab.binding.pioneeravr/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.pioneeravr
diff --git a/bundles/org.openhab.binding.pixometer/pom.xml b/bundles/org.openhab.binding.pixometer/pom.xml
index 6639963c6e1fd..6d144a0cee035 100644
--- a/bundles/org.openhab.binding.pixometer/pom.xml
+++ b/bundles/org.openhab.binding.pixometer/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.pixometer
diff --git a/bundles/org.openhab.binding.pjlinkdevice/pom.xml b/bundles/org.openhab.binding.pjlinkdevice/pom.xml
index b9f0296bd2689..925f6613d8d47 100644
--- a/bundles/org.openhab.binding.pjlinkdevice/pom.xml
+++ b/bundles/org.openhab.binding.pjlinkdevice/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.pjlinkdevice
diff --git a/bundles/org.openhab.binding.plclogo/pom.xml b/bundles/org.openhab.binding.plclogo/pom.xml
index 340d628cc8a31..27d0e4cad318b 100644
--- a/bundles/org.openhab.binding.plclogo/pom.xml
+++ b/bundles/org.openhab.binding.plclogo/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.plclogo
diff --git a/bundles/org.openhab.binding.plugwise/pom.xml b/bundles/org.openhab.binding.plugwise/pom.xml
index 5d4d7b3c86955..1e30d1f728924 100644
--- a/bundles/org.openhab.binding.plugwise/pom.xml
+++ b/bundles/org.openhab.binding.plugwise/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.plugwise
diff --git a/bundles/org.openhab.binding.powermax/pom.xml b/bundles/org.openhab.binding.powermax/pom.xml
index 673fa4744458b..021073e20c3de 100644
--- a/bundles/org.openhab.binding.powermax/pom.xml
+++ b/bundles/org.openhab.binding.powermax/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.powermax
diff --git a/bundles/org.openhab.binding.pulseaudio/pom.xml b/bundles/org.openhab.binding.pulseaudio/pom.xml
index c2f34f116a234..74f741da11349 100644
--- a/bundles/org.openhab.binding.pulseaudio/pom.xml
+++ b/bundles/org.openhab.binding.pulseaudio/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.pulseaudio
diff --git a/bundles/org.openhab.binding.pushbullet/pom.xml b/bundles/org.openhab.binding.pushbullet/pom.xml
index 12d20f879914c..a1d3e36ead82c 100644
--- a/bundles/org.openhab.binding.pushbullet/pom.xml
+++ b/bundles/org.openhab.binding.pushbullet/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.pushbullet
diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/IPushbulletActions.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/IPushbulletActions.java
new file mode 100644
index 0000000000000..46cbbc462a867
--- /dev/null
+++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/IPushbulletActions.java
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2010-2020 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.pushbullet.internal.action;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link IPushbulletActions} interface defines rule actions for sending notifications
+ *
+ * @author Laurent Garnier - Initial contribution
+ */
+@NonNullByDefault
+public interface IPushbulletActions {
+
+ public Boolean sendPushbulletNote(@Nullable String recipient, @Nullable String title, @Nullable String message);
+
+ public Boolean sendPushbulletNote(@Nullable String recipient, @Nullable String message);
+}
diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java
index fe64af81ec745..348c2dccbb20a 100644
--- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java
+++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java
@@ -12,6 +12,9 @@
*/
package org.openhab.binding.pushbullet.internal.action;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.binding.ThingActions;
@@ -26,12 +29,17 @@
/**
* The {@link PushbulletActions} class defines rule actions for sending notifications
+ *
+ * Note:The static method invokeMethodOf handles the case where
+ * the test actions instanceof PushbulletActions fails. This test can fail
+ * due to an issue in openHAB core v2.5.0 where the {@link PushbulletActions} class
+ * can be loaded by a different classloader than the actions instance.
*
* @author Hakan Tandogan - Initial contribution
*/
@ThingActionsScope(name = "pushbullet")
@NonNullByDefault
-public class PushbulletActions implements ThingActions {
+public class PushbulletActions implements ThingActions, IPushbulletActions {
private final Logger logger = LoggerFactory.getLogger(PushbulletActions.class);
@@ -47,6 +55,7 @@ public void setThingHandler(@Nullable ThingHandler handler) {
return this.handler;
}
+ @Override
@RuleAction(label = "@text/actionSendPushbulletNoteLabel", description = "@text/actionSendPushbulletNoteDesc")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletNote(
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc") @Nullable String recipient,
@@ -67,13 +76,10 @@ public void setThingHandler(@Nullable ThingHandler handler) {
public static boolean sendPushbulletNote(@Nullable ThingActions actions, @Nullable String recipient,
@Nullable String title, @Nullable String message) {
- if (actions instanceof PushbulletActions) {
- return ((PushbulletActions) actions).sendPushbulletNote(recipient, title, message);
- } else {
- throw new IllegalArgumentException("Instance is not a PushbulletActions class ( " + actions + " )");
- }
+ return invokeMethodOf(actions).sendPushbulletNote(recipient, title, message);
}
+ @Override
@RuleAction(label = "@text/actionSendPushbulletNoteLabel", description = "@text/actionSendPushbulletNoteDesc")
public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletNote(
@ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc") @Nullable String recipient,
@@ -93,10 +99,25 @@ public static boolean sendPushbulletNote(@Nullable ThingActions actions, @Nullab
public static boolean sendPushbulletNote(@Nullable ThingActions actions, @Nullable String recipient,
@Nullable String message) {
- if (actions instanceof PushbulletActions) {
- return ((PushbulletActions) actions).sendPushbulletNote(recipient, message);
- } else {
- throw new IllegalArgumentException("Instance is not a PushbulletActions class ( " + actions + " )");
+ return invokeMethodOf(actions).sendPushbulletNote(recipient, message);
+ }
+
+ private static IPushbulletActions invokeMethodOf(@Nullable ThingActions actions) {
+ if (actions == null) {
+ throw new IllegalArgumentException("actions cannot be null");
+ }
+ if (actions.getClass().getName().equals(PushbulletActions.class.getName())) {
+ if (actions instanceof IPushbulletActions) {
+ return (IPushbulletActions) actions;
+ } else {
+ return (IPushbulletActions) Proxy.newProxyInstance(IPushbulletActions.class.getClassLoader(),
+ new Class[] { IPushbulletActions.class }, (Object proxy, Method method, Object[] args) -> {
+ Method m = actions.getClass().getDeclaredMethod(method.getName(),
+ method.getParameterTypes());
+ return m.invoke(actions, args);
+ });
+ }
}
+ throw new IllegalArgumentException("Actions is not an instance of PushbulletActions");
}
}
diff --git a/bundles/org.openhab.binding.radiothermostat/pom.xml b/bundles/org.openhab.binding.radiothermostat/pom.xml
index a204fd487798d..c16d2a22b2801 100644
--- a/bundles/org.openhab.binding.radiothermostat/pom.xml
+++ b/bundles/org.openhab.binding.radiothermostat/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.radiothermostat
diff --git a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/IRadioThermostatThingActions.java b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/IRadioThermostatThingActions.java
new file mode 100644
index 0000000000000..101cef8f6bc94
--- /dev/null
+++ b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/IRadioThermostatThingActions.java
@@ -0,0 +1,28 @@
+/**
+ * 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.radiothermostat.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * The {@link IRadioThermostatThingActions} defines the interface for all thing actions supported by the binding.
+ * These methods, parameters, and return types are explained in {@link RadioThermostatThingActions}.
+ *
+ * @author Michael Lobstein - Initial contribution
+ */
+@NonNullByDefault
+public interface IRadioThermostatThingActions {
+
+ void sendRawCommand(@Nullable String rawCommand);
+}
diff --git a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatThingActions.java b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatThingActions.java
index 6e0a371fc4af6..66ef16fba3705 100644
--- a/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatThingActions.java
+++ b/bundles/org.openhab.binding.radiothermostat/src/main/java/org/openhab/binding/radiothermostat/internal/RadioThermostatThingActions.java
@@ -12,6 +12,9 @@
*/
package org.openhab.binding.radiothermostat.internal;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.binding.ThingActions;
@@ -31,29 +34,30 @@
*/
@ThingActionsScope(name = "radiothermostat")
@NonNullByDefault
-public class RadioThermostatThingActions implements ThingActions {
+public class RadioThermostatThingActions implements ThingActions, IRadioThermostatThingActions {
private final Logger logger = LoggerFactory.getLogger(RadioThermostatThingActions.class);
private @Nullable RadioThermostatHandler handler;
- @SuppressWarnings("null")
+ @Override
@RuleAction(label = "sendRawCommand", description = "Action that sends raw command to the thermostat")
public void sendRawCommand(@ActionInput(name = "sendRawCommand") @Nullable String rawCommand) {
- if (handler != null && rawCommand != null) {
- handler.handleRawCommand(rawCommand);
+ RadioThermostatHandler localHandler = handler;
+ if (rawCommand == null) {
+ logger.warn("sendRawCommand called with null command, ignoring");
+ return;
+ }
+
+ if (localHandler != null) {
+ localHandler.handleRawCommand(rawCommand);
logger.debug("sendRawCommand called with raw command: {}", rawCommand);
- } else {
- logger.debug("sendRawCommand called with null command, ignoring");
}
}
+ /** Static alias to support the old DSL rules engine and make the action available there. */
public static void sendRawCommand(@Nullable ThingActions actions, @Nullable String rawCommand)
throws IllegalArgumentException {
- if (actions instanceof RadioThermostatThingActions) {
- ((RadioThermostatThingActions) actions).sendRawCommand(rawCommand);
- } else {
- throw new IllegalArgumentException("Instance is not an RadioThermostatThingActions class.");
- }
+ invokeMethodOf(actions).sendRawCommand(rawCommand);
}
@Override
@@ -65,4 +69,25 @@ public void setThingHandler(@Nullable ThingHandler handler) {
public @Nullable ThingHandler getThingHandler() {
return this.handler;
}
+
+ private static IRadioThermostatThingActions invokeMethodOf(@Nullable ThingActions actions) {
+ if (actions == null) {
+ throw new IllegalArgumentException("actions cannot be null");
+ }
+ if (actions.getClass().getName().equals(RadioThermostatThingActions.class.getName())) {
+ if (actions instanceof RadioThermostatThingActions) {
+ return (IRadioThermostatThingActions) actions;
+ } else {
+ return (IRadioThermostatThingActions) Proxy.newProxyInstance(
+ IRadioThermostatThingActions.class.getClassLoader(),
+ new Class[] { IRadioThermostatThingActions.class },
+ (Object proxy, Method method, Object[] args) -> {
+ Method m = actions.getClass().getDeclaredMethod(method.getName(),
+ method.getParameterTypes());
+ return m.invoke(actions, args);
+ });
+ }
+ }
+ throw new IllegalArgumentException("Actions is not an instance of RadioThermostatThingActions");
+ }
}
diff --git a/bundles/org.openhab.binding.regoheatpump/pom.xml b/bundles/org.openhab.binding.regoheatpump/pom.xml
index ec26a2e99d007..eb8c52e4606ba 100644
--- a/bundles/org.openhab.binding.regoheatpump/pom.xml
+++ b/bundles/org.openhab.binding.regoheatpump/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.regoheatpump
diff --git a/bundles/org.openhab.binding.rfxcom/pom.xml b/bundles/org.openhab.binding.rfxcom/pom.xml
index f32fa1bea2e41..74261324ffbab 100644
--- a/bundles/org.openhab.binding.rfxcom/pom.xml
+++ b/bundles/org.openhab.binding.rfxcom/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.rfxcom
diff --git a/bundles/org.openhab.binding.rme/pom.xml b/bundles/org.openhab.binding.rme/pom.xml
index b9f15739021ab..b3df21e83f140 100644
--- a/bundles/org.openhab.binding.rme/pom.xml
+++ b/bundles/org.openhab.binding.rme/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.rme
diff --git a/bundles/org.openhab.binding.robonect/pom.xml b/bundles/org.openhab.binding.robonect/pom.xml
index 35aed480cf30b..8a844ec573b9f 100644
--- a/bundles/org.openhab.binding.robonect/pom.xml
+++ b/bundles/org.openhab.binding.robonect/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.robonect
diff --git a/bundles/org.openhab.binding.rotel/pom.xml b/bundles/org.openhab.binding.rotel/pom.xml
index 32f241b4c3a45..32f8b2d5c1a43 100644
--- a/bundles/org.openhab.binding.rotel/pom.xml
+++ b/bundles/org.openhab.binding.rotel/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.rotel
diff --git a/bundles/org.openhab.binding.rotelra1x/pom.xml b/bundles/org.openhab.binding.rotelra1x/pom.xml
index 72fcf3bec4a66..22bf144626c66 100644
--- a/bundles/org.openhab.binding.rotelra1x/pom.xml
+++ b/bundles/org.openhab.binding.rotelra1x/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.rotelra1x
diff --git a/bundles/org.openhab.binding.russound/pom.xml b/bundles/org.openhab.binding.russound/pom.xml
index f7654601537a3..9d793d8fcda1a 100644
--- a/bundles/org.openhab.binding.russound/pom.xml
+++ b/bundles/org.openhab.binding.russound/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.russound
diff --git a/bundles/org.openhab.binding.sagercaster/pom.xml b/bundles/org.openhab.binding.sagercaster/pom.xml
index c4c80c8227ec6..aacd6198325c5 100644
--- a/bundles/org.openhab.binding.sagercaster/pom.xml
+++ b/bundles/org.openhab.binding.sagercaster/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.sagercaster
diff --git a/bundles/org.openhab.binding.samsungtv/pom.xml b/bundles/org.openhab.binding.samsungtv/pom.xml
index a9029e1cb017d..e1a8b0f17b26e 100644
--- a/bundles/org.openhab.binding.samsungtv/pom.xml
+++ b/bundles/org.openhab.binding.samsungtv/pom.xml
@@ -1,13 +1,11 @@
-
-
+
4.0.0
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.samsungtv
diff --git a/bundles/org.openhab.binding.satel/pom.xml b/bundles/org.openhab.binding.satel/pom.xml
index 39b433fe196a8..c13625865f42c 100644
--- a/bundles/org.openhab.binding.satel/pom.xml
+++ b/bundles/org.openhab.binding.satel/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.satel
diff --git a/bundles/org.openhab.binding.seneye/pom.xml b/bundles/org.openhab.binding.seneye/pom.xml
index 2467bbfc8b57a..2944e299d38e6 100644
--- a/bundles/org.openhab.binding.seneye/pom.xml
+++ b/bundles/org.openhab.binding.seneye/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.seneye
diff --git a/bundles/org.openhab.binding.sensebox/pom.xml b/bundles/org.openhab.binding.sensebox/pom.xml
index 515b204355519..01e80519fcb12 100644
--- a/bundles/org.openhab.binding.sensebox/pom.xml
+++ b/bundles/org.openhab.binding.sensebox/pom.xml
@@ -5,7 +5,7 @@
org.openhab.addons.bundles
org.openhab.addons.reactor.bundles
- 2.5.7-SNAPSHOT
+ 2.5.8-SNAPSHOT
org.openhab.binding.sensebox
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxAPIConnection.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxAPIConnection.java
index ce6a6a8486741..8ac122988c59a 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxAPIConnection.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxAPIConnection.java
@@ -18,14 +18,14 @@
import java.util.List;
import java.util.Properties;
-import org.apache.commons.lang.StringUtils;
+import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.io.net.http.HttpUtil;
-import org.openhab.binding.sensebox.internal.model.SenseBoxData;
-import org.openhab.binding.sensebox.internal.model.SenseBoxDescriptor;
-import org.openhab.binding.sensebox.internal.model.SenseBoxLoc;
-import org.openhab.binding.sensebox.internal.model.SenseBoxLocation;
-import org.openhab.binding.sensebox.internal.model.SenseBoxSensor;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxData;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxDescriptor;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxLoc;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxLocation;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxSensor;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.Version;
import org.slf4j.Logger;
@@ -38,10 +38,12 @@
*
* @author Hakan Tandogan - Initial contribution
*/
+@NonNullByDefault
public class SenseBoxAPIConnection {
- private Logger logger = LoggerFactory.getLogger(SenseBoxAPIConnection.class);
- private Gson gson = new Gson();
+ private final Logger logger = LoggerFactory.getLogger(SenseBoxAPIConnection.class);
+
+ private final Gson gson = new Gson();
private static final Properties HEADERS = new Properties();
@@ -136,8 +138,9 @@ public SenseBoxData reallyFetchDataFromServer(String senseBoxId) {
SenseBoxDescriptor descriptor = new SenseBoxDescriptor();
descriptor.setApiUrl(query);
- if (StringUtils.isNotEmpty(parsedData.getImage())) {
- descriptor.setImageUrl(SENSEMAP_IMAGE_URL_BASE + "/" + parsedData.getImage());
+ String image = parsedData.getImage();
+ if (image != null && !image.isEmpty()) {
+ descriptor.setImageUrl(SENSEMAP_IMAGE_URL_BASE + "/" + image);
}
descriptor.setMapUrl(SENSEMAP_MAP_URL_BASE + "/explore/" + senseBoxId);
parsedData.setDescriptor(descriptor);
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxHandlerFactory.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxHandlerFactory.java
index 6063116c82f4e..f95373905d8ae 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxHandlerFactory.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/SenseBoxHandlerFactory.java
@@ -17,6 +17,8 @@
import java.util.Collections;
import java.util.Set;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory;
@@ -32,6 +34,7 @@
* @author Hakan Tandogan - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.sensebox")
+@NonNullByDefault
public class SenseBoxHandlerFactory extends BaseThingHandlerFactory {
private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_BOX);
@@ -42,7 +45,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
}
@Override
- protected ThingHandler createHandler(Thing thing) {
+ protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(THING_TYPE_BOX)) {
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/config/SenseBoxConfiguration.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/config/SenseBoxConfiguration.java
index 58fb6ae51a3af..b4fe112a0f279 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/config/SenseBoxConfiguration.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/config/SenseBoxConfiguration.java
@@ -12,17 +12,20 @@
*/
package org.openhab.binding.sensebox.internal.config;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
/**
* The {@link SenseBoxConfiguration} is the base class for configuration
* information held by devices and modules
*
* @author Hakan Tandogan - Initial contribution
*/
+@NonNullByDefault
public class SenseBoxConfiguration {
- private long refreshInterval;
-
- private String senseBoxId;
+ private @Nullable String senseBoxId;
+ private long refreshInterval = 300;
public long getRefreshInterval() {
return refreshInterval;
@@ -32,7 +35,7 @@ public void setRefreshInterval(long refreshInterval) {
this.refreshInterval = refreshInterval;
}
- public String getSenseBoxId() {
+ public @Nullable String getSenseBoxId() {
return senseBoxId;
}
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxData.java
similarity index 98%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxData.java
index 7f8886c0377fb..4fc17baee6992 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxData.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
import java.util.List;
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxDescriptor.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxDescriptor.java
similarity index 95%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxDescriptor.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxDescriptor.java
index dc03b9b67fbdb..cdc1f8c2b8f97 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxDescriptor.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxDescriptor.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
/**
* The {@link SenseBoxDescriptor} holds a de-serialized representation
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxGeometry.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxGeometry.java
similarity index 94%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxGeometry.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxGeometry.java
index 9a41a4c53140a..104ae70392020 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxGeometry.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxGeometry.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
import java.util.List;
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxLoc.java
similarity index 94%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxLoc.java
index d68f32f6a11dd..b7be2331e08f7 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxLoc.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLocation.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxLocation.java
similarity index 95%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLocation.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxLocation.java
index 899c3d25d1acc..04b14c97fb0db 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLocation.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxLocation.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
/**
* The {@link SenseBoxLocation} holds a de-serialized representation
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxMeasurement.java
similarity index 95%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxMeasurement.java
index 7b0390465260c..fec19acd3cafb 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxMeasurement.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxSensor.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxSensor.java
similarity index 97%
rename from bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxSensor.java
rename to bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxSensor.java
index 09864851b013f..fed04e00f1b41 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxSensor.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/dto/SenseBoxSensor.java
@@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.binding.sensebox.internal.model;
+package org.openhab.binding.sensebox.internal.dto;
import com.google.gson.annotations.SerializedName;
diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/handler/SenseBoxHandler.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/handler/SenseBoxHandler.java
index 19ffa59559232..0411d29867c71 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/handler/SenseBoxHandler.java
+++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/handler/SenseBoxHandler.java
@@ -15,10 +15,10 @@
import static org.openhab.binding.sensebox.internal.SenseBoxBindingConstants.*;
import java.math.BigDecimal;
+import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.cache.ExpiringCacheMap;
@@ -40,9 +40,9 @@
import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.sensebox.internal.SenseBoxAPIConnection;
import org.openhab.binding.sensebox.internal.config.SenseBoxConfiguration;
-import org.openhab.binding.sensebox.internal.model.SenseBoxData;
-import org.openhab.binding.sensebox.internal.model.SenseBoxLocation;
-import org.openhab.binding.sensebox.internal.model.SenseBoxSensor;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxData;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxLocation;
+import org.openhab.binding.sensebox.internal.dto.SenseBoxSensor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,7 +57,8 @@
*/
@NonNullByDefault
public class SenseBoxHandler extends BaseThingHandler {
- private Logger logger = LoggerFactory.getLogger(SenseBoxHandler.class);
+
+ private final Logger logger = LoggerFactory.getLogger(SenseBoxHandler.class);
protected @NonNullByDefault({}) SenseBoxConfiguration thingConfiguration;
@@ -84,33 +85,31 @@ public void initialize() {
thingConfiguration = getConfigAs(SenseBoxConfiguration.class);
String senseBoxId = thingConfiguration.getSenseBoxId();
- logger.debug("Thing Configuration {} initialized {}", getThing().getUID().toString(), senseBoxId);
+ logger.debug("Thing Configuration {} initialized {}", getThing().getUID(), senseBoxId);
String offlineReason = "";
boolean validConfig = true;
- if (StringUtils.trimToNull(senseBoxId) == null) {
+ if (senseBoxId == null || senseBoxId.trim().isEmpty()) {
offlineReason = "senseBox ID is mandatory and must be configured";
validConfig = false;
}
if (thingConfiguration.getRefreshInterval() < MINIMUM_UPDATE_INTERVAL) {
- logger.info("Refresh interval is much too small, setting to default of {} seconds",
+ logger.warn("Refresh interval is much too small, setting to default of {} seconds",
MINIMUM_UPDATE_INTERVAL);
thingConfiguration.setRefreshInterval(MINIMUM_UPDATE_INTERVAL);
}
- cache.put(CACHE_KEY_DATA, () -> {
- return connection.reallyFetchDataFromServer(senseBoxId);
- });
-
- if (validConfig) {
+ if (senseBoxId != null && validConfig) {
+ cache.put(CACHE_KEY_DATA, () -> {
+ return connection.reallyFetchDataFromServer(senseBoxId);
+ });
updateStatus(ThingStatus.UNKNOWN);
startAutomaticRefresh();
} else {
- updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_ERROR, offlineReason);
+ updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, offlineReason);
}
-
logger.debug("Thing {} initialized {}", getThing().getUID(), getThing().getStatus());
}
@@ -119,7 +118,7 @@ public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
data = fetchData();
if (data != null && ThingStatus.ONLINE == data.getStatus()) {
- publishDataForChannel(channelUID.getId());
+ publishDataForChannel(channelUID);
updateStatus(ThingStatus.ONLINE);
} else {
@@ -144,29 +143,10 @@ private void stopAutomaticRefresh() {
private void publishData() {
logger.debug("Refreshing data for box {}, scheduled after {} seconds...", thingConfiguration.getSenseBoxId(),
thingConfiguration.getRefreshInterval());
-
data = fetchData();
if (data != null && ThingStatus.ONLINE == data.getStatus()) {
publishProperties();
-
- publishDataForChannel(CHANNEL_LOCATION);
-
- publishDataForChannel(CHANNEL_UV_INTENSITY);
- publishDataForChannel(CHANNEL_ILLUMINANCE);
- publishDataForChannel(CHANNEL_PRESSURE);
- publishDataForChannel(CHANNEL_HUMIDITY);
- publishDataForChannel(CHANNEL_TEMPERATURE);
- publishDataForChannel(CHANNEL_PARTICULATE_MATTER_2_5);
- publishDataForChannel(CHANNEL_PARTICULATE_MATTER_10);
-
- publishDataForChannel(CHANNEL_UV_INTENSITY_LR);
- publishDataForChannel(CHANNEL_ILLUMINANCE_LR);
- publishDataForChannel(CHANNEL_PRESSURE_LR);
- publishDataForChannel(CHANNEL_HUMIDITY_LR);
- publishDataForChannel(CHANNEL_TEMPERATURE_LR);
- publishDataForChannel(CHANNEL_PARTICULATE_MATTER_2_5_LR);
- publishDataForChannel(CHANNEL_PARTICULATE_MATTER_10_LR);
-
+ publishChannels();
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
@@ -186,67 +166,70 @@ private void startAutomaticRefresh() {
private void publishProperties() {
SenseBoxData localData = data;
if (localData != null) {
- thing.setProperty(PROPERTY_NAME, localData.getName());
- thing.setProperty(PROPERTY_EXPOSURE, localData.getExposure());
- thing.setProperty(PROPERTY_IMAGE_URL, localData.getDescriptor().getImageUrl());
- thing.setProperty(PROPERTY_MAP_URL, localData.getDescriptor().getMapUrl());
+ Map properties = editProperties();
+ properties.put(PROPERTY_NAME, localData.getName());
+ properties.put(PROPERTY_EXPOSURE, localData.getExposure());
+ properties.put(PROPERTY_IMAGE_URL, localData.getDescriptor().getImageUrl());
+ properties.put(PROPERTY_MAP_URL, localData.getDescriptor().getMapUrl());
+ updateProperties(properties);
}
}
- private void publishDataForChannel(String channelID) {
+ private void publishChannels() {
+ thing.getChannels().forEach(channel -> publishDataForChannel(channel.getUID()));
+ }
+
+ private void publishDataForChannel(ChannelUID channelUID) {
SenseBoxData localData = data;
- if (localData != null && isLinked(channelID)) {
- switch (channelID) {
+ if (localData != null && isLinked(channelUID)) {
+ switch (channelUID.getId()) {
case CHANNEL_LOCATION:
- updateState(CHANNEL_LOCATION, locationFromData(localData.getLocation()));
+ updateState(channelUID, locationFromData(localData.getLocation()));
break;
case CHANNEL_UV_INTENSITY:
- updateState(CHANNEL_UV_INTENSITY, decimalFromSensor(localData.getUvIntensity()));
+ updateState(channelUID, decimalFromSensor(localData.getUvIntensity()));
break;
case CHANNEL_ILLUMINANCE:
- updateState(CHANNEL_ILLUMINANCE, decimalFromSensor(localData.getLuminance()));
+ updateState(channelUID, decimalFromSensor(localData.getLuminance()));
break;
case CHANNEL_PRESSURE:
- updateState(CHANNEL_PRESSURE, decimalFromSensor(localData.getPressure()));
+ updateState(channelUID, decimalFromSensor(localData.getPressure()));
break;
case CHANNEL_HUMIDITY:
- updateState(CHANNEL_HUMIDITY, decimalFromSensor(localData.getHumidity()));
+ updateState(channelUID, decimalFromSensor(localData.getHumidity()));
break;
case CHANNEL_TEMPERATURE:
- updateState(CHANNEL_TEMPERATURE, decimalFromSensor(localData.getTemperature()));
+ updateState(channelUID, decimalFromSensor(localData.getTemperature()));
break;
case CHANNEL_PARTICULATE_MATTER_2_5:
- updateState(CHANNEL_PARTICULATE_MATTER_2_5,
- decimalFromSensor(localData.getParticulateMatter2dot5()));
+ updateState(channelUID, decimalFromSensor(localData.getParticulateMatter2dot5()));
break;
case CHANNEL_PARTICULATE_MATTER_10:
- updateState(CHANNEL_PARTICULATE_MATTER_10, decimalFromSensor(localData.getParticulateMatter10()));
+ updateState(channelUID, decimalFromSensor(localData.getParticulateMatter10()));
break;
case CHANNEL_UV_INTENSITY_LR:
- updateState(CHANNEL_UV_INTENSITY_LR, dateTimeFromSensor(localData.getUvIntensity()));
+ updateState(channelUID, dateTimeFromSensor(localData.getUvIntensity()));
break;
case CHANNEL_ILLUMINANCE_LR:
- updateState(CHANNEL_ILLUMINANCE_LR, dateTimeFromSensor(localData.getLuminance()));
+ updateState(channelUID, dateTimeFromSensor(localData.getLuminance()));
break;
case CHANNEL_PRESSURE_LR:
- updateState(CHANNEL_PRESSURE_LR, dateTimeFromSensor(localData.getPressure()));
+ updateState(channelUID, dateTimeFromSensor(localData.getPressure()));
break;
case CHANNEL_HUMIDITY_LR:
- updateState(CHANNEL_HUMIDITY_LR, dateTimeFromSensor(localData.getHumidity()));
+ updateState(channelUID, dateTimeFromSensor(localData.getHumidity()));
break;
case CHANNEL_TEMPERATURE_LR:
- updateState(CHANNEL_TEMPERATURE_LR, dateTimeFromSensor(localData.getTemperature()));
+ updateState(channelUID, dateTimeFromSensor(localData.getTemperature()));
break;
case CHANNEL_PARTICULATE_MATTER_2_5_LR:
- updateState(CHANNEL_PARTICULATE_MATTER_2_5_LR,
- dateTimeFromSensor(localData.getParticulateMatter2dot5()));
+ updateState(channelUID, dateTimeFromSensor(localData.getParticulateMatter2dot5()));
break;
case CHANNEL_PARTICULATE_MATTER_10_LR:
- updateState(CHANNEL_PARTICULATE_MATTER_10_LR,
- dateTimeFromSensor(localData.getParticulateMatter10()));
+ updateState(channelUID, dateTimeFromSensor(localData.getParticulateMatter10()));
break;
default:
- logger.debug("Command received for an unknown channel: {}", channelID);
+ logger.debug("Command received for an unknown channel: {}", channelUID.getId());
break;
}
}
@@ -254,24 +237,22 @@ private void publishDataForChannel(String channelID) {
private State dateTimeFromSensor(@Nullable SenseBoxSensor sensorData) {
State result = UnDefType.UNDEF;
-
if (sensorData != null && sensorData.getLastMeasurement() != null
- && StringUtils.isNotEmpty(sensorData.getLastMeasurement().getCreatedAt())) {
+ && sensorData.getLastMeasurement().getCreatedAt() != null
+ && !sensorData.getLastMeasurement().getCreatedAt().isEmpty()) {
result = new DateTimeType(sensorData.getLastMeasurement().getCreatedAt());
}
-
return result;
}
private State decimalFromSensor(@Nullable SenseBoxSensor sensorData) {
State result = UnDefType.UNDEF;
-
if (sensorData != null && sensorData.getLastMeasurement() != null
- && StringUtils.isNotEmpty(sensorData.getLastMeasurement().getValue())) {
+ && sensorData.getLastMeasurement().getValue() != null
+ && !sensorData.getLastMeasurement().getValue().isEmpty()) {
logger.debug("About to determine quantity for {} / {}", sensorData.getLastMeasurement().getValue(),
sensorData.getUnit());
BigDecimal bd = new BigDecimal(sensorData.getLastMeasurement().getValue());
-
switch (sensorData.getUnit()) {
case "%":
result = new QuantityType<>(bd, SmartHomeUnits.PERCENT);
@@ -304,21 +285,17 @@ private State decimalFromSensor(@Nullable SenseBoxSensor sensorData) {
logger.debug("Could not determine unit for '{}', using default", sensorData.getUnit());
result = new QuantityType<>(bd, SmartHomeUnits.ONE);
}
-
logger.debug("State: '{}'", result);
}
-
return result;
}
private State locationFromData(@Nullable SenseBoxLocation locationData) {
State result = UnDefType.UNDEF;
-
if (locationData != null) {
result = new PointType(new DecimalType(locationData.getLatitude()),
new DecimalType(locationData.getLongitude()), new DecimalType(locationData.getHeight()));
}
-
return result;
}
}
diff --git a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml
index 749873fe8410e..f1ba9d12535ea 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml
+++ b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml
@@ -10,14 +10,14 @@
This is a senseBox sensor.
-
-
-
+
+
+
senseBoxId
-
+
diff --git a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml
index 302d919ea7254..6bc6f5fe9b64a 100644
--- a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml
+++ b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml
@@ -9,7 +9,7 @@
Box descriptors like Location, description, etc.
-
+
@@ -17,13 +17,13 @@
Measurements as fetched from the API.
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -31,13 +31,13 @@
Timestamps when a measurement was last reported.
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -58,7 +58,7 @@
DateTime
Timestamp when data was measured.
-
+