]> git.basschouten.com Git - openhab-addons.git/blob
36f644696d9efdc0dde080d9569640d70dd48e00
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.neeo.internal;
14
15 import java.io.IOException;
16 import java.util.Objects;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.neeo.internal.models.NeeoDevice;
20 import org.openhab.binding.neeo.internal.models.NeeoDevices;
21 import org.openhab.binding.neeo.internal.models.NeeoMacro;
22 import org.openhab.binding.neeo.internal.models.NeeoRoom;
23 import org.openhab.core.library.types.OnOffType;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 /**
28  * This protocol class for a Neeo Device
29  *
30  * @author Tim Roberts - Initial contribution
31  */
32 @NonNullByDefault
33 public class NeeoDeviceProtocol {
34
35     /** The logger */
36     private final Logger logger = LoggerFactory.getLogger(NeeoDeviceProtocol.class);
37
38     /** The {@link NeeoHandlerCallback} */
39     private final NeeoHandlerCallback callback;
40
41     /** The room key */
42     private final String roomKey;
43
44     /** The device key */
45     private final String deviceKey;
46
47     /** The {@link NeeoDevice} in the room */
48     private final NeeoDevice neeoDevice;
49
50     /**
51      * Instantiates a new neeo device protocol.
52      *
53      * @param callback the non-null callback
54      * @param roomKey the non-empty room key
55      * @param deviceKey the non-empty device key
56      * @throws IOException Signals that an I/O exception has occurred.
57      */
58     public NeeoDeviceProtocol(NeeoHandlerCallback callback, String roomKey, String deviceKey) throws IOException {
59         Objects.requireNonNull(callback, "callback cannot be null");
60         NeeoUtil.requireNotEmpty(roomKey, "roomKey cannot be empty");
61         NeeoUtil.requireNotEmpty(deviceKey, "deviceKey cannot be empty");
62
63         this.roomKey = roomKey;
64         this.callback = callback;
65         this.deviceKey = deviceKey;
66
67         final NeeoBrainApi api = callback.getApi();
68         if (api == null) {
69             throw new IllegalArgumentException("NeeoBrainApi cannot be null");
70         }
71
72         final NeeoRoom neeoRoom = api.getRoom(roomKey);
73
74         final NeeoDevices devices = neeoRoom.getDevices();
75         final NeeoDevice device = devices.getDevice(deviceKey);
76         if (device == null) {
77             throw new IllegalArgumentException(
78                     "Device (" + deviceKey + ") was not found in the NEEO Brain for room (" + roomKey + ")");
79         }
80
81         neeoDevice = device;
82     }
83
84     /**
85      * Returns the callback being used
86      *
87      * @return the non-null callback
88      */
89     public NeeoHandlerCallback getCallback() {
90         return callback;
91     }
92
93     /**
94      * Refresh the macro status.
95      *
96      * @param macroKey the non-null macro key
97      */
98     public void refreshMacroStatus(String macroKey) {
99         NeeoUtil.requireNotEmpty(macroKey, "macroKey cannot be empty");
100
101         final NeeoMacro macro = neeoDevice.getMacros().getMacro(macroKey);
102         if (macro != null) {
103             callback.stateChanged(UidUtils.createChannelId(NeeoConstants.DEVICE_GROUP_MACROS_ID,
104                     NeeoConstants.DEVICE_CHANNEL_STATUS, macroKey), OnOffType.OFF);
105         }
106     }
107
108     /**
109      * Sets the macro status. If the status is true, the macro will be triggered. If false, nothing occurs
110      *
111      * @param macroKey the non-null macro key
112      * @param start whether to start (true) or stop (false) the macro
113      */
114     public void setMacroStatus(String macroKey, boolean start) {
115         NeeoUtil.requireNotEmpty(macroKey, "macroKey cannot be empty");
116
117         final NeeoBrainApi api = callback.getApi();
118         if (api == null) {
119             logger.debug("API is null [likely bridge is offline]");
120         } else {
121             try {
122                 if (start) {
123                     api.triggerMacro(roomKey, deviceKey, macroKey);
124
125                     // NEEO macros are not what we generally think of for macros
126                     // Trigger a NEEO macro is simply asking the brain to send an IR pulse
127                     // for whatever the macro is linked up to (POWER ON would send the IR
128                     // pulse for the specified device). Because of this, the execution of the
129                     // macro will never take more than 100ms to complete. Since we get no
130                     // feedback from the brain whether the macro has executed or completed
131                     // AND it's impossible to tell if any macro is executing or not (no equivalent
132                     // API to poll for), we simply refresh the status back to OFF after 500ms
133                     callback.scheduleTask(() -> {
134                         callback.stateChanged(UidUtils.createChannelId(NeeoConstants.DEVICE_GROUP_MACROS_ID,
135                                 NeeoConstants.DEVICE_CHANNEL_STATUS, macroKey), OnOffType.OFF);
136                     }, 500);
137                 }
138             } catch (IOException e) {
139                 // Some macros have issues executing on the NEEO Brain (depends on the firmware)
140                 // and IO exception will be thrown if the macro encounters an issue
141                 // (mostly it depends on the state of the brain - if it's starting up or in the process
142                 // of executing a long scenario - the macro will likely timeout or simply throw an exception)
143                 // Because of this, we simply log the error versus taking the binding offline
144                 logger.warn(
145                         "Exception occurred during execution of a macro (may need to update the brain firmware): {}",
146                         e.getMessage(), e);
147                 // callback.statusChanged(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
148             }
149         }
150     }
151 }