From 5a441a69925ee8b7bfebc0a828b7d84dbbf6b459 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Sun, 15 Mar 2020 13:41:57 +0100 Subject: [PATCH] Socket now sends sensor updates --- socket_test.html | 4 +++ .../smarthut/config/GsonConfig.java | 2 +- .../smarthut/controller/SensorController.java | 27 +++++++++++++++++++ .../smarthut/dto/SensorSaveRequest.java | 11 ++++++++ .../sanmarinoes/smarthut/models/Device.java | 6 +++++ .../smarthut/models/DeviceRepository.java | 21 +++++++++++++++ .../sa4/sanmarinoes/smarthut/models/Room.java | 6 +++++ .../sanmarinoes/smarthut/models/Sensor.java | 23 +++++++++++----- .../sa4/sanmarinoes/smarthut/models/User.java | 19 +++++++++++++ .../socket/AuthenticationMessageListener.java | 3 ++- .../smarthut/socket/SensorSocketEndpoint.java | 6 +++-- .../sa4/sanmarinoes/smarthut/utils/Utils.java | 12 ++++++--- 12 files changed, 126 insertions(+), 14 deletions(-) diff --git a/socket_test.html b/socket_test.html index 90feba2..687388b 100644 --- a/socket_test.html +++ b/socket_test.html @@ -1,3 +1,5 @@ + + @@ -25,6 +27,8 @@ connection.onmessage = function(evt) { ""; } else if (data.authenticated === false) { malusa.innerHTML = "

Authentication error

"; + } else { + malusa.innerHTML += "

" + JSON.stringify(JSON.parse(evt.data), null, 2) + "

"; } }; 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 e12d9f0..69c4fc9 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 @@ -20,7 +20,7 @@ public class GsonConfig { return converter; } - private Gson gson() { + public static Gson gson() { final GsonBuilder builder = new GsonBuilder(); builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter()); builder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy()); 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 3412e0c..400d06f 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,6 +5,9 @@ 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.socket.SensorSocketEndpoint; +import java.math.BigDecimal; +import java.security.Principal; import java.util.*; import java.util.List; import javax.validation.Valid; @@ -19,6 +22,8 @@ public class SensorController { @Autowired private SensorRepository sensorRepository; + @Autowired private SensorSocketEndpoint sensorSocketEndpoint; + @GetMapping public List findAll() { return toList(sensorRepository.findAll()); @@ -35,10 +40,32 @@ public class SensorController { newSensor.setSensor(s.getSensor()); newSensor.setName(s.getName()); newSensor.setRoomId(s.getRoomId()); + newSensor.setValue(s.getValue()); return sensorRepository.save(newSensor); } + @PutMapping("/{id}/value") + public Sensor updateValue( + @PathVariable("id") Long sensorId, + @RequestParam("value") BigDecimal value, + final Principal principal) + throws NotFoundException { + + final Sensor sensor = + sensorRepository + .findByIdAndUsername(sensorId, principal.getName()) + .orElseThrow(NotFoundException::new); + sensor.setValue(value); + final Sensor toReturn = sensorRepository.save(sensor); + + System.out.println("sensor: " + sensor); + + sensorSocketEndpoint.broadcast(sensor, sensorRepository.findUser(sensorId)); + + return toReturn; + } + @DeleteMapping("/{id}") public void deleteById(@PathVariable("id") long id) { sensorRepository.deleteById(id); diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/SensorSaveRequest.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/SensorSaveRequest.java index e9a5c68..62b0b5e 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/SensorSaveRequest.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/dto/SensorSaveRequest.java @@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.dto; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Sensor; import com.google.gson.annotations.SerializedName; +import java.math.BigDecimal; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.validation.constraints.NotNull; @@ -28,6 +29,8 @@ public class SensorSaveRequest { @Enumerated(value = EnumType.STRING) private Sensor.SensorType sensor; + @NotNull private BigDecimal value; + /** * The room this device belongs in, as a foreign key id. To use when updating and inserting from * a REST call. @@ -60,4 +63,12 @@ public class SensorSaveRequest { public void setSensor(Sensor.SensorType sensor) { this.sensor = sensor; } + + public BigDecimal getValue() { + return value; + } + + public void setValue(BigDecimal value) { + this.value = value; + } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java index e8a621b..c564914 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Device.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude; import com.google.gson.annotations.SerializedName; import io.swagger.annotations.ApiModelProperty; import javax.persistence.*; @@ -26,6 +27,11 @@ public abstract class Device { @ApiModelProperty(hidden = true) private long id; + @ManyToOne + @JoinColumn(name = "room_id", updatable = false, insertable = false) + @GsonExclude + private Room room; + /** * The room this device belongs in, as a foreign key id. To use when updating and inserting from * a REST call. diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DeviceRepository.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DeviceRepository.java index fdae66e..b90639b 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DeviceRepository.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/DeviceRepository.java @@ -1,6 +1,8 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import java.util.List; +import java.util.Optional; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; @@ -10,4 +12,23 @@ import org.springframework.data.repository.query.Param; */ public interface DeviceRepository extends CrudRepository { List findByRoomId(@Param("roomId") long roomId); + + /** + * Finds devices by their id and a username + * + * @param id the device id + * @param username a User's username + * @return an optional device, empty if none found + */ + @Query("SELECT d FROM Device d JOIN d.room r JOIN r.user u WHERE d.id = ?1 AND u.username = ?2") + Optional findByIdAndUsername(Long id, String username); + + /** + * Find the user associated with a device through a room + * + * @param deviceId the device id + * @return a user object + */ + @Query("SELECT u FROM Device d JOIN d.room r JOIN r.user u WHERE d.id = ?1") + User findUser(Long deviceId); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java index e54b462..68c3fc0 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Room.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; +import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude; import com.google.gson.annotations.SerializedName; import io.swagger.annotations.ApiModelProperty; import javax.persistence.*; @@ -128,6 +129,11 @@ public class Room { @Column(name = "image", columnDefinition = "TEXT") private String image; + @ManyToOne + @JoinColumn(name = "user_id", updatable = false, insertable = false) + @GsonExclude + private User user; + /** * User that owns the house this room is in as a foreign key id. To use when updating and * inserting from a REST call. diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Sensor.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Sensor.java index b1d98a2..6dd634a 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Sensor.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/Sensor.java @@ -1,6 +1,8 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import com.google.gson.annotations.SerializedName; +import java.math.BigDecimal; +import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -11,6 +13,12 @@ import javax.validation.constraints.NotNull; @Entity public class Sensor extends InputDevice { + private static final Map TYPICAL_VALUES = + Map.of( + SensorType.TEMPERATURE, 17, + SensorType.HUMIDITY, 40, + SensorType.LIGHT, 1000); + /** Type of sensor, i.e. of the thing the sensor measures. */ public enum SensorType { /** A sensor that measures temperature in degrees celsius */ @@ -27,8 +35,8 @@ public class Sensor extends InputDevice { } /** The value of this sensor according to its sensor type */ - @Column(nullable = false) - private int value; + @Column(nullable = false, length = 10, precision = 1) + private BigDecimal value; /** The type of this sensor */ @Column(nullable = false) @@ -42,19 +50,22 @@ public class Sensor extends InputDevice { public void setSensor(SensorType sensor) { this.sensor = sensor; - - // TODO: setup hook for sockets live update } - public int getValue() { + public BigDecimal getValue() { return this.value; } - public void setValue(int newValue) { + public void setValue(BigDecimal newValue) { this.value = newValue; } public Sensor() { super("sensor"); } + + @Override + public String toString() { + return "Sensor{" + "value=" + value + ", sensor=" + sensor + '}'; + } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java index f1b88ca..dc6766d 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/models/User.java @@ -1,6 +1,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models; import io.swagger.annotations.ApiModelProperty; +import java.util.Objects; import javax.persistence.*; /** A user of the Smarthut application */ @@ -105,4 +106,22 @@ public class User { + isEnabled + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return id.equals(user.id) + && name.equals(user.name) + && username.equals(user.username) + && password.equals(user.password) + && email.equals(user.email) + && isEnabled.equals(user.isEnabled); + } + + @Override + public int hashCode() { + return Objects.hash(id, name, username, password, email, isEnabled); + } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java index e0b9249..e3d97ea 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/socket/AuthenticationMessageListener.java @@ -1,5 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.socket; +import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonConfig; import ch.usi.inf.sa4.sanmarinoes.smarthut.config.JWTTokenUtils; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; @@ -18,7 +19,7 @@ import org.springframework.stereotype.Component; @Component public class AuthenticationMessageListener { - private Gson gson = new Gson(); + private Gson gson = GsonConfig.gson(); private JWTTokenUtils jwtTokenUtils; 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 d40e874..ee7ff56 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 @@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.socket; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.didThrow; +import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonConfig; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; @@ -16,7 +17,7 @@ import org.springframework.stereotype.Component; @Component public class SensorSocketEndpoint extends Endpoint { - private Gson gson = new Gson(); + private Gson gson = GsonConfig.gson(); private AuthenticationMessageListener authenticationMessageListener; @@ -58,9 +59,10 @@ public class SensorSocketEndpoint extends Endpoint { */ public long broadcast(Object message, User u) { final Collection sessions = authorizedClients.get(u); + System.out.println(authorizedClients + " " + sessions + " " + u); return sessions.stream() .parallel() - .filter(didThrow(s -> s.getAsyncRemote().sendObject(gson.toJson(message)))) + .filter(didThrow(s -> s.getBasicRemote().sendText(gson.toJson(message)))) .count(); } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/utils/Utils.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/utils/Utils.java index bc8719d..3f24d4c 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/utils/Utils.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/utils/Utils.java @@ -1,8 +1,6 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.utils; import java.util.List; -import java.util.concurrent.Future; -import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -11,14 +9,20 @@ import java.util.stream.StreamSupport; public final class Utils { private Utils() {} + @FunctionalInterface + public interface ConsumerWithException { + void apply(T input) throws Throwable; + } + public static List toList(Iterable iterable) { return StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); } - public static Predicate didThrow(Function> consumer) { + public static Predicate didThrow(ConsumerWithException consumer) { return (t) -> { try { - consumer.apply(t).get(); + consumer.apply(t); + System.out.println("successful"); return true; } catch (Throwable e) { System.err.println(e.getMessage());