]> git.basschouten.com Git - openhab-addons.git/blob
1239c1869aa5f77e8500938d765da049d3d65231
[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.neato.internal.handler;
14
15 import java.io.ByteArrayInputStream;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.math.BigInteger;
19 import java.nio.charset.StandardCharsets;
20 import java.security.SecureRandom;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Properties;
24
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.openhab.binding.neato.internal.classes.BeehiveAuthentication;
27 import org.openhab.binding.neato.internal.classes.NeatoAccountInformation;
28 import org.openhab.binding.neato.internal.classes.Robot;
29 import org.openhab.binding.neato.internal.config.NeatoAccountConfig;
30 import org.openhab.core.io.net.http.HttpUtil;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.ChannelUID;
33 import org.openhab.core.thing.ThingStatus;
34 import org.openhab.core.thing.ThingStatusDetail;
35 import org.openhab.core.thing.binding.BaseBridgeHandler;
36 import org.openhab.core.types.Command;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.google.gson.Gson;
41
42 /**
43  * Bridge handler to manage Neato Cloud Account
44  *
45  * @author Jeff Lauterbach - Initial Contribution
46  *
47  */
48 public class NeatoAccountHandler extends BaseBridgeHandler {
49
50     private final Logger logger = LoggerFactory.getLogger(NeatoAccountHandler.class);
51
52     public NeatoAccountHandler(Bridge bridge) {
53         super(bridge);
54     }
55
56     @Override
57     public void handleCommand(ChannelUID channelUID, Command command) {
58     }
59
60     @Override
61     public void initialize() {
62         updateStatus(ThingStatus.ONLINE);
63     }
64
65     private List<Robot> sendGetRobots(String accessToken) {
66         Properties headers = new Properties();
67         headers.setProperty("Accept", "application/vnd.neato.nucleo.v1");
68
69         headers.setProperty("Authorization", "Token token=" + accessToken);
70
71         try {
72             String resultString = HttpUtil.executeUrl("GET", "https://beehive.neatocloud.com/dashboard", headers, null,
73                     "application/json", 20000);
74
75             Gson gson = new Gson();
76             NeatoAccountInformation accountInformation = gson.fromJson(resultString, NeatoAccountInformation.class);
77
78             logger.debug("Result from WS call to get Robots: {}", resultString);
79
80             return accountInformation.getRobots();
81         } catch (IOException e) {
82             logger.debug("Error attempting to find robots registered to account", e);
83             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
84                     "Error attempting to find robots registered to account");
85             return new ArrayList<>();
86         }
87     }
88
89     public @NonNull List<Robot> getRobotsFromNeato() {
90         logger.debug("Attempting to find robots tied to account");
91         NeatoAccountConfig accountConfig = getConfigAs(NeatoAccountConfig.class);
92         String accessToken = authenticate(accountConfig.getEmail(), accountConfig.getPassword());
93
94         if (accessToken != null) {
95             return sendGetRobots(accessToken);
96         }
97
98         return new ArrayList<>();
99     }
100
101     private String authenticate(String username, String password) {
102         Gson gson = new Gson();
103
104         AuthRequest req = new AuthRequest(username, password, "ios",
105                 new BigInteger(130, new SecureRandom()).toString(64));
106
107         String authenticationResponse = "";
108         try {
109             authenticationResponse = sendAuthRequestToNeato(gson.toJson(req));
110         } catch (IOException e) {
111             logger.debug("Error when sending Authentication request to Neato.", e);
112             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
113                     "Error when sending Authentication request to Neato.");
114         }
115
116         BeehiveAuthentication authenticationObject = gson.fromJson(authenticationResponse, BeehiveAuthentication.class);
117         return authenticationObject.getAccessToken();
118     }
119
120     private String sendAuthRequestToNeato(String data) throws IOException {
121         Properties headers = new Properties();
122         headers.setProperty("Accept", "application/vnd.neato.nucleo.v1");
123
124         InputStream stream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
125         String resultString = HttpUtil.executeUrl("POST", "https://beehive.neatocloud.com/sessions", headers, stream,
126                 "application/json", 20000);
127
128         logger.debug("Authentication Response: {}", resultString);
129
130         return resultString;
131     }
132
133     private static class AuthRequest {
134         private String email;
135         private String password;
136         private String os;
137         private String token;
138
139         public AuthRequest(String email, String password, String os, String token) {
140             this.email = email;
141             this.password = password;
142             this.os = os;
143             this.token = token;
144         }
145
146         public String getEmail() {
147             return email;
148         }
149
150         public String getPassword() {
151             return password;
152         }
153
154         public String getOs() {
155             return os;
156         }
157
158         public String getToken() {
159             return token;
160         }
161     }
162 }