diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CORSFilter.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CORSFilter.java index bfade8a..2d355f9 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CORSFilter.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CORSFilter.java @@ -14,7 +14,8 @@ import org.springframework.stereotype.Component; public class CORSFilter implements Filter { 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-Headers", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CameraConfigurationService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CameraConfigurationService.java new file mode 100644 index 0000000..6f15932 --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/CameraConfigurationService.java @@ -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; + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java index 4b69a07..d3c0c50 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/GsonConfig.java @@ -1,6 +1,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.config; 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.State; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SwitchableState; @@ -43,12 +44,32 @@ public class GsonConfig { .registerSubtype( AutomationFastUpdateRequest.RangeTriggerDTO.class, "rangeTrigger"); + + RuntimeTypeAdapterFactory + 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(runtimeTypeAdapterFactoryII); + builder.registerTypeAdapterFactory(runtimeTypeAdapterFactoryIII); builder.registerTypeAdapter( Trigger.class, (JsonSerializer>) (src, typeOfSrc, context) -> context.serialize((Object) src)); + builder.registerTypeAdapter( + Condition.class, + (JsonSerializer>) + (src, typeOfSrc, context) -> context.serialize((Object) src)); return builder; } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/RuntimeTypeAdapterFactory.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/RuntimeTypeAdapterFactory.java index d1d4e76..aa33517 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/RuntimeTypeAdapterFactory.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/RuntimeTypeAdapterFactory.java @@ -61,8 +61,8 @@ import java.util.Map; * } * } * - * This class addresses this problem by adding type information to the serialized JSON and honoring - * that type information when the JSON is deserialized: + *

This class addresses this problem by adding type information to the serialized JSON and + * honoring that type information when the JSON is deserialized: * *

{@code
  * {
@@ -82,12 +82,12 @@ import java.util.Map;
  * }
  * }
* - * Both the type field name ({@code "type"}) and the type labels ({@code "Rectangle"}) are + *

Both the type field name ({@code "type"}) and the type labels ({@code "Rectangle"}) are * configurable. * *

Registering Types

* - * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field name to the + *

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 * be used. * @@ -96,7 +96,7 @@ import java.util.Map; * = RuntimeTypeAdapterFactory.of(Shape.class, "type"); * } * - * Next register all of your subtypes. Every subtype must be explicitly registered. This protects + *

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 * simple name will be used. * @@ -106,7 +106,7 @@ import java.util.Map; * shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond"); * } * - * Finally, register the type adapter factory in your application's GSON builder: + *

Finally, register the type adapter factory in your application's GSON builder: * *

{@code
  * Gson gson = new GsonBuilder()
@@ -114,7 +114,7 @@ import java.util.Map;
  *     .create();
  * }
* - * Like {@code GsonBuilder}, this API supports chaining: + *

Like {@code GsonBuilder}, this API supports chaining: * *

