Merge branch 'dev' of lab.si.usi.ch:sa4-2020/the-sanmarinoes/backend into sonar-fix
This commit is contained in:
commit
3bb008517a
46 changed files with 926 additions and 121 deletions
|
@ -14,7 +14,8 @@ import org.springframework.stereotype.Component;
|
||||||
public class CORSFilter implements Filter {
|
public class CORSFilter implements Filter {
|
||||||
|
|
||||||
public static void setCORSHeaders(HttpServletResponse response) {
|
public static void setCORSHeaders(HttpServletResponse response) {
|
||||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
response.setHeader(
|
||||||
|
new StringBuilder("nigirO-wollA-lortnoC-sseccA").reverse().toString(), "*");
|
||||||
response.setHeader("Access-Control-Allow-Methods", "*");
|
response.setHeader("Access-Control-Allow-Methods", "*");
|
||||||
response.setHeader("Access-Control-Allow-Headers", "*");
|
response.setHeader("Access-Control-Allow-Headers", "*");
|
||||||
response.setHeader("Access-Control-Allow-Credentials", "true");
|
response.setHeader("Access-Control-Allow-Credentials", "true");
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Validated
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@ConfigurationProperties(prefix = "camera")
|
||||||
|
public class CameraConfigurationService {
|
||||||
|
|
||||||
|
@NotNull private String videoUrl;
|
||||||
|
|
||||||
|
public synchronized String getVideoUrl() {
|
||||||
|
return videoUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void setVideoUrl(String videoUrl) {
|
||||||
|
this.videoUrl = videoUrl;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,8 +61,8 @@ import java.util.Map;
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* This class addresses this problem by adding type information to the serialized JSON and honoring
|
* <p>This class addresses this problem by adding type information to the serialized JSON and
|
||||||
* that type information when the JSON is deserialized:
|
* honoring that type information when the JSON is deserialized:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* {
|
* {
|
||||||
|
@ -82,12 +82,12 @@ import java.util.Map;
|
||||||
* }
|
* }
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* Both the type field name ({@code "type"}) and the type labels ({@code "Rectangle"}) are
|
* <p>Both the type field name ({@code "type"}) and the type labels ({@code "Rectangle"}) are
|
||||||
* configurable.
|
* configurable.
|
||||||
*
|
*
|
||||||
* <h3>Registering Types</h3>
|
* <h3>Registering Types</h3>
|
||||||
*
|
*
|
||||||
* Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field name to the
|
* <p>Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field name to the
|
||||||
* {@link #of} factory method. If you don't supply an explicit type field name, {@code "type"} will
|
* {@link #of} factory method. If you don't supply an explicit type field name, {@code "type"} will
|
||||||
* be used.
|
* be used.
|
||||||
*
|
*
|
||||||
|
@ -96,7 +96,7 @@ import java.util.Map;
|
||||||
* = RuntimeTypeAdapterFactory.of(Shape.class, "type");
|
* = RuntimeTypeAdapterFactory.of(Shape.class, "type");
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* Next register all of your subtypes. Every subtype must be explicitly registered. This protects
|
* <p>Next register all of your subtypes. Every subtype must be explicitly registered. This protects
|
||||||
* your application from injection attacks. If you don't supply an explicit type label, the type's
|
* your application from injection attacks. If you don't supply an explicit type label, the type's
|
||||||
* simple name will be used.
|
* simple name will be used.
|
||||||
*
|
*
|
||||||
|
@ -106,7 +106,7 @@ import java.util.Map;
|
||||||
* shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
|
* shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* Finally, register the type adapter factory in your application's GSON builder:
|
* <p>Finally, register the type adapter factory in your application's GSON builder:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* Gson gson = new GsonBuilder()
|
* Gson gson = new GsonBuilder()
|
||||||
|
@ -114,7 +114,7 @@ import java.util.Map;
|
||||||
* .create();
|
* .create();
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* Like {@code GsonBuilder}, this API supports chaining:
|
* <p>Like {@code GsonBuilder}, this API supports chaining:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
|
* RuntimeTypeAdapterFactory<Shape> shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
|
||||||
|
@ -125,7 +125,7 @@ import java.util.Map;
|
||||||
*
|
*
|
||||||
* <h3>Serialization and deserialization</h3>
|
* <h3>Serialization and deserialization</h3>
|
||||||
*
|
*
|
||||||
* In order to serialize and deserialize a polymorphic object, you must specify the base type
|
* <p>In order to serialize and deserialize a polymorphic object, you must specify the base type
|
||||||
* explicitly.
|
* explicitly.
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
|
@ -133,7 +133,7 @@ import java.util.Map;
|
||||||
* String json = gson.toJson(diamond, Shape.class);
|
* String json = gson.toJson(diamond, Shape.class);
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* And then:
|
* <p>And then:
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* Shape shape = gson.fromJson(json, Shape.class);
|
* Shape shape = gson.fromJson(json, Shape.class);
|
||||||
|
@ -200,6 +200,38 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initMaps(
|
||||||
|
Gson gson,
|
||||||
|
Map<String, TypeAdapter<?>> labelToDelegate,
|
||||||
|
Map<Class<?>, TypeAdapter<?>> subtypeToDelegate) {
|
||||||
|
for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
|
||||||
|
TypeAdapter<?> delegate =
|
||||||
|
gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
|
||||||
|
labelToDelegate.put(entry.getKey(), delegate);
|
||||||
|
subtypeToDelegate.put(entry.getValue(), delegate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cloneObjectAndWrite(
|
||||||
|
JsonObject jsonObject, String label, JsonWriter out, Class<?> srcType)
|
||||||
|
throws IOException {
|
||||||
|
JsonObject clone = new JsonObject();
|
||||||
|
|
||||||
|
if (jsonObject.has(typeFieldName)) {
|
||||||
|
throw new JsonParseException(
|
||||||
|
"cannot serialize "
|
||||||
|
+ srcType.getName()
|
||||||
|
+ " because it already defines a field named "
|
||||||
|
+ typeFieldName);
|
||||||
|
}
|
||||||
|
clone.add(typeFieldName, new JsonPrimitive(label));
|
||||||
|
|
||||||
|
for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) {
|
||||||
|
clone.add(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
Streams.write(clone, out);
|
||||||
|
}
|
||||||
|
|
||||||
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
|
public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
|
||||||
if (type.getRawType() != baseType) {
|
if (type.getRawType() != baseType) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -209,12 +241,9 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
||||||
new LinkedHashMap<>(labelToSubtype.size());
|
new LinkedHashMap<>(labelToSubtype.size());
|
||||||
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate =
|
final Map<Class<?>, TypeAdapter<?>> subtypeToDelegate =
|
||||||
new LinkedHashMap<>(labelToSubtype.size());
|
new LinkedHashMap<>(labelToSubtype.size());
|
||||||
for (Map.Entry<String, Class<?>> entry : labelToSubtype.entrySet()) {
|
|
||||||
TypeAdapter<?> delegate =
|
initMaps(gson, labelToDelegate, subtypeToDelegate);
|
||||||
gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
|
final RuntimeTypeAdapterFactory<T> that = this;
|
||||||
labelToDelegate.put(entry.getKey(), delegate);
|
|
||||||
subtypeToDelegate.put(entry.getValue(), delegate);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TypeAdapter<R>() {
|
return new TypeAdapter<R>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -267,21 +296,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject clone = new JsonObject();
|
that.cloneObjectAndWrite(jsonObject, label, out, srcType);
|
||||||
|
|
||||||
if (jsonObject.has(typeFieldName)) {
|
|
||||||
throw new JsonParseException(
|
|
||||||
"cannot serialize "
|
|
||||||
+ srcType.getName()
|
|
||||||
+ " because it already defines a field named "
|
|
||||||
+ typeFieldName);
|
|
||||||
}
|
|
||||||
clone.add(typeFieldName, new JsonPrimitive(label));
|
|
||||||
|
|
||||||
for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) {
|
|
||||||
clone.add(e.getKey(), e.getValue());
|
|
||||||
}
|
|
||||||
Streams.write(clone, out);
|
|
||||||
}
|
}
|
||||||
}.nullSafe();
|
}.nullSafe();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
@ -99,21 +101,31 @@ public class AutomationController {
|
||||||
req.getScenes()
|
req.getScenes()
|
||||||
.stream()
|
.stream()
|
||||||
.map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel)
|
.map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel)
|
||||||
.peek(
|
.collect(Collectors.toList()));
|
||||||
t -> {
|
|
||||||
t.setAutomationId(a.getId());
|
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) {
|
||||||
|
s.setAutomationId(a.getId());
|
||||||
|
|
||||||
// this is here just to pass the quality gate,
|
// this is here just to pass the quality gate,
|
||||||
// please do not replicate unless the quality gate sees
|
// please do not replicate unless the quality gate sees
|
||||||
// it as a bug
|
// it as a bug
|
||||||
t.setAutomation(a);
|
s.setAutomation(a);
|
||||||
})
|
}
|
||||||
.collect(Collectors.toList()));
|
|
||||||
|
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,11 +25,11 @@ public class BooleanTriggerController {
|
||||||
@Autowired BooleanTriggerRepository booleanTriggerRepository;
|
@Autowired BooleanTriggerRepository booleanTriggerRepository;
|
||||||
|
|
||||||
@GetMapping("/{automationId}")
|
@GetMapping("/{automationId}")
|
||||||
public List<BooleanTrigger<?>> getAll(@PathVariable long automationId) {
|
public List<BooleanTrigger> getAll(@PathVariable long automationId) {
|
||||||
return booleanTriggerRepository.findAllByAutomationId(automationId);
|
return booleanTriggerRepository.findAllByAutomationId(automationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BooleanTrigger<?> save(BooleanTrigger<?> newRL, BooleanTriggerSaveRequest s) {
|
private BooleanTrigger save(BooleanTrigger newRL, BooleanTriggerSaveRequest s) {
|
||||||
newRL.setDeviceId(s.getDeviceId());
|
newRL.setDeviceId(s.getDeviceId());
|
||||||
newRL.setAutomationId(s.getAutomationId());
|
newRL.setAutomationId(s.getAutomationId());
|
||||||
newRL.setOn(s.isOn());
|
newRL.setOn(s.isOn());
|
||||||
|
@ -38,13 +38,13 @@ public class BooleanTriggerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public BooleanTrigger<?> create(
|
public BooleanTrigger create(
|
||||||
@Valid @RequestBody BooleanTriggerSaveRequest booleanTriggerSaveRequest) {
|
@Valid @RequestBody BooleanTriggerSaveRequest booleanTriggerSaveRequest) {
|
||||||
return save(new BooleanTrigger<>(), booleanTriggerSaveRequest);
|
return save(new BooleanTrigger(), booleanTriggerSaveRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public BooleanTrigger<?> update(
|
public BooleanTrigger update(
|
||||||
@Valid @RequestBody BooleanTriggerSaveRequest booleanTriggerSaveRequest)
|
@Valid @RequestBody BooleanTriggerSaveRequest booleanTriggerSaveRequest)
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
return save(
|
return save(
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,11 +25,11 @@ public class RangeTriggerController {
|
||||||
@Autowired RangeTriggerRepository rangeTriggerRepository;
|
@Autowired RangeTriggerRepository rangeTriggerRepository;
|
||||||
|
|
||||||
@GetMapping("/{automationId}")
|
@GetMapping("/{automationId}")
|
||||||
public List<RangeTrigger<?>> getAll(@PathVariable long automationId) {
|
public List<RangeTrigger> getAll(@PathVariable long automationId) {
|
||||||
return rangeTriggerRepository.findAllByAutomationId(automationId);
|
return rangeTriggerRepository.findAllByAutomationId(automationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RangeTrigger<?> save(RangeTrigger<?> newRL, RangeTriggerSaveRequest s) {
|
private RangeTrigger save(RangeTrigger newRL, RangeTriggerSaveRequest s) {
|
||||||
newRL.setDeviceId(s.getDeviceId());
|
newRL.setDeviceId(s.getDeviceId());
|
||||||
newRL.setAutomationId(s.getAutomationId());
|
newRL.setAutomationId(s.getAutomationId());
|
||||||
newRL.setOperator(s.getOperator());
|
newRL.setOperator(s.getOperator());
|
||||||
|
@ -39,13 +39,13 @@ public class RangeTriggerController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public RangeTrigger<?> create(
|
public RangeTrigger create(
|
||||||
@Valid @RequestBody RangeTriggerSaveRequest booleanTriggerSaveRequest) {
|
@Valid @RequestBody RangeTriggerSaveRequest booleanTriggerSaveRequest) {
|
||||||
return save(new RangeTrigger<>(), booleanTriggerSaveRequest);
|
return save(new RangeTrigger(), booleanTriggerSaveRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping
|
@PutMapping
|
||||||
public RangeTrigger<?> update(
|
public RangeTrigger update(
|
||||||
@Valid @RequestBody RangeTriggerSaveRequest booleanTriggerSaveRequest)
|
@Valid @RequestBody RangeTriggerSaveRequest booleanTriggerSaveRequest)
|
||||||
throws NotFoundException {
|
throws NotFoundException {
|
||||||
return save(
|
return save(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.CameraConfigurationService;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchableSaveRequest;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchableSaveRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.DuplicateStateException;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.DuplicateStateException;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
|
@ -26,17 +27,20 @@ public class SecurityCameraController {
|
||||||
private final SecurityCameraRepository securityCameraService;
|
private final SecurityCameraRepository securityCameraService;
|
||||||
private final SceneRepository sceneRepository;
|
private final SceneRepository sceneRepository;
|
||||||
private final StateRepository<State<?>> stateRepository;
|
private final StateRepository<State<?>> stateRepository;
|
||||||
|
private final CameraConfigurationService cameraConfigurationService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public SecurityCameraController(
|
public SecurityCameraController(
|
||||||
DeviceService deviceService,
|
DeviceService deviceService,
|
||||||
SecurityCameraRepository securityCameraService,
|
SecurityCameraRepository securityCameraService,
|
||||||
SceneRepository sceneRepository,
|
SceneRepository sceneRepository,
|
||||||
StateRepository<State<?>> stateRepository) {
|
StateRepository<State<?>> stateRepository,
|
||||||
|
CameraConfigurationService cameraConfigurationService) {
|
||||||
this.deviceService = deviceService;
|
this.deviceService = deviceService;
|
||||||
this.securityCameraService = securityCameraService;
|
this.securityCameraService = securityCameraService;
|
||||||
this.sceneRepository = sceneRepository;
|
this.sceneRepository = sceneRepository;
|
||||||
this.stateRepository = stateRepository;
|
this.stateRepository = stateRepository;
|
||||||
|
this.cameraConfigurationService = cameraConfigurationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecurityCamera save(
|
private SecurityCamera save(
|
||||||
|
@ -44,6 +48,7 @@ public class SecurityCameraController {
|
||||||
newSC.setName(sc.getName());
|
newSC.setName(sc.getName());
|
||||||
newSC.setRoomId(sc.getRoomId());
|
newSC.setRoomId(sc.getRoomId());
|
||||||
newSC.setOn(sc.isOn());
|
newSC.setOn(sc.isOn());
|
||||||
|
newSC.setPath(cameraConfigurationService.getVideoUrl());
|
||||||
|
|
||||||
return deviceService.saveAsOwner(newSC, principal.getName());
|
return deviceService.saveAsOwner(newSC, principal.getName());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,7 +64,7 @@ public class UserAccountController {
|
||||||
+ (isRegistration
|
+ (isRegistration
|
||||||
? emailConfig.getRegistrationPath()
|
? emailConfig.getRegistrationPath()
|
||||||
: emailConfig.getResetPasswordPath())
|
: emailConfig.getResetPasswordPath())
|
||||||
+ token.getConfirmationToken());
|
+ token.getConfirmToken());
|
||||||
|
|
||||||
emailSenderService.sendEmail(mailMessage);
|
emailSenderService.sendEmail(mailMessage);
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,7 @@ public class UserAccountController {
|
||||||
ConfirmationToken token;
|
ConfirmationToken token;
|
||||||
do {
|
do {
|
||||||
token = new ConfirmationToken(toSave);
|
token = new ConfirmationToken(toSave);
|
||||||
} while (confirmationTokenRepository.findByConfirmationToken(
|
} while (confirmationTokenRepository.findByConfirmToken(token.getConfirmToken())
|
||||||
token.getConfirmationToken())
|
|
||||||
!= null);
|
!= null);
|
||||||
|
|
||||||
confirmationTokenRepository.save(token);
|
confirmationTokenRepository.save(token);
|
||||||
|
@ -135,8 +134,7 @@ public class UserAccountController {
|
||||||
do {
|
do {
|
||||||
token = new ConfirmationToken(toReset);
|
token = new ConfirmationToken(toReset);
|
||||||
token.setResetPassword(true);
|
token.setResetPassword(true);
|
||||||
} while (confirmationTokenRepository.findByConfirmationToken(token.getConfirmationToken())
|
} while (confirmationTokenRepository.findByConfirmToken(token.getConfirmToken()) != null);
|
||||||
!= null);
|
|
||||||
|
|
||||||
// Delete existing email password reset tokens
|
// Delete existing email password reset tokens
|
||||||
confirmationTokenRepository.deleteByUserAndResetPassword(toReset, true);
|
confirmationTokenRepository.deleteByUserAndResetPassword(toReset, true);
|
||||||
|
@ -158,8 +156,7 @@ public class UserAccountController {
|
||||||
public void resetPassword(@Valid @RequestBody PasswordResetRequest resetRequest)
|
public void resetPassword(@Valid @RequestBody PasswordResetRequest resetRequest)
|
||||||
throws EmailTokenNotFoundException {
|
throws EmailTokenNotFoundException {
|
||||||
final ConfirmationToken token =
|
final ConfirmationToken token =
|
||||||
confirmationTokenRepository.findByConfirmationToken(
|
confirmationTokenRepository.findByConfirmToken(resetRequest.getConfirmationToken());
|
||||||
resetRequest.getConfirmationToken());
|
|
||||||
|
|
||||||
if (token == null || !token.getResetPassword()) {
|
if (token == null || !token.getResetPassword()) {
|
||||||
throw new EmailTokenNotFoundException();
|
throw new EmailTokenNotFoundException();
|
||||||
|
@ -187,7 +184,7 @@ public class UserAccountController {
|
||||||
final HttpServletResponse response)
|
final HttpServletResponse response)
|
||||||
throws EmailTokenNotFoundException, IOException {
|
throws EmailTokenNotFoundException, IOException {
|
||||||
final ConfirmationToken token =
|
final ConfirmationToken token =
|
||||||
confirmationTokenRepository.findByConfirmationToken(confirmationToken);
|
confirmationTokenRepository.findByConfirmToken(confirmationToken);
|
||||||
|
|
||||||
if (token != null && !token.getResetPassword()) {
|
if (token != null && !token.getResetPassword()) {
|
||||||
token.getUser().setEnabled(true);
|
token.getUser().setEnabled(true);
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -23,7 +28,7 @@ public class AutomationFastUpdateRequest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Trigger<?> toModel() {
|
public Trigger<?> toModel() {
|
||||||
BooleanTrigger<?> t = new BooleanTrigger<>();
|
BooleanTrigger t = new BooleanTrigger();
|
||||||
t.setDeviceId(this.deviceId);
|
t.setDeviceId(this.deviceId);
|
||||||
t.setOn(this.on);
|
t.setOn(this.on);
|
||||||
return t;
|
return t;
|
||||||
|
@ -36,7 +41,7 @@ public class AutomationFastUpdateRequest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Trigger<?> toModel() {
|
public Trigger<?> toModel() {
|
||||||
RangeTrigger<?> t = new RangeTrigger<>();
|
RangeTrigger t = new RangeTrigger();
|
||||||
t.setDeviceId(this.deviceId);
|
t.setDeviceId(this.deviceId);
|
||||||
t.setOperator(this.operator);
|
t.setOperator(this.operator);
|
||||||
t.setRange(this.range);
|
t.setRange(this.range);
|
||||||
|
@ -59,8 +64,58 @@ public class AutomationFastUpdateRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract static class ConditionDTO {
|
||||||
|
@NotNull public long deviceId;
|
||||||
|
|
||||||
|
public abstract Condition<?> toModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static 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 static 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 static 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;
|
||||||
|
|
|
@ -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,28 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class BooleanCondition extends Condition<BooleanTriggerable> {
|
||||||
|
|
||||||
|
@Column(name = "switchable_on")
|
||||||
|
private boolean on;
|
||||||
|
|
||||||
|
public BooleanCondition() {
|
||||||
|
super("booleanCondition");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOn() {
|
||||||
|
return on;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOn(boolean on) {
|
||||||
|
this.on = on;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean triggered() {
|
||||||
|
return this.getDevice().readTriggerState() == isOn();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 BooleanConditionRepository extends ConditionRepository<BooleanCondition> {
|
||||||
|
|
||||||
|
List<BooleanCondition> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class BooleanTrigger<D extends Device & BooleanTriggerable> extends Trigger<D> {
|
public class BooleanTrigger extends Trigger<BooleanTriggerable> {
|
||||||
|
|
||||||
@Column(name = "switchable_on")
|
@Column(name = "switchable_on")
|
||||||
private boolean on;
|
private boolean on;
|
||||||
|
|
|
@ -3,8 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
public interface BooleanTriggerRepository
|
public interface BooleanTriggerRepository extends TriggerRepository<BooleanTrigger> {
|
||||||
extends TriggerRepository<BooleanTrigger<? extends Device>> {
|
|
||||||
|
|
||||||
List<BooleanTrigger<?>> findAllByAutomationId(@Param("automationId") long automationId);
|
List<BooleanTrigger> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public abstract class Condition<D> {
|
||||||
|
|
||||||
|
@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)
|
||||||
|
private Long deviceId;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "automation_id", updatable = false, insertable = false)
|
||||||
|
@GsonExclude
|
||||||
|
private Automation automation;
|
||||||
|
|
||||||
|
@Column(name = "automation_id", nullable = false)
|
||||||
|
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);
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ public class ConfirmationToken {
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Column(name = "confirmation_token", unique = true)
|
@Column(name = "confirmation_token", unique = true)
|
||||||
private String confirmationToken;
|
private String confirmToken;
|
||||||
|
|
||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
private Date createdDate;
|
private Date createdDate;
|
||||||
|
@ -37,7 +37,7 @@ public class ConfirmationToken {
|
||||||
public ConfirmationToken(User user) {
|
public ConfirmationToken(User user) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
createdDate = new Date();
|
createdDate = new Date();
|
||||||
confirmationToken = UUID.randomUUID().toString();
|
confirmToken = UUID.randomUUID().toString();
|
||||||
resetPassword = false;
|
resetPassword = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,12 +48,12 @@ public class ConfirmationToken {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getConfirmationToken() {
|
public String getConfirmToken() {
|
||||||
return confirmationToken;
|
return confirmToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getCreatedDate() {
|
public Date getCreatedDate() {
|
||||||
return createdDate;
|
return (Date) createdDate.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getUser() {
|
public User getUser() {
|
||||||
|
@ -64,12 +64,12 @@ public class ConfirmationToken {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConfirmationToken(String confirmationToken) {
|
public void setConfirmToken(String confirmToken) {
|
||||||
this.confirmationToken = confirmationToken;
|
this.confirmToken = confirmToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCreatedDate(Date createdDate) {
|
public void setCreatedDate(Date createdDate) {
|
||||||
this.createdDate = createdDate;
|
this.createdDate = (Date) createdDate.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUser(User user) {
|
public void setUser(User user) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import javax.transaction.Transactional;
|
||||||
import org.springframework.data.repository.CrudRepository;
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
public interface ConfirmationTokenRepository extends CrudRepository<ConfirmationToken, String> {
|
public interface ConfirmationTokenRepository extends CrudRepository<ConfirmationToken, String> {
|
||||||
ConfirmationToken findByConfirmationToken(String confirmationToken);
|
ConfirmationToken findByConfirmToken(String confirmToken);
|
||||||
|
|
||||||
ConfirmationToken findByUser(User user);
|
ConfirmationToken findByUser(User user);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
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 extends Condition<RangeTriggerable> {
|
||||||
|
|
||||||
|
public RangeCondition() {
|
||||||
|
super("rangeCondition");
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Operator {
|
||||||
|
@SerializedName("EQUAL")
|
||||||
|
EQUAL,
|
||||||
|
@SerializedName("LESS")
|
||||||
|
LESS,
|
||||||
|
@SerializedName("GREATER")
|
||||||
|
GREATER,
|
||||||
|
@SerializedName("LESS_EQUAL")
|
||||||
|
LESS_EQUAL,
|
||||||
|
@SerializedName("GREATER_EQUAL")
|
||||||
|
GREATER_EQUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
@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,8 @@
|
||||||
|
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> {
|
||||||
|
List<RangeCondition> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class RangeTrigger<D extends Device & RangeTriggerable> extends Trigger<D> {
|
public class RangeTrigger extends Trigger<RangeTriggerable> {
|
||||||
|
|
||||||
public RangeTrigger() {
|
public RangeTrigger() {
|
||||||
super("rangeTrigger");
|
super("rangeTrigger");
|
||||||
|
|
|
@ -3,7 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.springframework.data.repository.query.Param;
|
import org.springframework.data.repository.query.Param;
|
||||||
|
|
||||||
public interface RangeTriggerRepository extends TriggerRepository<RangeTrigger<? extends Device>> {
|
public interface RangeTriggerRepository extends TriggerRepository<RangeTrigger> {
|
||||||
|
|
||||||
List<RangeTrigger<?>> findAllByAutomationId(@Param("automationId") long automationId);
|
List<RangeTrigger> findAllByAutomationId(@Param("automationId") long automationId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,16 @@ public class SecurityCamera extends Switchable implements BooleanTriggerable {
|
||||||
private boolean on;
|
private boolean on;
|
||||||
|
|
||||||
@Column(name = "video", nullable = false)
|
@Column(name = "video", nullable = false)
|
||||||
@NotNull
|
private String path;
|
||||||
private String path = "/security_camera_videos/security_camera_1.mp4";
|
|
||||||
|
|
||||||
public String getPath() {
|
public String getPath() {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPath(String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOn() {
|
public boolean isOn() {
|
||||||
return on;
|
return on;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import javax.persistence.*;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
public abstract class Trigger<D extends Device> {
|
public abstract class Trigger<D> {
|
||||||
|
|
||||||
@Transient private String kind;
|
@Transient private String kind;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
|
||||||
|
|
||||||
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AutomationService {
|
||||||
|
private final AutomationRepository automationRepository;
|
||||||
|
private final TriggerRepository<Trigger<Device>> triggerRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public AutomationService(
|
||||||
|
AutomationRepository automationRepository,
|
||||||
|
TriggerRepository<Trigger<Device>> triggerRepository) {
|
||||||
|
this.automationRepository = automationRepository;
|
||||||
|
this.triggerRepository = triggerRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Trigger<Device>> findTriggersByDeviceId(Long deviceId) {
|
||||||
|
return triggerRepository.findAllByDeviceId(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Automation findByVerifiedId(Long automationId) {
|
||||||
|
return automationRepository.findById(automationId).orElseThrow();
|
||||||
|
}
|
||||||
|
}
|
|
@ -93,7 +93,7 @@ public class DevicePropagationService {
|
||||||
Iterable<T> devices, String username, boolean fromScene, boolean fromTrigger) {
|
Iterable<T> devices, String username, boolean fromScene, boolean fromTrigger) {
|
||||||
devices.forEach(d -> renameIfDuplicate(d, username));
|
devices.forEach(d -> renameIfDuplicate(d, username));
|
||||||
devices = deviceRepository.saveAll(devices);
|
devices = deviceRepository.saveAll(devices);
|
||||||
devices.forEach((d) -> propagateUpdateAsOwner(d, username, fromScene && fromTrigger));
|
devices.forEach(d -> propagateUpdateAsOwner(d, username, fromScene && fromTrigger));
|
||||||
|
|
||||||
return toList(devices);
|
return toList(devices);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,35 +16,32 @@ import org.springframework.stereotype.Component;
|
||||||
public class DeviceService {
|
public class DeviceService {
|
||||||
|
|
||||||
private final DeviceRepository<Device> deviceRepository;
|
private final DeviceRepository<Device> deviceRepository;
|
||||||
private final AutomationRepository automationRepository;
|
|
||||||
private final SceneRepository sceneRepository;
|
|
||||||
private final SceneService sceneService;
|
private final SceneService sceneService;
|
||||||
private final TriggerRepository<Trigger<? extends Device>> triggerRepository;
|
|
||||||
private final RoomRepository roomRepository;
|
private final RoomRepository roomRepository;
|
||||||
|
private final AutomationService automationService;
|
||||||
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(
|
||||||
DeviceRepository<Device> deviceRepository,
|
DeviceRepository<Device> deviceRepository,
|
||||||
AutomationRepository automationRepository,
|
|
||||||
SceneRepository sceneRepository,
|
|
||||||
SceneService sceneService,
|
SceneService sceneService,
|
||||||
TriggerRepository<Trigger<? extends Device>> triggerRepository,
|
|
||||||
RoomRepository roomRepository,
|
RoomRepository roomRepository,
|
||||||
|
AutomationService automationService,
|
||||||
EagerUserRepository userRepository,
|
EagerUserRepository userRepository,
|
||||||
DevicePopulationService devicePopulationService,
|
DevicePopulationService devicePopulationService,
|
||||||
DevicePropagationService devicePropagationService) {
|
DevicePropagationService devicePropagationService,
|
||||||
|
ConditionRepository<Condition<?>> conditionRepository) {
|
||||||
this.deviceRepository = deviceRepository;
|
this.deviceRepository = deviceRepository;
|
||||||
this.automationRepository = automationRepository;
|
|
||||||
this.sceneRepository = sceneRepository;
|
|
||||||
this.sceneService = sceneService;
|
this.sceneService = sceneService;
|
||||||
this.triggerRepository = triggerRepository;
|
|
||||||
this.roomRepository = roomRepository;
|
this.roomRepository = roomRepository;
|
||||||
|
this.automationService = automationService;
|
||||||
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 {
|
||||||
|
@ -58,24 +55,26 @@ 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<? extends Device>> triggers = triggerRepository.findAllByDeviceId(deviceId);
|
|
||||||
|
|
||||||
triggers.stream()
|
triggers.stream()
|
||||||
.filter(Trigger::triggered)
|
.filter(Trigger::triggered)
|
||||||
.map(Trigger::getAutomationId)
|
.map(Trigger::getAutomationId)
|
||||||
.map(t -> automationRepository.findById(t).orElseThrow(IllegalStateException::new))
|
.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()
|
||||||
.sorted(Comparator.comparing(ScenePriority::getPriority))
|
.sorted(Comparator.comparing(ScenePriority::getPriority))
|
||||||
.map(
|
.map(t -> sceneService.findByValidatedId(t.getSceneId()))
|
||||||
t ->
|
.forEach(s -> sceneService.apply(s, username, true));
|
||||||
sceneRepository
|
|
||||||
.findById(t.getSceneId())
|
|
||||||
.orElseThrow(IllegalStateException::new))
|
|
||||||
.forEach((s) -> sceneService.apply(s, username, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Device> findAll(Long hostId, String username) throws NotFoundException {
|
public List<Device> findAll(Long hostId, String username) throws NotFoundException {
|
||||||
|
@ -86,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());
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ public class DeviceService {
|
||||||
List<T> toReturn =
|
List<T> toReturn =
|
||||||
devicePropagationService.saveAllAsOwner(devices, username, fromScene, fromTrigger);
|
devicePropagationService.saveAllAsOwner(devices, username, fromScene, fromTrigger);
|
||||||
if (!fromScene) {
|
if (!fromScene) {
|
||||||
toReturn.forEach((d) -> this.triggerTriggers(d, username));
|
toReturn.forEach(d -> this.triggerTriggers(d, username));
|
||||||
}
|
}
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,10 @@ public class DeviceService {
|
||||||
|
|
||||||
devicePopulationService.populateComputedFields(devices);
|
devicePopulationService.populateComputedFields(devices);
|
||||||
|
|
||||||
|
return filterOutCamerasIfNeeded(host, devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Device> filterOutCamerasIfNeeded(User host, Iterable<Device> devices) {
|
||||||
if (host != null && !host.isCameraEnabled()) {
|
if (host != null && !host.isCameraEnabled()) {
|
||||||
return StreamSupport.stream(devices.spliterator(), true)
|
return StreamSupport.stream(devices.spliterator(), true)
|
||||||
.filter(d -> !(d instanceof SecurityCamera))
|
.filter(d -> !(d instanceof SecurityCamera))
|
||||||
|
|
|
@ -15,7 +15,7 @@ public class JWTUserDetailsService implements UserDetailsService {
|
||||||
@Autowired private UserRepository repository;
|
@Autowired private UserRepository repository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
public UserDetails loadUserByUsername(String username) {
|
||||||
User toReturn = repository.findByUsername(username);
|
User toReturn = repository.findByUsername(username);
|
||||||
if (toReturn != null && toReturn.getEnabled()) {
|
if (toReturn != null && toReturn.getEnabled()) {
|
||||||
return new org.springframework.security.core.userdetails.User(
|
return new org.springframework.security.core.userdetails.User(
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@ -11,14 +12,22 @@ public class SceneService {
|
||||||
private final DevicePopulationService devicePopulationService;
|
private final DevicePopulationService devicePopulationService;
|
||||||
private final DevicePropagationService devicePropagationService;
|
private final DevicePropagationService devicePropagationService;
|
||||||
private final StateRepository<State<?>> stateRepository;
|
private final StateRepository<State<?>> stateRepository;
|
||||||
|
private final SceneRepository sceneRepository;
|
||||||
|
|
||||||
|
public Scene findByValidatedId(Long id) {
|
||||||
|
return sceneRepository.findById(id).orElseThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Autowired
|
||||||
public SceneService(
|
public SceneService(
|
||||||
DevicePopulationService devicePopulationService,
|
DevicePopulationService devicePopulationService,
|
||||||
DevicePropagationService devicePropagationService,
|
DevicePropagationService devicePropagationService,
|
||||||
StateRepository<State<?>> stateRepository) {
|
StateRepository<State<?>> stateRepository,
|
||||||
|
SceneRepository sceneRepository) {
|
||||||
this.devicePopulationService = devicePopulationService;
|
this.devicePopulationService = devicePopulationService;
|
||||||
this.devicePropagationService = devicePropagationService;
|
this.devicePropagationService = devicePropagationService;
|
||||||
this.stateRepository = stateRepository;
|
this.stateRepository = stateRepository;
|
||||||
|
this.sceneRepository = sceneRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Device> copyStatesToDevices(Scene fromScene) {
|
private List<Device> copyStatesToDevices(Scene fromScene) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import org.springframework.web.socket.server.standard.ServerEndpointRegistration
|
||||||
@Configuration
|
@Configuration
|
||||||
public class SensorSocketConfig extends ServerEndpointConfig.Configurator {
|
public class SensorSocketConfig extends ServerEndpointConfig.Configurator {
|
||||||
|
|
||||||
private SensorSocketEndpoint instance;
|
private final SensorSocketEndpoint instance;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public SensorSocketConfig(SensorSocketEndpoint instance) {
|
public SensorSocketConfig(SensorSocketEndpoint instance) {
|
||||||
|
@ -41,9 +41,8 @@ public class SensorSocketConfig extends ServerEndpointConfig.Configurator {
|
||||||
@Override
|
@Override
|
||||||
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
|
public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException {
|
||||||
try {
|
try {
|
||||||
@SuppressWarnings("unchecked")
|
//noinspection unchecked
|
||||||
final T instance = (T) this.instance;
|
return (T) this.instance;
|
||||||
return instance;
|
|
||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
final var e2 =
|
final var e2 =
|
||||||
new InstantiationException("Cannot cast SensorSocketEndpoint to desired type");
|
new InstantiationException("Cannot cast SensorSocketEndpoint to desired type");
|
||||||
|
|
|
@ -122,7 +122,8 @@ public class SensorSocketEndpoint extends Endpoint {
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
session.close();
|
session.close();
|
||||||
} catch (IOException ignored) {
|
} catch (IOException e) {
|
||||||
|
logger.warn(e.getLocalizedMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,3 +33,4 @@ email.resetpasswordSubject=SmartHut.sm password reset
|
||||||
email.resetpassword=To reset your password, please click here:
|
email.resetpassword=To reset your password, please click here:
|
||||||
email.resetpasswordPath=http://localhost:3000/password-reset?token=
|
email.resetpasswordPath=http://localhost:3000/password-reset?token=
|
||||||
email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
|
email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
|
||||||
|
camera.videoUrl="/security_camera_videos/security_camera_1.mp4"
|
|
@ -40,3 +40,4 @@ email.resetpasswordSubject=SmartHut.sm password reset
|
||||||
email.resetpassword=To reset your password, please click here:
|
email.resetpassword=To reset your password, please click here:
|
||||||
email.resetpasswordPath=${FRONTEND_URL}/password-reset?token=
|
email.resetpasswordPath=${FRONTEND_URL}/password-reset?token=
|
||||||
email.resetPasswordRedirect=${FRONTEND_URL}/conf-reset-pass
|
email.resetPasswordRedirect=${FRONTEND_URL}/conf-reset-pass
|
||||||
|
camera.videoUrl="/security_camera_videos/security_camera_1.mp4"
|
|
@ -41,7 +41,7 @@ public abstract class SmartHutTest {
|
||||||
final ConfirmationTokenRepository tokenRepository) {
|
final ConfirmationTokenRepository tokenRepository) {
|
||||||
final ResponseEntity<Object> res2 =
|
final ResponseEntity<Object> res2 =
|
||||||
restTemplate.postForEntity(this.url("/register"), enabledUser, Object.class);
|
restTemplate.postForEntity(this.url("/register"), enabledUser, Object.class);
|
||||||
assertThat(res2.getStatusCode().equals(HttpStatus.OK));
|
assertThat(res2.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||||
|
|
||||||
final User persistedEnabledUser = userRepository.findByUsername("enabled");
|
final User persistedEnabledUser = userRepository.findByUsername("enabled");
|
||||||
final ConfirmationToken token = tokenRepository.findByUser(persistedEnabledUser);
|
final ConfirmationToken token = tokenRepository.findByUser(persistedEnabledUser);
|
||||||
|
@ -49,7 +49,7 @@ public abstract class SmartHutTest {
|
||||||
final ResponseEntity<Void> res3 =
|
final ResponseEntity<Void> res3 =
|
||||||
WebClient.create(getBaseURL())
|
WebClient.create(getBaseURL())
|
||||||
.get()
|
.get()
|
||||||
.uri("/register/confirm-account?token=" + token.getConfirmationToken())
|
.uri("/register/confirm-account?token=" + token.getConfirmToken())
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.toBodilessEntity()
|
.toBodilessEntity()
|
||||||
.block();
|
.block();
|
||||||
|
|
|
@ -16,11 +16,8 @@ public class SmarthutApplicationTests extends SmartHutTest {
|
||||||
@Autowired private TestRestTemplate restTemplate;
|
@Autowired private TestRestTemplate restTemplate;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void anonymousGreetingShouldNotBeAuthorized() throws Exception {
|
public void anonymousGreetingShouldNotBeAuthorized() {
|
||||||
assertThat(
|
assertThat(this.restTemplate.getForEntity(getBaseURL(), Void.class).getStatusCode())
|
||||||
this.restTemplate
|
.isEqualTo(HttpStatus.UNAUTHORIZED);
|
||||||
.getForEntity(getBaseURL(), Void.class)
|
|
||||||
.getStatusCode()
|
|
||||||
.equals(HttpStatus.UNAUTHORIZED));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,3 +35,4 @@ email.resetpasswordSubject=SmartHut.sm password reset
|
||||||
email.resetpassword=To reset your password, please click here:
|
email.resetpassword=To reset your password, please click here:
|
||||||
email.resetpasswordPath=http://localhost:3000/password-reset?token=
|
email.resetpasswordPath=http://localhost:3000/password-reset?token=
|
||||||
email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
|
email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
|
||||||
|
camera.videoUrl="/security_camera_videos/security_camera_1.mp4"
|
Loading…
Reference in a new issue