Skip to content

Commit

Permalink
[livisismarthome] Support for the indoor siren device added (openhab#…
Browse files Browse the repository at this point in the history
…16914)

Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com>
Signed-off-by: Sven Strohschein <novanic@gmx.de>
  • Loading branch information
Novanic authored and matchews committed Oct 18, 2024
1 parent ae551d9 commit e8ee780
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 12 deletions.
2 changes: 2 additions & 0 deletions bundles/org.openhab.binding.livisismarthome/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The channels are described in detail in the next chapter.
| WSC2 | Wall Mounted Smart Controller | button1, button2, button1Count, button2Count, batteryLow |
| WSD | Wall Mounted Smoke Detector, old version | smoke, alarm, batteryLow |
| WSD2 | Wall Mounted Smoke Detector, new version | smoke, alarm, batteryLow |
| SIR | Wall Mounted Siren, indoor | siren, batteryLow |

Powermeter devices

Expand Down Expand Up @@ -94,6 +95,7 @@ However, only devices will appear that are added in the LIVISI SmartHome app bef
| operationMode | String | The mode of a thermostat (auto/manual) | RST, RST2, WRT |
| rollershutter | Rollershutter | Controls a roller shutter | ISR2 |
| targetTemperature | Number | Sets the target temperature in °C (min 6 °C, max 30 °C) | RST, RST2, WRT |
| siren | Switch | Switches the siren (ON/OFF) | SIR |
| smoke | Switch | Indicates, if smoke was detected (ON/OFF) | WSD, WSD2 |
| status | String | Status of the SHC (ACTIVE/NORMAL, INITIALIZING/REBOOTING or SHUTTINGDOWN) | SHC (bridge) |
| switch | Switch | A switch to turn the device or variable on/off (ON/OFF) | ISS2, PSS, PSSO, VariableActuator |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public class LivisiBindingConstants {
public static final String DEVICE_ISS2 = "ISS2"; // inwall smart switch
public static final String DEVICE_WSD = "WSD"; // wall mounted smoke detector
public static final String DEVICE_WSD2 = "WSD2"; // wall mounted smoke detector
public static final String DEVICE_SIR = "SIR"; // wall mounted siren indoor
public static final String DEVICE_WMD = "WMD"; // wall mounted motion detector indoor
public static final String DEVICE_WMDO = "WMDO"; // wall mounted motion detector outdoor
public static final String DEVICE_WSC2 = "WSC2"; // wall mounted smart controller (2 buttons)
Expand All @@ -88,12 +89,12 @@ public class LivisiBindingConstants {

public static final Set<String> SUPPORTED_DEVICES = Set.of(DEVICE_SHC, DEVICE_SHCA, DEVICE_PSS, DEVICE_PSSO,
DEVICE_BT_PSS, DEVICE_VARIABLE_ACTUATOR, DEVICE_RST, DEVICE_RST2, DEVICE_WRT, DEVICE_WDS, DEVICE_ISS2,
DEVICE_WSD, DEVICE_WSD2, DEVICE_WMD, DEVICE_WMDO, DEVICE_WSC2, DEVICE_BRC8, DEVICE_ISC2, DEVICE_ISD2,
DEVICE_ISR2, DEVICE_PSD, DEVICE_ANALOG_METER, DEVICE_GENERATION_METER, DEVICE_SMART_METER,
DEVICE_WSD, DEVICE_WSD2, DEVICE_SIR, DEVICE_WMD, DEVICE_WMDO, DEVICE_WSC2, DEVICE_BRC8, DEVICE_ISC2,
DEVICE_ISD2, DEVICE_ISR2, DEVICE_PSD, DEVICE_ANALOG_METER, DEVICE_GENERATION_METER, DEVICE_SMART_METER,
DEVICE_TWO_WAY_METER);

public static final Set<String> BATTERY_POWERED_DEVICES = Set.of(DEVICE_ISC2, DEVICE_RST, DEVICE_RST2, DEVICE_WRT,
DEVICE_WDS, DEVICE_WSD, DEVICE_WSD2, DEVICE_WMD, DEVICE_WMDO, DEVICE_WSC2, DEVICE_BRC8);
DEVICE_WDS, DEVICE_WSD, DEVICE_WSD2, DEVICE_SIR, DEVICE_WMD, DEVICE_WMDO, DEVICE_WSC2, DEVICE_BRC8);

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge");
Expand All @@ -109,6 +110,7 @@ public class LivisiBindingConstants {
public static final ThingTypeUID THING_TYPE_ISS2 = new ThingTypeUID(BINDING_ID, DEVICE_ISS2);
public static final ThingTypeUID THING_TYPE_WSD = new ThingTypeUID(BINDING_ID, DEVICE_WSD);
public static final ThingTypeUID THING_TYPE_WSD2 = new ThingTypeUID(BINDING_ID, DEVICE_WSD2);
public static final ThingTypeUID THING_TYPE_SIR = new ThingTypeUID(BINDING_ID, DEVICE_SIR);
public static final ThingTypeUID THING_TYPE_WMD = new ThingTypeUID(BINDING_ID, DEVICE_WMD);
public static final ThingTypeUID THING_TYPE_WMDO = new ThingTypeUID(BINDING_ID, DEVICE_WMDO);
public static final ThingTypeUID THING_TYPE_WSC2 = new ThingTypeUID(BINDING_ID, DEVICE_WSC2);
Expand All @@ -125,9 +127,10 @@ public class LivisiBindingConstants {

public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES = Set.of(THING_TYPE_PSS, THING_TYPE_PSSO,
THING_TYPE_BT_PSS, THING_TYPE_VARIABLE_ACTUATOR, THING_TYPE_RST, THING_TYPE_RST2, THING_TYPE_WRT,
THING_TYPE_WDS, THING_TYPE_ISS2, THING_TYPE_WSD, THING_TYPE_WSD2, THING_TYPE_WMD, THING_TYPE_WMDO,
THING_TYPE_WSC2, THING_TYPE_BRC8, THING_TYPE_ISC2, THING_TYPE_ISD2, THING_TYPE_ISR2, THING_TYPE_PSD,
THING_TYPE_ANALOG_METER, THING_TYPE_GENERATION_METER, THING_TYPE_SMART_METER, THING_TYPE_TWO_WAY_METER);
THING_TYPE_WDS, THING_TYPE_ISS2, THING_TYPE_WSD, THING_TYPE_WSD2, THING_TYPE_SIR, THING_TYPE_WMD,
THING_TYPE_WMDO, THING_TYPE_WSC2, THING_TYPE_BRC8, THING_TYPE_ISC2, THING_TYPE_ISD2, THING_TYPE_ISR2,
THING_TYPE_PSD, THING_TYPE_ANALOG_METER, THING_TYPE_GENERATION_METER, THING_TYPE_SMART_METER,
THING_TYPE_TWO_WAY_METER);

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Stream
.concat(Stream.of(THING_TYPE_BRIDGE), SUPPORTED_DEVICE_THING_TYPES.stream()).collect(Collectors.toSet());
Expand All @@ -140,6 +143,9 @@ public class LivisiBindingConstants {
public static final String CHANNEL_CONTACT = "contact";
public static final String CHANNEL_SMOKE = "smoke";
public static final String CHANNEL_ALARM = "alarm";
public static final String CHANNEL_SIREN_ALARM = "sirenAlarm";
public static final String CHANNEL_SIREN_NOTIFICATION = "sirenNotification";
public static final String CHANNEL_SIREN_FEEDBACK = "sirenFeedback";
public static final String CHANNEL_MOTION_COUNT = "motionCount";
public static final String CHANNEL_LUMINANCE = "luminance";
public static final String CHANNEL_OPERATION_MODE = "operationMode";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,14 @@ public void setAlarmActuatorState(final String capabilityId, final boolean alarm
new StateActionSetterDTO(capabilityId, CapabilityDTO.TYPE_ALARMACTUATOR, alarmState));
}

/**
* Sets the siren state.
*/
public void setSirenActuatorState(final String capabilityId, final String activeChannel) throws IOException {
executePost(createActionURL(),
new StateActionSetterDTO(capabilityId, CapabilityDTO.TYPE_SIRENACTUATOR, activeChannel));
}

/**
* Load the device and returns a {@link List} of {@link DeviceDTO}s.
* VariableActuators are returned additionally (independent from the device ids),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class ActionParamsDTO {
private IntegerActionParamDTO shutterLevel;
private StringActionParamDTO operationMode;
private StringActionParamDTO rampDirection;
private StringActionParamDTO activeChannel;

/**
* @return the onState
Expand Down Expand Up @@ -126,4 +127,18 @@ public StringActionParamDTO getRampDirection() {
public void setRampDirection(StringActionParamDTO rampDirection) {
this.rampDirection = rampDirection;
}

/**
* @return the activeChannel
*/
public StringActionParamDTO getActiveChannel() {
return activeChannel;
}

/**
* @param activeChannel the operationMode to set
*/
public void setActiveChannel(StringActionParamDTO activeChannel) {
this.activeChannel = activeChannel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@ public class StateActionSetterDTO extends ActionDTO {
* @param capabilityId String of the 32 character capability id
* @param capabilityType the type of the {@link CapabilityDTO}, {@link CapabilityDTO#TYPE_SWITCHACTUATOR} or
* {@link CapabilityDTO#TYPE_VARIABLEACTUATOR}
* @param state the new state as boolean (true=on, false=off)
* @param newState the new newState as boolean (true=on, false=off)
*/
public StateActionSetterDTO(String capabilityId, String capabilityType, boolean state) {
public StateActionSetterDTO(String capabilityId, String capabilityType, boolean newState) {
setType(ACTION_TYPE_SETSTATE);
setTargetCapabilityById(capabilityId);
final ActionParamsDTO params = new ActionParamsDTO();

if (CapabilityDTO.TYPE_SWITCHACTUATOR.equals(capabilityType)) {
params.setOnState(new BooleanActionParamDTO(CONSTANT, state));
params.setOnState(new BooleanActionParamDTO(CONSTANT, newState));
} else if (CapabilityDTO.TYPE_VARIABLEACTUATOR.equals(capabilityType)) {
params.setValue(new BooleanActionParamDTO(CONSTANT, state));
params.setValue(new BooleanActionParamDTO(CONSTANT, newState));
} else if (CapabilityDTO.TYPE_ALARMACTUATOR.equals(capabilityType)) {
params.setOnState(new BooleanActionParamDTO(CONSTANT, state));
params.setOnState(new BooleanActionParamDTO(CONSTANT, newState));
} else if (CapabilityDTO.TYPE_THERMOSTATACTUATOR.equals(capabilityType)) {
final String operationMode;
if (state) {
if (newState) {
operationMode = CapabilityStateDTO.STATE_VALUE_OPERATION_MODE_AUTO;
} else {
operationMode = CapabilityStateDTO.STATE_VALUE_OPERATION_MODE_MANUAL;
Expand All @@ -56,6 +56,17 @@ public StateActionSetterDTO(String capabilityId, String capabilityType, boolean
setParams(params);
}

public StateActionSetterDTO(String capabilityId, String capabilityType, String newState) {
setType(ACTION_TYPE_SETSTATE);
setTargetCapabilityById(capabilityId);
final ActionParamsDTO params = new ActionParamsDTO();

if (CapabilityDTO.TYPE_SIRENACTUATOR.equals(capabilityType)) {
params.setActiveChannel(new StringActionParamDTO(CONSTANT, newState));
}
setParams(params);
}

/**
* Constructs a new {@link StateActionSetterDTO}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class CapabilityDTO {
public static final String TYPE_WINDOWDOORSENSOR = "WindowDoorSensor";
public static final String TYPE_SMOKEDETECTORSENSOR = "SmokeDetectorSensor";
public static final String TYPE_ALARMACTUATOR = "AlarmActuator";
public static final String TYPE_SIRENACTUATOR = "SirenActuator";
public static final String TYPE_MOTIONDETECTIONSENSOR = "MotionDetectionSensor";
public static final String TYPE_LUMINANCESENSOR = "LuminanceSensor";
public static final String TYPE_PUSHBUTTONSENSOR = "PushButtonSensor";
Expand Down Expand Up @@ -221,6 +222,15 @@ public boolean isTypeAlarmActuator() {
return TYPE_ALARMACTUATOR.equals(getType());
}

/**
* Returns true, if the {@link CapabilityDTO} is of type SirenActuator.
*
* @return true if it is an SirenActuator, otherwise false
*/
public boolean isTypeSirenActuator() {
return TYPE_SIRENACTUATOR.equals(getType());
}

/**
* Returns true, if the {@link CapabilityDTO} is of type MotionDetectionSensor.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ public void setAlarmActuatorState(final Boolean on) {
getState().getOnState().setValue(on);
}

public String getSirenActuatorState() {
return getState().getActiveChannelState().getValue();
}

public void setSirenActuatorState(final String activeChannel) {
getState().getActiveChannelState().setValue(activeChannel);
}

public Integer getMotionDetectionSensorState() {
return getState().getMotionDetectedCountState().getValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class EventPropertiesDTO {
/** Writable capability properties **/
private Integer dimLevel;
private Boolean onState;
private String activeChannel;
private String operationMode;
private String operationStatus;
private Double pointTemperature;
Expand Down Expand Up @@ -128,6 +129,20 @@ public void setOnState(final Boolean onState) {
this.onState = onState;
}

/**
* @return the activeChannel
*/
public String getActiveChannel() {
return activeChannel;
}

/**
* @param activeChannel the activeChannel to set
*/
public void setActiveChannel(final String activeChannel) {
this.activeChannel = activeChannel;
}

/**
* @return the operationMode
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,18 @@ public void commandSwitchAlarm(final String deviceId, final boolean alarmState)
(capabilityId) -> client.setAlarmActuatorState(capabilityId, alarmState));
}

/**
* Sends the command to turn the siren of the {@link DeviceDTO} with the given id on or off. Is called by the
* {@link LivisiDeviceHandler} for siren {@link DeviceDTO}s like SIR.
*
* @param deviceId device id
* @param sirenState siren state (boolean)
*/
public void commandSwitchSiren(final String deviceId, final String sirenState) {
executeCommand(deviceId, CapabilityDTO.TYPE_SIRENACTUATOR,
(capabilityId) -> client.setSirenActuatorState(capabilityId, sirenState));
}

/**
* Sends the command to set the operation mode of the {@link DeviceDTO} with the given deviceId to auto (or manual,
* if
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ public class LivisiDeviceHandler extends BaseThingHandler implements DeviceStatu
private static final int MAX_TEMPERATURE_CELSIUS = 30;
private static final String LONG_PRESS = "LongPress";
private static final String SHORT_PRESS = "ShortPress";
private static final String SIREN_ALARM = "Alarm";
private static final String SIREN_NOTIFICATION = "Notification";
private static final String SIREN_FEEDBACK = "Feedback";
private static final String SIREN_NONE = "None";

private final Logger logger = LoggerFactory.getLogger(LivisiDeviceHandler.class);
private final Object lock = new Object();
Expand Down Expand Up @@ -120,6 +124,12 @@ private void executeCommand(ChannelUID channelUID, Command command, LivisiBridge
commandSetOperationMode(command, bridgeHandler);
} else if (CHANNEL_ALARM.equals(channelUID.getId())) {
commandSwitchAlarm(command, bridgeHandler);
} else if (CHANNEL_SIREN_ALARM.equals(channelUID.getId())) {
commandSwitchSiren(command, SIREN_ALARM, bridgeHandler);
} else if (CHANNEL_SIREN_NOTIFICATION.equals(channelUID.getId())) {
commandSwitchSiren(command, SIREN_NOTIFICATION, bridgeHandler);
} else if (CHANNEL_SIREN_FEEDBACK.equals(channelUID.getId())) {
commandSwitchSiren(command, SIREN_FEEDBACK, bridgeHandler);
} else {
logger.debug("UNSUPPORTED channel {} for device {}.", channelUID.getId(), deviceId);
}
Expand Down Expand Up @@ -214,6 +224,14 @@ private void commandSwitchAlarm(Command command, LivisiBridgeHandler bridgeHandl
}
}

private void commandSwitchSiren(Command command, String notificationSound, LivisiBridgeHandler bridgeHandler) {
if (command instanceof OnOffType && OnOffType.ON.equals(command)) {
bridgeHandler.commandSwitchSiren(deviceId, notificationSound);
} else {
bridgeHandler.commandSwitchSiren(deviceId, SIREN_NONE);
}
}

@Override
public void initialize() {
logger.debug("Initializing LIVISI SmartHome device handler.");
Expand Down Expand Up @@ -473,6 +491,10 @@ private boolean updateDevice(EventDTO event, CapabilityDTO capability) {
} else if (capability.isTypeAlarmActuator()) {
capabilityState.setAlarmActuatorState(event.getProperties().getOnState());

// SirenActuator
} else if (capability.isTypeSirenActuator()) {
capabilityState.setSirenActuatorState(event.getProperties().getActiveChannel());

// MotionDetectionSensor
} else if (capability.isTypeMotionDetectionSensor()) {
capabilityState.setMotionDetectionSensorState(event.getProperties().getMotionDetectedCount());
Expand Down Expand Up @@ -638,6 +660,9 @@ private void updateCapabilityChannels(DeviceDTO device, CapabilityDTO capability
case CapabilityDTO.TYPE_ALARMACTUATOR:
updateAlarmActuatorChannels(capability);
break;
case CapabilityDTO.TYPE_SIRENACTUATOR:
updateSirenActuatorChannels(capability);
break;
case CapabilityDTO.TYPE_MOTIONDETECTIONSENSOR:
updateMotionDetectionSensorChannels(capability);
break;
Expand Down Expand Up @@ -812,6 +837,30 @@ private void updateAlarmActuatorChannels(CapabilityDTO capability) {
}
}

private void updateSirenActuatorChannels(CapabilityDTO capability) {
final String sirenState = capability.getCapabilityState().getSirenActuatorState();
if (sirenState != null) {
switch (sirenState) {
case SIREN_ALARM:
updateState(CHANNEL_SIREN_ALARM, OnOffType.ON);
break;
case SIREN_NOTIFICATION:
updateState(CHANNEL_SIREN_NOTIFICATION, OnOffType.ON);
break;
case SIREN_FEEDBACK:
updateState(CHANNEL_SIREN_FEEDBACK, OnOffType.ON);
break;
default:
// "None" and everything else switches the siren sound off
updateState(CHANNEL_SIREN_ALARM, OnOffType.OFF);
updateState(CHANNEL_SIREN_NOTIFICATION, OnOffType.OFF);
updateState(CHANNEL_SIREN_FEEDBACK, OnOffType.OFF);
}
} else {
logStateNull(capability);
}
}

private void updateMotionDetectionSensorChannels(CapabilityDTO capability) {
final Integer motionCount = capability.getCapabilityState().getMotionDetectionSensorState();
if (motionCount != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="livisismarthome"
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="SIR">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>

<label>Wall Mounted Siren Indoor (SIR)</label>
<description>A battery powered indoor siren.</description>

<channels>
<channel id="sirenAlarm" typeId="sirenAlarmActuator"/>
<channel id="sirenNotification" typeId="sirenNotificationActuator"/>
<channel id="sirenFeedback" typeId="sirenFeedbackActuator"/>
<channel id="batteryLow" typeId="system.low-battery"/>
</channels>

<representation-property>id</representation-property>

<config-description-ref uri="thing-type:livisismarthome:config"/>
</thing-type>
</thing:thing-descriptions>
Loading

0 comments on commit e8ee780

Please sign in to comment.