2 * Copyright (c) 2010-2023 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.broadlinkthermostat.internal.handler;
15 import static org.openhab.core.library.types.OnOffType.OFF;
16 import static org.openhab.core.library.types.OnOffType.ON;
19 import java.io.IOException;
20 import java.nio.file.Files;
21 import java.nio.file.StandardOpenOption;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.broadlinkthermostat.internal.BroadlinkBindingConstants;
26 import org.openhab.binding.broadlinkthermostat.internal.BroadlinkHandlerFactory;
27 import org.openhab.core.library.types.OnOffType;
28 import org.openhab.core.thing.ChannelUID;
29 import org.openhab.core.thing.Thing;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.RefreshType;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
37 import com.github.mob41.blapi.RM2Device;
38 import com.github.mob41.blapi.mac.Mac;
39 import com.github.mob41.blapi.pkt.cmd.rm2.SendDataCmdPayload;
42 * The {@link RMUniversalRemoteHandler} is responsible for handling RM Mini Universal Remotes.
44 * @author Miguel Álvarez - Initial contribution
47 public class RMUniversalRemoteHandler extends BroadlinkBaseHandler {
48 private final Logger logger = LoggerFactory.getLogger(RMUniversalRemoteHandler.class);
49 private @Nullable RM2Device rm2Device;
52 * Creates a new instance of this class for the {@link RMUniversalRemoteHandler}.
54 * @param thing the thing that should be handled, not null
56 public RMUniversalRemoteHandler(Thing thing) {
61 * Initializes a new instance of a {@link RMUniversalRemoteHandler}.
64 public void initialize() {
66 if (!host.isBlank() && !macAddress.isBlank()) {
68 blDevice = new RM2Device(host, new Mac(macAddress));
69 this.rm2Device = (RM2Device) blDevice;
70 updateStatus(ThingStatus.ONLINE);
71 } catch (IOException e) {
72 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
73 "Could not find broadlink universal remote device at host " + host + " with MAC " + macAddress
74 + ": " + e.getMessage());
77 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Missing device configuration");
82 public void handleCommand(ChannelUID channelUID, Command command) {
83 logger.debug("Command: {}", command.toFullString());
85 if (command == RefreshType.REFRESH) {
86 logger.debug("Nothing to refresh on thing {}", thing.getUID());
90 String channelId = channelUID.getIdWithoutGroup();
93 case BroadlinkBindingConstants.LEARNING_MODE:
94 if (OnOffType.from(command.toFullString()).equals(ON)) {
95 handleLearningCommand();
98 case BroadlinkBindingConstants.SAVE_LEARNED:
99 handleSaveLearned(command);
101 case BroadlinkBindingConstants.SEND_LEARNED:
102 handleSendLearned(command);
105 logger.debug("Command {} not supported by channel {}", command.toFullString(), channelId);
107 } catch (Exception e) {
108 logger.warn("Exception while running channel {}", channelUID);
112 private void handleLearningCommand() throws IOException {
113 RM2Device rm2Device = this.rm2Device;
114 if (rm2Device != null) {
116 rm2Device.enterLearning();
117 updateState(BroadlinkBindingConstants.LEARNING_MODE, ON);
118 logger.debug("Thing {} entered learning mode", thing.getUID());
119 } catch (IOException e) {
120 updateState(BroadlinkBindingConstants.LEARNING_MODE, OFF);
124 logger.warn("Device not initialized");
128 private void handleSaveLearned(Command command) throws Exception {
129 RM2Device rm2Device = this.rm2Device;
130 if (rm2Device != null) {
131 byte @Nullable [] learned = rm2Device.checkData();
132 updateState(BroadlinkBindingConstants.LEARNING_MODE, OFF);
133 if (learned == null) {
134 logger.warn("Thing {}: nothing learned", thing.getUID());
137 var packetName = command.toFullString();
138 File destinationFile = new File(BroadlinkHandlerFactory.INFRARED_FOLDER, packetName);
139 if (destinationFile.exists()) {
140 logger.info("Key '{}' is already learned, overwriting...", packetName);
142 Files.write(destinationFile.toPath(), learned, new StandardOpenOption[] { StandardOpenOption.WRITE,
143 StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING });
147 private void handleSendLearned(Command command) throws IOException {
148 RM2Device rm2Device = this.rm2Device;
149 if (rm2Device != null) {
150 File packetFile = new File(BroadlinkHandlerFactory.INFRARED_FOLDER, command.toFullString());
151 if (!packetFile.exists()) {
152 logger.warn("{}: Nothing learned as '{}'", thing.getUID(), command.toFullString());
155 var packet = Files.readAllBytes(packetFile.toPath());
156 rm2Device.sendCmdPkt(new SendDataCmdPayload(packet));