Commit 51b0d50542ff0da65c7abd722e3c0f6332c8a5ee
Committed by
GitHub
1 parent
cb945010
Lwm2m discovery (#4438)
* Lwm2m: fix bug delete zero updateAttribute * Lwm2m: front add select binding * Lwm2m: discovery only for test * Lwm2m: remove type_cast_enabled from the main branch. * Lwm2m: remove type_cast_enabled from the main branch. * Lwm2m: remove type_cast_enabled from the main branch. * Lwm2m: remove double code.
Showing
15 changed files
with
420 additions
and
208 deletions
... | ... | @@ -35,7 +35,6 @@ import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInf |
35 | 35 | import org.thingsboard.server.transport.lwm2m.secure.ReadResultSecurityStore; |
36 | 36 | import org.thingsboard.server.transport.lwm2m.server.LwM2mSessionMsgListener; |
37 | 37 | import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportContextServer; |
38 | -import org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler; | |
39 | 38 | import org.thingsboard.server.transport.lwm2m.utils.TypeServer; |
40 | 39 | |
41 | 40 | import java.io.IOException; |
... | ... | @@ -165,13 +164,13 @@ public class LwM2MBootstrapSecurityStore implements BootstrapSecurityStore { |
165 | 164 | lwM2MBootstrapConfig.bootstrapServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.bootstrapServer, profileServerBootstrap); |
166 | 165 | lwM2MBootstrapConfig.lwm2mServer = new LwM2MServerBootstrap(lwM2MBootstrapConfig.lwm2mServer, profileLwm2mServer); |
167 | 166 | String logMsg = String.format("%s: getParametersBootstrap: %s Access connect client with bootstrap server.", LOG_LW2M_INFO, store.getEndPoint()); |
168 | - context.sendParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); | |
167 | + context.sendParametersOnThingsboardTelemetry(context.getKvLogyToThingsboard(logMsg), sessionInfo); | |
169 | 168 | return lwM2MBootstrapConfig; |
170 | 169 | } else { |
171 | 170 | log.error(" [{}] Different values SecurityMode between of client and profile.", store.getEndPoint()); |
172 | 171 | log.error("{} getParametersBootstrap: [{}] Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
173 | 172 | String logMsg = String.format("%s: getParametersBootstrap: %s Different values SecurityMode between of client and profile.", LOG_LW2M_ERROR, store.getEndPoint()); |
174 | - context.sendParametersOnThingsboard(context.getTelemetryMsgObject(logMsg), LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC, sessionInfo); | |
173 | + context.sendParametersOnThingsboardTelemetry(context.getKvLogyToThingsboard(logMsg), sessionInfo); | |
175 | 174 | return null; |
176 | 175 | } |
177 | 176 | } | ... | ... |
... | ... | @@ -26,7 +26,7 @@ import org.eclipse.leshan.server.registration.RegistrationUpdate; |
26 | 26 | |
27 | 27 | import java.util.Collection; |
28 | 28 | |
29 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
29 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | |
30 | 30 | |
31 | 31 | @Slf4j |
32 | 32 | public class LwM2mServerListener { |
... | ... | @@ -92,7 +92,7 @@ public class LwM2mServerListener { |
92 | 92 | public void onResponse(Observation observation, Registration registration, ObserveResponse response) { |
93 | 93 | if (registration != null) { |
94 | 94 | try { |
95 | - service.onObservationResponse(registration, convertToIdVerFromObjectId(observation.getPath().toString(), registration), response); | |
95 | + service.onObservationResponse(registration, convertPathFromObjectIdToIdVer(observation.getPath().toString(), registration), response); | |
96 | 96 | } catch (Exception e) { |
97 | 97 | log.error("[{}] onResponse", e.toString()); |
98 | 98 | |
... | ... | @@ -107,7 +107,7 @@ public class LwM2mServerListener { |
107 | 107 | |
108 | 108 | @Override |
109 | 109 | public void newObservation(Observation observation, Registration registration) { |
110 | -// log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint()); | |
110 | + log.info("Received newObservation from [{}] endpoint [{}] ", observation.getPath(), registration.getEndpoint()); | |
111 | 111 | } |
112 | 112 | }; |
113 | 113 | ... | ... |
... | ... | @@ -30,31 +30,33 @@ package org.thingsboard.server.transport.lwm2m.server; |
30 | 30 | * limitations under the License. |
31 | 31 | */ |
32 | 32 | |
33 | -import com.google.gson.JsonElement; | |
34 | -import com.google.gson.JsonObject; | |
35 | 33 | import lombok.Getter; |
36 | 34 | import lombok.extern.slf4j.Slf4j; |
37 | 35 | import org.eclipse.leshan.core.model.DDFFileParser; |
38 | 36 | import org.eclipse.leshan.core.model.DefaultDDFFileValidator; |
39 | 37 | import org.eclipse.leshan.core.model.InvalidDDFFileException; |
40 | 38 | import org.eclipse.leshan.core.model.ObjectModel; |
39 | +import org.eclipse.leshan.core.model.ResourceModel; | |
40 | +import org.eclipse.leshan.core.node.codec.CodecException; | |
41 | 41 | import org.springframework.stereotype.Component; |
42 | 42 | import org.thingsboard.server.common.transport.TransportContext; |
43 | 43 | import org.thingsboard.server.common.transport.TransportResourceCache; |
44 | 44 | import org.thingsboard.server.common.transport.TransportService; |
45 | 45 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
46 | -import org.thingsboard.server.common.transport.adaptor.AdaptorException; | |
47 | 46 | import org.thingsboard.server.common.transport.lwm2m.LwM2MTransportConfigServer; |
47 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
48 | 48 | import org.thingsboard.server.gen.transport.TransportProtos.PostAttributeMsg; |
49 | 49 | import org.thingsboard.server.gen.transport.TransportProtos.PostTelemetryMsg; |
50 | 50 | import org.thingsboard.server.gen.transport.TransportProtos.SessionInfoProto; |
51 | -import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceCredentialsResponseMsg; | |
52 | 51 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
53 | 52 | import org.thingsboard.server.transport.lwm2m.server.adaptors.LwM2MJsonAdaptor; |
54 | 53 | |
55 | 54 | import java.io.ByteArrayInputStream; |
56 | 55 | import java.io.IOException; |
56 | +import java.util.ArrayList; | |
57 | +import java.util.List; | |
57 | 58 | |
59 | +import static org.thingsboard.server.gen.transport.TransportProtos.KeyValueType.BOOLEAN_V; | |
58 | 60 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; |
59 | 61 | |
60 | 62 | @Slf4j |
... | ... | @@ -91,7 +93,7 @@ public class LwM2mTransportContextServer extends TransportContext { |
91 | 93 | /** |
92 | 94 | * send to Thingsboard Attribute || Telemetry |
93 | 95 | * |
94 | - * @param msg - JsonObject: [{name: value}] | |
96 | + * @param msg - JsonObject: [{name: value}] | |
95 | 97 | * @return - dummy |
96 | 98 | */ |
97 | 99 | private <T> TransportServiceCallback<Void> getPubAckCallbackSendAttrTelemetry(final T msg) { |
... | ... | @@ -108,33 +110,29 @@ public class LwM2mTransportContextServer extends TransportContext { |
108 | 110 | }; |
109 | 111 | } |
110 | 112 | |
111 | - public void sendParametersOnThingsboard(JsonElement msg, String topicName, SessionInfoProto sessionInfo) { | |
112 | - try { | |
113 | - if (topicName.equals(LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC)) { | |
114 | - PostAttributeMsg postAttributeMsg = adaptor.convertToPostAttributes(msg); | |
115 | - TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postAttributeMsg); | |
116 | - transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSendAttrTelemetry(call)); | |
117 | - } else if (topicName.equals(LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC)) { | |
118 | - PostTelemetryMsg postTelemetryMsg = adaptor.convertToPostTelemetry(msg); | |
119 | - TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postTelemetryMsg); | |
120 | - transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSendAttrTelemetry(call)); | |
121 | - } | |
122 | - } catch (AdaptorException e) { | |
123 | - log.error("[{}] Failed to process publish msg [{}]", topicName, e); | |
124 | - log.info("[{}] Closing current session due to invalid publish", topicName); | |
125 | - } | |
113 | + public void sendParametersOnThingsboardAttribute(List<TransportProtos.KeyValueProto> result, SessionInfoProto sessionInfo) { | |
114 | + PostAttributeMsg.Builder request = PostAttributeMsg.newBuilder(); | |
115 | + request.addAllKv(result); | |
116 | + PostAttributeMsg postAttributeMsg = request.build(); | |
117 | + TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postAttributeMsg); | |
118 | + transportService.process(sessionInfo, postAttributeMsg, this.getPubAckCallbackSendAttrTelemetry(call)); | |
126 | 119 | } |
127 | 120 | |
128 | - public JsonObject getTelemetryMsgObject(String logMsg) { | |
129 | - JsonObject telemetries = new JsonObject(); | |
130 | - telemetries.addProperty(LOG_LW2M_TELEMETRY, logMsg); | |
131 | - return telemetries; | |
121 | + public void sendParametersOnThingsboardTelemetry(List<TransportProtos.KeyValueProto> result, SessionInfoProto sessionInfo) { | |
122 | + PostTelemetryMsg.Builder request = PostTelemetryMsg.newBuilder(); | |
123 | + TransportProtos.TsKvListProto.Builder builder = TransportProtos.TsKvListProto.newBuilder(); | |
124 | + builder.setTs(System.currentTimeMillis()); | |
125 | + builder.addAllKv(result); | |
126 | + request.addTsKvList(builder.build()); | |
127 | + PostTelemetryMsg postTelemetryMsg = request.build(); | |
128 | + TransportServiceCallback call = this.getPubAckCallbackSendAttrTelemetry(postTelemetryMsg); | |
129 | + transportService.process(sessionInfo, postTelemetryMsg, this.getPubAckCallbackSendAttrTelemetry(call)); | |
132 | 130 | } |
133 | 131 | |
134 | 132 | /** |
135 | 133 | * @return - sessionInfo after access connect client |
136 | 134 | */ |
137 | - public SessionInfoProto getValidateSessionInfo(ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { | |
135 | + public SessionInfoProto getValidateSessionInfo(TransportProtos.ValidateDeviceCredentialsResponseMsg msg, long mostSignificantBits, long leastSignificantBits) { | |
138 | 136 | return SessionInfoProto.newBuilder() |
139 | 137 | .setNodeId(this.getNodeId()) |
140 | 138 | .setSessionIdMSB(mostSignificantBits) |
... | ... | @@ -159,4 +157,90 @@ public class LwM2mTransportContextServer extends TransportContext { |
159 | 157 | return null; |
160 | 158 | } |
161 | 159 | } |
160 | + | |
161 | + /** | |
162 | + * | |
163 | + * @param logMsg - info about Logs | |
164 | + * @return- KeyValueProto for telemetry (Logs) | |
165 | + */ | |
166 | + public List <TransportProtos.KeyValueProto> getKvLogyToThingsboard(String logMsg) { | |
167 | + List <TransportProtos.KeyValueProto> result = new ArrayList<>(); | |
168 | + result.add(TransportProtos.KeyValueProto.newBuilder() | |
169 | + .setKey(LOG_LW2M_TELEMETRY) | |
170 | + .setType(TransportProtos.KeyValueType.STRING_V) | |
171 | + .setStringV(logMsg).build()); | |
172 | + return result; | |
173 | + } | |
174 | + | |
175 | + /** | |
176 | + * @return - KeyValueProto for attribute/telemetry (change value) | |
177 | + * @throws CodecException - | |
178 | + */ | |
179 | + | |
180 | + public TransportProtos.KeyValueProto getKvAttrTelemetryToThingsboard(ResourceModel.Type resourceType, String resourceName, Object value, boolean isMultiInstances) { | |
181 | + TransportProtos.KeyValueProto.Builder kvProto = TransportProtos.KeyValueProto.newBuilder().setKey(resourceName); | |
182 | + if (isMultiInstances) { | |
183 | + kvProto.setType(TransportProtos.KeyValueType.JSON_V) | |
184 | + .setJsonV((String) value); | |
185 | + } | |
186 | + else { | |
187 | + switch (resourceType) { | |
188 | + case BOOLEAN: | |
189 | + kvProto.setType(BOOLEAN_V).setBoolV((Boolean) value).build(); | |
190 | + break; | |
191 | + case STRING: | |
192 | + case TIME: | |
193 | + case OPAQUE: | |
194 | + case OBJLNK: | |
195 | + kvProto.setType(TransportProtos.KeyValueType.STRING_V).setStringV((String) value); | |
196 | + break; | |
197 | + case INTEGER: | |
198 | + kvProto.setType(TransportProtos.KeyValueType.LONG_V).setLongV((Long) value); | |
199 | + break; | |
200 | + case FLOAT: | |
201 | + kvProto.setType(TransportProtos.KeyValueType.DOUBLE_V).setDoubleV((Double) value); | |
202 | + } | |
203 | + } | |
204 | + return kvProto.build(); | |
205 | + } | |
206 | + | |
207 | + /** | |
208 | + * | |
209 | + * @param currentType - | |
210 | + * @param resourcePath - | |
211 | + * @return | |
212 | + */ | |
213 | + public ResourceModel.Type getResourceModelTypeEqualsKvProtoValueType(ResourceModel.Type currentType, String resourcePath) { | |
214 | + switch (currentType) { | |
215 | + case BOOLEAN: | |
216 | + return ResourceModel.Type.BOOLEAN; | |
217 | + case STRING: | |
218 | + case TIME: | |
219 | + case OPAQUE: | |
220 | + case OBJLNK: | |
221 | + return ResourceModel.Type.STRING; | |
222 | + case INTEGER: | |
223 | + return ResourceModel.Type.INTEGER; | |
224 | + case FLOAT: | |
225 | + return ResourceModel.Type.FLOAT; | |
226 | + default: | |
227 | + } | |
228 | + throw new CodecException("Invalid ResourceModel_Type for resource %s, got %s", resourcePath, currentType); | |
229 | + } | |
230 | + | |
231 | + public Object getValueFromKvProto (TransportProtos.KeyValueProto kv) { | |
232 | + switch (kv.getType()) { | |
233 | + case BOOLEAN_V: | |
234 | + return kv.getBoolV(); | |
235 | + case LONG_V: | |
236 | + return kv.getLongV(); | |
237 | + case DOUBLE_V: | |
238 | + return kv.getDoubleV(); | |
239 | + case STRING_V: | |
240 | + return kv.getStringV(); | |
241 | + case JSON_V: | |
242 | + return kv.getJsonV(); | |
243 | + } | |
244 | + return null; | |
245 | + } | |
162 | 246 | } | ... | ... |
... | ... | @@ -75,6 +75,8 @@ public class LwM2mTransportHandler { |
75 | 75 | public static final String KEY_NAME = "keyName"; |
76 | 76 | public static final String OBSERVE = "observe"; |
77 | 77 | public static final String ATTRIBUTE_LWM2M = "attributeLwm2m"; |
78 | + public static final String RESOURCE_VALUE = "resValue"; | |
79 | + public static final String RESOURCE_TYPE = "resType"; | |
78 | 80 | |
79 | 81 | private static final String REQUEST = "/request"; |
80 | 82 | private static final String RESPONSE = "/response"; |
... | ... | @@ -333,28 +335,30 @@ public class LwM2mTransportHandler { |
333 | 335 | }; |
334 | 336 | } |
335 | 337 | |
336 | - public static String convertToObjectIdFromIdVer(String key) { | |
338 | + public static String convertPathFromIdVerToObjectId(String pathIdVer) { | |
337 | 339 | try { |
338 | - String[] keyArray = key.split(LWM2M_SEPARATOR_PATH); | |
340 | + String[] keyArray = pathIdVer.split(LWM2M_SEPARATOR_PATH); | |
339 | 341 | if (keyArray.length > 1 && keyArray[1].split(LWM2M_SEPARATOR_KEY).length == 2) { |
340 | 342 | keyArray[1] = keyArray[1].split(LWM2M_SEPARATOR_KEY)[0]; |
341 | 343 | return StringUtils.join(keyArray, LWM2M_SEPARATOR_PATH); |
342 | - } else { | |
343 | - return key; | |
344 | + } | |
345 | + else { | |
346 | + return pathIdVer; | |
344 | 347 | } |
345 | 348 | } catch (Exception e) { |
346 | 349 | return null; |
347 | 350 | } |
348 | 351 | } |
349 | 352 | |
350 | - public static String convertToIdVerFromObjectId(String path, Registration registration) { | |
353 | + public static String convertPathFromObjectIdToIdVer(String path, Registration registration) { | |
351 | 354 | String ver = registration.getSupportedObject().get(new LwM2mPath(path).getObjectId()); |
352 | 355 | try { |
353 | 356 | String[] keyArray = path.split(LWM2M_SEPARATOR_PATH); |
354 | 357 | if (keyArray.length > 1) { |
355 | 358 | keyArray[1] = keyArray[1] + LWM2M_SEPARATOR_KEY + ver; |
356 | 359 | return StringUtils.join(keyArray, LWM2M_SEPARATOR_PATH); |
357 | - } else { | |
360 | + } | |
361 | + else { | |
358 | 362 | return path; |
359 | 363 | } |
360 | 364 | } catch (Exception e) { | ... | ... |
... | ... | @@ -69,8 +69,8 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandle |
69 | 69 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES; |
70 | 70 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_UPDATE; |
71 | 71 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.RESPONSE_CHANNEL; |
72 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
73 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer; | |
72 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromIdVerToObjectId; | |
73 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | |
74 | 74 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.createWriteAttributeRequest; |
75 | 75 | |
76 | 76 | @Slf4j |
... | ... | @@ -114,7 +114,7 @@ public class LwM2mTransportRequest { |
114 | 114 | */ |
115 | 115 | public void sendAllRequest(Registration registration, String targetIdVer, String typeOper, |
116 | 116 | String contentFormatParam, Observation observation, Object params, long timeoutInMs) { |
117 | - String target = convertToObjectIdFromIdVer(targetIdVer); | |
117 | + String target = convertPathFromIdVerToObjectId(targetIdVer); | |
118 | 118 | LwM2mPath resultIds = new LwM2mPath(target); |
119 | 119 | if (registration != null && resultIds.getObjectId() >= 0) { |
120 | 120 | DownlinkRequest request = null; |
... | ... | @@ -204,7 +204,7 @@ public class LwM2mTransportRequest { |
204 | 204 | private void sendRequest(Registration registration, LwM2mClient lwM2MClient, DownlinkRequest request, long timeoutInMs) { |
205 | 205 | leshanServer.send(registration, request, timeoutInMs, (ResponseCallback<?>) response -> { |
206 | 206 | if (!lwM2MClient.isInit()) { |
207 | - lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration)); | |
207 | + lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | |
208 | 208 | } |
209 | 209 | if (CoAP.ResponseCode.isSuccess(((Response) response.getCoapResponse()).getCode())) { |
210 | 210 | this.handleResponse(registration, request.getPath().toString(), response, request); |
... | ... | @@ -228,7 +228,7 @@ public class LwM2mTransportRequest { |
228 | 228 | } |
229 | 229 | }, e -> { |
230 | 230 | if (!lwM2MClient.isInit()) { |
231 | - lwM2MClient.initValue(this.serviceImpl, convertToIdVerFromObjectId(request.getPath().toString(), registration)); | |
231 | + lwM2MClient.initValue(this.serviceImpl, convertPathFromObjectIdToIdVer(request.getPath().toString(), registration)); | |
232 | 232 | } |
233 | 233 | String msg = String.format("%s: sendRequest: Resource path - %s msg error - %s SendRequest to Client", |
234 | 234 | LOG_LW2M_ERROR, request.getPath().toString(), e.toString()); |
... | ... | @@ -287,7 +287,7 @@ public class LwM2mTransportRequest { |
287 | 287 | * @param response - |
288 | 288 | */ |
289 | 289 | private void sendResponse(Registration registration, String path, LwM2mResponse response, DownlinkRequest request) { |
290 | - String pathIdVer = convertToIdVerFromObjectId(path, registration); | |
290 | + String pathIdVer = convertPathFromObjectIdToIdVer(path, registration); | |
291 | 291 | if (response instanceof ReadResponse) { |
292 | 292 | serviceImpl.onObservationResponse(registration, pathIdVer, (ReadResponse) response); |
293 | 293 | } else if (response instanceof CancelObservationResponse) { | ... | ... |
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.transport.lwm2m.server; |
18 | 18 | import com.fasterxml.jackson.core.type.TypeReference; |
19 | 19 | import com.google.common.collect.Sets; |
20 | 20 | import com.google.gson.Gson; |
21 | +import com.google.gson.GsonBuilder; | |
21 | 22 | import com.google.gson.JsonArray; |
22 | 23 | import com.google.gson.JsonElement; |
23 | 24 | import com.google.gson.JsonObject; |
... | ... | @@ -42,7 +43,6 @@ import org.thingsboard.server.common.data.Device; |
42 | 43 | import org.thingsboard.server.common.data.DeviceProfile; |
43 | 44 | import org.thingsboard.server.common.transport.TransportService; |
44 | 45 | import org.thingsboard.server.common.transport.adaptor.AdaptorException; |
45 | -import org.thingsboard.server.common.transport.adaptor.JsonConverter; | |
46 | 46 | import org.thingsboard.server.common.transport.service.DefaultTransportService; |
47 | 47 | import org.thingsboard.server.gen.transport.TransportProtos; |
48 | 48 | import org.thingsboard.server.gen.transport.TransportProtos.AttributeUpdateNotificationMsg; |
... | ... | @@ -52,12 +52,12 @@ import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
52 | 52 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
53 | 53 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientContext; |
54 | 54 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClientProfile; |
55 | +import org.thingsboard.server.transport.lwm2m.server.client.ResultsAddKeyValueProto; | |
55 | 56 | import org.thingsboard.server.transport.lwm2m.server.client.ResultsAnalyzerParameters; |
56 | 57 | import org.thingsboard.server.transport.lwm2m.utils.LwM2mValueConverterImpl; |
57 | 58 | |
58 | 59 | import javax.annotation.PostConstruct; |
59 | 60 | import java.util.ArrayList; |
60 | -import java.util.Arrays; | |
61 | 61 | import java.util.Collection; |
62 | 62 | import java.util.HashSet; |
63 | 63 | import java.util.LinkedHashSet; |
... | ... | @@ -76,24 +76,19 @@ import java.util.stream.Collectors; |
76 | 76 | |
77 | 77 | import static org.eclipse.leshan.core.attributes.Attribute.OBJECT_VERSION; |
78 | 78 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
79 | -import static org.thingsboard.server.common.transport.util.JsonUtils.getJsonObject; | |
80 | 79 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.CLIENT_NOT_AUTHORIZED; |
81 | 80 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_REQUEST; |
82 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_ATTRIBUTES_TOPIC; | |
83 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.DEVICE_TELEMETRY_TOPIC; | |
84 | 81 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_DISCOVER; |
85 | 82 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_OBSERVE; |
86 | 83 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.GET_TYPE_OPER_READ; |
87 | 84 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_ERROR; |
88 | 85 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_INFO; |
89 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LOG_LW2M_TELEMETRY; | |
90 | 86 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.LWM2M_STRATEGY_2; |
91 | 87 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_EXECUTE; |
92 | 88 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.POST_TYPE_OPER_WRITE_REPLACE; |
93 | 89 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.PUT_TYPE_OPER_WRITE_ATTRIBUTES; |
94 | 90 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.SERVICE_CHANNEL; |
95 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
96 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer; | |
91 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromIdVerToObjectId; | |
97 | 92 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.getAckCallback; |
98 | 93 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.validateObjectVerFromKey; |
99 | 94 | |
... | ... | @@ -163,6 +158,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
163 | 158 | transportService.registerAsyncSession(sessionInfo, new LwM2mSessionMsgListener(this, sessionInfo)); |
164 | 159 | transportService.process(sessionInfo, DefaultTransportService.getSessionEventMsg(SessionEvent.OPEN), null); |
165 | 160 | transportService.process(sessionInfo, TransportProtos.SubscribeToAttributeUpdatesMsg.newBuilder().build(), null); |
161 | + transportService.process(sessionInfo, TransportProtos.SubscribeToRPCMsg.newBuilder().build(), null); | |
166 | 162 | this.initLwM2mFromClientValue(registration, lwM2MClient); |
167 | 163 | this.sendLogsToThingsboard(LOG_LW2M_INFO + ": Client create after Registration", registration); |
168 | 164 | } else { |
... | ... | @@ -309,33 +305,32 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
309 | 305 | @Override |
310 | 306 | public void onAttributeUpdate(AttributeUpdateNotificationMsg msg, TransportProtos.SessionInfoProto sessionInfo) { |
311 | 307 | if (msg.getSharedUpdatedCount() > 0) { |
312 | - JsonElement el = JsonConverter.toJson(msg); | |
313 | - el.getAsJsonObject().entrySet().forEach(de -> { | |
314 | - String pathIdVer = this.getPathAttributeUpdate(sessionInfo, de.getKey()); | |
315 | - String value = de.getValue().getAsString(); | |
308 | + msg.getSharedUpdatedList().forEach(tsKvProto -> { | |
309 | + String pathName = tsKvProto.getKv().getKey(); | |
310 | + String pathIdVer = this.validatePathIntoProfile(sessionInfo, pathName); | |
311 | + Object valueNew = this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()); | |
316 | 312 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClient(new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); |
317 | - LwM2mClientProfile clientProfile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); | |
318 | - if (pathIdVer != null && !pathIdVer.isEmpty() && (this.validatePathInAttrProfile(clientProfile, pathIdVer) || this.validatePathInTelemetryProfile(clientProfile, pathIdVer))) { | |
313 | + if (pathIdVer != null) { | |
319 | 314 | ResourceModel resourceModel = lwM2MClient.getResourceModel(pathIdVer); |
320 | 315 | if (resourceModel != null && resourceModel.operations.isWritable()) { |
321 | - lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), pathIdVer, POST_TYPE_OPER_WRITE_REPLACE, | |
322 | - ContentFormat.TLV.getName(), null, value, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout()); | |
316 | + this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), valueNew, pathIdVer); | |
323 | 317 | } else { |
324 | - log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, value); | |
318 | + log.error("Resource path - [{}] value - [{}] is not Writable and cannot be updated", pathIdVer, valueNew); | |
325 | 319 | String logMsg = String.format("%s: attributeUpdate: Resource path - %s value - %s is not Writable and cannot be updated", |
326 | - LOG_LW2M_ERROR, pathIdVer, value); | |
320 | + LOG_LW2M_ERROR, pathIdVer, valueNew); | |
327 | 321 | this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); |
328 | 322 | } |
329 | 323 | } else { |
330 | - log.error("Attribute name - [{}] value - [{}] is not present as attribute in profile and cannot be updated", de.getKey(), value); | |
324 | + log.error("Resource name name - [{}] value - [{}] is not present as attribute/telemetry in profile and cannot be updated", pathName, valueNew); | |
331 | 325 | String logMsg = String.format("%s: attributeUpdate: attribute name - %s value - %s is not present as attribute in profile and cannot be updated", |
332 | - LOG_LW2M_ERROR, de.getKey(), value); | |
326 | + LOG_LW2M_ERROR, pathName, valueNew); | |
333 | 327 | this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); |
334 | 328 | } |
335 | 329 | }); |
336 | 330 | } else if (msg.getSharedDeletedCount() > 0) { |
337 | 331 | log.info("[{}] delete [{}] onAttributeUpdate", msg.getSharedDeletedList(), sessionInfo); |
338 | 332 | } |
333 | + | |
339 | 334 | } |
340 | 335 | |
341 | 336 | /** |
... | ... | @@ -462,32 +457,13 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
462 | 457 | } |
463 | 458 | |
464 | 459 | /** |
465 | - * @param msg - text msg | |
460 | + * @param logMsg - text msg | |
466 | 461 | * @param registration - Id of Registration LwM2M Client |
467 | 462 | */ |
468 | - public void sendLogsToThingsboard(String msg, Registration registration) { | |
469 | - if (msg != null) { | |
470 | - JsonObject telemetries = new JsonObject(); | |
471 | - telemetries.addProperty(LOG_LW2M_TELEMETRY, msg); | |
472 | - this.updateParametersOnThingsboard(telemetries, DEVICE_TELEMETRY_TOPIC, registration); | |
473 | - } | |
474 | - } | |
475 | - | |
476 | - | |
477 | - /** | |
478 | - * // !!! Ok | |
479 | - * Prepare send to Thigsboard callback - Attribute or Telemetry | |
480 | - * | |
481 | - * @param msg - JsonArray: [{name: value}] | |
482 | - * @param topicName - Api Attribute or Telemetry | |
483 | - * @param registration - Id of Registration LwM2M Client | |
484 | - */ | |
485 | - public void updateParametersOnThingsboard(JsonElement msg, String topicName, Registration registration) { | |
463 | + public void sendLogsToThingsboard(String logMsg, Registration registration) { | |
486 | 464 | SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); |
487 | - if (sessionInfo != null) { | |
488 | - lwM2mTransportContextServer.sendParametersOnThingsboard(msg, topicName, sessionInfo); | |
489 | - } else { | |
490 | - log.error("Client: [{}] updateParametersOnThingsboard [{}] sessionInfo ", registration, null); | |
465 | + if (logMsg != null && sessionInfo != null) { | |
466 | + this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(this.lwM2mTransportContextServer.getKvLogyToThingsboard(logMsg), sessionInfo); | |
491 | 467 | } |
492 | 468 | } |
493 | 469 | |
... | ... | @@ -517,7 +493,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
517 | 493 | this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, GET_TYPE_OPER_READ, clientObjects); |
518 | 494 | this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, GET_TYPE_OPER_OBSERVE, clientObjects); |
519 | 495 | this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, PUT_TYPE_OPER_WRITE_ATTRIBUTES, clientObjects); |
520 | -// this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, GET_TYPE_OPER_DISCOVER, clientObjects); | |
496 | + this.initReadAttrTelemetryObserveToClient(registration, lwM2MClient, GET_TYPE_OPER_DISCOVER, clientObjects); | |
521 | 497 | } |
522 | 498 | } |
523 | 499 | |
... | ... | @@ -577,17 +553,20 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
577 | 553 | * @param registration - Registration LwM2M Client |
578 | 554 | */ |
579 | 555 | private void updateAttrTelemetry(Registration registration, Set<String> paths) { |
580 | - JsonObject attributes = new JsonObject(); | |
581 | - JsonObject telemetries = new JsonObject(); | |
582 | 556 | try { |
583 | - this.getParametersFromProfile(attributes, telemetries, registration, paths); | |
557 | + ResultsAddKeyValueProto results = getParametersFromProfile(registration, paths); | |
558 | + SessionInfoProto sessionInfo = this.getValidateSessionInfo(registration); | |
559 | + if (results != null && sessionInfo != null) { | |
560 | + if (results.getResultAttributes().size() > 0) { | |
561 | + this.lwM2mTransportContextServer.sendParametersOnThingsboardAttribute(results.getResultAttributes(), sessionInfo); | |
562 | + } | |
563 | + if (results.getResultTelemetries().size() > 0) { | |
564 | + this.lwM2mTransportContextServer.sendParametersOnThingsboardTelemetry(results.getResultTelemetries(), sessionInfo); | |
565 | + } | |
566 | + } | |
584 | 567 | } catch (Exception e) { |
585 | 568 | log.error("UpdateAttrTelemetry", e); |
586 | 569 | } |
587 | - if (attributes.getAsJsonObject().entrySet().size() > 0) | |
588 | - this.updateParametersOnThingsboard(attributes, DEVICE_ATTRIBUTES_TOPIC, registration); | |
589 | - if (telemetries.getAsJsonObject().entrySet().size() > 0) | |
590 | - this.updateParametersOnThingsboard(telemetries, DEVICE_TELEMETRY_TOPIC, registration); | |
591 | 570 | } |
592 | 571 | |
593 | 572 | /** |
... | ... | @@ -700,73 +679,99 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
700 | 679 | } |
701 | 680 | |
702 | 681 | /** |
703 | - * @param registration - | |
704 | - * @return all instances in client | |
705 | - */ | |
706 | - private Set<String> getAllInstancesInClient(Registration registration) { | |
707 | - Set<String> clientInstances = ConcurrentHashMap.newKeySet(); | |
708 | - Arrays.stream(registration.getObjectLinks()).forEach(url -> { | |
709 | - LwM2mPath pathIds = new LwM2mPath(url.getUrl()); | |
710 | - if (pathIds.isObjectInstance()) { | |
711 | - clientInstances.add(convertToIdVerFromObjectId(url.getUrl(), registration)); | |
712 | - } | |
713 | - }); | |
714 | - return (clientInstances.size() > 0) ? clientInstances : null; | |
715 | - } | |
716 | - | |
717 | - /** | |
718 | - * @param attributes - new JsonObject | |
719 | - * @param telemetry - new JsonObject | |
682 | + * // * @param attributes - new JsonObject | |
683 | + * // * @param telemetry - new JsonObject | |
684 | + * | |
720 | 685 | * @param registration - Registration LwM2M Client |
721 | 686 | * @param path - |
722 | 687 | */ |
723 | - private void getParametersFromProfile(JsonObject attributes, JsonObject telemetry, Registration registration, Set<String> path) { | |
688 | + private ResultsAddKeyValueProto getParametersFromProfile(Registration registration, Set<String> path) { | |
724 | 689 | if (path != null && path.size() > 0) { |
690 | + ResultsAddKeyValueProto results = new ResultsAddKeyValueProto(); | |
725 | 691 | LwM2mClientProfile lwM2MClientProfile = lwM2mClientContext.getProfile(registration); |
726 | - lwM2MClientProfile.getPostAttributeProfile().forEach(idVer -> { | |
727 | - if (path.contains(idVer.getAsString())) { | |
728 | - this.addParameters(idVer.getAsString(), attributes, registration); | |
692 | + List<TransportProtos.KeyValueProto> resultAttributes = new ArrayList<>(); | |
693 | + lwM2MClientProfile.getPostAttributeProfile().forEach(pathIdVer -> { | |
694 | + if (path.contains(pathIdVer.getAsString())) { | |
695 | + TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer.getAsString(), registration); | |
696 | + if (kvAttr != null) { | |
697 | + resultAttributes.add(kvAttr); | |
698 | + } | |
729 | 699 | } |
730 | 700 | }); |
731 | - lwM2MClientProfile.getPostTelemetryProfile().forEach(idVer -> { | |
732 | - if (path.contains(idVer.getAsString())) { | |
733 | - this.addParameters(idVer.getAsString(), telemetry, registration); | |
701 | + List<TransportProtos.KeyValueProto> resultTelemetries = new ArrayList<>(); | |
702 | + lwM2MClientProfile.getPostTelemetryProfile().forEach(pathIdVer -> { | |
703 | + if (path.contains(pathIdVer.getAsString())) { | |
704 | + TransportProtos.KeyValueProto kvAttr = this.getKvToThingsboard(pathIdVer.getAsString(), registration); | |
705 | + if (kvAttr != null) { | |
706 | + resultTelemetries.add(kvAttr); | |
707 | + } | |
734 | 708 | } |
735 | 709 | }); |
710 | + if (resultAttributes.size() > 0) { | |
711 | + results.setResultAttributes(resultAttributes); | |
712 | + } | |
713 | + if (resultTelemetries.size() > 0) { | |
714 | + results.setResultTelemetries(resultTelemetries); | |
715 | + } | |
716 | + return results; | |
736 | 717 | } |
718 | + return null; | |
737 | 719 | } |
738 | 720 | |
739 | - /** | |
740 | - * @param parameters - JsonObject attributes/telemetry | |
741 | - * @param registration - Registration LwM2M Client | |
742 | - */ | |
743 | - private void addParameters(String path, JsonObject parameters, Registration registration) { | |
744 | - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); | |
721 | +// public TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) { | |
722 | +// ResultsResourceValue resultsResourceValue = getResultsResourceValue(pathIdVer, registration); | |
723 | +// return resultsResourceValue != null ? this.lwM2mTransportContextServer.getKvAttrTelemetryToThingsboard(resultsResourceValue) : null; | |
724 | +// } | |
725 | + | |
726 | + private TransportProtos.KeyValueProto getKvToThingsboard(String pathIdVer, Registration registration) { | |
727 | + LwM2mClient lwM2MClient = this.lwM2mClientContext.getLwM2mClientWithReg(null, registration.getId()); | |
745 | 728 | JsonObject names = lwM2mClientContext.getProfiles().get(lwM2MClient.getProfileId()).getPostKeyNameProfile(); |
746 | - if (names != null && names.has(path)) { | |
747 | - String resName = names.get(path).getAsString(); | |
748 | - if (resName != null && !resName.isEmpty()) { | |
729 | + if (names != null && names.has(pathIdVer)) { | |
730 | + String resourceName = names.get(pathIdVer).getAsString(); | |
731 | + if (resourceName != null && !resourceName.isEmpty()) { | |
749 | 732 | try { |
750 | - String resValue = this.getResourceValueToString(lwM2MClient, path); | |
751 | - parameters.addProperty(resName, resValue); | |
733 | + LwM2mResource resourceValue = lwM2MClient != null ? getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer) : null; | |
734 | + if (resourceValue != null) { | |
735 | + ResourceModel.Type currentType = resourceValue.getType(); | |
736 | + ResourceModel.Type expectedType = this.lwM2mTransportContextServer.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); | |
737 | + Object valueKvProto = null; | |
738 | + if (resourceValue.isMultiInstances()) { | |
739 | + valueKvProto = new JsonObject(); | |
740 | + Object finalvalueKvProto = valueKvProto; | |
741 | + Gson gson = new GsonBuilder().create(); | |
742 | + resourceValue.getValues().forEach((k, v) -> { | |
743 | + Object val = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, | |
744 | + new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); | |
745 | + JsonElement element = gson.toJsonTree(val, val.getClass()); | |
746 | + ((JsonObject) finalvalueKvProto).add(String.valueOf(k), element); | |
747 | + }); | |
748 | + valueKvProto = gson.toJson(valueKvProto); | |
749 | + } else { | |
750 | + valueKvProto = this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, | |
751 | + new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); | |
752 | + } | |
753 | + return valueKvProto != null ? this.lwM2mTransportContextServer.getKvAttrTelemetryToThingsboard(currentType, resourceName, valueKvProto, resourceValue.isMultiInstances()) : null; | |
754 | + } | |
752 | 755 | } catch (Exception e) { |
753 | 756 | log.error("Failed to add parameters.", e); |
754 | 757 | } |
755 | 758 | } |
756 | 759 | } else { |
757 | - log.error("Failed to add parameters. path: [{}], names: [{}]", path, names); | |
760 | + log.error("Failed to add parameters. path: [{}], names: [{}]", pathIdVer, names); | |
758 | 761 | } |
762 | + return null; | |
759 | 763 | } |
760 | 764 | |
761 | 765 | /** |
762 | - * @param path - path resource | |
763 | - * @return - value of Resource or null | |
766 | + * @param pathIdVer - path resource | |
767 | + * @return - value of Resource into format KvProto or null | |
764 | 768 | */ |
765 | - private String getResourceValueToString(LwM2mClient lwM2MClient, String path) { | |
766 | - LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(path)); | |
767 | - LwM2mResource resourceValue = this.returnResourceValueFromLwM2MClient(lwM2MClient, path); | |
768 | - return resourceValue == null ? null : | |
769 | - this.converter.convertValue(resourceValue.isMultiInstances() ? resourceValue.getValues() : resourceValue.getValue(), resourceValue.getType(), ResourceModel.Type.STRING, pathIds).toString(); | |
769 | + private Object getResourceValueFormatKv(LwM2mClient lwM2MClient, String pathIdVer) { | |
770 | + LwM2mResource resourceValue = this.getResourceValueFromLwM2MClient(lwM2MClient, pathIdVer); | |
771 | + ResourceModel.Type currentType = resourceValue.getType(); | |
772 | + ResourceModel.Type expectedType = this.lwM2mTransportContextServer.getResourceModelTypeEqualsKvProtoValueType(currentType, pathIdVer); | |
773 | + return this.converter.convertValue(resourceValue.getValue(), currentType, expectedType, | |
774 | + new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer))); | |
770 | 775 | } |
771 | 776 | |
772 | 777 | /** |
... | ... | @@ -774,9 +779,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
774 | 779 | * @param path - |
775 | 780 | * @return - return value of Resource by idPath |
776 | 781 | */ |
777 | - private LwM2mResource returnResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) { | |
782 | + private LwM2mResource getResourceValueFromLwM2MClient(LwM2mClient lwM2MClient, String path) { | |
778 | 783 | LwM2mResource resourceValue = null; |
779 | - if (new LwM2mPath(convertToObjectIdFromIdVer(path)).isResource()) { | |
784 | + if (new LwM2mPath(convertPathFromIdVerToObjectId(path)).isResource()) { | |
780 | 785 | resourceValue = lwM2MClient.getResources().get(path).getLwM2mResource(); |
781 | 786 | } |
782 | 787 | return resourceValue; |
... | ... | @@ -959,7 +964,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
959 | 964 | */ |
960 | 965 | private void readResourceValueObserve(Registration registration, Set<String> targets, String typeOper) { |
961 | 966 | targets.forEach(target -> { |
962 | - LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(target)); | |
967 | + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(target)); | |
963 | 968 | if (pathIds.isResource()) { |
964 | 969 | if (GET_TYPE_OPER_READ.equals(typeOper)) { |
965 | 970 | lwM2mTransportRequest.sendAllRequest(registration, target, typeOper, |
... | ... | @@ -1050,19 +1055,23 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1050 | 1055 | private void cancelObserveIsValue(Registration registration, Set<String> paramAnallyzer) { |
1051 | 1056 | LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2mClientWithReg(registration, null); |
1052 | 1057 | paramAnallyzer.forEach(p -> { |
1053 | - if (this.returnResourceValueFromLwM2MClient(lwM2MClient, p) != null) { | |
1054 | - this.setCancelObservationRecourse(registration, convertToObjectIdFromIdVer(p)); | |
1058 | + if (this.getResourceValueFromLwM2MClient(lwM2MClient, p) != null) { | |
1059 | + this.setCancelObservationRecourse(registration, convertPathFromIdVerToObjectId(p)); | |
1055 | 1060 | } |
1056 | 1061 | } |
1057 | 1062 | ); |
1058 | 1063 | } |
1059 | 1064 | |
1060 | - private void putDelayedUpdateResourcesClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) { | |
1065 | + private void updateResourcesValueToClient(LwM2mClient lwM2MClient, Object valueOld, Object valueNew, String path) { | |
1061 | 1066 | if (valueNew != null && (valueOld == null || !valueNew.toString().equals(valueOld.toString()))) { |
1062 | 1067 | lwM2mTransportRequest.sendAllRequest(lwM2MClient.getRegistration(), path, POST_TYPE_OPER_WRITE_REPLACE, |
1063 | 1068 | ContentFormat.TLV.getName(), null, valueNew, this.lwM2mTransportContextServer.getLwM2MTransportConfigServer().getTimeout()); |
1064 | 1069 | } else { |
1065 | - log.error("05 delayError"); | |
1070 | + log.error("Failed update resource [{}] [{}]", path, valueNew); | |
1071 | + String logMsg = String.format("%s: Failed update resource path - %s value - %s. Value is not changed or bad", | |
1072 | + LOG_LW2M_ERROR, path, valueNew); | |
1073 | + this.sendLogsToThingsboard(logMsg, lwM2MClient.getRegistration()); | |
1074 | + log.info("Failed update resource [{}] [{}]", path, valueNew); | |
1066 | 1075 | } |
1067 | 1076 | } |
1068 | 1077 | |
... | ... | @@ -1082,9 +1091,9 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1082 | 1091 | * @param name - |
1083 | 1092 | * @return path if path isPresent in postProfile |
1084 | 1093 | */ |
1085 | - private String getPathAttributeUpdate(TransportProtos.SessionInfoProto sessionInfo, String name) { | |
1086 | - String profilePath = this.getPathAttributeUpdateProfile(sessionInfo, name); | |
1087 | - return !profilePath.isEmpty() ? profilePath : null; | |
1094 | + private String validatePathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { | |
1095 | + String pathIdVer = this.getPresentPathIntoProfile(sessionInfo, name); | |
1096 | + return !pathIdVer.isEmpty() ? pathIdVer : null; | |
1088 | 1097 | } |
1089 | 1098 | |
1090 | 1099 | /** |
... | ... | @@ -1094,7 +1103,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1094 | 1103 | * @param name - |
1095 | 1104 | * @return - |
1096 | 1105 | */ |
1097 | - private String getPathAttributeUpdateProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { | |
1106 | + private String getPresentPathIntoProfile(TransportProtos.SessionInfoProto sessionInfo, String name) { | |
1098 | 1107 | LwM2mClientProfile profile = lwM2mClientContext.getProfile(new UUID(sessionInfo.getDeviceProfileIdMSB(), sessionInfo.getDeviceProfileIdLSB())); |
1099 | 1108 | LwM2mClient lwM2mClient = lwM2mClientContext.getLwM2MClient(sessionInfo); |
1100 | 1109 | return profile.getPostKeyNameProfile().getAsJsonObject().entrySet().stream() |
... | ... | @@ -1105,41 +1114,50 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1105 | 1114 | /** |
1106 | 1115 | * Update resource value on client: if there is a difference in values between the current resource values and the shared attribute values |
1107 | 1116 | * #1 Get path resource by result attributesResponse |
1108 | - * #1.1 If two names have equal path => last time attribute | |
1109 | - * #2.1 if there is a difference in values between the current resource values and the shared attribute values | |
1110 | - * => send to client Request Update of value (new value from shared attribute) | |
1111 | - * and LwM2MClient.delayedRequests.add(path) | |
1112 | - * #2.1 if there is not a difference in values between the current resource values and the shared attribute values | |
1113 | 1117 | * |
1114 | 1118 | * @param attributesResponse - |
1115 | 1119 | * @param sessionInfo - |
1116 | 1120 | */ |
1117 | 1121 | public void onGetAttributesResponse(TransportProtos.GetAttributeResponseMsg attributesResponse, TransportProtos.SessionInfoProto sessionInfo) { |
1118 | 1122 | try { |
1119 | - LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo); | |
1120 | - attributesResponse.getSharedAttributeListList().forEach(attr -> { | |
1121 | - String path = this.getPathAttributeUpdate(sessionInfo, attr.getKv().getKey()); | |
1122 | - if (path != null) { | |
1123 | - // #1.1 | |
1124 | - if (lwM2MClient.getDelayedRequests().containsKey(path) && attr.getTs() > lwM2MClient.getDelayedRequests().get(path).getTs()) { | |
1125 | - lwM2MClient.getDelayedRequests().put(path, attr); | |
1126 | - } else { | |
1127 | - lwM2MClient.getDelayedRequests().put(path, attr); | |
1128 | - } | |
1129 | - } | |
1130 | - }); | |
1131 | - // #2.1 | |
1132 | - lwM2MClient.getDelayedRequests().forEach((k, v) -> { | |
1133 | - ArrayList<TransportProtos.KeyValueProto> listV = new ArrayList<>(); | |
1134 | - listV.add(v.getKv()); | |
1135 | - this.putDelayedUpdateResourcesClient(lwM2MClient, this.getResourceValueToString(lwM2MClient, k), getJsonObject(listV).get(v.getKv().getKey()), k); | |
1136 | - }); | |
1123 | + List<TransportProtos.TsKvProto> tsKvProtos = attributesResponse.getSharedAttributeListList(); | |
1124 | + this.updateAttriuteFromThingsboard(tsKvProtos, sessionInfo); | |
1137 | 1125 | } catch (Exception e) { |
1138 | 1126 | log.error(String.valueOf(e)); |
1139 | 1127 | } |
1140 | 1128 | } |
1141 | 1129 | |
1142 | 1130 | /** |
1131 | + * #1.1 If two names have equal path => last time attribute | |
1132 | + * #2.1 if there is a difference in values between the current resource values and the shared attribute values | |
1133 | + * => send to client Request Update of value (new value from shared attribute) | |
1134 | + * and LwM2MClient.delayedRequests.add(path) | |
1135 | + * #2.1 if there is not a difference in values between the current resource values and the shared attribute values | |
1136 | + * | |
1137 | + * @param tsKvProtos | |
1138 | + * @param sessionInfo | |
1139 | + */ | |
1140 | + public void updateAttriuteFromThingsboard(List<TransportProtos.TsKvProto> tsKvProtos, TransportProtos.SessionInfoProto sessionInfo) { | |
1141 | + LwM2mClient lwM2MClient = lwM2mClientContext.getLwM2MClient(sessionInfo); | |
1142 | + tsKvProtos.forEach(tsKvProto -> { | |
1143 | + String pathIdVer = this.validatePathIntoProfile(sessionInfo, tsKvProto.getKv().getKey()); | |
1144 | + if (pathIdVer != null) { | |
1145 | + // #1.1 | |
1146 | + if (lwM2MClient.getDelayedRequests().containsKey(pathIdVer) && tsKvProto.getTs() > lwM2MClient.getDelayedRequests().get(pathIdVer).getTs()) { | |
1147 | + lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto); | |
1148 | + } else if (!lwM2MClient.getDelayedRequests().containsKey(pathIdVer)) { | |
1149 | + lwM2MClient.getDelayedRequests().put(pathIdVer, tsKvProto); | |
1150 | + } | |
1151 | + } | |
1152 | + }); | |
1153 | + // #2.1 | |
1154 | + lwM2MClient.getDelayedRequests().forEach((pathIdVer, tsKvProto) -> { | |
1155 | + this.updateResourcesValueToClient(lwM2MClient, this.getResourceValueFormatKv(lwM2MClient, pathIdVer), | |
1156 | + this.lwM2mTransportContextServer.getValueFromKvProto(tsKvProto.getKv()), pathIdVer); | |
1157 | + }); | |
1158 | + } | |
1159 | + | |
1160 | + /** | |
1143 | 1161 | * @param lwM2MClient - |
1144 | 1162 | * @return SessionInfoProto - |
1145 | 1163 | */ |
... | ... | @@ -1257,7 +1275,7 @@ public class LwM2mTransportServiceImpl implements LwM2mTransportService { |
1257 | 1275 | |
1258 | 1276 | private boolean validateResourceInModel(LwM2mClient lwM2mClient, String pathIdVer, boolean isWritableNotOptional) { |
1259 | 1277 | ResourceModel resourceModel = lwM2mClient.getResourceModel(pathIdVer); |
1260 | - Integer objectId = new LwM2mPath(convertToObjectIdFromIdVer(pathIdVer)).getObjectId(); | |
1278 | + Integer objectId = new LwM2mPath(convertPathFromIdVerToObjectId(pathIdVer)).getObjectId(); | |
1261 | 1279 | String objectVer = validateObjectVerFromKey(pathIdVer); |
1262 | 1280 | return resourceModel != null && (isWritableNotOptional ? |
1263 | 1281 | objectId != null && objectVer != null && objectVer.equals(lwM2mClient.getRegistration().getSupportedVersion(objectId)) && resourceModel.operations.isWritable() : | ... | ... |
... | ... | @@ -39,7 +39,7 @@ import java.util.concurrent.CopyOnWriteArrayList; |
39 | 39 | import java.util.stream.Collectors; |
40 | 40 | |
41 | 41 | import static org.thingsboard.server.common.data.lwm2m.LwM2mConstants.LWM2M_SEPARATOR_PATH; |
42 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToObjectIdFromIdVer; | |
42 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromIdVerToObjectId; | |
43 | 43 | |
44 | 44 | @Slf4j |
45 | 45 | @Data |
... | ... | @@ -83,7 +83,7 @@ public class LwM2mClient implements Cloneable { |
83 | 83 | this.resources.get(pathRez).setLwM2mResource(rez); |
84 | 84 | return true; |
85 | 85 | } else { |
86 | - LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez)); | |
86 | + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); | |
87 | 87 | ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); |
88 | 88 | if (resourceModel != null) { |
89 | 89 | this.resources.put(pathRez, new ResourceValue(rez, resourceModel)); |
... | ... | @@ -110,7 +110,7 @@ public class LwM2mClient implements Cloneable { |
110 | 110 | public void deleteResources(String pathIdVer, LwM2mModelProvider modelProvider) { |
111 | 111 | Set<String> key = getKeysEqualsIdVer(pathIdVer); |
112 | 112 | key.forEach(pathRez -> { |
113 | - LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez)); | |
113 | + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); | |
114 | 114 | ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); |
115 | 115 | if (resourceModel != null) { |
116 | 116 | this.resources.get(pathRez).setResourceModel(resourceModel); |
... | ... | @@ -132,7 +132,7 @@ public class LwM2mClient implements Cloneable { |
132 | 132 | } |
133 | 133 | |
134 | 134 | private void saveResourceModel(String pathRez, LwM2mModelProvider modelProvider) { |
135 | - LwM2mPath pathIds = new LwM2mPath(convertToObjectIdFromIdVer(pathRez)); | |
135 | + LwM2mPath pathIds = new LwM2mPath(convertPathFromIdVerToObjectId(pathRez)); | |
136 | 136 | ResourceModel resourceModel = modelProvider.getObjectModel(registration).getResourceModel(pathIds.getObjectId(), pathIds.getResourceId()); |
137 | 137 | this.resources.get(pathRez).setResourceModel(resourceModel); |
138 | 138 | } | ... | ... |
... | ... | @@ -35,7 +35,7 @@ import java.util.UUID; |
35 | 35 | import java.util.concurrent.ConcurrentHashMap; |
36 | 36 | |
37 | 37 | import static org.thingsboard.server.transport.lwm2m.secure.LwM2MSecurityMode.NO_SEC; |
38 | -import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertToIdVerFromObjectId; | |
38 | +import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportHandler.convertPathFromObjectIdToIdVer; | |
39 | 39 | |
40 | 40 | @Service |
41 | 41 | @TbLwM2mTransportComponent |
... | ... | @@ -185,7 +185,7 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
185 | 185 | Arrays.stream(registration.getObjectLinks()).forEach(url -> { |
186 | 186 | LwM2mPath pathIds = new LwM2mPath(url.getUrl()); |
187 | 187 | if (!pathIds.isRoot()) { |
188 | - clientObjects.add(convertToIdVerFromObjectId(url.getUrl(), registration)); | |
188 | + clientObjects.add(convertPathFromObjectIdToIdVer(url.getUrl(), registration)); | |
189 | 189 | } |
190 | 190 | }); |
191 | 191 | return (clientObjects.size() > 0) ? clientObjects : null; | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.lwm2m.server.client; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.gen.transport.TransportProtos; | |
20 | + | |
21 | +import java.util.ArrayList; | |
22 | +import java.util.List; | |
23 | + | |
24 | +@Data | |
25 | +public class ResultsAddKeyValueProto { | |
26 | + List<TransportProtos.KeyValueProto> resultAttributes; | |
27 | + List<TransportProtos.KeyValueProto> resultTelemetries; | |
28 | + | |
29 | + public ResultsAddKeyValueProto() { | |
30 | + this.resultAttributes = new ArrayList<>(); | |
31 | + this.resultTelemetries = new ArrayList<>(); | |
32 | + } | |
33 | + | |
34 | +} | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.transport.lwm2m.server.client; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import org.thingsboard.server.common.data.kv.DataType; | |
20 | + | |
21 | +@Data | |
22 | +public class ResultsResourceValue { | |
23 | + DataType dataType; | |
24 | + Object value; | |
25 | + String resourceName; | |
26 | + | |
27 | + public ResultsResourceValue (DataType dataType, Object value, String resourceName) { | |
28 | + this.dataType = dataType; | |
29 | + this.value = value; | |
30 | + this.resourceName = resourceName; | |
31 | + } | |
32 | +} | ... | ... |
... | ... | @@ -18,14 +18,12 @@ package org.thingsboard.server.transport.lwm2m.utils; |
18 | 18 | import lombok.extern.slf4j.Slf4j; |
19 | 19 | import org.eclipse.leshan.core.model.ResourceModel.Type; |
20 | 20 | import org.eclipse.leshan.core.node.LwM2mPath; |
21 | +import org.eclipse.leshan.core.node.ObjectLink; | |
21 | 22 | import org.eclipse.leshan.core.node.codec.CodecException; |
22 | 23 | import org.eclipse.leshan.core.node.codec.LwM2mValueConverter; |
23 | 24 | import org.eclipse.leshan.core.util.Hex; |
24 | 25 | import org.eclipse.leshan.core.util.StringUtils; |
25 | 26 | |
26 | -import javax.xml.datatype.DatatypeConfigurationException; | |
27 | -import javax.xml.datatype.DatatypeFactory; | |
28 | -import javax.xml.datatype.XMLGregorianCalendar; | |
29 | 27 | import java.math.BigInteger; |
30 | 28 | import java.text.DateFormat; |
31 | 29 | import java.text.SimpleDateFormat; |
... | ... | @@ -111,15 +109,16 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { |
111 | 109 | case INTEGER: |
112 | 110 | log.debug("Trying to convert long value {} to date", value); |
113 | 111 | /** let's assume we received the millisecond since 1970/1/1 */ |
114 | - return new Date((Long) value); | |
112 | + return new Date(((Number) value).longValue() * 1000L); | |
115 | 113 | case STRING: |
116 | 114 | log.debug("Trying to convert string value {} to date", value); |
117 | 115 | /** let's assume we received an ISO 8601 format date */ |
118 | 116 | try { |
119 | - DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); | |
120 | - XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value); | |
121 | - return cal.toGregorianCalendar().getTime(); | |
122 | - } catch (DatatypeConfigurationException | IllegalArgumentException e) { | |
117 | + return new Date(Long.decode(value.toString())); | |
118 | +// DatatypeFactory datatypeFactory = DatatypeFactory.newInstance(); | |
119 | +// XMLGregorianCalendar cal = datatypeFactory.newXMLGregorianCalendar((String) value); | |
120 | +// return cal.toGregorianCalendar().getTime(); | |
121 | + } catch (IllegalArgumentException e) { | |
123 | 122 | log.debug("Unable to convert string to date", e); |
124 | 123 | throw new CodecException("Unable to convert string (%s) to date for resource %s", value, |
125 | 124 | resourcePath); |
... | ... | @@ -147,6 +146,8 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { |
147 | 146 | return formatter.format(new Date(timeValue)); |
148 | 147 | case OPAQUE: |
149 | 148 | return Hex.encodeHexString((byte[])value); |
149 | + case OBJLNK: | |
150 | + return ObjectLink.decodeFromString((String) value); | |
150 | 151 | default: |
151 | 152 | break; |
152 | 153 | } |
... | ... | @@ -164,10 +165,14 @@ public class LwM2mValueConverterImpl implements LwM2mValueConverter { |
164 | 165 | } |
165 | 166 | } |
166 | 167 | break; |
168 | + case OBJLNK: | |
169 | + if (currentType == Type.STRING) { | |
170 | + return ObjectLink.fromPath(value.toString()); | |
171 | + } | |
167 | 172 | default: |
168 | 173 | } |
169 | 174 | |
170 | 175 | throw new CodecException("Invalid value type for resource %s, expected %s, got %s", resourcePath, expectedType, |
171 | 176 | currentType); |
172 | 177 | } |
173 | -} | |
178 | + } | ... | ... |
... | ... | @@ -119,6 +119,18 @@ redis: |
119 | 119 | |
120 | 120 | # LWM2M server parameters |
121 | 121 | transport: |
122 | + sessions: | |
123 | + inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" | |
124 | + report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:30000}" | |
125 | + json: | |
126 | + # Cast String data types to Numeric if possible when processing Telemetry/Attributes JSON | |
127 | + type_cast_enabled: "${JSON_TYPE_CAST_ENABLED:false}" | |
128 | + # Maximum allowed string value length when processing Telemetry/Attributes JSON (0 value disables string value length check) | |
129 | + max_string_value_length: "${JSON_MAX_STRING_VALUE_LENGTH:0}" | |
130 | + client_side_rpc: | |
131 | + timeout: "${CLIENT_SIDE_RPC_TIMEOUT:60000}" | |
132 | + # Enable/disable http/mqtt/coap transport protocols (has higher priority than certain protocol's 'enabled' property) | |
133 | + api_enabled: "${TB_TRANSPORT_API_ENABLED:true}" | |
122 | 134 | # Local LwM2M transport parameters |
123 | 135 | lwm2m: |
124 | 136 | # Enable/disable lvm2m transport protocol. |
... | ... | @@ -180,15 +192,6 @@ transport: |
180 | 192 | # Use redis for Security and Registration stores |
181 | 193 | redis.enabled: "${LWM2M_REDIS_ENABLED:false}" |
182 | 194 | |
183 | - sessions: | |
184 | - inactivity_timeout: "${TB_TRANSPORT_SESSIONS_INACTIVITY_TIMEOUT:300000}" | |
185 | - report_timeout: "${TB_TRANSPORT_SESSIONS_REPORT_TIMEOUT:30000}" | |
186 | - json: | |
187 | - # Cast String data types to Numeric if possible when processing Telemetry/Attributes JSON | |
188 | - type_cast_enabled: "${JSON_TYPE_CAST_ENABLED:true}" | |
189 | - # Maximum allowed string value length when processing Telemetry/Attributes JSON (0 value disables string value length check) | |
190 | - max_string_value_length: "${JSON_MAX_STRING_VALUE_LENGTH:0}" | |
191 | - | |
192 | 195 | queue: |
193 | 196 | type: "${TB_QUEUE_TYPE:kafka}" # kafka (Apache Kafka) or aws-sqs (AWS SQS) or pubsub (PubSub) or service-bus (Azure Service Bus) or rabbitmq (RabbitMQ) |
194 | 197 | kafka: | ... | ... |
... | ... | @@ -82,8 +82,6 @@ |
82 | 82 | <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong> |
83 | 83 | </mat-error> |
84 | 84 | </mat-form-field> |
85 | - </div> | |
86 | - <div fxLayout="row" fxLayoutGap="8px"> | |
87 | 85 | <mat-form-field fxFlex> |
88 | 86 | <mat-label>{{ 'device-profile.lwm2m.default-min-period' | translate }}</mat-label> |
89 | 87 | <input matInput type="number" formControlName="defaultMinPeriod" required> |
... | ... | @@ -93,13 +91,16 @@ |
93 | 91 | <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong> |
94 | 92 | </mat-error> |
95 | 93 | </mat-form-field> |
96 | - <mat-form-field fxFlex> | |
94 | + </div> | |
95 | + <div fxLayout="row" fxLayoutGap="8px"> | |
96 | + <mat-form-field class="mat-block" fxFlex="100"> | |
97 | 97 | <mat-label>{{ 'device-profile.lwm2m.binding' | translate }}</mat-label> |
98 | - <input matInput type="text" formControlName="binding" required> | |
99 | - <mat-error *ngIf="lwm2mDeviceProfileFormGroup.get('binding').hasError('required')"> | |
100 | - {{ 'device-profile.lwm2m.binding' | translate }} | |
101 | - <strong>{{ 'device-profile.lwm2m.required' | translate }}</strong> | |
102 | - </mat-error> | |
98 | + <mat-select formControlName="binding"> | |
99 | + <mat-option *ngFor="let bindingMode of bindingModeTypes" | |
100 | + [value]="bindingMode"> | |
101 | + {{ bindingModeTypeNamesMap.get(bindingModeType[bindingMode]) }} | |
102 | + </mat-option> | |
103 | + </mat-select> | |
103 | 104 | </mat-form-field> |
104 | 105 | </div> |
105 | 106 | <div> | ... | ... |
... | ... | @@ -22,7 +22,8 @@ import { AppState } from '@app/core/core.state'; |
22 | 22 | import { coerceBooleanProperty } from '@angular/cdk/coercion'; |
23 | 23 | import { |
24 | 24 | ATTRIBUTE, |
25 | - DEFAULT_BINDING, | |
25 | + BINDING_MODE, | |
26 | + BINDING_MODE_NAMES, | |
26 | 27 | getDefaultProfileConfig, |
27 | 28 | INSTANCES, |
28 | 29 | KEY_NAME, |
... | ... | @@ -55,6 +56,9 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
55 | 56 | private requiredValue: boolean; |
56 | 57 | private disabled = false; |
57 | 58 | |
59 | + bindingModeType = BINDING_MODE; | |
60 | + bindingModeTypes = Object.keys(BINDING_MODE); | |
61 | + bindingModeTypeNamesMap = BINDING_MODE_NAMES; | |
58 | 62 | lwm2mDeviceProfileFormGroup: FormGroup; |
59 | 63 | lwm2mDeviceConfigFormGroup: FormGroup; |
60 | 64 | bootstrapServers: string; |
... | ... | @@ -86,7 +90,7 @@ export class Lwm2mDeviceProfileTransportConfigurationComponent implements Contro |
86 | 90 | lifetime: [null, Validators.required], |
87 | 91 | defaultMinPeriod: [null, Validators.required], |
88 | 92 | notifIfDisabled: [true, []], |
89 | - binding: [DEFAULT_BINDING, Validators.required], | |
93 | + binding:[], | |
90 | 94 | bootstrapServer: [null, Validators.required], |
91 | 95 | lwm2mServer: [null, Validators.required], |
92 | 96 | }); | ... | ... |
... | ... | @@ -44,6 +44,35 @@ export const KEY_REGEXP_NUMBER = /^(\-?|\+?)\d*$/; |
44 | 44 | export const INSTANCES_ID_VALUE_MIN = 0; |
45 | 45 | export const INSTANCES_ID_VALUE_MAX = 65535; |
46 | 46 | |
47 | + | |
48 | +export enum BINDING_MODE { | |
49 | + U = 'U', | |
50 | + UQ = 'UQ', | |
51 | + T = 'T', | |
52 | + TQ = 'TQ', | |
53 | + S = 'S', | |
54 | + SQ = 'SQ', | |
55 | + US = 'US', | |
56 | + TS = 'TS', | |
57 | + UQS = 'UQS', | |
58 | + TQS = 'TQS' | |
59 | +} | |
60 | + | |
61 | +export const BINDING_MODE_NAMES = new Map<BINDING_MODE, string>( | |
62 | + [ | |
63 | + [BINDING_MODE.U, 'U: UDP connection in standard mode'], | |
64 | + [BINDING_MODE.UQ, 'UQ: UDP connection in queue mode'], | |
65 | + [BINDING_MODE.US, 'US: both UDP and SMS connections active, both in standard mode'], | |
66 | + [BINDING_MODE.UQS, 'UQS: both UDP and SMS connections active; UDP in queue mode, SMS in standard mode'], | |
67 | + [BINDING_MODE.T,'T: TCP connection in standard mode'], | |
68 | + [BINDING_MODE.TQ, 'TQ: TCP connection in queue mode'], | |
69 | + [BINDING_MODE.TS, 'TS: both TCP and SMS connections active, both in standard mode'], | |
70 | + [BINDING_MODE.TQS, 'TQS: both TCP and SMS connections active; TCP in queue mode, SMS in standard mode'], | |
71 | + [BINDING_MODE.S, 'S: SMS connection in standard mode'], | |
72 | + [BINDING_MODE.SQ, 'SQ: SMS connection in queue mode'] | |
73 | + ] | |
74 | +); | |
75 | + | |
47 | 76 | export enum ATTRIBUTE_LWM2M_ENUM { |
48 | 77 | dim = 'dim', |
49 | 78 | ver = 'ver', |
... | ... | @@ -62,8 +91,7 @@ export const ATTRIBUTE_LWM2M_LABEL = new Map<ATTRIBUTE_LWM2M_ENUM, string>( |
62 | 91 | [ATTRIBUTE_LWM2M_ENUM.pmax, 'pmax='], |
63 | 92 | [ATTRIBUTE_LWM2M_ENUM.gt, '>'], |
64 | 93 | [ATTRIBUTE_LWM2M_ENUM.lt, '<'], |
65 | - [ATTRIBUTE_LWM2M_ENUM.st, 'st='], | |
66 | - | |
94 | + [ATTRIBUTE_LWM2M_ENUM.st, 'st='] | |
67 | 95 | ] |
68 | 96 | ); |
69 | 97 | ... | ... |