Commit a15e991d23d9bd421fdfa673f170418d5fe2d5fd

Authored by Andrii Shvaika
1 parent 6c1074a8

Added support of BigDecimal to the JsonConverter

@@ -51,6 +51,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre @@ -51,6 +51,7 @@ import org.thingsboard.server.gen.transport.TransportProtos.ValidateBasicMqttCre
51 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg; 51 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceTokenRequestMsg;
52 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg; 52 import org.thingsboard.server.gen.transport.TransportProtos.ValidateDeviceX509CertRequestMsg;
53 53
  54 +import java.math.BigDecimal;
54 import java.util.ArrayList; 55 import java.util.ArrayList;
55 import java.util.HashMap; 56 import java.util.HashMap;
56 import java.util.HashSet; 57 import java.util.HashSet;
@@ -245,12 +246,25 @@ public class JsonConverter { @@ -245,12 +246,25 @@ public class JsonConverter {
245 } 246 }
246 247
247 private static void parseNumericValue(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) { 248 private static void parseNumericValue(List<KvEntry> result, Entry<String, JsonElement> valueEntry, JsonPrimitive value) {
248 - if (value.getAsString().contains(".")) {  
249 - result.add(new DoubleDataEntry(valueEntry.getKey(), value.getAsDouble())); 249 + String valueAsString = value.getAsString();
  250 + String key = valueEntry.getKey();
  251 + if (valueAsString.contains("e") || valueAsString.contains("E")) {
  252 + var bd = new BigDecimal(valueAsString);
  253 + if (bd.stripTrailingZeros().scale() <= 0) {
  254 + try {
  255 + result.add(new LongDataEntry(key, bd.longValueExact()));
  256 + } catch (ArithmeticException e) {
  257 + result.add(new DoubleDataEntry(key, bd.doubleValue()));
  258 + }
  259 + } else {
  260 + result.add(new DoubleDataEntry(key, bd.doubleValue()));
  261 + }
  262 + } else if (valueAsString.contains(".")) {
  263 + result.add(new DoubleDataEntry(key, value.getAsDouble()));
250 } else { 264 } else {
251 try { 265 try {
252 long longValue = Long.parseLong(value.getAsString()); 266 long longValue = Long.parseLong(value.getAsString());
253 - result.add(new LongDataEntry(valueEntry.getKey(), longValue)); 267 + result.add(new LongDataEntry(key, longValue));
254 } catch (NumberFormatException e) { 268 } catch (NumberFormatException e) {
255 throw new JsonSyntaxException("Big integer values are not supported!"); 269 throw new JsonSyntaxException("Big integer values are not supported!");
256 } 270 }
@@ -285,7 +299,8 @@ public class JsonConverter { @@ -285,7 +299,8 @@ public class JsonConverter {
285 return result; 299 return result;
286 } 300 }
287 301
288 - public static JsonObject getJsonObjectForGateway(String deviceName, TransportProtos.GetAttributeResponseMsg responseMsg) { 302 + public static JsonObject getJsonObjectForGateway(String deviceName, TransportProtos.GetAttributeResponseMsg
  303 + responseMsg) {
289 JsonObject result = new JsonObject(); 304 JsonObject result = new JsonObject();
290 result.addProperty("id", responseMsg.getRequestId()); 305 result.addProperty("id", responseMsg.getRequestId());
291 result.addProperty(DEVICE_PROPERTY, deviceName); 306 result.addProperty(DEVICE_PROPERTY, deviceName);
@@ -298,7 +313,8 @@ public class JsonConverter { @@ -298,7 +313,8 @@ public class JsonConverter {
298 return result; 313 return result;
299 } 314 }
300 315
301 - public static JsonObject getJsonObjectForGateway(String deviceName, AttributeUpdateNotificationMsg notificationMsg) { 316 + public static JsonObject getJsonObjectForGateway(String deviceName, AttributeUpdateNotificationMsg
  317 + notificationMsg) {
302 JsonObject result = new JsonObject(); 318 JsonObject result = new JsonObject();
303 result.addProperty(DEVICE_PROPERTY, deviceName); 319 result.addProperty(DEVICE_PROPERTY, deviceName);
304 result.add("data", toJson(notificationMsg)); 320 result.add("data", toJson(notificationMsg));
@@ -446,7 +462,8 @@ public class JsonConverter { @@ -446,7 +462,8 @@ public class JsonConverter {
446 return result; 462 return result;
447 } 463 }
448 464
449 - public static JsonElement toGatewayJson(String deviceName, TransportProtos.ProvisionDeviceResponseMsg responseRequest) { 465 + public static JsonElement toGatewayJson(String deviceName, TransportProtos.ProvisionDeviceResponseMsg
  466 + responseRequest) {
450 JsonObject result = new JsonObject(); 467 JsonObject result = new JsonObject();
451 result.addProperty(DEVICE_PROPERTY, deviceName); 468 result.addProperty(DEVICE_PROPERTY, deviceName);
452 result.add("data", JsonConverter.toJson(responseRequest)); 469 result.add("data", JsonConverter.toJson(responseRequest));
@@ -496,15 +513,18 @@ public class JsonConverter { @@ -496,15 +513,18 @@ public class JsonConverter {
496 return result; 513 return result;
497 } 514 }
498 515
499 - public static Map<Long, List<KvEntry>> convertToTelemetry(JsonElement jsonElement, long systemTs) throws JsonSyntaxException { 516 + public static Map<Long, List<KvEntry>> convertToTelemetry(JsonElement jsonElement, long systemTs) throws
  517 + JsonSyntaxException {
500 return convertToTelemetry(jsonElement, systemTs, false); 518 return convertToTelemetry(jsonElement, systemTs, false);
501 } 519 }
502 520
503 - public static Map<Long, List<KvEntry>> convertToSortedTelemetry(JsonElement jsonElement, long systemTs) throws JsonSyntaxException { 521 + public static Map<Long, List<KvEntry>> convertToSortedTelemetry(JsonElement jsonElement, long systemTs) throws
  522 + JsonSyntaxException {
504 return convertToTelemetry(jsonElement, systemTs, true); 523 return convertToTelemetry(jsonElement, systemTs, true);
505 } 524 }
506 525
507 - public static Map<Long, List<KvEntry>> convertToTelemetry(JsonElement jsonElement, long systemTs, boolean sorted) throws JsonSyntaxException { 526 + public static Map<Long, List<KvEntry>> convertToTelemetry(JsonElement jsonElement, long systemTs, boolean sorted) throws
  527 + JsonSyntaxException {
508 Map<Long, List<KvEntry>> result = sorted ? new TreeMap<>() : new HashMap<>(); 528 Map<Long, List<KvEntry>> result = sorted ? new TreeMap<>() : new HashMap<>();
509 convertToTelemetry(jsonElement, systemTs, result, null); 529 convertToTelemetry(jsonElement, systemTs, result, null);
510 return result; 530 return result;
@@ -574,7 +594,8 @@ public class JsonConverter { @@ -574,7 +594,8 @@ public class JsonConverter {
574 .build(); 594 .build();
575 } 595 }
576 596
577 - private static TransportProtos.ProvisionDeviceCredentialsMsg buildProvisionDeviceCredentialsMsg(String provisionKey, String provisionSecret) { 597 + private static TransportProtos.ProvisionDeviceCredentialsMsg buildProvisionDeviceCredentialsMsg(String
  598 + provisionKey, String provisionSecret) {
578 return TransportProtos.ProvisionDeviceCredentialsMsg.newBuilder() 599 return TransportProtos.ProvisionDeviceCredentialsMsg.newBuilder()
579 .setProvisionDeviceKey(provisionKey) 600 .setProvisionDeviceKey(provisionKey)
580 .setProvisionDeviceSecret(provisionSecret) 601 .setProvisionDeviceSecret(provisionSecret)
  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 +
  17 +import com.google.gson.JsonParser;
  18 +import org.junit.Assert;
  19 +import org.junit.Test;
  20 +import org.junit.runner.RunWith;
  21 +import org.mockito.junit.MockitoJUnitRunner;
  22 +import org.thingsboard.server.common.transport.adaptor.JsonConverter;
  23 +
  24 +@RunWith(MockitoJUnitRunner.class)
  25 +public class JsonConverterTest {
  26 +
  27 + private static final JsonParser JSON_PARSER = new JsonParser();
  28 +
  29 + @Test
  30 + public void testParseBigDecimalAsLong() {
  31 + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1E+1}"), 0L);
  32 + Assert.assertEquals(10L, result.get(0L).get(0).getLongValue().get().longValue());
  33 + }
  34 +
  35 + @Test
  36 + public void testParseBigDecimalAsDouble() {
  37 + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 101E-1}"), 0L);
  38 + Assert.assertEquals(10.1, result.get(0L).get(0).getDoubleValue().get(), 0.0);
  39 + }
  40 +
  41 + @Test
  42 + public void testParseAsDouble() {
  43 + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 1.1}"), 0L);
  44 + Assert.assertEquals(1.1, result.get(0L).get(0).getDoubleValue().get(), 0.0);
  45 + }
  46 +
  47 + @Test
  48 + public void testParseAsLong() {
  49 + var result = JsonConverter.convertToTelemetry(JSON_PARSER.parse("{\"meterReadingDelta\": 11}"), 0L);
  50 + Assert.assertEquals(11L, result.get(0L).get(0).getLongValue().get().longValue());
  51 + }
  52 +
  53 +}
@@ -93,12 +93,17 @@ public class CalculateDeltaNode implements TbNode { @@ -93,12 +93,17 @@ public class CalculateDeltaNode implements TbNode {
93 return; 93 return;
94 } 94 }
95 95
  96 +
96 if (config.getRound() != null) { 97 if (config.getRound() != null) {
97 delta = delta.setScale(config.getRound(), RoundingMode.HALF_UP); 98 delta = delta.setScale(config.getRound(), RoundingMode.HALF_UP);
98 } 99 }
99 100
100 ObjectNode result = (ObjectNode) json; 101 ObjectNode result = (ObjectNode) json;
101 - result.put(config.getOutputValueKey(), delta); 102 + if (delta.stripTrailingZeros().scale() > 0) {
  103 + result.put(config.getOutputValueKey(), delta.doubleValue());
  104 + } else {
  105 + result.put(config.getOutputValueKey(), delta.longValueExact());
  106 + }
102 107
103 if (config.isAddPeriodBetweenMsgs()) { 108 if (config.isAddPeriodBetweenMsgs()) {
104 long period = previousData != null ? currentTs - previousData.ts : 0; 109 long period = previousData != null ? currentTs - previousData.ts : 0;