diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/JWTRequestFilter.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/JWTRequestFilter.java index e0cbb6a..503f7cd 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/JWTRequestFilter.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/JWTRequestFilter.java @@ -1,6 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.config; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.JWTUserDetailsService; +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.JWTUserDetailsService; import io.jsonwebtoken.ExpiredJwtException; import java.io.IOException; import javax.servlet.FilterChain; diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java index ec116c3..3789414 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/config/WebSecurityConfig.java @@ -1,6 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.config; -import ch.usi.inf.sa4.sanmarinoes.smarthut.models.JWTUserDetailsService; +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.JWTUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java index ad48da2..f806f01 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/AuthenticationController.java @@ -8,6 +8,8 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.error.UserNotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import java.security.Principal; import javax.validation.Valid; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.JWTUserDetailsService; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.DisabledException; diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SensorController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SensorController.java index ee1be81..b56fd60 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SensorController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/SensorController.java @@ -5,12 +5,15 @@ import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SensorSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.SensorService; import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint; + import java.math.BigDecimal; import java.security.Principal; import java.util.*; import java.util.List; import javax.validation.Valid; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.*; import org.springframework.web.bind.annotation.*; @@ -20,9 +23,14 @@ import org.springframework.web.bind.annotation.*; @RequestMapping("/sensor") public class SensorController { - @Autowired private SensorRepository sensorRepository; + @Autowired + private SensorRepository sensorRepository; - @Autowired private SensorSocketEndpoint sensorSocketEndpoint; + @Autowired + private SensorSocketEndpoint sensorSocketEndpoint; + + @Autowired + private SensorService sensorService; @GetMapping public List findAll() { @@ -45,29 +53,13 @@ public class SensorController { return sensorRepository.save(newSensor); } - /** - * Updates the sensor with new measurement and propagates update through websocket - * - * @param sensor the sensor to update - * @param value the new measurement - * @return the updated sensor - */ - public Sensor updateValueFromSensor(Sensor sensor, BigDecimal value) { - sensor.setValue(value); - final Sensor toReturn = sensorRepository.save(sensor); - - sensorSocketEndpoint.broadcast(sensor, sensorRepository.findUser(sensor.getId())); - - return toReturn; - } - @PutMapping("/{id}/value") public Sensor updateValue( @PathVariable("id") Long sensorId, @RequestParam("value") BigDecimal value, final Principal principal) throws NotFoundException { - return updateValueFromSensor( + return sensorService.updateValueFromSensor( sensorRepository .findByIdAndUsername(sensorId, principal.getName()) .orElseThrow(NotFoundException::new), diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java index 0ab66ff..4fc472a 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/controller/ThermostatController.java @@ -10,6 +10,8 @@ import java.util.*; import java.util.List; import java.util.stream.StreamSupport; import javax.validation.Valid; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.ThermostatService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.*; import org.springframework.web.bind.annotation.*; @@ -21,22 +23,16 @@ public class ThermostatController { @Autowired private ThermostatRepository thermostatRepository; + @Autowired private ThermostatService thermostatService; + @GetMapping - public List findAll() { - Iterable thermostats = thermostatRepository.findAll(); - StreamSupport.stream(thermostats.spliterator(), false) - .forEach( - s -> - s.setExternalSensorsAvailable( - thermostatRepository.getTemperatureSensorCount( - s.getRoomId()) - > 0)); - return toList(thermostats); + public List findAll(Principal user) { + return thermostatService.findAll(user.getName()); } @GetMapping("/{id}") - public Thermostat findById(@PathVariable("id") long id) throws NotFoundException { - return thermostatRepository.findById(id).orElseThrow(NotFoundException::new); + public Thermostat findById(@PathVariable("id") long id, Principal principal) throws NotFoundException { + return thermostatService.findById(id, principal.getName()).orElseThrow(NotFoundException::new); } private Thermostat save(Thermostat newT, ThermostatSaveRequest t) { @@ -47,7 +43,9 @@ public class ThermostatController { newT.setName(t.getName()); newT.setRoomId(t.getRoomId()); - return thermostatRepository.save(newT); + newT = thermostatRepository.save(newT); + thermostatService.populateMeasuredTemperature(newT); + return newT; } @PostMapping diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java index b897a92..6a541ba 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/ThermostatSaveRequest.java @@ -29,8 +29,7 @@ public class ThermostatSaveRequest { /** Temperature to be reached */ @NotNull private BigDecimal targetTemperature; - /** Embedded temperature sensor */ - @NotNull private Sensor temperatureSensor; + @NotNull private boolean useExternalSensors; /** State of this thermostat */ @NotNull private Thermostat.ThermostatState state; @@ -43,12 +42,12 @@ public class ThermostatSaveRequest { return this.state; } - public Sensor getTemperatureSensor() { - return this.temperatureSensor; + public boolean isUseExternalSensors() { + return useExternalSensors; } - public void setTemperatureSensor(Sensor temperatureSensor) { - this.temperatureSensor = temperatureSensor; + public void setUseExternalSensors(boolean useExternalSensors) { + this.useExternalSensors = useExternalSensors; } public BigDecimal getTargetTemperature() { diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java index e9d4375..f5d45ac 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Thermostat.java @@ -1,6 +1,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import com.google.gson.annotations.SerializedName; + import java.math.BigDecimal; import javax.persistence.Column; import javax.persistence.Entity; @@ -27,15 +28,15 @@ public class Thermostat extends OutputDevice { /** The temperature detected by the embedded sensor */ @Column(nullable = false, precision = 4, scale = 1) - private BigDecimal sensorTemperature; + private BigDecimal internalSensorTemperature; /** State of this thermostat */ @Column @NotNull private ThermostatState state; - @Column boolean useInternalSensor = true; + @Transient + private BigDecimal measuredTemperature; - /** True if there are any other sensors in the room */ - @Transient boolean externalSensorsAvaliable; + @Column boolean useExternalSensors = false; /** Creates a thermostat with a temperature sensor and its initial OFF state */ public Thermostat() { @@ -55,11 +56,23 @@ public class Thermostat extends OutputDevice { return this.targetTemperature; } - public void setExternalSensorsAvailable(boolean externalSensorsAvaliable) { - this.externalSensorsAvaliable = externalSensorsAvaliable; + public BigDecimal getInternalSensorTemperature() { + return internalSensorTemperature; } - /** + public boolean isUseExternalSensors() { + return useExternalSensors; + } + + public void setMeasuredTemperature(BigDecimal measuredTemperature) { + this.measuredTemperature = measuredTemperature; + } + + public void setTargetTemperature(BigDecimal targetTemperature) { + this.targetTemperature = targetTemperature; + } + + /* * Sets the target temperature to be reached. Changes the thermostat state accordingly and waits * until such temperature is reached by the embedded sensor to become idle again. * diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatRepository.java index 186276c..5f673c0 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatRepository.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/ThermostatRepository.java @@ -12,16 +12,6 @@ public interface ThermostatRepository extends DeviceRepository { * @return an optional big decimal, empty if none found */ @Query( - "SELECT AVG(s.temperature) FROM Sensor s JOIN s.room r WHERE s.sensor = 'TEMPERATURE' AND r.id = ?1") + "SELECT AVG(s.value) FROM Sensor s JOIN s.room r WHERE s.sensor = 'TEMPERATURE' AND r.id = ?1") Optional getAverageTemperature(Long thermostatRoomId); - - /** - * Computes the average temperature of all temperature sensors in the room - * - * @param thermostatRoomId room ID of the thermostat - * @return an optional big decimal, empty if none found - */ - @Query( - "SELECT COUNT(*) FROM Sensor s JOIN s.room r WHERE s.sensor = 'TEMPERATURE' AND r.id = ?1") - Integer getTemperatureSensorCount(Long thermostatRoomId); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/scheduled/UpdateTasks.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/scheduled/UpdateTasks.java index 932db5c..0f4bea5 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/scheduled/UpdateTasks.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/scheduled/UpdateTasks.java @@ -3,6 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.scheduled; import ch.usi.inf.sa4.sanmarinoes.smarthut.controller.MotionSensorController; import ch.usi.inf.sa4.sanmarinoes.smarthut.controller.SensorController; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.SensorService; import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint; import java.math.BigDecimal; import java.util.Collection; @@ -26,7 +27,7 @@ public class UpdateTasks { @Autowired private SmartPlugRepository smartPlugRepository; - @Autowired private SensorController sensorController; + @Autowired private SensorService sensorService; @Autowired private MotionSensorController motionSensorController; @@ -35,16 +36,7 @@ public class UpdateTasks { /** Generates fake sensor updates every two seconds with a +/- 1.25% error */ @Scheduled(fixedRate = 2000) public void sensorFakeUpdate() { - StreamSupport.stream(sensorRepository.findAll().spliterator(), true) - .forEach( - sensor -> - sensorController.updateValueFromSensor( - sensor, - Sensor.TYPICAL_VALUES - .get(sensor.getSensor()) - .multiply( - new BigDecimal( - 0.9875 + Math.random() / 40)))); + sensorService.sensorFakeUpdate(); } /** diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/Service/EmailSenderService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/EmailSenderService.java similarity index 100% rename from src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/Service/EmailSenderService.java rename to src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/EmailSenderService.java diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/JWTUserDetailsService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java similarity index 85% rename from src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/JWTUserDetailsService.java rename to src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java index 06ee415..7dff142 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/JWTUserDetailsService.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/JWTUserDetailsService.java @@ -1,6 +1,9 @@ -package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +package ch.usi.inf.sa4.sanmarinoes.smarthut.service; import java.util.Set; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.*; import org.springframework.security.core.userdetails.UserDetails; diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SensorService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SensorService.java new file mode 100644 index 0000000..b9c8fae --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/SensorService.java @@ -0,0 +1,52 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.service; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SensorRepository; +import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.stream.StreamSupport; + +@Component +public class SensorService { + + @Autowired + private SensorRepository sensorRepository; + + @Autowired + private SensorSocketEndpoint endpoint; + + public void sensorFakeUpdate() { + StreamSupport.stream(sensorRepository.findAll().spliterator(), true) + .forEach( + sensor -> + updateValueFromSensor( + sensor, + Sensor.TYPICAL_VALUES + .get(sensor.getSensor()) + .multiply( + BigDecimal.valueOf(0.9875 + Math.random() / 40)))); + } + + public void temperatureSensorFakeUpdate() { + + } + + /** + * Updates the sensor with new measurement and propagates update through websocket + * + * @param sensor the sensor to update + * @param value the new measurement + * @return the updated sensor + */ + public Sensor updateValueFromSensor(Sensor sensor, BigDecimal value) { + sensor.setValue(value); + final Sensor toReturn = sensorRepository.save(sensor); + + endpoint.broadcast(sensor, sensorRepository.findUser(sensor.getId())); + + return toReturn; + } +} diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/ThermostatService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/ThermostatService.java new file mode 100644 index 0000000..ab9be80 --- /dev/null +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/ThermostatService.java @@ -0,0 +1,54 @@ +package ch.usi.inf.sa4.sanmarinoes.smarthut.service; + +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SensorRepository; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Thermostat; +import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ThermostatRepository; +import ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; + +@Component +public class ThermostatService { + + @Autowired private SensorRepository sensorRepository; + + @Autowired private ThermostatRepository thermostatRepository; + + public List findAll(String username) { + Iterable all = thermostatRepository.findAllByUsername(username); + all.forEach(this::populateMeasuredTemperature); + return Utils.toList(all); + } + + public Optional findById(Long thermostat, String username) { + Optional t = thermostatRepository.findByIdAndUsername(thermostat, username); + + if (t.isPresent()) { + Thermostat u = t.get(); + populateMeasuredTemperature(u); + t = Optional.of(u); + } + + return t; + } + + private BigDecimal measureTemperature(final Thermostat thermostat) { + Optional average; + + if (thermostat.isUseExternalSensors()) { + average = thermostatRepository.getAverageTemperature(thermostat.getRoomId()); + } else { + return thermostat.getInternalSensorTemperature(); + } + + return average.orElse(null); + } + + public void populateMeasuredTemperature(Thermostat thermostat) { + thermostat.setMeasuredTemperature(measureTemperature(thermostat)); + } +}