[touchwand]- Added support for AlarmSensor and WallController (#8933)

* Added support for AlarmSensor and WallController

Signed-off-by: Roie Geron <roie.geron@gmail.com>
This commit is contained in:
Roie Geron
2020-11-17 01:44:03 +02:00
committed by GitHub
parent 1f4053538f
commit 387b9675fd
19 changed files with 675 additions and 77 deletions

View File

@@ -0,0 +1,173 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.touchwand.internal;
import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.*;
import java.util.ArrayList;
import javax.measure.quantity.Illuminance;
import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.touchwand.internal.dto.TouchWandAlarmSensorCurrentStatus.BinarySensorEvent;
import org.openhab.binding.touchwand.internal.dto.TouchWandAlarmSensorCurrentStatus.Sensor;
import org.openhab.binding.touchwand.internal.dto.TouchWandUnitData;
import org.openhab.binding.touchwand.internal.dto.TouchWandUnitDataAlarmSensor;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.SmartHomeUnits;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.binding.builder.ThingBuilder;
import org.openhab.core.types.Command;
/**
* The {@link TouchWandAlarmSensorHandler} is responsible for handling command for Alarm Sensor unit
*
*
* @author Roie Geron - Initial contribution
*
*/
@NonNullByDefault
public class TouchWandAlarmSensorHandler extends TouchWandBaseUnitHandler {
private static final int BATT_LEVEL_LOW = 20;
private static final int BATT_LEVEL_LOW_HYS = 5;
private boolean isBatteryLow = false;
private boolean isFirstUpdateTouchWandUnitState = true;
public TouchWandAlarmSensorHandler(Thing thing) {
super(thing);
}
@Override
void updateTouchWandUnitState(TouchWandUnitData unitData) {
if (unitData instanceof TouchWandUnitDataAlarmSensor) {
TouchWandUnitDataAlarmSensor sensor = (TouchWandUnitDataAlarmSensor) unitData;
if (isFirstUpdateTouchWandUnitState) {
removeUnsupportedChannels(sensor);
isFirstUpdateTouchWandUnitState = false;
}
updateBatteryLevel(sensor);
updateIllumination(sensor);
updateChannelLeak(sensor);
updateChannelDoorWindow(sensor);
updateChannelMotion(sensor);
updateChannelTemperature(sensor);
} else {
logger.warn("updateTouchWandUnitState incompatible TouchWandUnitData instance");
}
}
@Override
void touchWandUnitHandleCommand(Command command) {
}
void updateBatteryLevel(TouchWandUnitDataAlarmSensor unitData) {
Integer battLevel = unitData.getCurrStatus().getBatt();
updateState(CHANNEL_BATTERY_LEVEL, new DecimalType(battLevel));
int lowThreshold = isBatteryLow ? BATT_LEVEL_LOW + BATT_LEVEL_LOW_HYS : BATT_LEVEL_LOW;
boolean lowBattery = (battLevel <= lowThreshold);
updateState(CHANNEL_BATTERY_LOW, OnOffType.from(lowBattery));
isBatteryLow = lowBattery;
}
void updateIllumination(TouchWandUnitDataAlarmSensor unitData) {
for (Sensor sensor : unitData.getCurrStatus().getSensorsStatus()) {
if (sensor.type == SENSOR_TYPE_LUMINANCE) {
updateState(CHANNEL_ILLUMINATION, new QuantityType<Illuminance>(sensor.value, SmartHomeUnits.LUX));
}
}
}
void updateChannelLeak(TouchWandUnitDataAlarmSensor unitData) {
for (BinarySensorEvent bSensor : unitData.getCurrStatus().getbSensorsStatus()) {
if (bSensor.sensorType == SENSOR_TYPE_LEAK) {
boolean isLeak = bSensor.sensor.state;
updateState(CHANNEL_LEAK, OnOffType.from(isLeak));
}
}
}
void updateChannelDoorWindow(TouchWandUnitDataAlarmSensor unitData) {
for (BinarySensorEvent bSensor : unitData.getCurrStatus().getbSensorsStatus()) {
if (bSensor.sensorType == SENSOR_TYPE_DOOR_WINDOW) {
boolean isOpen = bSensor.sensor.state;
OpenClosedType myOpenClose;
myOpenClose = isOpen ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
updateState(CHANNEL_DOORWINDOW, myOpenClose);
}
}
}
void updateChannelMotion(TouchWandUnitDataAlarmSensor unitData) {
for (BinarySensorEvent bSensor : unitData.getCurrStatus().getbSensorsStatus()) {
if (bSensor.sensorType == SENSOR_TYPE_MOTION) {
boolean hasMotion = bSensor.sensor.state;
updateState(CHANNEL_MOTION, OnOffType.from(hasMotion));
}
}
}
void updateChannelTemperature(TouchWandUnitDataAlarmSensor unitData) {
for (Sensor sensor : unitData.getCurrStatus().getSensorsStatus()) {
if (sensor.type == SENSOR_TYPE_TEMPERATURE) {
updateState(CHANNEL_TEMPERATURE, new QuantityType<Temperature>(sensor.value, SIUnits.CELSIUS));
}
}
}
void removeUnsupportedChannels(TouchWandUnitDataAlarmSensor unitData) {
ArrayList<Channel> toBeRemovedChannels = new ArrayList<>(thing.getChannels());
for (BinarySensorEvent bSensor : unitData.getCurrStatus().getbSensorsStatus()) {
switch (bSensor.sensorType) {
case SENSOR_TYPE_MOTION:
toBeRemovedChannels.remove(thing.getChannel(CHANNEL_MOTION));
break;
case SENSOR_TYPE_DOOR_WINDOW:
toBeRemovedChannels.remove(thing.getChannel(CHANNEL_DOORWINDOW));
break;
case SENSOR_TYPE_LEAK:
Channel channel = thing.getChannel(CHANNEL_LEAK);
toBeRemovedChannels.remove(channel);
break;
}
}
for (Sensor sensor : unitData.getCurrStatus().getSensorsStatus()) {
switch (sensor.type) {
case SENSOR_TYPE_TEMPERATURE:
toBeRemovedChannels.remove(thing.getChannel(CHANNEL_TEMPERATURE));
break;
case SENSOR_TYPE_LUMINANCE:
toBeRemovedChannels.remove(thing.getChannel(CHANNEL_ILLUMINATION));
break;
}
}
if (unitData.getHasBattery()) {
toBeRemovedChannels.remove(thing.getChannel(CHANNEL_BATTERY_LEVEL));
toBeRemovedChannels.remove(thing.getChannel(CHANNEL_BATTERY_LOW));
}
ThingBuilder thingBuilder = editThing();
thingBuilder.withoutChannels(toBeRemovedChannels);
updateThing(thingBuilder.build());
}
}

View File

@@ -15,10 +15,12 @@ package org.openhab.binding.touchwand.internal;
import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.*;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.touchwand.internal.dto.TouchWandUnitData;
import org.openhab.binding.touchwand.internal.dto.TouchWandUnitFromJson;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
@@ -31,10 +33,6 @@ import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
/**
* The {@link TouchWandBaseUnitHandler} is responsible for handling commands and status updates
* for TouchWand units. This is an abstract class , units should implement the specific command
@@ -46,9 +44,10 @@ import com.google.gson.JsonParser;
@NonNullByDefault
public abstract class TouchWandBaseUnitHandler extends BaseThingHandler implements TouchWandUnitUpdateListener {
private static final int UNITS_STATUS_UPDATE_DELAY_SEC = 1;
protected final Logger logger = LoggerFactory.getLogger(TouchWandBaseUnitHandler.class);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_SHUTTER, THING_TYPE_SWITCH,
THING_TYPE_WALLCONTROLLER, THING_TYPE_DIMMER);
THING_TYPE_WALLCONTROLLER, THING_TYPE_DIMMER, THING_TYPE_ALARMSENSOR);
protected String unitId = "";
protected @Nullable TouchWandBridgeHandler bridgeHandler;
@@ -60,7 +59,10 @@ public abstract class TouchWandBaseUnitHandler extends BaseThingHandler implemen
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
// updateTouchWandUnitState(getUnitState(unitId));
TouchWandUnitData myUnitData = getUnitState(unitId);
if (myUnitData != null) {
updateTouchWandUnitState(myUnitData);
}
} else {
touchWandUnitHandleCommand(command);
}
@@ -98,47 +100,34 @@ public abstract class TouchWandBaseUnitHandler extends BaseThingHandler implemen
}
updateStatus(ThingStatus.UNKNOWN);
scheduler.execute(() -> {
scheduler.schedule(() -> {
boolean thingReachable = false;
if (myTmpBridgeHandler != null) {
String response = myTmpBridgeHandler.touchWandClient.cmdGetUnitById(unitId);
thingReachable = !response.isEmpty();
if (thingReachable) {
updateStatus(ThingStatus.ONLINE);
updateTouchWandUnitState(TouchWandUnitFromJson.parseResponse(response));
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
}
});
}, UNITS_STATUS_UPDATE_DELAY_SEC, TimeUnit.SECONDS);
}
@SuppressWarnings("unused") // not used at the moment till touchWand state in hub will be fixed
private int getUnitState(String unitId) {
int status = 0;
private @Nullable TouchWandUnitData getUnitState(String unitId) {
TouchWandBridgeHandler touchWandBridgeHandler = bridgeHandler;
if (touchWandBridgeHandler == null) {
return status;
return null;
}
String response = touchWandBridgeHandler.touchWandClient.cmdGetUnitById(unitId);
if (!response.isEmpty()) {
return status;
if (response.isEmpty()) {
return null;
}
JsonParser jsonParser = new JsonParser();
try {
JsonObject unitObj = jsonParser.parse(response).getAsJsonObject();
status = unitObj.get("currStatus").getAsInt();
if (!this.getThing().getStatusInfo().getStatus().equals(ThingStatus.ONLINE)) {
updateStatus(ThingStatus.ONLINE);
}
} catch (JsonParseException | IllegalStateException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"Could not parse cmdGetUnitById:" + e.getMessage());
}
return status;
return TouchWandUnitFromJson.parseResponse(response);
}
abstract void touchWandUnitHandleCommand(Command command);

View File

@@ -36,7 +36,7 @@ public class TouchWandBindingConstants {
public static final ThingTypeUID THING_TYPE_SHUTTER = new ThingTypeUID(BINDING_ID, "shutter");
public static final ThingTypeUID THING_TYPE_WALLCONTROLLER = new ThingTypeUID(BINDING_ID, "wallcontroller");
public static final ThingTypeUID THING_TYPE_DIMMER = new ThingTypeUID(BINDING_ID, "dimmer");
public static final ThingTypeUID THING_TYPE_ALARMSENSOR = new ThingTypeUID(BINDING_ID, "AlarmSensor"); // TBD
public static final ThingTypeUID THING_TYPE_ALARMSENSOR = new ThingTypeUID(BINDING_ID, "alarmsensor");
// List of all Channel ids
public static final String CHANNEL_SWITCH = "switch";
@@ -46,6 +46,11 @@ public class TouchWandBindingConstants {
public static final String CHANNEL_WALLCONTROLLER_ACTION = "wallaction";
public static final String CHANNEL_BATTERY_LEVEL = "battery_level";
public static final String CHANNEL_BATTERY_LOW = "battery_low";
public static final String CHANNEL_LEAK = "leak";
public static final String CHANNEL_MOTION = "motion";
public static final String CHANNEL_ILLUMINATION = "illumination";
public static final String CHANNEL_DOORWINDOW = "isOpen";
public static final String CHANNEL_TEMPERATURE = "temperature";
// List of configuration parameters
@@ -77,7 +82,7 @@ public class TouchWandBindingConstants {
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_SHUTTER);
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_WALLCONTROLLER);
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_DIMMER);
// SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_ALARMSENSOR); // not implemented yet
SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_ALARMSENSOR);
}
public static final String TYPE_WALLCONTROLLER = "WallController";
@@ -85,6 +90,13 @@ public class TouchWandBindingConstants {
public static final String TYPE_SHUTTER = "shutter";
public static final String TYPE_DIMMER = "dimmer";
public static final String TYPE_ALARMSENSOR = "AlarmSensor";
public static final String TYPE_UNKNOWN = "unknown";
public static final int SENSOR_TYPE_TEMPERATURE = 1;
public static final int SENSOR_TYPE_LUMINANCE = 3;
public static final int SENSOR_TYPE_LEAK = 6;
public static final int SENSOR_TYPE_DOOR_WINDOW = 10;
public static final int SENSOR_TYPE_MOTION = 12;
public static final String[] SUPPORTED_TOUCHWAND_TYPES = { TYPE_WALLCONTROLLER, TYPE_SWITCH, TYPE_SHUTTER,
TYPE_DIMMER, TYPE_ALARMSENSOR };

View File

@@ -68,6 +68,8 @@ public class TouchWandHandlerFactory extends BaseThingHandlerFactory {
return new TouchWandWallControllerHandler(thing);
} else if (THING_TYPE_DIMMER.equals(thingTypeUID)) {
return new TouchWandDimmerHandler(thing);
} else if (THING_TYPE_ALARMSENSOR.equals(thingTypeUID)) {
return new TouchWandAlarmSensorHandler(thing);
}
return null;

View File

@@ -117,16 +117,21 @@ public class TouchWandRestClient {
}
public String cmdListUnits() {
String command = buildUrl(CMD_LIST_UNITS);
String response = sendCommand(command, METHOD_GET, "");
String response = "";
if (isConnected) {
String command = buildUrl(CMD_LIST_UNITS);
response = sendCommand(command, METHOD_GET, "");
}
return response;
}
public String cmdGetUnitById(String id) {
String command = buildUrl(CMD_GET_UNIT_BY_ID) + "id=" + id;
String response = sendCommand(command, METHOD_GET, "");
String response = "";
if (isConnected) {
String command = buildUrl(CMD_GET_UNIT_BY_ID) + "id=" + id;
response = sendCommand(command, METHOD_GET, "");
}
return response;
}
@@ -167,9 +172,11 @@ public class TouchWandRestClient {
}
private String cmdUnitAction(String action) {
String command = buildUrl(CMD_UNIT_ACTION);
String response = sendCommand(command, METHOD_POST, action);
String response = "";
if (isConnected) {
String command = buildUrl(CMD_UNIT_ACTION);
response = sendCommand(command, METHOD_POST, action);
}
return response;
}

View File

@@ -17,6 +17,7 @@ import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.C
import java.time.Instant;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.touchwand.internal.dto.Csc;
import org.openhab.binding.touchwand.internal.dto.TouchWandUnitData;
import org.openhab.binding.touchwand.internal.dto.TouchWandUnitDataWallController;
import org.openhab.core.thing.Thing;
@@ -33,12 +34,12 @@ import org.openhab.core.types.Command;
@NonNullByDefault
public class TouchWandWallControllerHandler extends TouchWandBaseUnitHandler {
private long timeSinceLastEventMs;
private static final int ADJUSTENT_EVENT_FILTER_TIME_MILLISEC = 2000; // 2 seconds
private long timeLastEventMs;
private static final int ADJACENT_EVENT_FILTER_TIME_MILLISEC = 2000; // 2 seconds
public TouchWandWallControllerHandler(Thing thing) {
super(thing);
timeSinceLastEventMs = Instant.now().toEpochMilli();
timeLastEventMs = Instant.now().toEpochMilli();
}
@Override
@@ -47,12 +48,16 @@ public class TouchWandWallControllerHandler extends TouchWandBaseUnitHandler {
@Override
void updateTouchWandUnitState(TouchWandUnitData unitData) {
int status = ((TouchWandUnitDataWallController) unitData).getCurrStatus();
long timeDiff = Instant.now().toEpochMilli() - timeSinceLastEventMs;
if ((timeDiff) > ADJUSTENT_EVENT_FILTER_TIME_MILLISEC) {
String action = status <= 100 ? "SHORT" : "LONG";
triggerChannel(CHANNEL_WALLCONTROLLER_ACTION, action);
if (unitData instanceof TouchWandUnitDataWallController) {
Csc status = ((TouchWandUnitDataWallController) unitData).getCurrStatus();
long ts = status.getTs();
long timeDiff = ts - timeLastEventMs;
if ((timeDiff) > ADJACENT_EVENT_FILTER_TIME_MILLISEC) {
int value = status.getKeyAttr();
String action = (value <= 100) ? "SHORT" : "LONG";
triggerChannel(CHANNEL_WALLCONTROLLER_ACTION, action);
}
timeLastEventMs = status.getTs();
}
timeSinceLastEventMs = Instant.now().toEpochMilli();
}
}

View File

@@ -50,7 +50,8 @@ import com.google.gson.JsonSyntaxException;
@NonNullByDefault
public class TouchWandWebSockets {
private static final int CONNECT_TIMEOUT_SEC = 10;
private static final int CONNECT_TIMEOUT_SEC = 15;
private static final int CONNECT_TIMEOUT_MS = CONNECT_TIMEOUT_SEC * 1000;
private static final int WEBSOCKET_RECONNECT_INTERVAL_SEC = CONNECT_TIMEOUT_SEC * 2;
private static final int WEBSOCKET_IDLE_TIMEOUT_MS = CONNECT_TIMEOUT_SEC * 10 * 1000;
private final Logger logger = LoggerFactory.getLogger(TouchWandWebSockets.class);
@@ -82,7 +83,7 @@ public class TouchWandWebSockets {
return;
}
client.setConnectTimeout(CONNECT_TIMEOUT_SEC);
client.setConnectTimeout(CONNECT_TIMEOUT_MS);
ClientUpgradeRequest request = new ClientUpgradeRequest();
request.setSubProtocols("relay_protocol");
@@ -136,7 +137,9 @@ public class TouchWandWebSockets {
public void onConnect(Session session) {
logger.debug("TouchWandWebSockets connected to {}", session.getRemoteAddress().toString());
try {
session.getRemote().sendString("{\"myopenhab\": \"myopenhab\"}");
long timestamp = System.currentTimeMillis(); // need unique id
String controllerIdStr = String.format("{\"contId\": \"openhab%d\"}", timestamp);
session.getRemote().sendString(controllerIdStr);
} catch (IOException e) {
logger.warn("sendString : {}", e.getMessage());
}

View File

@@ -90,9 +90,7 @@ public class TouchWandUnitDiscoveryService extends AbstractDiscoveryService
for (JsonElement unit : jsonArray) {
TouchWandUnitData touchWandUnit;
touchWandUnit = TouchWandUnitFromJson.parseResponse(unit.getAsJsonObject());
if (touchWandUnit == null) {
continue;
}
if (!touchWandBridgeHandler.isAddSecondaryControllerUnits()) {
if (!Arrays.asList(CONNECTIVITY_OPTIONS).contains(touchWandUnit.getConnectivity())) {
continue;
@@ -118,6 +116,9 @@ public class TouchWandUnitDiscoveryService extends AbstractDiscoveryService
case TYPE_SHUTTER:
addDeviceDiscoveryResult(touchWandUnit, THING_TYPE_SHUTTER);
break;
case TYPE_ALARMSENSOR:
addDeviceDiscoveryResult(touchWandUnit, THING_TYPE_ALARMSENSOR);
break;
default:
continue;
}

View File

@@ -0,0 +1,122 @@
/**
* 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.touchwand.internal.dto;
import java.lang.reflect.Type;
import java.util.Map.Entry;
import org.openhab.binding.touchwand.internal.dto.TouchWandAlarmSensorCurrentStatus.Alarm;
import org.openhab.binding.touchwand.internal.dto.TouchWandAlarmSensorCurrentStatus.BinarySensor;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
/**
* The {@link AlarmSensorUnitDataDeserializer} implements AlarmSensorUnitData unit
* Json De-serializer.
*
* @author Roie Geron - Initial contribution
*/
public class AlarmSensorUnitDataDeserializer implements JsonDeserializer<TouchWandUnitDataAlarmSensor> {
static final Gson gson = new Gson();
static GsonBuilder builder = new GsonBuilder();
@Override
public TouchWandUnitDataAlarmSensor deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
TouchWandUnitDataAlarmSensor touchWandUnitDataAlarmSensor = new TouchWandUnitDataAlarmSensor();
JsonObject jsonObject = json.getAsJsonObject();
touchWandUnitDataAlarmSensor.setId(jsonObject.get("id").getAsInt());
touchWandUnitDataAlarmSensor.setName(jsonObject.get("name").getAsString());
touchWandUnitDataAlarmSensor.setConnectivity(jsonObject.get("connectivity").getAsString());
touchWandUnitDataAlarmSensor.setType(jsonObject.get("type").getAsString());
touchWandUnitDataAlarmSensor.setHasBattery(jsonObject.get("hasBattery").getAsBoolean());
JsonElement powerMeterElement = jsonObject.get("hasPowerMeter");
if (powerMeterElement != null && !powerMeterElement.isJsonNull()) {
touchWandUnitDataAlarmSensor.setHasPowerMeter(powerMeterElement.getAsBoolean());
} else {
touchWandUnitDataAlarmSensor.setHasPowerMeter(false);
}
JsonElement status = jsonObject.get("status");
if (status != null && !status.isJsonNull()) { // Sometimes status is null
touchWandUnitDataAlarmSensor.setStatus(jsonObject.get("status").getAsString());
}
JsonObject currentStatusObj = builder.create().fromJson(jsonObject.get("currStatus").getAsJsonObject(),
JsonObject.class);
if (currentStatusObj != null) {
TouchWandAlarmSensorCurrentStatus touchWandUnitDataAlarmSensorCurrentStatus = touchWandUnitDataAlarmSensor
.getCurrStatus();
for (Entry<String, JsonElement> entry : currentStatusObj.entrySet()) {
String key = entry.getKey();
String splits[] = key.split("_"); // the key is xxxx_n where xxx is sensor type and n is
String keyName = splits[0];
int index = 0;
if (splits.length > 1 && !splits[1].isEmpty()) {
try {
index = Integer.parseInt(splits[1]);
} catch (final NumberFormatException e) {
index = 0;
}
}
switch (keyName) {
case "batt":
touchWandUnitDataAlarmSensorCurrentStatus.setBatt(entry.getValue().getAsInt());
break;
case "alarm":
Alarm alarm = gson.fromJson(entry.getValue().getAsJsonObject(), Alarm.class);
TouchWandAlarmSensorCurrentStatus.AlarmEvent alarmEvent = new TouchWandAlarmSensorCurrentStatus.AlarmEvent();
if (alarm != null) {
alarmEvent.alarm = alarm;
alarmEvent.alarmType = index;
}
touchWandUnitDataAlarmSensor.getCurrStatus().getAlarmsStatus().add(alarmEvent);
break;
case "sensor":
TouchWandAlarmSensorCurrentStatus.Sensor sensor = new TouchWandAlarmSensorCurrentStatus.Sensor();
sensor.value = entry.getValue().getAsFloat();
sensor.type = index;
touchWandUnitDataAlarmSensor.getCurrStatus().getSensorsStatus().add(sensor);
break;
case "bsensor":
BinarySensor bsensor = gson.fromJson(entry.getValue().getAsJsonObject(), BinarySensor.class);
TouchWandAlarmSensorCurrentStatus.BinarySensorEvent bsensorevent = new TouchWandAlarmSensorCurrentStatus.BinarySensorEvent();
if (bsensor != null) {
bsensorevent.sensor = bsensor;
bsensorevent.sensorType = index;
}
touchWandUnitDataAlarmSensor.getCurrStatus().getbSensorsStatus().add(bsensorevent);
break;
default:
break;
}
}
}
return touchWandUnitDataAlarmSensor;
}
}

