]> git.basschouten.com Git - openhab-addons.git/blob
e76f0ea5310a0bd9d25ac7da75669e1beea8f9f8
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.tapocontrol.internal.api;
14
15 import static org.openhab.binding.tapocontrol.internal.helpers.TapoUtils.*;
16
17 import java.net.DatagramPacket;
18 import java.net.DatagramSocket;
19 import java.net.InetAddress;
20 import java.net.SocketTimeoutException;
21 import java.security.KeyPair;
22 import java.security.KeyPairGenerator;
23 import java.security.SecureRandom;
24 import java.security.interfaces.RSAPrivateKey;
25 import java.security.interfaces.RSAPublicKey;
26
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.openhab.binding.tapocontrol.internal.helpers.TapoCredentials;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import com.google.gson.JsonArray;
33 import com.google.gson.JsonObject;
34
35 /**
36  * Handler class for TAPO Smart Home device UDP-connections.
37  * THIS IS FOR TESTING
38  *
39  * @author Christian Wild - Initial contribution
40  */
41 @NonNullByDefault
42 public class TapoUDP {
43     private final Logger logger = LoggerFactory.getLogger(TapoUDP.class);
44     private static final Integer BROADCAST_TIMEOUT_MS = 5000;
45     private static final Integer BROADCAST_DISCOVERY_PORT = 20002; // int
46     private static final String BROADCAST_IP = "255.255.255.255";
47     private static final String DISCOVERY_MESSAGE_KEY = "rsa_key";
48     private static final String DISCOVERY_MESSAGE_START_BYTES = "0200000101e5110001cb8c577dd7deb8";
49     private static final Integer BUFFER_SIZE = 501;
50     private TapoCredentials credentials;
51
52     public TapoUDP(TapoCredentials credentials) {
53         this.credentials = credentials; // new TapoCredentials();
54     }
55
56     public JsonArray udpScan() {
57         try {
58             DatagramSocket udpSocket = new DatagramSocket();
59             udpSocket.setSoTimeout(BROADCAST_TIMEOUT_MS);
60             udpSocket.setBroadcast(true);
61
62             /* create payload for handshake */
63             String publicKey = credentials.getPublicKey();
64             publicKey = generateOwnRSAKey(); // credentials.getPublicKey();
65             JsonObject parameters = new JsonObject();
66             JsonObject messageObject = new JsonObject();
67             parameters.addProperty(DISCOVERY_MESSAGE_KEY, publicKey);
68             messageObject.add("params", parameters);
69
70             String discoveryMessage = messageObject.toString();
71
72             byte[] startByte = hexStringToByteArray(DISCOVERY_MESSAGE_START_BYTES);
73             byte[] message = discoveryMessage.getBytes("UTF-8");
74             byte[] sendData = new byte[startByte.length + message.length];
75             System.arraycopy(startByte, 0, sendData, 0, startByte.length);
76             System.arraycopy(message, 0, sendData, startByte.length, message.length);
77
78             DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length,
79                     InetAddress.getByName(BROADCAST_IP), BROADCAST_DISCOVERY_PORT);
80
81             udpSocket.send(sendPacket);
82
83             while (true) {
84                 // Wait for a response
85                 byte[] recvBuf = new byte[BUFFER_SIZE];
86                 DatagramPacket receivePacket;
87                 try {
88                     receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
89                     udpSocket.receive(receivePacket);
90                 } catch (SocketTimeoutException e) {
91                     udpSocket.close();
92                     return new JsonArray();
93                 } catch (Exception e) {
94                     udpSocket.close();
95                     return new JsonArray();
96                 }
97
98                 // Check if the message is correct
99                 String responseMessage = new String(receivePacket.getData(), "UTF-8").trim();
100
101                 if (responseMessage.length() == 0) {
102                     udpSocket.close();
103                 }
104                 String addressBC = receivePacket.getAddress().getHostAddress();
105                 gotDeviceAdress(addressBC);
106             }
107         } catch (Exception e) {
108             // handle exception
109         }
110         return new JsonArray();
111     }
112
113     private void gotDeviceAdress(String ipAddress) {
114         // handle exception
115     }
116
117     private String generateOwnRSAKey() {
118         try {
119             logger.trace("generating new keypair");
120             KeyPairGenerator instance = KeyPairGenerator.getInstance("RSA");
121             instance.initialize(1536, new SecureRandom());
122             KeyPair generateKeyPair = instance.generateKeyPair();
123
124             String publicKey = new String(java.util.Base64.getMimeEncoder()
125                     .encode(((RSAPublicKey) generateKeyPair.getPublic()).getEncoded()));
126             String privateKey = new String(java.util.Base64.getMimeEncoder()
127                     .encode(((RSAPrivateKey) generateKeyPair.getPrivate()).getEncoded()));
128             logger.trace("new privateKey: '{}'", privateKey);
129             logger.trace("new ublicKey: '{}'", publicKey);
130
131             return String.format("-----BEGIN PUBLIC KEY-----%n%s%n-----END PUBLIC KEY-----%n", publicKey);
132
133         } catch (Exception e) {
134             // couldn't generate own rsa key
135             return "";
136         }
137     }
138 }