Merge branch '55-users-can-add-conditions-to-automations' into 'dev'
Resolve "Users can add conditions to automations" Closes #55 See merge request sa4-2020/the-sanmarinoes/backend!133
This commit is contained in:
commit
c003bd1e87
21 changed files with 756 additions and 6 deletions
|
@ -1,6 +1,7 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.AutomationFastUpdateRequest;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.AutomationFastUpdateRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Condition;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableState;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableState;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.State;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.State;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SwitchableState;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SwitchableState;
|
||||||
|
@ -43,12 +44,32 @@ public class GsonConfig {
|
||||||
.registerSubtype(
|
.registerSubtype(
|
||||||
AutomationFastUpdateRequest.RangeTriggerDTO.class,
|
AutomationFastUpdateRequest.RangeTriggerDTO.class,
|
||||||
"rangeTrigger");
|
"rangeTrigger");
|
||||||
|
|
||||||
|
RuntimeTypeAdapterFactory<AutomationFastUpdateRequest.ConditionDTO>
|
||||||
|
runtimeTypeAdapterFactoryIII =
|
||||||
|
RuntimeTypeAdapterFactory.of(
|
||||||
|
AutomationFastUpdateRequest.ConditionDTO.class, "kind")
|
||||||
|
.registerSubtype(
|
||||||
|
AutomationFastUpdateRequest.BooleanConditionDTO.class,
|
||||||
|
"booleanCondition")
|
||||||
|
.registerSubtype(
|
||||||
|
AutomationFastUpdateRequest.RangeConditionDTO.class,
|
||||||
|
"rangeCondition")
|
||||||
|
.registerSubtype(
|
||||||
|
AutomationFastUpdateRequest.ThermostatConditionDTO.class,
|
||||||
|
"thermostatCondition");
|
||||||
|
|
||||||
builder.registerTypeAdapterFactory(runtimeTypeAdapterFactory);
|
builder.registerTypeAdapterFactory(runtimeTypeAdapterFactory);
|
||||||
builder.registerTypeAdapterFactory(runtimeTypeAdapterFactoryII);
|
builder.registerTypeAdapterFactory(runtimeTypeAdapterFactoryII);
|
||||||
|
builder.registerTypeAdapterFactory(runtimeTypeAdapterFactoryIII);
|
||||||
builder.registerTypeAdapter(
|
builder.registerTypeAdapter(
|
||||||
Trigger.class,
|
Trigger.class,
|
||||||
(JsonSerializer<Trigger<?>>)
|
(JsonSerializer<Trigger<?>>)
|
||||||
(src, typeOfSrc, context) -> context.serialize((Object) src));
|
(src, typeOfSrc, context) -> context.serialize((Object) src));
|
||||||
|
builder.registerTypeAdapter(
|
||||||
|
Condition.class,
|
||||||
|
(JsonSerializer<Condition<?>>)
|
||||||
|
(src, typeOfSrc, context) -> context.serialize((Object) src));
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -200,7 +200,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R> void initMaps(
|
private void initMaps(
|
||||||
Gson gson,
|
Gson gson,
|
||||||
Map<String, TypeAdapter<?>> labelToDelegate,
|
Map<String, TypeAdapter<?>> labelToDelegate,
|
||||||
Map<Class<?>, TypeAdapter<?>> subtypeToDelegate) {
|
Map<Class<?>, TypeAdapter<?>> subtypeToDelegate) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class AutomationController {
|
||||||
@Autowired private AutomationRepository automationRepository;
|
@Autowired private AutomationRepository automationRepository;
|
||||||
@Autowired private ScenePriorityRepository sceneRepository;
|
@Autowired private ScenePriorityRepository sceneRepository;
|
||||||
@Autowired private TriggerRepository<Trigger<?>> triggerRepository;
|
@Autowired private TriggerRepository<Trigger<?>> triggerRepository;
|
||||||
|
@Autowired private ConditionRepository<Condition<?>> conditionRepository;
|
||||||
@Autowired private UserRepository userService;
|
@Autowired private UserRepository userService;
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
|
@ -86,6 +87,7 @@ public class AutomationController {
|
||||||
|
|
||||||
triggerRepository.deleteAllByAutomationId(a.getId());
|
triggerRepository.deleteAllByAutomationId(a.getId());
|
||||||
sceneRepository.deleteAllByAutomationId(a.getId());
|
sceneRepository.deleteAllByAutomationId(a.getId());
|
||||||
|
conditionRepository.deleteAllByAutomationId(a.getId());
|
||||||
|
|
||||||
Iterable<Trigger<?>> tt =
|
Iterable<Trigger<?>> tt =
|
||||||
triggerRepository.saveAll(
|
triggerRepository.saveAll(
|
||||||
|
@ -101,6 +103,14 @@ public class AutomationController {
|
||||||
.map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel)
|
.map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
|
Iterable<Condition<?>> cc =
|
||||||
|
conditionRepository.saveAll(
|
||||||
|
req.getConditions()
|
||||||
|
.stream()
|
||||||
|
.map(AutomationFastUpdateRequest.ConditionDTO::toModel)
|
||||||
|
.map(t -> t.setAutomationId(a.getId()))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
for (final ScenePriority s : ss) {
|
for (final ScenePriority s : ss) {
|
||||||
s.setAutomationId(a.getId());
|
s.setAutomationId(a.getId());
|
||||||
|
|
||||||
|
@ -112,8 +122,10 @@ public class AutomationController {
|
||||||
|
|
||||||
a.getScenes().clear();
|
a.getScenes().clear();
|
||||||
a.getTriggers().clear();
|
a.getTriggers().clear();
|
||||||
|
a.getConditions().clear();
|
||||||
ss.forEach(t -> a.getScenes().add(t));
|
ss.forEach(t -> a.getScenes().add(t));
|
||||||
tt.forEach(t -> a.getTriggers().add(t));
|
tt.forEach(t -> a.getTriggers().add(t));
|
||||||
|
cc.forEach(t -> a.getConditions().add(t));
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.BooleanConditionSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.BooleanCondition;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.BooleanConditionRepository;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@RequestMapping("/booleanCondition")
|
||||||
|
public class BooleanConditionController {
|
||||||
|
|
||||||
|
@Autowired BooleanConditionRepository booleanConditionRepository;
|
||||||
|
|
||||||
|
@GetMapping("/{automationId}")
|
||||||
|
public List<BooleanCondition<?>> getAll(@PathVariable long automationId) {
|
||||||
|
return booleanConditionRepository.findAllByAutomationId(automationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BooleanCondition<?> save(BooleanCondition<?> newRL, BooleanConditionSaveRequest s) {
|
||||||
|
newRL.setDeviceId(s.getDeviceId());
|
||||||
|
newRL.setAutomationId(s.getAutomationId());
|
||||||
|
newRL.setOn(s.isOn());
|
||||||
|
|
||||||
|
return booleanConditionRepository.save(newRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public BooleanCondition<?> create(
|
||||||
|
@Valid @RequestBody BooleanConditionSaveRequest booleanTriggerSaveRequest) {
|
||||||
|
return save(new BooleanCondition<>(), booleanTriggerSaveRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public BooleanCondition<?> update(
|
||||||
|
@Valid @RequestBody BooleanConditionSaveRequest booleanTriggerSaveRequest)
|
||||||
|
throws NotFoundException {
|
||||||
|
return save(
|
||||||
|
booleanConditionRepository
|
||||||
|
.findById(booleanTriggerSaveRequest.getId())
|
||||||
|
.orElseThrow(NotFoundException::new),
|
||||||
|
booleanTriggerSaveRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public void delete(@PathVariable long id) {
|
||||||
|
booleanConditionRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.RangeConditionSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeCondition;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeConditionRepository;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@RequestMapping("/rangeCondition")
|
||||||
|
public class RangeConditionController {
|
||||||
|
|
||||||
|
@Autowired RangeConditionRepository rangeConditionRepository;
|
||||||
|
|
||||||
|
@GetMapping("/{automationId}")
|
||||||
|
public List<RangeCondition<?>> getAll(@PathVariable long automationId) {
|
||||||
|
return rangeConditionRepository.findAllByAutomationId(automationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RangeCondition<?> save(RangeCondition<?> newRL, RangeConditionSaveRequest s) {
|
||||||
|
newRL.setDeviceId(s.getDeviceId());
|
||||||
|
newRL.setAutomationId(s.getAutomationId());
|
||||||
|
newRL.setOperator(s.getOperator());
|
||||||
|
newRL.setRange(s.getRange());
|
||||||
|
|
||||||
|
return rangeConditionRepository.save(newRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public RangeCondition<?> create(
|
||||||
|
@Valid @RequestBody RangeConditionSaveRequest booleanTriggerSaveRequest) {
|
||||||
|
return save(new RangeCondition<>(), booleanTriggerSaveRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public RangeCondition<?> update(
|
||||||
|
@Valid @RequestBody RangeConditionSaveRequest booleanTriggerSaveRequest)
|
||||||
|
throws NotFoundException {
|
||||||
|
return save(
|
||||||
|
rangeConditionRepository
|
||||||
|
.findById(booleanTriggerSaveRequest.getId())
|
||||||
|
.orElseThrow(NotFoundException::new),
|
||||||
|
booleanTriggerSaveRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public void delete(@PathVariable long id) {
|
||||||
|
rangeConditionRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.ThermostatConditionSaveRequest;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatCondition;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatConditionRepository;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PutMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@RequestMapping("/thermostatCondition")
|
||||||
|
public class ThermostatConditionController {
|
||||||
|
|
||||||
|
@Autowired ThermostatConditionRepository thermostatConditionRepository;
|
||||||
|
|
||||||
|
@GetMapping("/{automationId}")
|
||||||
|
public List<ThermostatCondition> getAll(@PathVariable long automationId) {
|
||||||
|
return thermostatConditionRepository.findAllByAutomationId(automationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThermostatCondition save(ThermostatCondition newRL, ThermostatConditionSaveRequest s) {
|
||||||
|
newRL.setDeviceId(s.getDeviceId());
|
||||||
|
newRL.setAutomationId(s.getAutomationId());
|
||||||
|
newRL.setOperator(s.getOperator());
|
||||||
|
newRL.setMode(s.getMode());
|
||||||
|
|
||||||
|
return thermostatConditionRepository.save(newRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public ThermostatCondition create(
|
||||||
|
@Valid @RequestBody ThermostatConditionSaveRequest booleanTriggerSaveRequest) {
|
||||||
|
return save(new ThermostatCondition(), booleanTriggerSaveRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
public ThermostatCondition update(
|
||||||
|
@Valid @RequestBody ThermostatConditionSaveRequest booleanTriggerSaveRequest)
|
||||||
|
throws NotFoundException {
|
||||||
|
return save(
|
||||||
|
thermostatConditionRepository
|
||||||
|
.findById(booleanTriggerSaveRequest.getId())
|
||||||
|
.orElseThrow(NotFoundException::new),
|
||||||
|
booleanTriggerSaveRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
public void delete(@PathVariable long id) {
|
||||||
|
thermostatConditionRepository.deleteById(id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,13 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.BooleanCondition;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.BooleanTrigger;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.BooleanTrigger;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Condition;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeCondition;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeTrigger;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeTrigger;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ScenePriority;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ScenePriority;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Thermostat;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatCondition;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Trigger;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Trigger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.validation.constraints.Min;
|
import javax.validation.constraints.Min;
|
||||||
|
@ -57,8 +62,58 @@ public class AutomationFastUpdateRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract class ConditionDTO {
|
||||||
|
@NotNull public long deviceId;
|
||||||
|
|
||||||
|
public abstract Condition<?> toModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BooleanConditionDTO extends ConditionDTO {
|
||||||
|
|
||||||
|
@NotNull public boolean on;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Condition<?> toModel() {
|
||||||
|
BooleanCondition<?> t = new BooleanCondition<>();
|
||||||
|
t.setDeviceId(this.deviceId);
|
||||||
|
t.setOn(this.on);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class RangeConditionDTO extends ConditionDTO {
|
||||||
|
|
||||||
|
@NotNull RangeCondition.Operator operator;
|
||||||
|
@NotNull double range;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Condition<?> toModel() {
|
||||||
|
RangeCondition<?> t = new RangeCondition<>();
|
||||||
|
t.setDeviceId(this.deviceId);
|
||||||
|
t.setOperator(this.operator);
|
||||||
|
t.setRange(this.range);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ThermostatConditionDTO extends ConditionDTO {
|
||||||
|
|
||||||
|
@NotNull ThermostatCondition.Operator operator;
|
||||||
|
@NotNull private Thermostat.Mode mode;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Condition<?> toModel() {
|
||||||
|
ThermostatCondition t = new ThermostatCondition();
|
||||||
|
t.setDeviceId(this.deviceId);
|
||||||
|
t.setOperator(this.operator);
|
||||||
|
t.setMode(this.mode);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull private List<ScenePriorityDTO> scenes;
|
@NotNull private List<ScenePriorityDTO> scenes;
|
||||||
@NotNull private List<TriggerDTO> triggers;
|
@NotNull private List<TriggerDTO> triggers;
|
||||||
|
@NotNull private List<ConditionDTO> conditions;
|
||||||
@NotNull private long id;
|
@NotNull private long id;
|
||||||
|
|
||||||
@NotNull @NotEmpty private String name;
|
@NotNull @NotEmpty private String name;
|
||||||
|
@ -94,4 +149,12 @@ public class AutomationFastUpdateRequest {
|
||||||
public void setId(long id) {
|
public void setId(long id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ConditionDTO> getConditions() {
|
||||||
|
return conditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConditions(List<ConditionDTO> conditions) {
|
||||||
|
this.conditions = conditions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class BooleanConditionSaveRequest {
|
||||||
|
|
||||||
|
@NotNull private long id;
|
||||||
|
|
||||||
|
@NotNull private Long deviceId;
|
||||||
|
|
||||||
|
@NotNull private Long automationId;
|
||||||
|
|
||||||
|
@NotNull private boolean on;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(Long deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAutomationId() {
|
||||||
|
return automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutomationId(Long automationId) {
|
||||||
|
this.automationId = automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOn() {
|
||||||
|
return on;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOn(boolean on) {
|
||||||
|
this.on = on;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeCondition;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeCondition.Operator;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class RangeConditionSaveRequest {
|
||||||
|
|
||||||
|
@NotNull private long id;
|
||||||
|
|
||||||
|
@NotNull private Long deviceId;
|
||||||
|
|
||||||
|
@NotNull private Long automationId;
|
||||||
|
|
||||||
|
@NotNull private RangeCondition.Operator operator;
|
||||||
|
|
||||||
|
@NotNull private double range;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(Long deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAutomationId() {
|
||||||
|
return automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutomationId(Long automationId) {
|
||||||
|
this.automationId = automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operator getOperator() {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOperator(Operator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRange(double range) {
|
||||||
|
this.range = range;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Thermostat;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Thermostat.Mode;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatCondition;
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatCondition.Operator;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
public class ThermostatConditionSaveRequest {
|
||||||
|
|
||||||
|
@NotNull private long id;
|
||||||
|
|
||||||
|
@NotNull private Long deviceId;
|
||||||
|
|
||||||
|
@NotNull private Long automationId;
|
||||||
|
|
||||||
|
@NotNull private ThermostatCondition.Operator operator;
|
||||||
|
|
||||||
|
@NotNull private Thermostat.Mode mode;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(Long deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAutomationId() {
|
||||||
|
return automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutomationId(Long automationId) {
|
||||||
|
this.automationId = automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Operator getOperator() {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOperator(Operator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mode getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(Mode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,6 +33,9 @@ public class Automation {
|
||||||
@OneToMany(mappedBy = "automation", cascade = CascadeType.REMOVE)
|
@OneToMany(mappedBy = "automation", cascade = CascadeType.REMOVE)
|
||||||
private Set<ScenePriority> scenes = new HashSet<>();
|
private Set<ScenePriority> scenes = new HashSet<>();
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "automation", orphanRemoval = true, cascade = CascadeType.REMOVE)
|
||||||
|
private Set<Condition<?>> conditions = new HashSet<>();
|
||||||
|
|
||||||
@NotNull @NotEmpty private String name;
|
@NotNull @NotEmpty private String name;
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
|
@ -74,4 +77,8 @@ public class Automation {
|
||||||
public void setUserId(Long userId) {
|
public void setUserId(Long userId) {
|
||||||
this.userId = userId;
|
this.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Set<Condition<?>> getConditions() {
|
||||||
|
return conditions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,9 @@ import org.springframework.data.repository.CrudRepository;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
public interface AutomationRepository extends CrudRepository<Automation, Long> {
|
public interface AutomationRepository extends CrudRepository<Automation, Long> {
|
||||||
@EntityGraph(attributePaths = {"scenes", "triggers"})
|
@EntityGraph(attributePaths = {"scenes", "triggers", "conditions"})
|
||||||
List<Automation> findAllByUserId(@Param("userId") long userId);
|
List<Automation> findAllByUserId(@Param("userId") long userId);
|
||||||
|
|
||||||
@EntityGraph(attributePaths = {"scenes", "triggers"})
|
@EntityGraph(attributePaths = {"scenes", "triggers", "conditions"})
|
||||||
Optional<Automation> findByIdAndUserId(@Param("id") long id, @Param("userId") long userId);
|
Optional<Automation> findByIdAndUserId(@Param("id") long id, @Param("userId") long userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class BooleanCondition<D extends Device & BooleanTriggerable>
|
||||||
|
extends Condition<D> { // TODO add interface to type constraints
|
||||||
|
|
||||||
|
@Column(name = "switchable_on")
|
||||||
|
private boolean on;
|
||||||
|
|
||||||
|
public BooleanCondition() {
|
||||||
|
super("booleanCondition");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOn() {
|
||||||
|
return on;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOn(boolean on) {
|
||||||
|
this.on = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean check(boolean on) {
|
||||||
|
return this.on == on;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean triggered() {
|
||||||
|
return this.getDevice().readTriggerState() == isOn();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface BooleanConditionRepository
|
||||||
|
extends ConditionRepository<BooleanCondition<? extends Device>> {
|
||||||
|
|
||||||
|
List<BooleanCondition<?>> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Transient;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public abstract class Condition<D extends Device> {
|
||||||
|
|
||||||
|
@Transient private String kind;
|
||||||
|
|
||||||
|
protected Condition(String kind) {
|
||||||
|
this.kind = kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKind() {
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
@Column(name = "id", updatable = false, nullable = false, unique = true)
|
||||||
|
@ApiModelProperty(hidden = true)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@ManyToOne(targetEntity = Device.class)
|
||||||
|
@JoinColumn(name = "device_id", updatable = false, insertable = false)
|
||||||
|
@GsonExclude
|
||||||
|
private D device;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device this condition belongs to, as a foreign key id. To use when updating and inserting
|
||||||
|
* from a REST call.
|
||||||
|
*/
|
||||||
|
@Column(name = "device_id", nullable = false)
|
||||||
|
@NotNull
|
||||||
|
private Long deviceId;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "automation_id", updatable = false, insertable = false)
|
||||||
|
@GsonExclude
|
||||||
|
private Automation automation;
|
||||||
|
|
||||||
|
@Column(name = "automation_id", nullable = false)
|
||||||
|
@NotNull
|
||||||
|
private Long automationId;
|
||||||
|
|
||||||
|
public abstract boolean triggered();
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public D getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevice(D device) {
|
||||||
|
this.device = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(Long deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Automation getAutomation() {
|
||||||
|
return automation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutomation(Automation automation) {
|
||||||
|
this.automation = automation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getAutomationId() {
|
||||||
|
return automationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Condition<D> setAutomationId(Long automationId) {
|
||||||
|
this.automationId = automationId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface ConditionRepository<T extends Condition<?>> extends CrudRepository<T, Long> {
|
||||||
|
|
||||||
|
List<T> findAllByDeviceId(@Param("deviceId") long deviceId);
|
||||||
|
|
||||||
|
List<T> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
void deleteAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RangeTrigger.Operator;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class RangeCondition<D extends Device & RangeTriggerable> extends Condition<D> {
|
||||||
|
|
||||||
|
public RangeCondition() {
|
||||||
|
super("booleanCondition");
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Operator {
|
||||||
|
@SerializedName("EQUAL")
|
||||||
|
EQUAL,
|
||||||
|
@SerializedName("LESS")
|
||||||
|
LESS,
|
||||||
|
@SerializedName("GREATER")
|
||||||
|
GREATER,
|
||||||
|
@SerializedName("LESS_EQUAL")
|
||||||
|
LESS_EQUAL,
|
||||||
|
@SerializedName("GREATER_EQUAL")
|
||||||
|
GREATER_EQUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private RangeCondition.Operator operator;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Column(nullable = false)
|
||||||
|
private double range;
|
||||||
|
|
||||||
|
public RangeCondition.Operator getOperator() {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOperator(RangeCondition.Operator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRange(Double range) {
|
||||||
|
this.range = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean triggered() {
|
||||||
|
double value = getDevice().readTriggerState();
|
||||||
|
switch (operator) {
|
||||||
|
case EQUAL:
|
||||||
|
return value == range;
|
||||||
|
case LESS:
|
||||||
|
return value < range;
|
||||||
|
case GREATER:
|
||||||
|
return value > range;
|
||||||
|
case GREATER_EQUAL:
|
||||||
|
return value >= range;
|
||||||
|
case LESS_EQUAL:
|
||||||
|
return value <= range;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface RangeConditionRepository
|
||||||
|
extends ConditionRepository<RangeCondition<? extends Device>> {
|
||||||
|
|
||||||
|
List<RangeCondition<?>> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ThermostatCondition extends Condition<Thermostat> {
|
||||||
|
|
||||||
|
public ThermostatCondition() {
|
||||||
|
super("thermostatCondition");
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Operator {
|
||||||
|
@SerializedName("EQUAL")
|
||||||
|
EQUAL,
|
||||||
|
@SerializedName("NOTEQUAL")
|
||||||
|
NOTEQUAL,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private ThermostatCondition.Operator operator;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private Thermostat.Mode mode;
|
||||||
|
|
||||||
|
public Operator getOperator() {
|
||||||
|
return operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOperator(Operator operator) {
|
||||||
|
this.operator = operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Thermostat.Mode getMode() {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMode(Thermostat.Mode mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean triggered() {
|
||||||
|
switch (operator) {
|
||||||
|
case EQUAL:
|
||||||
|
return getDevice().getMode() == mode;
|
||||||
|
case NOTEQUAL:
|
||||||
|
return getDevice().getMode() != mode;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
|
public interface ThermostatConditionRepository extends ConditionRepository<ThermostatCondition> {
|
||||||
|
|
||||||
|
List<ThermostatCondition> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ public class DeviceService {
|
||||||
private final EagerUserRepository userRepository;
|
private final EagerUserRepository userRepository;
|
||||||
private final DevicePopulationService devicePopulationService;
|
private final DevicePopulationService devicePopulationService;
|
||||||
private final DevicePropagationService devicePropagationService;
|
private final DevicePropagationService devicePropagationService;
|
||||||
|
private final ConditionRepository<Condition<?>> conditionRepository;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DeviceService(
|
public DeviceService(
|
||||||
|
@ -31,7 +32,8 @@ public class DeviceService {
|
||||||
AutomationService automationService,
|
AutomationService automationService,
|
||||||
EagerUserRepository userRepository,
|
EagerUserRepository userRepository,
|
||||||
DevicePopulationService devicePopulationService,
|
DevicePopulationService devicePopulationService,
|
||||||
DevicePropagationService devicePropagationService) {
|
DevicePropagationService devicePropagationService,
|
||||||
|
ConditionRepository<Condition<?>> conditionRepository) {
|
||||||
this.deviceRepository = deviceRepository;
|
this.deviceRepository = deviceRepository;
|
||||||
this.sceneService = sceneService;
|
this.sceneService = sceneService;
|
||||||
this.roomRepository = roomRepository;
|
this.roomRepository = roomRepository;
|
||||||
|
@ -39,6 +41,7 @@ public class DeviceService {
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.devicePopulationService = devicePopulationService;
|
this.devicePopulationService = devicePopulationService;
|
||||||
this.devicePropagationService = devicePropagationService;
|
this.devicePropagationService = devicePropagationService;
|
||||||
|
this.conditionRepository = conditionRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void throwIfRoomNotOwned(Long roomId, String username) throws NotFoundException {
|
public void throwIfRoomNotOwned(Long roomId, String username) throws NotFoundException {
|
||||||
|
@ -52,14 +55,20 @@ public class DeviceService {
|
||||||
private void triggerTriggers(Device device, final String username) {
|
private void triggerTriggers(Device device, final String username) {
|
||||||
|
|
||||||
final long deviceId = device.getId();
|
final long deviceId = device.getId();
|
||||||
|
final List<Trigger<Device>> triggers = automationService.findTriggersByDeviceId(deviceId);
|
||||||
List<Trigger<Device>> triggers = automationService.findTriggersByDeviceId(deviceId);
|
|
||||||
|
|
||||||
triggers.stream()
|
triggers.stream()
|
||||||
.filter(Trigger::triggered)
|
.filter(Trigger::triggered)
|
||||||
.map(Trigger::getAutomationId)
|
.map(Trigger::getAutomationId)
|
||||||
.map(automationService::findByVerifiedId)
|
.map(automationService::findByVerifiedId)
|
||||||
.distinct()
|
.distinct()
|
||||||
|
.filter(
|
||||||
|
a -> {
|
||||||
|
final List<Condition<?>> conditions =
|
||||||
|
conditionRepository.findAllByAutomationId(a.getId());
|
||||||
|
if (conditions.size() == 0) return true;
|
||||||
|
return conditions.stream().allMatch(Condition::triggered);
|
||||||
|
})
|
||||||
.map(Automation::getScenes)
|
.map(Automation::getScenes)
|
||||||
.flatMap(Collection::stream)
|
.flatMap(Collection::stream)
|
||||||
.distinct()
|
.distinct()
|
||||||
|
@ -76,6 +85,7 @@ public class DeviceService {
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
final User currentUser = userRepository.findByUsername(guestUsername);
|
final User currentUser = userRepository.findByUsername(guestUsername);
|
||||||
final User host = userRepository.findById(hostId).orElseThrow(NotFoundException::new);
|
final User host = userRepository.findById(hostId).orElseThrow(NotFoundException::new);
|
||||||
|
|
||||||
if (!host.getGuests().contains(currentUser)) throw new NotFoundException();
|
if (!host.getGuests().contains(currentUser)) throw new NotFoundException();
|
||||||
devicePropagationService.renameIfDuplicate(device, host.getUsername());
|
devicePropagationService.renameIfDuplicate(device, host.getUsername());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue