diff --git a/src/main/angular/src/app/api/api.service.ts b/src/main/angular/src/app/api/api.service.ts index 5dc931b..36348c5 100644 --- a/src/main/angular/src/app/api/api.service.ts +++ b/src/main/angular/src/app/api/api.service.ts @@ -6,7 +6,7 @@ import {environment} from "../../environments/environment"; export function NO_OP() { } -export function NO_SORT(a: T, b: T): number { +export function NO_COMPARE(a: T, b: T): number { return 0; } @@ -32,7 +32,7 @@ export class ApiService { this.http.get(environment.apiBasePath + path).pipe(map(fromJson)).subscribe(next, errorInterceptor(error)); } - getList(path: string, fromJson: (json: any) => T, compare: (a: T, b: T) => number = NO_SORT, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) { + getList(path: string, fromJson: (json: any) => T, compare: (a: T, b: T) => number = NO_COMPARE, next: (list: T[]) => void = NO_OP, error: (error: any) => void = NO_OP) { this.http.get(environment.apiBasePath + path).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next, errorInterceptor(error)); } diff --git a/src/main/angular/src/app/api/device/Device.ts b/src/main/angular/src/app/api/device/Device.ts new file mode 100644 index 0000000..fc0f2f1 --- /dev/null +++ b/src/main/angular/src/app/api/device/Device.ts @@ -0,0 +1,73 @@ +import {validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators"; +import {Property} from "../property/property.service"; + +export abstract class Device { + + constructor( + readonly id: number, + readonly title: string, + readonly type: string, + ) { + // nothing + } + + static fromJson(json: any): Device { + const type: string = validateStringNotEmptyNotNull(json['type']); + switch (type) { + case "DeviceSwitch": + return new DeviceSwitch( + validateNumberNotNull(json['id']), + validateStringNotEmptyNotNull(json['title']), + type, + Property.fromJsonAllowNull(json['getState']), + Property.fromJsonAllowNull(json['setState']), + ); + case "DeviceShutter": + return new DeviceShutter( + validateNumberNotNull(json['id']), + validateStringNotEmptyNotNull(json['title']), + type, + Property.fromJsonAllowNull(json['getPercent']), + Property.fromJsonAllowNull(json['setPercent']), + ); + } + throw new Error("No such type: " + type); + } + + public static trackBy(index: number, item: Device): string { + return item.title; + } + + public static compareTitle(a: Device, b: Device): number { + return a.title.localeCompare(b.title); + } + +} + +export class DeviceSwitch extends Device { + + constructor( + id: number, + title: string, + type: string, + readonly getState: Property | null, + readonly setState: Property | null, + ) { + super(id, title, type); + } + +} + +export class DeviceShutter extends Device { + + constructor( + id: number, + title: string, + type: string, + readonly getPercent: Property | null, + readonly setPercent: Property | null, + ) { + super(id, title, type); + } + +} diff --git a/src/main/angular/src/app/api/device/DeviceShutter.ts b/src/main/angular/src/app/api/device/DeviceShutter.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/main/angular/src/app/api/device/DeviceSwitch.ts b/src/main/angular/src/app/api/device/DeviceSwitch.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/main/angular/src/app/api/device/device.service.spec.ts b/src/main/angular/src/app/api/device/device.service.spec.ts new file mode 100644 index 0000000..0a1f82a --- /dev/null +++ b/src/main/angular/src/app/api/device/device.service.spec.ts @@ -0,0 +1,16 @@ +import {TestBed} from '@angular/core/testing'; + +import {DeviceService} from './device.service'; + +describe('DeviceService', () => { + let service: DeviceService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(DeviceService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/main/angular/src/app/api/device/device.service.ts b/src/main/angular/src/app/api/device/device.service.ts new file mode 100644 index 0000000..bdcddcb --- /dev/null +++ b/src/main/angular/src/app/api/device/device.service.ts @@ -0,0 +1,20 @@ +import {Injectable} from '@angular/core'; +import {ApiService, NO_COMPARE, NO_OP} from "../api.service"; +import {Device} from "./Device"; + +@Injectable({ + providedIn: 'root' +}) +export class DeviceService { + + constructor( + readonly api: ApiService, + ) { + // nothing + } + + 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); + } + +} diff --git a/src/main/angular/src/app/api/property/property.service.ts b/src/main/angular/src/app/api/property/property.service.ts index e810cb7..26c7554 100644 --- a/src/main/angular/src/app/api/property/property.service.ts +++ b/src/main/angular/src/app/api/property/property.service.ts @@ -1,6 +1,6 @@ import {Injectable} from '@angular/core'; import {ApiService, NO_OP} from "../api.service"; -import {validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators"; +import {validateBooleanAllowNull, validateDateAllowNull, validateNumberAllowNull, validateStringNotEmptyNotNull} from "../validators"; import {ISearchService} from "../ISearchService"; import {KeyValuePair} from "../KeyValuePair"; @@ -8,17 +8,30 @@ export class Property { constructor( public name: string, - public type: string, - public value: number, + public title: string, + public propertyType: string, + public booleanValue: boolean | null, + public numberValue: number | null, + public timestamp: Date | null, ) { // nothing } + static fromJsonAllowNull(json: any): Property | null { + if (json === undefined || json === null) { + return null; + } + return this.fromJson(json); + } + static fromJson(json: any): Property { return new Property( validateStringNotEmptyNotNull(json['name']), - validateStringNotEmptyNotNull(json['type']), - validateNumberNotNull(json['value']), + validateStringNotEmptyNotNull(json['title']), + validateStringNotEmptyNotNull(json['propertyType']), + validateBooleanAllowNull(json['booleanValue']), + validateNumberAllowNull(json['numberValue']), + validateDateAllowNull(json['timestamp']), ); } @@ -51,4 +64,8 @@ export class PropertyService implements ISearchService { this.api.postReturnList("property/searchLike", term, KeyValuePair.fromJson, next, error); } + set(name: string, value: number, next: () => void = NO_OP, error: (error: any) => void = NO_OP): void { + this.api.postReturnNone("property/set", {name: name, value: value}, next, error) + } + } diff --git a/src/main/angular/src/app/app-routing.module.ts b/src/main/angular/src/app/app-routing.module.ts index bf7d9c3..3876748 100644 --- a/src/main/angular/src/app/app-routing.module.ts +++ b/src/main/angular/src/app/app-routing.module.ts @@ -2,8 +2,10 @@ import {NgModule} from '@angular/core'; import {RouterModule, Routes} from '@angular/router'; import {ScheduleListComponent} from "./pages/schedule-list/schedule-list.component"; import {ScheduleComponent} from "./pages/schedule/schedule.component"; +import {DeviceListComponent} from "./pages/device-list/device-list.component"; const routes: Routes = [ + {path: 'DeviceList', component: DeviceListComponent}, {path: 'Schedule', component: ScheduleComponent}, {path: 'ScheduleList', component: ScheduleListComponent}, {path: '**', redirectTo: '/ScheduleList'}, diff --git a/src/main/angular/src/app/app.component.html b/src/main/angular/src/app/app.component.html index 0ae728b..1b0a353 100644 --- a/src/main/angular/src/app/app.component.html +++ b/src/main/angular/src/app/app.component.html @@ -4,6 +4,10 @@ Zeitpläne +
+ Geräte +
+ diff --git a/src/main/angular/src/app/app.component.less b/src/main/angular/src/app/app.component.less index f4bbbdb..825e53a 100644 --- a/src/main/angular/src/app/app.component.less +++ b/src/main/angular/src/app/app.component.less @@ -7,6 +7,10 @@ border-right: 1px solid black; } + .item:hover { + background-color: lightskyblue; + } + .breadcrumb { background-color: lightgray; } diff --git a/src/main/angular/src/app/app.module.ts b/src/main/angular/src/app/app.module.ts index 4b869ff..ce251d1 100644 --- a/src/main/angular/src/app/app.module.ts +++ b/src/main/angular/src/app/app.module.ts @@ -11,6 +11,7 @@ import {FontAwesomeModule} from '@fortawesome/angular-fontawesome'; import {NumberComponent} from './shared/number/number.component'; import {ScheduleComponent} from "./pages/schedule/schedule.component"; import {SearchComponent} from './shared/search/search.component'; +import {DeviceListComponent} from './pages/device-list/device-list.component'; @NgModule({ declarations: [ @@ -20,6 +21,7 @@ import {SearchComponent} from './shared/search/search.component'; ScheduleListComponent, NumberComponent, SearchComponent, + DeviceListComponent, ], imports: [ BrowserModule, 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 new file mode 100644 index 0000000..25ada8d --- /dev/null +++ b/src/main/angular/src/app/pages/device-list/device-list.component.html @@ -0,0 +1,35 @@ + + +
+
+ {{device.title}} +
+
+ + +
+
+
+
+ {{device.title}} +
+
+
+ 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 new file mode 100644 index 0000000..c72b397 --- /dev/null +++ b/src/main/angular/src/app/pages/device-list/device-list.component.less @@ -0,0 +1,66 @@ +.device { + padding: 5px; + margin-bottom: 5px; + border-radius: 10px; + + .title { + font-weight: bold; + } + + .controls { + .control { + position: relative; + float: left; + width: 60px; + height: 60px; + padding: 5px; + margin: 5px; + border-radius: 25%; + + .center { + position: absolute; + margin: 0; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } + } + + .button { + background-color: lightblue; + } + + .control:hover { + background-color: lightskyblue; + } + + } +} + +.switchOn { + background-color: palegreen; +} + +.switchOff { + background-color: indianred; +} + +.switchUnknown { + background-color: gray; +} + +.blindOpen { + background-color: palegreen; +} + +.shutterBetween { + background-color: yellow; +} + +.shutterClosed { + background-color: indianred; +} + +.shutterUnknown { + background-color: gray; +} diff --git a/src/main/angular/src/app/pages/device-list/device-list.component.spec.ts b/src/main/angular/src/app/pages/device-list/device-list.component.spec.ts new file mode 100644 index 0000000..764bbb8 --- /dev/null +++ b/src/main/angular/src/app/pages/device-list/device-list.component.spec.ts @@ -0,0 +1,25 @@ +import {ComponentFixture, TestBed} from '@angular/core/testing'; + +import {DeviceListComponent} from './device-list.component'; + +describe('DeviceListComponent', () => { + let component: DeviceListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DeviceListComponent] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(DeviceListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); 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 new file mode 100644 index 0000000..7ad25ba --- /dev/null +++ b/src/main/angular/src/app/pages/device-list/device-list.component.ts @@ -0,0 +1,81 @@ +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"; + +@Component({ + selector: 'app-device-list', + templateUrl: './device-list.component.html', + styleUrls: ['./device-list.component.less'] +}) +export class DeviceListComponent implements OnInit { + + devices: Device[] = []; + + constructor( + readonly deviceService: DeviceService, + readonly propertyService: PropertyService, + ) { + // nothing + } + + ngOnInit(): void { + this.deviceService.findAll(devices => this.devices = devices); + } + + asDeviceSwitch(device: Device): DeviceSwitch { + return device as DeviceSwitch; + } + + asDeviceShutter(device: Device): DeviceShutter { + return device as DeviceShutter; + } + + setSwitchState(d: Device, value: boolean): void { + const device: DeviceSwitch = d as DeviceSwitch; + if (!device.setState) { + throw new Error("Property 'setState' not set for: " + device); + } + this.propertyService.set(device.setState.name, value ? 1 : 0); + } + + setShutterPercent(d: Device, value: number): void { + const device: DeviceShutter = d as DeviceShutter; + if (!device.setPercent) { + throw new Error("Property 'setPercent' not set for: " + device); + } + this.propertyService.set(device.setPercent.name, value); + } + + isSwitchStateOn(device: Device): boolean { + return (device as DeviceSwitch).getState?.booleanValue === true; + } + + isSwitchStateOff(device: Device): boolean { + return (device as DeviceSwitch).getState?.booleanValue === false; + } + + isSwitchStateUnknown(device: Device): boolean { + const value: boolean | null | undefined = (device as DeviceSwitch).getState?.booleanValue; + return value === null || value === undefined; + } + + isShutterStateOpen(device: Device): boolean { + return (device as DeviceShutter).getPercent?.numberValue === 0; + } + + isShutterStateBetween(device: Device): boolean { + const value: number | null | undefined = (device as DeviceShutter).getPercent?.numberValue; + return value !== null && value !== undefined && value > 0 && value < 100; + } + + isShutterStateClosed(device: Device): boolean { + return (device as DeviceShutter).getPercent?.numberValue === 100; + } + + isShutterStateUnknown(device: Device): boolean { + const value: number | null | undefined = (device as DeviceShutter).getPercent?.numberValue; + return value === null || value === undefined; + } + +} 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 838eeae..5ac454e 100644 --- a/src/main/angular/src/app/shared/search/search.component.ts +++ b/src/main/angular/src/app/shared/search/search.component.ts @@ -91,7 +91,6 @@ export class SearchComponent implements OnInit { } select(result: KeyValuePair): void { - console.log(result); this.searching = false; this.selected = result; this.valueChange.emit(this.selected?.key); diff --git a/src/main/angular/src/assets/switch-off.svg b/src/main/angular/src/assets/switch-off.svg new file mode 100644 index 0000000..976c98b --- /dev/null +++ b/src/main/angular/src/assets/switch-off.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/angular/src/assets/switch-on.svg b/src/main/angular/src/assets/switch-on.svg new file mode 100644 index 0000000..f29c921 --- /dev/null +++ b/src/main/angular/src/assets/switch-on.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/java/de/ph87/homeautomation/DemoDataService.java b/src/main/java/de/ph87/homeautomation/DemoDataService.java index 77548dd..6cfa907 100644 --- a/src/main/java/de/ph87/homeautomation/DemoDataService.java +++ b/src/main/java/de/ph87/homeautomation/DemoDataService.java @@ -1,9 +1,11 @@ package de.ph87.homeautomation; import com.luckycatlabs.sunrisesunset.Zenith; +import de.ph87.homeautomation.device.DeviceWriteService; import de.ph87.homeautomation.knx.group.KnxGroupDto; import de.ph87.homeautomation.knx.group.KnxGroupRepository; import de.ph87.homeautomation.knx.group.KnxGroupWriteService; +import de.ph87.homeautomation.property.PropertyDto; import de.ph87.homeautomation.property.PropertyType; import de.ph87.homeautomation.schedule.Schedule; import de.ph87.homeautomation.schedule.ScheduleRepository; @@ -23,7 +25,9 @@ import java.time.ZonedDateTime; @RequiredArgsConstructor public class DemoDataService { - public static final int MIN30 = 30 * 60; + private static final int MIN30 = 30 * 60; + + private static final Zenith BETWEEN_OFFICIAL_AND_CIVIL = new Zenith(93.0); private final KnxGroupWriteService knxGroupWriteService; @@ -31,19 +35,25 @@ public class DemoDataService { private final KnxGroupRepository knxGroupRepository; + private final DeviceWriteService deviceWriteService; + @PostConstruct public void postConstruct() { - 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", PropertyType.ON_OFF, 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", PropertyType.PERCENT, 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", PropertyType.PERCENT, 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", PropertyType.LUX, false, true); + final KnxGroupDto eg_flur_licht_schalten = createKnxGroupIfNotExists("EG Flur Licht Schalten", 0, 5, 14, "1.001", PropertyType.ON_OFF, false, false); + final KnxGroupDto eg_ambiente_schalten = createKnxGroupIfNotExists("EG Ambiente Schalten", 0, 3, 80, "1.001", PropertyType.ON_OFF, false, false); + final KnxGroupDto og_ambiente_schalten = createKnxGroupIfNotExists("OG Ambiente Schalten", 0, 6, 3, "1.001", PropertyType.ON_OFF, false, false); + final KnxGroupDto wohnzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Wohnzimmer Rollladen Position Anfahren", 0, 4, 24, "5.001", PropertyType.PERCENT, false, false); + final KnxGroupDto schlafzimmer_rollladen_position_anfahren = createKnxGroupIfNotExists("Schlafzimmer Rollladen Position Anfahren", 0, 3, 3, "5.001", PropertyType.PERCENT, false, false); + final KnxGroupDto flur_rollladen_position_anfahren = createKnxGroupIfNotExists("Flur Rollladen Position Anfahren", 0, 5, 13, "5.001", PropertyType.PERCENT, false, false); + final KnxGroupDto bad_licht_mitte_schalten = createKnxGroupIfNotExists("Bad Licht Mitte Schalten", 0, 3, 29, "1.001", PropertyType.ON_OFF, false, false); + final KnxGroupDto bad_licht_mitte_status = createKnxGroupIfNotExists("Bad Licht Mitte Status", 0, 3, 30, "1.001", PropertyType.ON_OFF, true, false); + final KnxGroupDto helligkeit = createKnxGroupIfNotExists("Helligkeit", 0, 5, 6, "9.004", PropertyType.LUX, false, true); + + deviceWriteService.createDeviceSwitch("Bad Licht Mitte", bad_licht_mitte_status, bad_licht_mitte_schalten); + deviceWriteService.createDeviceShutter("Flur OG Rollladen", null, flur_rollladen_position_anfahren); if (scheduleRepository.count() == 0) { - final Schedule scheduleEgFlurLicht = createSchedule("EG Flur Licht", eg_flur_licht_schalten, PropertyType.ON_OFF); + final Schedule scheduleEgFlurLicht = createSchedule("EG Flur Licht", eg_flur_licht_schalten); createTime(scheduleEgFlurLicht, 11, 30, 0, MIN30, true); createTime(scheduleEgFlurLicht, 12, 30, 0, MIN30, false); createTime(scheduleEgFlurLicht, 16, 30, 0, MIN30, true); @@ -54,36 +64,36 @@ public class DemoDataService { createTime(scheduleEgFlurLicht, 2, 0, 0, MIN30, false); scheduleRepository.save(scheduleEgFlurLicht); - final Schedule scheduleEgAmbiente = createSchedule("EG Ambiente", eg_ambiente_schalten, PropertyType.ON_OFF); + final Schedule scheduleEgAmbiente = createSchedule("EG Ambiente", eg_ambiente_schalten); createTime(scheduleEgAmbiente, 7, 15, 0, MIN30, true); createTime(scheduleEgAmbiente, 9, 30, 0, MIN30, false); createSunset(scheduleEgAmbiente, Zenith.OFFICIAL, MIN30, true); createSunset(scheduleEgAmbiente, Zenith.ASTRONOMICAL, MIN30, false); scheduleRepository.save(scheduleEgAmbiente); - final Schedule scheduleOgAmbiente = createSchedule("OG Ambiente", og_ambiente_schalten, PropertyType.ON_OFF); + final Schedule scheduleOgAmbiente = createSchedule("OG Ambiente", og_ambiente_schalten); createTime(scheduleOgAmbiente, 7, 15, 0, MIN30, true); createTime(scheduleOgAmbiente, 9, 30, 0, MIN30, false); createSunset(scheduleOgAmbiente, Zenith.OFFICIAL, MIN30, true); createSunset(scheduleOgAmbiente, Zenith.ASTRONOMICAL, MIN30, false); scheduleRepository.save(scheduleOgAmbiente); - final Schedule scheduleWohnzimmerRollladen = createSchedule("Rollläden Wohnzimmer", wohnzimmer_rollladen_position_anfahren, PropertyType.SHUTTER); - createSunrise(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, 0); - createSunset(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, 100); + final Schedule scheduleWohnzimmerRollladen = createSchedule("Rollläden Wohnzimmer", wohnzimmer_rollladen_position_anfahren); + createSunrise(scheduleWohnzimmerRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0); + createSunset(scheduleWohnzimmerRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100); scheduleRepository.save(scheduleWohnzimmerRollladen); - final Schedule scheduleSchlafzimmerRollladen = createSchedule("Rollläden Schlafzimmer", schlafzimmer_rollladen_position_anfahren, PropertyType.SHUTTER); + final Schedule scheduleSchlafzimmerRollladen = createSchedule("Rollläden Schlafzimmer", schlafzimmer_rollladen_position_anfahren); createTime(scheduleSchlafzimmerRollladen, 7, 0, 0, 0, 0); - createSunset(scheduleSchlafzimmerRollladen, Zenith.CIVIL, 0, 100); + createSunset(scheduleSchlafzimmerRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100); scheduleRepository.save(scheduleSchlafzimmerRollladen); - final Schedule scheduleFlurRollladen = createSchedule("Rollladen Flur", flur_rollladen_position_anfahren, PropertyType.SHUTTER); - createSunrise(scheduleFlurRollladen, Zenith.CIVIL, 0, 0); - createSunset(scheduleFlurRollladen, Zenith.CIVIL, 0, 100); + final Schedule scheduleFlurRollladen = createSchedule("Rollladen Flur", flur_rollladen_position_anfahren); + createSunrise(scheduleFlurRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0); + createSunset(scheduleFlurRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100); scheduleRepository.save(scheduleFlurRollladen); - final Schedule scheduleBadLichtMitte = createSchedule("Bad Licht Mitte", bad_licht_mitte_schalten, PropertyType.ON_OFF); + final Schedule scheduleBadLichtMitte = createSchedule("Bad Licht Mitte", bad_licht_mitte_schalten); createTime(scheduleBadLichtMitte, 10, 30, 0, MIN30, true); createTime(scheduleBadLichtMitte, 11, 30, 0, MIN30, false); createTime(scheduleBadLichtMitte, 15, 30, 0, MIN30, true); @@ -96,20 +106,17 @@ public class DemoDataService { } } - private Schedule createSchedule(final String s, final KnxGroupDto knxGroupDto, final PropertyType propertyType) { + private Schedule createSchedule(final String s, final PropertyDto propertyDto) { final Schedule schedule = new Schedule(); schedule.setEnabled(true); schedule.setName(s); - schedule.setPropertyName(knxGroupDto.propertyName); - schedule.setPropertyType(propertyType); + schedule.setPropertyName(propertyDto.getName()); + schedule.setPropertyType(propertyDto.getPropertyType()); return schedule; } - private KnxGroupDto createKnxGroupIfNotExists(final String name, final int address, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) { - return createKnxGroupIfNotExists(name, new GroupAddress(address), dpt, type, readable, multiGroup); - } - - private KnxGroupDto createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) { + private KnxGroupDto createKnxGroupIfNotExists(final String name, final int main, final int mid, final int sub, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) { + final GroupAddress address = new GroupAddress(main, mid, sub); return knxGroupRepository.findByAddressRaw(address.getRawAddress()).map(KnxGroupDto::new).orElseGet(() -> knxGroupWriteService.create(name, address, dpt, type, readable, multiGroup)); } diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceController.java b/src/main/java/de/ph87/homeautomation/device/DeviceController.java index 91050a4..8f6a6ce 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceController.java +++ b/src/main/java/de/ph87/homeautomation/device/DeviceController.java @@ -1,9 +1,9 @@ package de.ph87.homeautomation.device; +import de.ph87.homeautomation.device.devices.DeviceDto; +import de.ph87.homeautomation.property.PropertySetException; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -14,9 +14,16 @@ public class DeviceController { private final DeviceReadService deviceReadService; + private final DeviceWriteService deviceWriteService; + @GetMapping("findAll") public List findAll() { return deviceReadService.findAll(); } + @PostMapping("set") + public void set(@RequestBody final DeviceSetDto dto) throws PropertySetException { + deviceWriteService.set(dto); + } + } diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java b/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java index 79f608b..b572fb5 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java +++ b/src/main/java/de/ph87/homeautomation/device/DeviceReadService.java @@ -1,6 +1,7 @@ package de.ph87.homeautomation.device; import de.ph87.homeautomation.device.devices.*; +import de.ph87.homeautomation.property.PropertyDto; import de.ph87.homeautomation.property.PropertyService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -10,6 +11,8 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; +import static de.ph87.homeautomation.shared.Helpers.mapIfNotNull; + @Slf4j @Service @Transactional @@ -27,12 +30,16 @@ public class DeviceReadService { private DeviceDto toDto(final Device device) { if (device instanceof DeviceSwitch) { final DeviceSwitch deviceSwitch = (DeviceSwitch) device; - return new DeviceSwitchDto(deviceSwitch, propertyService.readBoolean(deviceSwitch.getStatePropertyName())); - } else if (device instanceof DeviceNumber) { - final DeviceNumber deviceNumber = (DeviceNumber) device; - return new DeviceNumberDto(deviceNumber, propertyService.readNumber(deviceNumber.getValuePropertyName())); + final PropertyDto getState = mapIfNotNull(deviceSwitch.getGetState(), propertyService::getById); + final PropertyDto setState = mapIfNotNull(deviceSwitch.getSetState(), propertyService::getById); + return new DeviceSwitchDto(deviceSwitch, getState, setState); + } else if (device instanceof DeviceShutter) { + final DeviceShutter deviceShutter = (DeviceShutter) device; + final PropertyDto getPercent = mapIfNotNull(deviceShutter.getGetPercent(), propertyService::getById); + final PropertyDto setPercent = mapIfNotNull(deviceShutter.getSetPercent(), propertyService::getById); + return new DeviceShutterDto(deviceShutter, getPercent, setPercent); } - throw new RuntimeException("Not imeplemented: toDto(" + device + ")"); + throw new RuntimeException("Not implemented: toDto(" + device + ")"); } } diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceSetDto.java b/src/main/java/de/ph87/homeautomation/device/DeviceSetDto.java new file mode 100644 index 0000000..ed48c04 --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/device/DeviceSetDto.java @@ -0,0 +1,14 @@ +package de.ph87.homeautomation.device; + +import lombok.Data; + +@Data +public class DeviceSetDto { + + private long id; + + private String property; + + private double value; + +} diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java b/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java index 446ea0f..193b556 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java +++ b/src/main/java/de/ph87/homeautomation/device/DeviceWriteService.java @@ -1,13 +1,18 @@ package de.ph87.homeautomation.device; -import de.ph87.homeautomation.device.devices.DeviceNumber; +import de.ph87.homeautomation.device.devices.Device; +import de.ph87.homeautomation.device.devices.DeviceShutter; import de.ph87.homeautomation.device.devices.DeviceSwitch; +import de.ph87.homeautomation.property.PropertyDto; +import de.ph87.homeautomation.property.PropertyService; +import de.ph87.homeautomation.property.PropertySetException; +import de.ph87.office.web.NotFoundException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import javax.annotation.PostConstruct; +import static de.ph87.homeautomation.shared.Helpers.mapIfNotNull; @Slf4j @Service @@ -17,17 +22,49 @@ public class DeviceWriteService { private final DeviceRepository deviceRepository; - @PostConstruct - public void postConstruct() { - final DeviceSwitch deviceSwitch = new DeviceSwitch(); - deviceSwitch.setName("TEST"); - deviceSwitch.setStatePropertyName("knx.group.0.3.6"); - deviceRepository.save(deviceSwitch); + private final PropertyService propertyService; - final DeviceNumber deviceNumber = new DeviceNumber(); - deviceNumber.setName("Helligkeit"); - deviceNumber.setValuePropertyName("knx.group.0.5.6"); - deviceRepository.save(deviceNumber); + public void createDeviceSwitch(final String title, final PropertyDto getState, final PropertyDto setState) { + final DeviceSwitch deviceSwitch = new DeviceSwitch(); + deviceSwitch.setTitle(title); + deviceSwitch.setGetState(mapIfNotNull(getState, PropertyDto::getName)); + deviceSwitch.setSetState(mapIfNotNull(setState, PropertyDto::getName)); + deviceRepository.save(deviceSwitch); + } + + public void createDeviceShutter(final String title, final PropertyDto getPercent, final PropertyDto setPercent) { + final DeviceShutter deviceShutter = new DeviceShutter(); + deviceShutter.setTitle(title); + deviceShutter.setGetPercent(mapIfNotNull(getPercent, PropertyDto::getName)); + deviceShutter.setSetPercent(mapIfNotNull(setPercent, PropertyDto::getName)); + deviceRepository.save(deviceShutter); + } + + public void set(final DeviceSetDto dto) throws PropertySetException { + final Device device = getById(dto.getId()); + if (device instanceof DeviceSwitch) { + setSwitch((DeviceSwitch) device, dto.getProperty(), dto.getValue()); + } else if (device instanceof DeviceShutter) { + setShutter((DeviceShutter) device, dto.getProperty(), dto.getValue()); + } + } + + private void setSwitch(final DeviceSwitch device, final String property, final double value) throws PropertySetException { + switch (property) { + case "switch": + propertyService.set(device.getSetState(), value); + } + } + + private void setShutter(final DeviceShutter device, final String property, final double value) throws PropertySetException { + switch (property) { + case "percent": + propertyService.set(device.getSetPercent(), value); + } + } + + private Device getById(final long id) { + return deviceRepository.findById(id).orElseThrow(() -> new NotFoundException("Device.id=%d", id)); } } diff --git a/src/main/java/de/ph87/homeautomation/device/devices/Device.java b/src/main/java/de/ph87/homeautomation/device/devices/Device.java index 1716508..c5a68fc 100644 --- a/src/main/java/de/ph87/homeautomation/device/devices/Device.java +++ b/src/main/java/de/ph87/homeautomation/device/devices/Device.java @@ -19,6 +19,6 @@ public abstract class Device { @Setter(AccessLevel.NONE) private Long id; - private String name; + private String title; } diff --git a/src/main/java/de/ph87/homeautomation/device/DeviceDto.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java similarity index 62% rename from src/main/java/de/ph87/homeautomation/device/DeviceDto.java rename to src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java index 3848c20..08a8625 100644 --- a/src/main/java/de/ph87/homeautomation/device/DeviceDto.java +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceDto.java @@ -1,6 +1,5 @@ -package de.ph87.homeautomation.device; +package de.ph87.homeautomation.device.devices; -import de.ph87.homeautomation.device.devices.Device; import lombok.Getter; @Getter @@ -8,13 +7,13 @@ public abstract class DeviceDto { public final long id; - public final String name; + public final String title; public final String type; public DeviceDto(final Device device) { this.id = device.getId(); - this.name = device.getName(); + this.title = device.getTitle(); this.type = device.getClass().getSimpleName(); } diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceNumberDto.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceNumberDto.java deleted file mode 100644 index aa1064e..0000000 --- a/src/main/java/de/ph87/homeautomation/device/devices/DeviceNumberDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.ph87.homeautomation.device.devices; - -import de.ph87.homeautomation.device.DeviceDto; -import lombok.Getter; - -@Getter -public class DeviceNumberDto extends DeviceDto { - - public final Number value; - - public DeviceNumberDto(final DeviceNumber device, final Number value) { - super(device); - this.value = value; - } - -} diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceNumber.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceShutter.java similarity index 64% rename from src/main/java/de/ph87/homeautomation/device/devices/DeviceNumber.java rename to src/main/java/de/ph87/homeautomation/device/devices/DeviceShutter.java index 3fa12d1..37ed72c 100644 --- a/src/main/java/de/ph87/homeautomation/device/devices/DeviceNumber.java +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceShutter.java @@ -10,8 +10,10 @@ import javax.persistence.Entity; @Setter @ToString @Entity -public class DeviceNumber extends Device { +public class DeviceShutter extends Device { - private String valuePropertyName; + private String getPercent; + + private String setPercent; } diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceShutterDto.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceShutterDto.java new file mode 100644 index 0000000..29f6fbc --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceShutterDto.java @@ -0,0 +1,19 @@ +package de.ph87.homeautomation.device.devices; + +import de.ph87.homeautomation.property.PropertyDto; +import lombok.Getter; + +@Getter +public class DeviceShutterDto extends DeviceDto { + + public final PropertyDto getPercent; + + public final PropertyDto setPercent; + + public DeviceShutterDto(final DeviceShutter device, final PropertyDto getPercent, final PropertyDto setPercent) { + super(device); + this.getPercent = getPercent; + this.setPercent = setPercent; + } + +} diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitch.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitch.java index 390cea8..275ddf4 100644 --- a/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitch.java +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitch.java @@ -12,8 +12,8 @@ import javax.persistence.Entity; @Entity public class DeviceSwitch extends Device { - private String switchPropertyName; + private String setState; - private String statePropertyName; + private String getState; } diff --git a/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitchDto.java b/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitchDto.java index 7d02626..377c4d1 100644 --- a/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitchDto.java +++ b/src/main/java/de/ph87/homeautomation/device/devices/DeviceSwitchDto.java @@ -1,16 +1,19 @@ package de.ph87.homeautomation.device.devices; -import de.ph87.homeautomation.device.DeviceDto; +import de.ph87.homeautomation.property.PropertyDto; import lombok.Getter; @Getter public class DeviceSwitchDto extends DeviceDto { - public final Boolean state; + public final PropertyDto getState; - public DeviceSwitchDto(final DeviceSwitch device, final Boolean state) { + public final PropertyDto setState; + + public DeviceSwitchDto(final DeviceSwitch device, final PropertyDto getState, final PropertyDto setState) { super(device); - this.state = state; + this.getState = getState; + this.setState = setState; } } diff --git a/src/main/java/de/ph87/homeautomation/knx/KnxThreadService.java b/src/main/java/de/ph87/homeautomation/knx/KnxThreadService.java index 250a47e..3fe2247 100644 --- a/src/main/java/de/ph87/homeautomation/knx/KnxThreadService.java +++ b/src/main/java/de/ph87/homeautomation/knx/KnxThreadService.java @@ -7,7 +7,6 @@ import de.ph87.homeautomation.shared.AbstractThreadService; import de.ph87.network.router.Router; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import org.springframework.transaction.event.TransactionalEventListener; import tuwien.auto.calimero.CloseEvent; @@ -153,9 +152,8 @@ public class KnxThreadService extends AbstractThreadService implements NetworkLi // ignore } - @EventListener(KnxThreadWakeUpEvent.class) @TransactionalEventListener - public void wakeUp() { + public void wakeUp(final KnxThreadWakeUpEvent event) { _wakeUp(); } diff --git a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroup.java b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroup.java index 228e41a..862ddaf 100644 --- a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroup.java +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroup.java @@ -1,5 +1,6 @@ package de.ph87.homeautomation.knx.group; +import de.ph87.homeautomation.property.IProperty; import de.ph87.homeautomation.property.PropertyType; import lombok.AccessLevel; import lombok.Getter; @@ -14,7 +15,7 @@ import java.time.ZonedDateTime; @Setter @ToString @Entity -public class KnxGroup { +public class KnxGroup implements IProperty { @Id @GeneratedValue diff --git a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java index 700df02..602053a 100644 --- a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupDto.java @@ -1,12 +1,10 @@ package de.ph87.homeautomation.knx.group; -import de.ph87.homeautomation.property.PropertyType; +import de.ph87.homeautomation.property.PropertyDto; import lombok.Getter; -import java.time.ZonedDateTime; - @Getter -public class KnxGroupDto { +public class KnxGroupDto extends PropertyDto { public final long id; @@ -14,32 +12,14 @@ public class KnxGroupDto { public final String addressStr; - public final String propertyName; - public final String dpt; - public final String name; - - public final PropertyType propertyType; - - public final Boolean booleanValue; - - public final Double numberValue; - - public final ZonedDateTime valueTimestamp; - public KnxGroupDto(final KnxGroup knxGroup) { + super(knxGroup.getPropertyName(), knxGroup.getTitle(), knxGroup.getPropertyType(), knxGroup.getBooleanValue(), knxGroup.getNumberValue(), knxGroup.getValueTimestamp()); id = knxGroup.getId(); addressRaw = knxGroup.getAddressRaw(); addressStr = knxGroup.getAddressStr(); - propertyName = knxGroup.getPropertyName(); dpt = knxGroup.getDpt(); - name = knxGroup.getTitle(); - propertyType = knxGroup.getPropertyType(); - - booleanValue = knxGroup.getBooleanValue(); - numberValue = knxGroup.getNumberValue(); - valueTimestamp = knxGroup.getValueTimestamp(); } } diff --git a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupSetService.java b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupSetService.java index 6ba038f..2d7c1a7 100644 --- a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupSetService.java +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupSetService.java @@ -1,6 +1,5 @@ package de.ph87.homeautomation.knx.group; -import de.ph87.homeautomation.knx.KnxThreadService; import de.ph87.homeautomation.property.IPropertyOwner; import de.ph87.homeautomation.property.PropertyDto; import de.ph87.homeautomation.property.PropertySetException; @@ -11,6 +10,7 @@ import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import tuwien.auto.calimero.GroupAddress; import java.util.List; @@ -23,14 +23,13 @@ import static de.ph87.homeautomation.shared.Helpers.quoteOrNull; @Slf4j @Service +@Transactional @RequiredArgsConstructor public class KnxGroupSetService implements IPropertyOwner { @Getter private final Pattern propertyNamePattern = Pattern.compile("^knx\\.group\\.(\\d+)\\.(\\d+)\\.(\\d+)$"); - private final KnxThreadService knxThreadService; - private final KnxGroupWriteService knxGroupWriteService; private final KnxGroupRepository knxGroupRepository; @@ -68,28 +67,18 @@ public class KnxGroupSetService implements IPropertyOwner { } @Override - public Optional findPropertyByName(final String propertyName) { - return knxGroupRepository.findByPropertyName(propertyName).map(this::toPropertyDto); + public Optional findPropertyByName(final String propertyName) { + return knxGroupRepository.findByPropertyName(propertyName).map(KnxGroupDto::new); } @Override public List findAllProperties() { - return knxGroupRepository.findAll().stream().map(this::toPropertyDto).collect(Collectors.toList()); + return knxGroupRepository.findAll().stream().map(KnxGroupDto::new).collect(Collectors.toList()); } @Override public List findAllPropertiesLike(final String like) { - return knxGroupRepository.findAllByPropertyNameLikeIgnoreCaseOrTitleLikeIgnoreCase(like, like).stream().map(this::toPropertyDto).collect(Collectors.toList()); - } - - private PropertyDto toPropertyDto(final KnxGroup knxGroup) { - return new PropertyDto( - knxGroup.getPropertyName(), - knxGroup.getTitle(), - knxGroup.getBooleanValue(), - knxGroup.getNumberValue(), - knxGroup.getValueTimestamp() - ); + return knxGroupRepository.findAllByPropertyNameLikeIgnoreCaseOrTitleLikeIgnoreCase(like, like).stream().map(KnxGroupDto::new).collect(Collectors.toList()); } private GroupAddress parseGroupAddress(final String propertyName) { 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 6a93bc9..8f4509b 100644 --- a/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java +++ b/src/main/java/de/ph87/homeautomation/knx/group/KnxGroupWriteService.java @@ -125,7 +125,6 @@ public class KnxGroupWriteService { return false; } final KnxGroup knxGroup = knxGroupOptional.get(); - try { final DPTXlator translator = findTranslator(knxGroup); if (translator instanceof DPTXlatorBoolean) { diff --git a/src/main/java/de/ph87/homeautomation/property/IProperty.java b/src/main/java/de/ph87/homeautomation/property/IProperty.java new file mode 100644 index 0000000..e40e055 --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/property/IProperty.java @@ -0,0 +1,7 @@ +package de.ph87.homeautomation.property; + +public interface IProperty { + + String getPropertyName(); + +} diff --git a/src/main/java/de/ph87/homeautomation/property/IPropertyOwner.java b/src/main/java/de/ph87/homeautomation/property/IPropertyOwner.java index eb4aa61..47d66ad 100644 --- a/src/main/java/de/ph87/homeautomation/property/IPropertyOwner.java +++ b/src/main/java/de/ph87/homeautomation/property/IPropertyOwner.java @@ -18,6 +18,6 @@ public interface IPropertyOwner { List findAllPropertiesLike(final String like); - Optional findPropertyByName(final String propertyName); + Optional findPropertyByName(final String propertyName); } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyController.java b/src/main/java/de/ph87/homeautomation/property/PropertyController.java index 93765a0..8c500a8 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyController.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyController.java @@ -31,4 +31,9 @@ public class PropertyController implements ISearchController { return propertyService.findAllLike("%" + term + "%").stream().map(propertyDto -> new KeyValuePair(propertyDto.name, propertyDto.title)).collect(Collectors.toList()); } + @PostMapping("set") + public void set(@RequestBody final PropertySetDto dto) throws PropertySetException { + propertyService.set(dto.getName(), dto.getValue()); + } + } diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyDto.java b/src/main/java/de/ph87/homeautomation/property/PropertyDto.java index a8452a1..92f3dbd 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyDto.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyDto.java @@ -11,15 +11,18 @@ public class PropertyDto { public final String title; + public final PropertyType propertyType; + public final Boolean booleanValue; public final Number numberValue; public final ZonedDateTime timestamp; - public PropertyDto(final String name, final String title, final Boolean booleanValue, final Number numberValue, final ZonedDateTime timestamp) { + public PropertyDto(final String name, final String title, final PropertyType propertyType, final Boolean booleanValue, final Number numberValue, final ZonedDateTime timestamp) { this.name = name; this.title = title; + this.propertyType = propertyType; this.booleanValue = booleanValue; this.numberValue = numberValue; this.timestamp = timestamp; diff --git a/src/main/java/de/ph87/homeautomation/property/PropertyService.java b/src/main/java/de/ph87/homeautomation/property/PropertyService.java index d027098..c0ad00f 100644 --- a/src/main/java/de/ph87/homeautomation/property/PropertyService.java +++ b/src/main/java/de/ph87/homeautomation/property/PropertyService.java @@ -1,12 +1,15 @@ package de.ph87.homeautomation.property; -import de.ph87.homeautomation.shared.Helpers; import de.ph87.office.web.NotFoundException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Stream; @Slf4j @Service @@ -34,17 +37,17 @@ public class PropertyService { } public List findAll() { - return propertyOwners.stream().map(IPropertyOwner::findAllProperties).reduce(new ArrayList<>(), Helpers::merge); + return mergeDtoLists(propertyOwners.stream().map(IPropertyOwner::findAllProperties)); } public List findAllLike(final String like) { - return propertyOwners.stream().map(iProperyOwner -> iProperyOwner.findAllPropertiesLike(like)).reduce(PropertyService::merge).orElse(Collections.emptyList()); + return mergeDtoLists(propertyOwners.stream().map(iProperyOwner -> iProperyOwner.findAllPropertiesLike(like))); } - private static List merge(final List a, final List b) { - final ArrayList c = new ArrayList<>(a); - c.addAll(b); - return c; + private List mergeDtoLists(final Stream> stream) { + final List result = new ArrayList<>(); + stream.forEach(result::addAll); + return result; } public PropertyDto getById(final String propertyName) { diff --git a/src/main/java/de/ph87/homeautomation/property/PropertySetDto.java b/src/main/java/de/ph87/homeautomation/property/PropertySetDto.java new file mode 100644 index 0000000..fdcd73d --- /dev/null +++ b/src/main/java/de/ph87/homeautomation/property/PropertySetDto.java @@ -0,0 +1,12 @@ +package de.ph87.homeautomation.property; + +import lombok.Data; + +@Data +public class PropertySetDto { + + private String name; + + private double value; + +} diff --git a/src/main/java/de/ph87/homeautomation/shared/Helpers.java b/src/main/java/de/ph87/homeautomation/shared/Helpers.java index 651df8a..f682c11 100644 --- a/src/main/java/de/ph87/homeautomation/shared/Helpers.java +++ b/src/main/java/de/ph87/homeautomation/shared/Helpers.java @@ -2,9 +2,17 @@ package de.ph87.homeautomation.shared; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; public class Helpers { + public static U mapIfNotNull(final T value, final Function map) { + if (value == null) { + return null; + } + return map.apply(value); + } + public static String quoteOrNull(final String value) { if (value == null) { return null; @@ -33,7 +41,7 @@ public class Helpers { return result; } - public static List merge(final List a, final List b) { + public static List merge(final List a, final List b) { final List c = new ArrayList<>(a); c.addAll(b); return c;