97 lines
3.1 KiB
Java
97 lines
3.1 KiB
Java
package de.ph87.data.message.handler;
|
|
|
|
import com.fasterxml.jackson.annotation.*;
|
|
import com.fasterxml.jackson.databind.*;
|
|
import com.fasterxml.jackson.databind.annotation.*;
|
|
import de.ph87.data.message.*;
|
|
import de.ph87.data.series.varying.*;
|
|
import de.ph87.data.value.Value;
|
|
import de.ph87.data.value.*;
|
|
import lombok.*;
|
|
import lombok.extern.slf4j.*;
|
|
import org.springframework.context.*;
|
|
import org.springframework.stereotype.*;
|
|
|
|
import java.time.*;
|
|
import java.util.*;
|
|
import java.util.regex.*;
|
|
import java.util.stream.*;
|
|
|
|
@Slf4j
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
public class EspHomeHandler implements IMessageHandler {
|
|
|
|
private static final Pattern REGEX = Pattern.compile("^(?<area>\\w+)/sensor/(?<property>\\w+)$");
|
|
|
|
private final ObjectMapper objectMapper;
|
|
|
|
private final ApplicationEventPublisher applicationEventPublisher;
|
|
|
|
@Override
|
|
public void handle(@NonNull final Message message) throws Exception {
|
|
final Matcher matcher = REGEX.matcher(message.topic);
|
|
if (!matcher.find()) {
|
|
return;
|
|
}
|
|
final String area = matcher.group("area");
|
|
final String property = propertyReplace(matcher.group("property"));
|
|
final String name = "%s/%s".formatted(area, property.replace("_", "/"));
|
|
final Unit targetUnit = switch (property) {
|
|
case "iaq" -> Unit.IAQ;
|
|
case "iaq_co2" -> Unit.IAQ_CO2_EQUIVALENT;
|
|
case "iaq_voc" -> Unit.IAQ_VOC_EQUIVALENT;
|
|
case "pressure" -> Unit.PRESSURE_HPA;
|
|
case "temperature" -> Unit.TEMPERATURE_C;
|
|
case "humidity_relative" -> Unit.HUMIDITY_RELATIVE_PERCENT;
|
|
case "humidity_absolute" -> Unit.HUMIDITY_ABSOLUTE_GM3;
|
|
case "sun" -> Unit.SUN_DC;
|
|
default -> null;
|
|
};
|
|
if (targetUnit == null) {
|
|
log.debug("Skipping property: {}", name);
|
|
return;
|
|
}
|
|
final Inbound inbound = objectMapper.readValue(message.payload, Inbound.class);
|
|
final Unit unitFromPayload = inbound.units.stream().filter(ufp -> ufp.base == targetUnit.base).findFirst().orElse(null);
|
|
if (unitFromPayload == null) {
|
|
log.error("Unit mismatch: fromTopic={}, fromPayload=[{}]", targetUnit, inbound.getUnits().stream().map(Enum::name).collect(Collectors.joining(",")));
|
|
return;
|
|
}
|
|
final Value value = new Value(inbound.value, unitFromPayload);
|
|
applicationEventPublisher.publishEvent(new VaryingInbound(name, inbound.date, value.as(targetUnit)));
|
|
}
|
|
|
|
private String propertyReplace(final String property) {
|
|
if ("iaq_co2_equivalent".equals(property)) {
|
|
return "iaq_co2";
|
|
}
|
|
if ("iaq_equivalent_voc".equals(property)) {
|
|
return "iaq_voc";
|
|
}
|
|
return property;
|
|
}
|
|
|
|
@Getter
|
|
@ToString
|
|
private static class Inbound {
|
|
|
|
@NonNull
|
|
public final ZonedDateTime date;
|
|
|
|
public final double value;
|
|
|
|
@NonNull
|
|
@JsonDeserialize(using = Unit.ListDeserializer.class)
|
|
public final List<Unit> units;
|
|
|
|
public Inbound(final long timestamp, final double value, @JsonProperty("unit") @NonNull final List<Unit> units) {
|
|
this.date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
|
|
this.value = value;
|
|
this.units = units;
|
|
}
|
|
|
|
}
|
|
|
|
}
|