]> git.basschouten.com Git - openhab-addons.git/blob
8a86a62e4fd6790c812b243e486b0d64714f6d03
[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.mynice.internal.handler;
14
15 import static org.openhab.binding.mynice.internal.MyNiceBindingConstants.*;
16 import static org.openhab.core.thing.Thing.*;
17
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Optional;
21 import java.util.concurrent.TimeUnit;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.openhab.binding.mynice.internal.config.CourtesyConfiguration;
25 import org.openhab.binding.mynice.internal.xml.dto.CommandType;
26 import org.openhab.binding.mynice.internal.xml.dto.Device;
27 import org.openhab.binding.mynice.internal.xml.dto.Properties.DoorStatus;
28 import org.openhab.binding.mynice.internal.xml.dto.Property;
29 import org.openhab.binding.mynice.internal.xml.dto.T4Command;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.StopMoveType;
32 import org.openhab.core.library.types.StringType;
33 import org.openhab.core.thing.Bridge;
34 import org.openhab.core.thing.Channel;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.binding.BaseThingHandler;
39 import org.openhab.core.thing.binding.BridgeHandler;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.RefreshType;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  *
47  * @author GaĆ«l L'hopital - Initial contribution
48  */
49 @NonNullByDefault
50 public class GateHandler extends BaseThingHandler implements MyNiceDataListener {
51
52     private final Logger logger = LoggerFactory.getLogger(GateHandler.class);
53
54     private String id = "";
55     private Optional<DoorStatus> gateStatus = Optional.empty();
56     private List<T4Command> t4Allowed = List.of();
57
58     public GateHandler(Thing thing) {
59         super(thing);
60     }
61
62     @Override
63     public void initialize() {
64         id = (String) getConfig().get(DEVICE_ID);
65         getBridgeHandler().ifPresent(h -> h.registerDataListener(this));
66     }
67
68     @Override
69     public void dispose() {
70         id = "";
71         gateStatus = Optional.empty();
72         t4Allowed = List.of();
73         getBridgeHandler().ifPresent(h -> h.unregisterDataListener(this));
74     }
75
76     private Optional<It4WifiHandler> getBridgeHandler() {
77         Bridge bridge = getBridge();
78         if (bridge != null) {
79             BridgeHandler handler = bridge.getHandler();
80             if (handler instanceof It4WifiHandler it4Handler) {
81                 return Optional.of(it4Handler);
82             }
83         }
84         return Optional.empty();
85     }
86
87     @Override
88     public void handleCommand(ChannelUID channelUID, Command command) {
89         String channelId = channelUID.getId();
90
91         if (command instanceof RefreshType) {
92             getBridgeHandler().ifPresent(handler -> handler.sendCommand(CommandType.INFO));
93         } else if (CHANNEL_COURTESY.equals(channelId) && command instanceof OnOffType) {
94             handleT4Command(T4Command.MDEy);
95         } else if (CHANNEL_STATUS.equals(channelId)) {
96             gateStatus.ifPresentOrElse(status -> {
97                 if (command instanceof StopMoveType stopMoveCommand) {
98                     handleStopMove(status, stopMoveCommand);
99                 } else {
100                     try {
101                         handleStopMove(status, StopMoveType.valueOf(command.toString()));
102                     } catch (IllegalArgumentException e) {
103                         logger.warn("Invalid StopMoveType command received : {}", command);
104                     }
105                 }
106             }, () -> logger.info("Current status of the gate unknown, can not send {} command", command));
107         } else if (CHANNEL_COMMAND.equals(channelId)) {
108             getBridgeHandler().ifPresent(handler -> handler.sendCommand(id, command.toString()));
109         } else if (CHANNEL_T4_COMMAND.equals(channelId)) {
110             try {
111                 T4Command t4 = T4Command.fromCode(command.toString());
112                 handleT4Command(t4);
113             } catch (IllegalArgumentException e) {
114                 logger.warn("{} is not a valid T4 command", command);
115             }
116         } else {
117             logger.warn("Unable to handle command {} on channel {}", command, channelId);
118         }
119     }
120
121     private void handleStopMove(DoorStatus status, StopMoveType stopMoveCommand) {
122         if (stopMoveCommand == StopMoveType.STOP) {
123             if (status == DoorStatus.STOPPED) {
124                 logger.info("The gate is already stopped.");
125             } else {
126                 handleT4Command(T4Command.MDAy);
127             }
128             return;
129         }
130
131         // It's a move Command
132         if (status == DoorStatus.OPEN) {
133             handleT4Command(T4Command.MDA0);
134         } else if (status == DoorStatus.CLOSED) {
135             handleT4Command(T4Command.MDAz);
136         } else if (status.moving) {
137             logger.info("The gate is already currently moving.");
138         } else { // it is closed
139             handleT4Command(T4Command.MDAx);
140         }
141     }
142
143     private void handleT4Command(T4Command t4Command) {
144         if (t4Allowed.contains(t4Command)) {
145             getBridgeHandler().ifPresent(handler -> handler.sendCommand(id, t4Command));
146         } else {
147             logger.warn("This gate does not accept the T4 command '{}'", t4Command);
148         }
149     }
150
151     @Override
152     public void onDataFetched(List<Device> devices) {
153         devices.stream().filter(d -> id.equals(d.id)).findFirst().map(device -> {
154             updateStatus(ThingStatus.ONLINE);
155             Property t4list = device.properties.t4allowed;
156             if (t4Allowed.isEmpty() && t4list != null) {
157                 int value = Integer.parseInt(t4list.values, 16);
158                 t4Allowed = T4Command.fromBitmask(value).stream().toList();
159                 if (thing.getProperties().isEmpty()) {
160                     updateProperties(Map.of(PROPERTY_VENDOR, device.manuf, PROPERTY_MODEL_ID, device.prod,
161                             PROPERTY_SERIAL_NUMBER, device.serialNr, PROPERTY_HARDWARE_VERSION, device.versionHW,
162                             PROPERTY_FIRMWARE_VERSION, device.versionFW, ALLOWED_T4,
163                             String.join(",", t4Allowed.stream().map(Enum::name).toList())));
164                 }
165             }
166             if (device.prod != null) {
167                 getBridgeHandler().ifPresent(h -> h.sendCommand(CommandType.STATUS));
168             } else {
169                 DoorStatus status = device.properties.status();
170
171                 updateState(CHANNEL_STATUS, new StringType(status.name()));
172                 updateState(CHANNEL_OBSTRUCTED, OnOffType.from(device.properties.obstructed()));
173                 updateState(CHANNEL_MOVING, OnOffType.from(status.moving));
174                 if (status.moving && isLinked(CHANNEL_COURTESY)) {
175                     Channel courtesy = getThing().getChannel(CHANNEL_COURTESY);
176                     if (courtesy != null) {
177                         updateState(CHANNEL_COURTESY, OnOffType.ON);
178                         CourtesyConfiguration config = courtesy.getConfiguration().as(CourtesyConfiguration.class);
179                         scheduler.schedule(() -> updateState(CHANNEL_COURTESY, OnOffType.OFF), config.duration,
180                                 TimeUnit.SECONDS);
181                     }
182                 }
183                 gateStatus = Optional.of(status);
184             }
185             return true;
186         });
187     }
188 }