Skip to content

Commit

Permalink
implement alarms
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Herwege <mark.herwege@telenet.be>
  • Loading branch information
mherwege committed Jan 16, 2023
1 parent f7015c2 commit 447e413
Show file tree
Hide file tree
Showing 14 changed files with 670 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class NikoHomeControlBindingConstants {
public static final ThingTypeUID THING_TYPE_ACCESS = new ThingTypeUID(BINDING_ID, "access");
public static final ThingTypeUID THING_TYPE_ACCESS_RINGANDCOMEIN = new ThingTypeUID(BINDING_ID,
"accessRingAndComeIn");
public static final ThingTypeUID THING_TYPE_ALARM = new ThingTypeUID(BINDING_ID, "alarm");

// thing type sets
public static final Set<ThingTypeUID> BRIDGE_THING_TYPES_UIDS = Set.of(BRIDGEI_THING_TYPE, BRIDGEII_THING_TYPE);
Expand All @@ -62,9 +63,12 @@ public class NikoHomeControlBindingConstants {
THING_TYPE_ENERGYMETER, THING_TYPE_GASMETER, THING_TYPE_WATERMETER);
public static final Set<ThingTypeUID> ACCESS_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCESS,
THING_TYPE_ACCESS_RINGANDCOMEIN);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream.of(BRIDGE_THING_TYPES_UIDS.stream(),
ACTION_THING_TYPES_UIDS.stream(), THERMOSTAT_THING_TYPES_UIDS.stream(), METER_THING_TYPES_UIDS.stream(),
ACCESS_THING_TYPES_UIDS.stream()).flatMap(i -> i).collect(Collectors.toSet());
public static final Set<ThingTypeUID> ALARM_THING_TYPES_UIDS = Set.of(THING_TYPE_ALARM);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
.of(BRIDGE_THING_TYPES_UIDS.stream(), ACTION_THING_TYPES_UIDS.stream(),
THERMOSTAT_THING_TYPES_UIDS.stream(), METER_THING_TYPES_UIDS.stream(),
ACCESS_THING_TYPES_UIDS.stream(), ALARM_THING_TYPES_UIDS.stream())
.flatMap(i -> i).collect(Collectors.toSet());

