Data2025/src/main/java/de/ph87/data/topic/parser/TasmotaSmartMeter.java

95 lines
3.4 KiB
Java

package de.ph87.data.topic.parser;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.ph87.data.series.data.delta.DeltaService;
import de.ph87.data.series.data.varying.VaryingService;
import de.ph87.data.topic.TopicDto;
import de.ph87.data.topic.TopicParserAbstract;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import tools.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
@Slf4j
@Service
public class TasmotaSmartMeter extends TopicParserAbstract<TasmotaSmartMeter.Dto> {
public TasmotaSmartMeter(@NonNull final ObjectMapper mapper, @NonNull final DeltaService deltaService, @NonNull final VaryingService varyingService) {
super(Dto.class, mapper, deltaService, varyingService);
}
@Override
protected void handle2(final @NonNull TopicDto topic, @NonNull final Dto dto) {
delta(topic.series0, dto.meter.number, dto.date, dto.meter.purchaseKWh);
delta(topic.series1, dto.meter.number, dto.date, dto.meter.deliverKWh);
varying(topic.series2, dto.date, Math.max(0, dto.meter.powerW));
varying(topic.series3, dto.date, Math.max(0, -dto.meter.powerW));
}
public static class Dto {
@NonNull
public final ZonedDateTime date;
@NonNull
public final Meter meter;
public Dto(
@JsonProperty(value = "Time", required = true) @NonNull final String localDateTimeString,
@JsonProperty(value = "meter", required = true) @NonNull final Meter meter
) {
this.date = ZonedDateTime.of(LocalDateTime.parse(localDateTimeString), ZoneId.systemDefault());
this.meter = meter;
}
public static class Meter {
@NonNull
public final String number;
public final double purchaseKWh;
public final double deliverKWh;
public final double powerW;
public Meter(
@JsonProperty(value = "number", required = true) @NonNull final String number,
@JsonProperty(value = "energy_purchased_kwh", required = true) final double purchaseWh,
@JsonProperty(value = "energy_delivered_kwh", required = true) final double deliverWh,
@JsonProperty(value = "power_w", required = true) final double powerW
) {
this.number = parseMeterNumber(number);
this.purchaseKWh = purchaseWh;
this.deliverKWh = deliverWh;
this.powerW = powerW;
}
@NonNull
private static String parseMeterNumber(@NonNull final String input) {
if (input.isEmpty()) {
throw new NumberFormatException("Cannot parse Meter number: No Hex-chars read.");
}
if (input.length() % 2 != 0) {
throw new NumberFormatException("Cannot parse Meter number: Hex-char count must be multiple of 2.");
}
final int length = Integer.parseInt(input.substring(0, 2), 16);
if (input.length() != length * 2) {
throw new NumberFormatException("Cannot parse Meter number: Invalid length");
}
final int type = Integer.parseInt(input.substring(2, 4), 16);
final String name = "" + (char) Integer.parseInt(input.substring(4, 6), 16) + (char) Integer.parseInt(input.substring(6, 8), 16) + (char) Integer.parseInt(input.substring(8, 10), 16);
final int number = Integer.parseInt(input.substring(10), 16);
return "%d%s%s".formatted(type, name, number);
}
}
}
}