moved PropertyType from Schedule to Property ^^

This commit is contained in:
Patrick Haßel 2021-11-06 20:22:33 +01:00
parent 9b75e591fd
commit bc8ba1ef8b
16 changed files with 119 additions and 75 deletions

View File

@ -9,6 +9,7 @@ export class Property {
constructor(
public name: string,
public type: string,
public title: string,
public value: number | null,
public valueTimestamp: Date | null,
@ -26,6 +27,7 @@ export class Property {
static fromJson(json: any): Property {
return new Property(
validateStringNotEmptyNotNull(json['name']),
validateStringNotEmptyNotNull(json['type']),
validateStringNotEmptyNotNull(json['title']),
validateNumberAllowNull(json['value']),
validateDateAllowNull(json['valueTimestamp']),

View File

@ -1,5 +1,6 @@
import {validateBooleanNotNull, validateListOrEmpty, validateNumberNotNull, validateStringNotEmptyNotNull, validateStringNullToEmpty} from "../validators";
import {validateBooleanNotNull, validateListOrEmpty, validateNumberNotNull, validateStringNotEmptyNotNull} from "../validators";
import {ScheduleEntry} from "./entry/ScheduleEntry";
import {Property} from "../property/property.service";
export class Schedule {
@ -7,8 +8,7 @@ export class Schedule {
public id: number,
public enabled: boolean,
public title: string,
public propertyName: string,
public propertyType: string,
public property: Property | null,
public entries: ScheduleEntry[],
) {
// nothing
@ -19,8 +19,7 @@ export class Schedule {
validateNumberNotNull(json['id']),
validateBooleanNotNull(json['enabled']),
validateStringNotEmptyNotNull(json['title']),
validateStringNullToEmpty(json['propertyName']),
validateStringNullToEmpty(json['propertyType']),
Property.fromJsonAllowNull(json['property']),
validateListOrEmpty(json['entries'], ScheduleEntry.fromJson, ScheduleEntry.compare),
);
}

View File

@ -14,15 +14,10 @@
<app-edit-field [initial]="schedule.title" (valueChange)="set(null, 'title', $event)"></app-edit-field>
</td>
<td colspan="5">
<app-search [searchService]="propertyService" [initial]="schedule.propertyName" (valueChange)="set(null, 'propertyName', $event)"></app-search>
<app-search [searchService]="propertyService" [initial]="schedule.property?.name" (valueChange)="set(null, 'propertyName', $event)"></app-search>
</td>
<td colspan="9">
<select [(ngModel)]="schedule.propertyType" (ngModelChange)="set(null,'propertyType', schedule.propertyType)">
<option value="SWITCH">An / Aus</option>
<option value="PERCENT">Prozent</option>
<option value="SHUTTER">Rollladen</option>
<option value="SCENE">Szene</option>
</select>
{{schedule.property?.type}}
</td>
</tr>
<tr [class.disabled]="!schedule.enabled">
@ -137,20 +132,10 @@
<td class="empty last"></td>
</ng-container>
<td *ngIf="schedule.propertyType === 'SWITCH'" [class.true]="entry.value" [class.false]="!entry.value" (click)="set(entry, 'value', entry.value > 0 ? 0 : 1)">
<td *ngIf="schedule.property?.type === 'SWITCH'" [class.true]="entry.value" [class.false]="!entry.value" (click)="set(entry, 'value', entry.value > 0 ? 0 : 1)">
{{entry.value ? "An" : "Aus"}}
</td>
<td *ngIf="schedule.propertyType === 'PERCENT'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
</select>
</td>
<td *ngIf="schedule.propertyType === 'SCENE'">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option *ngFor="let _ of [].constructor(64); let value = index" [ngValue]="value + 1">{{value + 1}}</option>
</select>
</td>
<td *ngIf="schedule.propertyType === 'SHUTTER'" [class.true]="entry.value === 0" [class.false]="entry.value === 100" [class.tristate]="0 < entry.value && entry.value < 100">
<td *ngIf="schedule.property?.type === 'SHUTTER'" [class.true]="entry.value === 0" [class.false]="entry.value === 100" [class.tristate]="0 < entry.value && entry.value < 100">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option [ngValue]="0">100% Offen</option>
<option [ngValue]="35">&nbsp;50%</option>
@ -159,6 +144,26 @@
<option [ngValue]="100">100% Geschlossen</option>
</select>
</td>
<td *ngIf="schedule.property?.type === 'BRIGHTNESS'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
</select>
</td>
<td *ngIf="schedule.property?.type === 'COLOR_TEMPERATURE'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
</select>
</td>
<td *ngIf="schedule.property?.type === 'LUX'" [class.true]="entry.value" [class.false]="!entry.value" [class.tristate]="0 < entry.value && entry.value < 100">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option *ngFor="let _ of [].constructor(21); let value = index" [ngValue]="value * 5">{{value * 5}}%</option>
</select>
</td>
<td *ngIf="schedule.property?.type === 'SCENE'">
<select [(ngModel)]="entry.value" (ngModelChange)="set(entry, 'value', entry.value)">
<option *ngFor="let _ of [].constructor(64); let value = index" [ngValue]="value + 1">{{value + 1}}</option>
</select>
</td>
<td class="delete" (click)="delete(entry)">
<fa-icon title="Löschen" [icon]="faTimes"></fa-icon>

View File

@ -8,8 +8,8 @@ import de.ph87.homeautomation.knx.group.KnxGroup;
import de.ph87.homeautomation.knx.group.KnxGroupReadService;
import de.ph87.homeautomation.property.Property;
import de.ph87.homeautomation.property.PropertyRepository;
import de.ph87.homeautomation.property.PropertyType;
import de.ph87.homeautomation.schedule.Schedule;
import de.ph87.homeautomation.schedule.SchedulePropertyType;
import de.ph87.homeautomation.schedule.ScheduleRepository;
import de.ph87.homeautomation.schedule.entry.ScheduleEntry;
import de.ph87.homeautomation.schedule.entry.ScheduleEntryType;
@ -42,16 +42,16 @@ public class DemoDataService {
private final KnxGroupReadService knxGroupReadService;
public void insertDemoData() {
final Property ambiente_eg = createProperty("ambiente.eg", "Ambiente EG", knx(0, 3, 81), knx(0, 3, 80));
final Property ambiente_og = createProperty("ambiente.og", "Ambiente OG", knx(0, 6, 2), knx(0, 6, 3));
final Property bad_licht = createProperty("bad.licht", "Bad Licht", knx(0, 5, 19), knx(0, 3, 73));
final Property bad_licht_mitte = createProperty("bad.licht.mitte", "Bad Licht Mitte", knx(0, 3, 30), knx(0, 3, 29));
final Property flur_eg_licht = createProperty("flur.eg.licht", "Flur EG Licht", knx(0, 4, 8), knx(0, 5, 14));
final Property wohnzimmer_rollladen = createProperty("wohnzimmer.rollladen", "Wohnzimmer Rollladen", null, knx(0, 4, 24));
final Property schlafzimmer_rollladen = createProperty("schlafzimmer_rollladen", "Schlafzimmer Rollladen", null, knx(0, 3, 3));
final Property flur_og_rollladen = createProperty("flur_og_rollladen", "Flur OG Rollladen", null, knx(0, 5, 13));
final Property helligkeit = createProperty("helligkeit", "Helligkeit", knx(0, 5, 6), null);
final Property szene_haus = createProperty("szene_haus", "Szene Haus ", null, knx(0, 0, 21));
final Property ambiente_eg = createProperty("ambiente.eg", PropertyType.SWITCH, "Ambiente EG", knx(0, 3, 81), knx(0, 3, 80));
final Property ambiente_og = createProperty("ambiente.og", PropertyType.SWITCH, "Ambiente OG", knx(0, 6, 2), knx(0, 6, 3));
final Property bad_licht = createProperty("bad.licht", PropertyType.SWITCH, "Bad Licht", knx(0, 5, 19), knx(0, 3, 73));
final Property bad_licht_mitte = createProperty("bad.licht.mitte", PropertyType.SWITCH, "Bad Licht Mitte", knx(0, 3, 30), knx(0, 3, 29));
final Property flur_eg_licht = createProperty("flur.eg.licht", PropertyType.SWITCH, "Flur EG Licht", knx(0, 4, 8), knx(0, 5, 14));
final Property wohnzimmer_rollladen = createProperty("wohnzimmer.rollladen", PropertyType.SHUTTER, "Wohnzimmer Rollladen", null, knx(0, 4, 24));
final Property schlafzimmer_rollladen = createProperty("schlafzimmer_rollladen", PropertyType.SHUTTER, "Schlafzimmer Rollladen", null, knx(0, 3, 3));
final Property flur_og_rollladen = createProperty("flur_og_rollladen", PropertyType.SHUTTER, "Flur OG Rollladen", null, knx(0, 5, 13));
final Property helligkeit = createProperty("helligkeit", PropertyType.LUX, "Helligkeit", knx(0, 5, 6), null);
final Property szene_haus = createProperty("szene_haus", PropertyType.SCENE, "Szene Haus ", null, knx(0, 0, 21));
if (deviceRepository.count() == 0) {
deviceWriteService.createDeviceSwitch("Ambiente EG", ambiente_eg);
@ -63,7 +63,7 @@ public class DemoDataService {
}
if (scheduleRepository.count() == 0) {
final Schedule scheduleEgFlurLicht = createSchedule(true, "EG Flur Licht", flur_eg_licht, SchedulePropertyType.SWITCH);
final Schedule scheduleEgFlurLicht = createSchedule(true, "EG Flur Licht", flur_eg_licht);
createTime(scheduleEgFlurLicht, true, 1, 0, 0, MIN30, true);
createTime(scheduleEgFlurLicht, true, 2, 0, 0, MIN30, false);
createTime(scheduleEgFlurLicht, true, 7, 30, 0, MIN30, true);
@ -74,36 +74,36 @@ public class DemoDataService {
createTime(scheduleEgFlurLicht, true, 20, 0, 0, MIN30, false);
scheduleRepository.save(scheduleEgFlurLicht);
final Schedule scheduleEgAmbiente = createSchedule(false, "Ambiente EG", ambiente_eg, SchedulePropertyType.SWITCH);
final Schedule scheduleEgAmbiente = createSchedule(false, "Ambiente EG", ambiente_eg);
createTime(scheduleEgAmbiente, true, 7, 15, 0, MIN30, true);
createTime(scheduleEgAmbiente, true, 9, 30, 0, MIN30, false);
createSunset(scheduleEgAmbiente, true, Zenith.OFFICIAL, MIN30, true);
createSunset(scheduleEgAmbiente, true, Zenith.ASTRONOMICAL, MIN30, false);
scheduleRepository.save(scheduleEgAmbiente);
final Schedule scheduleOgAmbiente = createSchedule(false, "Ambiente OG", ambiente_og, SchedulePropertyType.SWITCH);
final Schedule scheduleOgAmbiente = createSchedule(false, "Ambiente OG", ambiente_og);
createTime(scheduleOgAmbiente, true, 7, 15, 0, MIN30, true);
createTime(scheduleOgAmbiente, true, 9, 30, 0, MIN30, false);
createSunset(scheduleOgAmbiente, true, Zenith.OFFICIAL, MIN30, true);
createSunset(scheduleOgAmbiente, true, Zenith.ASTRONOMICAL, MIN30, false);
scheduleRepository.save(scheduleOgAmbiente);
final Schedule scheduleWohnzimmerRollladen = createSchedule(true, "Rollläden Wohnzimmer", wohnzimmer_rollladen, SchedulePropertyType.SHUTTER);
final Schedule scheduleWohnzimmerRollladen = createSchedule(true, "Rollläden Wohnzimmer", wohnzimmer_rollladen);
createSunrise(scheduleWohnzimmerRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0);
createSunset(scheduleWohnzimmerRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100);
scheduleRepository.save(scheduleWohnzimmerRollladen);
final Schedule scheduleSchlafzimmerRollladen = createSchedule(true, "Rollläden Schlafzimmer", schlafzimmer_rollladen, SchedulePropertyType.SHUTTER);
final Schedule scheduleSchlafzimmerRollladen = createSchedule(true, "Rollläden Schlafzimmer", schlafzimmer_rollladen);
createTime(scheduleSchlafzimmerRollladen, true, 7, 0, 0, 0, 0);
createSunset(scheduleSchlafzimmerRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100);
scheduleRepository.save(scheduleSchlafzimmerRollladen);
final Schedule scheduleFlurRollladen = createSchedule(true, "Rollladen Flur", flur_og_rollladen, SchedulePropertyType.SHUTTER);
final Schedule scheduleFlurRollladen = createSchedule(true, "Rollladen Flur", flur_og_rollladen);
createSunrise(scheduleFlurRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 0);
createSunset(scheduleFlurRollladen, true, BETWEEN_OFFICIAL_AND_CIVIL, 0, 100);
scheduleRepository.save(scheduleFlurRollladen);
final Schedule scheduleBadLichtMitte = createSchedule(false, "Bad Licht Mitte", bad_licht_mitte, SchedulePropertyType.SWITCH);
final Schedule scheduleBadLichtMitte = createSchedule(false, "Bad Licht Mitte", bad_licht_mitte);
createTime(scheduleBadLichtMitte, true, 10, 30, 0, MIN30, true);
createTime(scheduleBadLichtMitte, true, 11, 30, 0, MIN30, false);
createTime(scheduleBadLichtMitte, true, 15, 30, 0, MIN30, true);
@ -114,7 +114,7 @@ public class DemoDataService {
createTime(scheduleBadLichtMitte, true, 1, 0, 0, MIN30, false);
scheduleRepository.save(scheduleBadLichtMitte);
final Schedule scheduleSzeneHaus = createSchedule(true, "Dekoration", szene_haus, SchedulePropertyType.SCENE);
final Schedule scheduleSzeneHaus = createSchedule(true, "Dekoration", szene_haus);
createTime(scheduleSzeneHaus, true, 6, 0, 0, 0, 31);
createTime(scheduleSzeneHaus, true, 8, 30, 0, 0, 30);
createSunset(scheduleSzeneHaus, true, Zenith.OFFICIAL, 0, 31);
@ -127,20 +127,19 @@ public class DemoDataService {
return knxGroupReadService.getByAddress(main, mid, sub);
}
private Property createProperty(final String name, final String title, final Channel readChannel, final Channel writeChannel) {
final Property property = propertyRepository.findByName(name).orElseGet(() -> propertyRepository.save(new Property(name)));
private Property createProperty(final String name, final PropertyType type, final String title, final Channel readChannel, final Channel writeChannel) {
final Property property = propertyRepository.findByName(name).orElseGet(() -> propertyRepository.save(new Property(name, type)));
property.setTitle(title);
property.setReadChannel(readChannel);
property.setWriteChannel(writeChannel);
return property;
}
private Schedule createSchedule(final boolean enabled, final String title, final Property property, final SchedulePropertyType propertyType) {
private Schedule createSchedule(final boolean enabled, final String title, final Property property) {
final Schedule schedule = new Schedule();
schedule.setEnabled(enabled);
schedule.setTitle(title);
schedule.setProperty(property);
schedule.setPropertyType(propertyType);
return schedule;
}

View File

@ -18,6 +18,10 @@ public final class Property {
@Setter(AccessLevel.NONE)
private Long id;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private PropertyType type;
@Column(nullable = false)
private String name;
@ -34,8 +38,9 @@ public final class Property {
@ManyToOne
private Channel writeChannel;
public Property(final String name) {
public Property(final String name, final PropertyType type) {
this.name = name;
this.type = type;
}
}

View File

@ -3,10 +3,7 @@ package de.ph87.homeautomation.property;
import de.ph87.homeautomation.shared.ISearchController;
import de.ph87.homeautomation.shared.KeyValuePair;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
@ -42,4 +39,9 @@ public class PropertyController implements ISearchController {
return new KeyValuePair(propertyDto.getName(), propertyDto.getTitle());
}
@PostMapping("set/{id}/type")
public PropertyDto setPropertyType(@PathVariable final long id, @RequestBody final String propertyType) {
return propertyWriteService.set(id, Property::setType, PropertyType.valueOf(propertyType));
}
}

View File

@ -10,6 +10,8 @@ public final class PropertyDto implements Serializable {
private final long id;
private final PropertyType type;
private final String name;
private final String title;
@ -20,6 +22,7 @@ public final class PropertyDto implements Serializable {
public PropertyDto(final Property property) {
this.id = property.getId();
this.type = property.getType();
this.name = property.getName();
this.title = property.getTitle();
this.value = property.getValue();

View File

@ -34,4 +34,8 @@ public class PropertyReadService {
return propertyMapper.toDto(getByName(name));
}
public Property getById(final long id) {
return propertyRepository.findById(id).orElseThrow(RuntimeException::new);
}
}

View File

@ -13,4 +13,6 @@ public interface PropertyRepository extends CrudRepository<Property, Long> {
List<Property> findAllByNameLike(final String like);
boolean existsByName(String name);
}

View File

@ -0,0 +1,5 @@
package de.ph87.homeautomation.property;
public enum PropertyType {
SWITCH, SHUTTER, BRIGHTNESS, COLOR_TEMPERATURE, LUX, SCENE
}

View File

@ -10,12 +10,16 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
import java.util.function.BiConsumer;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class PropertyWriteService {
private static final String NAME_PREFIX = "NEU ";
private final PropertyReadService propertyReadService;
private final ChannelService channelService;
@ -24,6 +28,8 @@ public class PropertyWriteService {
private final WebSocketService webSocketService;
private final PropertyRepository propertyRepository;
public void write(final String name, final double value) {
write(propertyReadService.getByName(name), value);
}
@ -44,4 +50,29 @@ public class PropertyWriteService {
);
}
public PropertyDto create() {
final Property entry = new Property();
entry.setTitle(generateUnusedName());
return propertyMapper.toDto(propertyRepository.save(entry));
}
private String generateUnusedName() {
int index = 0;
String name = null;
while (name == null || propertyRepository.existsByName(name)) {
name = PropertyWriteService.NAME_PREFIX + ++index;
}
return name;
}
public <T> PropertyDto set(final long id, final BiConsumer<Property, T> setter, final T value) {
final Property property = propertyReadService.getById(id);
setter.accept(property, value);
return propertyMapper.toDto(property);
}
public void delete(final long id) {
propertyRepository.deleteById(id);
}
}

View File

@ -30,9 +30,6 @@ public class Schedule {
@ManyToOne
private Property property;
@Enumerated(EnumType.STRING)
private SchedulePropertyType propertyType;
@ToString.Exclude
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
private Set<ScheduleEntry> entries = new HashSet<>();

View File

@ -54,9 +54,4 @@ public class ScheduleController {
return scheduleWriteService.set(id, (schedule, v) -> schedule.setProperty(mapIfNotNull(v, propertyReadService::getByName)), propertyName);
}
@PostMapping("set/{id}/propertyType")
public ScheduleDto setPropertyType(@PathVariable final long id, @RequestBody final String propertyType) {
return scheduleWriteService.set(id, Schedule::setPropertyType, SchedulePropertyType.valueOf(propertyType));
}
}

View File

@ -1,14 +1,12 @@
package de.ph87.homeautomation.schedule;
import de.ph87.homeautomation.property.Property;
import de.ph87.homeautomation.property.PropertyDto;
import de.ph87.homeautomation.schedule.entry.ScheduleEntryDto;
import lombok.Getter;
import java.util.Set;
import java.util.stream.Collectors;
import static de.ph87.homeautomation.shared.Helpers.mapIfNotNull;
@Getter
public class ScheduleDto {
@ -18,18 +16,15 @@ public class ScheduleDto {
public final String title;
public final String propertyName;
public final SchedulePropertyType propertyType;
public final PropertyDto property;
public final Set<ScheduleEntryDto> entries;
public ScheduleDto(final Schedule schedule) {
public ScheduleDto(final Schedule schedule, final PropertyDto propertyDto) {
this.id = schedule.getId();
this.enabled = schedule.isEnabled();
this.title = schedule.getTitle();
this.propertyName = mapIfNotNull(schedule.getProperty(), Property::getName);
this.propertyType = schedule.getPropertyType();
this.property = propertyDto;
this.entries = schedule.getEntries().stream().map(ScheduleEntryDto::new).collect(Collectors.toSet());
}

View File

@ -1,18 +1,23 @@
package de.ph87.homeautomation.schedule;
import de.ph87.homeautomation.property.PropertyMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import static de.ph87.homeautomation.shared.Helpers.mapIfNotNull;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class ScheduleMapper {
private final PropertyMapper propertyMapper;
public ScheduleDto toDto(final Schedule schedule) {
return new ScheduleDto(schedule);
return new ScheduleDto(schedule, mapIfNotNull(schedule.getProperty(), propertyMapper::toDto));
}
}

View File

@ -1,5 +0,0 @@
package de.ph87.homeautomation.schedule;
public enum SchedulePropertyType {
SWITCH, PERCENT, SHUTTER, SCENE
}