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 397bb1e..d2231d8 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 @@ -71,14 +71,18 @@ public abstract class Device { @SocketGsonExclude private Set> states = new HashSet<>(); - @Transient @GsonExclude private boolean fromHost = false; + @Transient @GsonExclude private Long fromHostId = null; @Transient @GsonExclude private boolean fromGuest = false; @Transient @GsonExclude private boolean deleted = false; - public boolean isFromHost() { - return fromHost; + public Long getFromHostId() { + return fromHostId; + } + + public void setFromHostId(Long fromHostId) { + this.fromHostId = fromHostId; } public boolean isDeleted() { @@ -97,10 +101,6 @@ public abstract class Device { this.fromGuest = fromGuest; } - public void setFromHost(boolean fromHost) { - this.fromHost = fromHost; - } - public long getId() { return id; } 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 e701166..ec0f43f 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 @@ -78,7 +78,7 @@ public class UpdateTasks { c.forEach( s -> sensorSocketEndpoint.queueDeviceUpdate( - s, sensorRepository.findUser(s.getId()))); + s, sensorRepository.findUser(s.getId()), false, null, false)); } /** Sends device updates through sensor socket in batch every one second */ 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 b4bde1b..a0116c2 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 @@ -125,21 +125,17 @@ public class DeviceService { // We're telling the host that a guest has modified a device. Therefore, fromGuest becomes // true. - device.setFromHost(false); - device.setFromGuest(true); // broadcast device update to host - endpoint.queueDeviceUpdate(device, host); + endpoint.queueDeviceUpdate(device, host, true, null, false); // We're telling all guests that a higher entity has issued a device update. Therefore, // fromHost becomes true. - device.setFromHost(true); - device.setFromGuest(false); for (final User guest : guests) { if (guest.equals(currentUser)) { continue; } // enqueue all device updates for all other guests - endpoint.queueDeviceUpdate(device, guest); + endpoint.queueDeviceUpdate(device, guest, false, host.getId(), false); } return device; @@ -157,15 +153,13 @@ public class DeviceService { final User user = userRepository.findByUsername(username); final Set guests = user.getGuests(); // make sure we're broadcasting from host - device.setFromHost(true); - device.setFromGuest(false); for (final User guest : guests) { // broadcast to endpoint the object device, with receiving user set to guest - endpoint.queueDeviceUpdate(device, guest); + endpoint.queueDeviceUpdate(device, guest, false, user.getId(), false); } if (causedByTrigger) { - endpoint.queueDeviceUpdate(device, user); + endpoint.queueDeviceUpdate(device, user, false, user.getId(), false); } } diff --git a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/MotionSensorService.java b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/MotionSensorService.java index 01a7401..f4288ee 100644 --- a/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/MotionSensorService.java +++ b/src/main/java/ch/usi/inf/sa4/sanmarinoes/smarthut/service/MotionSensorService.java @@ -14,7 +14,7 @@ public class MotionSensorService { @Autowired private MotionSensorRepository motionSensorRepository; /** - * Updates detection status of given motion sensor and propagates update throgh socket + * Updates detection status of given motion sensor and propagates update through socket * * @param sensor the motion sensor to update * @param detected the new detection status @@ -26,7 +26,7 @@ public class MotionSensorService { final MotionSensor toReturn = deviceService.saveAsOwner(sensor, username); sensorSocketEndpoint.queueDeviceUpdate( - sensor, motionSensorRepository.findUser(sensor.getId())); + sensor, motionSensorRepository.findUser(sensor.getId()), false, null, false); return toReturn; } 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 index 0e4fbbd..532442b 100644 --- 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 @@ -43,7 +43,8 @@ public class SensorService { sensor = deviceService.saveAsOwner( sensor, sensorRepository.findUser(sensor.getId()).getUsername()); - endpoint.queueDeviceUpdate(sensor, sensorRepository.findUser(sensor.getId())); + endpoint.queueDeviceUpdate( + sensor, sensorRepository.findUser(sensor.getId()), false, null, false); return sensor; } } 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 index 91d0b18..328d092 100644 --- 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 @@ -54,7 +54,7 @@ public class ThermostatService { this.computeState(t); deviceService.saveAsOwner(t, thermostatRepository.findUser(t.getId()).getUsername()); - endpoint.queueDeviceUpdate(t, thermostatRepository.findUser(t.getId())); + endpoint.queueDeviceUpdate(t, thermostatRepository.findUser(t.getId()), false, null, false); } public void updateStates() { 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 b68cb25..4764f18 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 @@ -5,6 +5,7 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.config.JWTTokenUtils; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Device; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.User; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.UserRepository; +import ch.usi.inf.sa4.sanmarinoes.smarthut.service.DeviceService; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Multimaps; @@ -21,6 +22,8 @@ public class SensorSocketEndpoint extends Endpoint { private Gson gson = GsonConfig.socketGson(); + @Autowired private DeviceService deviceService; + private UserRepository userRepository; private JWTTokenUtils jwtTokenUtils; @@ -28,7 +31,10 @@ public class SensorSocketEndpoint extends Endpoint { private Multimap authorizedClients = Multimaps.synchronizedMultimap(HashMultimap.create()); - private final Map> messages = new HashMap<>(); + // messages are now stored as strings as a "hack" to capture and clone the state of the device, + // since + // fromHost and fromGuest are just mutable properties and hibernate caches the object. + private final Map> messages = new HashMap<>(); @Autowired public SensorSocketEndpoint(UserRepository userRepository, JWTTokenUtils jwtTokenUtils) { @@ -41,18 +47,33 @@ public class SensorSocketEndpoint extends Endpoint { * * @param device the device update to be sent * @param u the user the device belongs + * @param fromGuest value for device.fromGuest. This will be put in the device passed. + * @param fromHostId value for device.fromHostId. This will be put in the device passed. + * @param deleted value for device.deleted. This will be put in the device passed. */ - public void queueDeviceUpdate(Device device, User u) { + public void queueDeviceUpdate( + Device device, User u, boolean fromGuest, Long fromHostId, boolean deleted) { synchronized (messages) { + device.setFromGuest(fromGuest); + device.setFromHostId(fromHostId); + device.setDeleted(deleted); + + // sort of an hack: force the population of thermostat measureTemperature and other + // possible + // computed fields in the future. This should already be done by the callers of this + // method but for + // whatever reason they don't do it. + deviceService.populateComputedFields(List.of(device)); + messages.putIfAbsent(u, new HashMap<>()); - messages.get(u).put(device.getId(), device); + messages.get(u).put(device.getId(), gson.toJson(device)); } } /** Sends all device updates queued to be sent in a unique WebSocket message */ public void flushDeviceUpdates() { synchronized (messages) { - for (Map.Entry> batchForUser : messages.entrySet()) { + for (Map.Entry> batchForUser : messages.entrySet()) { broadcast(batchForUser.getKey(), batchForUser.getValue().values()); batchForUser.getValue().clear(); } @@ -66,13 +87,13 @@ public class SensorSocketEndpoint extends Endpoint { * @param messages the message batch to send * @param u the user to which to send the message */ - private void broadcast(User u, Collection messages) { + private void broadcast(User u, Collection messages) { if (messages.isEmpty()) return; final HashSet sessions = new HashSet<>(authorizedClients.get(u)); for (Session s : sessions) { try { if (s.isOpen()) { - s.getBasicRemote().sendText(gson.toJson(messages)); + s.getBasicRemote().sendText("[" + String.join(",", messages) + "]"); } else { authorizedClients.remove(u, s); }