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.verisure.internal.handler;
15 import static org.openhab.binding.verisure.internal.VerisureBindingConstants.*;
17 import java.math.BigDecimal;
18 import java.util.ArrayList;
19 import java.util.List;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.eclipse.jetty.http.HttpStatus;
25 import org.openhab.binding.verisure.internal.VerisureSession;
26 import org.openhab.binding.verisure.internal.dto.VerisureSmartPlugsDTO;
27 import org.openhab.binding.verisure.internal.dto.VerisureSmartPlugsDTO.Smartplug;
28 import org.openhab.core.library.types.OnOffType;
29 import org.openhab.core.library.types.StringType;
30 import org.openhab.core.thing.Channel;
31 import org.openhab.core.thing.ChannelUID;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingTypeUID;
35 import org.openhab.core.types.Command;
36 import org.openhab.core.types.RefreshType;
37 import org.openhab.core.types.State;
38 import org.openhab.core.types.UnDefType;
41 * Handler for the Smart Plug Device thing type that Verisure provides.
43 * @author Jan Gustafsson - Initial contribution
47 public class VerisureSmartPlugThingHandler extends VerisureThingHandler<VerisureSmartPlugsDTO> {
49 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_SMARTPLUG);
51 private static final int REFRESH_DELAY_SECONDS = 10;
53 public VerisureSmartPlugThingHandler(Thing thing) {
58 public void handleCommand(ChannelUID channelUID, Command command) {
59 logger.debug("handleCommand, channel: {}, command: {}", channelUID, command);
60 if (command instanceof RefreshType) {
61 super.handleCommand(channelUID, command);
62 } else if (channelUID.getId().equals(CHANNEL_SMARTPLUG_STATUS)) {
63 handleSmartPlugState(command);
64 scheduleImmediateRefresh(REFRESH_DELAY_SECONDS);
66 logger.warn("Unknown command! {}", command);
70 private void handleSmartPlugState(Command command) {
71 String deviceId = config.getDeviceId();
72 VerisureSession session = getSession();
73 if (session != null) {
74 VerisureSmartPlugsDTO smartPlug = session.getVerisureThing(deviceId, getVerisureThingClass());
75 if (smartPlug != null) {
76 BigDecimal installationId = smartPlug.getSiteId();
77 String url = START_GRAPHQL;
80 if (command == OnOffType.OFF) {
83 } else if (command == OnOffType.ON) {
87 logger.debug("Unknown command! {}", command);
90 String query = "mutation UpdateState($giid: String!, $deviceLabel: String!, $state: Boolean!) {\n SmartPlugSetState(giid: $giid, input: [{deviceLabel: $deviceLabel, state: $state}])\n}\n";
91 ArrayList<SmartPlugDTO> list = new ArrayList<>();
92 SmartPlugDTO smartPlugJSON = new SmartPlugDTO();
93 VariablesDTO variables = new VariablesDTO();
95 variables.setDeviceLabel(deviceId);
96 variables.setGiid(installationId.toString());
97 variables.setState(isOperation);
98 smartPlugJSON.setOperationName("UpdateState");
99 smartPlugJSON.setVariables(variables);
100 smartPlugJSON.setQuery(query);
101 list.add(smartPlugJSON);
103 String queryQLSmartPlugSetState = gson.toJson(list);
104 logger.debug("Trying to set SmartPlug state to {} with URL {} and data {}", operation, url,
105 queryQLSmartPlugSetState);
106 int httpResultCode = session.sendCommand(url, queryQLSmartPlugSetState, installationId);
107 if (httpResultCode == HttpStatus.OK_200) {
108 logger.debug("Smartplug state successfully changed!");
110 logger.warn("Failed to send command, HTTP result code {}", httpResultCode);
117 public Class<VerisureSmartPlugsDTO> getVerisureThingClass() {
118 return VerisureSmartPlugsDTO.class;
122 public synchronized void update(VerisureSmartPlugsDTO thing) {
123 updateSmartPlugState(thing);
124 updateStatus(ThingStatus.ONLINE);
127 private void updateSmartPlugState(VerisureSmartPlugsDTO smartPlugJSON) {
128 List<Smartplug> smartPlugList = smartPlugJSON.getData().getInstallation().getSmartplugs();
129 if (!smartPlugList.isEmpty()) {
130 Smartplug smartplug = smartPlugList.get(0);
131 String smartPlugStatus = smartplug.getCurrentState();
132 if (smartPlugStatus != null) {
133 getThing().getChannels().stream().map(Channel::getUID)
134 .filter(channelUID -> isLinked(channelUID) && !"timestamp".equals(channelUID.getId()))
135 .forEach(channelUID -> {
136 State state = getValue(channelUID.getId(), smartplug, smartPlugStatus);
137 updateState(channelUID, state);
139 updateInstallationChannels(smartPlugJSON);
142 logger.debug("SmartPlugList is empty!");
146 public State getValue(String channelId, Smartplug smartplug, String smartPlugStatus) {
148 case CHANNEL_SMARTPLUG_STATUS:
149 if ("ON".equals(smartPlugStatus)) {
151 } else if ("OFF".equals(smartPlugStatus)) {
152 return OnOffType.OFF;
153 } else if ("PENDING".equals(smartPlugStatus)) {
154 // Schedule another refresh.
155 logger.debug("Issuing another immediate refresh since status is still PENDING ...");
156 this.scheduleImmediateRefresh(REFRESH_DELAY_SECONDS);
159 case CHANNEL_LOCATION:
160 String location = smartplug.getDevice().getArea();
161 return location != null ? new StringType(location) : UnDefType.NULL;
162 case CHANNEL_HAZARDOUS:
163 return OnOffType.from(smartplug.isHazardous());
165 return UnDefType.UNDEF;
168 private static class SmartPlugDTO {
170 @SuppressWarnings("unused")
171 private @Nullable String operationName;
172 @SuppressWarnings("unused")
173 private VariablesDTO variables = new VariablesDTO();
174 @SuppressWarnings("unused")
175 private @Nullable String query;
177 public void setOperationName(String operationName) {
178 this.operationName = operationName;
181 public void setVariables(VariablesDTO variables) {
182 this.variables = variables;
185 public void setQuery(String query) {
190 private static class VariablesDTO {
192 @SuppressWarnings("unused")
193 private @Nullable String giid;
194 @SuppressWarnings("unused")
195 private @Nullable String deviceLabel;
196 @SuppressWarnings("unused")
197 private boolean state;
199 public void setGiid(String giid) {
203 public void setDeviceLabel(String deviceLabel) {
204 this.deviceLabel = deviceLabel;
207 public void setState(boolean state) {
213 public void updateTriggerChannel(String event) {
214 logger.debug("SmartPlugThingHandler trigger event {}", event);
215 triggerChannel(CHANNEL_SMARTPLUG_TRIGGER_CHANNEL, event);