]> git.basschouten.com Git - openhab-addons.git/blob
1cd75b8a5cd1ddb60b37285b0fb3f133cf4cca84
[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.io.neeo.internal.serialization;
14
15 import java.lang.reflect.Type;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.List;
19 import java.util.Objects;
20 import java.util.Set;
21
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jdt.annotation.Nullable;
24 import org.openhab.core.thing.Thing;
25 import org.openhab.core.thing.ThingStatus;
26 import org.openhab.core.thing.type.ThingType;
27 import org.openhab.io.neeo.NeeoService;
28 import org.openhab.io.neeo.internal.NeeoBrainServlet;
29 import org.openhab.io.neeo.internal.NeeoConstants;
30 import org.openhab.io.neeo.internal.NeeoDeviceKeys;
31 import org.openhab.io.neeo.internal.NeeoUtil;
32 import org.openhab.io.neeo.internal.ServiceContext;
33 import org.openhab.io.neeo.internal.models.NeeoDevice;
34 import org.openhab.io.neeo.internal.models.NeeoDeviceChannel;
35 import org.openhab.io.neeo.internal.models.NeeoDeviceTiming;
36 import org.openhab.io.neeo.internal.models.NeeoDeviceType;
37 import org.openhab.io.neeo.internal.models.NeeoThingUID;
38
39 import com.google.gson.JsonArray;
40 import com.google.gson.JsonDeserializationContext;
41 import com.google.gson.JsonDeserializer;
42 import com.google.gson.JsonElement;
43 import com.google.gson.JsonObject;
44 import com.google.gson.JsonParseException;
45 import com.google.gson.JsonSerializationContext;
46 import com.google.gson.JsonSerializer;
47
48 /**
49  * Implementation of {@link JsonSerializer} and {@link JsonDeserializer} to serialize/deserial
50  * {@link NeeoDevice}. This implementation should NOT be used in communications with the NEEO brain (use
51  * {@link NeeoBrainDeviceSerializer} instead)
52  *
53  * @author Tim Roberts - Initial Contribution
54  */
55 @NonNullByDefault
56 public class NeeoDeviceSerializer implements JsonSerializer<NeeoDevice>, JsonDeserializer<NeeoDevice> {
57
58     /** The service */
59     @Nullable
60     private final NeeoService service;
61
62     /** The service context */
63     @Nullable
64     private final ServiceContext context;
65
66     /**
67      * Constructs the object with no service or context
68      */
69     public NeeoDeviceSerializer() {
70         this(null, null);
71     }
72
73     /**
74      * Constructs the object from the service and context. A null service or context will suppress certain values on the
75      * returned json object
76      *
77      * @param service the possibly null service
78      * @param context the possibly null context
79      */
80     public NeeoDeviceSerializer(@Nullable NeeoService service, @Nullable ServiceContext context) {
81         this.service = service;
82         this.context = context;
83     }
84
85     @Override
86     public @Nullable NeeoDevice deserialize(JsonElement elm, Type type, JsonDeserializationContext jsonContext)
87             throws JsonParseException {
88         if (!(elm instanceof JsonObject)) {
89             throw new JsonParseException("Element not an instance of JsonObject: " + elm);
90         }
91
92         final JsonObject jo = (JsonObject) elm;
93         final NeeoThingUID uid = jsonContext.deserialize(jo.get("uid"), NeeoThingUID.class);
94         final NeeoDeviceType devType = jsonContext.deserialize(jo.get("type"), NeeoDeviceType.class);
95         final String manufacturer = NeeoUtil.getString(jo, "manufacturer");
96         final String name = NeeoUtil.getString(jo, "name");
97         final NeeoDeviceChannel[] channels = jsonContext.deserialize(jo.get("channels"), NeeoDeviceChannel[].class);
98         final NeeoDeviceTiming timing = jo.has("timing")
99                 ? jsonContext.deserialize(jo.get("timing"), NeeoDeviceTiming.class)
100                 : null;
101
102         final String[] deviceCapabilities = jo.has("deviceCapabilities")
103                 ? jsonContext.deserialize(jo.get("deviceCapabilities"), String[].class)
104                 : null;
105
106         final String specificName = jo.has("specificName") ? jo.get("specificName").getAsString() : null;
107
108         final String iconName = jo.has("iconName") ? jo.get("iconName").getAsString() : null;
109         final int driverVersion = jo.has("driverVersion") ? jo.get("driverVersion").getAsInt() : 0;
110
111         try {
112             return new NeeoDevice(uid, driverVersion, devType,
113                     manufacturer == null || manufacturer.isEmpty() ? NeeoUtil.NOTAVAILABLE : manufacturer, name,
114                     Arrays.asList(channels), timing,
115                     deviceCapabilities == null ? null : Arrays.asList(deviceCapabilities), specificName, iconName);
116         } catch (NullPointerException | IllegalArgumentException e) {
117             throw new JsonParseException(e);
118         }
119     }
120
121     @Override
122     public JsonElement serialize(NeeoDevice device, @Nullable Type deviceType,
123             @Nullable JsonSerializationContext jsonContext) {
124         Objects.requireNonNull(device, "device cannot be null");
125         Objects.requireNonNull(deviceType, "deviceType cannot be null");
126         Objects.requireNonNull(jsonContext, "jsonContext cannot be null");
127
128         final JsonObject jsonObject = new JsonObject();
129
130         final NeeoThingUID uid = device.getUid();
131         jsonObject.add("uid", jsonContext.serialize(uid));
132         jsonObject.add("type", jsonContext.serialize(device.getType()));
133         jsonObject.addProperty("manufacturer", device.getManufacturer());
134         jsonObject.addProperty("name", device.getName());
135         jsonObject.addProperty("specificName", device.getSpecificName());
136         jsonObject.addProperty("iconName", device.getIconName());
137         jsonObject.addProperty("driverVersion", device.getDriverVersion());
138
139         final JsonArray channels = (JsonArray) jsonContext.serialize(device.getChannels());
140
141         final NeeoDeviceTiming timing = device.getDeviceTiming();
142         jsonObject.add("timing", jsonContext.serialize(timing == null ? new NeeoDeviceTiming() : timing));
143
144         jsonObject.add("deviceCapabilities", jsonContext.serialize(device.getDeviceCapabilities()));
145
146         jsonObject.addProperty("thingType", uid.getThingType());
147
148         if (NeeoConstants.NEEOIO_BINDING_ID.equalsIgnoreCase(uid.getBindingId())) {
149             jsonObject.addProperty("thingStatus", uid.getThingType().toUpperCase());
150         }
151
152         final ServiceContext localContext = context;
153         if (localContext != null) {
154             if (!NeeoConstants.NEEOIO_BINDING_ID.equalsIgnoreCase(uid.getBindingId())) {
155                 final Thing thing = localContext.getThingRegistry().get(device.getUid().asThingUID());
156                 jsonObject.addProperty("thingStatus",
157                         thing == null ? ThingStatus.UNKNOWN.name() : thing.getStatus().name());
158
159                 if (thing != null) {
160                     final ThingType thingType = localContext.getThingTypeRegistry()
161                             .getThingType(thing.getThingTypeUID());
162
163                     if (thingType != null) {
164                         for (JsonElement chnl : channels) {
165                             JsonObject jo = (JsonObject) chnl;
166                             if (jo.has("groupId") && jo.has("itemLabel")) {
167                                 final String groupId = jo.get("groupId").getAsString();
168                                 final String groupLabel = NeeoUtil.getGroupLabel(thingType, groupId);
169                                 if (groupLabel != null && !groupLabel.isEmpty()) {
170                                     final JsonElement itemLabel = jo.remove("itemLabel");
171                                     jo.addProperty("itemLabel", groupLabel + "#" + itemLabel.getAsString());
172                                 } else if (groupId != null && !groupId.isEmpty()) {
173                                     // have a groupid but no group definition found (usually error on binding)
174                                     // just default to "Others".
175                                     final JsonElement itemLabel = jo.remove("itemLabel");
176                                     jo.addProperty("itemLabel", "Others#" + itemLabel.getAsString());
177                                 }
178                             }
179                         }
180                     }
181                 }
182             }
183         }
184
185         jsonObject.add("channels", channels);
186
187         final NeeoService localService = service;
188         if (localService != null) {
189             List<String> foundKeys = new ArrayList<>();
190             for (final NeeoBrainServlet servlet : localService.getServlets()) {
191                 final NeeoDeviceKeys servletKeys = servlet.getDeviceKeys();
192                 final Set<String> keys = servletKeys.get(device.getUid());
193                 foundKeys.addAll(keys);
194             }
195             jsonObject.add("keys", jsonContext.serialize(foundKeys));
196         }
197
198         return jsonObject;
199     }
200 }