Fixed propagation of device updates on automation scene application

This commit is contained in:
Claudio Maggioni (maggicl) 2020-05-02 14:53:12 +02:00
parent c3d6590507
commit 7ae7522359
7 changed files with 50 additions and 24 deletions

View file

@ -67,7 +67,7 @@ public class ButtonDimmerController
break; break;
} }
deviceService.saveAllAsOwner(buttonDimmer.getOutputs(), principal.getName(), false); deviceService.saveAllAsOwner(buttonDimmer.getOutputs(), principal.getName());
return buttonDimmer.getOutputs(); return buttonDimmer.getOutputs();
} }

View file

@ -91,7 +91,7 @@ public abstract class InputDeviceConnectionController<
connector.connect(pair.input, o, true); connector.connect(pair.input, o, true);
} }
deviceService.saveAllAsOwner(pair.outputs, username, false); deviceService.saveAllAsOwner(pair.outputs, username);
return pair.input.getOutputs(); return pair.input.getOutputs();
} }
@ -111,7 +111,7 @@ public abstract class InputDeviceConnectionController<
connector.connect(pair.input, o, false); connector.connect(pair.input, o, false);
} }
deviceService.saveAllAsOwner(pair.outputs, username, false); deviceService.saveAllAsOwner(pair.outputs, username);
return pair.input.getOutputs(); return pair.input.getOutputs();
} }

View file

@ -54,7 +54,7 @@ public class KnobDimmerController extends InputDeviceConnectionController<KnobDi
.orElseThrow(NotFoundException::new); .orElseThrow(NotFoundException::new);
dimmer.setLightIntensity(bd.getIntensity()); dimmer.setLightIntensity(bd.getIntensity());
deviceService.saveAllAsOwner(dimmer.getOutputs(), principal.getName(), false); deviceService.saveAllAsOwner(dimmer.getOutputs(), principal.getName());
return dimmer.getOutputs(); return dimmer.getOutputs();
} }

View file

@ -68,7 +68,7 @@ public class SceneController {
.findByIdAndUsername(id, principal.getName()) .findByIdAndUsername(id, principal.getName())
.orElseThrow(NotFoundException::new); .orElseThrow(NotFoundException::new);
return sceneService.apply(newScene, principal.getName()); return sceneService.apply(newScene, principal.getName(), false);
} }
@PutMapping("/{id}") @PutMapping("/{id}")

View file

@ -75,7 +75,7 @@ public class SwitchController extends InputDeviceConnectionController<Switch, Sw
} }
deviceService.saveAsOwner(s, principal.getName()); deviceService.saveAsOwner(s, principal.getName());
return deviceService.saveAllAsOwner(s.getOutputs(), principal.getName(), false); return deviceService.saveAllAsOwner(s.getOutputs(), principal.getName());
} }
@DeleteMapping("/{id}") @DeleteMapping("/{id}")

View file

