2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.shelly.internal.api1;
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.List;
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;
26 * The {@link Shelly1CoapJSonDTO} helps the CoIoT Json into Java objects
28 * @author Markus Michels - Initial contribution
30 public class Shelly1CoapJSonDTO {
32 public static final int COIOT_VERSION_1 = 1;
33 public static final int COIOT_VERSION_2 = 2;
35 public static final int COIOT_PORT = 5683;
36 public static final String COAP_MULTICAST_ADDRESS = "224.0.1.187";
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";
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;
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";
51 public static class CoIotDescrBlk {
55 String desc; // Description
57 // Sometimes sen entries are part of the blk array - not conforming the Spec!
59 public String type; // Type
61 public String range; // Range
63 public String links; // Links
66 public static class CoIotDescrSen {
70 String desc = ""; // Description
72 public String type; // Type
74 public String range; // Range
76 public String links; // Links
78 public String unit; // Unit
81 public static class CoIotDescrP {
85 String desc; // Description
87 public String range; // Range
90 public static class CoIotDescrAct {
94 String desc; // Description
96 public String links; // Links
98 public List<CoIotDescrP> pTag; // ?
101 public static class CoIotDevDescription {
102 public List<CoIotDescrBlk> blk;
103 public List<CoIotDescrSen> sen;
104 // public List<CoIotDescrAct> act;
106 public CoIotDevDescription() {
107 blk = new ArrayList<>();
108 sen = new ArrayList<>();
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;
120 public static class CoIotGenericSensorList {
122 public List<CoIotSensor> generic;
124 public CoIotGenericSensorList() {
125 generic = new ArrayList<>();
129 protected static class CoIotDevDescrTypeAdapter extends TypeAdapter<CoIotDevDescription> {
131 public CoIotDevDescription read(final JsonReader in) throws IOException {
132 CoIotDevDescription descr = new CoIotDevDescription();
137 * { "I": 0, "D": "Relay0"},
138 * { "I": 1, "D": "Sensors"} ],
140 * { "I": 111, "T": "P", "D": "Power","R": "0/3500","L": 0},
141 * { "I": 112,"T": "S","D": "Switch","R": "0/1","L": 0}
145 String name = in.nextName();
146 if (name.equalsIgnoreCase(COIOT_TAG_BLK)) {
148 while (in.hasNext()) {
149 CoIotDescrBlk blk = new CoIotDescrBlk();
151 while (in.hasNext()) {
152 switch (in.nextName().toUpperCase()) {
154 blk.id = in.nextString();
157 blk.desc = in.nextString();
168 name = in.nextName();
171 if (name.equalsIgnoreCase(COIOT_TAG_SEN)) {
173 * parse sensor list, e.g.
175 * { "I":111,"T":"Red","R":"0/255","L":0},
176 * { "I":121,"T":"Green","R":"0/255","L":0},
180 while (in.hasNext()) {
181 CoIotDescrSen sen = new CoIotDescrSen();
183 while (in.hasNext()) {
184 String tag = in.nextName();
185 switch (tag.toUpperCase()) {
187 sen.id = in.nextString();
190 sen.desc = in.nextString();
193 sen.type = in.nextString();
196 JsonToken token = in.peek();
197 if (token == JsonToken.BEGIN_ARRAY) {
198 // must be v2: an array
201 while (in.hasNext()) {
202 String value = in.nextString();
203 sen.range += sen.range.isEmpty() ? value : ";" + value;
207 sen.range = in.nextString();
211 sen.links = String.valueOf(in.nextInt());
213 case "U": // New in CoAPv2: unit"
214 sen.unit = in.nextString();
227 name = in.nextName();
231 if (name.equalsIgnoreCase(COIOT_TAG_ACT)) {
241 public void write(final JsonWriter out, final CoIotDevDescription descr) throws IOException {
244 out.name(COIOT_TAG_BLK).beginArray();
245 for (int i = 0; i < descr.blk.size(); i++) {
246 CoIotDescrBlk blk = descr.blk.get(i);
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);
262 out.value(sen.range);
263 out.value(sen.links);
264 if (sen.unit != null) {
275 protected static class CoIotSensorTypeAdapter extends TypeAdapter<CoIotGenericSensorList> {
277 public CoIotGenericSensorList read(final JsonReader in) throws IOException {
278 CoIotGenericSensorList list = new CoIotGenericSensorList();
281 String generic = in.nextName();
282 if (generic.equals(COIOT_TAG_GENERIC)) {
284 while (in.hasNext()) {
285 CoIotSensor sensor = new CoIotSensor();
287 in.nextInt(); // alway 0
288 sensor.id = Integer.toString(in.nextInt());
289 JsonToken token = in.peek();
290 if (token == JsonToken.STRING) {
292 sensor.valueStr = in.nextString();
294 } else if (token == JsonToken.NUMBER) {
296 sensor.value = in.nextDouble();
297 sensor.valueStr = "";
298 } else if (token == JsonToken.BEGIN_ARRAY) {
299 sensor.valueArray = new ArrayList<>();
301 while (in.hasNext()) {
302 if (in.peek() == JsonToken.STRING) {
303 sensor.valueArray.add(in.nextString());
312 list.generic.add(sensor);
322 public void write(final JsonWriter out, final CoIotGenericSensorList o) throws IOException {
323 CoIotGenericSensorList sensors = o;
325 if (sensors != null) {
326 out.name(COIOT_TAG_GENERIC).beginArray();
327 for (int i = 0; i < sensors.generic.size(); i++) {
330 out.value(sensors.generic.get(i).id);
331 out.value(sensors.generic.get(i).value);