package de.ph87.homeautomation; import com.luckycatlabs.sunrisesunset.Zenith; import de.ph87.homeautomation.channel.Channel; import de.ph87.homeautomation.device.DeviceRepository; import de.ph87.homeautomation.device.DeviceWriteService; import de.ph87.homeautomation.device.devices.DeviceDto; import de.ph87.homeautomation.knx.group.KnxGroup; import de.ph87.homeautomation.knx.group.KnxGroupReadService; import de.ph87.homeautomation.logic.Logic; import de.ph87.homeautomation.logic.LogicOperator; import de.ph87.homeautomation.logic.LogicRepository; import de.ph87.homeautomation.logic.LogicWriter; import de.ph87.homeautomation.property.Property; import de.ph87.homeautomation.property.PropertyRepository; import de.ph87.homeautomation.property.PropertyType; import de.ph87.homeautomation.scene.SceneDto; import de.ph87.homeautomation.scene.SceneRepository; import de.ph87.homeautomation.scene.SceneWriteService; import de.ph87.homeautomation.schedule.Schedule; import de.ph87.homeautomation.schedule.ScheduleRepository; import de.ph87.homeautomation.schedule.entry.ScheduleEntry; import de.ph87.homeautomation.schedule.entry.ScheduleEntryType; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.ZonedDateTime; import java.util.Arrays; import java.util.HashSet; @SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment", "RedundantSuppression"}) @Slf4j @Service @Transactional @RequiredArgsConstructor public class DemoDataService { private static final int MIN30 = 30 * 60; private static final Zenith BETWEEN_OFFICIAL_AND_CIVIL = new Zenith(93.0); private final ScheduleRepository scheduleRepository; private final DeviceWriteService deviceWriteService; private final DeviceRepository deviceRepository; private final PropertyRepository propertyRepository; private final KnxGroupReadService knxGroupReadService; private final SceneRepository sceneRepository; private final SceneWriteService sceneWriteService; private final LogicWriter logicWriter; private final LogicRepository logicRepository; private final Config config; public void insertDemoData() { if (!config.isInsertDemoData()) { return; } final Property erdgeschoss = createProperty("Erdgeschoss", PropertyType.BOOLEAN, knx(0, 4, 2), null); final Property erdgeschoss_szene = createProperty("Erdgeschoss Szene", PropertyType.SCENE, null, knx(0, 0, 1)); final Property obergeschoss = createProperty("Obergeschoss", PropertyType.BOOLEAN, knx(0, 6, 6), null); final Property obergeschoss_szene = createProperty("Obergeschoss Szene", PropertyType.SCENE, null, knx(0, 3, 2)); final Property fernseher = createProperty("Fernseher", PropertyType.BOOLEAN, knx(0, 0, 20), knx(0, 0, 4)); final Property verstaerker = createProperty("Verstärker", PropertyType.BOOLEAN, knx(0, 3, 57), knx(0, 3, 56)); final Property aussendekoration = createProperty("Außendekoration", PropertyType.BOOLEAN, knx(0, 4, 12), knx(0, 4, 11)); final Property terrasse = createProperty("Terrasse Licht", PropertyType.BOOLEAN, knx(0, 4, 1), knx(0, 4, 0)); final Property ambiente_eg = createProperty("Ambiente EG", PropertyType.BOOLEAN, knx(0, 3, 81), knx(0, 3, 80)); final Property ambiente_og = createProperty("Ambiente OG", PropertyType.BOOLEAN, knx(0, 6, 2), knx(0, 6, 3)); final Property flur_eg_licht = createProperty("Flur EG Licht", PropertyType.BOOLEAN, knx(0, 4, 8), knx(0, 5, 14)); final Property wohnzimmer_rollladen = createProperty("Wohnzimmer Rollladen", PropertyType.SHUTTER, null, knx(0, 4, 24)); final Property schlafzimmer_rollladen = createProperty("Schlafzimmer Rollladen", PropertyType.SHUTTER, null, knx(0, 3, 3)); final Property flur_og_rollladen = createProperty("Flur OG Rollladen", PropertyType.SHUTTER, null, knx(0, 5, 13)); final Property helligkeit = createProperty("Helligkeit", PropertyType.LUX, knx(0, 5, 6), null); final Property szene_haus = createProperty("Szene Haus ", PropertyType.SCENE, null, knx(0, 0, 21)); final SceneDto alles_aus = sceneWriteService.create(1, "Alles AUS"); final SceneDto nachtlicht = sceneWriteService.create(2, "Nachtlicht"); final SceneDto aussendekoration_aus = sceneWriteService.create(30, "Außendekoration AUS"); final SceneDto aussendekoration_an = sceneWriteService.create(31, "Außendekoration AN"); deviceWriteService.createDeviceStateScene(erdgeschoss, erdgeschoss_szene, alles_aus); deviceWriteService.createDeviceStateScene(obergeschoss, obergeschoss_szene, alles_aus); deviceWriteService.createDeviceSwitch(fernseher); deviceWriteService.createDeviceSwitch(verstaerker); deviceWriteService.createDeviceSwitch(aussendekoration); deviceWriteService.createDeviceSwitch(terrasse); deviceWriteService.createDeviceSwitch(ambiente_eg); deviceWriteService.createDeviceSwitch(ambiente_og); deviceWriteService.createDeviceSwitch(flur_eg_licht); deviceWriteService.createDeviceShutter(wohnzimmer_rollladen); deviceWriteService.createDeviceShutter(schlafzimmer_rollladen); deviceWriteService.createDeviceShutter(flur_og_rollladen); final Schedule scheduleEgFlurLicht = createSchedule(true, "EG Flur Licht", flur_eg_licht); createTime(scheduleEgFlurLicht, true, 1, 0, 0, MIN30, true); createTime(scheduleEgFlurLicht, true, 2, 0, 0, MIN30, false); createTime(scheduleEgFlurLicht, true, 7, 30, 0, MIN30, true); createTime(scheduleEgFlurLicht, true, 8, 30, 0, MIN30, false); createTime(scheduleEgFlurLicht, true, 13, 30, 0, MIN30, true); createTime(scheduleEgFlurLicht, true, 14, 30, 0, MIN30, false); createTime(scheduleEgFlurLicht, true, 19, 0, 0, MIN30, true); createTime(scheduleEgFlurLicht, true, 20, 0, 0, MIN30, false); scheduleRepository.save(scheduleEgFlurLicht); final Schedule scheduleEgAmbiente = createSchedule(false, "Ambiente EG", ambiente_eg); createTime(scheduleEgAmbiente, true, 7, 15, 0, MIN30, true); createTime(scheduleEgAmbiente, true, 9, 30, 0, MIN30, false); createSunset(scheduleEgAmbiente, true, Zenith.OFFICIAL, MIN30, true); createSunset(scheduleEgAmbiente, true, Zenith.ASTRONOMICAL, MIN30, false); scheduleRepository.save(scheduleEgAmbiente); final Schedule scheduleOgAmbiente = createSchedule(false, "Ambiente OG", ambiente_og); createTime(scheduleOgAmbiente, true, 7, 15, 0, MIN30, true); createTime(scheduleOgAmbiente, true, 9, 30, 0, MIN30, false); createSunset(scheduleOgAmbiente, true, Zenith.OFFICIAL, MIN30, true); createSunset(scheduleOgAmbiente, true, Zenith.ASTRONOMICAL, MIN30, false); scheduleRepository.save(scheduleOgAmbiente); final Schedule scheduleWohnzimmerRollladen = createSchedule(true, "Rollläden Wohnzimmer", wohnzimmer_rollladen); createSunrise(scheduleWohnzimmerRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0); createSunset(scheduleWohnzimmerRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100); scheduleRepository.save(scheduleWohnzimmerRollladen); final Schedule scheduleSchlafzimmerRollladen = createSchedule(true, "Rollläden Schlafzimmer", schlafzimmer_rollladen); createTime(scheduleSchlafzimmerRollladen, true, 7, 0, 0, 0, 0); createSunset(scheduleSchlafzimmerRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100); scheduleRepository.save(scheduleSchlafzimmerRollladen); final Schedule scheduleFlurRollladen = createSchedule(true, "Rollladen Flur", flur_og_rollladen); createSunrise(scheduleFlurRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0); createSunset(scheduleFlurRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100); scheduleRepository.save(scheduleFlurRollladen); final Schedule scheduleSzeneHaus = createSchedule(true, "Dekoration", szene_haus); createTime(scheduleSzeneHaus, true, 6, 0, 0, 0, 31); createTime(scheduleSzeneHaus, true, 8, 30, 0, 0, 30); createSunset(scheduleSzeneHaus, true, Zenith.OFFICIAL, 0, 31); createTime(scheduleSzeneHaus, true, 22, 0, 0, 0, 30); scheduleRepository.save(scheduleSzeneHaus); final Property propertyBadLicht = createProperty("Bad Licht", PropertyType.BOOLEAN, knx(0, 5, 19), knx(0, 3, 73)); final DeviceDto deviceBadLicht = deviceWriteService.createDeviceSwitch(propertyBadLicht); // final Logic logicStatusOg = getOrCreateLogic("Status OG", LogicOperator.OR, propertyBadLicht); // final Property propertyStatusOg = createProperty(logicStatusOg.getName(), PropertyType.BOOLEAN, logicStatusOg, null); // final DeviceDto deviceStatusOg = deviceWriteService.createDeviceSwitch(propertyStatusOg); } private Logic getOrCreateLogic(final String name, final LogicOperator operator, final Property... properties) { return logicRepository.findByName(name).orElseGet(() -> { final Logic logic = new Logic(name, operator, new HashSet<>(Arrays.asList(properties))); return logicRepository.save(logic); }); } private KnxGroup knx(final int main, final int mid, final int sub) { return knxGroupReadService.getByAddress(main, mid, sub); } private Property createProperty(final String title, final PropertyType type, final Channel readChannel, final Channel writeChannel) { final Property property = propertyRepository.findByTitle(title).orElseGet(() -> propertyRepository.save(new Property(title, type))); property.setReadChannel(readChannel); property.setWriteChannel(writeChannel); return property; } private Schedule createSchedule(final boolean enabled, final String title, final Property property) { final Schedule schedule = new Schedule(); schedule.setEnabled(enabled); schedule.setTitle(title); schedule.setProperty(property); return schedule; } private ScheduleEntry createRelative(final Schedule schedule, final boolean enabled, final int inSeconds, final int fuzzySeconds, final Object value) { final ZonedDateTime now = ZonedDateTime.now().plusSeconds(inSeconds).withNano(0); return createTime(schedule, enabled, now.getHour(), now.getMinute(), now.getSecond(), fuzzySeconds, value); } private ScheduleEntry createTime(final Schedule schedule, final boolean enabled, final int hour, final int minute, final int second, final int fuzzySeconds, final Object value) { return newScheduleEntry(schedule, enabled, ScheduleEntryType.TIME, null, hour, minute, second, fuzzySeconds, value); } private ScheduleEntry createSunrise(final Schedule schedule, final boolean enabled, final Zenith zenith, final int fuzzySeconds, final Object value) { return newScheduleEntry(schedule, enabled, ScheduleEntryType.SUNRISE, zenith, 0, 0, 0, fuzzySeconds, value); } private ScheduleEntry createSunset(final Schedule schedule, final boolean enabled, final Zenith zenith, final int fuzzySeconds, final Object value) { return newScheduleEntry(schedule, enabled, ScheduleEntryType.SUNSET, zenith, 0, 0, 0, fuzzySeconds, value); } private ScheduleEntry newScheduleEntry(final Schedule schedule, final boolean enabled, final ScheduleEntryType type, final Zenith zenith, final int hour, final int minute, final int second, final int fuzzySeconds, final Object value) { final ScheduleEntry entry = new ScheduleEntry(); entry.setEnabled(enabled); entry.setType(type); if (zenith != null) { entry.setZenith(zenith.degrees().doubleValue()); } entry.setHour(hour); entry.setMinute(minute); entry.setSecond(second); entry.setFuzzySeconds(fuzzySeconds); if (value instanceof Boolean) { entry.setValue((boolean) value ? 1.0 : 0.0); } else if (value instanceof Double) { entry.setValue((Double) value); } else if (value instanceof Integer) { entry.setValue((Integer) value); } else { throw new RuntimeException(); } schedule.getEntries().add(entry); return entry; } }