// List of all Channel ids
public static final String CHANNEL_BUTTON = "button";
Expand Down Expand Up @@ -95,6 +99,8 @@ public class NikoHomeControlBindingConstants {
public static final String CHANNEL_RING_AND_COME_IN = "ringandcomein";
public static final String CHANNEL_LOCK = "lock";

public static final String CHANNEL_ALARM_STATE = "alarmstate";

public static final String CHANNEL_ALARM = "alarm";
public static final String CHANNEL_NOTICE = "notice";

Expand All @@ -113,11 +119,13 @@ public class NikoHomeControlBindingConstants {
public static final String CONFIG_THERMOSTAT_ID = "thermostatId";
public static final String CONFIG_OVERRULETIME = "overruleTime";

public static final String METER_ID = "meterId";
public static final String CONFIG_METER_ID = "meterId";
public static final String CONFIG_METER_REFRESH = "refresh";

public static final String CONFIG_ACCESS_ID = "accessId";

public static final String CONFIG_ALARM_ID = "alarmId";

// Thing properties
public static final String PROPERTY_DEVICE_TYPE = "deviceType";
public static final String PROPERTY_DEVICE_TECHNOLOGY = "deviceTechnology";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlAccessHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlActionHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlAlarmHandler;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler1;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlMeterHandler;
Expand Down Expand Up @@ -77,6 +78,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return new NikoHomeControlMeterHandler(thing);
} else if (ACCESS_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new NikoHomeControlAccessHandler(thing);
} else if (ALARM_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) {
return new NikoHomeControlAlarmHandler(thing);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.openhab.binding.nikohomecontrol.internal.handler.NikoHomeControlBridgeHandler2;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAccess;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAction;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAlarm;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcMeter;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcThermostat;
import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlCommunication;
Expand Down Expand Up @@ -94,6 +95,7 @@ public void discoverDevices() {
discoverThermostatDevices(bridgeHandler, nhcComm);
discoverMeterDevices(bridgeHandler, nhcComm);
discoverAccessDevices(bridgeHandler, nhcComm);
discoverAlarmDevices(bridgeHandler, nhcComm);
}

private void discoverActionDevices(NikoHomeControlBridgeHandler bridgeHandler,
Expand Down Expand Up @@ -156,19 +158,19 @@ private void discoverMeterDevices(NikoHomeControlBridgeHandler bridgeHandler,
switch (nhcMeter.getType()) {
case ENERGY_LIVE:
addDevice(new ThingUID(THING_TYPE_ENERGYMETER_LIVE, bridgeHandler.getThing().getUID(), deviceId),
METER_ID, deviceId, thingName, thingLocation);
CONFIG_METER_ID, deviceId, thingName, thingLocation);
break;
case ENERGY:
addDevice(new ThingUID(THING_TYPE_ENERGYMETER, bridgeHandler.getThing().getUID(), deviceId),
METER_ID, deviceId, thingName, thingLocation);
CONFIG_METER_ID, deviceId, thingName, thingLocation);
break;
case GAS:
addDevice(new ThingUID(THING_TYPE_GASMETER, bridgeHandler.getThing().getUID(), deviceId), deviceId,
METER_ID, thingName, thingLocation);
CONFIG_METER_ID, thingName, thingLocation);
break;
case WATER:
addDevice(new ThingUID(THING_TYPE_WATERMETER, bridgeHandler.getThing().getUID(), deviceId),
METER_ID, deviceId, thingName, thingLocation);
CONFIG_METER_ID, deviceId, thingName, thingLocation);
break;
default:
logger.debug("unrecognized meter type {} for {} {}", nhcMeter.getType(), deviceId, thingName);
Expand Down Expand Up @@ -201,6 +203,18 @@ private void discoverAccessDevices(NikoHomeControlBridgeHandler bridgeHandler,
});
}

private void discoverAlarmDevices(NikoHomeControlBridgeHandler bridgeHandler,
NikoHomeControlCommunication nhcComm) {
Map<String, NhcAlarm> alarmDevices = nhcComm.getAlarmDevices();

alarmDevices.forEach((deviceId, nhcAlarm) -> {
String thingName = nhcAlarm.getName();
String thingLocation = nhcAlarm.getLocation();
addDevice(new ThingUID(THING_TYPE_ALARM, bridgeHandler.getThing().getUID(), deviceId), CONFIG_ALARM_ID,
deviceId, thingName, thingLocation);
});
}

