]> git.basschouten.com Git - openhab-addons.git/blob
440f6224088ac0b96f7815bb3fac296b0344dd3a
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.cm11a.internal.handler;
14
15 import java.io.IOException;
16
17 import org.openhab.binding.cm11a.internal.InvalidAddressException;
18 import org.openhab.binding.cm11a.internal.X10Interface;
19 import org.openhab.core.config.core.Configuration;
20 import org.openhab.core.library.types.OnOffType;
21 import org.openhab.core.library.types.PercentType;
22 import org.openhab.core.thing.Bridge;
23 import org.openhab.core.thing.ChannelUID;
24 import org.openhab.core.thing.Thing;
25 import org.openhab.core.thing.ThingStatus;
26 import org.openhab.core.thing.ThingStatusDetail;
27 import org.openhab.core.thing.ThingStatusInfo;
28 import org.openhab.core.thing.binding.BaseThingHandler;
29 import org.openhab.core.types.State;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * This is an abstract base class for the "Thing" handlers (i.e. Cm11aApplianceHandler and Cm11aLampHandler).
35  * It is not used by the Bridge handler (Cm11aHandler)
36  *
37  * @author Bob Raker - Initial contribution
38  *
39  */
40 public abstract class Cm11aAbstractHandler extends BaseThingHandler {
41
42     /**
43      * The House and Unit codes set on the module, i.e. A1, J14
44      */
45     protected String houseUnitCode;
46
47     /**
48      * The X10 function
49      */
50     protected int x10Function;
51
52     /**
53      * The channel ID
54      */
55     protected ChannelUID channelUID;
56
57     /**
58      * The current State of the device
59      */
60     protected State currentState;
61
62     /**
63      * Number of CM11a dim increments for dimable devices
64      */
65     static final int X10_DIM_INCREMENTS = 22;
66     static final String HOUSE_UNIT_CODE = "houseUnitCode";
67     static final String NO_BRIDGE_ERROR = "No bridge found using house unit code ";
68
69     private final Logger logger = LoggerFactory.getLogger(Cm11aAbstractHandler.class);
70
71     /**
72      * The construction
73      *
74      * @param thing The "Thing" to be handled
75      */
76     public Cm11aAbstractHandler(Thing thing) {
77         super(thing);
78     }
79
80     @Override
81     public void initialize() {
82         Configuration config = thing.getConfiguration();
83
84         houseUnitCode = (String) config.get(HOUSE_UNIT_CODE);
85         Bridge bridge = getBridge();
86         if (bridge == null) {
87             logger.warn("{}", NO_BRIDGE_ERROR + houseUnitCode);
88             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, NO_BRIDGE_ERROR + houseUnitCode);
89             return;
90         }
91
92         if (ThingStatus.ONLINE.equals(bridge.getStatus())) {
93             updateStatus(ThingStatus.ONLINE);
94         } else {
95             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
96         }
97     }
98
99     @Override
100     public void dispose() {
101         houseUnitCode = null;
102     }
103
104     @Override
105     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
106         logger.debug("CM11A status changed to {}.", bridgeStatusInfo.getStatus());
107
108         if (bridgeStatusInfo.getStatus() != ThingStatus.ONLINE) {
109             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
110             logger.debug("CM11A is not online. Bridge status: {}", bridgeStatusInfo.getStatus());
111             return;
112         }
113
114         if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
115             if (houseUnitCode.length() > 0) {
116                 // The config must be present and was set during initialization
117                 updateStatus(ThingStatus.ONLINE);
118             } else {
119                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
120             }
121         }
122     }
123
124     /**
125      * Will be called by the X10Interface when it is ready for this X10 device to use the X10 bus.
126      * Child classes should override this method with the specific process necessary to update the
127      * hardware with the latest data.
128      *
129      * <p>
130      * Warning: This will be called in a different thread. It must be thread safe.
131      * </p>
132      *
133      * <p>
134      * Retries in the event of interface problems will be handled by the X10Interface. If a comms
135      * problem occurs and the method throws an exception, this device will be rescheduled again later.
136      * </p>
137      */
138     public abstract void updateHardware(X10Interface x10Interface) throws IOException, InvalidAddressException;
139
140     public State getCurrentState() {
141         return currentState;
142     }
143
144     public void setCurrentState(State currentState) {
145         this.currentState = currentState;
146     }
147
148     /**
149      * Subtract the specified number of X10 "dims" from the current state
150      *
151      * @param dims The number of dims to remove
152      * @return The updated current state
153      */
154     public State addDimsToCurrentState(int dims) {
155         if (!(currentState instanceof PercentType)) {
156             if (currentState instanceof OnOffType && currentState == OnOffType.ON) {
157                 currentState = PercentType.HUNDRED;
158             } else {
159                 currentState = PercentType.ZERO;
160             }
161         }
162         // The current state is stored in a PercentType object and therefore needs to be converted to an incremental
163         // percent
164         int curPercent = ((PercentType) currentState).intValue();
165         // dims is a number between 0 and 22 which represents the full range of cm11a
166         int dimsPercent = (dims * 100) / X10_DIM_INCREMENTS;
167         int newPercent = curPercent - dimsPercent;
168         newPercent = Math.max(newPercent, 0);
169         newPercent = Math.min(newPercent, 100);
170         currentState = new PercentType(newPercent);
171         return currentState;
172     }
173
174     /**
175      * Add the specified number of X10 "dims" from the current state
176      *
177      * @param dims The number of dims to remove
178      * @return The updated current state
179      */
180     public State addBrightsToCurrentState(int dims) {
181         return addDimsToCurrentState(-dims);
182     }
183 }