diff --git a/src/main/angular/src/app/api/device/Device.ts b/src/main/angular/src/app/api/device/Device.ts index e5019bd..351adbd 100644 --- a/src/main/angular/src/app/api/device/Device.ts +++ b/src/main/angular/src/app/api/device/Device.ts @@ -1,4 +1,4 @@ -import {validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators"; +import {validateListOrEmpty, validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators"; import {Property} from "../property/Property"; export abstract class Device { @@ -21,6 +21,15 @@ export abstract class Device { type, Property.fromJsonAllowNull(json['stateProperty']), ); + case "DeviceStateScene": + return new DeviceStateScene( + validateNumberNotNull(json['id']), + validateStringNotEmptyNotNull(json['title']), + type, + Property.fromJsonAllowNull(json['stateProperty']), + Property.fromJsonAllowNull(json['sceneProperty']), + validateListOrEmpty(json['sceneNumbers'], parseInt), + ); case "DeviceShutter": return new DeviceShutter( validateNumberNotNull(json['id']), @@ -67,6 +76,28 @@ export class DeviceSwitch extends Device { } +export class DeviceStateScene extends DeviceSwitch { + + constructor( + id: number, + title: string, + type: string, + stateProperty: Property | null, + public sceneProperty: Property | null, + public sceneNumbers: number[], + ) { + super(id, title, type, stateProperty); + } + + updateProperty(property: Property): void { + super.updateProperty(property); + if (this.sceneProperty?.id === property.id) { + this.sceneProperty = property; + } + } + +} + export class DeviceShutter extends Device { constructor( diff --git a/src/main/angular/src/app/api/device/device.service.ts b/src/main/angular/src/app/api/device/device.service.ts index ba9731c..8b6648c 100644 --- a/src/main/angular/src/app/api/device/device.service.ts +++ b/src/main/angular/src/app/api/device/device.service.ts @@ -1,6 +1,8 @@ import {Injectable} from '@angular/core'; import {ApiService, NO_COMPARE, NO_OP} from "../api.service"; -import {Device} from "./Device"; +import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "./Device"; +import {Update} from "../Update"; +import {PropertyService} from "../property/property.service"; @Injectable({ providedIn: 'root' @@ -9,10 +11,15 @@ export class DeviceService { constructor( readonly api: ApiService, + readonly propertyService: PropertyService, ) { // nothing } + subscribe(next: (device: Update) => void): void { + this.api.subscribe("DeviceDto", Device.fromJson, next); + } + findAll(next: (list: Device[]) => void, compare: (a: Device, b: Device) => number = NO_COMPARE, error: (error: any) => void = NO_OP): void { this.api.getList("device/findAll", Device.fromJson, compare, next, error); } @@ -21,14 +28,42 @@ export class DeviceService { this.api.postReturnItem("device/set/" + device.id + "/" + key, value, Device.fromJson, next, error); } - setDeviceSwitch(device: Device, key: string, value: any, next: (item: Device) => void, error: (error: any) => void = NO_OP): void { + setDeviceSwitch(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP, error: (error: any) => void = NO_OP): void { this.api.postReturnItem("device/set/" + device.id + "/DeviceSwitch/" + key, value, Device.fromJson, next, error); } - setDeviceShutter(device: Device, key: string, value: any, next: (item: Device) => void, error: (error: any) => void = NO_OP): void { + setDeviceStateScene(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP, error: (error: any) => void = NO_OP): void { + this.api.postReturnItem("device/set/" + device.id + "/DeviceStateScene/" + key, value, Device.fromJson, next, error); + } + + setDeviceShutter(device: Device, key: string, value: any, next: (item: Device) => void = NO_OP, error: (error: any) => void = NO_OP): void { this.api.postReturnItem("device/set/" + device.id + "/DeviceShutter/" + key, value, Device.fromJson, next, error); } + setSwitchState(d: Device, value: boolean): void { + const device: DeviceSwitch = d as DeviceSwitch; + if (!device.stateProperty) { + throw new Error("Property 'stateProperty' not set for: " + device); + } + this.propertyService.set(device.stateProperty, "value", value ? 1 : 0); + } + + setStateScene(d: Device, value: number): void { + const device: DeviceStateScene = d as DeviceStateScene; + if (!device.sceneProperty) { + throw new Error("Property 'sceneProperty' not set for: " + device); + } + this.propertyService.set(device.sceneProperty, "value", value); + } + + setShutterPosition(d: Device, value: number): void { + const device: DeviceShutter = d as DeviceShutter; + if (!device.positionProperty) { + throw new Error("Property 'positionProperty' not set for: " + device); + } + this.propertyService.set(device.positionProperty, "value", value); + } + getById(id: number, next: (item: Device) => void, error: (error: any) => void = NO_OP): void { this.api.getItem("device/getById/" + id, Device.fromJson, next, error); } diff --git a/src/main/angular/src/app/api/validators.ts b/src/main/angular/src/app/api/validators.ts index 993eb11..414830e 100644 --- a/src/main/angular/src/app/api/validators.ts +++ b/src/main/angular/src/app/api/validators.ts @@ -1,3 +1,5 @@ +import {NO_COMPARE} from "./api.service"; + export function validateBooleanNotNull(value: any): boolean { if (value !== true && value !== false) { throw new Error("Not a boolean: " + value); @@ -66,7 +68,7 @@ export function validateDateAllowNull(value: any): Date | null { return validateDateNotNull(value); } -export function validateListOrEmpty(json: any, fromJson: (json: any) => T, compare: (a: T, b: T) => number): T[] { +export function validateListOrEmpty(json: any, fromJson: (json: any) => T, compare: (a: T, b: T) => number = NO_COMPARE): T[] { if (!Array.isArray(json)) { return []; } diff --git a/src/main/angular/src/app/pages/device-list/device-list.component.html b/src/main/angular/src/app/pages/device-list/device-list.component.html index 2ad582a..3f546f6 100644 --- a/src/main/angular/src/app/pages/device-list/device-list.component.html +++ b/src/main/angular/src/app/pages/device-list/device-list.component.html @@ -1,5 +1,14 @@ +
+ + +
+ +
{{device.title}} @@ -8,10 +17,25 @@
- An - Aus + An + Aus
+ +
+
+ {{device.title}} +
+
+ +
+
+
+ {{scene.title}} +
+
+
+
{{device.title}} @@ -20,30 +44,23 @@
-
+
Auf
-
+
50%
-
+
90%
-
+
Schlitze
-
+
Zu
+ - -

- - -

diff --git a/src/main/angular/src/app/pages/device-list/device-list.component.less b/src/main/angular/src/app/pages/device-list/device-list.component.less index e2ec199..123bc42 100644 --- a/src/main/angular/src/app/pages/device-list/device-list.component.less +++ b/src/main/angular/src/app/pages/device-list/device-list.component.less @@ -3,6 +3,12 @@ margin-bottom: 5px; border-radius: 10px; + @media (min-width: 1000px) { + float: left; + width: 400px; + margin-right: 5px; + } + .title { float: left; font-weight: bold; @@ -71,3 +77,8 @@ .shutterUnknown { background-color: gray; } + +.config { + clear: both; + margin-bottom: 5px; +} diff --git a/src/main/angular/src/app/pages/device-list/device-list.component.ts b/src/main/angular/src/app/pages/device-list/device-list.component.ts index dc50033..4982dde 100644 --- a/src/main/angular/src/app/pages/device-list/device-list.component.ts +++ b/src/main/angular/src/app/pages/device-list/device-list.component.ts @@ -1,8 +1,10 @@ import {Component, OnInit} from '@angular/core'; import {DeviceService} from "../../api/device/device.service"; import {PropertyService} from "../../api/property/property.service"; -import {Device, DeviceShutter, DeviceSwitch} from "../../api/device/Device"; +import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../api/device/Device"; import {faEdit} from '@fortawesome/free-regular-svg-icons'; +import {Scene} from "../../api/scene/Scene"; +import {SceneService} from "../../api/scene/scene.service"; @Component({ selector: 'app-device-list', @@ -17,10 +19,13 @@ export class DeviceListComponent implements OnInit { devices: Device[] = []; + scenes: Scene[] = []; + createType: string = "DeviceSwitch"; constructor( readonly deviceService: DeviceService, + readonly sceneService: SceneService, readonly propertyService: PropertyService, ) { // nothing @@ -28,23 +33,12 @@ export class DeviceListComponent implements OnInit { ngOnInit(): void { this.propertyService.subscribe(update => this.devices.forEach(d => d.updateProperty(update.payload))); + + this.deviceService.subscribe(update => this.updateDevice(update.payload, update.existing)); this.deviceService.findAll(devices => this.devices = devices); - } - setSwitchState(d: Device, value: boolean): void { - const device: DeviceSwitch = d as DeviceSwitch; - if (!device.stateProperty) { - throw new Error("Property 'stateProperty' not set for: " + device); - } - this.propertyService.set(device.stateProperty, "value", value ? 1 : 0); - } - - setShutterPosition(d: Device, value: number): void { - const device: DeviceShutter = d as DeviceShutter; - if (!device.positionProperty) { - throw new Error("Property 'positionProperty' not set for: " + device); - } - this.propertyService.set(device.positionProperty, "value", value); + this.sceneService.subscribe(update => this.updateScene(update.payload, update.existing)); + this.sceneService.findAll(scenes => this.scenes = scenes); } create(): void { @@ -66,6 +60,20 @@ export class DeviceListComponent implements OnInit { } } + + private updateScene(scene: Scene, existing: boolean): void { + const index: number = this.scenes.findIndex(p => p.id === scene.id); + if (index >= 0) { + if (existing) { + this.scenes[index] = scene; + } else { + this.scenes.slice(index, 1); + } + } else if (existing) { + this.scenes.push(scene); + } + } + getSwitchClassList(device: Device): object { const value: number | null | undefined = (device as DeviceSwitch).stateProperty?.value; return { @@ -75,6 +83,10 @@ export class DeviceListComponent implements OnInit { }; } + getStateSceneClassList(device: Device): object { + return this.getSwitchClassList(device); + } + getShutterClassList(device: Device): object { const value: number | null | undefined = (device as DeviceShutter).positionProperty?.value; return { @@ -85,4 +97,9 @@ export class DeviceListComponent implements OnInit { }; } + getStateScenes(d: Device): Scene[] { + const device: DeviceStateScene = d as DeviceStateScene; + return device.sceneNumbers.map(sceneNumber => this.scenes.find(scene => scene.number === sceneNumber)).filter(scene => scene !== undefined).map(s => s as Scene); + } + } diff --git a/src/main/angular/src/app/pages/device/device.component.html b/src/main/angular/src/app/pages/device/device.component.html index d53ace1..2f5263c 100644 --- a/src/main/angular/src/app/pages/device/device.component.html +++ b/src/main/angular/src/app/pages/device/device.component.html @@ -13,7 +13,30 @@ Eigenschaft - + + + + + + + + + + + + + + + + + + +
Name + +
Status-Eigenschaft + +
Szene-Eigenschaft +
@@ -30,7 +53,7 @@ Eigenschaft - + diff --git a/src/main/angular/src/app/pages/device/device.component.ts b/src/main/angular/src/app/pages/device/device.component.ts index 00775f2..12f11ef 100644 --- a/src/main/angular/src/app/pages/device/device.component.ts +++ b/src/main/angular/src/app/pages/device/device.component.ts @@ -2,7 +2,7 @@ import {Component, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from "@angular/router"; import {DataService} from "../../data.service"; import {PropertyService} from "../../api/property/property.service"; -import {Device, DeviceShutter, DeviceSwitch} from "../../api/device/Device"; +import {Device, DeviceShutter, DeviceStateScene, DeviceSwitch} from "../../api/device/Device"; import {DeviceService} from "../../api/device/device.service"; @Component({ @@ -16,6 +16,8 @@ export class DeviceComponent implements OnInit { deviceSwitch: DeviceSwitch | undefined; + deviceStateScene: DeviceStateScene | undefined; + deviceShutter: DeviceShutter | undefined; constructor( @@ -39,6 +41,9 @@ export class DeviceComponent implements OnInit { case "DeviceSwitch": this.deviceSwitch = device as DeviceSwitch; break; + case "DeviceStateScene": + this.deviceStateScene = device as DeviceStateScene; + break; case "DeviceShutter": this.deviceShutter = device as DeviceShutter; break; @@ -50,14 +55,6 @@ export class DeviceComponent implements OnInit { this.deviceService.set(this.device, key, value, device => this.setDevice(device)); } - setDeviceSwitch(key: string, value: any): void { - this.deviceService.setDeviceSwitch(this.device, key, value, device => this.setDevice(device)); - } - - setDeviceShutter(key: string, value: any): void { - this.deviceService.setDeviceShutter(this.device, key, value, device => this.setDevice(device)); - } - delete(): void { if (confirm(this.getDeviceTypeTitle() + " \"" + this.device.title + "\" wirklich löschen?")) { this.deviceService.delete(this.device, () => this.router.navigate(["/DeviceList"])); diff --git a/src/main/angular/src/app/pages/property-list/property-list.component.html b/src/main/angular/src/app/pages/property-list/property-list.component.html index 3e8b679..7ea6791 100644 --- a/src/main/angular/src/app/pages/property-list/property-list.component.html +++ b/src/main/angular/src/app/pages/property-list/property-list.component.html @@ -8,14 +8,14 @@ - + - + - + @@ -24,7 +24,7 @@ - + {{property.value ? "An" : "Aus"}} diff --git a/src/main/angular/src/app/pages/property-list/property-list.component.less b/src/main/angular/src/app/pages/property-list/property-list.component.less index e69de29..1922e7f 100644 --- a/src/main/angular/src/app/pages/property-list/property-list.component.less +++ b/src/main/angular/src/app/pages/property-list/property-list.component.less @@ -0,0 +1,3 @@ +table { + width: 100%; +} diff --git a/src/main/angular/src/app/pages/property-list/property-list.component.ts b/src/main/angular/src/app/pages/property-list/property-list.component.ts index 44b6ba8..7e3ff4b 100644 --- a/src/main/angular/src/app/pages/property-list/property-list.component.ts +++ b/src/main/angular/src/app/pages/property-list/property-list.component.ts @@ -32,12 +32,12 @@ export class PropertyListComponent implements OnInit { this.sceneService.subscribe(update => this.updateScene(update.payload, update.existing)); } - setProperty(property: Property, key: string, value: any): void { - this.propertyService.set(property, key, value, property => this.updateProperty(property, true)); + edit(property: Property, key: string, value: any): void { + this.propertyService.set(property, key, value); } setScene(scene: Scene, key: string, value: any): void { - this.sceneService.set(scene, key, value, scene => this.updateScene(scene, true)); + this.sceneService.set(scene, key, value); } private updateProperty(property: Property, existing: boolean): void { diff --git a/src/main/angular/src/app/pages/schedule/schedule.component.html b/src/main/angular/src/app/pages/schedule/schedule.component.html index 6706263..3a3123c 100644 --- a/src/main/angular/src/app/pages/schedule/schedule.component.html +++ b/src/main/angular/src/app/pages/schedule/schedule.component.html @@ -132,7 +132,7 @@ - + {{entry.value ? "An" : "Aus"}} diff --git a/src/main/angular/src/app/shared/search/search.component.html b/src/main/angular/src/app/shared/search/search.component.html index a5b6427..b0d8db4 100644 --- a/src/main/angular/src/app/shared/search/search.component.html +++ b/src/main/angular/src/app/shared/search/search.component.html @@ -10,19 +10,19 @@
- +
-
+
-
-
+
{{selected.value}} [{{selected.key}}]
-
+
{{result.value}} [{{result.key}}] diff --git a/src/main/angular/src/app/shared/search/search.component.ts b/src/main/angular/src/app/shared/search/search.component.ts index 5377125..ffb05b1 100644 --- a/src/main/angular/src/app/shared/search/search.component.ts +++ b/src/main/angular/src/app/shared/search/search.component.ts @@ -9,7 +9,7 @@ import {ISearchService} from "../../api/ISearchService"; }) export class SearchComponent implements OnInit { - private timeout: number | undefined; + private changedTimeout: number | undefined; @ViewChild('input') input2?: ElementRef; @@ -43,6 +43,8 @@ export class SearchComponent implements OnInit { searching: boolean = false; + cancelOnBlur: boolean = true; + constructor() { } @@ -53,14 +55,14 @@ export class SearchComponent implements OnInit { } changed(): void { - this.clearTimeout(); - this.timeout = setTimeout(() => this.doSearch(), 400); + this.clearChangedTimeout(); + this.changedTimeout = setTimeout(() => this.doSearch(), 400); } - private clearTimeout(): void { - if (this.timeout) { - clearTimeout(this.timeout); - this.timeout = undefined; + private clearChangedTimeout(): void { + if (this.changedTimeout) { + clearTimeout(this.changedTimeout); + this.changedTimeout = undefined; } } @@ -80,13 +82,13 @@ export class SearchComponent implements OnInit { this.doSearch(); break; case 'Escape': - this.cancel(); + this.cancelSearch(); break; } } doSearch(): void { - this.clearTimeout(); + this.clearChangedTimeout(); if (!this.term) { this.results = []; } else { @@ -95,13 +97,19 @@ export class SearchComponent implements OnInit { } blur() { - setTimeout(() => this.cancel(), 100); + if (this.cancelOnBlur) { + this.cancelSearch(); + } } - cancel(): void { + cancelSearch(): void { this.searching = false; } + dontCancelOnBlur(): void { + this.cancelOnBlur = false; + } + select(result: KeyValuePair | undefined): void { this.searching = false; this.selected = result; diff --git a/src/main/angular/src/index.html b/src/main/angular/src/index.html index 4c19e05..d3d0ec5 100644 --- a/src/main/angular/src/index.html +++ b/src/main/angular/src/index.html @@ -4,7 +4,7 @@ Angular - + diff --git a/src/main/java/de/ph87/homeautomation/DemoDataService.java b/src/main/java/de/ph87/homeautomation/DemoDataService.java index c54bd5a..9eeca93 100644 --- a/src/main/java/de/ph87/homeautomation/DemoDataService.java +++ b/src/main/java/de/ph87/homeautomation/DemoDataService.java @@ -9,6 +9,7 @@ import de.ph87.homeautomation.knx.group.KnxGroupReadService; 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; @@ -48,16 +49,21 @@ public class DemoDataService { private final SceneWriteService sceneWriteService; public void insertDemoData() { - final Property fernseher = createProperty("fernseher.eg", PropertyType.SWITCH, "Fernseher", knx(0, 0, 20), knx(0, 0, 4)); - final Property verstaerker = createProperty("verstaerker", PropertyType.SWITCH, "Verstärker", knx(0, 3, 57), knx(0, 3, 56)); - final Property garten_steckdosen = createProperty("garten.steckdosen", PropertyType.SWITCH, "Garten Steckdosen", knx(0, 4, 12), knx(0, 4, 11)); - final Property terrasse = createProperty("terrasse", PropertyType.SWITCH, "Terrasse Licht", knx(0, 4, 1), knx(0, 4, 0)); + final Property eg = createProperty("eg.status", PropertyType.BOOLEAN, "Erdgeschoss", knx(0, 4, 2), null); + final Property eg_szene = createProperty("eg.szene", PropertyType.SCENE, "Erdgeschoss Szene", null, knx(0, 0, 1)); + final Property og = createProperty("og.status", PropertyType.BOOLEAN, "Obergeschoss", knx(0, 6, 6), null); + final Property og_szene = createProperty("og.szene", PropertyType.SCENE, "Obergeschoss Szene", null, knx(0, 3, 2)); - final Property ambiente_eg = createProperty("ambiente.eg", PropertyType.SWITCH, "Ambiente EG", knx(0, 3, 81), knx(0, 3, 80)); - final Property ambiente_og = createProperty("ambiente.og", PropertyType.SWITCH, "Ambiente OG", knx(0, 6, 2), knx(0, 6, 3)); + final Property fernseher = createProperty("fernseher.eg", PropertyType.BOOLEAN, "Fernseher", knx(0, 0, 20), knx(0, 0, 4)); + final Property verstaerker = createProperty("verstaerker", PropertyType.BOOLEAN, "Verstärker", knx(0, 3, 57), knx(0, 3, 56)); + final Property garten_steckdosen = createProperty("garten.steckdosen", PropertyType.BOOLEAN, "Garten Steckdosen", knx(0, 4, 12), knx(0, 4, 11)); + final Property terrasse = createProperty("terrasse", PropertyType.BOOLEAN, "Terrasse Licht", knx(0, 4, 1), knx(0, 4, 0)); - final Property bad_licht = createProperty("bad.licht", PropertyType.SWITCH, "Bad Licht", knx(0, 5, 19), knx(0, 3, 73)); - final Property flur_eg_licht = createProperty("flur.eg.licht", PropertyType.SWITCH, "Flur EG Licht", knx(0, 4, 8), knx(0, 5, 14)); + final Property ambiente_eg = createProperty("ambiente.eg", PropertyType.BOOLEAN, "Ambiente EG", knx(0, 3, 81), knx(0, 3, 80)); + final Property ambiente_og = createProperty("ambiente.og", PropertyType.BOOLEAN, "Ambiente OG", knx(0, 6, 2), knx(0, 6, 3)); + + final Property bad_licht = createProperty("bad.licht", PropertyType.BOOLEAN, "Bad Licht", knx(0, 5, 19), knx(0, 3, 73)); + final Property flur_eg_licht = createProperty("flur.eg.licht", PropertyType.BOOLEAN, "Flur EG Licht", knx(0, 4, 8), knx(0, 5, 14)); final Property wohnzimmer_rollladen = createProperty("wohnzimmer.rollladen", PropertyType.SHUTTER, "Wohnzimmer Rollladen", null, knx(0, 4, 24)); final Property schlafzimmer_rollladen = createProperty("schlafzimmer_rollladen", PropertyType.SHUTTER, "Schlafzimmer Rollladen", null, knx(0, 3, 3)); @@ -66,28 +72,31 @@ public class DemoDataService { final Property helligkeit = createProperty("helligkeit", PropertyType.LUX, "Helligkeit", knx(0, 5, 6), null); final Property szene_haus = createProperty("szene_haus", PropertyType.SCENE, "Szene Haus ", null, knx(0, 0, 21)); - if (deviceRepository.count() == 0) { - deviceWriteService.createDeviceSwitch(fernseher); - deviceWriteService.createDeviceSwitch(verstaerker); - deviceWriteService.createDeviceSwitch(garten_steckdosen); - deviceWriteService.createDeviceSwitch(terrasse); - - deviceWriteService.createDeviceSwitch(ambiente_eg); - deviceWriteService.createDeviceSwitch(ambiente_og); - - deviceWriteService.createDeviceSwitch(bad_licht); - deviceWriteService.createDeviceSwitch(flur_eg_licht); - - deviceWriteService.createDeviceShutter(wohnzimmer_rollladen); - deviceWriteService.createDeviceShutter(schlafzimmer_rollladen); - deviceWriteService.createDeviceShutter(flur_og_rollladen); - } - if (sceneRepository.count() == 0) { - sceneWriteService.create(1, "Alles AUS"); - sceneWriteService.create(2, "Nachtlicht"); - sceneWriteService.create(30, "Dekoration AUS"); - sceneWriteService.create(31, "Dekoration AN"); + final SceneDto alles_aus = sceneWriteService.create(1, "Alles AUS"); + final SceneDto nachtlicht = sceneWriteService.create(2, "Nachtlicht"); + final SceneDto dekoration_aus = sceneWriteService.create(30, "Dekoration AUS"); + final SceneDto dekoration_an = sceneWriteService.create(31, "Dekoration AN"); + + if (deviceRepository.count() == 0) { + deviceWriteService.createDeviceStateScene(eg, eg_szene, alles_aus); + deviceWriteService.createDeviceStateScene(og, og_szene, alles_aus); + + deviceWriteService.createDeviceSwitch(fernseher); + deviceWriteService.createDeviceSwitch(verstaerker); + deviceWriteService.createDeviceSwitch(garten_steckdosen); + deviceWriteService.createDeviceSwitch(terrasse); + + deviceWriteService.createDeviceSwitch(ambiente_eg); + deviceWriteService.createDeviceSwitch(ambiente_og); + + deviceWriteService.createDeviceSwitch(bad_licht); + deviceWriteService.createDeviceSwitch(flur_eg_licht); + + deviceWriteService.createDeviceShutter(wohnzimmer_rollladen); + deviceWriteService.createDeviceShutter(schlafzimmer_rollladen); + deviceWriteService.createDeviceShutter(flur_og_rollladen); + } } if (scheduleRepository.count() == 0) { diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceController.java b/src/main/java/de/ph87/homeautomation/device/DeviceController.java index 14a8fef..4d43243 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceController.java +++ b/src/main/java/de/ph87/homeautomation/device/DeviceController.java @@ -56,6 +56,16 @@ public class DeviceController { return deviceWriteService.setDeviceSwitch(id, (device, v) -> device.setStateProperty(mapIfNotNull(v, propertyReadService::getByName)), name); } + @PostMapping("set/{id}/DeviceStateScene/stateProperty") + public DeviceDto setDeviceStateSceneStateProperty(@PathVariable final long id, @RequestBody(required = false) final String name) { + return deviceWriteService.setDeviceStateScene(id, (device, v) -> device.setStateProperty(mapIfNotNull(v, propertyReadService::getByName)), name); + } + + @PostMapping("set/{id}/DeviceStateScene/sceneProperty") + public DeviceDto setDeviceStateSceneSceneProperty(@PathVariable final long id, @RequestBody(required = false) final String name) { + return deviceWriteService.setDeviceStateScene(id, (device, v) -> device.setSceneProperty(mapIfNotNull(v, propertyReadService::getByName)), name); + } + @PostMapping("set/{id}/DeviceShutter/positionProperty") public DeviceDto setDeviceShutterPositionProperty(@PathVariable final long id, @RequestBody(required = false) final String name) { return deviceWriteService.setDeviceShutter(id, (device, v) -> device.setPositionProperty(mapIfNotNull(v, propertyReadService::getByName)), name); diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java b/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java index 3453d22..b5bb882 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java +++ b/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java @@ -31,6 +31,9 @@ public class DeviceReadService { if (device instanceof DeviceSwitch) { final DeviceSwitch deviceSwitch = (DeviceSwitch) device; return new DeviceSwitchDto(deviceSwitch, mapIfNotNull(deviceSwitch.getStateProperty(), propertyMapper::toDto)); + } else if (device instanceof DeviceStateScene) { + final DeviceStateScene deviceStateScene = (DeviceStateScene) device; + return new DeviceStateSceneDto(deviceStateScene, mapIfNotNull(deviceStateScene.getStateProperty(), propertyMapper::toDto), mapIfNotNull(deviceStateScene.getSceneProperty(), propertyMapper::toDto)); } else if (device instanceof DeviceShutter) { final DeviceShutter deviceShutter = (DeviceShutter) device; return new DeviceShutterDto(deviceShutter, mapIfNotNull(deviceShutter.getPositionProperty(), propertyMapper::toDto)); diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java b/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java index 3fc47d6..1c4e74f 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java +++ b/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java @@ -1,18 +1,19 @@ package de.ph87.homeautomation.device; -import de.ph87.homeautomation.device.devices.Device; -import de.ph87.homeautomation.device.devices.DeviceDto; -import de.ph87.homeautomation.device.devices.DeviceShutter; -import de.ph87.homeautomation.device.devices.DeviceSwitch; +import de.ph87.homeautomation.device.devices.*; import de.ph87.homeautomation.property.Property; +import de.ph87.homeautomation.scene.SceneDto; import de.ph87.homeautomation.schedule.ScheduleWriteService; import de.ph87.homeautomation.web.BadRequestException; +import de.ph87.homeautomation.web.WebSocketService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; import java.util.function.BiConsumer; +import java.util.stream.Collectors; @Slf4j @Service @@ -24,6 +25,8 @@ public class DeviceWriteService { private final DeviceReadService deviceReadService; + private final WebSocketService webSocketService; + public DeviceDto createDeviceSwitch(final Property stateProperty) { return createDeviceSwitch(null, stateProperty); } @@ -33,7 +36,7 @@ public class DeviceWriteService { deviceSwitch.setTitle(getTitle(title, stateProperty)); deviceSwitch.setStateProperty(stateProperty); deviceRepository.save(deviceSwitch); - return deviceReadService.toDto(deviceSwitch); + return publish(deviceSwitch, true); } public DeviceDto createDeviceShutter(final Property positionProperty) { @@ -45,13 +48,27 @@ public class DeviceWriteService { deviceShutter.setTitle(getTitle(title, positionProperty)); deviceShutter.setPositionProperty(positionProperty); deviceRepository.save(deviceShutter); - return deviceReadService.toDto(deviceShutter); + return publish(deviceShutter, true); + } + + public DeviceDto createDeviceStateScene(final Property stateProperty, final Property sceneProperty, final SceneDto... scenes) { + return createDeviceStateScene(null, stateProperty, sceneProperty, scenes); + } + + public DeviceDto createDeviceStateScene(final String title, final Property stateProperty, final Property sceneProperty, final SceneDto... scenes) { + final DeviceStateScene deviceStateScene = new DeviceStateScene(); + deviceStateScene.setTitle(getTitle(title, stateProperty)); + deviceStateScene.setStateProperty(stateProperty); + deviceStateScene.setSceneProperty(sceneProperty); + deviceStateScene.setSceneNumbers(Arrays.stream(scenes).map(SceneDto::getNumber).collect(Collectors.toList())); + deviceRepository.save(deviceStateScene); + return publish(deviceStateScene, true); } public DeviceDto set(final long id, final BiConsumer setter, final T value) { final Device device = deviceReadService.getById(id); setter.accept(device, value); - return deviceReadService.toDto(device); + return publish(device, true); } public DeviceDto setDeviceSwitch(final long id, final BiConsumer setter, final T value) { @@ -60,7 +77,16 @@ public class DeviceWriteService { throw new BadRequestException("Not a DeviceSwitch: %s", device); } setter.accept((DeviceSwitch) device, value); - return deviceReadService.toDto(device); + return publish(device, true); + } + + public DeviceDto setDeviceStateScene(final long id, final BiConsumer setter, final T value) { + final Device device = deviceReadService.getById(id); + if (!(device instanceof DeviceStateScene)) { + throw new BadRequestException("Not a DeviceStateScene: %s", device); + } + setter.accept((DeviceStateScene) device, value); + return publish(device, true); } public DeviceDto setDeviceShutter(final long id, final BiConsumer setter, final T value) { @@ -69,14 +95,20 @@ public class DeviceWriteService { throw new BadRequestException("Not a DeviceShutter: %s", device); } setter.accept((DeviceShutter) device, value); - return deviceReadService.toDto(device); + return publish(device, true); } public void delete(final long id) { - deviceRepository.deleteById(id); + final Device device = deviceReadService.getById(id); + deviceRepository.delete(device); + publish(device, false); } public DeviceDto create(final String type) { + return publish(create2(type), true); + } + + private DeviceDto create2(final String type) { switch (type) { case "DeviceSwitch": return createDeviceSwitch(null, null); @@ -86,6 +118,15 @@ public class DeviceWriteService { throw new RuntimeException("Not implemented type: " + type); } + private DeviceDto publish(final Device device, final boolean existing) { + return publish(deviceReadService.toDto(device), existing); + } + + private DeviceDto publish(final DeviceDto dto, final boolean existing) { + webSocketService.send(dto, existing); + return dto; + } + private String getTitle(final String title, final Property property) { if (title != null) { return title; diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java index 08a8625..e797ac9 100644 --- a/src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java @@ -2,8 +2,10 @@ package de.ph87.homeautomation.device.devices; import lombok.Getter; +import java.io.Serializable; + @Getter -public abstract class DeviceDto { +public abstract class DeviceDto implements Serializable { public final long id; diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceStateScene.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceStateScene.java new file mode 100644 index 0000000..0efa707 --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceStateScene.java @@ -0,0 +1,30 @@ +package de.ph87.homeautomation.device.devices; + +import de.ph87.homeautomation.property.Property; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.ManyToOne; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@ToString +@Entity +public class DeviceStateScene extends Device { + + @ManyToOne + private Property stateProperty; + + @ManyToOne + private Property sceneProperty; + + @ElementCollection(fetch = FetchType.EAGER) + private List sceneNumbers = new ArrayList<>(); + +} diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceStateSceneDto.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceStateSceneDto.java new file mode 100644 index 0000000..06def56 --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceStateSceneDto.java @@ -0,0 +1,24 @@ +package de.ph87.homeautomation.device.devices; + +import de.ph87.homeautomation.property.PropertyDto; +import lombok.Getter; + +import java.util.List; + +@Getter +public class DeviceStateSceneDto extends DeviceDto { + + public final PropertyDto stateProperty; + + public final PropertyDto sceneProperty; + + public final List sceneNumbers; + + public DeviceStateSceneDto(final DeviceStateScene device, final PropertyDto stateProperty, final PropertyDto sceneProperty) { + super(device); + this.stateProperty = stateProperty; + this.sceneProperty = sceneProperty; + this.sceneNumbers = device.getSceneNumbers(); + } + +} diff --git a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java new file mode 100644 index 0000000..d27cedb --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java @@ -0,0 +1,56 @@ +package de.ph87.homeautomation.knx.group; + +import lombok.Data; + +import java.io.Serializable; +import java.time.ZonedDateTime; + +@Data +public class KnxGroupDto implements Serializable { + + public final int addressRaw; + + public final String addressStr; + + public final int dptMain; + + public final int dptSub; + + public final String name; + + public final String description; + + public final int puid; + + public final boolean ets; + + public final KnxTelegram lastTelegram; + + public final Double value; + + public final ZonedDateTime timestamp; + + public final KnxGroupLinkInfo read; + + public final byte[] sendValue; + + public final KnxGroupLinkInfo send; + + public KnxGroupDto(final KnxGroup knxGroup) { + this.addressRaw = knxGroup.getAddressRaw(); + this.addressStr = knxGroup.getAddressStr(); + this.dptMain = knxGroup.getDptMain(); + this.dptSub = knxGroup.getDptSub(); + this.name = knxGroup.getName(); + this.description = knxGroup.getDescription(); + this.puid = knxGroup.getPuid(); + this.ets = knxGroup.isEts(); + this.lastTelegram = knxGroup.getLastTelegram(); + this.value = knxGroup.getValue(); + this.timestamp = knxGroup.getTimestamp(); + this.read = knxGroup.getRead(); + this.sendValue = knxGroup.getSendValue(); + this.send = knxGroup.getSend(); + } + +} diff --git a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupMapper.java b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupMapper.java new file mode 100644 index 0000000..90cb044 --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupMapper.java @@ -0,0 +1,12 @@ +package de.ph87.homeautomation.knx.group; + +import org.springframework.stereotype.Service; + +@Service +public class KnxGroupMapper { + + public KnxGroupDto toDto(final KnxGroup knxGroup) { + return new KnxGroupDto(knxGroup); + } + +} diff --git a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java index f454697..515861a 100644 --- a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java @@ -1,6 +1,7 @@ package de.ph87.homeautomation.knx.group; import de.ph87.homeautomation.channel.ChannelChangedEvent; +import de.ph87.homeautomation.web.WebSocketService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.ApplicationEventPublisher; @@ -26,6 +27,10 @@ public class KnxGroupWriteService { private final ApplicationEventPublisher applicationEventPublisher; + private final WebSocketService webSocketService; + + private final KnxGroupMapper knxGroupMapper; + public void requestRead(final KnxGroup knxGroup) { knxGroup.getRead().setNextTimestamp(ZonedDateTime.now()); log.debug("Requesting read for KnxGroup: {}", knxGroup); @@ -39,11 +44,14 @@ public class KnxGroupWriteService { ((DPTXlatorBoolean) translator).setValue(value == 1.0); } else if (translator instanceof DPTXlator8BitUnsigned) { ((DPTXlator8BitUnsigned) translator).setValue((int) value); + } else if (translator instanceof DPTXlatorSceneNumber) { + ((DPTXlatorSceneNumber) translator).setValue((int) value - 1); } else { // TODO implement all DPTXlator... translator.setValue("" + value); } knxGroup.getSend().setNextTimestamp(ZonedDateTime.now()); knxGroup.setSendValue(translator.getData()); + publish(knxGroup); sendThreadWakeUpEvent(); } catch (KNXFormatException e) { log.error("Failed set value \"{}\" to DptXlator {} for KnxGroup {}", value, translator, knxGroup); @@ -84,6 +92,7 @@ public class KnxGroupWriteService { knxGroup.setValue(valueOptional.get()); knxGroup.setTimestamp(ZonedDateTime.now()); log.debug("KnxGroup updated: {}", knxGroup); + publish(knxGroup); applicationEventPublisher.publishEvent(new ChannelChangedEvent(knxGroup)); } else { log.error("Failed to get value from DptXlator {} for KnxGroup {}", translator, knxGroup); @@ -109,4 +118,10 @@ public class KnxGroupWriteService { return Optional.empty(); } + private KnxGroupDto publish(final KnxGroup knxGroup) { + final KnxGroupDto dto = knxGroupMapper.toDto(knxGroup); + webSocketService.send(dto, true); + return dto; + } + } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyController.java b/src/main/java/de/ph87/homeautomation/property/PropertyController.java index cea0cfc..cd2b586 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyController.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyController.java @@ -32,6 +32,11 @@ public class PropertyController implements ISearchController { return propertyWriteService.set(id, Property::setName, propertyName); } + @PostMapping("set/{id}/title") + public PropertyDto setPropertyTitle(@PathVariable final long id, @RequestBody final String propertyTitle) { + return propertyWriteService.set(id, Property::setTitle, propertyTitle); + } + @PostMapping("set/{id}/value") public PropertyDto setValue(@PathVariable final long id, @RequestBody final double value) { return propertyWriteService.set(id, propertyWriteService::write, value); diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyType.java b/src/main/java/de/ph87/homeautomation/property/PropertyType.java index 1a834c7..afe8c28 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyType.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyType.java @@ -1,5 +1,5 @@ package de.ph87.homeautomation.property; public enum PropertyType { - SWITCH, SHUTTER, BRIGHTNESS_PERCENT, COLOR_TEMPERATURE, LUX, SCENE + BOOLEAN, SHUTTER, BRIGHTNESS_PERCENT, COLOR_TEMPERATURE, LUX, SCENE } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyWriteService.java b/src/main/java/de/ph87/homeautomation/property/PropertyWriteService.java index ea0906b..14c9c11 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyWriteService.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyWriteService.java @@ -43,9 +43,9 @@ public class PropertyWriteService { propertyReadService.findAllByReadChannel_Id(event.getChannelId()) .forEach(property -> { property.setValue(property.getReadChannel().getValue()); - property.setTimestamp(property.getReadChannel().getTimestamp()); - log.debug("Updated Property from Channel: {}", property); - webSocketService.send(propertyMapper.toDto(property), true); + property.setTimestamp(property.getReadChannel().getTimestamp()); + log.debug("Updated Property from Channel: {}", property); + publish(property, true); } ); } @@ -53,7 +53,7 @@ public class PropertyWriteService { public PropertyDto create() { final Property entry = new Property(); entry.setTitle(generateUnusedName()); - return propertyMapper.toDto(propertyRepository.save(entry)); + return publish(propertyRepository.save(entry), true); } private String generateUnusedName() { @@ -68,11 +68,19 @@ public class PropertyWriteService { public PropertyDto set(final long id, final BiConsumer setter, final T value) { final Property property = propertyReadService.getById(id); setter.accept(property, value); - return propertyMapper.toDto(property); + return publish(property, true); } public void delete(final long id) { - propertyRepository.deleteById(id); + final Property property = propertyReadService.getById(id); + propertyRepository.delete(property); + publish(property, false); + } + + private PropertyDto publish(final Property property, final boolean existing) { + final PropertyDto dto = propertyMapper.toDto(property); + webSocketService.send(dto, existing); + return dto; } } diff --git a/src/main/java/de/ph87/homeautomation/scene/SceneDto.java b/src/main/java/de/ph87/homeautomation/scene/SceneDto.java index 73e29c1..a748ae9 100644 --- a/src/main/java/de/ph87/homeautomation/scene/SceneDto.java +++ b/src/main/java/de/ph87/homeautomation/scene/SceneDto.java @@ -2,8 +2,10 @@ package de.ph87.homeautomation.scene; import lombok.Getter; +import java.io.Serializable; + @Getter -public class SceneDto { +public class SceneDto implements Serializable { public final long id; diff --git a/src/main/java/de/ph87/homeautomation/scene/SceneWriteService.java b/src/main/java/de/ph87/homeautomation/scene/SceneWriteService.java index 2632728..2204497 100644 --- a/src/main/java/de/ph87/homeautomation/scene/SceneWriteService.java +++ b/src/main/java/de/ph87/homeautomation/scene/SceneWriteService.java @@ -1,6 +1,7 @@ package de.ph87.homeautomation.scene; import de.ph87.homeautomation.schedule.ScheduleWriteService; +import de.ph87.homeautomation.web.WebSocketService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -22,18 +23,29 @@ public class SceneWriteService { private final SceneMapper sceneMapper; + private final WebSocketService webSocketService; + public SceneDto set(final long id, final BiConsumer setter, final T value) { final Scene scene = sceneReadService.getById(id); setter.accept(scene, value); - return sceneMapper.toDto(scene); - } - - public void delete(final long id) { - sceneRepository.deleteById(id); + return publish(scene, true); } public SceneDto create(final int number, final String title) { - return sceneMapper.toDto(sceneRepository.save(new Scene(number, orElseGet(title, this::generateUnusedTitle)))); + final Scene scene = sceneRepository.save(new Scene(number, orElseGet(title, this::generateUnusedTitle))); + return publish(scene, true); + } + + public void delete(final long id) { + final Scene scene = sceneReadService.getById(id); + sceneRepository.delete(scene); + publish(scene, false); + } + + private SceneDto publish(final Scene scene, final boolean existing) { + final SceneDto dto = sceneMapper.toDto(scene); + webSocketService.send(dto, existing); + return dto; } private String generateUnusedTitle() { diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleDto.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleDto.java index 8c88c57..736e548 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleDto.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleDto.java @@ -4,11 +4,12 @@ import de.ph87.homeautomation.property.PropertyDto; import de.ph87.homeautomation.schedule.entry.ScheduleEntryDto; import lombok.Getter; +import java.io.Serializable; import java.util.Set; import java.util.stream.Collectors; @Getter -public class ScheduleDto { +public class ScheduleDto implements Serializable { public final long id; diff --git a/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java b/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java index 9268b5b..ab2146e 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/ScheduleWriteService.java @@ -1,5 +1,6 @@ package de.ph87.homeautomation.schedule; +import de.ph87.homeautomation.web.WebSocketService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -24,10 +25,12 @@ public class ScheduleWriteService { private final ScheduleRepository scheduleRepository; + private final WebSocketService webSocketService; + public ScheduleDto create() { final Schedule entry = new Schedule(); entry.setTitle(generateUnusedName()); - return scheduleMapper.toDto(scheduleRepository.save(entry)); + return publish(scheduleRepository.save(entry), true); } private String generateUnusedName() { @@ -43,11 +46,19 @@ public class ScheduleWriteService { final Schedule schedule = scheduleReadService.getById(id); setter.accept(schedule, value); scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now()); - return scheduleMapper.toDto(schedule); + return publish(schedule, true); } public void delete(final long id) { - scheduleRepository.deleteById(id); + final Schedule schedule = scheduleReadService.getById(id); + scheduleRepository.delete(schedule); + publish(schedule, false); + } + + private ScheduleDto publish(final Schedule schedule, final boolean existing) { + final ScheduleDto dto = scheduleMapper.toDto(schedule); + webSocketService.send(dto, existing); + return dto; } } diff --git a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryDto.java b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryDto.java index 255484c..531733b 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryDto.java +++ b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryDto.java @@ -2,10 +2,11 @@ package de.ph87.homeautomation.schedule.entry; import lombok.Getter; +import java.io.Serializable; import java.time.ZonedDateTime; @Getter -public class ScheduleEntryDto { +public class ScheduleEntryDto implements Serializable { public final long id; diff --git a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java index 94a6c64..faaabe4 100644 --- a/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java +++ b/src/main/java/de/ph87/homeautomation/schedule/entry/ScheduleEntryWriteService.java @@ -3,6 +3,7 @@ package de.ph87.homeautomation.schedule.entry; import de.ph87.homeautomation.schedule.Schedule; import de.ph87.homeautomation.schedule.ScheduleCalculationService; import de.ph87.homeautomation.schedule.ScheduleReadService; +import de.ph87.homeautomation.web.WebSocketService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -27,25 +28,34 @@ public class ScheduleEntryWriteService { private final ScheduleEntryRepository scheduleEntryRepository; + private final WebSocketService webSocketService; + public ScheduleEntryDto set(final long id, final BiConsumer setter, final T value) { final ScheduleEntry entry = scheduleEntryReadService.getById(id); setter.accept(entry, value); final Schedule schedule = scheduleReadService.getByEntry(entry); scheduleCalculationService.calculateSchedule(schedule, ZonedDateTime.now()); - return scheduleEntryMapper.toDto(entry); + return publish(entry, true); } public ScheduleEntryDto create(final long scheduleId) { final Schedule schedule = scheduleReadService.getById(scheduleId); final ScheduleEntry entry = new ScheduleEntry(); schedule.getEntries().add(scheduleEntryRepository.save(entry)); - return scheduleEntryMapper.toDto(entry); + return publish(entry, true); } public void delete(final long id) { final ScheduleEntry entry = scheduleEntryReadService.getById(id); scheduleReadService.getByEntry(entry).getEntries().remove(entry); scheduleEntryRepository.delete(entry); + publish(entry, false); + } + + private ScheduleEntryDto publish(final ScheduleEntry entry, final boolean existing) { + final ScheduleEntryDto dto = scheduleEntryMapper.toDto(entry); + webSocketService.send(dto, existing); + return dto; } }