{@code
  * RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
@@ -125,7 +125,7 @@ import java.util.Map;
  *
  * 

Serialization and deserialization

* - * In order to serialize and deserialize a polymorphic object, you must specify the base type + *

In order to serialize and deserialize a polymorphic object, you must specify the base type * explicitly. * *

{@code
@@ -133,7 +133,7 @@ import java.util.Map;
  * String json = gson.toJson(diamond, Shape.class);
  * }
* - * And then: + *

And then: * *

{@code
  * Shape shape = gson.fromJson(json, Shape.class);
@@ -200,6 +200,38 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {
         return this;
     }
 
+    private void initMaps(
+            Gson gson,
+            Map> labelToDelegate,
+            Map, TypeAdapter> subtypeToDelegate) {
+        for (Map.Entry> 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 e : jsonObject.entrySet()) {
+            clone.add(e.getKey(), e.getValue());
+        }
+        Streams.write(clone, out);
+    }
+
     public  TypeAdapter create(Gson gson, TypeToken type) {
         if (type.getRawType() != baseType) {
             return null;
@@ -209,12 +241,9 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {
                 new LinkedHashMap<>(labelToSubtype.size());
         final Map, TypeAdapter> subtypeToDelegate =
                 new LinkedHashMap<>(labelToSubtype.size());
-        for (Map.Entry> entry : labelToSubtype.entrySet()) {
-            TypeAdapter delegate =
-                    gson.getDelegateAdapter(this, TypeToken.get(entry.getValue()));
-            labelToDelegate.put(entry.getKey(), delegate);
-            subtypeToDelegate.put(entry.getValue(), delegate);
-        }
+
+        initMaps(gson, labelToDelegate, subtypeToDelegate);
+        final RuntimeTypeAdapterFactory that = this;
 
         return new TypeAdapter() {
             @Override
@@ -267,21 +296,7 @@ public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory {
                     return;
                 }
 
-                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 e : jsonObject.entrySet()) {
-                    clone.add(e.getKey(), e.getValue());
-                }
-                Streams.write(clone, out);
+                that.cloneObjectAndWrite(jsonObject, label, out, srcType);
             }
         }.nullSafe();
     }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java
index c3027ae..e82bce2 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AutomationController.java
@@ -28,6 +28,7 @@ public class AutomationController {
     @Autowired private AutomationRepository automationRepository;
     @Autowired private ScenePriorityRepository sceneRepository;
     @Autowired private TriggerRepository> triggerRepository;
+    @Autowired private ConditionRepository> conditionRepository;
     @Autowired private UserRepository userService;
 
     @GetMapping
@@ -86,6 +87,7 @@ public class AutomationController {
 
         triggerRepository.deleteAllByAutomationId(a.getId());
         sceneRepository.deleteAllByAutomationId(a.getId());
+        conditionRepository.deleteAllByAutomationId(a.getId());
 
         Iterable> tt =
                 triggerRepository.saveAll(
@@ -99,21 +101,31 @@ public class AutomationController {
                         req.getScenes()
                                 .stream()
                                 .map(AutomationFastUpdateRequest.ScenePriorityDTO::toModel)
-                                .peek(
-                                        t -> {
-                                            t.setAutomationId(a.getId());
-
-                                            // this is here just to pass the quality gate,
-                                            // please do not replicate unless the quality gate sees
-                                            // it as a bug
-                                            t.setAutomation(a);
-                                        })
                                 .collect(Collectors.toList()));
 
+        Iterable> 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,
+            // please do not replicate unless the quality gate sees
+            // it as a bug
+            s.setAutomation(a);
+        }
+
         a.getScenes().clear();
         a.getTriggers().clear();
+        a.getConditions().clear();
         ss.forEach(t -> a.getScenes().add(t));
         tt.forEach(t -> a.getTriggers().add(t));
+        cc.forEach(t -> a.getConditions().add(t));
 
         return a;
     }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanConditionController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanConditionController.java
new file mode 100644
index 0000000..ddcb880
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanConditionController.java
@@ -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 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);
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanTriggerController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanTriggerController.java
index 9331b56..46af99e 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanTriggerController.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/BooleanTriggerController.java
@@ -25,11 +25,11 @@ public class BooleanTriggerController {
     @Autowired BooleanTriggerRepository booleanTriggerRepository;
 
     @GetMapping("/{automationId}")
-    public List> getAll(@PathVariable long automationId) {
+    public List getAll(@PathVariable long automationId) {
         return booleanTriggerRepository.findAllByAutomationId(automationId);
     }
 
-    private BooleanTrigger save(BooleanTrigger newRL, BooleanTriggerSaveRequest s) {
+    private BooleanTrigger save(BooleanTrigger newRL, BooleanTriggerSaveRequest s) {
         newRL.setDeviceId(s.getDeviceId());
         newRL.setAutomationId(s.getAutomationId());
         newRL.setOn(s.isOn());
@@ -38,13 +38,13 @@ public class BooleanTriggerController {
     }
 
     @PostMapping
-    public BooleanTrigger create(
+    public BooleanTrigger create(
             @Valid @RequestBody BooleanTriggerSaveRequest booleanTriggerSaveRequest) {
-        return save(new BooleanTrigger<>(), booleanTriggerSaveRequest);
+        return save(new BooleanTrigger(), booleanTriggerSaveRequest);
     }
 
     @PutMapping
-    public BooleanTrigger update(
+    public BooleanTrigger update(
             @Valid @RequestBody BooleanTriggerSaveRequest booleanTriggerSaveRequest)
             throws NotFoundException {
         return save(
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeConditionController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeConditionController.java
new file mode 100644
index 0000000..5055c61
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeConditionController.java
@@ -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 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);
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeTriggerController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeTriggerController.java
index 655ce4b..a86a386 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeTriggerController.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/RangeTriggerController.java
@@ -25,11 +25,11 @@ public class RangeTriggerController {
     @Autowired RangeTriggerRepository rangeTriggerRepository;
 
     @GetMapping("/{automationId}")
-    public List> getAll(@PathVariable long automationId) {
+    public List getAll(@PathVariable long automationId) {
         return rangeTriggerRepository.findAllByAutomationId(automationId);
     }
 
-    private RangeTrigger save(RangeTrigger newRL, RangeTriggerSaveRequest s) {
+    private RangeTrigger save(RangeTrigger newRL, RangeTriggerSaveRequest s) {
         newRL.setDeviceId(s.getDeviceId());
         newRL.setAutomationId(s.getAutomationId());
         newRL.setOperator(s.getOperator());
@@ -39,13 +39,13 @@ public class RangeTriggerController {
     }
 
     @PostMapping
-    public RangeTrigger create(
+    public RangeTrigger create(
             @Valid @RequestBody RangeTriggerSaveRequest booleanTriggerSaveRequest) {
-        return save(new RangeTrigger<>(), booleanTriggerSaveRequest);
+        return save(new RangeTrigger(), booleanTriggerSaveRequest);
     }
 
     @PutMapping
-    public RangeTrigger update(
+    public RangeTrigger update(
             @Valid @RequestBody RangeTriggerSaveRequest booleanTriggerSaveRequest)
             throws NotFoundException {
         return save(
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SecurityCameraController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SecurityCameraController.java
index 9716430..d006879 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SecurityCameraController.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SecurityCameraController.java
@@ -1,5 +1,6 @@
 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.error.DuplicateStateException;
 import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
@@ -26,17 +27,20 @@ public class SecurityCameraController {
     private final SecurityCameraRepository securityCameraService;
     private final SceneRepository sceneRepository;
     private final StateRepository> stateRepository;
+    private final CameraConfigurationService cameraConfigurationService;
 
     @Autowired
     public SecurityCameraController(
             DeviceService deviceService,
             SecurityCameraRepository securityCameraService,
             SceneRepository sceneRepository,
-            StateRepository> stateRepository) {
+            StateRepository> stateRepository,
+            CameraConfigurationService cameraConfigurationService) {
         this.deviceService = deviceService;
         this.securityCameraService = securityCameraService;
         this.sceneRepository = sceneRepository;
         this.stateRepository = stateRepository;
+        this.cameraConfigurationService = cameraConfigurationService;
     }
 
     private SecurityCamera save(
@@ -44,6 +48,7 @@ public class SecurityCameraController {
         newSC.setName(sc.getName());
         newSC.setRoomId(sc.getRoomId());
         newSC.setOn(sc.isOn());
+        newSC.setPath(cameraConfigurationService.getVideoUrl());
 
         return deviceService.saveAsOwner(newSC, principal.getName());
     }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatConditionController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatConditionController.java
new file mode 100644
index 0000000..a6d118a
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatConditionController.java
@@ -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 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);
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/UserAccountController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/UserAccountController.java
index c5ecfb1..fe5d6fd 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/UserAccountController.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/UserAccountController.java
@@ -64,7 +64,7 @@ public class UserAccountController {
                         + (isRegistration
                                 ? emailConfig.getRegistrationPath()
                                 : emailConfig.getResetPasswordPath())
-                        + token.getConfirmationToken());
+                        + token.getConfirmToken());
 
         emailSenderService.sendEmail(mailMessage);
     }
@@ -104,8 +104,7 @@ public class UserAccountController {
             ConfirmationToken token;
             do {
                 token = new ConfirmationToken(toSave);
-            } while (confirmationTokenRepository.findByConfirmationToken(
-                            token.getConfirmationToken())
+            } while (confirmationTokenRepository.findByConfirmToken(token.getConfirmToken())
                     != null);
 
             confirmationTokenRepository.save(token);
@@ -135,8 +134,7 @@ public class UserAccountController {
         do {
             token = new ConfirmationToken(toReset);
             token.setResetPassword(true);
-        } while (confirmationTokenRepository.findByConfirmationToken(token.getConfirmationToken())
-                != null);
+        } while (confirmationTokenRepository.findByConfirmToken(token.getConfirmToken()) != null);
 
         // Delete existing email password reset tokens
         confirmationTokenRepository.deleteByUserAndResetPassword(toReset, true);
@@ -158,8 +156,7 @@ public class UserAccountController {
     public void resetPassword(@Valid @RequestBody PasswordResetRequest resetRequest)
             throws EmailTokenNotFoundException {
         final ConfirmationToken token =
-                confirmationTokenRepository.findByConfirmationToken(
-                        resetRequest.getConfirmationToken());
+                confirmationTokenRepository.findByConfirmToken(resetRequest.getConfirmationToken());
 
         if (token == null || !token.getResetPassword()) {
             throw new EmailTokenNotFoundException();
@@ -187,7 +184,7 @@ public class UserAccountController {
             final HttpServletResponse response)
             throws EmailTokenNotFoundException, IOException {
         final ConfirmationToken token =
-                confirmationTokenRepository.findByConfirmationToken(confirmationToken);
+                confirmationTokenRepository.findByConfirmToken(confirmationToken);
 
         if (token != null && !token.getResetPassword()) {
             token.getUser().setEnabled(true);
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java
index 1fd45ea..0861429 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/AutomationFastUpdateRequest.java
@@ -1,8 +1,13 @@
 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.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.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 java.util.List;
 import javax.validation.constraints.Min;
@@ -23,7 +28,7 @@ public class AutomationFastUpdateRequest {
 
         @Override
         public Trigger toModel() {
-            BooleanTrigger t = new BooleanTrigger<>();
+            BooleanTrigger t = new BooleanTrigger();
             t.setDeviceId(this.deviceId);
             t.setOn(this.on);
             return t;
@@ -36,7 +41,7 @@ public class AutomationFastUpdateRequest {
 
         @Override
         public Trigger toModel() {
-            RangeTrigger t = new RangeTrigger<>();
+            RangeTrigger t = new RangeTrigger();
             t.setDeviceId(this.deviceId);
             t.setOperator(this.operator);
             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 scenes;
     @NotNull private List triggers;
+    @NotNull private List conditions;
     @NotNull private long id;
 
     @NotNull @NotEmpty private String name;
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/BooleanConditionSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/BooleanConditionSaveRequest.java
new file mode 100644
index 0000000..2abf6e0
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/BooleanConditionSaveRequest.java
@@ -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;
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RangeConditionSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RangeConditionSaveRequest.java
new file mode 100644
index 0000000..8cf4bf6
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/RangeConditionSaveRequest.java
@@ -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;
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatConditionSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatConditionSaveRequest.java
new file mode 100644
index 0000000..8c56f2d
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatConditionSaveRequest.java
@@ -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;
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java
index 4d01cde..f711c93 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Automation.java
@@ -33,6 +33,9 @@ public class Automation {
     @OneToMany(mappedBy = "automation", cascade = CascadeType.REMOVE)
     private Set scenes = new HashSet<>();
 
+    @OneToMany(mappedBy = "automation", orphanRemoval = true, cascade = CascadeType.REMOVE)
+    private Set> conditions = new HashSet<>();
+
     @NotNull @NotEmpty private String name;
 
     public long getId() {
@@ -74,4 +77,8 @@ public class Automation {
     public void setUserId(Long userId) {
         this.userId = userId;
     }
+
+    public Set> getConditions() {
+        return conditions;
+    }
 }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java
index b874146..afdfab3 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/AutomationRepository.java
@@ -7,9 +7,9 @@ import org.springframework.data.repository.CrudRepository;
 import org.springframework.data.repository.query.Param;
 
 public interface AutomationRepository extends CrudRepository {
-    @EntityGraph(attributePaths = {"scenes", "triggers"})
+    @EntityGraph(attributePaths = {"scenes", "triggers", "conditions"})
     List findAllByUserId(@Param("userId") long userId);
 
-    @EntityGraph(attributePaths = {"scenes", "triggers"})
+    @EntityGraph(attributePaths = {"scenes", "triggers", "conditions"})
     Optional findByIdAndUserId(@Param("id") long id, @Param("userId") long userId);
 }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanCondition.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanCondition.java
new file mode 100644
index 0000000..22ac7a2
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanCondition.java
@@ -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 {
+
+    @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();
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanConditionRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanConditionRepository.java
new file mode 100644
index 0000000..539eb6d
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanConditionRepository.java
@@ -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 {
+
+    List findAllByAutomationId(@Param("automationId") long automationId);
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java
index f6e493e..6eeb69e 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTrigger.java
@@ -4,7 +4,7 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 
 @Entity
-public class BooleanTrigger extends Trigger {
+public class BooleanTrigger extends Trigger {
 
     @Column(name = "switchable_on")
     private boolean on;
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTriggerRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTriggerRepository.java
index 08b8898..4f9263c 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTriggerRepository.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/BooleanTriggerRepository.java
@@ -3,8 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
 import java.util.List;
 import org.springframework.data.repository.query.Param;
 
-public interface BooleanTriggerRepository
-        extends TriggerRepository> {
+public interface BooleanTriggerRepository extends TriggerRepository {
 
-    List> findAllByAutomationId(@Param("automationId") long automationId);
+    List findAllByAutomationId(@Param("automationId") long automationId);
 }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Condition.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Condition.java
new file mode 100644
index 0000000..08b2db8
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Condition.java
@@ -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 {
+
+    @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 setAutomationId(Long automationId) {
+        this.automationId = automationId;
+        return this;
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConditionRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConditionRepository.java
new file mode 100644
index 0000000..2f7a1cc
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConditionRepository.java
@@ -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> extends CrudRepository {
+
+    List findAllByDeviceId(@Param("deviceId") long deviceId);
+
+    List findAllByAutomationId(@Param("automationId") long automationId);
+
+    @Transactional
+    void deleteAllByAutomationId(@Param("automationId") long automationId);
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationToken.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationToken.java
index ac1f151..a661aa0 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationToken.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationToken.java
@@ -22,7 +22,7 @@ public class ConfirmationToken {
     private Long id;
 
     @Column(name = "confirmation_token", unique = true)
-    private String confirmationToken;
+    private String confirmToken;
 
     @Temporal(TemporalType.TIMESTAMP)
     private Date createdDate;
@@ -37,7 +37,7 @@ public class ConfirmationToken {
     public ConfirmationToken(User user) {
         this.user = user;
         createdDate = new Date();
-        confirmationToken = UUID.randomUUID().toString();
+        confirmToken = UUID.randomUUID().toString();
         resetPassword = false;
     }
 
@@ -48,12 +48,12 @@ public class ConfirmationToken {
         return id;
     }
 
-    public String getConfirmationToken() {
-        return confirmationToken;
+    public String getConfirmToken() {
+        return confirmToken;
     }
 
     public Date getCreatedDate() {
-        return createdDate;
+        return (Date) createdDate.clone();
     }
 
     public User getUser() {
@@ -64,12 +64,12 @@ public class ConfirmationToken {
         this.id = id;
     }
 
-    public void setConfirmationToken(String confirmationToken) {
-        this.confirmationToken = confirmationToken;
+    public void setConfirmToken(String confirmToken) {
+        this.confirmToken = confirmToken;
     }
 
     public void setCreatedDate(Date createdDate) {
-        this.createdDate = createdDate;
+        this.createdDate = (Date) createdDate.clone();
     }
 
     public void setUser(User user) {
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationTokenRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationTokenRepository.java
index 40c6a17..851be41 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationTokenRepository.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ConfirmationTokenRepository.java
@@ -4,7 +4,7 @@ import javax.transaction.Transactional;
 import org.springframework.data.repository.CrudRepository;
 
 public interface ConfirmationTokenRepository extends CrudRepository {
-    ConfirmationToken findByConfirmationToken(String confirmationToken);
+    ConfirmationToken findByConfirmToken(String confirmToken);
 
     ConfirmationToken findByUser(User user);
 
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeCondition.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeCondition.java
new file mode 100644
index 0000000..f3e4bce
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeCondition.java
@@ -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 {
+
+    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();
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeConditionRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeConditionRepository.java
new file mode 100644
index 0000000..451d4a7
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeConditionRepository.java
@@ -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 {
+    List findAllByAutomationId(@Param("automationId") long automationId);
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java
index c4d5836..0d926ae 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTrigger.java
@@ -5,7 +5,7 @@ import javax.persistence.Column;
 import javax.persistence.Entity;
 
 @Entity
-public class RangeTrigger extends Trigger {
+public class RangeTrigger extends Trigger {
 
     public RangeTrigger() {
         super("rangeTrigger");
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTriggerRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTriggerRepository.java
index 8ef6772..b4827b5 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTriggerRepository.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/RangeTriggerRepository.java
@@ -3,7 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
 import java.util.List;
 import org.springframework.data.repository.query.Param;
 
-public interface RangeTriggerRepository extends TriggerRepository> {
+public interface RangeTriggerRepository extends TriggerRepository {
 
-    List> findAllByAutomationId(@Param("automationId") long automationId);
+    List findAllByAutomationId(@Param("automationId") long automationId);
 }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SecurityCamera.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SecurityCamera.java
index 3d4cef9..218ba4a 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SecurityCamera.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/SecurityCamera.java
@@ -17,13 +17,16 @@ public class SecurityCamera extends Switchable implements BooleanTriggerable {
     private boolean on;
 
     @Column(name = "video", nullable = false)
-    @NotNull
-    private String path = "/security_camera_videos/security_camera_1.mp4";
+    private String path;
 
     public String getPath() {
         return path;
     }
 
+    public void setPath(String path) {
+        this.path = path;
+    }
+
     @Override
     public boolean isOn() {
         return on;
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatCondition.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatCondition.java
new file mode 100644
index 0000000..2bb65d1
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatCondition.java
@@ -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 {
+
+    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;
+        }
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatConditionRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatConditionRepository.java
new file mode 100644
index 0000000..4b529fb
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatConditionRepository.java
@@ -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 {
+
+    List findAllByAutomationId(@Param("automationId") long automationId);
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java
index f766b4c..3633a35 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Trigger.java
@@ -6,7 +6,7 @@ import javax.persistence.*;
 
 @Entity
 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
-public abstract class Trigger {
+public abstract class Trigger {
 
     @Transient private String kind;
 
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/AutomationService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/AutomationService.java
new file mode 100644
index 0000000..9eaf401
--- /dev/null
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/AutomationService.java
@@ -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> triggerRepository;
+
+    @Autowired
+    public AutomationService(
+            AutomationRepository automationRepository,
+            TriggerRepository> triggerRepository) {
+        this.automationRepository = automationRepository;
+        this.triggerRepository = triggerRepository;
+    }
+
+    public List> findTriggersByDeviceId(Long deviceId) {
+        return triggerRepository.findAllByDeviceId(deviceId);
+    }
+
+    public Automation findByVerifiedId(Long automationId) {
+        return automationRepository.findById(automationId).orElseThrow();
+    }
+}
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DevicePropagationService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DevicePropagationService.java
index ae004a4..edba584 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DevicePropagationService.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DevicePropagationService.java
@@ -93,7 +93,7 @@ public class DevicePropagationService {
             Iterable devices, String username, boolean fromScene, boolean fromTrigger) {
         devices.forEach(d -> renameIfDuplicate(d, username));
         devices = deviceRepository.saveAll(devices);
-        devices.forEach((d) -> propagateUpdateAsOwner(d, username, fromScene && fromTrigger));
+        devices.forEach(d -> propagateUpdateAsOwner(d, username, fromScene && fromTrigger));
 
         return toList(devices);
     }
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java
index bf16b88..ea21d5d 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/DeviceService.java
@@ -16,35 +16,32 @@ import org.springframework.stereotype.Component;
 public class DeviceService {
 
     private final DeviceRepository deviceRepository;
-    private final AutomationRepository automationRepository;
-    private final SceneRepository sceneRepository;
     private final SceneService sceneService;
-    private final TriggerRepository> triggerRepository;
     private final RoomRepository roomRepository;
+    private final AutomationService automationService;
     private final EagerUserRepository userRepository;
     private final DevicePopulationService devicePopulationService;
     private final DevicePropagationService devicePropagationService;
+    private final ConditionRepository> conditionRepository;
 
     @Autowired
     public DeviceService(
             DeviceRepository deviceRepository,
-            AutomationRepository automationRepository,
-            SceneRepository sceneRepository,
             SceneService sceneService,
-            TriggerRepository> triggerRepository,
             RoomRepository roomRepository,
+            AutomationService automationService,
             EagerUserRepository userRepository,
             DevicePopulationService devicePopulationService,
-            DevicePropagationService devicePropagationService) {
+            DevicePropagationService devicePropagationService,
+            ConditionRepository> conditionRepository) {
         this.deviceRepository = deviceRepository;
-        this.automationRepository = automationRepository;
-        this.sceneRepository = sceneRepository;
         this.sceneService = sceneService;
-        this.triggerRepository = triggerRepository;
         this.roomRepository = roomRepository;
+        this.automationService = automationService;
         this.userRepository = userRepository;
         this.devicePopulationService = devicePopulationService;
         this.devicePropagationService = devicePropagationService;
+        this.conditionRepository = conditionRepository;
     }
 
     public void throwIfRoomNotOwned(Long roomId, String username) throws NotFoundException {
@@ -58,24 +55,26 @@ public class DeviceService {
     private void triggerTriggers(Device device, final String username) {
 
         final long deviceId = device.getId();
-
-        List> triggers = triggerRepository.findAllByDeviceId(deviceId);
+        final List> triggers = automationService.findTriggersByDeviceId(deviceId);
 
         triggers.stream()
                 .filter(Trigger::triggered)
                 .map(Trigger::getAutomationId)
-                .map(t -> automationRepository.findById(t).orElseThrow(IllegalStateException::new))
+                .map(automationService::findByVerifiedId)
                 .distinct()
+                .filter(
+                        a -> {
+                            final List> conditions =
+                                    conditionRepository.findAllByAutomationId(a.getId());
+                            if (conditions.size() == 0) return true;
+                            return conditions.stream().allMatch(Condition::triggered);
+                        })
                 .map(Automation::getScenes)
                 .flatMap(Collection::stream)
                 .distinct()
                 .sorted(Comparator.comparing(ScenePriority::getPriority))
-                .map(
-                        t ->
-                                sceneRepository
-                                        .findById(t.getSceneId())
-                                        .orElseThrow(IllegalStateException::new))
-                .forEach((s) -> sceneService.apply(s, username, true));
+                .map(t -> sceneService.findByValidatedId(t.getSceneId()))
+                .forEach(s -> sceneService.apply(s, username, true));
     }
 
     public List findAll(Long hostId, String username) throws NotFoundException {
@@ -86,6 +85,7 @@ public class DeviceService {
             throws NotFoundException {
         final User currentUser = userRepository.findByUsername(guestUsername);
         final User host = userRepository.findById(hostId).orElseThrow(NotFoundException::new);
+
         if (!host.getGuests().contains(currentUser)) throw new NotFoundException();
         devicePropagationService.renameIfDuplicate(device, host.getUsername());
 
@@ -123,7 +123,7 @@ public class DeviceService {
         List toReturn =
                 devicePropagationService.saveAllAsOwner(devices, username, fromScene, fromTrigger);
         if (!fromScene) {
-            toReturn.forEach((d) -> this.triggerTriggers(d, username));
+            toReturn.forEach(d -> this.triggerTriggers(d, username));
         }
         return toReturn;
     }
@@ -170,6 +170,10 @@ public class DeviceService {
 
         devicePopulationService.populateComputedFields(devices);
 
+        return filterOutCamerasIfNeeded(host, devices);
+    }
+
+    private List filterOutCamerasIfNeeded(User host, Iterable devices) {
         if (host != null && !host.isCameraEnabled()) {
             return StreamSupport.stream(devices.spliterator(), true)
                     .filter(d -> !(d instanceof SecurityCamera))
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java
index 8ab5f8a..f8c8e5b 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java
@@ -15,7 +15,7 @@ public class JWTUserDetailsService implements UserDetailsService {
     @Autowired private UserRepository repository;
 
     @Override
-    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+    public UserDetails loadUserByUsername(String username) {
         User toReturn = repository.findByUsername(username);
         if (toReturn != null && toReturn.getEnabled()) {
             return new org.springframework.security.core.userdetails.User(
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java
index 0fcf1f8..824ea7e 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SceneService.java
@@ -3,6 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.service;
 import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
 import java.util.ArrayList;
 import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -11,14 +12,22 @@ public class SceneService {
     private final DevicePopulationService devicePopulationService;
     private final DevicePropagationService devicePropagationService;
     private final StateRepository> stateRepository;
+    private final SceneRepository sceneRepository;
 
+    public Scene findByValidatedId(Long id) {
+        return sceneRepository.findById(id).orElseThrow();
+    }
+
+    @Autowired
     public SceneService(
             DevicePopulationService devicePopulationService,
             DevicePropagationService devicePropagationService,
-            StateRepository> stateRepository) {
+            StateRepository> stateRepository,
+            SceneRepository sceneRepository) {
         this.devicePopulationService = devicePopulationService;
         this.devicePropagationService = devicePropagationService;
         this.stateRepository = stateRepository;
+        this.sceneRepository = sceneRepository;
     }
 
     private List copyStatesToDevices(Scene fromScene) {
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketConfig.java
index 503667a..338a8f2 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketConfig.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketConfig.java
@@ -11,7 +11,7 @@ import org.springframework.web.socket.server.standard.ServerEndpointRegistration
 @Configuration
 public class SensorSocketConfig extends ServerEndpointConfig.Configurator {
 
-    private SensorSocketEndpoint instance;
+    private final SensorSocketEndpoint instance;
 
     @Autowired
     public SensorSocketConfig(SensorSocketEndpoint instance) {
@@ -41,9 +41,8 @@ public class SensorSocketConfig extends ServerEndpointConfig.Configurator {
     @Override
     public  T getEndpointInstance(Class endpointClass) throws InstantiationException {
         try {
-            @SuppressWarnings("unchecked")
-            final T instance = (T) this.instance;
-            return instance;
+            //noinspection unchecked
+            return (T) this.instance;
         } catch (ClassCastException e) {
             final var e2 =
                     new InstantiationException("Cannot cast SensorSocketEndpoint to desired type");
diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java
index cc298d4..009dfab 100644
--- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java
+++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/SensorSocketEndpoint.java
@@ -122,7 +122,8 @@ public class SensorSocketEndpoint extends Endpoint {
         } else {
             try {
                 session.close();
-            } catch (IOException ignored) {
+            } catch (IOException e) {
+                logger.warn(e.getLocalizedMessage(), e);
             }
         }
     }
diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties
index 8720442..9f460b4 100644
--- a/src/main/resources/application-dev.properties
+++ b/src/main/resources/application-dev.properties
@@ -32,4 +32,5 @@ email.registrationRedirect=http://localhost:3000/login
 email.resetpasswordSubject=SmartHut.sm password reset
 email.resetpassword=To reset your password, please click here:
 email.resetpasswordPath=http://localhost:3000/password-reset?token=
-email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
\ No newline at end of file
+email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
+camera.videoUrl="/security_camera_videos/security_camera_1.mp4"
\ No newline at end of file
diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties
index 1727673..d607427 100644
--- a/src/main/resources/application-prod.properties
+++ b/src/main/resources/application-prod.properties
@@ -39,4 +39,5 @@ email.registrationRedirect=${FRONTEND_URL}/login
 email.resetpasswordSubject=SmartHut.sm password reset
 email.resetpassword=To reset your password, please click here:
 email.resetpasswordPath=${FRONTEND_URL}/password-reset?token=
-email.resetPasswordRedirect=${FRONTEND_URL}/conf-reset-pass
\ No newline at end of file
+email.resetPasswordRedirect=${FRONTEND_URL}/conf-reset-pass
+camera.videoUrl="/security_camera_videos/security_camera_1.mp4"
\ No newline at end of file
diff --git a/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmartHutTest.java b/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmartHutTest.java
index 445bf08..4ac1a0f 100644
--- a/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmartHutTest.java
+++ b/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmartHutTest.java
@@ -41,7 +41,7 @@ public abstract class SmartHutTest {
             final ConfirmationTokenRepository tokenRepository) {
         final ResponseEntity res2 =
                 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 ConfirmationToken token = tokenRepository.findByUser(persistedEnabledUser);
@@ -49,7 +49,7 @@ public abstract class SmartHutTest {
         final ResponseEntity res3 =
                 WebClient.create(getBaseURL())
                         .get()
-                        .uri("/register/confirm-account?token=" + token.getConfirmationToken())
+                        .uri("/register/confirm-account?token=" + token.getConfirmToken())
                         .retrieve()
                         .toBodilessEntity()
                         .block();
diff --git a/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmarthutApplicationTests.java b/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmarthutApplicationTests.java
index dbd7e21..2aaa1b1 100644
--- a/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmarthutApplicationTests.java
+++ b/src/test/java/ch/usi/inf/sa4/sanmarinoes/smarthut/SmarthutApplicationTests.java
@@ -16,11 +16,8 @@ public class SmarthutApplicationTests extends SmartHutTest {
     @Autowired private TestRestTemplate restTemplate;
 
     @Test
-    public void anonymousGreetingShouldNotBeAuthorized() throws Exception {
-        assertThat(
-                this.restTemplate
-                        .getForEntity(getBaseURL(), Void.class)
-                        .getStatusCode()
-                        .equals(HttpStatus.UNAUTHORIZED));
+    public void anonymousGreetingShouldNotBeAuthorized() {
+        assertThat(this.restTemplate.getForEntity(getBaseURL(), Void.class).getStatusCode())
+                .isEqualTo(HttpStatus.UNAUTHORIZED);
     }
 }
diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties
index bdaafc0..1db382b 100644
--- a/src/test/resources/application.properties
+++ b/src/test/resources/application.properties
@@ -34,4 +34,5 @@ email.registrationRedirect=http://localhost:3000
 email.resetpasswordSubject=SmartHut.sm password reset
 email.resetpassword=To reset your password, please click here:
 email.resetpasswordPath=http://localhost:3000/password-reset?token=
-email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
\ No newline at end of file
+email.resetPasswordRedirect=http://localhost:3000/conf-reset-pass
+camera.videoUrl="/security_camera_videos/security_camera_1.mp4"
\ No newline at end of file