[livisismarthome] Support for the indoor siren device added (#16914)

Signed-off-by: Sven Strohschein <sven.strohschein@gmail.com>
Signed-off-by: Sven Strohschein <novanic@gmx.de>
This commit is contained in:
Sven Strohschein 2024-06-27 19:25:58 +02:00 committed by GitHub
parent 33a9894bde
commit e662320877
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 198 additions and 12 deletions

View File

@ -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
@ -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 |

View File

@ -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)
@ -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");
@ -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);
@ -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());
@ -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";

View File

@ -297,6 +297,14 @@ public class LivisiClient {
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),

View File

@ -28,6 +28,7 @@ public class ActionParamsDTO {
private IntegerActionParamDTO shutterLevel;
private StringActionParamDTO operationMode;
private StringActionParamDTO rampDirection;
private StringActionParamDTO activeChannel;
/**
* @return the onState
@ -126,4 +127,18 @@ public class ActionParamsDTO {
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;
}
}

View File

@ -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;
@ -56,6 +56,17 @@ public class StateActionSetterDTO extends ActionDTO {
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}.
*

View File

@ -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";
@ -221,6 +222,15 @@ public class CapabilityDTO {
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.
*

View File

@ -164,6 +164,14 @@ public class CapabilityStateDTO {
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();
}

View File

@ -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;
@ -128,6 +129,20 @@ public class EventPropertiesDTO {
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
*/

View File

@ -761,6 +761,18 @@ public class LivisiBridgeHandler extends BaseBridgeHandler
(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

View File

@ -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();
@ -120,6 +124,12 @@ public class LivisiDeviceHandler extends BaseThingHandler implements DeviceStatu
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);
}
@ -214,6 +224,14 @@ public class LivisiDeviceHandler extends BaseThingHandler implements DeviceStatu
}
}
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.");
@ -473,6 +491,10 @@ public class LivisiDeviceHandler extends BaseThingHandler implements DeviceStatu
} 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());
@ -638,6 +660,9 @@ public class LivisiDeviceHandler extends BaseThingHandler implements DeviceStatu
case CapabilityDTO.TYPE_ALARMACTUATOR:
updateAlarmActuatorChannels(capability);
break;
case CapabilityDTO.TYPE_SIRENACTUATOR:
updateSirenActuatorChannels(capability);
break;
case CapabilityDTO.TYPE_MOTIONDETECTIONSENSOR:
updateMotionDetectionSensorChannels(capability);
break;
@ -812,6 +837,30 @@ public class LivisiDeviceHandler extends BaseThingHandler implements DeviceStatu
}
}
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) {

View File

@ -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>

View File

@ -140,6 +140,30 @@
<category>Alarm</category>
</channel-type>
<!-- SirenActuator Channel (Alarm) -->
<channel-type id="sirenAlarmActuator">
<item-type>Switch</item-type>
<label>Alarm</label>
<description>Switches the alarm of the siren on/off</description>
<category>Siren</category>
</channel-type>
<!-- SirenActuator Channel (Notification) -->
<channel-type id="sirenNotificationActuator">
<item-type>Switch</item-type>
<label>Notification</label>
<description>Switches the notification sound of the siren on/off</description>
<category>Siren</category>
</channel-type>
<!-- SirenActuator Channel (Feedback) -->
<channel-type id="sirenFeedbackActuator">
<item-type>Switch</item-type>
<label>Feedback</label>
<description>Switches the feedback sound of the siren on/off</description>
<category>Siren</category>
</channel-type>
<!-- MotionDetectionSensor Channel -->
<channel-type id="motionDetectionSensor">
<item-type>Number</item-type>