private void addDevice(ThingUID uid, String deviceIdKey, String deviceId, String thingName,
@Nullable String thingLocation) {
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2010-2022 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.nikohomecontrol.internal.handler;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* {@link NikoHomeControlAlarmConfig} is the general config class for Niko Home Control Alarm systems.
*
* @author Mark Herwege - Initial Contribution
*/
@NonNullByDefault
public class NikoHomeControlAlarmConfig {
public String alarmId = "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/**
* Copyright (c) 2010-2022 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.nikohomecontrol.internal.handler;

import static org.openhab.binding.nikohomecontrol.internal.NikoHomeControlBindingConstants.*;
import static org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlConstants.*;
import static org.openhab.core.types.RefreshType.REFRESH;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAlarm;
import org.openhab.binding.nikohomecontrol.internal.protocol.NhcAlarmEvent;
import org.openhab.binding.nikohomecontrol.internal.protocol.NikoHomeControlCommunication;
import org.openhab.binding.nikohomecontrol.internal.protocol.nhc2.NhcAlarm2;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.types.Command;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* The {@link NikoHomeControlAlarmHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Mark Herwege - Initial Contribution
*/
@NonNullByDefault
public class NikoHomeControlAlarmHandler extends NikoHomeControlBaseHandler implements NhcAlarmEvent {

private final Logger logger = LoggerFactory.getLogger(NikoHomeControlAlarmHandler.class);

private volatile @Nullable NhcAlarm nhcAlarm;

public NikoHomeControlAlarmHandler(Thing thing) {
super(thing);
}

@Override
void handleCommandSelection(ChannelUID channelUID, Command command) {
NhcAlarm nhcAlarm = this.nhcAlarm;
if (nhcAlarm == null) {
logger.debug("alarm device with ID {} not initialized", deviceId);
return;
}

logger.debug("handle command {} for {}", command, channelUID);

if (REFRESH.equals(command)) {

} else if (CHANNEL_SWITCH.equals(channelUID.getId()) && command instanceof OnOffType) {
OnOffType s = (OnOffType) command;
if (OnOffType.ON.equals(s)) {
nhcAlarm.executeArm();
} else {
nhcAlarm.executeDisarm();
}
} else {
logger.debug("unexpected command for channel {}", channelUID.getId());
}

updateStatus(ThingStatus.ONLINE);
}

@Override
public void initialize() {
initialized = false;

NikoHomeControlAlarmConfig config = getConfig().as(NikoHomeControlAlarmConfig.class);
deviceId = config.alarmId;

NikoHomeControlBridgeHandler bridgeHandler = getBridgeHandler();
if (bridgeHandler == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.configuration-error.invalid-bridge-handler");
return;
}

updateStatus(ThingStatus.UNKNOWN);

Bridge bridge = getBridge();
if ((bridge != null) && ThingStatus.ONLINE.equals(bridge.getStatus())) {
// We need to do this in a separate thread because we may have to wait for the
// communication to become active
scheduler.submit(this::startCommunication);
}
}

@Override
synchronized void startCommunication() {
NikoHomeControlCommunication nhcComm = getCommunication(getBridgeHandler());

if (nhcComm == null) {
return;
}

if (!nhcComm.communicationActive()) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
"@text/offline.communication-error");
return;
}

NhcAlarm nhcAlarm = nhcComm.getAlarmDevices().get(deviceId);
if (nhcAlarm == null) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
"@text/offline.configuration-error.deviceId");
return;
}

nhcAlarm.setEventHandler(this);

updateProperties(nhcAlarm);

String location = nhcAlarm.getLocation();
if (thing.getLocation() == null) {
thing.setLocation(location);
}

this.nhcAlarm = nhcAlarm;

initialized = true;
deviceInitialized();
}

@Override
void refresh() {
NhcAlarm alarm = nhcAlarm;
if (alarm != null) {
alarmEvent(alarm.getState());
}
}

@Override
public void dispose() {
NikoHomeControlCommunication nhcComm = getCommunication(getBridgeHandler());
if (nhcComm != null) {
NhcAlarm alarm = nhcComm.getAlarmDevices().get(deviceId);
if (alarm != null) {
alarm.unsetEventHandler();
}
}
nhcAlarm = null;
super.dispose();
}

private void updateProperties(NhcAlarm nhcAlarm) {
Map<String, String> properties = new HashMap<>();

if (nhcAlarm instanceof NhcAlarm2) {
NhcAlarm2 alarm = (NhcAlarm2) nhcAlarm;
properties.put(PROPERTY_DEVICE_TYPE, alarm.getDeviceType());
properties.put(PROPERTY_DEVICE_TECHNOLOGY, alarm.getDeviceTechnology());
properties.put(PROPERTY_DEVICE_MODEL, alarm.getDeviceModel());
}

thing.setProperties(properties);
}

@Override
public void alarmEvent(String state) {
NhcAlarm nhcAlarm = this.nhcAlarm;
if (nhcAlarm == null) {
logger.debug(" alarm device with ID {} not initialized", deviceId);
return;
}

updateState(CHANNEL_SWITCH, NHCOFF.equals(state) ? OnOffType.OFF : OnOffType.ON);
updateState(CHANNEL_ALARM_STATE, StringType.valueOf(ALARMSTATES.get(state)));
if (NHCTRIGGERED.equals(state)) {
triggerChannel(CHANNEL_ALARM);
}
updateStatus(ThingStatus.ONLINE);
}
}
Loading

0 comments on commit 447e413

Please sign in to comment.