From e371fff07eb904fc29be10df962d1ba636471b06 Mon Sep 17 00:00:00 2001 From: JaroslawLegierski Date: Tue, 12 Nov 2024 14:08:43 +0100 Subject: [PATCH 1/4] JsonArrayEntry class modifications --- .../leshan/core/json/JsonArrayEntry.java | 46 +++++--------- .../json/jackson/JsonArrayEntrySerDes.java | 22 ++++--- .../node/codec/json/LwM2mNodeJsonEncoder.java | 31 ++++++---- .../leshan/core/json/JsonSerializerTest.java | 60 +++++-------------- 4 files changed, 65 insertions(+), 94 deletions(-) diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonArrayEntry.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonArrayEntry.java index f8b71e9858..17415698d2 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonArrayEntry.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonArrayEntry.java @@ -25,17 +25,27 @@ public class JsonArrayEntry { - private String name; + private final String name; - private Number floatValue; + private final Number floatValue; - private Boolean booleanValue; + private final Boolean booleanValue; - private String objectLinkValue; + private final String objectLinkValue; - private String stringValue; + private final String stringValue; - private BigDecimal time; + private final BigDecimal time; + + public JsonArrayEntry(String name, Number floatValue, Boolean booleanValue, String objectLinkValue, + String stringValue, BigDecimal time) { + this.name = name; + this.floatValue = floatValue; + this.booleanValue = booleanValue; + this.objectLinkValue = objectLinkValue; + this.stringValue = stringValue; + this.time = time; + } public ResourceModel.Type getType() { if (booleanValue != null) { @@ -57,50 +67,26 @@ public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public BigDecimal getTime() { return time; } - public void setTime(BigDecimal time) { - this.time = time; - } - public Number getFloatValue() { return floatValue; } - public void setFloatValue(Number floatValue) { - this.floatValue = floatValue; - } - public Boolean getBooleanValue() { return booleanValue; } - public void setBooleanValue(Boolean booleanValue) { - this.booleanValue = booleanValue; - } - public String getObjectLinkValue() { return objectLinkValue; } - public void setObjectLinkValue(String objectLinkValue) { - this.objectLinkValue = objectLinkValue; - } - public String getStringValue() { return stringValue; } - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - public Object getResourceValue() { if (booleanValue != null) { diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonArrayEntrySerDes.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonArrayEntrySerDes.java index 385ff45995..202dd8c951 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonArrayEntrySerDes.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonArrayEntrySerDes.java @@ -88,30 +88,38 @@ public JsonArrayEntry deserialize(JsonNode o) throws JsonException { if (o == null) return null; - JsonArrayEntry jae = new JsonArrayEntry(); + String name = null; + BigDecimal time = null; + Number floatValue = null; + Boolean booleanValue = null; + String stringValue = null; + String objectLinkValue = null; + JsonNode n = o.get("n"); if (n != null && n.isTextual()) - jae.setName(n.asText()); + name = n.asText(); JsonNode t = o.get("t"); if (t != null && t.isNumber()) - jae.setTime(new BigDecimal(t.asText())); + time = new BigDecimal(t.asText()); JsonNode v = o.get("v"); if (v != null && v.isNumber()) - jae.setFloatValue(v.numberValue()); + floatValue = v.numberValue(); JsonNode bv = o.get("bv"); if (bv != null && bv.isBoolean()) - jae.setBooleanValue(bv.asBoolean()); + booleanValue = bv.asBoolean(); JsonNode sv = o.get("sv"); if (sv != null && sv.isTextual()) - jae.setStringValue(sv.asText()); + stringValue = sv.asText(); JsonNode ov = o.get("ov"); if (ov != null && ov.isTextual()) - jae.setObjectLinkValue(ov.asText()); + objectLinkValue = ov.asText(); + + JsonArrayEntry jae = new JsonArrayEntry(name, floatValue, booleanValue, objectLinkValue, stringValue, time); if (jae.getType() == null) { throw new JsonException("Missing value(v,bv,ov,sv) field for entry %s", o.toString()); diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java index 45f397db95..d7c9ba76d0 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java @@ -263,19 +263,18 @@ private ArrayList lwM2mResourceToJsonArrayEntry(String resourceP private JsonArrayEntry createJsonArrayEntry(String name, BigDecimal timestampInSeconds, Type type, Type expectedType, Object value) { // Create resource element - JsonArrayEntry jsonResourceElt = new JsonArrayEntry(); - jsonResourceElt.setName(name); - jsonResourceElt.setTime(timestampInSeconds); + JsonArrayEntry jsonResourceElt = new JsonArrayEntry(name, null, null, null, null, timestampInSeconds); // Convert value using expected type LwM2mPath lwM2mResourcePath = name != null ? new LwM2mPath(name) : null; Object convertedValue = converter.convertValue(value, type, expectedType, lwM2mResourcePath); - this.setResourceValue(convertedValue, expectedType, jsonResourceElt, lwM2mResourcePath); + jsonResourceElt = this.setResourceValue(convertedValue, expectedType, jsonResourceElt, lwM2mResourcePath); return jsonResourceElt; } - private void setResourceValue(Object value, Type type, JsonArrayEntry jsonResource, LwM2mPath resourcePath) { + private JsonArrayEntry setResourceValue(Object value, Type type, JsonArrayEntry jsonResource, + LwM2mPath resourcePath) { LOG.trace("Encoding value {} in JSON", value); if (type == null || type == Type.NONE) { @@ -283,41 +282,49 @@ private void setResourceValue(Object value, Type type, JsonArrayEntry jsonResour "Unable to encode value for resource {} without type(probably a executable one)", resourcePath); } + String name = jsonResource.getName(); + BigDecimal time = jsonResource.getTime(); + Number floatValue = jsonResource.getFloatValue(); + Boolean booleanValue = jsonResource.getBooleanValue(); + String stringValue = jsonResource.getStringValue(); + String objectLinkValue = jsonResource.getObjectLinkValue(); + // Following table 20 in the Specs switch (type) { case STRING: - jsonResource.setStringValue((String) value); + stringValue = (String) value; break; case INTEGER: case UNSIGNED_INTEGER: case FLOAT: - jsonResource.setFloatValue((Number) value); + floatValue = (Number) value; break; case BOOLEAN: - jsonResource.setBooleanValue((Boolean) value); + booleanValue = (Boolean) value; break; case TIME: // Specs device object example page 44, rec 13 is Time // represented as float? - jsonResource.setFloatValue((((Date) value).getTime() / 1000L)); + floatValue = BigDecimal.valueOf((((Date) value).getTime() / 1000L)); break; case OPAQUE: - jsonResource.setStringValue(base64Encoder.encode((byte[]) value)); + stringValue = base64Encoder.encode((byte[]) value); break; case OBJLNK: try { - jsonResource.setStringValue(((ObjectLink) value).encodeToString()); + stringValue = ((ObjectLink) value).encodeToString(); } catch (IllegalArgumentException e) { throw new CodecException(e, "Invalid value [%s] for objectLink resource [%s] ", value, resourcePath); } break; case CORELINK: - jsonResource.setStringValue(linkSerializer.serializeCoreLinkFormat((Link[]) value)); + stringValue = linkSerializer.serializeCoreLinkFormat((Link[]) value); break; default: throw new CodecException("Invalid value type %s for %s", type, resourcePath); } + return (new JsonArrayEntry(name, floatValue, booleanValue, objectLinkValue, stringValue, time)); } } } diff --git a/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java b/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java index 142aa29485..b60f2cbedf 100644 --- a/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java +++ b/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java @@ -35,65 +35,35 @@ public class JsonSerializerTest { public void serialize_device_object() throws LwM2mJsonException { ArrayList elements = new ArrayList<>(); - JsonArrayEntry elt1 = new JsonArrayEntry(); - elt1.setName("0"); - elt1.setStringValue("Open Mobile Alliance"); + JsonArrayEntry elt1 = new JsonArrayEntry("0", null, null, null, "Open Mobile Alliance", null); elements.add(elt1); - JsonArrayEntry elt2 = new JsonArrayEntry(); - elt2.setName("1"); - elt2.setStringValue("Lightweight M2M Client"); + JsonArrayEntry elt2 = new JsonArrayEntry("1", null, null, null, "Lightweight M2M Client", null); elements.add(elt2); - JsonArrayEntry elt3 = new JsonArrayEntry(); - elt3.setName("2"); - elt3.setStringValue("345000123"); + JsonArrayEntry elt3 = new JsonArrayEntry("2", null, null, null, "345000123", null); elements.add(elt3); - JsonArrayEntry elt4 = new JsonArrayEntry(); - elt4.setName("6/0"); - elt4.setFloatValue(1); + JsonArrayEntry elt4 = new JsonArrayEntry("6/0", 1, null, null, null, null); elements.add(elt4); - JsonArrayEntry elt5 = new JsonArrayEntry(); - elt5.setName("6/1"); - elt5.setFloatValue(5); + JsonArrayEntry elt5 = new JsonArrayEntry("6/1", 5, null, null, null, null); elements.add(elt5); - JsonArrayEntry elt6 = new JsonArrayEntry(); - elt6.setName("7/0"); - elt6.setFloatValue(3800); + JsonArrayEntry elt6 = new JsonArrayEntry("7/0", 3800, null, null, null, null); elements.add(elt6); - JsonArrayEntry elt7 = new JsonArrayEntry(); - elt7.setName("7/1"); - elt7.setFloatValue(5000); + JsonArrayEntry elt7 = new JsonArrayEntry("7/1", 5000, null, null, null, null); elements.add(elt7); - JsonArrayEntry elt8 = new JsonArrayEntry(); - elt8.setName("8/0"); - elt8.setFloatValue(125); + JsonArrayEntry elt8 = new JsonArrayEntry("8/0", 125, null, null, null, null); elements.add(elt8); - JsonArrayEntry elt9 = new JsonArrayEntry(); - elt9.setName("8/1"); - elt9.setFloatValue(900); + JsonArrayEntry elt9 = new JsonArrayEntry("8/1", 900, null, null, null, null); elements.add(elt9); - JsonArrayEntry elt10 = new JsonArrayEntry(); - elt10.setName("9"); - elt10.setFloatValue(100); + JsonArrayEntry elt10 = new JsonArrayEntry("9", 100, null, null, null, null); elements.add(elt10); - JsonArrayEntry elt11 = new JsonArrayEntry(); - elt11.setName("10"); - elt11.setFloatValue(15); + JsonArrayEntry elt11 = new JsonArrayEntry("10", 15, null, null, null, null); elements.add(elt11); - JsonArrayEntry elt12 = new JsonArrayEntry(); - elt12.setName("11/0"); - elt12.setFloatValue(0); + JsonArrayEntry elt12 = new JsonArrayEntry("11/0", 0, null, null, null, null); elements.add(elt12); - JsonArrayEntry elt13 = new JsonArrayEntry(); - elt13.setName("13"); - elt13.setFloatValue(1367491215); + JsonArrayEntry elt13 = new JsonArrayEntry("13", 1367491215, null, null, null, null); elements.add(elt13); - JsonArrayEntry elt14 = new JsonArrayEntry(); - elt14.setName("14"); - elt14.setStringValue("+02:00"); + JsonArrayEntry elt14 = new JsonArrayEntry("14", null, null, null, "+02:00", null); elements.add(elt14); - JsonArrayEntry elt15 = new JsonArrayEntry(); - elt15.setName("15"); - elt15.setStringValue("U"); + JsonArrayEntry elt15 = new JsonArrayEntry("15", null, null, null, "U", null); elements.add(elt15); JsonRootObject element = new JsonRootObject(); From 6bcc707c466ff66f4d3bbb70479927334c53dbb4 Mon Sep 17 00:00:00 2001 From: JaroslawLegierski Date: Wed, 13 Nov 2024 15:28:44 +0100 Subject: [PATCH 2/4] SenMLPack class refactoring --- .../node/codec/senml/LwM2mNodeSenMLEncoder.java | 3 +-- .../java/org/eclipse/leshan/senml/SenMLPack.java | 14 ++------------ 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java index 8d5862e850..40bfe0996d 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java @@ -82,8 +82,7 @@ public byte[] encode(LwM2mNode node, String rootPath, LwM2mPath path, LwM2mModel internalEncoder.converter = converter; node.accept(internalEncoder); - SenMLPack pack = new SenMLPack(); - pack.setRecords(internalEncoder.records); + SenMLPack pack = new SenMLPack(internalEncoder.records); try { return encoder.toSenML(pack); diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLPack.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLPack.java index 9b16fe303e..3737805904 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLPack.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLPack.java @@ -26,9 +26,10 @@ */ public class SenMLPack { - private List records; + private final List records; public SenMLPack() { + records = new ArrayList<>(); } public SenMLPack(List records) { @@ -36,24 +37,13 @@ public SenMLPack(List records) { } public void addRecord(SenMLRecord record) { - if (records == null) { - records = new ArrayList<>(); - } - records.add(record); } public void addRecords(List records) { - if (this.records == null) { - this.records = new ArrayList<>(); - } this.records.addAll(records); } - public void setRecords(List records) { - this.records = records; - } - public List getRecords() { if (records == null) return Collections.emptyList(); From 3920a1403689b5a0e487b202df23dc5d5809de26 Mon Sep 17 00:00:00 2001 From: JaroslawLegierski Date: Fri, 15 Nov 2024 13:08:38 +0100 Subject: [PATCH 3/4] JsonRootObject class refactoring --- .../leshan/core/json/JsonRootObject.java | 23 ++++++------------- .../json/jackson/JsonRootObjectSerDes.java | 14 +++++++---- .../node/codec/json/LwM2mNodeJsonEncoder.java | 8 ++----- .../leshan/core/json/JsonSerializerTest.java | 3 +-- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonRootObject.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonRootObject.java index 6a5eeed7d9..009fdab111 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonRootObject.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/JsonRootObject.java @@ -27,35 +27,26 @@ */ public class JsonRootObject { - private String baseName = null; + private final String baseName; - private List jsonArray; + private final List jsonArray; - private BigDecimal baseTime; + private final BigDecimal baseTime; - public JsonRootObject() { + public JsonRootObject(String baseName, List jsonArray, BigDecimal baseTime) { + this.baseName = baseName; + this.jsonArray = jsonArray; + this.baseTime = baseTime; } public String getBaseName() { return baseName; } - public void setBaseName(String baseName) { - this.baseName = baseName; - } - public BigDecimal getBaseTime() { return baseTime; } - public void setBaseTime(BigDecimal baseTime) { - this.baseTime = baseTime; - } - - public void setResourceList(List jsonArray) { - this.jsonArray = jsonArray; - } - public List getResourceList() { if (jsonArray == null) return Collections.emptyList(); diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonRootObjectSerDes.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonRootObjectSerDes.java index 640088dc0a..9ecec69554 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonRootObjectSerDes.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/json/jackson/JsonRootObjectSerDes.java @@ -16,7 +16,9 @@ package org.eclipse.leshan.core.json.jackson; import java.math.BigDecimal; +import java.util.List; +import org.eclipse.leshan.core.json.JsonArrayEntry; import org.eclipse.leshan.core.json.JsonRootObject; import org.eclipse.leshan.core.util.json.JacksonJsonSerDes; import org.eclipse.leshan.core.util.json.JsonException; @@ -52,22 +54,24 @@ public JsonRootObject deserialize(JsonNode jsonNode) throws JsonException { if (jsonNode == null) return null; - JsonRootObject jro = new JsonRootObject(); + List ResourceList; + String baseName = null; + BigDecimal baseTime = null; JsonNode e = jsonNode.get("e"); if (e != null && e.isArray()) - jro.setResourceList(serDes.deserialize(e.elements())); + ResourceList = serDes.deserialize(e.elements()); else throw new JsonException("'e' field is missing for %s", jsonNode.toString()); JsonNode bn = jsonNode.get("bn"); if (bn != null && bn.isTextual()) - jro.setBaseName(bn.asText()); + baseName = bn.asText(); JsonNode bt = jsonNode.get("bt"); if (bt != null && bt.isNumber()) - jro.setBaseTime(new BigDecimal(bt.asText())); + baseTime = new BigDecimal(bt.asText()); - return jro; + return new JsonRootObject(baseName, ResourceList, baseTime); } } diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java index d7c9ba76d0..c08c3ebb10 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/json/LwM2mNodeJsonEncoder.java @@ -87,9 +87,7 @@ public byte[] encode(LwM2mNode node, String rootPath, LwM2mPath path, LwM2mModel internalEncoder.requestPath = path; internalEncoder.converter = converter; node.accept(internalEncoder); - JsonRootObject jsonObject = new JsonRootObject(); - jsonObject.setResourceList(internalEncoder.resourceList); - jsonObject.setBaseName(internalEncoder.baseName); + JsonRootObject jsonObject = new JsonRootObject(internalEncoder.baseName, internalEncoder.resourceList, null); try { return encoder.toJsonLwM2m(jsonObject).getBytes(); } catch (LwM2mJsonException e) { @@ -126,9 +124,7 @@ public byte[] encodeTimestampedData(List timestampedNodes, baseName = internalEncoder.baseName; } } - JsonRootObject jsonObject = new JsonRootObject(); - jsonObject.setResourceList(entries); - jsonObject.setBaseName(internalEncoder.baseName); + JsonRootObject jsonObject = new JsonRootObject(internalEncoder.baseName, entries, null); try { return encoder.toJsonLwM2m(jsonObject).getBytes(); } catch (LwM2mJsonException e) { diff --git a/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java b/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java index b60f2cbedf..3b79ffbe6e 100644 --- a/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java +++ b/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/json/JsonSerializerTest.java @@ -66,8 +66,7 @@ public void serialize_device_object() throws LwM2mJsonException { JsonArrayEntry elt15 = new JsonArrayEntry("15", null, null, null, "U", null); elements.add(elt15); - JsonRootObject element = new JsonRootObject(); - element.setResourceList(elements); + JsonRootObject element = new JsonRootObject(null, elements, null); String json = LWM2M_JSON_ENCODER_DECODER.toJsonLwM2m(element); LOG.debug(" JSON String: " + json); From c4123f79b2d2c51afcf144952a197e7a518ea86e Mon Sep 17 00:00:00 2001 From: JaroslawLegierski Date: Tue, 26 Nov 2024 14:34:45 +0100 Subject: [PATCH 4/4] SenMLRecord class modifications --- .../codec/senml/LwM2mNodeSenMLEncoder.java | 50 +++++--- .../codec/senml/LwM2mPathSenMLEncoder.java | 4 +- .../org/eclipse/leshan/senml/SenMLRecord.java | 67 ++++------- .../cbor/upokecenter/SenMLCborPackSerDes.java | 107 +++++++++++------- .../json/jackson/SenMLJsonRecordSerDes.java | 32 ++++-- .../core/senml/cbor/AbstractSenMLTest.java | 16 +-- 6 files changed, 149 insertions(+), 127 deletions(-) diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java index 40bfe0996d..4b6b4a83f1 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mNodeSenMLEncoder.java @@ -156,7 +156,12 @@ public byte[] encodeTimestampedData(List timestampedNodes, internalEncoder.records = new ArrayList<>(); timestampedLwM2mNode.getNode().accept(internalEncoder); BigDecimal timestampInSeconds = TimestampUtil.fromInstant(timestampedLwM2mNode.getTimestamp()); - internalEncoder.records.get(0).setBaseTime(timestampInSeconds); + + SenMLRecord record = internalEncoder.records.get(0); + SenMLRecord timestampedrecord = new SenMLRecord(record.getBaseName(), timestampInSeconds, record.getName(), + record.getTime(), record.getNumberValue(), record.getBooleanValue(), record.getObjectLinkValue(), + record.getStringValue(), record.getOpaqueValue()); + internalEncoder.records.set(0, timestampedrecord); pack.addRecords(internalEncoder.records); } @@ -190,7 +195,13 @@ public byte[] encodeTimestampedNodes(String rootPath, TimestampedLwM2mNodes time List records = internalEncoder.records; if (!records.isEmpty()) { - records.get(0).setBaseTime(TimestampUtil.fromInstant(timestamp)); + SenMLRecord record = internalEncoder.records.get(0); + SenMLRecord timestampedrecord = new SenMLRecord(record.getBaseName(), + TimestampUtil.fromInstant(timestamp), record.getName(), record.getTime(), + record.getNumberValue(), record.getBooleanValue(), record.getObjectLinkValue(), + record.getStringValue(), record.getOpaqueValue()); + internalEncoder.records.set(0, timestampedrecord); + pack.addRecords(records); } } @@ -323,8 +334,9 @@ private void lwM2mResourceToSenMLRecord(String recordName, LwM2mResource resourc } private void addSenMLRecord(String recordName, Type valueType, Type expectedType, Object value) { - // Create SenML record - SenMLRecord record = new SenMLRecord(); + // Create SenML record attributes + String recordbasename = null; + String recordname = null; // Compute baseName and name for SenML record String bn = requestPath.toString(); @@ -337,48 +349,54 @@ private void addSenMLRecord(String recordName, Type valueType, Type expectedType // Set basename only for first record if (records.isEmpty()) { - record.setBaseName(rootPath != null ? rootPath + bn : bn); + recordbasename = (rootPath != null ? rootPath + bn : bn); } - record.setName(n); + recordname = n; // Convert value using expected type LwM2mPath lwM2mResourcePath = new LwM2mPath(bn + n); Object convertedValue = converter.convertValue(value, valueType, expectedType, lwM2mResourcePath); - setResourceValue(convertedValue, expectedType, lwM2mResourcePath, record); + SenMLRecord record = setResourceValue(convertedValue, expectedType, lwM2mResourcePath, recordbasename, + recordname); // Add record to the List records.add(record); } - private void setResourceValue(Object value, Type type, LwM2mPath resourcePath, SenMLRecord record) { + private SenMLRecord setResourceValue(Object value, Type type, LwM2mPath resourcePath, String recordBaseName, + String recordName) { LOG.trace("Encoding resource value {} in SenML", value); if (type == null || type == Type.NONE) { throw new CodecException( "Unable to encode value for resource {} without type(probably a executable one)", resourcePath); } + String recordStringValue = null; + Number recordNumberValue = null; + Boolean recordBooleanValue = null; + byte[] recordopaqueValue = null; switch (type) { case STRING: - record.setStringValue((String) value); + recordStringValue = (String) value; break; case INTEGER: case UNSIGNED_INTEGER: case FLOAT: - record.setNumberValue((Number) value); + recordNumberValue = (Number) value; break; case BOOLEAN: - record.setBooleanValue((Boolean) value); + recordBooleanValue = (Boolean) value; break; case TIME: - record.setNumberValue((((Date) value).getTime() / 1000L)); + recordNumberValue = ((Date) value).getTime() / 1000L; break; case OPAQUE: - record.setOpaqueValue((byte[]) value); + recordopaqueValue = (byte[]) value; break; case OBJLNK: try { - record.setStringValue(((ObjectLink) value).encodeToString()); + recordStringValue = ((ObjectLink) value).encodeToString(); } catch (IllegalArgumentException e) { throw new CodecException(e, "Invalid value [%s] for objectLink resource [%s] ", value, resourcePath); @@ -386,11 +404,13 @@ private void setResourceValue(Object value, Type type, LwM2mPath resourcePath, S break; case CORELINK: - record.setStringValue(linkSerializer.serializeCoreLinkFormat((Link[]) value)); + recordStringValue = linkSerializer.serializeCoreLinkFormat((Link[]) value); break; default: throw new CodecException("Invalid value type %s for %s", type, resourcePath); } + return new SenMLRecord(recordBaseName, null, recordName, null, recordNumberValue, recordBooleanValue, null, + recordStringValue, recordopaqueValue); } } } diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mPathSenMLEncoder.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mPathSenMLEncoder.java index 2c72eb2555..3514c7d380 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mPathSenMLEncoder.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/core/node/codec/senml/LwM2mPathSenMLEncoder.java @@ -41,8 +41,8 @@ public byte[] encode(String rootPath, List paths) { // Create SenML Pack SenMLPack pack = new SenMLPack(); for (LwM2mPath path : paths) { - SenMLRecord record = new SenMLRecord(); - record.setName(rootPath != null ? rootPath + path.toString() : path.toString()); + String Name = (rootPath != null ? rootPath + path.toString() : path.toString()); + SenMLRecord record = new SenMLRecord(null, null, Name, null, null, null, null, null, null); pack.addRecord(record); } diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLRecord.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLRecord.java index 2b26353920..f1ee25b1d2 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLRecord.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/SenMLRecord.java @@ -31,17 +31,30 @@ public enum Type { STRING, NUMBER, BOOLEAN, OPAQUE, OBJLNK } - private String baseName = null; - private BigDecimal baseTime; + private final String baseName; + private final BigDecimal baseTime; - private String name; - private BigDecimal time; + private final String name; + private final BigDecimal time; - private Number numberValue; - private Boolean booleanValue; - private String objectLinkValue; - private String stringValue; - private byte[] opaqueValue; + private final Number numberValue; + private final Boolean booleanValue; + private final String objectLinkValue; + private final String stringValue; + private final byte[] opaqueValue; + + public SenMLRecord(String baseName, BigDecimal baseTime, String name, BigDecimal time, Number numberValue, + Boolean booleanValue, String objectLinkValue, String stringValue, byte[] opaqueValue) { + this.baseName = baseName; + this.baseTime = baseTime; + this.name = name; + this.time = time; + this.numberValue = numberValue; + this.booleanValue = booleanValue; + this.objectLinkValue = objectLinkValue; + this.stringValue = stringValue; + this.opaqueValue = opaqueValue; + } public Type getType() { if (booleanValue != null) { @@ -62,10 +75,6 @@ public Type getType() { return null; } - public void setTime(BigDecimal time) { - this.time = time; - } - public BigDecimal getTime() { return time; } @@ -74,46 +83,22 @@ public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public Number getNumberValue() { return numberValue; } - public void setNumberValue(Number numberValue) { - this.numberValue = numberValue; - } - public Boolean getBooleanValue() { return booleanValue; } - public void setBooleanValue(Boolean booleanValue) { - this.booleanValue = booleanValue; - } - public String getObjectLinkValue() { return objectLinkValue; } - public void setObjectLinkValue(String objectLinkValue) { - this.objectLinkValue = objectLinkValue; - } - public String getStringValue() { return stringValue; } - public void setStringValue(String stringValue) { - this.stringValue = stringValue; - } - - public void setOpaqueValue(byte[] opaqueValue) { - this.opaqueValue = opaqueValue; - } - public byte[] getOpaqueValue() { return opaqueValue; } @@ -122,18 +107,10 @@ public String getBaseName() { return baseName; } - public void setBaseName(String baseName) { - this.baseName = baseName; - } - public BigDecimal getBaseTime() { return baseTime; } - public void setBaseTime(BigDecimal baseTime) { - this.baseTime = baseTime; - } - public Object getResourceValue() { if (booleanValue != null) { return booleanValue; diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/cbor/upokecenter/SenMLCborPackSerDes.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/cbor/upokecenter/SenMLCborPackSerDes.java index 7a6f426330..df985868aa 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/cbor/upokecenter/SenMLCborPackSerDes.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/cbor/upokecenter/SenMLCborPackSerDes.java @@ -68,98 +68,120 @@ public SenMLPack deserializeFromCbor(Collection objects) throws SenM } protected SenMLRecord deserializeRecord(CBORObject o) throws SenMLException { - SenMLRecord record = new SenMLRecord(); - - deserializeBaseName(o, record); - deserializeBaseTime(o, record); - deserializeName(o, record); - deserializeTime(o, record); - boolean hasValue = deserializeValue(o, record); - hasValue |= deserializeBooleanValue(o, record); - hasValue |= deserializeStringValue(o, record); - hasValue |= deserializeObjectLinkValue(o, record); - hasValue |= deserializeOpaqueValue(o, record); - - if (!allowNoValue && !hasValue) { + + String recordBaseName = null; + BigDecimal recordBaseTime = null; + String recordName = null; + BigDecimal recordTime = null; + Number recordNumberValue = null; + Boolean recordBooleanValue = null; + String recordStringValue = null; + String recordObjectLinkValue = null; + byte[] recordOpaqueValue = null; + + recordBaseName = deserializeBaseName(o); + recordBaseTime = deserializeBaseTime(o); + recordName = deserializeName(o); + recordTime = deserializeTime(o); + recordNumberValue = deserializeValue(o); + recordBooleanValue = deserializeBooleanValue(o); + recordStringValue = deserializeStringValue(o); + recordObjectLinkValue = deserializeObjectLinkValue(o); + recordOpaqueValue = deserializeOpaqueValue(o); + + if (!allowNoValue && !(recordNumberValue != null || recordBooleanValue != null || recordStringValue != null + || recordObjectLinkValue != null || recordOpaqueValue != null)) { throw new SenMLException( "Invalid SenML record: record must have a value, meaning one of those field must be present v(number:2), vb(number:4), vlo(string:vlo) ,vd(number:8) or vs(number:3): %s", o); } - return record; + return new SenMLRecord(recordBaseName, recordBaseTime, recordName, recordTime, recordNumberValue, + recordBooleanValue, recordObjectLinkValue, recordStringValue, recordOpaqueValue); } - protected void deserializeBaseName(CBORObject o, SenMLRecord record) throws SenMLException { + protected String deserializeBaseName(CBORObject o) throws SenMLException { CBORObject bn = o.get(-2); + String recordBaseName = null; if (bn != null) { - record.setBaseName(deserializeString(bn, "bn")); + recordBaseName = deserializeString(bn, "bn"); } + return recordBaseName; } - protected void deserializeBaseTime(CBORObject o, SenMLRecord record) throws SenMLException { + protected BigDecimal deserializeBaseTime(CBORObject o) throws SenMLException { CBORObject bt = o.get(-3); + BigDecimal recordBaseTime = null; if (bt != null) { - record.setBaseTime(deserializeTime(bt, "bt")); + recordBaseTime = deserializeTime(bt, "bt"); } + return recordBaseTime; } - protected void deserializeName(CBORObject o, SenMLRecord record) throws SenMLException { + protected String deserializeName(CBORObject o) throws SenMLException { CBORObject n = o.get(0); + String recordName = null; if (n != null) { - record.setName(deserializeString(n, "n")); + recordName = deserializeString(n, "n"); } + return recordName; } - protected void deserializeTime(CBORObject o, SenMLRecord record) throws SenMLException { + protected BigDecimal deserializeTime(CBORObject o) throws SenMLException { CBORObject t = o.get(6); + BigDecimal recordTime = null; if (t != null) { - record.setTime(deserializeTime(t, "t")); + recordTime = deserializeTime(t, "t"); } + return recordTime; } - protected boolean deserializeValue(CBORObject o, SenMLRecord record) throws SenMLException { + protected Number deserializeValue(CBORObject o) throws SenMLException { CBORObject v = o.get(2); + Number recordNumberValue = null; if (v != null) { - record.setNumberValue(deserializeNumber(v, "v")); - return true; + recordNumberValue = deserializeNumber(v, "v"); } - return false; + return recordNumberValue; } - protected boolean deserializeBooleanValue(CBORObject o, SenMLRecord record) throws SenMLException { + protected Boolean deserializeBooleanValue(CBORObject o) throws SenMLException { CBORObject vb = o.get(4); + Boolean recordBooleanValue; if (vb != null) { if (!(vb.getType() == CBORType.Boolean)) { throw new SenMLException( "Invalid SenML record : 'boolean' type was expected but was '%s' for 'vb' field", o.getType().toString()); } - record.setBooleanValue(vb.AsBoolean()); - return true; + recordBooleanValue = vb.AsBoolean(); + return recordBooleanValue; } - return false; + return null; } - protected boolean deserializeStringValue(CBORObject o, SenMLRecord record) throws SenMLException { + protected String deserializeStringValue(CBORObject o) throws SenMLException { CBORObject vs = o.get(3); + String recordStringValue; if (vs != null) { - record.setStringValue(deserializeString(vs, "vs")); - return true; + recordStringValue = deserializeString(vs, "vs"); + return recordStringValue; } - return false; + return null; } - protected boolean deserializeObjectLinkValue(CBORObject o, SenMLRecord record) throws SenMLException { + protected String deserializeObjectLinkValue(CBORObject o) throws SenMLException { CBORObject vlo = o.get("vlo"); + String recordObjectLinkValue; if (vlo != null) { - record.setObjectLinkValue(deserializeString(vlo, "vlo")); - return true; + recordObjectLinkValue = deserializeString(vlo, "vlo"); + return recordObjectLinkValue; } - return false; + return null; } - protected boolean deserializeOpaqueValue(CBORObject o, SenMLRecord record) throws SenMLException { + protected byte[] deserializeOpaqueValue(CBORObject o) throws SenMLException { // The RFC says : https://datatracker.ietf.org/doc/html/rfc8428#section-6 // // > Octets in the Data Value are encoded using @@ -168,16 +190,17 @@ protected boolean deserializeOpaqueValue(CBORObject o, SenMLRecord record) throw // So we should check this but there is no way to check this with current cbor library. // https://github.com/peteroupc/CBOR-Java/issues/28 CBORObject vd = o.get(8); + byte[] recordOpaqueValue; if (vd != null) { if (!(vd.getType() == CBORType.ByteString)) { throw new SenMLException( "Invalid SenML record : 'byteString' type was expected but was '%s' for 'vd' field", o.getType().toString()); } - record.setOpaqueValue(vd.GetByteString()); - return true; + recordOpaqueValue = vd.GetByteString(); + return recordOpaqueValue; } - return false; + return null; } protected String deserializeString(CBORObject o, String fieldname) throws SenMLException { diff --git a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/json/jackson/SenMLJsonRecordSerDes.java b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/json/jackson/SenMLJsonRecordSerDes.java index f6da781303..c12b03f319 100644 --- a/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/json/jackson/SenMLJsonRecordSerDes.java +++ b/leshan-lwm2m-core/src/main/java/org/eclipse/leshan/senml/json/jackson/SenMLJsonRecordSerDes.java @@ -128,54 +128,61 @@ else if (value instanceof Float) { public SenMLRecord deserialize(JsonNode o) throws JsonException { if (o == null) return null; - - SenMLRecord record = new SenMLRecord(); + String recordBaseName = null; + BigDecimal recordBaseTime = null; + String recordName = null; + BigDecimal recordTime = null; + Number recordNumberValue = null; + Boolean recordBooleanValue = null; + String recordStringValue = null; + String recordObjectLinkValue = null; + byte[] recordOpaqueValue = null; JsonNode bn = o.get("bn"); if (bn != null && bn.isTextual()) - record.setBaseName(bn.asText()); + recordBaseName = bn.asText(); JsonNode bt = o.get("bt"); if (bt != null && bt.isNumber()) - record.setBaseTime(new BigDecimal(bt.asText())); + recordBaseTime = new BigDecimal(bt.asText()); JsonNode n = o.get("n"); if (n != null && n.isTextual()) - record.setName(n.asText()); + recordName = n.asText(); JsonNode t = o.get("t"); if (t != null && t.isNumber()) - record.setTime(new BigDecimal(t.asText())); + recordTime = new BigDecimal(t.asText()); JsonNode v = o.get("v"); boolean hasValue = false; if (v != null && v.isNumber()) { - record.setNumberValue(v.numberValue()); + recordNumberValue = v.numberValue(); hasValue = true; } JsonNode vb = o.get("vb"); if (vb != null && vb.isBoolean()) { - record.setBooleanValue(vb.asBoolean()); + recordBooleanValue = vb.asBoolean(); hasValue = true; } JsonNode vs = o.get("vs"); if (vs != null && vs.isTextual()) { - record.setStringValue(vs.asText()); + recordStringValue = vs.asText(); hasValue = true; } JsonNode vlo = o.get("vlo"); if (vlo != null && vlo.isTextual()) { - record.setObjectLinkValue(vlo.asText()); + recordObjectLinkValue = vlo.asText(); hasValue = true; } JsonNode vd = o.get("vd"); if (vd != null && vd.isTextual()) { try { - record.setOpaqueValue(base64Decoder.decode(vd.asText())); + recordOpaqueValue = base64Decoder.decode(vd.asText()); } catch (InvalidBase64Exception exception) { throw new JsonException(exception, "Node vd with value '%s' is not in valid Base64 format.", vd.asText()); @@ -186,6 +193,7 @@ public SenMLRecord deserialize(JsonNode o) throws JsonException { if (!allowNoValue && !hasValue) throw new JsonException("Invalid SenML record : record must have a value (v,vb,vlo,vd,vs) : %s", o); - return record; + return new SenMLRecord(recordBaseName, recordBaseTime, recordName, recordTime, recordNumberValue, + recordBooleanValue, recordObjectLinkValue, recordStringValue, recordOpaqueValue); } } diff --git a/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/senml/cbor/AbstractSenMLTest.java b/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/senml/cbor/AbstractSenMLTest.java index 991501554d..1a8175371b 100644 --- a/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/senml/cbor/AbstractSenMLTest.java +++ b/leshan-lwm2m-core/src/test/java/org/eclipse/leshan/core/senml/cbor/AbstractSenMLTest.java @@ -20,9 +20,7 @@ public abstract class AbstractSenMLTest { private void givenResourceWithFloatValue(SenMLPack pack, String n, Number value) { - SenMLRecord elt = new SenMLRecord(); - elt.setName(n); - elt.setNumberValue(value); + SenMLRecord elt = new SenMLRecord(null, null, n, null, value, null, null, null, null); pack.addRecord(elt); } @@ -31,13 +29,11 @@ private void givenResourceWithStringValue(SenMLPack pack, String n, String value } private void givenResourceWithStringValue(SenMLPack pack, String bn, String n, String value) { - SenMLRecord elt = new SenMLRecord(); + String baseName = null; if (bn != null) { - elt.setBaseName(bn); + baseName = bn; } - - elt.setName(n); - elt.setStringValue(value); + SenMLRecord elt = new SenMLRecord(baseName, null, n, null, null, null, null, value, null); pack.addRecord(elt); } @@ -105,9 +101,7 @@ protected SenMLPack givenDeviceObjectInstance() { protected SenMLPack getPackWithSingleOpaqueValue(String path, byte[] value) { SenMLPack pack = new SenMLPack(); - SenMLRecord r = new SenMLRecord(); - r.setBaseName(path); - r.setOpaqueValue(value); + SenMLRecord r = new SenMLRecord(path, null, null, null, null, null, null, null, value); pack.addRecord(r); return pack;