@ -57,7 +57,7 @@ public class DeviceService {
sceneRepository sceneRepository
.findById(t.getSceneId()) .findById(t.getSceneId())
.orElseThrow(IllegalStateException::new)) .orElseThrow(IllegalStateException::new))
.forEach((s) -> sceneService.apply(s, username)); .forEach((s) -> sceneService.apply(s, username, true));
} }
public List<Device> findAll(Long hostId, String username) throws NotFoundException { public List<Device> findAll(Long hostId, String username) throws NotFoundException {
@ -145,7 +145,15 @@ public class DeviceService {
return device; return device;
} }
private void propagateUpdateAsOwner(Device device, String username) { /**
* Propagates the update through the socket assuming that the user that modified the device is
* the owner of that device
*
* @param device the updated device
* @param username the username of the owner of that device
* @param causedByTrigger if true, send the update to the owner as well
*/
private void propagateUpdateAsOwner(Device device, String username, boolean causedByTrigger) {
final User user = userRepository.findByUsername(username); final User user = userRepository.findByUsername(username);
final Set<User> guests = user.getGuests(); final Set<User> guests = user.getGuests();
// make sure we're broadcasting from host // make sure we're broadcasting from host
@ -155,13 +163,33 @@ public class DeviceService {
// broadcast to endpoint the object device, with receiving user set to guest // broadcast to endpoint the object device, with receiving user set to guest
endpoint.queueDeviceUpdate(device, guest); endpoint.queueDeviceUpdate(device, guest);
} }
if (causedByTrigger) {
endpoint.queueDeviceUpdate(device, user);
}
} }
/**
* Saves all the devices given in devices assuming that the owner updated them in one way or
* another. Takes care of the appropriate websocket updates and trigger checking as well. No
* checking is done to verify that the user whose username is given is in fact the owner of
* these devices
*
* @param devices the list of devices to save
* @param username the username of the owner of these devices
* @param fromScene true if the update comes from the a scene application side effect. Disables
* trigger checking to avoid recursive invocations of automations
* @param fromTrigger true if the update comes from a scene application executed by an
* automation. Propagates updated through socket to owner as well. No effect if fromScene is
* false.
* @param <T> the type of device contained in the list
* @return the updated list of devices, ready to be fed to GSON
*/
public <T extends Device> List<T> saveAllAsOwner( public <T extends Device> List<T> saveAllAsOwner(
Iterable<T> devices, String username, boolean fromScene) { Iterable<T> devices, String username, boolean fromScene, boolean fromTrigger) {
devices.forEach(d -> renameIfDuplicate(d, username)); devices.forEach(d -> renameIfDuplicate(d, username));
devices = deviceRepository.saveAll(devices); devices = deviceRepository.saveAll(devices);
devices.forEach((d) -> propagateUpdateAsOwner(d, username)); devices.forEach((d) -> propagateUpdateAsOwner(d, username, fromScene && fromTrigger));
if (!fromScene) { if (!fromScene) {
devices.forEach((d) -> triggerTriggers(d, username)); devices.forEach((d) -> triggerTriggers(d, username));
@ -170,20 +198,18 @@ public class DeviceService {
return toList(devices); return toList(devices);
} }
public <T extends Device> T saveAsOwner(T device, String username, boolean fromScene) { public <T extends Device> List<T> saveAllAsOwner(Iterable<T> devices, String username) {
renameIfDuplicate(device, username); return saveAllAsOwner(devices, username, false, false);
device = deviceRepository.save(device);
propagateUpdateAsOwner(device, username);
if (!fromScene) {
triggerTriggers(device, username);
}
return device;
} }
public <T extends Device> T saveAsOwner(T device, String username) { public <T extends Device> T saveAsOwner(T device, String username) {
return saveAsOwner(device, username, false); renameIfDuplicate(device, username);
device = deviceRepository.save(device);
propagateUpdateAsOwner(device, username, false);
triggerTriggers(device, username);
return device;
} }
public void delete(Long id, String username) throws NotFoundException { public void delete(Long id, String username) throws NotFoundException {
@ -193,6 +219,6 @@ public class DeviceService {
.orElseThrow(NotFoundException::new); .orElseThrow(NotFoundException::new);
deviceRepository.delete(device); deviceRepository.delete(device);
propagateUpdateAsOwner(device, username); propagateUpdateAsOwner(device, username, false);
} }
} }

View file

@ -15,14 +15,14 @@ public class SceneService {
@Autowired private DeviceRepository<Device> deviceRepository; @Autowired private DeviceRepository<Device> deviceRepository;
@Autowired private DeviceService deviceService; @Autowired private DeviceService deviceService;
public List<Device> apply(Scene newScene, String username) { public List<Device> apply(Scene newScene, String username, boolean fromTrigger) {
final List<Device> updated = new ArrayList<>(); final List<Device> updated = new ArrayList<>();
for (final State<?> s : newScene.getStates()) { for (final State<?> s : newScene.getStates()) {
s.apply(); s.apply();
updated.add(s.getDevice()); updated.add(s.getDevice());
} }
deviceService.saveAllAsOwner(updated, username, true); deviceService.saveAllAsOwner(updated, username, true, fromTrigger);
deviceService.populateComputedFields(updated); deviceService.populateComputedFields(updated);
return updated; return updated;
} }