Merge branch 'automations-fix-2' into 'dev'

Fixed propagation of device updates on automation scene application

See merge request sa4-2020/the-sanmarinoes/backend!107
This commit is contained in:
Claudio Maggioni 2020-05-02 14:57:13 +02:00
commit e8a3480add
7 changed files with 50 additions and 24 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -57,7 +57,7 @@ public class DeviceService {
sceneRepository
.findById(t.getSceneId())
.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 {
@ -145,7 +145,15 @@ public class DeviceService {
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 Set<User> guests = user.getGuests();
// 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
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(
Iterable<T> devices, String username, boolean fromScene) {
Iterable<T> devices, String username, boolean fromScene, boolean fromTrigger) {
devices.forEach(d -> renameIfDuplicate(d, username));
devices = deviceRepository.saveAll(devices);
devices.forEach((d) -> propagateUpdateAsOwner(d, username));
devices.forEach((d) -> propagateUpdateAsOwner(d, username, fromScene && fromTrigger));
if (!fromScene) {
devices.forEach((d) -> triggerTriggers(d, username));
@ -170,20 +198,18 @@ public class DeviceService {
return toList(devices);
}
public <T extends Device> T saveAsOwner(T device, String username, boolean fromScene) {
renameIfDuplicate(device, username);
device = deviceRepository.save(device);
propagateUpdateAsOwner(device, username);
if (!fromScene) {
triggerTriggers(device, username);
}
return device;
public <T extends Device> List<T> saveAllAsOwner(Iterable<T> devices, String username) {
return saveAllAsOwner(devices, username, false, false);
}
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 {
@ -193,6 +219,6 @@ public class DeviceService {
.orElseThrow(NotFoundException::new);
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 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<>();
for (final State<?> s : newScene.getStates()) {
s.apply();
updated.add(s.getDevice());
}
deviceService.saveAllAsOwner(updated, username, true);
deviceService.saveAllAsOwner(updated, username, true, fromTrigger);
deviceService.populateComputedFields(updated);
return updated;
}