2 * Copyright (c) 2010-2024 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.OnOffType;
24 import org.openhab.core.library.types.PercentType;
25 import org.openhab.core.library.types.StopMoveType;
26 import org.openhab.core.library.types.UpDownType;
27 import org.openhab.core.thing.Bridge;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.binding.BaseThingHandler;
33 import org.openhab.core.thing.binding.ThingHandler;
34 import org.openhab.core.types.Command;
35 import org.openhab.core.types.State;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * The {@link PHCHandler} is responsible for handling commands, which are
41 * sent to one of the channels.
43 * @author Jonas Hohaus - Initial contribution
46 public class PHCHandler extends BaseThingHandler {
48 private final Logger logger = LoggerFactory.getLogger(PHCHandler.class);
50 private String moduleAddress; // like DIP switches
52 private final short[] times = new short[4];
53 private final Map<String, State> channelState = new HashMap<>();
54 private PHCBridgeHandler bridgeHandler;
56 public PHCHandler(Thing thing) {
61 public void initialize() {
62 moduleAddress = (String) getConfig().get(ADDRESS);
64 if (getPHCBridgeHandler() == null) {
68 module = Byte.parseByte(new StringBuilder(moduleAddress).reverse().toString(), 2);
70 if (getThing().getThingTypeUID().equals(THING_TYPE_AM) || getThing().getThingTypeUID().equals(THING_TYPE_JRM)) {
72 } else if (getThing().getThingTypeUID().equals(THING_TYPE_DIM)) {
75 getPHCBridgeHandler().addModule(module);
77 if (getThing().getThingTypeUID().equals(THING_TYPE_JRM)) {
78 times[0] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_1)).shortValue() * 10);
79 times[1] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_2)).shortValue() * 10);
80 times[2] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_3)).shortValue() * 10);
81 times[3] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_4)).shortValue() * 10);
83 } else if (getThing().getThingTypeUID().equals(THING_TYPE_DIM)) {
84 times[0] = (((BigDecimal) getConfig().get(DIM_TIME_1)).shortValue());
85 times[1] = (((BigDecimal) getConfig().get(DIM_TIME_2)).shortValue());
88 Bridge bridge = getBridge();
89 if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
90 updateStatus(ThingStatus.ONLINE);
92 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
96 public void handleIncoming(String channelId, OnOffType state) {
97 if (logger.isDebugEnabled()) {
98 logger.debug("EM command: {}, last: {}, in: {}", channelId, channelState.get(channelId), state);
101 if (!channelState.containsKey(channelId) || !channelState.get(channelId).equals(state)) {
102 postCommand(channelId, state);
103 channelState.put(channelId, state);
108 public void handleCommand(ChannelUID channelUID, Command command) {
109 final String groupId = channelUID.getGroupId();
110 if (getThing().getStatus().equals(ThingStatus.ONLINE)) {
111 if ((CHANNELS_JRM.equals(groupId) && (command instanceof UpDownType || command instanceof StopMoveType))
112 || (CHANNELS_DIM.equals(groupId)
113 && (command instanceof OnOffType || command instanceof PercentType))) {
114 getPHCBridgeHandler().send(groupId, module & 0x1F, channelUID.getIdWithoutGroup(), command,
115 times[Integer.parseInt(channelUID.getIdWithoutGroup())]);
116 } else if ((CHANNELS_AM.equals(groupId) || CHANNELS_EM_LED.equals(groupId))
117 && command instanceof OnOffType) {
118 getPHCBridgeHandler().send(groupId, module & 0x1F, channelUID.getIdWithoutGroup(), command, (short) 0);
121 logger.debug("send command: {}, {}", channelUID, command);
123 logger.info("The Thing {} is offline.", getThing().getUID());
128 public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
129 if (isInitialized()) { // prevents change of address
130 validateConfigurationParameters(configurationParameters);
132 Configuration configuration = editConfiguration();
133 for (Entry<String, Object> configurationParmeter : configurationParameters.entrySet()) {
134 if (!configurationParmeter.getKey().equals(ADDRESS)) {
135 configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue());
137 configuration.put(configurationParmeter.getKey(), moduleAddress);
141 // persist new configuration and reinitialize handler
143 updateConfiguration(configuration);
146 super.handleConfigurationUpdate(configurationParameters);
150 private PHCBridgeHandler getPHCBridgeHandler() {
151 if (bridgeHandler == null) {
152 Bridge bridge = getBridge();
153 if (bridge == null) {
154 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING,
155 "The Thing requires to select a Bridge");
159 ThingHandler handler = bridge.getHandler();
160 if (handler instanceof PHCBridgeHandler phcBridgeHandler) {
161 bridgeHandler = phcBridgeHandler;
163 logger.debug("No available bridge handler for {}.", bridge.getUID());
165 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_MISSING_ERROR,
166 "No available bridge handler.");
172 return bridgeHandler;