]> git.basschouten.com Git - openhab-addons.git/blob
6d69be3b402ca2b96660e0cbc716eac990fe18d2
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.verisure.internal.handler;
14
15 import static org.openhab.binding.verisure.internal.VerisureBindingConstants.*;
16
17 import java.math.BigDecimal;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.List;
21 import java.util.Set;
22
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;
40
41 /**
42  * Handler for the Smart Plug Device thing type that Verisure provides.
43  *
44  * @author Jan Gustafsson - Initial contribution
45  *
46  */
47 @NonNullByDefault
48 public class VerisureSmartPlugThingHandler extends VerisureThingHandler<VerisureSmartPlugsDTO> {
49
50     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_SMARTPLUG);
51
52     private static final int REFRESH_DELAY_SECONDS = 10;
53
54     public VerisureSmartPlugThingHandler(Thing thing) {
55         super(thing);
56     }
57
58     @Override
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);
66         } else {
67             logger.warn("Unknown command! {}", command);
68         }
69     }
70
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;
79                 String operation;
80                 boolean isOperation;
81                 if (command == OnOffType.OFF) {
82                     operation = "false";
83                     isOperation = false;
84                 } else if (command == OnOffType.ON) {
85                     operation = "true";
86                     isOperation = true;
87                 } else {
88                     logger.debug("Unknown command! {}", command);
89                     return;
90                 }
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();
95
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);
103
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!");
110                 } else {
111                     logger.warn("Failed to send command, HTTP result code {}", httpResultCode);
112                 }
113             }
114         }
115     }
116
117     @Override
118     public Class<VerisureSmartPlugsDTO> getVerisureThingClass() {
119         return VerisureSmartPlugsDTO.class;
120     }
121
122     @Override
123     public synchronized void update(VerisureSmartPlugsDTO thing) {
124         updateSmartPlugState(thing);
125         updateStatus(ThingStatus.ONLINE);
126     }
127
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);
139                         });
140                 updateInstallationChannels(smartPlugJSON);
141             }
142         } else {
143             logger.debug("SmartPlugList is empty!");
144         }
145     }
146
147     public State getValue(String channelId, Smartplug smartplug, String smartPlugStatus) {
148         switch (channelId) {
149             case CHANNEL_SMARTPLUG_STATUS:
150                 if ("ON".equals(smartPlugStatus)) {
151                     return OnOffType.ON;
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);
158                 }
159                 break;
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());
165         }
166         return UnDefType.UNDEF;
167     }
168
169     private static class SmartPlugDTO {
170
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;
177
178         public void setOperationName(String operationName) {
179             this.operationName = operationName;
180         }
181
182         public void setVariables(VariablesDTO variables) {
183             this.variables = variables;
184         }
185
186         public void setQuery(String query) {
187             this.query = query;
188         }
189     }
190
191     private static class VariablesDTO {
192
193         @SuppressWarnings("unused")
194         private @Nullable String giid;
195         @SuppressWarnings("unused")
196         private @Nullable String deviceLabel;
197         @SuppressWarnings("unused")
198         private boolean state;
199
200         public void setGiid(String giid) {
201             this.giid = giid;
202         }
203
204         public void setDeviceLabel(String deviceLabel) {
205             this.deviceLabel = deviceLabel;
206         }
207
208         public void setState(boolean state) {
209             this.state = state;
210         }
211     }
212
213     @Override
214     public void updateTriggerChannel(String event) {
215         logger.debug("SmartPlugThingHandler trigger event {}", event);
216         triggerChannel(CHANNEL_SMARTPLUG_TRIGGER_CHANNEL, event);
217     }
218 }