]> git.basschouten.com Git - openhab-addons.git/blob
d951285d0597301fc5db5fc7a833a45cf30edf2f
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 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.shelly.internal.coap;
14
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.List;
18
19 import com.google.gson.TypeAdapter;
20 import com.google.gson.annotations.SerializedName;
21 import com.google.gson.stream.JsonReader;
22 import com.google.gson.stream.JsonToken;
23 import com.google.gson.stream.JsonWriter;
24
25 /**
26  * The {@link ShellyCoapJSonDTO} helps the CoIoT Json into Java objects
27  *
28  * @author Markus Michels - Initial contribution
29  */
30 public class ShellyCoapJSonDTO {
31     // Coap
32     public static final int COIOT_VERSION_1 = 1;
33     public static final int COIOT_VERSION_2 = 2;
34
35     public static final int COIOT_PORT = 5683;
36     public static final String COAP_MULTICAST_ADDRESS = "224.0.1.187";
37
38     public static final String COLOIT_URI_BASE = "/cit/";
39     public static final String COLOIT_URI_DEVDESC = COLOIT_URI_BASE + "d";
40     public static final String COLOIT_URI_DEVSTATUS = COLOIT_URI_BASE + "s";
41
42     public static final int COIOT_OPTION_GLOBAL_DEVID = 3332;
43     public static final int COIOT_OPTION_STATUS_VALIDITY = 3412;
44     public static final int COIOT_OPTION_STATUS_SERIAL = 3420;
45
46     public static final String COIOT_TAG_BLK = "blk";
47     public static final String COIOT_TAG_SEN = "sen";
48     public static final String COIOT_TAG_ACT = "act";
49     public static final String COIOT_TAG_GENERIC = "G";
50
51     public static class CoIotDescrBlk {
52         @SerializedName("I")
53         String id; // ID
54         @SerializedName("D")
55         String desc; // Description
56
57         // Sometimes sen entries are part of the blk array - not conforming the Spec!
58         @SerializedName("T")
59         public String type; // Type
60         @SerializedName("R")
61         public String range; // Range
62         @SerializedName("L")
63         public String links; // Links
64     }
65
66     public static class CoIotDescrSen {
67         @SerializedName("I")
68         String id; // ID
69         @SerializedName("D")
70         String desc = ""; // Description
71         @SerializedName("T")
72         public String type; // Type
73         @SerializedName("R")
74         public String range; // Range
75         @SerializedName("L")
76         public String links; // Links
77         @SerializedName("U")
78         public String unit; // Unit
79     }
80
81     public static class CoIotDescrP {
82         @SerializedName("I")
83         String id; // ID
84         @SerializedName("D")
85         String desc; // Description
86         @SerializedName("R")
87         public String range; // Range
88     }
89
90     public static class CoIotDescrAct {
91         @SerializedName("I")
92         String id; // ID
93         @SerializedName("D")
94         String desc; // Description
95         @SerializedName("L")
96         public String links; // Links
97         @SerializedName("P")
98         public List<CoIotDescrP> pTag; // ?
99     }
100
101     public static class CoIotDevDescription {
102         public List<CoIotDescrBlk> blk;
103         public List<CoIotDescrSen> sen;
104         // public List<CoIotDescrAct> act;
105
106         public CoIotDevDescription() {
107             blk = new ArrayList<>();
108             sen = new ArrayList<>();
109         }
110     }
111
112     public static class CoIotSensor {
113         @SerializedName("index")
114         public String id; // id
115         public double value; // value
116         public String valueStr; // value
117         public List<Object> valueArray;
118     }
119
120     public static class CoIotGenericSensorList {
121         @SerializedName("G")
122         public List<CoIotSensor> generic;
123
124         public CoIotGenericSensorList() {
125             generic = new ArrayList<>();
126         }
127     }
128
129     protected static class CoIotDevDescrTypeAdapter extends TypeAdapter<CoIotDevDescription> {
130         @Override
131         public CoIotDevDescription read(final JsonReader in) throws IOException {
132             CoIotDevDescription descr = new CoIotDevDescription();
133
134             /*
135              * parse JSON like
136              * "blk": [
137              * { "I": 0, "D": "Relay0"},
138              * { "I": 1, "D": "Sensors"} ],
139              * "sen": [
140              * { "I": 111, "T": "P", "D": "Power","R": "0/3500","L": 0},
141              * { "I": 112,"T": "S","D": "Switch","R": "0/1","L": 0}
142              * ]
143              */
144             in.beginObject();
145             String name = in.nextName();
146             if (name.equalsIgnoreCase(COIOT_TAG_BLK)) {
147                 in.beginArray();
148                 while (in.hasNext()) {
149                     CoIotDescrBlk blk = new CoIotDescrBlk();
150                     in.beginObject();
151                     while (in.hasNext()) {
152                         switch (in.nextName().toUpperCase()) {
153                             case "I":
154                                 blk.id = in.nextString();
155                                 break;
156                             case "D":
157                                 blk.desc = in.nextString();
158                                 break;
159                             default:
160                                 // skip data
161                                 in.nextNull();
162                         }
163                     }
164                     in.endObject();
165                     descr.blk.add(blk);
166                 }
167                 in.endArray();
168                 name = in.nextName();
169             }
170
171             if (name.equalsIgnoreCase(COIOT_TAG_SEN)) {
172                 /*
173                  * parse sensor list, e.g.
174                  * "sen":[
175                  * { "I":111,"T":"Red","R":"0/255","L":0},
176                  * { "I":121,"T":"Green","R":"0/255","L":0},
177                  * ]
178                  */
179                 in.beginArray();
180                 while (in.hasNext()) {
181                     CoIotDescrSen sen = new CoIotDescrSen();
182                     in.beginObject();
183                     while (in.hasNext()) {
184                         String tag = in.nextName();
185                         switch (tag.toUpperCase()) {
186                             case "I":
187                                 sen.id = in.nextString();
188                                 break;
189                             case "D":
190                                 sen.desc = in.nextString();
191                                 break;
192                             case "T":
193                                 sen.type = in.nextString();
194                                 break;
195                             case "R":
196                                 JsonToken token = in.peek();
197                                 if (token == JsonToken.BEGIN_ARRAY) {
198                                     // must be v2: an array
199                                     in.beginArray();
200                                     sen.range = "";
201                                     while (in.hasNext()) {
202                                         String value = in.nextString();
203                                         sen.range += sen.range.isEmpty() ? value : ";" + value;
204                                     }
205                                     in.endArray();
206                                 } else {
207                                     sen.range = in.nextString();
208                                 }
209                                 break;
210                             case "L":
211                                 sen.links = String.valueOf(in.nextInt());
212                                 break;
213                             case "U": // New in CoAPv2: unit"
214                                 sen.unit = in.nextString();
215                                 break;
216                             default:
217                                 // skip data
218                                 in.nextNull();
219                         }
220                     }
221                     in.endObject();
222                     descr.sen.add(sen);
223                 }
224
225                 in.endArray();
226             }
227
228             if (name.equalsIgnoreCase(COIOT_TAG_ACT)) {
229                 // skip record
230                 in.skipValue();
231             }
232
233             in.endObject();
234             return descr;
235         }
236
237         @Override
238         public void write(final JsonWriter out, final CoIotDevDescription descr) throws IOException {
239             out.beginObject();
240             if (descr != null) {
241                 out.name(COIOT_TAG_BLK).beginArray();
242                 for (int i = 0; i < descr.blk.size(); i++) {
243                     CoIotDescrBlk blk = descr.blk.get(i);
244                     out.beginArray();
245                     out.value(blk.id);
246                     out.value(blk.desc);
247                     out.endArray();
248                 }
249                 out.endArray();
250
251                 out.name(COIOT_TAG_SEN).beginArray();
252                 for (int i = 0; i < descr.sen.size(); i++) {
253                     // Create element, e.g. {“I”:66, “D”:“lux”, “T”:“L”, “R”:“0/100000”, “L”:1},
254                     CoIotDescrSen sen = descr.sen.get(i);
255                     out.beginArray();
256                     out.value(sen.id);
257                     out.value(sen.desc);
258                     out.value(sen.type);
259                     out.value(sen.range);
260                     out.value(sen.links);
261                     if (sen.unit != null) {
262                         out.value(sen.unit);
263                     }
264                     out.endArray();
265                 }
266                 out.endArray();
267             }
268             out.endObject();
269         }
270     }
271
272     protected static class CoIotSensorTypeAdapter extends TypeAdapter<CoIotGenericSensorList> {
273         @Override
274         public CoIotGenericSensorList read(final JsonReader in) throws IOException {
275             CoIotGenericSensorList list = new CoIotGenericSensorList();
276
277             in.beginObject();
278             String generic = in.nextName();
279             if (generic.equals(COIOT_TAG_GENERIC)) {
280                 in.beginArray();
281                 while (in.hasNext()) {
282                     CoIotSensor sensor = new CoIotSensor();
283                     in.beginArray();
284                     in.nextInt(); // alway 0
285                     sensor.id = Integer.toString(in.nextInt());
286                     JsonToken token = in.peek();
287                     if (token == JsonToken.STRING) {
288                         // handle as string
289                         sensor.valueStr = in.nextString();
290                         sensor.value = -1;
291                     } else if (token == JsonToken.NUMBER) {
292                         // handle as double
293                         sensor.value = in.nextDouble();
294                         sensor.valueStr = "";
295                     } else if (token == JsonToken.BEGIN_ARRAY) {
296                         sensor.valueArray = new ArrayList<>();
297                         in.beginArray();
298                         while (in.hasNext()) {
299                             if (in.peek() == JsonToken.STRING) {
300                                 sensor.valueArray.add(in.nextString());
301                             } else {
302                                 // skip
303                                 in.nextNull();
304                             }
305                         }
306                         in.endArray();
307                     }
308                     in.endArray();
309                     list.generic.add(sensor);
310                 }
311                 in.endArray();
312             }
313             in.endObject();
314
315             return list;
316         }
317
318         @Override
319         public void write(final JsonWriter out, final CoIotGenericSensorList o) throws IOException {
320             CoIotGenericSensorList sensors = o;
321             out.beginObject();
322             if (sensors != null) {
323                 out.name(COIOT_TAG_GENERIC).beginArray();
324                 for (int i = 0; i < sensors.generic.size(); i++) {
325                     out.beginArray();
326                     out.value(0);
327                     out.value(sensors.generic.get(i).id);
328                     out.value(sensors.generic.get(i).value);
329                     out.endArray();
330                 }
331                 out.endArray();
332             }
333             out.endObject();
334         }
335     }
336 }