2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.phc.internal.handler;
15 import static org.openhab.binding.phc.internal.PHCBindingConstants.*;
17 import java.math.BigDecimal;
18 import java.util.HashMap;
20 import java.util.Map.Entry;
22 import org.openhab.core.config.core.Configuration;
23 import org.openhab.core.library.types.DecimalType;
24 import org.openhab.core.library.types.OnOffType;
25 import org.openhab.core.library.types.PercentType;
26 import org.openhab.core.library.types.StopMoveType;
27 import org.openhab.core.library.types.UpDownType;
28 import org.openhab.core.thing.Bridge;
29 import org.openhab.core.thing.ChannelUID;
30 import org.openhab.core.thing.Thing;
31 import org.openhab.core.thing.ThingStatus;
32 import org.openhab.core.thing.ThingStatusDetail;
33 import org.openhab.core.thing.binding.BaseThingHandler;
34 import org.openhab.core.thing.binding.ThingHandler;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.State;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * The {@link PHCHandler} is responsible for handling commands, which are
42 * sent to one of the channels.
44 * @author Jonas Hohaus - Initial contribution
47 public class PHCHandler extends BaseThingHandler {
49 private final Logger logger = LoggerFactory.getLogger(PHCHandler.class);
51 private String moduleAddress; // like DIP switches
53 private final short[] times = new short[4];
54 private final Map<String, State> channelState = new HashMap<>();
55 private PHCBridgeHandler bridgeHandler;
57 public PHCHandler(Thing thing) {
62 public void initialize() {
63 moduleAddress = (String) getConfig().get(ADDRESS);
65 if (getPHCBridgeHandler() == null) {
69 module = Byte.parseByte(new StringBuilder(moduleAddress).reverse().toString(), 2);
71 if (getThing().getThingTypeUID().equals(THING_TYPE_AM) || getThing().getThingTypeUID().equals(THING_TYPE_JRM)) {
73 } else if (getThing().getThingTypeUID().equals(THING_TYPE_DIM)) {
76 getPHCBridgeHandler().addModule(module);
78 if (getThing().getThingTypeUID().equals(THING_TYPE_JRM)) {
79 times[0] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_1)).shortValue() * 10);
80 times[1] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_2)).shortValue() * 10);
81 times[2] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_3)).shortValue() * 10);
82 times[3] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_4)).shortValue() * 10);
84 } else if (getThing().getThingTypeUID().equals(THING_TYPE_DIM)) {
85 times[0] = (((BigDecimal) getConfig().get(DIM_TIME_1)).shortValue());
86 times[1] = (((BigDecimal) getConfig().get(DIM_TIME_2)).shortValue());
89 Bridge bridge = getBridge();
90 if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
91 updateStatus(ThingStatus.ONLINE);
93 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
97 public void handleIncoming(String channelId, OnOffType state) {
98 if (logger.isDebugEnabled()) {
99 logger.debug("EM command: {}, last: {}, in: {}", channelId, channelState.get(channelId), state);
102 if (!channelState.containsKey(channelId) || !channelState.get(channelId).equals(state)) {
103 postCommand(channelId, state);
104 channelState.put(channelId, state);
109 public void handleCommand(ChannelUID channelUID, Command command) {
110 final String groupId = channelUID.getGroupId();
111 if (getThing().getStatus().equals(ThingStatus.ONLINE)) {
112 if ((CHANNELS_JRM.equals(groupId) && (command instanceof UpDownType || command instanceof StopMoveType))
113 || (CHANNELS_DIM.equals(groupId)
114 && (command instanceof OnOffType || command instanceof PercentType))) {
115 getPHCBridgeHandler().send(groupId, module & 0x1F, channelUID.getIdWithoutGroup(), command,
116 times[Integer.parseInt(channelUID.getIdWithoutGroup())]);
117 } else if ((CHANNELS_AM.equals(groupId) || CHANNELS_EM_LED.equals(groupId))
118 && command instanceof OnOffType) {
119 getPHCBridgeHandler().send(groupId, module & 0x1F, channelUID.getIdWithoutGroup(), command, (short) 0);
122 logger.debug("send command: {}, {}", channelUID, command);
124 logger.info("The Thing {} is offline.", getThing().getUID());
129 public void handleUpdate(ChannelUID channelUID, State newState) {
130 if (CHANNELS_JRM_TIME.equals(channelUID.getGroupId())) {
132 .parseInt(channelUID.getIdWithoutGroup())] = (short) (((DecimalType) newState).floatValue() * 10);
137 public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
138 if (isInitialized()) { // prevents change of address
139 validateConfigurationParameters(configurationParameters);
141 Configuration configuration = editConfiguration();
142 for (Entry<String, Object> configurationParmeter : configurationParameters.entrySet()) {
143 if (!configurationParmeter.getKey().equals(ADDRESS)) {
144 configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue());
146 configuration.put(configurationParmeter.getKey(), moduleAddress);
150 // persist new configuration and reinitialize handler
152 updateConfiguration(configuration);
155 super.handleConfigurationUpdate(configurationParameters);
159 private PHCBridgeHandler getPHCBridgeHandler() {
160 if (bridgeHandler == null) {
161 Bridge bridge = getBridge();
162 if (bridge == null) {
163 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING,
164 "The Thing requires to select a Bridge");
168 ThingHandler handler = bridge.getHandler();
169 if (handler instanceof PHCBridgeHandler) {
170 bridgeHandler = (PHCBridgeHandler) handler;
172 logger.debug("No available bridge handler for {}.", bridge.getUID());
174 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_MISSING_ERROR,
175 "No available bridge handler.");
181 return bridgeHandler;