]> git.basschouten.com Git - openhab-addons.git/blob
384496693eae3785066c1ad6867fa380559b2c7f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.konnected.internal.handler;
14
15 import static org.openhab.binding.konnected.internal.KonnectedBindingConstants.*;
16
17 import java.math.BigDecimal;
18 import java.util.Arrays;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import java.util.concurrent.TimeUnit;
22
23 import org.openhab.binding.konnected.internal.KonnectedConfiguration;
24 import org.openhab.binding.konnected.internal.KonnectedHTTPUtils;
25 import org.openhab.binding.konnected.internal.KonnectedHttpRetryExceeded;
26 import org.openhab.binding.konnected.internal.gson.KonnectedModuleGson;
27 import org.openhab.binding.konnected.internal.gson.KonnectedModulePayload;
28 import org.openhab.core.config.core.Configuration;
29 import org.openhab.core.config.core.validation.ConfigValidationException;
30 import org.openhab.core.library.types.OnOffType;
31 import org.openhab.core.library.types.QuantityType;
32 import org.openhab.core.library.unit.SIUnits;
33 import org.openhab.core.library.unit.SmartHomeUnits;
34 import org.openhab.core.thing.Channel;
35 import org.openhab.core.thing.ChannelUID;
36 import org.openhab.core.thing.Thing;
37 import org.openhab.core.thing.ThingStatus;
38 import org.openhab.core.thing.ThingStatusDetail;
39 import org.openhab.core.thing.binding.BaseThingHandler;
40 import org.openhab.core.types.Command;
41 import org.openhab.core.types.RefreshType;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import com.google.gson.Gson;
46 import com.google.gson.GsonBuilder;
47
48 /**
49  * The {@link KonnectedHandler} is responsible for handling commands, which are
50  * sent to one of the channels.
51  *
52  * @author Zachary Christiansen - Initial contribution
53  */
54 public class KonnectedHandler extends BaseThingHandler {
55     private final Logger logger = LoggerFactory.getLogger(KonnectedHandler.class);
56     private KonnectedConfiguration config;
57
58     private final String konnectedServletPath;
59     private final KonnectedHTTPUtils http = new KonnectedHTTPUtils(30);
60     private String callbackIpAddress = null;
61     private String moduleIpAddress;
62     private Gson gson = new GsonBuilder().create();
63     private int retryCount;
64
65     /**
66      * This is the constructor of the Konnected Handler.
67      *
68      * @param thing the instance of the Konnected thing
69      * @param webHookServlet the instance of the callback servlet that is running for communication with the Konnected
70      *            Module
71      * @param hostAddress the webaddress of the openHAB server instance obtained by the runtime
72      * @param port the port on which the openHAB instance is running that was obtained by the runtime.
73      */
74     public KonnectedHandler(Thing thing, String path, String hostAddress, String port) {
75         super(thing);
76
77         this.konnectedServletPath = path;
78         callbackIpAddress = hostAddress + ":" + port;
79         logger.debug("The callback ip address is: {}", callbackIpAddress);
80         retryCount = 2;
81     }
82
83     @Override
84     public void handleCommand(ChannelUID channelUID, Command command) {
85         // get the zone number in integer form
86         Channel channel = this.getThing().getChannel(channelUID.getId());
87         String channelType = channel.getChannelTypeUID().getAsString();
88         String zoneNumber = (String) channel.getConfiguration().get(CHANNEL_ZONE);
89         Integer zone = Integer.parseInt(zoneNumber);
90         logger.debug("The channelUID is: {} and the zone is : {}", channelUID.getAsString(), zone);
91         // convert the zone to the pin based on value at index of zone
92         Integer pin = Arrays.asList(PIN_TO_ZONE).get(zone);
93         // if the command is OnOfftype
94         if (command instanceof OnOffType) {
95             if (channelType.equalsIgnoreCase(CHANNEL_SWITCH)) {
96                 logger.debug("A command was sent to a sensor type so we are ignoring the command");
97             } else {
98                 int sendCommand = (OnOffType.OFF.compareTo((OnOffType) command));
99                 logger.debug("The command being sent to pin {} for channel:{}  is {}", pin, channelUID.getAsString(),
100                         sendCommand);
101                 sendActuatorCommand(Integer.toString(sendCommand), pin, channelUID);
102             }
103         } else if (command instanceof RefreshType) {
104             // check to see if handler has been initialized before attempting to get state of pin, else wait one minute
105             if (this.isInitialized()) {
106                 getSwitchState(pin, channelUID);
107             } else {
108                 scheduler.schedule(() -> {
109                     handleCommand(channelUID, command);
110                 }, 1, TimeUnit.MINUTES);
111             }
112         }
113     }
114
115     /**
116      * Process a {@link WebHookEvent} that has been received by the Servlet from a Konnected module with respect to a
117      * sensor event or status update request
118      *
119      * @param event the {@link KonnectedModuleGson} event that contains the state and pin information to be processed
120      */
121     public void handleWebHookEvent(KonnectedModuleGson event) {
122         // if we receive a command upteate the thing status to being online
123         updateStatus(ThingStatus.ONLINE);
124         // get the zone number based off of the index location of the pin value
125         String sentZone = Integer.toString(Arrays.asList(PIN_TO_ZONE).indexOf(event.getPin()));
126         // check that the zone number is in one of the channelUID definitions
127         logger.debug("Looping Through all channels on thing: {} to find a match for {}", thing.getUID().getAsString(),
128                 event.getAuthToken());
129         getThing().getChannels().forEach(channel -> {
130             ChannelUID channelId = channel.getUID();
131             String zoneNumber = (String) channel.getConfiguration().get(CHANNEL_ZONE);
132             // if the string zone that was sent equals the last digit of the channelId found process it as the
133             // channelId else do nothing
134             if (sentZone.equalsIgnoreCase(zoneNumber)) {
135                 logger.debug(
136                         "The configrued zone of channelID: {}  was a match for the zone sent by the alarm panel: {} on thing: {}",
137                         channelId, sentZone, this.getThing().getUID().getId());
138                 String channelType = channel.getChannelTypeUID().getAsString();
139                 logger.debug("The channeltypeID is: {}", channelType);
140                 // check if the itemType has been defined for the zone received
141                 // check the itemType of the Zone, if Contact, send the State if Temp send Temp, etc.
142                 if (channelType.equalsIgnoreCase(CHANNEL_SWITCH) || channelType.equalsIgnoreCase(CHANNEL_ACTUATOR)) {
143                     OnOffType onOffType = event.getState().equalsIgnoreCase(getOnState(channel)) ? OnOffType.ON
144                             : OnOffType.OFF;
145                     updateState(channelId, onOffType);
146                 } else if (channelType.equalsIgnoreCase(CHANNEL_HUMIDITY)) {
147                     // if the state is of type number then this means it is the humidity channel of the dht22
148                     updateState(channelId,
149                             new QuantityType<>(Double.parseDouble(event.getHumi()), SmartHomeUnits.PERCENT));
150                 } else if (channelType.equalsIgnoreCase(CHANNEL_TEMPERATURE)) {
151                     Configuration configuration = channel.getConfiguration();
152                     if (((Boolean) configuration.get(CHANNEL_TEMPERATURE_TYPE))) {
153                         updateState(channelId,
154                                 new QuantityType<>(Double.parseDouble(event.getTemp()), SIUnits.CELSIUS));
155                     } else {
156                         // need to check to make sure right dsb1820 address
157                         logger.debug("The address of the DSB1820 sensor received from modeule {} is: {}",
158                                 this.thing.getUID(), event.getAddr());
159                         if (event.getAddr().toString()
160                                 .equalsIgnoreCase((String) (configuration.get(CHANNEL_TEMPERATURE_DS18B20_ADDRESS)))) {
161                             updateState(channelId,
162                                     new QuantityType<>(Double.parseDouble(event.getTemp()), SIUnits.CELSIUS));
163                         } else {
164                             logger.debug("The address of {} does not match {} not updating this channel",
165                                     event.getAddr().toString(),
166                                     (configuration.get(CHANNEL_TEMPERATURE_DS18B20_ADDRESS)));
167                         }
168                     }
169                 }
170             } else {
171                 logger.trace(
172                         "The zone number sent by the alarm panel: {} was not a match the configured zone for channelId: {} for thing {}",
173                         sentZone, channelId, getThing().getThingTypeUID().toString());
174             }
175         });
176     }
177
178     private void checkConfiguration() throws ConfigValidationException {
179         logger.debug("Checking configuration on thing {}", this.getThing().getUID().getAsString());
180         Configuration testConfig = this.getConfig();
181         String testRetryCount = testConfig.get(RETRY_COUNT).toString();
182         String testRequestTimeout = testConfig.get(REQUEST_TIMEOUT).toString();
183         logger.debug("The RequestTimeout Parameter is Configured as: {}", testRequestTimeout);
184         logger.debug("The Retry Count Parameter is Configured as: {}", testRetryCount);
185         try {
186             this.retryCount = Integer.parseInt(testRetryCount);
187         } catch (NumberFormatException e) {
188             logger.debug(
189                     "Please check your configuration of the Retry Count as it is not an Integer. It is configured as: {}, will contintue to configure the binding with the default of 2",
190                     testRetryCount);
191             this.retryCount = 2;
192         }
193         try {
194             this.http.setRequestTimeout(Integer.parseInt(testRequestTimeout));
195         } catch (NumberFormatException e) {
196             logger.debug(
197                     "Please check your configuration of the Request Timeout as it is not an Integer. It is configured as: {}, will contintue to configure the binding with the default of 30",
198                     testRequestTimeout);
199         }
200
201         if ((callbackIpAddress == null)) {
202             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
203                     "Unable to obtain hostaddress from OSGI service, please configure hostaddress");
204         }
205
206         else {
207             this.config = getConfigAs(KonnectedConfiguration.class);
208         }
209     }
210
211     @Override
212     public void handleConfigurationUpdate(Map<String, Object> configurationParameters)
213             throws ConfigValidationException {
214         this.validateConfigurationParameters(configurationParameters);
215         for (Entry<String, Object> configurationParameter : configurationParameters.entrySet()) {
216             Object value = configurationParameter.getValue();
217             logger.debug("Controller Configuration update {} to {}", configurationParameter.getKey(), value);
218
219             if (value == null) {
220                 continue;
221             }
222             // this is a nonstandard implementation to to address the configuration of the konnected alarm panel (as
223             // opposed to the handler) until
224             // https://github.com/eclipse/smarthome/issues/3484 has been implemented in the framework
225             String[] cfg = configurationParameter.getKey().split("_");
226             if ("controller".equals(cfg[0])) {
227                 if (cfg[1].equals("softreset") && value instanceof Boolean && (Boolean) value) {
228                     scheduler.execute(() -> {
229                         try {
230                             http.doGet(moduleIpAddress + "/settings?restart=true", null, retryCount);
231                         } catch (KonnectedHttpRetryExceeded e) {
232                             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
233                         }
234                     });
235                     value = false;
236                 } else if (cfg[1].equals("removewifi") && value instanceof Boolean && (Boolean) value) {
237                     scheduler.execute(() -> {
238                         try {
239                             http.doGet(moduleIpAddress + "/settings?restore=true", null, retryCount);
240                         } catch (KonnectedHttpRetryExceeded e) {
241                             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
242                         }
243                     });
244                     value = false;
245                 } else if (cfg[1].equals("sendConfig") && value instanceof Boolean && (Boolean) value) {
246                     scheduler.execute(() -> {
247                         try {
248                             String response = updateKonnectedModule();
249                             logger.trace("The response from the konnected module with thingID {} was {}",
250                                     getThing().getUID().toString(), response);
251                             if (response == null) {
252                                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
253                                         "Unable to communicate with Konnected Module.");
254                             } else {
255                                 updateStatus(ThingStatus.ONLINE);
256                             }
257                         } catch (KonnectedHttpRetryExceeded e) {
258                             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
259                         }
260                     });
261                     value = false;
262                 }
263             }
264         }
265
266         super.handleConfigurationUpdate(configurationParameters);
267         try
268
269         {
270             String response = updateKonnectedModule();
271             logger.trace("The response from the konnected module with thingID {} was {}",
272                     getThing().getUID().toString(), response);
273             if (response == null) {
274                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
275                         "Unable to communicate with Konnected Module confirm settings.");
276             } else {
277                 updateStatus(ThingStatus.ONLINE);
278             }
279         } catch (KonnectedHttpRetryExceeded e) {
280             logger.trace("The number of retries was exceeeded during the HandleConfigurationUpdate(): {}",
281                     e.getMessage());
282             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
283         }
284     }
285
286     @Override
287     public void initialize() {
288         updateStatus(ThingStatus.UNKNOWN);
289         try {
290             checkConfiguration();
291         } catch (ConfigValidationException e) {
292             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
293         }
294         this.moduleIpAddress = this.getThing().getProperties().get(HOST).toString();
295         scheduler.execute(() -> {
296             try {
297                 String response = updateKonnectedModule();
298                 if (response == null) {
299                     updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
300                             "Unable to communicate with Konnected Module confirm settings or readd thing.");
301                 } else {
302                     updateStatus(ThingStatus.ONLINE);
303                 }
304             } catch (KonnectedHttpRetryExceeded e) {
305                 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
306             }
307         });
308     }
309
310     @Override
311     public void dispose() {
312         logger.debug("Running dispose()");
313         super.dispose();
314     }
315
316     /**
317      * This method constructs the payload that will be sent
318      * to the Konnected module via the put request
319      * it adds the appropriate sensors and actuators to the {@link KonnectedModulePayload}
320      * as well as the location of the callback {@link KonnectedJTTPServlet}
321      * and auth_token which can be used for validation
322      *
323      * @return a json settings payload which can be sent to the Konnected Module based on the Thing
324      */
325     private String constructSettingsPayload() {
326         String hostPath = "";
327         hostPath = callbackIpAddress + this.konnectedServletPath;
328         String authToken = getThing().getUID().getAsString();
329         logger.debug("The Auth_Token is: {}", authToken);
330         KonnectedModulePayload payload = new KonnectedModulePayload(authToken, "http://" + hostPath);
331         payload.setBlink(config.blink);
332         payload.setDiscovery(config.discovery);
333         this.getThing().getChannels().forEach(channel -> {
334             // ChannelUID channelId = channel.getUID();
335             if (isLinked(channel.getUID())) {
336                 // adds linked channels to list based on last value of Channel ID
337                 // which is set to a number
338                 // get the zone number in integer form
339                 String zoneNumber = (String) channel.getConfiguration().get(CHANNEL_ZONE);
340                 Integer zone = Integer.parseInt(zoneNumber);
341                 // convert the zone to the pin based on value at index of zone
342                 Integer pin = Arrays.asList(PIN_TO_ZONE).get(zone);
343                 // if the pin is an actuator add to actuator string
344                 // else add to sensor string
345                 // This is determined based off of the accepted item type, contact types are sensors
346                 // switch types are actuators
347                 String channelType = channel.getChannelTypeUID().getAsString();
348                 logger.debug("The channeltypeID is: {}", channelType);
349                 KonnectedModuleGson module = new KonnectedModuleGson();
350                 module.setPin(pin);
351                 if (channelType.equalsIgnoreCase(CHANNEL_SWITCH)) {
352                     payload.addSensor(module);
353                     logger.trace("Channel {} will be configured on the konnected alarm panel as a switch",
354                             channel.toString());
355                 } else if (channelType.equalsIgnoreCase(CHANNEL_ACTUATOR)) {
356                     payload.addActuators(module);
357                     logger.trace("Channel {} will be configured on the konnected alarm panel as an actuator",
358                             channel.toString());
359                 } else if (channelType.equalsIgnoreCase(CHANNEL_HUMIDITY)) {
360                     // the humidity channels do not need to be added because the supported sensor (dht22) is added under
361                     // the temp sensor
362                     logger.trace("Channel {} is a humidity channel.", channel.toString());
363                 } else if (channelType.equalsIgnoreCase(CHANNEL_TEMPERATURE)) {
364                     logger.trace("Channel {} will be configured on the konnected alarm panel as a temperature sensor",
365                             channel.toString());
366                     Configuration configuration = channel.getConfiguration();
367                     if (configuration.get(CHANNEL_TEMPERATRUE_POLL) == null) {
368                         module.setPollInterval(3);
369                     } else {
370                         module.setPollInterval(((BigDecimal) configuration.get(CHANNEL_TEMPERATRUE_POLL)).intValue());
371                     }
372                     logger.trace("The Temperature Sensor Type is: {} ",
373                             configuration.get(CHANNEL_TEMPERATURE_TYPE).toString());
374                     if ((boolean) configuration.get(CHANNEL_TEMPERATURE_TYPE)) {
375                         // add it as a dht22 module
376                         payload.addDht22(module);
377                         logger.trace(
378                                 "Channel {} will be configured on the konnected alarm panel as a DHT22 temperature sensor",
379                                 channel.toString());
380                     } else {
381                         // add to payload as a DS18B20 module if the parameter is false
382                         payload.addDs18b20(module);
383                         logger.trace(
384                                 "Channel {} will be configured on the konnected alarm panel as a DS18B20 temperature sensor",
385                                 channel.toString());
386                     }
387                 } else {
388                     logger.debug("Channel {} is of type {} which is not supported by the konnected binding",
389                             channel.toString(), channelType);
390                 }
391             } else {
392                 logger.debug("The Channel {} is not linked to an item", channel.getUID());
393             }
394         });
395         // Create Json to Send to Konnected Module
396
397         String payloadString = gson.toJson(payload);
398         logger.debug("The payload is: {}", payloadString);
399         return payloadString;
400     }
401
402     /*
403      * Prepares and sends the {@link KonnectedModulePayload} via the {@link KonnectedHttpUtils}
404      *
405      * @return response obtained from sending the settings payload to Konnected module defined by the thing
406      *
407      * @throws KonnectedHttpRetryExceeded if unable to communicate with the Konnected module defined by the Thing
408      */
409     private String updateKonnectedModule() throws KonnectedHttpRetryExceeded {
410         String payload = constructSettingsPayload();
411         String response = http.doPut(moduleIpAddress + "/settings", payload, retryCount);
412         logger.debug("The response of the put request was: {}", response);
413         return response;
414     }
415
416     /**
417      * Sends a command to the module via {@link KonnectedHTTPUtils}
418      *
419      * @param scommand the string command, either 0 or 1 to send to the actutor pin on the Konnected module
420      * @param pin the pin to send the command to on the Konnected Module
421      */
422     private void sendActuatorCommand(String scommand, Integer pin, ChannelUID channelId) {
423         try {
424             Channel channel = getThing().getChannel(channelId.getId());
425             if (!(channel == null)) {
426                 logger.debug("getasstring: {} getID: {} getGroupId: {} toString:{}", channelId.getAsString(),
427                         channelId.getId(), channelId.getGroupId(), channelId.toString());
428                 Configuration configuration = channel.getConfiguration();
429                 KonnectedModuleGson payload = new KonnectedModuleGson();
430                 payload.setState(scommand);
431                 payload.setPin(pin);
432                 // check to see if this is an On Command type, if so add the momentary, pause, times to the payload if
433                 // they exist on the configuration.
434                 if (scommand.equals(getOnState(channel))) {
435                     if (configuration.get(CHANNEL_ACTUATOR_TIMES) == null) {
436                         logger.debug(
437                                 "The times configuration was not set for channelID: {}, not adding it to the payload.",
438                                 channelId.toString());
439                     } else {
440                         payload.setTimes(configuration.get(CHANNEL_ACTUATOR_TIMES).toString());
441                         logger.debug("The times configuration was set to: {} for channelID: {}.",
442                                 configuration.get(CHANNEL_ACTUATOR_TIMES).toString(), channelId.toString());
443                     }
444                     if (configuration.get(CHANNEL_ACTUATOR_MOMENTARY) == null) {
445                         logger.debug(
446                                 "The momentary configuration was not set for channelID: {}, not adding it to the payload.",
447                                 channelId.toString());
448                     } else {
449                         payload.setMomentary(configuration.get(CHANNEL_ACTUATOR_MOMENTARY).toString());
450                         logger.debug("The momentary configuration set to: {} channelID: {}.",
451                                 configuration.get(CHANNEL_ACTUATOR_MOMENTARY).toString(), channelId.toString());
452                     }
453                     if (configuration.get(CHANNEL_ACTUATOR_PAUSE) == null) {
454                         logger.debug(
455                                 "The pause configuration was not set for channelID: {}, not adding it to the payload.",
456                                 channelId.toString());
457                     } else {
458                         payload.setPause(configuration.get(CHANNEL_ACTUATOR_PAUSE).toString());
459                         logger.debug("The pause configuration was set to: {} for channelID: {}.",
460                                 configuration.get(CHANNEL_ACTUATOR_PAUSE).toString(), channelId.toString());
461                     }
462                 }
463                 String payloadString = gson.toJson(payload);
464                 logger.debug("The command payload  is: {}", payloadString);
465                 http.doPut(moduleIpAddress + "/device", payloadString, retryCount);
466             } else {
467                 logger.debug("The channel {} returned null for channelId.getID(): {}", channelId.toString(),
468                         channelId.getId());
469             }
470         } catch (KonnectedHttpRetryExceeded e) {
471             logger.debug("Attempting to set the state of the actuator on thing {} failed: {}",
472                     this.thing.getUID().getId(), e.getMessage());
473             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
474                     "Unable to communicate with Konnected Alarm Panel confirm settings, and that module is online.");
475         }
476     }
477
478     private void getSwitchState(Integer pin, ChannelUID channelId) {
479         Channel channel = getThing().getChannel(channelId.getId());
480         if (!(channel == null)) {
481             logger.debug("getasstring: {} getID: {} getGroupId: {} toString:{}", channelId.getAsString(),
482                     channelId.getId(), channelId.getGroupId(), channelId.toString());
483             KonnectedModuleGson payload = new KonnectedModuleGson();
484             payload.setPin(pin);
485             String payloadString = gson.toJson(payload);
486             logger.debug("The command payload  is: {}", payloadString);
487             try {
488                 sendSetSwitchState(payloadString);
489             } catch (KonnectedHttpRetryExceeded e) {
490                 // try to get the state of the device one more time 30 seconds later. This way it can be confirmed if
491                 // the device was simply in a reboot loop when device state was attempted the first time
492                 scheduler.schedule(() -> {
493                     try {
494                         sendSetSwitchState(payloadString);
495                     } catch (KonnectedHttpRetryExceeded ex) {
496                         updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
497                                 "Unable to communicate with Konnected Alarm Panel confirm settings, and that module is online.");
498                         logger.debug("Attempting to get the state of the zone on thing {} failed for channel: {} : {}",
499                                 this.thing.getUID().getId(), channelId.getAsString(), ex.getMessage());
500                     }
501                 }, 2, TimeUnit.MINUTES);
502             }
503         } else {
504             logger.debug("The channel {} returned null for channelId.getID(): {}", channelId.toString(),
505                     channelId.getId());
506         }
507     }
508
509     private void sendSetSwitchState(String payloadString) throws KonnectedHttpRetryExceeded {
510         String response = http.doGet(moduleIpAddress + "/device", payloadString, retryCount);
511         KonnectedModuleGson event = gson.fromJson(response, KonnectedModuleGson.class);
512         this.handleWebHookEvent(event);
513     }
514
515     private String getOnState(Channel channel) {
516         String config = (String) channel.getConfiguration().get(CHANNEL_ONVALUE);
517         if (config == null) {
518             return "1";
519         } else {
520             return config;
521         }
522     }
523 }