View File

@@ -13,16 +13,19 @@
package org.openhab.binding.touchwand.internal.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link Csc} implements Csc data class.
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class Csc {
private int sceneNo;
private int ts;
private int keyAttr;
private int sceneNo = 0;
private long ts = 0;
private int keyAttr = 0;
public int getSceneNo() {
return sceneNo;
@@ -32,11 +35,11 @@ public class Csc {
this.sceneNo = sceneNo;
}
public int getTs() {
public long getTs() {
return ts;
}
public void setTs(int ts) {
public void setTs(long ts) {
this.ts = ts;
}

View File

@@ -13,15 +13,17 @@
package org.openhab.binding.touchwand.internal.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link CurrStatus} implements CurrStatus data class.
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class CurrStatus {
private Csc csc;
private Csc csc = new Csc();
public Csc getCsc() {
return csc;

View File

@@ -0,0 +1,92 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.touchwand.internal.dto;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link TouchWandAlarmSensorCurrentStatus} implements Alarm Sensor unit
* CurrentStatus data property.
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class TouchWandAlarmSensorCurrentStatus {
private int batt;
private List<Sensor> sensorsStatus = new ArrayList<Sensor>();
private List<AlarmEvent> alarmsStatus = new ArrayList<AlarmEvent>();
private List<BinarySensorEvent> bSensorsStatus = new ArrayList<BinarySensorEvent>();
public void setBatt(Integer batt) {
this.batt = batt;
}
public int getBatt() {
return batt;
}
public void setSensorsStatus(List<Sensor> sensorsStatus) {
this.sensorsStatus = sensorsStatus;
}
public List<Sensor> getSensorsStatus() {
return sensorsStatus;
}
public List<BinarySensorEvent> getbSensorsStatus() {
return bSensorsStatus;
}
public void setbSensorsStatus(List<BinarySensorEvent> bSensorsStatus) {
this.bSensorsStatus = bSensorsStatus;
}
public List<AlarmEvent> getAlarmsStatus() {
return alarmsStatus;
}
public void setAlarmsStatus(List<AlarmEvent> alarmsStatus) {
this.alarmsStatus = alarmsStatus;
}
public static class Alarm {
public int event;
public long ts;
}
public static class AlarmEvent {
int alarmType;
Alarm alarm = new Alarm();
}
public static class Sensor {
public int type;
public float value;
}
public static class BinarySensor {
public long ts;
public boolean state;
}
public static class BinarySensorEvent {
public int sensorType;
public BinarySensor sensor = new BinarySensor();
}
}

View File

@@ -195,5 +195,5 @@ public abstract class TouchWandUnitData {
this.roomId = roomId;
}
public abstract Integer getCurrStatus();
public abstract Object getCurrStatus();
}

View File

@@ -0,0 +1,43 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.touchwand.internal.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link TouchWandUnitDataAlarmSensor} implements Alarm Sensor unit
* data property.
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class TouchWandUnitDataAlarmSensor extends TouchWandUnitData {
private TouchWandAlarmSensorCurrentStatus currStatus = new TouchWandAlarmSensorCurrentStatus();
@Override
public TouchWandAlarmSensorCurrentStatus getCurrStatus() {
return this.currStatus;
}
public class AlarmEventType {
public int eventsNum;
public String description = "";
}
public class SensorType {
public int type;
public String description = "";
}
}

View File

@@ -13,23 +13,22 @@
package org.openhab.binding.touchwand.internal.dto;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link TouchWandUnitDataWallController} implements WallController unit
* property.
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class TouchWandUnitDataWallController extends TouchWandUnitData {
private CurrStatus currStatus;
private CurrStatus currStatus = new CurrStatus();
@Override
public Integer getCurrStatus() {
if (currStatus != null) {
return currStatus.getCsc().getKeyAttr();
} else {
return 0;
}
public Csc getCurrStatus() {
return currStatus.getCsc();
}
public void setCurrStatus(CurrStatus currStatus) {

View File

@@ -17,8 +17,14 @@ import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.*
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
/**
@@ -26,8 +32,11 @@ import com.google.gson.JsonParser;
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class TouchWandUnitFromJson {
private final static Logger logger = LoggerFactory.getLogger(TouchWandUnitFromJson.class);
public TouchWandUnitFromJson() {
}
@@ -36,11 +45,11 @@ public class TouchWandUnitFromJson {
TouchWandUnitData touchWandUnit;
String type = jsonUnit.get("type").getAsString();
if (!Arrays.asList(SUPPORTED_TOUCHWAND_TYPES).contains(type)) {
return null;
type = TYPE_UNKNOWN;
}
if (!jsonUnit.has("currStatus") || (jsonUnit.get("currStatus") == null)) {
return null;
type = TYPE_UNKNOWN;
}
switch (type) {
@@ -56,8 +65,21 @@ public class TouchWandUnitFromJson {
case TYPE_SHUTTER:
touchWandUnit = gson.fromJson(jsonUnit, TouchWandShutterSwitchUnitData.class);
break;
case TYPE_ALARMSENSOR:
Gson builder = new GsonBuilder()
.registerTypeAdapter(TouchWandUnitDataAlarmSensor.class, new AlarmSensorUnitDataDeserializer())
.create();
touchWandUnit = builder.fromJson(jsonUnit, TouchWandUnitDataAlarmSensor.class);
break;
case TYPE_UNKNOWN:
touchWandUnit = new TouchWandUnknownTypeUnitData();
break;
default:
return null;
touchWandUnit = new TouchWandUnknownTypeUnitData();
}
if (touchWandUnit == null) {
touchWandUnit = new TouchWandUnknownTypeUnitData();
}
return touchWandUnit;
@@ -65,7 +87,15 @@ public class TouchWandUnitFromJson {
public static TouchWandUnitData parseResponse(String JsonUnit) {
final JsonParser jsonParser = new JsonParser();
JsonObject unitObj = jsonParser.parse(JsonUnit).getAsJsonObject();
return parseResponse(unitObj);
TouchWandUnitData myTouchWandUnitData;
JsonObject unitObj;
try {
unitObj = jsonParser.parse(JsonUnit).getAsJsonObject();
myTouchWandUnitData = parseResponse(unitObj);
} catch (JsonParseException | IllegalStateException e) {
logger.warn("Could not parse response {}", JsonUnit);
myTouchWandUnitData = new TouchWandUnknownTypeUnitData(); // Return unknown type
}
return myTouchWandUnitData;
}
}

View File

@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.touchwand.internal.dto;
import static org.openhab.binding.touchwand.internal.TouchWandBindingConstants.TYPE_UNKNOWN;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link TouchWandUnknownTypeUnitData} implements unknown unit data
* property.
* It makes the code generic in case parsing error or unknown types
*
* @author Roie Geron - Initial contribution
*/
@NonNullByDefault
public class TouchWandUnknownTypeUnitData extends TouchWandUnitData {
public TouchWandUnknownTypeUnitData() {
this.setType(TYPE_UNKNOWN);
}
@Override
public Integer getCurrStatus() {
return 0;
}
}

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="touchwand"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="alarmsensor">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"></bridge-type-ref>
</supported-bridge-type-refs>
<label>TouchWand Alarm Sensor Unit</label>
<channels>
<channel id="battery_level" typeId="system.battery-level"/>
<channel id="battery_low" typeId="system.low-battery"/>
<channel id="leak" typeId="leak"></channel>
<channel id="motion" typeId="motion"/>
<channel id="illumination" typeId="illumination"/>
<channel id="isOpen" typeId="isOpen"/>
<channel id="temperature" typeId="temperature"/>
</channels>
</thing-type>
<channel-type id="leak">
<item-type>Switch</item-type>
<label>Leak Detected</label>
<state readOnly="true"></state>
</channel-type>
<channel-type id="temperature">
<item-type>Number:Temperature</item-type>
<label>Temperature</label>
<category>Temperature</category>
<state pattern="%.1f %unit%" readOnly="true">
</state>
</channel-type>
<channel-type id="illumination">
<item-type>Number:Illuminance</item-type>
<label>Illumination</label>
<description>
This channel shows the brightness of the environment in Lux.
</description>
<state pattern="%d %unit%" readOnly="true"></state>
</channel-type>
<channel-type id="isOpen">
<item-type>Contact</item-type>
<label>Open Status</label>
<category>Contact</category>
<state readOnly="true"></state>
</channel-type>
<channel-type id="motion">
<item-type>Switch</item-type>
<label>Motion Status</label>
<category>Motion</category>
<state readOnly="true"></state>
</channel-type>
</thing:thing-descriptions>