]> git.basschouten.com Git - openhab-addons.git/blob
f4ed0b25f1782d7f5793629720c3e1c245ab556a
[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.THING_TYPE_LIB485_BRIDGE;
16
17 import java.io.IOException;
18 import java.net.Socket;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.dmx.internal.DmxBridgeHandler;
26 import org.openhab.binding.dmx.internal.config.Lib485BridgeHandlerConfiguration;
27 import org.openhab.binding.dmx.internal.dmxoverethernet.IpNode;
28 import org.openhab.binding.dmx.internal.multiverse.Universe;
29 import org.openhab.core.thing.Bridge;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * The {@link Lib485BridgeHandler} is responsible for communication with
38  * an Lib485 instance
39  *
40  * @author Jan N. Klug - Initial contribution
41  */
42 @NonNullByDefault
43 public class Lib485BridgeHandler extends DmxBridgeHandler {
44     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_LIB485_BRIDGE);
45     public static final int MIN_UNIVERSE_ID = 0;
46     public static final int MAX_UNIVERSE_ID = 0;
47     public static final int DEFAULT_PORT = 9020;
48
49     private final Logger logger = LoggerFactory.getLogger(Lib485BridgeHandler.class);
50     private final Map<IpNode, @Nullable Socket> receiverNodes = new HashMap<>();
51
52     public Lib485BridgeHandler(Bridge lib485Bridge) {
53         super(lib485Bridge);
54     }
55
56     @Override
57     protected void openConnection() {
58         if (getThing().getStatus() != ThingStatus.ONLINE) {
59             for (IpNode receiverNode : receiverNodes.keySet()) {
60                 Socket socket = receiverNodes.get(receiverNode);
61                 if (socket == null) {
62                     try {
63                         socket = new Socket(receiverNode.getAddressString(), receiverNode.getPort());
64                     } catch (IOException e) {
65                         logger.debug("Could not connect to {} in {}: {}", receiverNode, this.thing.getUID(),
66                                 e.getMessage());
67                         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
68                                 "could not connect to " + receiverNode.toString());
69                         return;
70                     }
71                 }
72
73                 if (socket.isConnected()) {
74                     receiverNodes.put(receiverNode, socket);
75                 } else {
76                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
77                     receiverNodes.put(receiverNode, null);
78                     return;
79                 }
80             }
81             updateStatus(ThingStatus.ONLINE);
82         }
83     }
84
85     @Override
86     protected void closeConnection() {
87         for (IpNode receiverNode : receiverNodes.keySet()) {
88             Socket socket = receiverNodes.get(receiverNode);
89             if ((socket != null) && (!socket.isClosed())) {
90                 try {
91                     socket.close();
92                 } catch (IOException e) {
93                     logger.warn("Could not close socket {} in {}: {}", receiverNode, this.thing.getUID(),
94                             e.getMessage());
95                 }
96             }
97             receiverNodes.put(receiverNode, null);
98         }
99     }
100
101     @Override
102     protected void sendDmxData() {
103         if (getThing().getStatus() == ThingStatus.ONLINE) {
104             long now = System.currentTimeMillis();
105             universe.calculateBuffer(now);
106             for (IpNode receiverNode : receiverNodes.keySet()) {
107                 Socket socket = receiverNodes.get(receiverNode);
108                 if (socket != null && socket.isConnected()) {
109                     try {
110                         socket.getOutputStream().write(universe.getBuffer());
111                     } catch (IOException e) {
112                         logger.debug("Could not send to {} in {}: {}", receiverNode, this.thing.getUID(),
113                                 e.getMessage());
114                         closeConnection(ThingStatusDetail.COMMUNICATION_ERROR, "could not send DMX data");
115                         return;
116                     }
117                 } else {
118                     closeConnection(ThingStatusDetail.NONE, "reconnect");
119                     return;
120                 }
121             }
122         } else {
123             openConnection();
124         }
125     }
126
127     @Override
128     protected void updateConfiguration() {
129         Lib485BridgeHandlerConfiguration configuration = getConfig().as(Lib485BridgeHandlerConfiguration.class);
130
131         universe = new Universe(MIN_UNIVERSE_ID);
132
133         receiverNodes.clear();
134         if (configuration.address.isEmpty()) {
135             receiverNodes.put(new IpNode("localhost:9020"), null);
136             logger.debug("sending to {} for {}", receiverNodes, this.thing.getUID());
137         } else {
138             try {
139                 for (IpNode receiverNode : IpNode.fromString(configuration.address, DEFAULT_PORT)) {
140                     receiverNodes.put(receiverNode, null);
141                     logger.debug("sending to {} for {}", receiverNode, this.thing.getUID());
142                 }
143             } catch (IllegalArgumentException e) {
144                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
145                 return;
146             }
147         }
148         super.updateConfiguration();
149
150         updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE);
151
152         logger.debug("updated configuration for Lib485 bridge {}", this.thing.getUID());
153     }
154
155     @Override
156     public void initialize() {
157         logger.debug("initializing Lib485 bridge {}", this.thing.getUID());
158
159         updateConfiguration();
160     }
161 }