Merge pull request #11830 from dashevchenko/efentoPulseCounterFix
Fixed accumulative pulse counter total value calculation
This commit is contained in:
commit
0d0c2f6101
@ -53,8 +53,6 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -80,6 +78,10 @@ import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils
|
|||||||
import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.WATER_METER_ACC_MINOR_METADATA_FACTOR;
|
import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.WATER_METER_ACC_MINOR_METADATA_FACTOR;
|
||||||
import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.isBinarySensor;
|
import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.isBinarySensor;
|
||||||
import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.isSensorError;
|
import static org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils.isSensorError;
|
||||||
|
import static org.thingsboard.server.transport.coap.efento.utils.PulseCounterType.ELEC_METER_ACC;
|
||||||
|
import static org.thingsboard.server.transport.coap.efento.utils.PulseCounterType.PULSE_CNT_ACC;
|
||||||
|
import static org.thingsboard.server.transport.coap.efento.utils.PulseCounterType.PULSE_CNT_ACC_WIDE;
|
||||||
|
import static org.thingsboard.server.transport.coap.efento.utils.PulseCounterType.WATER_CNT_ACC;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
||||||
@ -300,12 +302,6 @@ public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valuesMap.values().forEach(jsonObject -> {
|
|
||||||
for (PulseCounterType pulseCounterType : PulseCounterType.values()) {
|
|
||||||
calculatePulseCounterTotalValue(jsonObject, pulseCounterType);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (CollectionUtils.isEmpty(valuesMap)) {
|
if (CollectionUtils.isEmpty(valuesMap)) {
|
||||||
throw new IllegalStateException("[" + sessionId + "]: Failed to collect Efento measurements, reason, values map is empty!");
|
throw new IllegalStateException("[" + sessionId + "]: Failed to collect Efento measurements, reason, values map is empty!");
|
||||||
}
|
}
|
||||||
@ -338,7 +334,7 @@ public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
|||||||
values.addProperty("pulse_cnt_" + channelNumber, (double) (startPoint + sampleOffset));
|
values.addProperty("pulse_cnt_" + channelNumber, (double) (startPoint + sampleOffset));
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_IAQ:
|
case MEASUREMENT_TYPE_IAQ:
|
||||||
addPulseCounterProperties(values, "iaq_", channelNumber, startPoint + sampleOffset, IAQ_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, "iaq_", channelNumber, startPoint + sampleOffset, IAQ_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_ELECTRICITY_METER:
|
case MEASUREMENT_TYPE_ELECTRICITY_METER:
|
||||||
values.addProperty("watt_hour_" + channelNumber, (double) (startPoint + sampleOffset));
|
values.addProperty("watt_hour_" + channelNumber, (double) (startPoint + sampleOffset));
|
||||||
@ -356,25 +352,25 @@ public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
|||||||
values.addProperty("distance_mm_" + channelNumber, (double) (startPoint + sampleOffset));
|
values.addProperty("distance_mm_" + channelNumber, (double) (startPoint + sampleOffset));
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_WATER_METER_ACC_MINOR:
|
case MEASUREMENT_TYPE_WATER_METER_ACC_MINOR:
|
||||||
addPulseCounterProperties(values, "water_cnt_acc_minor_", channelNumber, startPoint + sampleOffset, WATER_METER_ACC_MINOR_METADATA_FACTOR);
|
calculateAccPulseCounterTotalValue(values, WATER_CNT_ACC , channelNumber, startPoint + sampleOffset, WATER_METER_ACC_MINOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR:
|
case MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR:
|
||||||
addPulseCounterProperties(values, "water_cnt_acc_major_", channelNumber, startPoint + sampleOffset, WATER_METER_ACC_MAJOR_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, WATER_CNT_ACC.getPrefix(), channelNumber, startPoint + sampleOffset, WATER_METER_ACC_MAJOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_HUMIDITY_ACCURATE:
|
case MEASUREMENT_TYPE_HUMIDITY_ACCURATE:
|
||||||
values.addProperty("humidity_relative_" + channelNumber, (double) (startPoint + sampleOffset) / 10f);
|
values.addProperty("humidity_relative_" + channelNumber, (double) (startPoint + sampleOffset) / 10f);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_STATIC_IAQ:
|
case MEASUREMENT_TYPE_STATIC_IAQ:
|
||||||
addPulseCounterProperties(values, "static_iaq_", channelNumber, startPoint + sampleOffset, STATIC_IAQ_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, "static_iaq_", channelNumber, startPoint + sampleOffset, STATIC_IAQ_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_CO2_GAS:
|
case MEASUREMENT_TYPE_CO2_GAS:
|
||||||
addPulseCounterProperties(values, "co2_gas_", channelNumber, startPoint + sampleOffset, CO2_GAS_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, "co2_gas_", channelNumber, startPoint + sampleOffset, CO2_GAS_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_CO2_EQUIVALENT:
|
case MEASUREMENT_TYPE_CO2_EQUIVALENT:
|
||||||
addPulseCounterProperties(values, "co2_", channelNumber, startPoint + sampleOffset, CO2_EQUIVALENT_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, "co2_", channelNumber, startPoint + sampleOffset, CO2_EQUIVALENT_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_BREATH_VOC:
|
case MEASUREMENT_TYPE_BREATH_VOC:
|
||||||
addPulseCounterProperties(values, "breath_voc_", channelNumber, startPoint + sampleOffset, BREATH_VOC_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, "breath_voc_", channelNumber, startPoint + sampleOffset, BREATH_VOC_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_PERCENTAGE:
|
case MEASUREMENT_TYPE_PERCENTAGE:
|
||||||
values.addProperty("percentage_" + channelNumber, (double) (startPoint + sampleOffset) / 100f);
|
values.addProperty("percentage_" + channelNumber, (double) (startPoint + sampleOffset) / 100f);
|
||||||
@ -386,22 +382,22 @@ public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
|||||||
values.addProperty("current_" + channelNumber, (double) (startPoint + sampleOffset) / 100f);
|
values.addProperty("current_" + channelNumber, (double) (startPoint + sampleOffset) / 100f);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR:
|
case MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR:
|
||||||
addPulseCounterProperties(values, "pulse_cnt_acc_minor_", channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_MINOR_METADATA_FACTOR);
|
calculateAccPulseCounterTotalValue(values, PULSE_CNT_ACC , channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_MINOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR:
|
case MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR:
|
||||||
addPulseCounterProperties(values, "pulse_cnt_acc_major_", channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_MAJOR_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, PULSE_CNT_ACC.getPrefix(), channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_MAJOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR:
|
case MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR:
|
||||||
addPulseCounterProperties(values, "elec_meter_acc_minor_", channelNumber, startPoint + sampleOffset, ELEC_METER_ACC_MINOR_METADATA_FACTOR);
|
calculateAccPulseCounterTotalValue(values, ELEC_METER_ACC , channelNumber, startPoint + sampleOffset, ELEC_METER_ACC_MINOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR:
|
case MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR:
|
||||||
addPulseCounterProperties(values, "elec_meter_acc_major_", channelNumber, startPoint + sampleOffset, ELEC_METER_ACC_MAJOR_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, ELEC_METER_ACC.getPrefix(), channelNumber, startPoint + sampleOffset, ELEC_METER_ACC_MAJOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR:
|
case MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR:
|
||||||
addPulseCounterProperties(values, "pulse_cnt_acc_wide_minor_", channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_WIDE_MINOR_METADATA_FACTOR);
|
calculateAccPulseCounterTotalValue(values, PULSE_CNT_ACC_WIDE , channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_WIDE_MINOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR:
|
case MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR:
|
||||||
addPulseCounterProperties(values, "pulse_cnt_acc_wide_major_", channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_WIDE_MAJOR_METADATA_FACTOR);
|
addPropertiesForMeasurementTypeWithMetadataFactor(values, PULSE_CNT_ACC_WIDE.getPrefix(), channelNumber, startPoint + sampleOffset, PULSE_CNT_ACC_WIDE_MAJOR_METADATA_FACTOR);
|
||||||
break;
|
break;
|
||||||
case MEASUREMENT_TYPE_CURRENT_PRECISE:
|
case MEASUREMENT_TYPE_CURRENT_PRECISE:
|
||||||
values.addProperty("current_precise_" + channelNumber, (double) (startPoint + sampleOffset) / 1000f);
|
values.addProperty("current_precise_" + channelNumber, (double) (startPoint + sampleOffset) / 1000f);
|
||||||
@ -416,17 +412,20 @@ public class CoapEfentoTransportResource extends AbstractCoapTransportResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPulseCounterProperties(JsonObject values, String prefix, int channelNumber, int value, int metadataFactor) {
|
private void addPropertiesForMeasurementTypeWithMetadataFactor(JsonObject values, String prefix, int channelNumber, int value, int metadataFactor) {
|
||||||
values.addProperty(prefix + channelNumber, value / metadataFactor);
|
values.addProperty(prefix + channelNumber, value / metadataFactor);
|
||||||
values.addProperty(prefix + "metadata_" + channelNumber, value % metadataFactor);
|
values.addProperty(prefix + "metadata_" + channelNumber, value % metadataFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculatePulseCounterTotalValue(JsonObject value, PulseCounterType pulseCounterType) {
|
private void calculateAccPulseCounterTotalValue(JsonObject values, PulseCounterType pulseCounterType, int channelNumber, int value, int metadataFactor) {
|
||||||
Set<String> keys = value.keySet();
|
int minorValue = value / metadataFactor;
|
||||||
Optional<String> major = keys.stream().filter(s -> s.startsWith(pulseCounterType.getPrefix() + "major_")).findAny();
|
int majorChannel = value % metadataFactor + 1;
|
||||||
Optional<String> minor = keys.stream().filter(s -> s.startsWith(pulseCounterType.getPrefix() + "minor_")).findAny();
|
String majorPropertyKey = pulseCounterType.getPrefix() + majorChannel;
|
||||||
if (major.isPresent() && minor.isPresent()) {
|
JsonElement majorProperty = values.get(majorPropertyKey);
|
||||||
value.addProperty(pulseCounterType.getPrefix() + "total_value", value.get(major.get()).getAsInt() * pulseCounterType.getMajorResolution() + value.get(minor.get()).getAsInt());
|
if (majorProperty != null) {
|
||||||
|
int totalValue = majorProperty.getAsInt() * pulseCounterType.getMajorResolution() + minorValue;
|
||||||
|
values.addProperty(pulseCounterType.getPrefix() + "total_" + channelNumber, totalValue);
|
||||||
|
values.remove(majorPropertyKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,7 @@ import org.thingsboard.server.transport.coap.efento.utils.CoapEfentoUtils;
|
|||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@ -172,7 +173,7 @@ class CoapEfentoTransportResourceTest {
|
|||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource
|
@MethodSource
|
||||||
void checkPulseCounterSensors(MeasurementType minorType, List<Integer> minorSampleOffsets, MeasurementType majorType, List<Integer> majorSampleOffsets,
|
void checkPulseCounterSensors(MeasurementType minorType, List<Integer> minorSampleOffsets, MeasurementType majorType, List<Integer> majorSampleOffsets,
|
||||||
String propertyPrefix, double expectedValue) {
|
String totalPropertyName, double expectedTotalValue) {
|
||||||
long tsInSec = Instant.now().getEpochSecond();
|
long tsInSec = Instant.now().getEpochSecond();
|
||||||
ProtoMeasurements measurements = ProtoMeasurements.newBuilder()
|
ProtoMeasurements measurements = ProtoMeasurements.newBuilder()
|
||||||
.setSerialNum(integerToByteString(1234))
|
.setSerialNum(integerToByteString(1234))
|
||||||
@ -184,34 +185,34 @@ class CoapEfentoTransportResourceTest {
|
|||||||
.setNextTransmissionAt(1000)
|
.setNextTransmissionAt(1000)
|
||||||
.setTransferReason(0)
|
.setTransferReason(0)
|
||||||
.setHash(0)
|
.setHash(0)
|
||||||
.addAllChannels(List.of(MeasurementsProtos.ProtoChannel.newBuilder()
|
.addAllChannels(Arrays.asList(MeasurementsProtos.ProtoChannel.newBuilder()
|
||||||
.setType(minorType)
|
|
||||||
.setTimestamp(Math.toIntExact(tsInSec))
|
|
||||||
.addAllSampleOffsets(minorSampleOffsets)
|
|
||||||
.build(),
|
|
||||||
MeasurementsProtos.ProtoChannel.newBuilder()
|
|
||||||
.setType(majorType)
|
.setType(majorType)
|
||||||
.setTimestamp(Math.toIntExact(tsInSec))
|
.setTimestamp(Math.toIntExact(tsInSec))
|
||||||
.addAllSampleOffsets(majorSampleOffsets)
|
.addAllSampleOffsets(majorSampleOffsets)
|
||||||
|
.build(),
|
||||||
|
MeasurementsProtos.ProtoChannel.newBuilder()
|
||||||
|
.setType(minorType)
|
||||||
|
.setTimestamp(Math.toIntExact(tsInSec))
|
||||||
|
.addAllSampleOffsets(minorSampleOffsets)
|
||||||
.build()))
|
.build()))
|
||||||
.build();
|
.build();
|
||||||
List<CoapEfentoTransportResource.EfentoTelemetry> efentoMeasurements = coapEfentoTransportResource.getEfentoMeasurements(measurements, UUID.randomUUID());
|
List<CoapEfentoTransportResource.EfentoTelemetry> efentoMeasurements = coapEfentoTransportResource.getEfentoMeasurements(measurements, UUID.randomUUID());
|
||||||
assertThat(efentoMeasurements).hasSize(1);
|
assertThat(efentoMeasurements).hasSize(1);
|
||||||
assertThat(efentoMeasurements.get(0).getTs()).isEqualTo(tsInSec * 1000);
|
assertThat(efentoMeasurements.get(0).getTs()).isEqualTo(tsInSec * 1000);
|
||||||
assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get(propertyPrefix + "_total_value").getAsDouble()).isEqualTo(expectedValue);
|
assertThat(efentoMeasurements.get(0).getValues().getAsJsonObject().get(totalPropertyName + "_2").getAsDouble()).isEqualTo(expectedTotalValue);
|
||||||
checkDefaultMeasurements(measurements, efentoMeasurements, 180, false);
|
checkDefaultMeasurements(measurements, efentoMeasurements, 180, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Arguments> checkPulseCounterSensors() {
|
private static Stream<Arguments> checkPulseCounterSensors() {
|
||||||
return Stream.of(
|
return Stream.of(
|
||||||
Arguments.of(MEASUREMENT_TYPE_WATER_METER_ACC_MINOR, List.of(125), MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR,
|
Arguments.of(MEASUREMENT_TYPE_WATER_METER_ACC_MINOR, List.of(15*6), MEASUREMENT_TYPE_WATER_METER_ACC_MAJOR,
|
||||||
List.of(2500), "water_cnt_acc", 62520.0),
|
List.of(625*4), "water_cnt_acc_total", 625.0*100 + 15),
|
||||||
Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR, List.of(180), MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR,
|
Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_MINOR, List.of(10*6), MEASUREMENT_TYPE_PULSE_CNT_ACC_MAJOR,
|
||||||
List.of(1200), "pulse_cnt_acc", 300030.0),
|
List.of(300*4), "pulse_cnt_acc_total", 300.0*1000 + 10),
|
||||||
Arguments.of(MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR, List.of(550), MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR,
|
Arguments.of(MEASUREMENT_TYPE_ELEC_METER_ACC_MINOR, List.of(12*6), MEASUREMENT_TYPE_ELEC_METER_ACC_MAJOR,
|
||||||
List.of(5500), "elec_meter_acc", 1375091.0),
|
List.of(100*4), "elec_meter_acc_total", 100.0*1000 + 12),
|
||||||
Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR, List.of(230), MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR,
|
Arguments.of(MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MINOR, List.of(13*6), MEASUREMENT_TYPE_PULSE_CNT_ACC_WIDE_MAJOR,
|
||||||
List.of(1700), "pulse_cnt_acc_wide", 425000038.0));
|
List.of(440*4), "pulse_cnt_acc_wide_total", 440.0*1000000 + 13));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user