From 4560f4966b31591184049a816377e7a9b302dfe3 Mon Sep 17 00:00:00 2001 From: Matt Jones Date: Wed, 25 Sep 2024 20:03:44 -0500 Subject: [PATCH] feat: add a controller to check multiple sensors and control humidity with a smart switch --- .../MultipointDehumidifierController.java | 105 ++++++++++++++++++ .../calendar/GCalendarController.java | 8 +- 2 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/bigboxer23/lights/controllers/aggregate/MultipointDehumidifierController.java diff --git a/src/main/java/com/bigboxer23/lights/controllers/aggregate/MultipointDehumidifierController.java b/src/main/java/com/bigboxer23/lights/controllers/aggregate/MultipointDehumidifierController.java new file mode 100644 index 0000000..a969a85 --- /dev/null +++ b/src/main/java/com/bigboxer23/lights/controllers/aggregate/MultipointDehumidifierController.java @@ -0,0 +1,105 @@ +package com.bigboxer23.lights.controllers.aggregate; + +import com.bigboxer23.lights.controllers.switchbot.SwitchBotController; +import com.bigboxer23.switch_bot.IDeviceCommands; +import com.bigboxer23.switch_bot.data.Device; +import com.bigboxer23.utils.command.RetryingCommand; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * This component takes one or more sensors (switchbot) and takes an average humidity reading. It + * will turn on or off a switchbot smart switch which should be connected to a dehumidifier based on + * the reading and defined low/high values of RH + */ +@Component +public class MultipointDehumidifierController implements InitializingBean { + private static final Logger logger = LoggerFactory.getLogger(MultipointDehumidifierController.class); + + @Value("${dehumidifierId}") + private String dehumidifierId; + + @Value("${sensorIds}") + private String sensorIdString; + + @Value("${lowHumidity}") + private float lowHumidity; + + @Value("${highHumidity}") + private float highHumidity; + + private List sensorIds; + + private final SwitchBotController switchbotController; + + public MultipointDehumidifierController(SwitchBotController switchbotController) { + this.switchbotController = switchbotController; + logger.info("MultipointDehumidifierController initialized"); + } + + @Override + public void afterPropertiesSet() throws Exception { + sensorIds = Arrays.stream(sensorIdString.split(",")).map(String::trim).toList(); + } + + @Scheduled(fixedDelay = 300000) // 5min + private void checkHumidity() throws IOException { + double humidity = getHumidity(); + logger.info("humidity: " + humidity); + Device dehumidifier = RetryingCommand.execute( + () -> switchbotController.getSwitchbotAPI().getDeviceApi().getDeviceStatus(dehumidifierId), + dehumidifierId); + if (humidity > highHumidity && !dehumidifier.isPowerOn()) { + logger.info("turning on dehumidifier " + dehumidifierId); + RetryingCommand.execute( + () -> { + switchbotController + .getSwitchbotAPI() + .getDeviceApi() + .sendDeviceControlCommands(dehumidifierId, IDeviceCommands.PLUG_MINI_ON); + return null; + }, + dehumidifierId); + } else if (humidity < lowHumidity && dehumidifier.isPowerOn()) { + logger.info("turning off dehumidifier " + dehumidifierId); + RetryingCommand.execute( + () -> { + switchbotController + .getSwitchbotAPI() + .getDeviceApi() + .sendDeviceControlCommands(dehumidifierId, IDeviceCommands.PLUG_MINI_OFF); + return null; + }, + dehumidifierId); + } + } + + private double getHumidity() { + logger.debug("checking humidity"); + return sensorIds.stream() + .map(id -> { + try { + return RetryingCommand.execute( + () -> switchbotController + .getSwitchbotAPI() + .getDeviceApi() + .getDeviceStatus(id), + id); + } catch (IOException e) { + logger.error("", e); + throw new RuntimeException(e); + } + }) + .map(Device::getHumidity) + .mapToDouble(a -> a) + .average() + .orElse(-1); + } +} diff --git a/src/main/java/com/bigboxer23/lights/controllers/calendar/GCalendarController.java b/src/main/java/com/bigboxer23/lights/controllers/calendar/GCalendarController.java index 038161f..0d6c477 100644 --- a/src/main/java/com/bigboxer23/lights/controllers/calendar/GCalendarController.java +++ b/src/main/java/com/bigboxer23/lights/controllers/calendar/GCalendarController.java @@ -29,10 +29,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.List; +import java.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -163,7 +160,8 @@ private boolean findLateEvents(Events events) { .truncatedTo(ChronoUnit.MINUTES) .withMinute(30) .withHour(22) - .atZone(ZoneId.of(event.getEnd().getTimeZone())) + .atZone(ZoneId.of(Optional.ofNullable(event.getEnd().getTimeZone()) + .orElseGet(() -> ZoneId.systemDefault().getId()))) .toInstant()); boolean found = event.getEnd() != null && event.getEnd().getDateTime() != null