]> git.basschouten.com Git - openhab-addons.git/blob
1c854814b4ee6a580515e5fafc779574dd0f517f
[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.dmx.internal.handler;
14
15 import static org.openhab.binding.dmx.internal.DmxBindingConstants.*;
16
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Set;
21
22 import org.openhab.binding.dmx.internal.DmxBindingConstants.ListenerType;
23 import org.openhab.binding.dmx.internal.DmxBridgeHandler;
24 import org.openhab.binding.dmx.internal.DmxThingHandler;
25 import org.openhab.binding.dmx.internal.ValueSet;
26 import org.openhab.binding.dmx.internal.action.FadeAction;
27 import org.openhab.binding.dmx.internal.action.ResumeAction;
28 import org.openhab.binding.dmx.internal.config.ChaserThingHandlerConfiguration;
29 import org.openhab.binding.dmx.internal.multiverse.BaseDmxChannel;
30 import org.openhab.binding.dmx.internal.multiverse.DmxChannel;
31 import org.openhab.core.library.types.OnOffType;
32 import org.openhab.core.library.types.StringType;
33 import org.openhab.core.thing.Bridge;
34 import org.openhab.core.thing.ChannelUID;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingStatus;
37 import org.openhab.core.thing.ThingStatusDetail;
38 import org.openhab.core.thing.ThingTypeUID;
39 import org.openhab.core.types.Command;
40 import org.openhab.core.types.RefreshType;
41 import org.openhab.core.types.State;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * The {@link ChaserThingHandler} is responsible for handling commands, which are
47  * sent to the chaser.
48  *
49  * @author Jan N. Klug - Initial contribution
50  */
51
52 public class ChaserThingHandler extends DmxThingHandler {
53     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_CHASER);
54
55     private final Logger logger = LoggerFactory.getLogger(ChaserThingHandler.class);
56
57     private final List<DmxChannel> channels = new ArrayList<>();
58     private List<ValueSet> values = new ArrayList<>();
59
60     private boolean resumeAfter = false;
61     private OnOffType isRunning = OnOffType.OFF;
62
63     public ChaserThingHandler(Thing dimmerThing) {
64         super(dimmerThing);
65     }
66
67     @Override
68     public void handleCommand(ChannelUID channelUID, Command command) {
69         switch (channelUID.getId()) {
70             case CHANNEL_SWITCH:
71                 if (command instanceof OnOffType) {
72                     if (((OnOffType) command).equals(OnOffType.ON)) {
73                         Integer channelCounter = 0;
74                         for (DmxChannel channel : channels) {
75                             if (resumeAfter) {
76                                 channel.suspendAction();
77                             } else {
78                                 channel.clearAction();
79                             }
80                             for (ValueSet value : values) {
81                                 channel.addChannelAction(new FadeAction(value.getFadeTime(),
82                                         value.getValue(channelCounter), value.getHoldTime()));
83                             }
84                             if (resumeAfter) {
85                                 channel.addChannelAction(new ResumeAction());
86                             }
87                             channel.addListener(channelUID, this, ListenerType.ACTION);
88                             channelCounter++;
89                         }
90                     } else {
91                         for (DmxChannel channel : channels) {
92                             if (resumeAfter && channel.isSuspended()) {
93                                 channel.setChannelAction(new ResumeAction());
94                             } else {
95                                 channel.clearAction();
96                             }
97                         }
98                     }
99                 } else if (command instanceof RefreshType) {
100                     updateState(channelUID, isRunning);
101                 } else {
102                     logger.debug("command {} not supported in channel {}:switch", command.getClass(),
103                             this.thing.getUID());
104                 }
105                 break;
106             case CHANNEL_CONTROL:
107                 if (command instanceof StringType) {
108                     List<ValueSet> newValues = ValueSet.parseChaseConfig(((StringType) command).toString());
109                     if (!newValues.isEmpty()) {
110                         values = newValues;
111                         logger.debug("updated chase config in {}", this.thing.getUID());
112                     } else {
113                         logger.debug("could not update chase config in {}, malformed: {}", this.thing.getUID(),
114                                 command);
115                     }
116                 } else {
117                     logger.debug("command {} not supported in channel {}:control", command.getClass(),
118                             this.thing.getUID());
119                 }
120                 break;
121             default:
122                 logger.debug("Channel {} not supported in thing {}", channelUID.getId(), this.thing.getUID());
123         }
124     }
125
126     @Override
127     public void initialize() {
128         Bridge bridge = getBridge();
129         DmxBridgeHandler bridgeHandler;
130         if (bridge == null) {
131             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "no bridge assigned");
132             dmxHandlerStatus = ThingStatusDetail.CONFIGURATION_ERROR;
133             return;
134         } else {
135             bridgeHandler = (DmxBridgeHandler) bridge.getHandler();
136             if (bridgeHandler == null) {
137                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "no bridge handler available");
138                 dmxHandlerStatus = ThingStatusDetail.CONFIGURATION_ERROR;
139                 return;
140             }
141         }
142
143         ChaserThingHandlerConfiguration configuration = getConfig().as(ChaserThingHandlerConfiguration.class);
144
145         if (configuration.dmxid.isEmpty()) {
146             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
147                     "DMX channel configuration missing");
148             dmxHandlerStatus = ThingStatusDetail.CONFIGURATION_ERROR;
149             return;
150         }
151
152         try {
153             List<BaseDmxChannel> configChannels = BaseDmxChannel.fromString(configuration.dmxid,
154                     bridgeHandler.getUniverseId());
155             logger.trace("found {} channels in {}", configChannels.size(), this.thing.getUID());
156             for (BaseDmxChannel channel : configChannels) {
157                 channels.add(bridgeHandler.getDmxChannel(channel, this.thing));
158             }
159         } catch (IllegalArgumentException e) {
160             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
161             dmxHandlerStatus = ThingStatusDetail.CONFIGURATION_ERROR;
162             return;
163         }
164         if (!configuration.steps.isEmpty()) {
165             values = ValueSet.parseChaseConfig(configuration.steps);
166             if (!values.isEmpty()) {
167                 if (bridge.getStatus().equals(ThingStatus.ONLINE)) {
168                     updateStatus(ThingStatus.ONLINE);
169                     dmxHandlerStatus = ThingStatusDetail.NONE;
170                 } else {
171                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
172                 }
173             } else {
174                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
175                         "chaser configuration malformed");
176                 dmxHandlerStatus = ThingStatusDetail.CONFIGURATION_ERROR;
177             }
178         } else {
179             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Chase configuration missing");
180             dmxHandlerStatus = ThingStatusDetail.CONFIGURATION_ERROR;
181         }
182
183         resumeAfter = configuration.resumeafter;
184         logger.trace("set resumeAfter to {}", resumeAfter);
185     }
186
187     @Override
188     public void dispose() {
189         if (!channels.isEmpty()) {
190             Bridge bridge = getBridge();
191             if (bridge != null) {
192                 DmxBridgeHandler bridgeHandler = (DmxBridgeHandler) bridge.getHandler();
193                 if (bridgeHandler != null) {
194                     bridgeHandler.unregisterDmxChannels(this.thing);
195                     logger.debug("removing {} channels from {}", channels.size(), this.thing.getUID());
196                 }
197                 ChannelUID switchChannelUID = new ChannelUID(this.thing.getUID(), CHANNEL_SWITCH);
198                 for (DmxChannel channel : channels) {
199                     channel.removeListener(switchChannelUID);
200                 }
201             }
202             channels.clear();
203         }
204     }
205
206     @Override
207     public void updateSwitchState(ChannelUID channelUID, State state) {
208         logger.trace("received {} for {}", state, channelUID);
209         if (channelUID.getId().equals(CHANNEL_SWITCH) && (state instanceof OnOffType)) {
210             this.isRunning = (OnOffType) state;
211             updateState(channelUID, state);
212         } else {
213             logger.debug("unknown state received: {} in channel {} thing {}", state, channelUID, this.thing.getUID());
214         }
215     }
216 }