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());