REFACTOR: Replaced ScheduleEntry properties by single value
+ UI ScheduleEntry.value
This commit is contained in:
parent
87acae3b2e
commit
da31a892e1
35
src/main/angular/src/app/api/Timestamp.ts
Normal file
35
src/main/angular/src/app/api/Timestamp.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import {prefix} from "../helpers";
|
||||||
|
|
||||||
|
export class Timestamp {
|
||||||
|
|
||||||
|
public readonly WEEKDAY: string[] = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
|
||||||
|
|
||||||
|
public readonly dayName;
|
||||||
|
|
||||||
|
public readonly timeString;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
readonly date: Date,
|
||||||
|
) {
|
||||||
|
const now = new Date();
|
||||||
|
const minutes: string = prefix(this.date.getMinutes(), '0', 2);
|
||||||
|
if (date.getDate() === now.getDate()) {
|
||||||
|
this.dayName = "Heute";
|
||||||
|
this.timeString = date.getHours() + ":" + minutes;
|
||||||
|
} else if (date.getDate() === now.getDate() + 1) {
|
||||||
|
this.dayName = "Morgen";
|
||||||
|
this.timeString = date.getHours() + ":" + minutes;
|
||||||
|
} else {
|
||||||
|
this.dayName = this.WEEKDAY[date.getDay()];
|
||||||
|
this.timeString = date.getHours() + ":" + minutes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fromDateOrNull(date: Date | null): Timestamp | null {
|
||||||
|
if (date === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Timestamp(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -7,6 +7,8 @@ export class Schedule {
|
|||||||
public id: number,
|
public id: number,
|
||||||
public enabled: boolean,
|
public enabled: boolean,
|
||||||
public name: string,
|
public name: string,
|
||||||
|
public propertyName: string,
|
||||||
|
public propertyType: string,
|
||||||
public entries: ScheduleEntry[],
|
public entries: ScheduleEntry[],
|
||||||
) {
|
) {
|
||||||
// nothing
|
// nothing
|
||||||
@ -17,7 +19,9 @@ export class Schedule {
|
|||||||
validateNumberNotNull(json['id']),
|
validateNumberNotNull(json['id']),
|
||||||
validateBooleanNotNull(json['enabled']),
|
validateBooleanNotNull(json['enabled']),
|
||||||
validateStringNotEmptyNotNull(json['name']),
|
validateStringNotEmptyNotNull(json['name']),
|
||||||
validateListOrEmpty(json['entries'], ScheduleEntry.fromJson, ScheduleEntry.compareId),
|
validateStringNotEmptyNotNull(json['propertyName']),
|
||||||
|
validateStringNotEmptyNotNull(json['propertyType']),
|
||||||
|
validateListOrEmpty(json['entries'], ScheduleEntry.fromJson, ScheduleEntry.compare),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,39 +1,5 @@
|
|||||||
import {validateBooleanNotNull, validateDateAllowNull, validateMap, validateNumberNotNull, validateStringNotEmptyNotNull} from "../../validators";
|
import {validateBooleanNotNull, validateDateAllowNull, validateNumberNotNull, validateStringNotEmptyNotNull} from "../../validators";
|
||||||
import {prefix} from "../../../helpers";
|
import {Timestamp} from "../../Timestamp";
|
||||||
|
|
||||||
class Timestamp {
|
|
||||||
|
|
||||||
public readonly WEEKDAY: string[] = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
|
|
||||||
|
|
||||||
public readonly dayName;
|
|
||||||
|
|
||||||
public readonly timeString;
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
readonly date: Date,
|
|
||||||
) {
|
|
||||||
const now = new Date();
|
|
||||||
const minutes: string = prefix(this.date.getMinutes(), '0', 2);
|
|
||||||
if (date.getDate() === now.getDate()) {
|
|
||||||
this.dayName = "Heute";
|
|
||||||
this.timeString = date.getHours() + ":" + minutes;
|
|
||||||
} else if (date.getDate() === now.getDate() + 1) {
|
|
||||||
this.dayName = "Morgen";
|
|
||||||
this.timeString = date.getHours() + ":" + minutes;
|
|
||||||
} else {
|
|
||||||
this.dayName = this.WEEKDAY[date.getDay()];
|
|
||||||
this.timeString = date.getHours() + ":" + minutes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromDateOrNull(date: Date | null): Timestamp | null {
|
|
||||||
if (date === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new Timestamp(date);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ScheduleEntry {
|
export class ScheduleEntry {
|
||||||
|
|
||||||
@ -56,7 +22,7 @@ export class ScheduleEntry {
|
|||||||
public lastClearTimestamp: Timestamp | null,
|
public lastClearTimestamp: Timestamp | null,
|
||||||
public nextClearTimestamp: Timestamp | null,
|
public nextClearTimestamp: Timestamp | null,
|
||||||
public nextFuzzyTimestamp: Timestamp | null,
|
public nextFuzzyTimestamp: Timestamp | null,
|
||||||
public properties: Map<String, String>,
|
public value: number,
|
||||||
) {
|
) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
@ -81,7 +47,7 @@ export class ScheduleEntry {
|
|||||||
Timestamp.fromDateOrNull(validateDateAllowNull(json['lastClearTimestamp'])),
|
Timestamp.fromDateOrNull(validateDateAllowNull(json['lastClearTimestamp'])),
|
||||||
Timestamp.fromDateOrNull(validateDateAllowNull(json['nextClearTimestamp'])),
|
Timestamp.fromDateOrNull(validateDateAllowNull(json['nextClearTimestamp'])),
|
||||||
Timestamp.fromDateOrNull(validateDateAllowNull(json['nextFuzzyTimestamp'])),
|
Timestamp.fromDateOrNull(validateDateAllowNull(json['nextFuzzyTimestamp'])),
|
||||||
validateMap(json['properties'], validateStringNotEmptyNotNull),
|
validateNumberNotNull(json['value']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,8 +55,13 @@ export class ScheduleEntry {
|
|||||||
return item.id;
|
return item.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static compareId(a: ScheduleEntry, b: ScheduleEntry): number {
|
public static compare(a: ScheduleEntry, b: ScheduleEntry): number {
|
||||||
return a.id - b.id;
|
if (a.nextFuzzyTimestamp === null) {
|
||||||
|
return +1;
|
||||||
|
} else if (b.nextFuzzyTimestamp === null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return a.nextFuzzyTimestamp.date.getTime() - b.nextFuzzyTimestamp.date.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,13 @@ export function validateBooleanNotNull(value: any): boolean {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateBooleanAllowNull(value: any): boolean | null {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return validateBooleanNotNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
export function validateNumberNotNull(value: any): number {
|
export function validateNumberNotNull(value: any): number {
|
||||||
const number: number = parseFloat(value);
|
const number: number = parseFloat(value);
|
||||||
if (isNaN(number)) {
|
if (isNaN(number)) {
|
||||||
@ -13,6 +20,13 @@ export function validateNumberNotNull(value: any): number {
|
|||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function validateNumberAllowNull(value: any): number | null {
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return validateNumberNotNull(value);
|
||||||
|
}
|
||||||
|
|
||||||
export function validateStringNotEmptyNotNull(value: any): string {
|
export function validateStringNotEmptyNotNull(value: any): string {
|
||||||
if (!(typeof value === 'string')) {
|
if (!(typeof value === 'string')) {
|
||||||
throw new Error("Not a string: " + value);
|
throw new Error("Not a string: " + value);
|
||||||
@ -23,25 +37,26 @@ export function validateStringNotEmptyNotNull(value: any): string {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateStringNotEmpty_Nullable(value: any): string | null {
|
export function validateStringNotEmpty_AllowNull(value: any): string | null {
|
||||||
if (value === null || value === undefined || value === '') {
|
if (value === null || value === undefined || value === '') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!(typeof value === 'string')) {
|
return validateStringNotEmptyNotNull(value);
|
||||||
throw new Error("Not a string: " + value);
|
}
|
||||||
|
|
||||||
|
function validateDateNotNull(value: any): Date {
|
||||||
|
const number: number = Date.parse(value);
|
||||||
|
if (isNaN(number)) {
|
||||||
|
throw new Error("Not a Date: " + value);
|
||||||
}
|
}
|
||||||
return value;
|
return new Date(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateDateAllowNull(value: any): Date | null {
|
export function validateDateAllowNull(value: any): Date | null {
|
||||||
if (value === null || value === undefined || value === 0 || value === '') {
|
if (value === null || value === undefined || value === 0 || value === '') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const number: number = Date.parse(value);
|
return validateDateNotNull(value);
|
||||||
if (isNaN(number)) {
|
|
||||||
throw new Error("Not a Date: " + value);
|
|
||||||
}
|
|
||||||
return new Date(number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function validateListOrEmpty<T>(json: any, fromJson: (json: any) => T, compare: (a: T, b: T) => number): T[] {
|
export function validateListOrEmpty<T>(json: any, fromJson: (json: any) => T, compare: (a: T, b: T) => number): T[] {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<div class="menubar">
|
<div class="menubar">
|
||||||
|
|
||||||
<div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive">
|
<div class="item" routerLink="/ScheduleList" routerLinkActive="itemActive">
|
||||||
Zeitplan
|
Zeitpläne
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item breadcrumb" [routerLink]="['/Schedule', {id: dataService.schedule.id}]" routerLinkActive="itemActive" *ngIf="dataService.schedule">
|
<div class="item breadcrumb" [routerLink]="['/Schedule', {id: dataService.schedule.id}]" routerLinkActive="itemActive" *ngIf="dataService.schedule">
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
<th colspan="3">Uhrzeit</th>
|
<th colspan="3">Uhrzeit</th>
|
||||||
<th>Unschärfe</th>
|
<th>Unschärfe</th>
|
||||||
<th colspan="6">Nächste Ausführung</th>
|
<th colspan="6">Nächste Ausführung</th>
|
||||||
|
<th>Wert</th>
|
||||||
<th> </th>
|
<th> </th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr *ngFor="let entry of schedule.entries" [class.disabled]="entry.nextClearTimestamp === null">
|
<tr *ngFor="let entry of schedule.entries" [class.disabled]="entry.nextClearTimestamp === null">
|
||||||
@ -70,7 +71,7 @@
|
|||||||
<ng-container *ngIf="entry.type === 'TIME'">
|
<ng-container *ngIf="entry.type === 'TIME'">
|
||||||
<td class="first">
|
<td class="first">
|
||||||
<select class="number" [(ngModel)]="entry.hour" (ngModelChange)="set(entry, 'hour', entry.hour)">
|
<select class="number" [(ngModel)]="entry.hour" (ngModelChange)="set(entry, 'hour', entry.hour)">
|
||||||
<option *ngFor="let _ of [].constructor(60); let value = index" [ngValue]="value">{{value}}</option>
|
<option *ngFor="let _ of [].constructor(24); let value = index" [ngValue]="value">{{value}}</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
<td class="middle">:</td>
|
<td class="middle">:</td>
|
||||||
@ -120,6 +121,15 @@
|
|||||||
<td class="empty last"></td>
|
<td class="empty last"></td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<td *ngIf="schedule.propertyType === 'ON_OFF'" [class.true]="entry.value" [class.false]="!entry.value" (click)="set(entry, 'value', entry.value > 0 ? 0 : 1)">
|
||||||
|
{{entry.value ? "An" : "Aus"}}
|
||||||
|
</td>
|
||||||
|
<td *ngIf="schedule.propertyType === 'PERCENT'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
|
||||||
|
<select class="number" [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
|
||||||
|
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td class="delete" (click)="delete(entry)">
|
<td class="delete" (click)="delete(entry)">
|
||||||
<fa-icon title="Löschen" [icon]="faTimes"></fa-icon>
|
<fa-icon title="Löschen" [icon]="faTimes"></fa-icon>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -32,6 +32,10 @@ tr.header {
|
|||||||
background-color: palegreen;
|
background-color: palegreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tristate {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
.false {
|
.false {
|
||||||
background-color: indianred;
|
background-color: indianred;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,6 @@ export class ScheduleComponent implements OnInit {
|
|||||||
} else {
|
} else {
|
||||||
this.schedule.entries[index] = entry;
|
this.schedule.entries[index] = entry;
|
||||||
}
|
}
|
||||||
this.schedule.entries = this.schedule.entries.sort(ScheduleEntry.compareId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private remove(entry: ScheduleEntry): void {
|
private remove(entry: ScheduleEntry): void {
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import com.luckycatlabs.sunrisesunset.Zenith;
|
|||||||
import de.ph87.homeautomation.knx.group.KnxGroupDto;
|
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.property.PropertyType;
|
||||||
import de.ph87.homeautomation.schedule.Schedule;
|
import de.ph87.homeautomation.schedule.Schedule;
|
||||||
import de.ph87.homeautomation.schedule.ScheduleRepository;
|
import de.ph87.homeautomation.schedule.ScheduleRepository;
|
||||||
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
|
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
|
||||||
@ -16,8 +16,6 @@ import tuwien.auto.calimero.GroupAddress;
|
|||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment", "RedundantSuppression"})
|
@SuppressWarnings({"unchecked", "UnusedReturnValue", "SameParameterValue", "UnusedAssignment", "RedundantSuppression"})
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -35,109 +33,104 @@ public class DemoDataService {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
final KnxGroupDto eg_flur_licht_schalten = createKnxGroupIfNotExists("EG Flur Licht Schalten", 1294, "1.001", false, false);
|
final KnxGroupDto eg_flur_licht_schalten = createKnxGroupIfNotExists("EG Flur Licht Schalten", 1294, "1.001", PropertyType.ON_OFF, false, false);
|
||||||
final KnxGroupDto eg_ambiente_schalten = createKnxGroupIfNotExists("EG Ambiente Schalten", 848, "1.001", false, false);
|
final KnxGroupDto eg_ambiente_schalten = createKnxGroupIfNotExists("EG Ambiente Schalten", 848, "1.001", PropertyType.ON_OFF, false, false);
|
||||||
final KnxGroupDto og_ambiente_schalten = createKnxGroupIfNotExists("OG Ambiente Schalten", 1539, "1.001", false, false);
|
final KnxGroupDto og_ambiente_schalten = createKnxGroupIfNotExists("OG Ambiente Schalten", 1539, "1.001", PropertyType.ON_OFF, false, false);
|
||||||
final KnxGroupDto wohnzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Wohnzimmer Rollladen Position Anfahren", new GroupAddress(0, 4, 24), "5.001", false, false);
|
final KnxGroupDto wohnzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Wohnzimmer Rollladen Position Anfahren", new GroupAddress(0, 4, 24), "5.001", PropertyType.PERCENT, false, false);
|
||||||
final KnxGroupDto schlafzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Schlafzimmer Rollladen Position Anfahren", new GroupAddress(0, 3, 3), "5.001", false, false);
|
final KnxGroupDto schlafzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Schlafzimmer Rollladen Position Anfahren", new GroupAddress(0, 3, 3), "5.001", PropertyType.PERCENT, false, false);
|
||||||
final KnxGroupDto flur_rollladen_position_anfahren = createKnxGroupIfNotExists("Flur Rollladen Position Anfahren", new GroupAddress(0, 5, 13), "5.001", false, false);
|
final KnxGroupDto flur_rollladen_position_anfahren = createKnxGroupIfNotExists("Flur Rollladen Position Anfahren", new GroupAddress(0, 5, 13), "5.001", PropertyType.PERCENT, false, false);
|
||||||
final KnxGroupDto bad_licht_mitteschalten = createKnxGroupIfNotExists("Bad Licht Mitte Schalten", 797, "1.001", false, false);
|
final KnxGroupDto bad_licht_mitte_schalten = createKnxGroupIfNotExists("Bad Licht Mitte Schalten", 797, "1.001", PropertyType.ON_OFF, false, false);
|
||||||
final KnxGroupDto helligkeit = createKnxGroupIfNotExists("Helligkeit", 1286, "9.004", false, true);
|
final KnxGroupDto helligkeit = createKnxGroupIfNotExists("Helligkeit", 1286, "9.004", PropertyType.LUX, false, true);
|
||||||
|
|
||||||
if (scheduleRepository.count() == 0) {
|
if (scheduleRepository.count() == 0) {
|
||||||
final Schedule scheduleEgFlurLicht = new Schedule();
|
final Schedule scheduleEgFlurLicht = createSchedule("EG Flur Licht", eg_flur_licht_schalten);
|
||||||
scheduleEgFlurLicht.setEnabled(true);
|
createTime(scheduleEgFlurLicht, 11, 30, 0, MIN30, true);
|
||||||
scheduleEgFlurLicht.setName("EG Flur Licht");
|
createTime(scheduleEgFlurLicht, 12, 30, 0, MIN30, false);
|
||||||
createTime(scheduleEgFlurLicht, 11, 30, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, true));
|
createTime(scheduleEgFlurLicht, 16, 30, 0, MIN30, true);
|
||||||
createTime(scheduleEgFlurLicht, 12, 30, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, false));
|
createTime(scheduleEgFlurLicht, 17, 30, 0, MIN30, false);
|
||||||
createTime(scheduleEgFlurLicht, 16, 30, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, true));
|
createTime(scheduleEgFlurLicht, 22, 0, 0, MIN30, true);
|
||||||
createTime(scheduleEgFlurLicht, 17, 30, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, false));
|
createTime(scheduleEgFlurLicht, 23, 0, 0, MIN30, false);
|
||||||
createTime(scheduleEgFlurLicht, 22, 0, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, true));
|
createTime(scheduleEgFlurLicht, 1, 0, 0, MIN30, true);
|
||||||
createTime(scheduleEgFlurLicht, 23, 0, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, false));
|
createTime(scheduleEgFlurLicht, 2, 0, 0, MIN30, false);
|
||||||
createTime(scheduleEgFlurLicht, 1, 0, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, true));
|
|
||||||
createTime(scheduleEgFlurLicht, 2, 0, 0, MIN30, new PropertyEntry(eg_flur_licht_schalten, false));
|
|
||||||
scheduleRepository.save(scheduleEgFlurLicht);
|
scheduleRepository.save(scheduleEgFlurLicht);
|
||||||
|
|
||||||
final Schedule scheduleEgAmbiente = new Schedule();
|
final Schedule scheduleEgAmbiente = createSchedule("EG Ambiente", eg_ambiente_schalten);
|
||||||
scheduleEgAmbiente.setEnabled(true);
|
createTime(scheduleEgAmbiente, 7, 15, 0, MIN30, true);
|
||||||
scheduleEgAmbiente.setName("EG Ambiente");
|
createTime(scheduleEgAmbiente, 9, 30, 0, MIN30, false);
|
||||||
createTime(scheduleEgAmbiente, 7, 15, 0, MIN30, new PropertyEntry(eg_ambiente_schalten, true));
|
createSunset(scheduleEgAmbiente, Zenith.OFFICIAL, MIN30, true);
|
||||||
createTime(scheduleEgAmbiente, 9, 30, 0, MIN30, new PropertyEntry(eg_ambiente_schalten, false));
|
createSunset(scheduleEgAmbiente, Zenith.ASTRONOMICAL, MIN30, false);
|
||||||
createSunset(scheduleEgAmbiente, Zenith.OFFICIAL, MIN30, new PropertyEntry(eg_ambiente_schalten, true));
|
|
||||||
createSunset(scheduleEgAmbiente, Zenith.ASTRONOMICAL, MIN30, new PropertyEntry(eg_ambiente_schalten, false));
|
|
||||||
scheduleRepository.save(scheduleEgAmbiente);
|
scheduleRepository.save(scheduleEgAmbiente);
|
||||||
|
|
||||||
final Schedule scheduleOgAmbiente = new Schedule();
|
final Schedule scheduleOgAmbiente = createSchedule("OG Ambiente", og_ambiente_schalten);
|
||||||
scheduleOgAmbiente.setEnabled(true);
|
createTime(scheduleOgAmbiente, 7, 15, 0, MIN30, true);
|
||||||
scheduleOgAmbiente.setName("OG Ambiente");
|
createTime(scheduleOgAmbiente, 9, 30, 0, MIN30, false);
|
||||||
createTime(scheduleOgAmbiente, 7, 15, 0, MIN30, new PropertyEntry(og_ambiente_schalten, true));
|
createSunset(scheduleOgAmbiente, Zenith.OFFICIAL, MIN30, true);
|
||||||
createTime(scheduleOgAmbiente, 9, 30, 0, MIN30, new PropertyEntry(og_ambiente_schalten, false));
|
createSunset(scheduleOgAmbiente, Zenith.ASTRONOMICAL, MIN30, false);
|
||||||
createSunset(scheduleOgAmbiente, Zenith.OFFICIAL, MIN30, new PropertyEntry(og_ambiente_schalten, true));
|
|
||||||
createSunset(scheduleOgAmbiente, Zenith.ASTRONOMICAL, MIN30, new PropertyEntry(og_ambiente_schalten, false));
|
|
||||||
scheduleRepository.save(scheduleOgAmbiente);
|
scheduleRepository.save(scheduleOgAmbiente);
|
||||||
|
|
||||||
final Schedule scheduleWohnzimmerRollladen = new Schedule();
|
final Schedule scheduleWohnzimmerRollladen = createSchedule("Rollläden Wohnzimmer", wohnzimmer_rollladen_position_anfahren);
|
||||||
scheduleWohnzimmerRollladen.setEnabled(true);
|
createSunrise(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, 0);
|
||||||
scheduleWohnzimmerRollladen.setName("Rollläden Wohnzimmer");
|
createSunset(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, 100);
|
||||||
createSunrise(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, new PropertyEntry(wohnzimmer_rollladen_position_anfahren, 0));
|
|
||||||
createSunset(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, new PropertyEntry(wohnzimmer_rollladen_position_anfahren, 100));
|
|
||||||
scheduleRepository.save(scheduleWohnzimmerRollladen);
|
scheduleRepository.save(scheduleWohnzimmerRollladen);
|
||||||
|
|
||||||
final Schedule scheduleSchlafzimmerRollladen = new Schedule();
|
final Schedule scheduleSchlafzimmerRollladen = createSchedule("Rollläden Schlafzimmer", schlafzimmer_rollladen_position_anfahren);
|
||||||
scheduleSchlafzimmerRollladen.setEnabled(true);
|
createTime(scheduleSchlafzimmerRollladen, 7, 0, 0, 0, 0);
|
||||||
scheduleSchlafzimmerRollladen.setName("Rollläden Schlafzimmer");
|
createSunset(scheduleSchlafzimmerRollladen, Zenith.CIVIL, 0, 100);
|
||||||
createTime(scheduleSchlafzimmerRollladen, 7, 0, 0, 0, new PropertyEntry(schlafzimmer_rollladen_position_anfahren, 0));
|
|
||||||
createSunset(scheduleSchlafzimmerRollladen, Zenith.CIVIL, 0, new PropertyEntry(schlafzimmer_rollladen_position_anfahren, 100));
|
|
||||||
scheduleRepository.save(scheduleSchlafzimmerRollladen);
|
scheduleRepository.save(scheduleSchlafzimmerRollladen);
|
||||||
|
|
||||||
final Schedule scheduleFlurRollladen = new Schedule();
|
final Schedule scheduleFlurRollladen = createSchedule("Rollläden Flur", flur_rollladen_position_anfahren);
|
||||||
scheduleFlurRollladen.setEnabled(true);
|
createSunrise(scheduleFlurRollladen, Zenith.CIVIL, 0, 0);
|
||||||
scheduleFlurRollladen.setName("Rollläden Flur");
|
createSunset(scheduleFlurRollladen, Zenith.CIVIL, 0, 100);
|
||||||
createSunrise(scheduleFlurRollladen, Zenith.CIVIL, 0, new PropertyEntry(flur_rollladen_position_anfahren, 0));
|
|
||||||
createSunset(scheduleFlurRollladen, Zenith.CIVIL, 0, new PropertyEntry(flur_rollladen_position_anfahren, 100));
|
|
||||||
scheduleRepository.save(scheduleFlurRollladen);
|
scheduleRepository.save(scheduleFlurRollladen);
|
||||||
|
|
||||||
final Schedule scheduleBadLichtMitte = new Schedule();
|
final Schedule scheduleBadLichtMitte = createSchedule("Bad Licht Mitte", bad_licht_mitte_schalten);
|
||||||
scheduleBadLichtMitte.setEnabled(true);
|
createTime(scheduleBadLichtMitte, 10, 30, 0, MIN30, true);
|
||||||
scheduleBadLichtMitte.setName("Bad Licht Mitte");
|
createTime(scheduleBadLichtMitte, 11, 30, 0, MIN30, false);
|
||||||
createTime(scheduleBadLichtMitte, 10, 30, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, true));
|
createTime(scheduleBadLichtMitte, 15, 30, 0, MIN30, true);
|
||||||
createTime(scheduleBadLichtMitte, 11, 30, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, false));
|
createTime(scheduleBadLichtMitte, 16, 30, 0, MIN30, false);
|
||||||
createTime(scheduleBadLichtMitte, 15, 30, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, true));
|
createTime(scheduleBadLichtMitte, 21, 0, 0, MIN30, true);
|
||||||
createTime(scheduleBadLichtMitte, 16, 30, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, false));
|
createTime(scheduleBadLichtMitte, 22, 0, 0, MIN30, false);
|
||||||
createTime(scheduleBadLichtMitte, 21, 0, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, true));
|
createTime(scheduleBadLichtMitte, 0, 0, 0, MIN30, true);
|
||||||
createTime(scheduleBadLichtMitte, 22, 0, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, false));
|
createTime(scheduleBadLichtMitte, 1, 0, 0, MIN30, false);
|
||||||
createTime(scheduleBadLichtMitte, 0, 0, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, true));
|
|
||||||
createTime(scheduleBadLichtMitte, 1, 0, 0, MIN30, new PropertyEntry(bad_licht_mitteschalten, false));
|
|
||||||
scheduleRepository.save(scheduleBadLichtMitte);
|
scheduleRepository.save(scheduleBadLichtMitte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KnxGroupDto createKnxGroupIfNotExists(final String name, final int address, final String dpt, final boolean readable, final boolean multiGroup) {
|
private Schedule createSchedule(final String s, final KnxGroupDto knxGroupDto) {
|
||||||
return createKnxGroupIfNotExists(name, new GroupAddress(address), dpt, readable, multiGroup);
|
final Schedule schedule = new Schedule();
|
||||||
|
schedule.setEnabled(true);
|
||||||
|
schedule.setName(s);
|
||||||
|
schedule.setPropertyName(knxGroupDto.propertyName);
|
||||||
|
schedule.setPropertyType(knxGroupDto.getPropertyType());
|
||||||
|
return schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KnxGroupDto createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final boolean readable, final boolean multiGroup) {
|
private KnxGroupDto createKnxGroupIfNotExists(final String name, final int address, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) {
|
||||||
return knxGroupRepository.findByAddressRaw(address.getRawAddress()).map(KnxGroupDto::new).orElseGet(() -> knxGroupWriteService.create(name, address, dpt, readable, multiGroup));
|
return createKnxGroupIfNotExists(name, new GroupAddress(address), dpt, type, readable, multiGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createRelative(final Schedule schedule, final int inSeconds, final int fuzzySeconds, final Map.Entry<String, String>... entries) {
|
private KnxGroupDto createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) {
|
||||||
|
return knxGroupRepository.findByAddressRaw(address.getRawAddress()).map(KnxGroupDto::new).orElseGet(() -> knxGroupWriteService.create(name, address, dpt, type, readable, multiGroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScheduleEntry createRelative(final Schedule schedule, final int inSeconds, final int fuzzySeconds, final Object value) {
|
||||||
final ZonedDateTime now = ZonedDateTime.now().plusSeconds(inSeconds).withNano(0);
|
final ZonedDateTime now = ZonedDateTime.now().plusSeconds(inSeconds).withNano(0);
|
||||||
return newScheduleEntry(schedule, ScheduleEntryType.TIME, null, now.getHour(), now.getMinute(), now.getSecond(), fuzzySeconds, entries);
|
return newScheduleEntry(schedule, ScheduleEntryType.TIME, null, now.getHour(), now.getMinute(), now.getSecond(), fuzzySeconds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createTime(final Schedule schedule, final int hour, final int minute, final int second, final int fuzzySeconds, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry createTime(final Schedule schedule, final int hour, final int minute, final int second, final int fuzzySeconds, final Object value) {
|
||||||
return newScheduleEntry(schedule, ScheduleEntryType.TIME, null, hour, minute, second, fuzzySeconds, entries);
|
return newScheduleEntry(schedule, ScheduleEntryType.TIME, null, hour, minute, second, fuzzySeconds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createSunrise(final Schedule schedule, final Zenith zenith, final int fuzzySeconds, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry createSunrise(final Schedule schedule, final Zenith zenith, final int fuzzySeconds, final Object value) {
|
||||||
return newScheduleEntry(schedule, ScheduleEntryType.SUNRISE, zenith, 0, 0, 0, fuzzySeconds, entries);
|
return newScheduleEntry(schedule, ScheduleEntryType.SUNRISE, zenith, 0, 0, 0, fuzzySeconds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry createSunset(final Schedule schedule, final Zenith zenith, final int fuzzySeconds, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry createSunset(final Schedule schedule, final Zenith zenith, final int fuzzySeconds, final Object value) {
|
||||||
return newScheduleEntry(schedule, ScheduleEntryType.SUNSET, zenith, 0, 0, 0, fuzzySeconds, entries);
|
return newScheduleEntry(schedule, ScheduleEntryType.SUNSET, zenith, 0, 0, 0, fuzzySeconds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScheduleEntry newScheduleEntry(final Schedule schedule, final ScheduleEntryType type, final Zenith zenith, final int hour, final int minute, final int second, final int fuzzySeconds, final Map.Entry<String, String>... entries) {
|
private ScheduleEntry newScheduleEntry(final Schedule schedule, 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();
|
final ScheduleEntry entry = new ScheduleEntry();
|
||||||
entry.setEnabled(true);
|
entry.setEnabled(true);
|
||||||
entry.setType(type);
|
entry.setType(type);
|
||||||
@ -148,7 +141,15 @@ public class DemoDataService {
|
|||||||
entry.setMinute(minute);
|
entry.setMinute(minute);
|
||||||
entry.setSecond(second);
|
entry.setSecond(second);
|
||||||
entry.setFuzzySeconds(fuzzySeconds);
|
entry.setFuzzySeconds(fuzzySeconds);
|
||||||
Arrays.stream(entries).forEach(p -> entry.getProperties().put(p.getKey(), p.getValue()));
|
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);
|
schedule.getEntries().add(entry);
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -20,16 +21,21 @@ public class KnxGroup {
|
|||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
private int addressRaw;
|
private int addressRaw;
|
||||||
|
|
||||||
@Column(unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
private String addressStr;
|
private String addressStr;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
private String dpt;
|
private String dpt;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private PropertyType propertyType;
|
||||||
|
|
||||||
private byte[] value;
|
private byte[] value;
|
||||||
|
|
||||||
private int lastDeviceAddressRaw;
|
private int lastDeviceAddressRaw;
|
||||||
@ -46,6 +52,7 @@ public class KnxGroup {
|
|||||||
|
|
||||||
private int readInterval;
|
private int readInterval;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
private boolean multiGroup;
|
private boolean multiGroup;
|
||||||
|
|
||||||
@Embedded
|
@Embedded
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
@ -19,6 +20,8 @@ public class KnxGroupDto {
|
|||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
|
public final PropertyType propertyType;
|
||||||
|
|
||||||
public final Boolean booleanValue;
|
public final Boolean booleanValue;
|
||||||
|
|
||||||
public final Double numberValue;
|
public final Double numberValue;
|
||||||
@ -32,6 +35,8 @@ public class KnxGroupDto {
|
|||||||
propertyName = knxGroup.getPropertyName();
|
propertyName = knxGroup.getPropertyName();
|
||||||
dpt = knxGroup.getDpt();
|
dpt = knxGroup.getDpt();
|
||||||
name = knxGroup.getName();
|
name = knxGroup.getName();
|
||||||
|
propertyType = knxGroup.getPropertyType();
|
||||||
|
|
||||||
booleanValue = knxGroup.getBooleanValue();
|
booleanValue = knxGroup.getBooleanValue();
|
||||||
numberValue = knxGroup.getNumberValue();
|
numberValue = knxGroup.getNumberValue();
|
||||||
valueTimestamp = knxGroup.getValueTimestamp();
|
valueTimestamp = knxGroup.getValueTimestamp();
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
import static de.ph87.homeautomation.shared.Helpers.quoteOrNull;
|
|
||||||
|
|
||||||
public class KnxGroupFormatException extends Exception {
|
public class KnxGroupFormatException extends Exception {
|
||||||
|
|
||||||
public KnxGroupFormatException(final KnxGroup knxGroup, final String value, final String reason) {
|
public KnxGroupFormatException(final KnxGroup knxGroup, final double value, final String reason) {
|
||||||
super(String.format("Cannot use value %s (%s) to set KnxGroup: %s", quoteOrNull(value), reason, knxGroup));
|
super(String.format("Cannot use value %f (%s) to set KnxGroup: %s", value, reason, knxGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ public class KnxGroupSetService implements IPropertyOwner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProperty(final String propertyName, final String value) throws PropertySetException {
|
public void setProperty(final String propertyName, final double value) throws PropertySetException {
|
||||||
final GroupAddress groupAddress = parseGroupAddress(propertyName);
|
final GroupAddress groupAddress = parseGroupAddress(propertyName);
|
||||||
try {
|
try {
|
||||||
if (knxGroupWriteService.setSendValue(groupAddress, value)) {
|
if (knxGroupWriteService.setSendValue(groupAddress, value)) {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -16,7 +17,6 @@ import java.io.IOException;
|
|||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@ -108,17 +108,18 @@ public class KnxGroupWriteService {
|
|||||||
knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()));
|
knxGroupRepository.findAllByRead_AbleTrue().forEach(knxGroup -> knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public KnxGroupDto create(final String name, final GroupAddress address, final String dpt, final boolean readable, final boolean multiGroup) {
|
public KnxGroupDto create(final String name, final GroupAddress address, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) {
|
||||||
final KnxGroup trans = new KnxGroup();
|
final KnxGroup trans = new KnxGroup();
|
||||||
trans.setAddress(address);
|
trans.setAddress(address);
|
||||||
trans.setDpt(dpt);
|
trans.setDpt(dpt);
|
||||||
trans.setMultiGroup(multiGroup);
|
trans.setMultiGroup(multiGroup);
|
||||||
trans.setName(name);
|
trans.setName(name);
|
||||||
|
trans.setPropertyType(type);
|
||||||
trans.getRead().setAble(readable);
|
trans.getRead().setAble(readable);
|
||||||
return new KnxGroupDto(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 double value) throws KnxGroupFormatException {
|
||||||
final Optional<KnxGroup> knxGroupOptional = knxGroupRepository.findByAddressRaw(groupAddress.getRawAddress());
|
final Optional<KnxGroup> knxGroupOptional = knxGroupRepository.findByAddressRaw(groupAddress.getRawAddress());
|
||||||
if (knxGroupOptional.isEmpty()) {
|
if (knxGroupOptional.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
@ -128,16 +129,11 @@ public class KnxGroupWriteService {
|
|||||||
try {
|
try {
|
||||||
final DPTXlator translator = findTranslator(knxGroup);
|
final DPTXlator translator = findTranslator(knxGroup);
|
||||||
if (translator instanceof DPTXlatorBoolean) {
|
if (translator instanceof DPTXlatorBoolean) {
|
||||||
final boolean isTrue = Objects.equals(value, "true");
|
((DPTXlatorBoolean) translator).setValue(value == 1.0);
|
||||||
final boolean isFalse = Objects.equals(value, "false");
|
|
||||||
if (!isTrue && !isFalse) {
|
|
||||||
throw new KnxGroupFormatException(knxGroup, value, "Must be \"true\" or \"false\".");
|
|
||||||
}
|
|
||||||
((DPTXlatorBoolean) translator).setValue(isTrue);
|
|
||||||
} else if (translator instanceof DPTXlator8BitUnsigned) {
|
} else if (translator instanceof DPTXlator8BitUnsigned) {
|
||||||
((DPTXlator8BitUnsigned) translator).setValue(Integer.parseInt(value));
|
((DPTXlator8BitUnsigned) translator).setValue((int) value);
|
||||||
} else { // TODO implement all DPTXlator...
|
} else { // TODO implement all DPTXlator...
|
||||||
translator.setValue(value);
|
translator.setValue("" + value);
|
||||||
}
|
}
|
||||||
knxGroup.setSendValue(translator.getData());
|
knxGroup.setSendValue(translator.getData());
|
||||||
knxGroup.getSend().setNextTimestamp(ZonedDateTime.now());
|
knxGroup.getSend().setNextTimestamp(ZonedDateTime.now());
|
||||||
|
|||||||
@ -7,7 +7,7 @@ public interface IPropertyOwner {
|
|||||||
|
|
||||||
Pattern getPropertyNamePattern();
|
Pattern getPropertyNamePattern();
|
||||||
|
|
||||||
void setProperty(final String propertyName, final String value) throws PropertySetException;
|
void setProperty(final String propertyName, final double value) throws PropertySetException;
|
||||||
|
|
||||||
Boolean readBoolean(String propertyName);
|
Boolean readBoolean(String propertyName);
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ public class PropertyService {
|
|||||||
|
|
||||||
private final Set<IPropertyOwner> propertyOwners;
|
private final Set<IPropertyOwner> propertyOwners;
|
||||||
|
|
||||||
public void set(final String propertyName, final String value) throws PropertySetException {
|
public void set(final String propertyName, final double value) throws PropertySetException {
|
||||||
log.debug("Setting property \"{}\" => {}", propertyName, value);
|
log.debug("Setting property \"{}\" => {}", propertyName, value);
|
||||||
getOwnerOrThrow(propertyName).setProperty(propertyName, value);
|
getOwnerOrThrow(propertyName).setProperty(propertyName, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,8 @@ package de.ph87.homeautomation.property;
|
|||||||
|
|
||||||
public class PropertySetException extends Exception {
|
public class PropertySetException extends Exception {
|
||||||
|
|
||||||
public PropertySetException(final String propertyName, final String value, final Exception e) {
|
public PropertySetException(final String propertyName, final double value, final Exception e) {
|
||||||
super(String.format("Failed to set property %s to value %s: %s", propertyName, value, e.getMessage()));
|
super(String.format("Failed to set property %s to value %f: %s", propertyName, value, e.getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
package de.ph87.homeautomation.property;
|
||||||
|
|
||||||
|
public enum PropertyType {
|
||||||
|
ON_OFF, PERCENT, LUX
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.schedule;
|
package de.ph87.homeautomation.schedule;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
|
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -26,6 +27,12 @@ public class Schedule {
|
|||||||
@Column(nullable = false, unique = true)
|
@Column(nullable = false, unique = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String propertyName;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private PropertyType propertyType;
|
||||||
|
|
||||||
@ToString.Exclude
|
@ToString.Exclude
|
||||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
|
||||||
private Set<ScheduleEntry> entries = new HashSet<>();
|
private Set<ScheduleEntry> entries = new HashSet<>();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.schedule;
|
package de.ph87.homeautomation.schedule;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import de.ph87.homeautomation.schedule.entry.ScheduleEntryDto;
|
import de.ph87.homeautomation.schedule.entry.ScheduleEntryDto;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@ -15,13 +16,19 @@ public class ScheduleDto {
|
|||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
|
public final String propertyName;
|
||||||
|
|
||||||
|
public final PropertyType propertyType;
|
||||||
|
|
||||||
public final Set<ScheduleEntryDto> entries;
|
public final Set<ScheduleEntryDto> entries;
|
||||||
|
|
||||||
public ScheduleDto(final Schedule schedule) {
|
public ScheduleDto(final Schedule schedule) {
|
||||||
id = schedule.getId();
|
this.id = schedule.getId();
|
||||||
enabled = schedule.isEnabled();
|
this.enabled = schedule.isEnabled();
|
||||||
name = schedule.getName();
|
this.name = schedule.getName();
|
||||||
entries = schedule.getEntries().stream().map(ScheduleEntryDto::new).collect(Collectors.toSet());
|
this.propertyName = schedule.getPropertyName();
|
||||||
|
this.propertyType = schedule.getPropertyType();
|
||||||
|
this.entries = schedule.getEntries().stream().map(ScheduleEntryDto::new).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,20 +32,18 @@ public class ScheduleExecutionService {
|
|||||||
schedule.getEntries().stream()
|
schedule.getEntries().stream()
|
||||||
.filter(entry -> entry.getNextFuzzyTimestamp() != null && !entry.getNextFuzzyTimestamp().isAfter(now))
|
.filter(entry -> entry.getNextFuzzyTimestamp() != null && !entry.getNextFuzzyTimestamp().isAfter(now))
|
||||||
.max(Comparator.comparing(ScheduleEntry::getNextFuzzyTimestamp))
|
.max(Comparator.comparing(ScheduleEntry::getNextFuzzyTimestamp))
|
||||||
.ifPresent(entry -> {
|
.ifPresent(entry -> executeEntry(schedule, entry, now));
|
||||||
entry.setLastClearTimestamp(entry.getNextClearTimestamp());
|
|
||||||
log.info("Executing Schedule \"{}\" Entry {}", schedule.getName(), entry);
|
|
||||||
entry.getProperties().forEach(this::applyPropertyMapEntry);
|
|
||||||
scheduleCalculationService.calculateSchedule(schedule, now);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyPropertyMapEntry(final String propertyName, final String value) {
|
private void executeEntry(final Schedule schedule, final ScheduleEntry entry, final ZonedDateTime now) {
|
||||||
|
entry.setLastClearTimestamp(entry.getNextClearTimestamp());
|
||||||
|
log.info("Executing Schedule \"{}\" Entry {}", schedule.getName(), entry);
|
||||||
try {
|
try {
|
||||||
propertyService.set(propertyName, value);
|
propertyService.set(schedule.getPropertyName(), entry.getValue());
|
||||||
} catch (PropertySetException e) {
|
} catch (PropertySetException e) {
|
||||||
log.error(e.getMessage());
|
log.error(e.getMessage());
|
||||||
}
|
}
|
||||||
|
scheduleCalculationService.calculateSchedule(schedule, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,10 +5,11 @@ import lombok.AccessLevel;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -52,6 +53,8 @@ public class ScheduleEntry {
|
|||||||
|
|
||||||
private int fuzzySeconds = 0;
|
private int fuzzySeconds = 0;
|
||||||
|
|
||||||
|
private double value = 0;
|
||||||
|
|
||||||
private ZonedDateTime nextClearTimestamp;
|
private ZonedDateTime nextClearTimestamp;
|
||||||
|
|
||||||
private ZonedDateTime lastClearTimestamp;
|
private ZonedDateTime lastClearTimestamp;
|
||||||
@ -59,9 +62,6 @@ public class ScheduleEntry {
|
|||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
private ZonedDateTime nextFuzzyTimestamp;
|
private ZonedDateTime nextFuzzyTimestamp;
|
||||||
|
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
|
||||||
private Map<String, String> properties = new HashMap<>();
|
|
||||||
|
|
||||||
public void setNextClearTimestamp(final ZonedDateTime next) {
|
public void setNextClearTimestamp(final ZonedDateTime next) {
|
||||||
nextClearTimestamp = next;
|
nextClearTimestamp = next;
|
||||||
if (nextClearTimestamp == null) {
|
if (nextClearTimestamp == null) {
|
||||||
|
|||||||
@ -80,9 +80,19 @@ public class ScheduleEntryController {
|
|||||||
return scheduleEntryWriteService.set(id, ScheduleEntry::setMinute, value);
|
return scheduleEntryWriteService.set(id, ScheduleEntry::setMinute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("set/{id}/second")
|
||||||
|
public ScheduleEntryDto setSecond(@PathVariable final long id, @RequestBody final int value) {
|
||||||
|
return scheduleEntryWriteService.set(id, ScheduleEntry::setSecond, value);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("set/{id}/fuzzySeconds")
|
@PostMapping("set/{id}/fuzzySeconds")
|
||||||
public ScheduleEntryDto setFuzzySeconds(@PathVariable final long id, @RequestBody final int value) {
|
public ScheduleEntryDto setFuzzySeconds(@PathVariable final long id, @RequestBody final int value) {
|
||||||
return scheduleEntryWriteService.set(id, ScheduleEntry::setFuzzySeconds, value);
|
return scheduleEntryWriteService.set(id, ScheduleEntry::setFuzzySeconds, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("set/{id}/value")
|
||||||
|
public ScheduleEntryDto setValue(@PathVariable final long id, @RequestBody final double value) {
|
||||||
|
return scheduleEntryWriteService.set(id, ScheduleEntry::setValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,6 @@ package de.ph87.homeautomation.schedule.entry;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class ScheduleEntryDto {
|
public class ScheduleEntryDto {
|
||||||
@ -44,28 +43,28 @@ public class ScheduleEntryDto {
|
|||||||
|
|
||||||
public final ZonedDateTime nextFuzzyTimestamp;
|
public final ZonedDateTime nextFuzzyTimestamp;
|
||||||
|
|
||||||
public final Map<String, String> properties;
|
public final double value;
|
||||||
|
|
||||||
public ScheduleEntryDto(final ScheduleEntry scheduleEntry) {
|
public ScheduleEntryDto(final ScheduleEntry entry) {
|
||||||
id = scheduleEntry.getId();
|
this.id = entry.getId();
|
||||||
enabled = scheduleEntry.isEnabled();
|
this.enabled = entry.isEnabled();
|
||||||
monday = scheduleEntry.isMonday();
|
this.monday = entry.isMonday();
|
||||||
tuesday = scheduleEntry.isTuesday();
|
this.tuesday = entry.isTuesday();
|
||||||
wednesday = scheduleEntry.isWednesday();
|
this.wednesday = entry.isWednesday();
|
||||||
thursday = scheduleEntry.isThursday();
|
this.thursday = entry.isThursday();
|
||||||
friday = scheduleEntry.isFriday();
|
this.friday = entry.isFriday();
|
||||||
saturday = scheduleEntry.isSaturday();
|
this.saturday = entry.isSaturday();
|
||||||
sunday = scheduleEntry.isSunday();
|
this.sunday = entry.isSunday();
|
||||||
type = scheduleEntry.getType();
|
this.type = entry.getType();
|
||||||
zenith = scheduleEntry.getZenith();
|
this.zenith = entry.getZenith();
|
||||||
hour = scheduleEntry.getHour();
|
this.hour = entry.getHour();
|
||||||
minute = scheduleEntry.getMinute();
|
this.minute = entry.getMinute();
|
||||||
second = scheduleEntry.getSecond();
|
this.second = entry.getSecond();
|
||||||
fuzzySeconds = scheduleEntry.getFuzzySeconds();
|
this.fuzzySeconds = entry.getFuzzySeconds();
|
||||||
nextClearTimestamp = scheduleEntry.getNextClearTimestamp();
|
this.nextClearTimestamp = entry.getNextClearTimestamp();
|
||||||
lastClearTimestamp = scheduleEntry.getLastClearTimestamp();
|
this.lastClearTimestamp = entry.getLastClearTimestamp();
|
||||||
nextFuzzyTimestamp = scheduleEntry.getNextFuzzyTimestamp();
|
this.nextFuzzyTimestamp = entry.getNextFuzzyTimestamp();
|
||||||
properties = Map.copyOf(scheduleEntry.getProperties());
|
this.value = entry.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import lombok.Getter;
|
|||||||
|
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -15,12 +14,12 @@ public class ScheduleNextExecutionDto {
|
|||||||
|
|
||||||
public final ZonedDateTime nextTimestamp;
|
public final ZonedDateTime nextTimestamp;
|
||||||
|
|
||||||
public final HashMap<String, String> properties;
|
public final double numberValue;
|
||||||
|
|
||||||
private ScheduleNextExecutionDto(final Schedule schedule, final ScheduleEntry entry) {
|
private ScheduleNextExecutionDto(final Schedule schedule, final ScheduleEntry entry) {
|
||||||
this.name = schedule.getName();
|
this.name = schedule.getName();
|
||||||
this.nextTimestamp = entry.getNextFuzzyTimestamp();
|
this.nextTimestamp = entry.getNextFuzzyTimestamp();
|
||||||
this.properties = new HashMap<>(entry.getProperties());
|
this.numberValue = entry.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Optional<ScheduleNextExecutionDto> create(final Schedule schedule, final ZonedDateTime now) {
|
public static Optional<ScheduleNextExecutionDto> create(final Schedule schedule, final ZonedDateTime now) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user