DeviceSwitch, DeviceShutter incl. UI
This commit is contained in:
parent
08f1c6f93f
commit
4939d9398f
@ -6,7 +6,7 @@ import {environment} from "../../environments/environment";
|
|||||||
export function NO_OP() {
|
export function NO_OP() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NO_SORT<T>(a: T, b: T): number {
|
export function NO_COMPARE<T>(a: T, b: T): number {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ export class ApiService {
|
|||||||
this.http.get<any>(environment.apiBasePath + path).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
this.http.get<any>(environment.apiBasePath + path).pipe(map(fromJson)).subscribe(next, errorInterceptor(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
getList<T>(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<T>(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<any[]>(environment.apiBasePath + path).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next, errorInterceptor(error));
|
this.http.get<any[]>(environment.apiBasePath + path).pipe(map(list => list.map(fromJson).sort(compare))).subscribe(next, errorInterceptor(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
src/main/angular/src/app/api/device/Device.ts
Normal file
73
src/main/angular/src/app/api/device/Device.ts
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
0
src/main/angular/src/app/api/device/DeviceSwitch.ts
Normal file
0
src/main/angular/src/app/api/device/DeviceSwitch.ts
Normal file
16
src/main/angular/src/app/api/device/device.service.spec.ts
Normal file
16
src/main/angular/src/app/api/device/device.service.spec.ts
Normal file
@ -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();
|
||||||
|
});
|
||||||
|
});
|
||||||
20
src/main/angular/src/app/api/device/device.service.ts
Normal file
20
src/main/angular/src/app/api/device/device.service.ts
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import {Injectable} from '@angular/core';
|
import {Injectable} from '@angular/core';
|
||||||
import {ApiService, NO_OP} from "../api.service";
|
import {ApiService, NO_OP} from "../api.service";
|
||||||
import {validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators";
|
import {validateBooleanAllowNull, validateDateAllowNull, validateNumberAllowNull, validateStringNotEmptyNotNull} from "../validators";
|
||||||
import {ISearchService} from "../ISearchService";
|
import {ISearchService} from "../ISearchService";
|
||||||
import {KeyValuePair} from "../KeyValuePair";
|
import {KeyValuePair} from "../KeyValuePair";
|
||||||
|
|
||||||
@ -8,17 +8,30 @@ export class Property {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public name: string,
|
public name: string,
|
||||||
public type: string,
|
public title: string,
|
||||||
public value: number,
|
public propertyType: string,
|
||||||
|
public booleanValue: boolean | null,
|
||||||
|
public numberValue: number | null,
|
||||||
|
public timestamp: Date | null,
|
||||||
) {
|
) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fromJsonAllowNull(json: any): Property | null {
|
||||||
|
if (json === undefined || json === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return this.fromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
static fromJson(json: any): Property {
|
static fromJson(json: any): Property {
|
||||||
return new Property(
|
return new Property(
|
||||||
validateStringNotEmptyNotNull(json['name']),
|
validateStringNotEmptyNotNull(json['name']),
|
||||||
validateStringNotEmptyNotNull(json['type']),
|
validateStringNotEmptyNotNull(json['title']),
|
||||||
validateNumberNotNull(json['value']),
|
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);
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,10 @@ import {NgModule} from '@angular/core';
|
|||||||
import {RouterModule, Routes} from '@angular/router';
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
import {ScheduleListComponent} from "./pages/schedule-list/schedule-list.component";
|
import {ScheduleListComponent} from "./pages/schedule-list/schedule-list.component";
|
||||||
import {ScheduleComponent} from "./pages/schedule/schedule.component";
|
import {ScheduleComponent} from "./pages/schedule/schedule.component";
|
||||||
|
import {DeviceListComponent} from "./pages/device-list/device-list.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
{path: 'DeviceList', component: DeviceListComponent},
|
||||||
{path: 'Schedule', component: ScheduleComponent},
|
{path: 'Schedule', component: ScheduleComponent},
|
||||||
{path: 'ScheduleList', component: ScheduleListComponent},
|
{path: 'ScheduleList', component: ScheduleListComponent},
|
||||||
{path: '**', redirectTo: '/ScheduleList'},
|
{path: '**', redirectTo: '/ScheduleList'},
|
||||||
|
|||||||
@ -4,6 +4,10 @@
|
|||||||
Zeitpläne
|
Zeitpläne
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="item" routerLink="/DeviceList" routerLinkActive="itemActive">
|
||||||
|
Geräte
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <div class="item breadcrumb" [routerLink]="['/Schedule', {id: dataService.schedule.id}]" routerLinkActive="itemActive" *ngIf="dataService.schedule">-->
|
<!-- <div class="item breadcrumb" [routerLink]="['/Schedule', {id: dataService.schedule.id}]" routerLinkActive="itemActive" *ngIf="dataService.schedule">-->
|
||||||
<!-- {{dataService.schedule.name}}-->
|
<!-- {{dataService.schedule.name}}-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
|
|||||||
@ -7,6 +7,10 @@
|
|||||||
border-right: 1px solid black;
|
border-right: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.item:hover {
|
||||||
|
background-color: lightskyblue;
|
||||||
|
}
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {FontAwesomeModule} from '@fortawesome/angular-fontawesome';
|
|||||||
import {NumberComponent} from './shared/number/number.component';
|
import {NumberComponent} from './shared/number/number.component';
|
||||||
import {ScheduleComponent} from "./pages/schedule/schedule.component";
|
import {ScheduleComponent} from "./pages/schedule/schedule.component";
|
||||||
import {SearchComponent} from './shared/search/search.component';
|
import {SearchComponent} from './shared/search/search.component';
|
||||||
|
import {DeviceListComponent} from './pages/device-list/device-list.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -20,6 +21,7 @@ import {SearchComponent} from './shared/search/search.component';
|
|||||||
ScheduleListComponent,
|
ScheduleListComponent,
|
||||||
NumberComponent,
|
NumberComponent,
|
||||||
SearchComponent,
|
SearchComponent,
|
||||||
|
DeviceListComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@ -0,0 +1,35 @@
|
|||||||
|
<ng-container *ngFor="let device of devices">
|
||||||
|
<ng-container [ngSwitch]="device.type">
|
||||||
|
<div class="device" *ngSwitchCase="'DeviceSwitch'" [class.switchOn]="isSwitchStateOn(device)" [class.switchOff]="isSwitchStateOff(device)" [class.switchUnknown]="isSwitchStateUnknown(device)">
|
||||||
|
<div class="title">
|
||||||
|
{{device.title}}
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<img class="control" src="assets/switch-on.svg" (click)="setSwitchState(device, true)"/>
|
||||||
|
<img class="control" src="assets/switch-off.svg" (click)="setSwitchState(device, false)"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="device" *ngSwitchCase="'DeviceShutter'" [class.blindOpen]="isShutterStateOpen(device)" [class.shutterBetween]="isShutterStateBetween(device)" [class.shutterClosed]="isShutterStateClosed(device)" [class.shutterUnknown]="isShutterStateUnknown(device)">
|
||||||
|
<div class="title">
|
||||||
|
{{device.title}}
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<div class="control button" (click)="setShutterPercent(device, 0)">
|
||||||
|
<span class="center">Auf</span>
|
||||||
|
</div>
|
||||||
|
<div class="control button" (click)="setShutterPercent(device, 40)">
|
||||||
|
<span class="center">50%</span>
|
||||||
|
</div>
|
||||||
|
<div class="control button" (click)="setShutterPercent(device, 75)">
|
||||||
|
<span class="center">90%</span>
|
||||||
|
</div>
|
||||||
|
<div class="control button" (click)="setShutterPercent(device, 85)">
|
||||||
|
<span class="center">Schlitze</span>
|
||||||
|
</div>
|
||||||
|
<div class="control button" (click)="setShutterPercent(device, 100)">
|
||||||
|
<span class="center">Zu</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -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<DeviceListComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [DeviceListComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(DeviceListComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -91,7 +91,6 @@ export class SearchComponent<T> implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select(result: KeyValuePair): void {
|
select(result: KeyValuePair): void {
|
||||||
console.log(result);
|
|
||||||
this.searching = false;
|
this.searching = false;
|
||||||
this.selected = result;
|
this.selected = result;
|
||||||
this.valueChange.emit(this.selected?.key);
|
this.valueChange.emit(this.selected?.key);
|
||||||
|
|||||||
8
src/main/angular/src/assets/switch-off.svg
Normal file
8
src/main/angular/src/assets/switch-off.svg
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 496.158 496.158" xml:space="preserve">
|
||||||
|
<path style="fill:#EB9783;" d="M496.158,248.085c0-137.021-111.07-248.082-248.076-248.082C111.07,0.003,0,111.063,0,248.085 c0,137.002,111.07,248.07,248.082,248.07C385.088,496.155,496.158,385.087,496.158,248.085z"/>
|
||||||
|
<g>
|
||||||
|
<path style="fill:#D63232;" d="M373.299,154.891c-19.558-26.212-47.401-46.023-78.401-55.787c-0.759-0.238-1.588-0.103-2.229,0.369 c-0.643,0.471-1.021,1.22-1.021,2.016l0.16,40.256c0,1.074,0.514,2.06,1.332,2.562c31.732,19.456,66.504,47,66.504,103.237 c0,61.515-50.047,111.56-111.562,111.56c-61.517,0-111.566-50.045-111.566-111.56c0-58.737,35.199-84.661,67.615-103.917 c0.836-0.496,1.363-1.492,1.363-2.58l0.154-39.909c0-0.793-0.375-1.539-1.013-2.01c-0.638-0.472-1.46-0.611-2.219-0.381 c-31.283,9.586-59.41,29.357-79.202,55.672c-20.467,27.215-31.285,59.603-31.285,93.662c0,86.099,70.049,156.146,156.152,156.146 c86.1,0,156.147-70.047,156.147-156.146C404.228,214.235,393.533,182.01,373.299,154.891z"/>
|
||||||
|
<path style="fill:#D63232;" d="M251.851,67.009h-7.549c-11.788,0-21.378,9.59-21.378,21.377v181.189 c0,11.787,9.59,21.377,21.378,21.377h7.549c11.788,0,21.378-9.59,21.378-21.377V88.386 C273.229,76.599,263.64,67.009,251.851,67.009z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
8
src/main/angular/src/assets/switch-on.svg
Normal file
8
src/main/angular/src/assets/switch-on.svg
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 496.158 496.158" xml:space="preserve">
|
||||||
|
<path style="fill:#97EB83;" d="M496.158,248.085c0-137.021-111.07-248.082-248.076-248.082C111.07,0.003,0,111.063,0,248.085 c0,137.002,111.07,248.07,248.082,248.07C385.088,496.155,496.158,385.087,496.158,248.085z"/>
|
||||||
|
<g>
|
||||||
|
<path style="fill:#32D632;" d="M373.299,154.891c-19.558-26.212-47.401-46.023-78.401-55.787c-0.759-0.238-1.588-0.103-2.229,0.369 c-0.643,0.471-1.021,1.22-1.021,2.016l0.16,40.256c0,1.074,0.514,2.06,1.332,2.562c31.732,19.456,66.504,47,66.504,103.237 c0,61.515-50.047,111.56-111.562,111.56c-61.517,0-111.566-50.045-111.566-111.56c0-58.737,35.199-84.661,67.615-103.917 c0.836-0.496,1.363-1.492,1.363-2.58l0.154-39.909c0-0.793-0.375-1.539-1.013-2.01c-0.638-0.472-1.46-0.611-2.219-0.381 c-31.283,9.586-59.41,29.357-79.202,55.672c-20.467,27.215-31.285,59.603-31.285,93.662c0,86.099,70.049,156.146,156.152,156.146 c86.1,0,156.147-70.047,156.147-156.146C404.228,214.235,393.533,182.01,373.299,154.891z"/>
|
||||||
|
<path style="fill:#32D632;" d="M251.851,67.009h-7.549c-11.788,0-21.378,9.59-21.378,21.377v181.189 c0,11.787,9.59,21.377,21.378,21.377h7.549c11.788,0,21.378-9.59,21.378-21.377V88.386 C273.229,76.599,263.64,67.009,251.851,67.009z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -1,9 +1,11 @@
|
|||||||
package de.ph87.homeautomation;
|
package de.ph87.homeautomation;
|
||||||
|
|
||||||
import com.luckycatlabs.sunrisesunset.Zenith;
|
import com.luckycatlabs.sunrisesunset.Zenith;
|
||||||
|
import de.ph87.homeautomation.device.DeviceWriteService;
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroupDto;
|
import de.ph87.homeautomation.knx.group.KnxGroupDto;
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroupRepository;
|
import de.ph87.homeautomation.knx.group.KnxGroupRepository;
|
||||||
import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
|
import de.ph87.homeautomation.knx.group.KnxGroupWriteService;
|
||||||
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
import de.ph87.homeautomation.property.PropertyType;
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import de.ph87.homeautomation.schedule.Schedule;
|
import de.ph87.homeautomation.schedule.Schedule;
|
||||||
import de.ph87.homeautomation.schedule.ScheduleRepository;
|
import de.ph87.homeautomation.schedule.ScheduleRepository;
|
||||||
@ -23,7 +25,9 @@ import java.time.ZonedDateTime;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class DemoDataService {
|
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;
|
private final KnxGroupWriteService knxGroupWriteService;
|
||||||
|
|
||||||
@ -31,19 +35,25 @@ public class DemoDataService {
|
|||||||
|
|
||||||
private final KnxGroupRepository knxGroupRepository;
|
private final KnxGroupRepository knxGroupRepository;
|
||||||
|
|
||||||
|
private final DeviceWriteService deviceWriteService;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void 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_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", 848, "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", 1539, "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", new GroupAddress(0, 4, 24), "5.001", PropertyType.PERCENT, 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", new GroupAddress(0, 3, 3), "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", new GroupAddress(0, 5, 13), "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", 797, "1.001", PropertyType.ON_OFF, 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 helligkeit = createKnxGroupIfNotExists("Helligkeit", 1286, "9.004", PropertyType.LUX, false, true);
|
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) {
|
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, 11, 30, 0, MIN30, true);
|
||||||
createTime(scheduleEgFlurLicht, 12, 30, 0, MIN30, false);
|
createTime(scheduleEgFlurLicht, 12, 30, 0, MIN30, false);
|
||||||
createTime(scheduleEgFlurLicht, 16, 30, 0, MIN30, true);
|
createTime(scheduleEgFlurLicht, 16, 30, 0, MIN30, true);
|
||||||
@ -54,36 +64,36 @@ public class DemoDataService {
|
|||||||
createTime(scheduleEgFlurLicht, 2, 0, 0, MIN30, false);
|
createTime(scheduleEgFlurLicht, 2, 0, 0, MIN30, false);
|
||||||
scheduleRepository.save(scheduleEgFlurLicht);
|
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, 7, 15, 0, MIN30, true);
|
||||||
createTime(scheduleEgAmbiente, 9, 30, 0, MIN30, false);
|
createTime(scheduleEgAmbiente, 9, 30, 0, MIN30, false);
|
||||||
createSunset(scheduleEgAmbiente, Zenith.OFFICIAL, MIN30, true);
|
createSunset(scheduleEgAmbiente, Zenith.OFFICIAL, MIN30, true);
|
||||||
createSunset(scheduleEgAmbiente, Zenith.ASTRONOMICAL, MIN30, false);
|
createSunset(scheduleEgAmbiente, Zenith.ASTRONOMICAL, MIN30, false);
|
||||||
scheduleRepository.save(scheduleEgAmbiente);
|
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, 7, 15, 0, MIN30, true);
|
||||||
createTime(scheduleOgAmbiente, 9, 30, 0, MIN30, false);
|
createTime(scheduleOgAmbiente, 9, 30, 0, MIN30, false);
|
||||||
createSunset(scheduleOgAmbiente, Zenith.OFFICIAL, MIN30, true);
|
createSunset(scheduleOgAmbiente, Zenith.OFFICIAL, MIN30, true);
|
||||||
createSunset(scheduleOgAmbiente, Zenith.ASTRONOMICAL, MIN30, false);
|
createSunset(scheduleOgAmbiente, Zenith.ASTRONOMICAL, MIN30, false);
|
||||||
scheduleRepository.save(scheduleOgAmbiente);
|
scheduleRepository.save(scheduleOgAmbiente);
|
||||||
|
|
||||||
final Schedule scheduleWohnzimmerRollladen = createSchedule("Rollläden Wohnzimmer", wohnzimmer_rollladen_position_anfahren, PropertyType.SHUTTER);
|
final Schedule scheduleWohnzimmerRollladen = createSchedule("Rollläden Wohnzimmer", wohnzimmer_rollladen_position_anfahren);
|
||||||
createSunrise(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, 0);
|
createSunrise(scheduleWohnzimmerRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0);
|
||||||
createSunset(scheduleWohnzimmerRollladen, Zenith.CIVIL, 0, 100);
|
createSunset(scheduleWohnzimmerRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100);
|
||||||
scheduleRepository.save(scheduleWohnzimmerRollladen);
|
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);
|
createTime(scheduleSchlafzimmerRollladen, 7, 0, 0, 0, 0);
|
||||||
createSunset(scheduleSchlafzimmerRollladen, Zenith.CIVIL, 0, 100);
|
createSunset(scheduleSchlafzimmerRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100);
|
||||||
scheduleRepository.save(scheduleSchlafzimmerRollladen);
|
scheduleRepository.save(scheduleSchlafzimmerRollladen);
|
||||||
|
|
||||||
final Schedule scheduleFlurRollladen = createSchedule("Rollladen Flur", flur_rollladen_position_anfahren, PropertyType.SHUTTER);
|
final Schedule scheduleFlurRollladen = createSchedule("Rollladen Flur", flur_rollladen_position_anfahren);
|
||||||
createSunrise(scheduleFlurRollladen, Zenith.CIVIL, 0, 0);
|
createSunrise(scheduleFlurRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0);
|
||||||
createSunset(scheduleFlurRollladen, Zenith.CIVIL, 0, 100);
|
createSunset(scheduleFlurRollladen, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100);
|
||||||
scheduleRepository.save(scheduleFlurRollladen);
|
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, 10, 30, 0, MIN30, true);
|
||||||
createTime(scheduleBadLichtMitte, 11, 30, 0, MIN30, false);
|
createTime(scheduleBadLichtMitte, 11, 30, 0, MIN30, false);
|
||||||
createTime(scheduleBadLichtMitte, 15, 30, 0, MIN30, true);
|
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();
|
final Schedule schedule = new Schedule();
|
||||||
schedule.setEnabled(true);
|
schedule.setEnabled(true);
|
||||||
schedule.setName(s);
|
schedule.setName(s);
|
||||||
schedule.setPropertyName(knxGroupDto.propertyName);
|
schedule.setPropertyName(propertyDto.getName());
|
||||||
schedule.setPropertyType(propertyType);
|
schedule.setPropertyType(propertyDto.getPropertyType());
|
||||||
return schedule;
|
return schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KnxGroupDto createKnxGroupIfNotExists(final String name, final int 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) {
|
||||||
return createKnxGroupIfNotExists(name, new GroupAddress(address), dpt, type, readable, multiGroup);
|
final GroupAddress address = new GroupAddress(main, mid, sub);
|
||||||
}
|
|
||||||
|
|
||||||
private KnxGroupDto createKnxGroupIfNotExists(final String name, final GroupAddress address, final String dpt, final PropertyType type, final boolean readable, final boolean multiGroup) {
|
|
||||||
return knxGroupRepository.findByAddressRaw(address.getRawAddress()).map(KnxGroupDto::new).orElseGet(() -> knxGroupWriteService.create(name, address, dpt, type, readable, multiGroup));
|
return knxGroupRepository.findByAddressRaw(address.getRawAddress()).map(KnxGroupDto::new).orElseGet(() -> knxGroupWriteService.create(name, address, dpt, type, readable, multiGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
package de.ph87.homeautomation.device;
|
package de.ph87.homeautomation.device;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.device.devices.DeviceDto;
|
||||||
|
import de.ph87.homeautomation.property.PropertySetException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -14,9 +14,16 @@ public class DeviceController {
|
|||||||
|
|
||||||
private final DeviceReadService deviceReadService;
|
private final DeviceReadService deviceReadService;
|
||||||
|
|
||||||
|
private final DeviceWriteService deviceWriteService;
|
||||||
|
|
||||||
@GetMapping("findAll")
|
@GetMapping("findAll")
|
||||||
public List<DeviceDto> findAll() {
|
public List<DeviceDto> findAll() {
|
||||||
return deviceReadService.findAll();
|
return deviceReadService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("set")
|
||||||
|
public void set(@RequestBody final DeviceSetDto dto) throws PropertySetException {
|
||||||
|
deviceWriteService.set(dto);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package de.ph87.homeautomation.device;
|
package de.ph87.homeautomation.device;
|
||||||
|
|
||||||
import de.ph87.homeautomation.device.devices.*;
|
import de.ph87.homeautomation.device.devices.*;
|
||||||
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
import de.ph87.homeautomation.property.PropertyService;
|
import de.ph87.homeautomation.property.PropertyService;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -10,6 +11,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static de.ph87.homeautomation.shared.Helpers.mapIfNotNull;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -27,12 +30,16 @@ public class DeviceReadService {
|
|||||||
private DeviceDto toDto(final Device device) {
|
private DeviceDto toDto(final Device device) {
|
||||||
if (device instanceof DeviceSwitch) {
|
if (device instanceof DeviceSwitch) {
|
||||||
final DeviceSwitch deviceSwitch = (DeviceSwitch) device;
|
final DeviceSwitch deviceSwitch = (DeviceSwitch) device;
|
||||||
return new DeviceSwitchDto(deviceSwitch, propertyService.readBoolean(deviceSwitch.getStatePropertyName()));
|
final PropertyDto getState = mapIfNotNull(deviceSwitch.getGetState(), propertyService::getById);
|
||||||
} else if (device instanceof DeviceNumber) {
|
final PropertyDto setState = mapIfNotNull(deviceSwitch.getSetState(), propertyService::getById);
|
||||||
final DeviceNumber deviceNumber = (DeviceNumber) device;
|
return new DeviceSwitchDto(deviceSwitch, getState, setState);
|
||||||
return new DeviceNumberDto(deviceNumber, propertyService.readNumber(deviceNumber.getValuePropertyName()));
|
} 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 + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,13 +1,18 @@
|
|||||||
package de.ph87.homeautomation.device;
|
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.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.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import static de.ph87.homeautomation.shared.Helpers.mapIfNotNull;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -17,17 +22,49 @@ public class DeviceWriteService {
|
|||||||
|
|
||||||
private final DeviceRepository deviceRepository;
|
private final DeviceRepository deviceRepository;
|
||||||
|
|
||||||
@PostConstruct
|
private final PropertyService propertyService;
|
||||||
public void postConstruct() {
|
|
||||||
final DeviceSwitch deviceSwitch = new DeviceSwitch();
|
|
||||||
deviceSwitch.setName("TEST");
|
|
||||||
deviceSwitch.setStatePropertyName("knx.group.0.3.6");
|
|
||||||
deviceRepository.save(deviceSwitch);
|
|
||||||
|
|
||||||
final DeviceNumber deviceNumber = new DeviceNumber();
|
public void createDeviceSwitch(final String title, final PropertyDto getState, final PropertyDto setState) {
|
||||||
deviceNumber.setName("Helligkeit");
|
final DeviceSwitch deviceSwitch = new DeviceSwitch();
|
||||||
deviceNumber.setValuePropertyName("knx.group.0.5.6");
|
deviceSwitch.setTitle(title);
|
||||||
deviceRepository.save(deviceNumber);
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,6 @@ public abstract class Device {
|
|||||||
@Setter(AccessLevel.NONE)
|
@Setter(AccessLevel.NONE)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
private String name;
|
private String title;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ -8,13 +7,13 @@ public abstract class DeviceDto {
|
|||||||
|
|
||||||
public final long id;
|
public final long id;
|
||||||
|
|
||||||
public final String name;
|
public final String title;
|
||||||
|
|
||||||
public final String type;
|
public final String type;
|
||||||
|
|
||||||
public DeviceDto(final Device device) {
|
public DeviceDto(final Device device) {
|
||||||
this.id = device.getId();
|
this.id = device.getId();
|
||||||
this.name = device.getName();
|
this.title = device.getTitle();
|
||||||
this.type = device.getClass().getSimpleName();
|
this.type = device.getClass().getSimpleName();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -10,8 +10,10 @@ import javax.persistence.Entity;
|
|||||||
@Setter
|
@Setter
|
||||||
@ToString
|
@ToString
|
||||||
@Entity
|
@Entity
|
||||||
public class DeviceNumber extends Device {
|
public class DeviceShutter extends Device {
|
||||||
|
|
||||||
private String valuePropertyName;
|
private String getPercent;
|
||||||
|
|
||||||
|
private String setPercent;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -12,8 +12,8 @@ import javax.persistence.Entity;
|
|||||||
@Entity
|
@Entity
|
||||||
public class DeviceSwitch extends Device {
|
public class DeviceSwitch extends Device {
|
||||||
|
|
||||||
private String switchPropertyName;
|
private String setState;
|
||||||
|
|
||||||
private String statePropertyName;
|
private String getState;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,19 @@
|
|||||||
package de.ph87.homeautomation.device.devices;
|
package de.ph87.homeautomation.device.devices;
|
||||||
|
|
||||||
import de.ph87.homeautomation.device.DeviceDto;
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class DeviceSwitchDto extends DeviceDto {
|
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);
|
super(device);
|
||||||
this.state = state;
|
this.getState = getState;
|
||||||
|
this.setState = setState;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import de.ph87.homeautomation.shared.AbstractThreadService;
|
|||||||
import de.ph87.network.router.Router;
|
import de.ph87.network.router.Router;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.event.TransactionalEventListener;
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
import tuwien.auto.calimero.CloseEvent;
|
import tuwien.auto.calimero.CloseEvent;
|
||||||
@ -153,9 +152,8 @@ public class KnxThreadService extends AbstractThreadService implements NetworkLi
|
|||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener(KnxThreadWakeUpEvent.class)
|
|
||||||
@TransactionalEventListener
|
@TransactionalEventListener
|
||||||
public void wakeUp() {
|
public void wakeUp(final KnxThreadWakeUpEvent event) {
|
||||||
_wakeUp();
|
_wakeUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
|
import de.ph87.homeautomation.property.IProperty;
|
||||||
import de.ph87.homeautomation.property.PropertyType;
|
import de.ph87.homeautomation.property.PropertyType;
|
||||||
import lombok.AccessLevel;
|
import lombok.AccessLevel;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -14,7 +15,7 @@ import java.time.ZonedDateTime;
|
|||||||
@Setter
|
@Setter
|
||||||
@ToString
|
@ToString
|
||||||
@Entity
|
@Entity
|
||||||
public class KnxGroup {
|
public class KnxGroup implements IProperty {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
import de.ph87.homeautomation.property.PropertyType;
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.time.ZonedDateTime;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class KnxGroupDto {
|
public class KnxGroupDto extends PropertyDto {
|
||||||
|
|
||||||
public final long id;
|
public final long id;
|
||||||
|
|
||||||
@ -14,32 +12,14 @@ public class KnxGroupDto {
|
|||||||
|
|
||||||
public final String addressStr;
|
public final String addressStr;
|
||||||
|
|
||||||
public final String propertyName;
|
|
||||||
|
|
||||||
public final String dpt;
|
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) {
|
public KnxGroupDto(final KnxGroup knxGroup) {
|
||||||
|
super(knxGroup.getPropertyName(), knxGroup.getTitle(), knxGroup.getPropertyType(), knxGroup.getBooleanValue(), knxGroup.getNumberValue(), knxGroup.getValueTimestamp());
|
||||||
id = knxGroup.getId();
|
id = knxGroup.getId();
|
||||||
addressRaw = knxGroup.getAddressRaw();
|
addressRaw = knxGroup.getAddressRaw();
|
||||||
addressStr = knxGroup.getAddressStr();
|
addressStr = knxGroup.getAddressStr();
|
||||||
propertyName = knxGroup.getPropertyName();
|
|
||||||
dpt = knxGroup.getDpt();
|
dpt = knxGroup.getDpt();
|
||||||
name = knxGroup.getTitle();
|
|
||||||
propertyType = knxGroup.getPropertyType();
|
|
||||||
|
|
||||||
booleanValue = knxGroup.getBooleanValue();
|
|
||||||
numberValue = knxGroup.getNumberValue();
|
|
||||||
valueTimestamp = knxGroup.getValueTimestamp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package de.ph87.homeautomation.knx.group;
|
package de.ph87.homeautomation.knx.group;
|
||||||
|
|
||||||
import de.ph87.homeautomation.knx.KnxThreadService;
|
|
||||||
import de.ph87.homeautomation.property.IPropertyOwner;
|
import de.ph87.homeautomation.property.IPropertyOwner;
|
||||||
import de.ph87.homeautomation.property.PropertyDto;
|
import de.ph87.homeautomation.property.PropertyDto;
|
||||||
import de.ph87.homeautomation.property.PropertySetException;
|
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.ApplicationEventPublisher;
|
||||||
import org.springframework.context.event.EventListener;
|
import org.springframework.context.event.EventListener;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import tuwien.auto.calimero.GroupAddress;
|
import tuwien.auto.calimero.GroupAddress;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -23,14 +23,13 @@ import static de.ph87.homeautomation.shared.Helpers.quoteOrNull;
|
|||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
@Transactional
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class KnxGroupSetService implements IPropertyOwner {
|
public class KnxGroupSetService implements IPropertyOwner {
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Pattern propertyNamePattern = Pattern.compile("^knx\\.group\\.(\\d+)\\.(\\d+)\\.(\\d+)$");
|
private final Pattern propertyNamePattern = Pattern.compile("^knx\\.group\\.(\\d+)\\.(\\d+)\\.(\\d+)$");
|
||||||
|
|
||||||
private final KnxThreadService knxThreadService;
|
|
||||||
|
|
||||||
private final KnxGroupWriteService knxGroupWriteService;
|
private final KnxGroupWriteService knxGroupWriteService;
|
||||||
|
|
||||||
private final KnxGroupRepository knxGroupRepository;
|
private final KnxGroupRepository knxGroupRepository;
|
||||||
@ -68,28 +67,18 @@ public class KnxGroupSetService implements IPropertyOwner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<PropertyDto> findPropertyByName(final String propertyName) {
|
public Optional<KnxGroupDto> findPropertyByName(final String propertyName) {
|
||||||
return knxGroupRepository.findByPropertyName(propertyName).map(this::toPropertyDto);
|
return knxGroupRepository.findByPropertyName(propertyName).map(KnxGroupDto::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PropertyDto> findAllProperties() {
|
public List<PropertyDto> findAllProperties() {
|
||||||
return knxGroupRepository.findAll().stream().map(this::toPropertyDto).collect(Collectors.toList());
|
return knxGroupRepository.findAll().stream().map(KnxGroupDto::new).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PropertyDto> findAllPropertiesLike(final String like) {
|
public List<PropertyDto> findAllPropertiesLike(final String like) {
|
||||||
return knxGroupRepository.findAllByPropertyNameLikeIgnoreCaseOrTitleLikeIgnoreCase(like, like).stream().map(this::toPropertyDto).collect(Collectors.toList());
|
return knxGroupRepository.findAllByPropertyNameLikeIgnoreCaseOrTitleLikeIgnoreCase(like, like).stream().map(KnxGroupDto::new).collect(Collectors.toList());
|
||||||
}
|
|
||||||
|
|
||||||
private PropertyDto toPropertyDto(final KnxGroup knxGroup) {
|
|
||||||
return new PropertyDto(
|
|
||||||
knxGroup.getPropertyName(),
|
|
||||||
knxGroup.getTitle(),
|
|
||||||
knxGroup.getBooleanValue(),
|
|
||||||
knxGroup.getNumberValue(),
|
|
||||||
knxGroup.getValueTimestamp()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupAddress parseGroupAddress(final String propertyName) {
|
private GroupAddress parseGroupAddress(final String propertyName) {
|
||||||
|
|||||||
@ -125,7 +125,6 @@ public class KnxGroupWriteService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final KnxGroup knxGroup = knxGroupOptional.get();
|
final KnxGroup knxGroup = knxGroupOptional.get();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final DPTXlator translator = findTranslator(knxGroup);
|
final DPTXlator translator = findTranslator(knxGroup);
|
||||||
if (translator instanceof DPTXlatorBoolean) {
|
if (translator instanceof DPTXlatorBoolean) {
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
package de.ph87.homeautomation.property;
|
||||||
|
|
||||||
|
public interface IProperty {
|
||||||
|
|
||||||
|
String getPropertyName();
|
||||||
|
|
||||||
|
}
|
||||||
@ -18,6 +18,6 @@ public interface IPropertyOwner {
|
|||||||
|
|
||||||
List<PropertyDto> findAllPropertiesLike(final String like);
|
List<PropertyDto> findAllPropertiesLike(final String like);
|
||||||
|
|
||||||
Optional<PropertyDto> findPropertyByName(final String propertyName);
|
Optional<? extends PropertyDto> findPropertyByName(final String propertyName);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,15 +11,18 @@ public class PropertyDto {
|
|||||||
|
|
||||||
public final String title;
|
public final String title;
|
||||||
|
|
||||||
|
public final PropertyType propertyType;
|
||||||
|
|
||||||
public final Boolean booleanValue;
|
public final Boolean booleanValue;
|
||||||
|
|
||||||
public final Number numberValue;
|
public final Number numberValue;
|
||||||
|
|
||||||
public final ZonedDateTime timestamp;
|
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.name = name;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
this.propertyType = propertyType;
|
||||||
this.booleanValue = booleanValue;
|
this.booleanValue = booleanValue;
|
||||||
this.numberValue = numberValue;
|
this.numberValue = numberValue;
|
||||||
this.timestamp = timestamp;
|
this.timestamp = timestamp;
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
package de.ph87.homeautomation.property;
|
package de.ph87.homeautomation.property;
|
||||||
|
|
||||||
import de.ph87.homeautomation.shared.Helpers;
|
|
||||||
import de.ph87.office.web.NotFoundException;
|
import de.ph87.office.web.NotFoundException;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
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
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -34,17 +37,17 @@ public class PropertyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<PropertyDto> findAll() {
|
public List<PropertyDto> findAll() {
|
||||||
return propertyOwners.stream().map(IPropertyOwner::findAllProperties).reduce(new ArrayList<>(), Helpers::merge);
|
return mergeDtoLists(propertyOwners.stream().map(IPropertyOwner::findAllProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PropertyDto> findAllLike(final String like) {
|
public List<PropertyDto> 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 <T> List<T> merge(final List<T> a, final List<T> b) {
|
private List<PropertyDto> mergeDtoLists(final Stream<? extends List<? extends PropertyDto>> stream) {
|
||||||
final ArrayList<T> c = new ArrayList<>(a);
|
final List<PropertyDto> result = new ArrayList<>();
|
||||||
c.addAll(b);
|
stream.forEach(result::addAll);
|
||||||
return c;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyDto getById(final String propertyName) {
|
public PropertyDto getById(final String propertyName) {
|
||||||
|
|||||||
@ -0,0 +1,12 @@
|
|||||||
|
package de.ph87.homeautomation.property;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PropertySetDto {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,9 +2,17 @@ package de.ph87.homeautomation.shared;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class Helpers {
|
public class Helpers {
|
||||||
|
|
||||||
|
public static <T, U> U mapIfNotNull(final T value, final Function<T, U> map) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return map.apply(value);
|
||||||
|
}
|
||||||
|
|
||||||
public static String quoteOrNull(final String value) {
|
public static String quoteOrNull(final String value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -33,7 +41,7 @@ public class Helpers {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> List<T> merge(final List<T> a, final List<T> b) {
|
public static <T> List<T> merge(final List<? extends T> a, final List<? extends T> b) {
|
||||||
final List<T> c = new ArrayList<>(a);
|
final List<T> c = new ArrayList<>(a);
|
||||||
c.addAll(b);
|
c.addAll(b);
|
||||||
return c;
|
return c;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user