]> git.basschouten.com Git - openhab-addons.git/blob
9357915e0b778915c2f2256722b5859e6acc8adf
[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.shelly.internal.api1;
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 Shelly1CoapJSonDTO} helps the CoIoT Json into Java objects
27  *
28  * @author Markus Michels - Initial contribution
29  */
30 public class Shelly1CoapJSonDTO {
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                 if (in.hasNext()) {
227                     name = in.nextName();
228                 }
229             }
230
231             if (name.equalsIgnoreCase(COIOT_TAG_ACT)) {
232                 // skip record
233                 in.skipValue();
234             }
235
236             in.endObject();
237             return descr;
238         }
239
240         @Override
241         public void write(final JsonWriter out, final CoIotDevDescription descr) throws IOException {
242             out.beginObject();
243             if (descr != null) {
244                 out.name(COIOT_TAG_BLK).beginArray();
245                 for (int i = 0; i < descr.blk.size(); i++) {
246                     CoIotDescrBlk blk = descr.blk.get(i);
247                     out.beginArray();
248                     out.value(blk.id);
249                     out.value(blk.desc);
250                     out.endArray();
251                 }
252                 out.endArray();
253
254                 out.name(COIOT_TAG_SEN).beginArray();
255                 for (int i = 0; i < descr.sen.size(); i++) {
256                     // Create element, e.g. {“I”:66, “D”:“lux”, “T”:“L”, “R”:“0/100000”, “L”:1},
257                     CoIotDescrSen sen = descr.sen.get(i);
258                     out.beginArray();
259                     out.value(sen.id);
260                     out.value(sen.desc);
261                     out.value(sen.type);
262                     out.value(sen.range);
263                     out.value(sen.links);
264                     if (sen.unit != null) {
265                         out.value(sen.unit);
266                     }
267                     out.endArray();
268                 }
269                 out.endArray();
270             }
271             out.endObject();
272         }
273     }
274
275     protected static class CoIotSensorTypeAdapter extends TypeAdapter<CoIotGenericSensorList> {
276         @Override
277         public CoIotGenericSensorList read(final JsonReader in) throws IOException {
278             CoIotGenericSensorList list = new CoIotGenericSensorList();
279
280             in.beginObject();
281             String generic = in.nextName();
282             if (generic.equals(COIOT_TAG_GENERIC)) {
283                 in.beginArray();
284                 while (in.hasNext()) {
285                     CoIotSensor sensor = new CoIotSensor();
286                     in.beginArray();
287                     in.nextInt(); // alway 0
288                     sensor.id = Integer.toString(in.nextInt());
289                     JsonToken token = in.peek();
290                     if (token == JsonToken.STRING) {
291                         // handle as string
292                         sensor.valueStr = in.nextString();
293                         sensor.value = -1;
294                     } else if (token == JsonToken.NUMBER) {
295                         // handle as double
296                         sensor.value = in.nextDouble();
297                         sensor.valueStr = "";
298                     } else if (token == JsonToken.BEGIN_ARRAY) {
299                         sensor.valueArray = new ArrayList<>();
300                         in.beginArray();
301                         while (in.hasNext()) {
302                             if (in.peek() == JsonToken.STRING) {
303                                 sensor.valueArray.add(in.nextString());
304                             } else {
305                                 // skip
306                                 in.nextNull();
307                             }
308                         }
309                         in.endArray();
310                     }
311                     in.endArray();
312                     list.generic.add(sensor);
313                 }
314                 in.endArray();
315             }
316             in.endObject();
317
318             return list;
319         }
320
321         @Override
322         public void write(final JsonWriter out, final CoIotGenericSensorList o) throws IOException {
323             CoIotGenericSensorList sensors = o;
324             out.beginObject();
325             if (sensors != null) {
326                 out.name(COIOT_TAG_GENERIC).beginArray();
327                 for (int i = 0; i < sensors.generic.size(); i++) {
328                     out.beginArray();
329                     out.value(0);
330                     out.value(sensors.generic.get(i).id);
331                     out.value(sensors.generic.get(i).value);
332                     out.endArray();
333                 }
334                 out.endArray();
335             }
336             out.endObject();
337         }
338     }
339 }