Merge branch '30-add-wattage-data-to-smart-plugs' into 'dev'
Resolve "Add wattage data to smart plugs" Closes #30 See merge request sa4-2020/the-sanmarinoes/backend!42
This commit is contained in:
commit
7095de71a6
8 changed files with 83 additions and 10 deletions
|
@ -5,6 +5,7 @@ import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SmartPlugSaveRequest;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SmartPlugSaveRequest;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
|
import java.security.Principal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
@ -14,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@EnableAutoConfiguration
|
@EnableAutoConfiguration
|
||||||
@RequestMapping("/smartplug")
|
@RequestMapping("/smartPlug")
|
||||||
public class SmartPlugController {
|
public class SmartPlugController {
|
||||||
|
|
||||||
@Autowired private SmartPlugRepository smartPlugRepository;
|
@Autowired private SmartPlugRepository smartPlugRepository;
|
||||||
|
@ -49,6 +50,18 @@ public class SmartPlugController {
|
||||||
smartPlugRepository.findById(sp.getId()).orElseThrow(NotFoundException::new), sp);
|
smartPlugRepository.findById(sp.getId()).orElseThrow(NotFoundException::new), sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}/meter")
|
||||||
|
public SmartPlug resetMeter(@PathVariable("id") long id, final Principal principal)
|
||||||
|
throws NotFoundException {
|
||||||
|
final SmartPlug s =
|
||||||
|
smartPlugRepository
|
||||||
|
.findByIdAndUsername(id, principal.getName())
|
||||||
|
.orElseThrow(NotFoundException::new);
|
||||||
|
|
||||||
|
s.resetTotalConsumption();
|
||||||
|
return smartPlugRepository.save(s);
|
||||||
|
}
|
||||||
|
|
||||||
@DeleteMapping("/{id}")
|
@DeleteMapping("/{id}")
|
||||||
public void deleteById(@PathVariable("id") long id) {
|
public void deleteById(@PathVariable("id") long id) {
|
||||||
smartPlugRepository.deleteById(id);
|
smartPlugRepository.deleteById(id);
|
||||||
|
|
|
@ -36,7 +36,7 @@ public abstract class Device {
|
||||||
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
|
||||||
* a REST call.
|
* a REST call.
|
||||||
*/
|
*/
|
||||||
@Column(name = "room_id", nullable = false, unique = true)
|
@Column(name = "room_id", nullable = false)
|
||||||
@NotNull
|
@NotNull
|
||||||
private Long roomId;
|
private Long roomId;
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class Sensor extends InputDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The value of this sensor according to its sensor type */
|
/** The value of this sensor according to its sensor type */
|
||||||
@Column(nullable = false, length = 10, precision = 1)
|
@Column(nullable = false, precision = 11, scale = 1)
|
||||||
private BigDecimal value;
|
private BigDecimal value;
|
||||||
|
|
||||||
/** The type of this sensor */
|
/** The type of this sensor */
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
@ -8,11 +9,28 @@ import javax.validation.constraints.NotNull;
|
||||||
@Entity
|
@Entity
|
||||||
public class SmartPlug extends Switchable {
|
public class SmartPlug extends Switchable {
|
||||||
|
|
||||||
|
/** The average consumption of an active plug when on in Watt */
|
||||||
|
public static final Double AVERAGE_CONSUMPTION_KW = 200.0;
|
||||||
|
|
||||||
|
/** The total amount of power that the smart plug has consumed represented in W/h */
|
||||||
|
@Column(precision = 13, scale = 3)
|
||||||
|
@NotNull
|
||||||
|
private BigDecimal totalConsumption = BigDecimal.ZERO;
|
||||||
|
|
||||||
/** Whether the smart plug is on */
|
/** Whether the smart plug is on */
|
||||||
@Column(name = "smart_plug_on", nullable = false)
|
@Column(name = "smart_plug_on", nullable = false)
|
||||||
@NotNull
|
@NotNull
|
||||||
private boolean on;
|
private boolean on;
|
||||||
|
|
||||||
|
public BigDecimal getTotalConsumption() {
|
||||||
|
return totalConsumption;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resets the consuption meter */
|
||||||
|
public void resetTotalConsumption() {
|
||||||
|
totalConsumption = BigDecimal.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOn() {
|
public boolean isOn() {
|
||||||
return on;
|
return on;
|
||||||
|
|
|
@ -1,3 +1,24 @@
|
||||||
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
|
||||||
|
|
||||||
public interface SmartPlugRepository extends SwitchableRepository<SmartPlug> {}
|
import java.util.Collection;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
|
||||||
|
public interface SmartPlugRepository extends SwitchableRepository<SmartPlug> {
|
||||||
|
@Transactional
|
||||||
|
Collection<SmartPlug> findByOn(boolean on);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates total consumption of all activated smart plugs by considering a load of
|
||||||
|
* fakeConsumption W. This query must be executed every second
|
||||||
|
*
|
||||||
|
* @see ch.usi.inf.sa4.sanmarinoes.smarthut.scheduled.UpdateTasks
|
||||||
|
* @param fakeConsumption the fake consumption in watts
|
||||||
|
*/
|
||||||
|
@Modifying(clearAutomatically = true)
|
||||||
|
@Transactional
|
||||||
|
@Query(
|
||||||
|
"UPDATE SmartPlug s SET totalConsumption = s.totalConsumption + ?1 / 3600.0 WHERE s.on = true")
|
||||||
|
void updateTotalConsumption(Double fakeConsumption);
|
||||||
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ 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.MotionSensorController;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.controller.SensorController;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.controller.SensorController;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.MotionSensorRepository;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor;
|
import ch.usi.inf.sa4.sanmarinoes.smarthut.socket.SensorSocketEndpoint;
|
||||||
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SensorRepository;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
@ -13,18 +13,25 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/** Generates fake sensor (and motion sensor) updates as required by milestone one */
|
/**
|
||||||
|
* Generates fake sensor (and motion sensor) and smart plug consumption updates as required by
|
||||||
|
* milestone one
|
||||||
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class SensorUpdateTasks {
|
public class UpdateTasks {
|
||||||
|
|
||||||
@Autowired private SensorRepository sensorRepository;
|
@Autowired private SensorRepository sensorRepository;
|
||||||
|
|
||||||
@Autowired private MotionSensorRepository motionSensorRepository;
|
@Autowired private MotionSensorRepository motionSensorRepository;
|
||||||
|
|
||||||
|
@Autowired private SmartPlugRepository smartPlugRepository;
|
||||||
|
|
||||||
@Autowired private SensorController sensorController;
|
@Autowired private SensorController sensorController;
|
||||||
|
|
||||||
@Autowired private MotionSensorController motionSensorController;
|
@Autowired private MotionSensorController motionSensorController;
|
||||||
|
|
||||||
|
@Autowired private SensorSocketEndpoint sensorSocketEndpoint;
|
||||||
|
|
||||||
/** Generates fake sensor updates every two seconds with a +/- 1.25% error */
|
/** Generates fake sensor updates every two seconds with a +/- 1.25% error */
|
||||||
@Scheduled(fixedRate = 2000)
|
@Scheduled(fixedRate = 2000)
|
||||||
public void sensorFakeUpdate() {
|
public void sensorFakeUpdate() {
|
||||||
|
@ -59,4 +66,12 @@ public class SensorUpdateTasks {
|
||||||
sensor, false));
|
sensor, false));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Updates power consumption of all activated smart plugs every second */
|
||||||
|
@Scheduled(fixedDelay = 1000)
|
||||||
|
public void smartPlugConsumptionFakeUpdate() {
|
||||||
|
smartPlugRepository.updateTotalConsumption(SmartPlug.AVERAGE_CONSUMPTION_KW);
|
||||||
|
final Collection<SmartPlug> c = smartPlugRepository.findByOn(true);
|
||||||
|
c.forEach(s -> sensorSocketEndpoint.broadcast(s, sensorRepository.findUser(s.getId())));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -61,6 +61,12 @@ public class SensorSocketEndpoint extends Endpoint {
|
||||||
final Collection<Session> sessions = authorizedClients.get(u);
|
final Collection<Session> sessions = authorizedClients.get(u);
|
||||||
return sessions.stream()
|
return sessions.stream()
|
||||||
.parallel()
|
.parallel()
|
||||||
|
.filter(
|
||||||
|
s -> {
|
||||||
|
if (s.isOpen()) return true;
|
||||||
|
sessions.remove(s);
|
||||||
|
return false;
|
||||||
|
})
|
||||||
.filter(didThrow(s -> s.getBasicRemote().sendText(gson.toJson(message))))
|
.filter(didThrow(s -> s.getBasicRemote().sendText(gson.toJson(message))))
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ spring.datasource.password=
|
||||||
|
|
||||||
# Hibernate properties
|
# Hibernate properties
|
||||||
spring.jpa.database=POSTGRESQL
|
spring.jpa.database=POSTGRESQL
|
||||||
spring.jpa.show-sql=true
|
spring.jpa.show-sql=false
|
||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
|
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
|
||||||
spring.jpa.properties.hibernate.format_sql=true
|
spring.jpa.properties.hibernate.format_sql=true
|
||||||
|
|
Loading…
Reference in a new issue