2 * Copyright (c) 2010-2022 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.neeo.internal;
15 import java.io.IOException;
16 import java.util.Objects;
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;
28 * This protocol class for a Neeo Device
30 * @author Tim Roberts - Initial contribution
33 public class NeeoDeviceProtocol {
36 private final Logger logger = LoggerFactory.getLogger(NeeoDeviceProtocol.class);
38 /** The {@link NeeoHandlerCallback} */
39 private final NeeoHandlerCallback callback;
42 private final String roomKey;
45 private final String deviceKey;
47 /** The {@link NeeoDevice} in the room */
48 private final NeeoDevice neeoDevice;
51 * Instantiates a new neeo device protocol.
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.
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");
63 this.roomKey = roomKey;
64 this.callback = callback;
65 this.deviceKey = deviceKey;
67 final NeeoBrainApi api = callback.getApi();
69 throw new IllegalArgumentException("NeeoBrainApi cannot be null");
72 final NeeoRoom neeoRoom = api.getRoom(roomKey);
74 final NeeoDevices devices = neeoRoom.getDevices();
75 final NeeoDevice device = devices.getDevice(deviceKey);
77 throw new IllegalArgumentException(
78 "Device (" + deviceKey + ") was not found in the NEEO Brain for room (" + roomKey + ")");
85 * Returns the callback being used
87 * @return the non-null callback
89 public NeeoHandlerCallback getCallback() {
94 * Refresh the macro status.
96 * @param macroKey the non-null macro key
98 public void refreshMacroStatus(String macroKey) {
99 NeeoUtil.requireNotEmpty(macroKey, "macroKey cannot be empty");
101 final NeeoMacro macro = neeoDevice.getMacros().getMacro(macroKey);
103 callback.stateChanged(UidUtils.createChannelId(NeeoConstants.DEVICE_GROUP_MACROS_ID,
104 NeeoConstants.DEVICE_CHANNEL_STATUS, macroKey), OnOffType.OFF);
109 * Sets the macro status. If the status is true, the macro will be triggered. If false, nothing occurs
111 * @param macroKey the non-null macro key
112 * @param start whether to start (true) or stop (false) the macro
114 public void setMacroStatus(String macroKey, boolean start) {
115 NeeoUtil.requireNotEmpty(macroKey, "macroKey cannot be empty");
117 final NeeoBrainApi api = callback.getApi();
119 logger.debug("API is null [likely bridge is offline]");
123 api.triggerMacro(roomKey, deviceKey, macroKey);
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);
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
145 "Exception occurred during execution of a macro (may need to update the brain firmware): {}",
147 // callback.statusChanged(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());