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.Collections;
20 import java.util.List;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.eclipse.jetty.http.HttpStatus;
26 import org.openhab.binding.verisure.internal.VerisureSession;
27 import org.openhab.binding.verisure.internal.dto.VerisureSmartPlugsDTO;
28 import org.openhab.binding.verisure.internal.dto.VerisureSmartPlugsDTO.Smartplug;
29 import org.openhab.core.library.types.OnOffType;
30 import org.openhab.core.library.types.StringType;
31 import org.openhab.core.thing.Channel;
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.ThingTypeUID;
36 import org.openhab.core.types.Command;
37 import org.openhab.core.types.RefreshType;
38 import org.openhab.core.types.State;
39 import org.openhab.core.types.UnDefType;
42 * Handler for the Smart Plug Device thing type that Verisure provides.
44 * @author Jan Gustafsson - Initial contribution
48 public class VerisureSmartPlugThingHandler extends VerisureThingHandler<VerisureSmartPlugsDTO> {
50 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_SMARTPLUG);
52 private static final int REFRESH_DELAY_SECONDS = 10;
54 public VerisureSmartPlugThingHandler(Thing thing) {
59 public void handleCommand(ChannelUID channelUID, Command command) {
60 logger.debug("handleCommand, channel: {}, command: {}", channelUID, command);
61 if (command instanceof RefreshType) {
62 super.handleCommand(channelUID, command);
63 } else if (channelUID.getId().equals(CHANNEL_SMARTPLUG_STATUS)) {
64 handleSmartPlugState(command);
65 scheduleImmediateRefresh(REFRESH_DELAY_SECONDS);
67 logger.warn("Unknown command! {}", command);
71 private void handleSmartPlugState(Command command) {
72 String deviceId = config.getDeviceId();
73 VerisureSession session = getSession();
74 if (session != null) {
75 VerisureSmartPlugsDTO smartPlug = session.getVerisureThing(deviceId, getVerisureThingClass());
76 if (smartPlug != null) {
77 BigDecimal installationId = smartPlug.getSiteId();
78 String url = START_GRAPHQL;
81 if (command == OnOffType.OFF) {
84 } else if (command == OnOffType.ON) {
88 logger.debug("Unknown command! {}", command);
91 String query = "mutation UpdateState($giid: String!, $deviceLabel: String!, $state: Boolean!) {\n SmartPlugSetState(giid: $giid, input: [{deviceLabel: $deviceLabel, state: $state}])\n}\n";
92 ArrayList<SmartPlugDTO> list = new ArrayList<>();
93 SmartPlugDTO smartPlugJSON = new SmartPlugDTO();
94 VariablesDTO variables = new VariablesDTO();
96 variables.setDeviceLabel(deviceId);
97 variables.setGiid(installationId.toString());
98 variables.setState(isOperation);
99 smartPlugJSON.setOperationName("UpdateState");
100 smartPlugJSON.setVariables(variables);
101 smartPlugJSON.setQuery(query);
102 list.add(smartPlugJSON);
104 String queryQLSmartPlugSetState = gson.toJson(list);
105 logger.debug("Trying to set SmartPlug state to {} with URL {} and data {}", operation, url,
106 queryQLSmartPlugSetState);
107 int httpResultCode = session.sendCommand(url, queryQLSmartPlugSetState, installationId);
108 if (httpResultCode == HttpStatus.OK_200) {
109 logger.debug("Smartplug state successfully changed!");
111 logger.warn("Failed to send command, HTTP result code {}", httpResultCode);
118 public Class<VerisureSmartPlugsDTO> getVerisureThingClass() {
119 return VerisureSmartPlugsDTO.class;
123 public synchronized void update(VerisureSmartPlugsDTO thing) {
124 updateSmartPlugState(thing);
125 updateStatus(ThingStatus.ONLINE);
128 private void updateSmartPlugState(VerisureSmartPlugsDTO smartPlugJSON) {
129 List<Smartplug> smartPlugList = smartPlugJSON.getData().getInstallation().getSmartplugs();
130 if (!smartPlugList.isEmpty()) {
131 Smartplug smartplug = smartPlugList.get(0);
132 String smartPlugStatus = smartplug.getCurrentState();
133 if (smartPlugStatus != null) {
134 getThing().getChannels().stream().map(Channel::getUID)
135 .filter(channelUID -> isLinked(channelUID) && !channelUID.getId().equals("timestamp"))
136 .forEach(channelUID -> {
137 State state = getValue(channelUID.getId(), smartplug, smartPlugStatus);
138 updateState(channelUID, state);
140 updateInstallationChannels(smartPlugJSON);
143 logger.debug("SmartPlugList is empty!");
147 public State getValue(String channelId, Smartplug smartplug, String smartPlugStatus) {
149 case CHANNEL_SMARTPLUG_STATUS:
150 if ("ON".equals(smartPlugStatus)) {
152 } else if ("OFF".equals(smartPlugStatus)) {
153 return OnOffType.OFF;
154 } else if ("PENDING".equals(smartPlugStatus)) {
155 // Schedule another refresh.
156 logger.debug("Issuing another immediate refresh since status is still PENDING ...");
157 this.scheduleImmediateRefresh(REFRESH_DELAY_SECONDS);
160 case CHANNEL_LOCATION:
161 String location = smartplug.getDevice().getArea();
162 return location != null ? new StringType(location) : UnDefType.NULL;
163 case CHANNEL_HAZARDOUS:
164 return OnOffType.from(smartplug.isHazardous());
166 return UnDefType.UNDEF;
169 private static class SmartPlugDTO {
171 @SuppressWarnings("unused")
172 private @Nullable String operationName;
173 @SuppressWarnings("unused")
174 private VariablesDTO variables = new VariablesDTO();
175 @SuppressWarnings("unused")
176 private @Nullable String query;
178 public void setOperationName(String operationName) {
179 this.operationName = operationName;
182 public void setVariables(VariablesDTO variables) {
183 this.variables = variables;
186 public void setQuery(String query) {
191 private static class VariablesDTO {
193 @SuppressWarnings("unused")
194 private @Nullable String giid;
195 @SuppressWarnings("unused")
196 private @Nullable String deviceLabel;
197 @SuppressWarnings("unused")
198 private boolean state;
200 public void setGiid(String giid) {
204 public void setDeviceLabel(String deviceLabel) {
205 this.deviceLabel = deviceLabel;
208 public void setState(boolean state) {
214 public void updateTriggerChannel(String event) {
215 logger.debug("SmartPlugThingHandler trigger event {}", event);
216 triggerChannel(CHANNEL_SMARTPLUG_TRIGGER_CHANNEL, event);