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.revogi.internal;
15 import static org.openhab.core.library.unit.MetricPrefix.MILLI;
16 import static org.openhab.core.library.unit.Units.AMPERE;
17 import static org.openhab.core.library.unit.Units.WATT;
19 import java.util.concurrent.CompletableFuture;
20 import java.util.concurrent.ScheduledFuture;
21 import java.util.concurrent.TimeUnit;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.revogi.internal.api.StatusDTO;
26 import org.openhab.binding.revogi.internal.api.StatusService;
27 import org.openhab.binding.revogi.internal.api.SwitchService;
28 import org.openhab.binding.revogi.internal.udp.DatagramSocketWrapper;
29 import org.openhab.binding.revogi.internal.udp.UdpSenderService;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.QuantityType;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.Thing;
34 import org.openhab.core.thing.ThingStatus;
35 import org.openhab.core.thing.ThingStatusDetail;
36 import org.openhab.core.thing.binding.BaseThingHandler;
37 import org.openhab.core.types.Command;
38 import org.openhab.core.types.RefreshType;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
43 * The {@link RevogiSmartStripControlHandler} is responsible for handling commands, which are
44 * sent to one of the channels.
46 * @author Andi Bräu - Initial contribution
49 public class RevogiSmartStripControlHandler extends BaseThingHandler {
51 private final Logger logger = LoggerFactory.getLogger(RevogiSmartStripControlHandler.class);
52 private final StatusService statusService;
53 private final SwitchService switchService;
54 private @Nullable ScheduledFuture<?> pollingJob;
56 private RevogiSmartStripControlConfiguration config;
58 public RevogiSmartStripControlHandler(Thing thing) {
60 config = getConfigAs(RevogiSmartStripControlConfiguration.class);
61 UdpSenderService udpSenderService = new UdpSenderService(new DatagramSocketWrapper(), scheduler);
62 this.statusService = new StatusService(udpSenderService);
63 this.switchService = new SwitchService(udpSenderService);
67 public void handleCommand(ChannelUID channelUID, Command command) {
68 switch (channelUID.getId()) {
69 case RevogiSmartStripControlBindingConstants.PLUG_1_SWITCH:
70 switchPlug(command, 1);
72 case RevogiSmartStripControlBindingConstants.PLUG_2_SWITCH:
73 switchPlug(command, 2);
75 case RevogiSmartStripControlBindingConstants.PLUG_3_SWITCH:
76 switchPlug(command, 3);
78 case RevogiSmartStripControlBindingConstants.PLUG_4_SWITCH:
79 switchPlug(command, 4);
81 case RevogiSmartStripControlBindingConstants.PLUG_5_SWITCH:
82 switchPlug(command, 5);
84 case RevogiSmartStripControlBindingConstants.PLUG_6_SWITCH:
85 switchPlug(command, 6);
87 case RevogiSmartStripControlBindingConstants.ALL_PLUGS:
88 switchPlug(command, 0);
91 logger.debug("Something went wrong, we've got a message for {}", channelUID.getId());
95 private void switchPlug(Command command, int port) {
96 RevogiSmartStripControlConfiguration localConfig = this.config;
97 if (command instanceof OnOffType) {
98 int state = convertOnOffTypeToState(command);
99 switchService.switchPort(localConfig.serialNumber, localConfig.ipAddress, port, state);
101 if (command instanceof RefreshType) {
102 updateStripInformation();
106 private int convertOnOffTypeToState(Command command) {
107 if (command == OnOffType.ON) {
115 public void initialize() {
116 config = getConfigAs(RevogiSmartStripControlConfiguration.class);
117 updateStatus(ThingStatus.UNKNOWN);
119 pollingJob = scheduler.scheduleWithFixedDelay(this::updateStripInformation, 0, config.pollInterval,
124 public void dispose() {
126 ScheduledFuture<?> localPollingJob = this.pollingJob;
127 if (localPollingJob != null) {
128 localPollingJob.cancel(true);
129 this.pollingJob = null;
133 private void updateStripInformation() {
134 CompletableFuture<StatusDTO> futureStatus = statusService.queryStatus(config.serialNumber, config.ipAddress);
135 futureStatus.thenAccept(this::updatePlugStatus);
138 private void updatePlugStatus(StatusDTO status) {
139 if (status.isOnline()) {
140 updateStatus(ThingStatus.ONLINE);
141 handleAllPlugsInformation(status);
142 handleSinglePlugInformation(status);
144 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.GONE,
145 "Retrieved status code: " + status.getResponseCode());
149 private void handleSinglePlugInformation(StatusDTO status) {
150 for (int i = 0; i < status.getSwitchValue().size(); i++) {
151 int plugNumber = i + 1;
152 updateState("plug" + plugNumber + "#switch", OnOffType.from(status.getSwitchValue().get(i).toString()));
153 updateState("plug" + plugNumber + "#watt", new QuantityType<>(status.getWatt().get(i), MILLI(WATT)));
154 updateState("plug" + plugNumber + "#amp", new QuantityType<>(status.getAmp().get(i), MILLI(AMPERE)));
158 private void handleAllPlugsInformation(StatusDTO status) {
159 long onCount = status.getSwitchValue().stream().filter(statusValue -> statusValue == 1).count();
161 updateState(RevogiSmartStripControlBindingConstants.ALL_PLUGS, OnOffType.ON);
163 updateState(RevogiSmartStripControlBindingConstants.ALL_PLUGS, OnOffType.OFF);