Implemented fuzzy-shift for Scheduler
This commit is contained in:
parent
caa7e55d10
commit
36ee78783c
@ -1,6 +1,7 @@
|
|||||||
package de.ph87.homeautomation;
|
package de.ph87.homeautomation;
|
||||||
|
|
||||||
import com.luckycatlabs.sunrisesunset.Zenith;
|
import com.luckycatlabs.sunrisesunset.Zenith;
|
||||||
|
import de.ph87.homeautomation.knx.group.KnxGroupDto;
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroupRepository;
|
import de.ph87.homeautomation.knx.group.KnxGroupRepository;
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
|
import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
|
||||||
import de.ph87.homeautomation.schedule.PropertyEntry;
|
import de.ph87.homeautomation.schedule.PropertyEntry;
|
||||||
@ -18,20 +19,13 @@ import java.time.ZonedDateTime;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment"})
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DemoDataService {
|
public class DemoDataService {
|
||||||
|
|
||||||
private static final GroupAddress WOHNZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS = new GroupAddress(0, 4, 24);
|
public static final int MIN30_SEC = 30 * 60;
|
||||||
|
|
||||||
private static final GroupAddress SCHLAFZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS = new GroupAddress(0, 3, 3);
|
|
||||||
|
|
||||||
private static final GroupAddress FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS = new GroupAddress(0, 5, 13);
|
|
||||||
|
|
||||||
private static final GroupAddress BADEWANNE_SCHALTEN = new GroupAddress(781);
|
|
||||||
|
|
||||||
private static final GroupAddress BADEWANNE_STATUS = new GroupAddress(782);
|
|
||||||
|
|
||||||
private final KnxGroupWriteService knxGroupWriteService;
|
private final KnxGroupWriteService knxGroupWriteService;
|
||||||
|
|
||||||
@ -41,64 +35,86 @@ public class DemoDataService {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
createKnxGroupIfNotExists("Wohnzimmer Rollladen Position Anfahren", WOHNZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false);
|
final KnxGroupDto eg_ambiente_schalten = createKnxGroupIfNotExists("EG Ambiente Schalten", 848, "1.001", false);
|
||||||
createKnxGroupIfNotExists("Schlafzimmer Rollladen Position Anfahren", SCHLAFZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false);
|
final KnxGroupDto og_ambiente_schalten = createKnxGroupIfNotExists("OG Ambiente Schalten", 1539, "1.001", false);
|
||||||
createKnxGroupIfNotExists("Flur Rollladen Position Anfahren", FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "5.001", false);
|
final KnxGroupDto wohnzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Wohnzimmer Rollladen Position Anfahren", new GroupAddress(0, 4, 24), "5.001", false);
|
||||||
createKnxGroupIfNotExists("Badewanne Schalten", BADEWANNE_SCHALTEN, "1.001", false);
|
final KnxGroupDto schlafzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Schlafzimmer Rollladen Position Anfahren", new GroupAddress(0, 3, 3), "5.001", false);
|
||||||
createKnxGroupIfNotExists("Badewanne Status", BADEWANNE_STATUS, "1.001", true);
|
final KnxGroupDto flur_rollladen_position_anfahren = createKnxGroupIfNotExists("Flur Rollladen Position Anfahren", new GroupAddress(0, 5, 13), "5.001", false);
|
||||||
|
final KnxGroupDto badewanne_schalten = createKnxGroupIfNotExists("Badewanne Schalten", new GroupAddress(781), "1.001", false);
|
||||||
|
final KnxGroupDto badewanne_status = createKnxGroupIfNotExists("Badewanne Status", new GroupAddress(782), "1.001", true);
|
||||||
|
|
||||||
final Schedule wohnzimmer = new Schedule();
|
final Schedule scheduleEgAmbiente = new Schedule();
|
||||||
wohnzimmer.setName("Rollläden Wohnzimmer");
|
scheduleEgAmbiente.setName("EG Ambiente");
|
||||||
createSunrise(wohnzimmer, Zenith.OFFICIAL, new PropertyEntry(WOHNZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "0"));
|
createTime(scheduleEgAmbiente, 7, 15, 0, MIN30_SEC, MIN30_SEC, new PropertyEntry(eg_ambiente_schalten.getAddress(), "true"));
|
||||||
createSunset(wohnzimmer, Zenith.OFFICIAL, new PropertyEntry(WOHNZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "100"));
|
createTime(scheduleEgAmbiente, 9, 30, 0, MIN30_SEC, MIN30_SEC, new PropertyEntry(eg_ambiente_schalten.getAddress(), "false"));
|
||||||
scheduleRepository.save(wohnzimmer);
|
createSunset(scheduleEgAmbiente, Zenith.OFFICIAL, MIN30_SEC, MIN30_SEC, new PropertyEntry(eg_ambiente_schalten.getAddress(), "true"));
|
||||||
|
createSunset(scheduleEgAmbiente, Zenith.ASTRONOMICAL, MIN30_SEC, MIN30_SEC, new PropertyEntry(eg_ambiente_schalten.getAddress(), "false"));
|
||||||
|
scheduleRepository.save(scheduleEgAmbiente);
|
||||||
|
|
||||||
final Schedule schlafzimmer = new Schedule();
|
final Schedule scheduleOgAmbiente = new Schedule();
|
||||||
schlafzimmer.setName("Rollläden Schlafzimmer");
|
scheduleOgAmbiente.setName("OG Ambiente");
|
||||||
createTime(schlafzimmer, 7, 0, 0, new PropertyEntry(SCHLAFZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "0"));
|
createTime(scheduleOgAmbiente, 7, 15, 0, MIN30_SEC, MIN30_SEC, new PropertyEntry(og_ambiente_schalten.getAddress(), "true"));
|
||||||
createTime(schlafzimmer, 20, 0, 0, new PropertyEntry(SCHLAFZIMMER_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "100"));
|
createTime(scheduleOgAmbiente, 9, 30, 0, MIN30_SEC, MIN30_SEC, new PropertyEntry(og_ambiente_schalten.getAddress(), "false"));
|
||||||
scheduleRepository.save(schlafzimmer);
|
createSunset(scheduleOgAmbiente, Zenith.OFFICIAL, MIN30_SEC, MIN30_SEC, new PropertyEntry(og_ambiente_schalten.getAddress(), "true"));
|
||||||
|
createSunset(scheduleOgAmbiente, Zenith.ASTRONOMICAL, MIN30_SEC, MIN30_SEC, new PropertyEntry(og_ambiente_schalten.getAddress(), "false"));
|
||||||
|
scheduleRepository.save(scheduleOgAmbiente);
|
||||||
|
|
||||||
final Schedule flur = new Schedule();
|
final Schedule scheduleWohnzimmerRollladen = new Schedule();
|
||||||
flur.setName("Rollläden Flur");
|
scheduleWohnzimmerRollladen.setName("Rollläden Wohnzimmer");
|
||||||
createSunrise(flur, Zenith.NAUTICAL, new PropertyEntry(FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "0"));
|
createSunrise(scheduleWohnzimmerRollladen, Zenith.OFFICIAL, 0, 0, new PropertyEntry(wohnzimmer_rollladen_position_anfahren.getAddress(), "0"));
|
||||||
createSunset(flur, Zenith.NAUTICAL, new PropertyEntry(FLUR_ROLLLADEN_POSITION_ANFAHREN_ADDRESS, "100"));
|
createSunset(scheduleWohnzimmerRollladen, Zenith.OFFICIAL, 0, 0, new PropertyEntry(wohnzimmer_rollladen_position_anfahren.getAddress(), "100"));
|
||||||
scheduleRepository.save(flur);
|
scheduleRepository.save(scheduleWohnzimmerRollladen);
|
||||||
|
|
||||||
final Schedule badewanne = new Schedule();
|
final Schedule scheduleSchlafzimmerRollladen = new Schedule();
|
||||||
badewanne.setName("Badewanne");
|
scheduleSchlafzimmerRollladen.setName("Rollläden Schlafzimmer");
|
||||||
int seconds = 2;
|
createTime(scheduleSchlafzimmerRollladen, 7, 0, 0, 0, 0, new PropertyEntry(schlafzimmer_rollladen_position_anfahren.getAddress(), "0"));
|
||||||
createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "true"));
|
createTime(scheduleSchlafzimmerRollladen, 20, 0, 0, 0, 0, new PropertyEntry(schlafzimmer_rollladen_position_anfahren.getAddress(), "100"));
|
||||||
createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "false"));
|
scheduleRepository.save(scheduleSchlafzimmerRollladen);
|
||||||
createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "true"));
|
|
||||||
createRelative(badewanne, seconds += 2, new PropertyEntry(BADEWANNE_SCHALTEN, "false"));
|
final Schedule scheduleFlurRollladen = new Schedule();
|
||||||
scheduleRepository.save(badewanne);
|
scheduleFlurRollladen.setName("Rollläden Flur");
|
||||||
|
createSunrise(scheduleFlurRollladen, Zenith.NAUTICAL, 0, 0, new PropertyEntry(flur_rollladen_position_anfahren.getAddress(), "0"));
|
||||||
|
createSunset(scheduleFlurRollladen, Zenith.NAUTICAL, 0, 0, new PropertyEntry(flur_rollladen_position_anfahren.getAddress(), "100"));
|
||||||
|
scheduleRepository.save(scheduleFlurRollladen);
|
||||||
|
|
||||||
|
final Schedule scheduleBadewanneBlinken = new Schedule();
|
||||||
|
scheduleBadewanneBlinken.setName("Badewanne");
|
||||||
|
final int interval = 2;
|
||||||
|
final int fuzzy = 0;
|
||||||
|
int seconds = interval;
|
||||||
|
createRelative(scheduleBadewanneBlinken, seconds += interval, fuzzy, fuzzy, new PropertyEntry(badewanne_schalten.getAddress(), "true"));
|
||||||
|
createRelative(scheduleBadewanneBlinken, seconds += interval, fuzzy, fuzzy, new PropertyEntry(badewanne_schalten.getAddress(), "false"));
|
||||||
|
createRelative(scheduleBadewanneBlinken, seconds += interval, fuzzy, fuzzy, new PropertyEntry(badewanne_schalten.getAddress(), "true"));
|
||||||
|
createRelative(scheduleBadewanneBlinken, seconds += interval, fuzzy, fuzzy, new PropertyEntry(badewanne_schalten.getAddress(), "false"));
|
||||||
|
scheduleRepository.save(scheduleBadewanneBlinken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final boolean readable) {
|
private KnxGroupDto createKnxGroupIfNotExists(final String name, final int address, final String dpt, final boolean readable) {
|
||||||
if (!knxGroupRepository.existsByAddressRaw(address.getRawAddress())) {
|
return createKnxGroupIfNotExists(name, new GroupAddress(address), dpt, readable);
|
||||||
knxGroupWriteService.create(name, address, dpt, readable);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createRelative(final Schedule schedule, final int inSeconds, final Map.Entry<String, String>... entries) {
|
private KnxGroupDto createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final boolean readable) {
|
||||||
|
return knxGroupRepository.findByAddressRaw(address.getRawAddress()).map(KnxGroupDto::new).orElseGet(() -> knxGroupWriteService.create(name, address, dpt, readable));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScheduleEntry createRelative(final Schedule schedule, final int inSeconds, final int fuzzyMinusSeconds, final int fuzzyPlusSeconds, final Map.Entry<String, String>... entries) {
|
||||||
final ZonedDateTime now = ZonedDateTime.now().plusSeconds(inSeconds).withNano(0);
|
final ZonedDateTime now = ZonedDateTime.now().plusSeconds(inSeconds).withNano(0);
|
||||||
return create(schedule, ScheduleEntryType.TIME, null, now.getHour(), now.getMinute(), now.getSecond(), entries);
|
return create(schedule, ScheduleEntryType.TIME, null, now.getHour(), now.getMinute(), now.getSecond(), fuzzyMinusSeconds, fuzzyPlusSeconds, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createTime(final Schedule schedule, final int hour, final int minute, final int second, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry createTime(final Schedule schedule, final int hour, final int minute, final int second, final int fuzzyMinusSeconds, final int fuzzyPlusSeconds, final Map.Entry<String, String>... entries) {
|
||||||
return create(schedule, ScheduleEntryType.TIME, null, hour, minute, second, entries);
|
return create(schedule, ScheduleEntryType.TIME, null, hour, minute, second, fuzzyMinusSeconds, fuzzyPlusSeconds, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createSunrise(final Schedule schedule, final Zenith zenith, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry createSunrise(final Schedule schedule, final Zenith zenith, final int fuzzyMinusSeconds, final int fuzzyPlusSeconds, final Map.Entry<String, String>... entries) {
|
||||||
return create(schedule, ScheduleEntryType.SUNRISE, zenith, 0, 0, 0, entries);
|
return create(schedule, ScheduleEntryType.SUNRISE, zenith, 0, 0, 0, fuzzyMinusSeconds, fuzzyPlusSeconds, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createSunset(final Schedule schedule, final Zenith zenith, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry createSunset(final Schedule schedule, final Zenith zenith, final int fuzzyMinusSeconds, final int fuzzyPlusSeconds, final Map.Entry<String, String>... entries) {
|
||||||
return create(schedule, ScheduleEntryType.SUNSET, zenith, 0, 0, 0, entries);
|
return create(schedule, ScheduleEntryType.SUNSET, zenith, 0, 0, 0, fuzzyMinusSeconds, fuzzyPlusSeconds, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry create(final Schedule schedule, final ScheduleEntryType type, final Zenith zenith, final int hour, final int minute, final int second, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry create(final Schedule schedule, final ScheduleEntryType type, final Zenith zenith, final int hour, final int minute, final int second, final int fuzzyMinusSeconds, final int fuzzyPlusSeconds, final Map.Entry<String, String>... entries) {
|
||||||
final ScheduleEntry entry = new ScheduleEntry();
|
final ScheduleEntry entry = new ScheduleEntry();
|
||||||
entry.setType(type);
|
entry.setType(type);
|
||||||
if (zenith != null) {
|
if (zenith != null) {
|
||||||
@ -107,6 +123,8 @@ public class DemoDataService {
|
|||||||
entry.setHour(hour);
|
entry.setHour(hour);
|
||||||
entry.setMinute(minute);
|
entry.setMinute(minute);
|
||||||
entry.setSecond(second);
|
entry.setSecond(second);
|
||||||
|
entry.setFuzzyMinusSeconds(fuzzyMinusSeconds);
|
||||||
|
entry.setFuzzyPlusSeconds(fuzzyPlusSeconds);
|
||||||
Arrays.stream(entries).forEach(p -> entry.getProperties().put(p.getKey(), p.getValue()));
|
Arrays.stream(entries).forEach(p -> entry.getProperties().put(p.getKey(), p.getValue()));
|
||||||
schedule.getEntries().add(entry);
|
schedule.getEntries().add(entry);
|
||||||
return entry;
|
return entry;
|
||||||
|
|||||||
@ -0,0 +1,43 @@
|
|||||||
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import tuwien.auto.calimero.GroupAddress;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class KnxGroupDto {
|
||||||
|
|
||||||
|
public final long id;
|
||||||
|
|
||||||
|
public final int addressRaw;
|
||||||
|
|
||||||
|
public final String addressStr;
|
||||||
|
|
||||||
|
public final String dpt;
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
|
||||||
|
public final Boolean booleanValue;
|
||||||
|
|
||||||
|
public final BigDecimal numberValue;
|
||||||
|
|
||||||
|
public final ZonedDateTime valueTimestamp;
|
||||||
|
|
||||||
|
public KnxGroupDto(final KnxGroup knxGroup) {
|
||||||
|
id = knxGroup.getId();
|
||||||
|
addressRaw = knxGroup.getAddressRaw();
|
||||||
|
addressStr = knxGroup.getAddressStr();
|
||||||
|
dpt = knxGroup.getDpt();
|
||||||
|
name = knxGroup.getName();
|
||||||
|
booleanValue = knxGroup.getBooleanValue();
|
||||||
|
numberValue = knxGroup.getNumberValue();
|
||||||
|
valueTimestamp = knxGroup.getValueTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupAddress getAddress() {
|
||||||
|
return new GroupAddress(addressRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -53,13 +53,13 @@ public class KnxGroupWriteService {
|
|||||||
knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()));
|
knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void create(final String name, final GroupAddress address, final String dpt, final boolean readable) {
|
public KnxGroupDto create(final String name, final GroupAddress address, final String dpt, final boolean readable) {
|
||||||
final KnxGroup trans = new KnxGroup();
|
final KnxGroup trans = new KnxGroup();
|
||||||
trans.setAddress(address);
|
trans.setAddress(address);
|
||||||
trans.setDpt(dpt);
|
trans.setDpt(dpt);
|
||||||
trans.setName(name);
|
trans.setName(name);
|
||||||
trans.getRead().setAble(readable);
|
trans.getRead().setAble(readable);
|
||||||
knxGroupRepository.save(trans);
|
return new KnxGroupDto(knxGroupRepository.save(trans));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setSendValue(final GroupAddress groupAddress, final String value) throws KnxGroupFormatException {
|
public boolean setSendValue(final GroupAddress groupAddress, final String value) throws KnxGroupFormatException {
|
||||||
|
|||||||
@ -17,11 +17,6 @@ public class PropertyEntry implements Map.Entry<String, String> {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyEntry(final String propertyName, final String value) {
|
|
||||||
this.key = propertyName;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String setValue(final String value) {
|
public String setValue(final String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@ -45,14 +45,14 @@ public class ScheduleController {
|
|||||||
|
|
||||||
private ScheduleEntryNextDto(final Schedule schedule, final ScheduleEntry entry) {
|
private ScheduleEntryNextDto(final Schedule schedule, final ScheduleEntry entry) {
|
||||||
this.name = schedule.getName();
|
this.name = schedule.getName();
|
||||||
this.nextTimestamp = entry.getNextDateTime();
|
this.nextTimestamp = entry.getNextFuzzyTimestamp();
|
||||||
this.properties = new HashMap<>(entry.getProperties());
|
this.properties = new HashMap<>(entry.getProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<ScheduleEntryNextDto> create(final Schedule schedule, final ZonedDateTime now) {
|
public static Optional<ScheduleEntryNextDto> create(final Schedule schedule, final ZonedDateTime now) {
|
||||||
return schedule.getEntries().stream()
|
return schedule.getEntries().stream()
|
||||||
.filter(entry -> entry.getNextDateTime() != null && entry.getNextDateTime().isAfter(now))
|
.filter(entry -> entry.getNextFuzzyTimestamp() != null && entry.getNextFuzzyTimestamp().isAfter(now))
|
||||||
.min(Comparator.comparing(ScheduleEntry::getNextDateTime))
|
.min(Comparator.comparing(ScheduleEntry::getNextFuzzyTimestamp))
|
||||||
.map(scheduleEntry -> new ScheduleEntryNextDto(schedule, scheduleEntry));
|
.map(scheduleEntry -> new ScheduleEntryNextDto(schedule, scheduleEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -49,9 +49,10 @@ public class ScheduleWriteService {
|
|||||||
|
|
||||||
private void executeLastDue(final Schedule schedule, final ZonedDateTime now) {
|
private void executeLastDue(final Schedule schedule, final ZonedDateTime now) {
|
||||||
schedule.getEntries().stream()
|
schedule.getEntries().stream()
|
||||||
.filter(entry -> entry.getNextDateTime() != null && !entry.getNextDateTime().isAfter(now))
|
.filter(entry -> entry.getNextFuzzyTimestamp() != null && !entry.getNextFuzzyTimestamp().isAfter(now))
|
||||||
.max(Comparator.comparing(ScheduleEntry::getNextDateTime))
|
.max(Comparator.comparing(ScheduleEntry::getNextFuzzyTimestamp))
|
||||||
.ifPresent(entry -> {
|
.ifPresent(entry -> {
|
||||||
|
entry.setLastClearTimestamp(entry.getNextClearTimestamp());
|
||||||
log.info("Executing ScheduleEntry {}", entry);
|
log.info("Executing ScheduleEntry {}", entry);
|
||||||
entry.getProperties().forEach(this::applyPropertyMapEntry);
|
entry.getProperties().forEach(this::applyPropertyMapEntry);
|
||||||
calculateSchedule(schedule, now);
|
calculateSchedule(schedule, now);
|
||||||
@ -69,15 +70,15 @@ public class ScheduleWriteService {
|
|||||||
private void calculateSchedule(final Schedule schedule, final ZonedDateTime now) {
|
private void calculateSchedule(final Schedule schedule, final ZonedDateTime now) {
|
||||||
schedule.getEntries().forEach(scheduleEntry -> calculateEntry(schedule, scheduleEntry, now));
|
schedule.getEntries().forEach(scheduleEntry -> calculateEntry(schedule, scheduleEntry, now));
|
||||||
schedule.getEntries().stream()
|
schedule.getEntries().stream()
|
||||||
.filter(entry -> entry.getNextDateTime() != null && entry.getNextDateTime().isAfter(now))
|
.filter(entry -> entry.getNextFuzzyTimestamp() != null && entry.getNextFuzzyTimestamp().isAfter(now))
|
||||||
.min(Comparator.comparing(ScheduleEntry::getNextDateTime))
|
.min(Comparator.comparing(ScheduleEntry::getNextFuzzyTimestamp))
|
||||||
.ifPresent(scheduleEntry -> log.info("Next schedule for \"{}\": {}", schedule.getName(), scheduleEntry.getNextDateTime()));
|
.ifPresent(scheduleEntry -> log.info("Next schedule for \"{}\": {}", schedule.getName(), scheduleEntry.getNextFuzzyTimestamp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateEntry(final Schedule schedule, final ScheduleEntry entry, final ZonedDateTime now) {
|
private void calculateEntry(final Schedule schedule, final ScheduleEntry entry, final ZonedDateTime now) {
|
||||||
log.debug("calculateNext \"{}\", {}:", schedule.getName(), entry);
|
log.debug("calculateNext \"{}\", {}:", schedule.getName(), entry);
|
||||||
if (!entry.isEnabled() || !isAnyWeekdayEnabled(entry)) {
|
if (!entry.isEnabled() || !isAnyWeekdayEnabled(entry)) {
|
||||||
entry.setNextDateTime(null);
|
entry.setNextClearTimestamp(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ZonedDateTime midnight = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
|
ZonedDateTime midnight = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||||
@ -88,7 +89,7 @@ public class ScheduleWriteService {
|
|||||||
next = calculateEntryForDay(entry, midnight);
|
next = calculateEntryForDay(entry, midnight);
|
||||||
}
|
}
|
||||||
log.debug(" => {}", next);
|
log.debug(" => {}", next);
|
||||||
entry.setNextDateTime(next);
|
entry.setNextClearTimestamp(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ZonedDateTime calculateEntryForDay(final ScheduleEntry entry, final ZonedDateTime midnight) {
|
private ZonedDateTime calculateEntryForDay(final ScheduleEntry entry, final ZonedDateTime midnight) {
|
||||||
@ -151,7 +152,7 @@ public class ScheduleWriteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Optional<ZonedDateTime> getNextTimestamp() {
|
public Optional<ZonedDateTime> getNextTimestamp() {
|
||||||
return scheduleEntryRepository.findFirstNextDateTimeByNextDateTimeNotNullOrderByNextDateTimeAsc().map(ScheduleEntry::getNextDateTime);
|
return scheduleEntryRepository.findFirstByNextFuzzyTimestampNotNullOrderByNextFuzzyTimestampAsc().map(ScheduleEntry::getNextFuzzyTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,12 +9,15 @@ import javax.persistence.*;
|
|||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Entity
|
@Entity
|
||||||
public class ScheduleEntry {
|
public class ScheduleEntry {
|
||||||
|
|
||||||
|
private static final Random RANDOM = new Random(System.currentTimeMillis());
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
@ -47,11 +50,31 @@ public class ScheduleEntry {
|
|||||||
|
|
||||||
private int second;
|
private int second;
|
||||||
|
|
||||||
private ZonedDateTime nextDateTime;
|
private int fuzzyMinusSeconds = 0;
|
||||||
|
|
||||||
|
private int fuzzyPlusSeconds = 0;
|
||||||
|
|
||||||
|
private ZonedDateTime nextClearTimestamp;
|
||||||
|
|
||||||
|
private ZonedDateTime lastClearTimestamp;
|
||||||
|
|
||||||
|
@Setter(AccessLevel.NONE)
|
||||||
|
private ZonedDateTime nextFuzzyTimestamp;
|
||||||
|
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
private Map<String, String> properties = new HashMap<>();
|
private Map<String, String> properties = new HashMap<>();
|
||||||
|
|
||||||
|
public void setNextClearTimestamp(final ZonedDateTime next) {
|
||||||
|
nextClearTimestamp = next;
|
||||||
|
if (nextClearTimestamp != null && (lastClearTimestamp == null || nextClearTimestamp.compareTo(lastClearTimestamp) != 0)) {
|
||||||
|
final int secondsRange = fuzzyPlusSeconds + fuzzyMinusSeconds;
|
||||||
|
final int fuzzySeconds = secondsRange > 0 ? RANDOM.nextInt(secondsRange) - fuzzyMinusSeconds : 0;
|
||||||
|
nextFuzzyTimestamp = nextClearTimestamp.plusSeconds(fuzzySeconds);
|
||||||
|
} else {
|
||||||
|
nextFuzzyTimestamp = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setWorkday(final boolean enabled) {
|
public void setWorkday(final boolean enabled) {
|
||||||
monday = enabled;
|
monday = enabled;
|
||||||
tuesday = enabled;
|
tuesday = enabled;
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public class ScheduleEntryDto {
|
|||||||
hour = scheduleEntry.getHour();
|
hour = scheduleEntry.getHour();
|
||||||
minute = scheduleEntry.getMinute();
|
minute = scheduleEntry.getMinute();
|
||||||
second = scheduleEntry.getSecond();
|
second = scheduleEntry.getSecond();
|
||||||
nextDateTime = scheduleEntry.getNextDateTime();
|
nextDateTime = scheduleEntry.getNextFuzzyTimestamp();
|
||||||
properties = new HashMap<>(scheduleEntry.getProperties());
|
properties = new HashMap<>(scheduleEntry.getProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,6 @@ import java.util.Optional;
|
|||||||
|
|
||||||
public interface ScheduleEntryRepository extends CrudRepository<ScheduleEntry, Long> {
|
public interface ScheduleEntryRepository extends CrudRepository<ScheduleEntry, Long> {
|
||||||
|
|
||||||
Optional<ScheduleEntry> findFirstNextDateTimeByNextDateTimeNotNullOrderByNextDateTimeAsc();
|
Optional<ScheduleEntry> findFirstByNextFuzzyTimestampNotNullOrderByNextFuzzyTimestampAsc();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user