Skip to content

Commit

Permalink
Always send correct 'item' member in SSE events (openhab#691)
Browse files Browse the repository at this point in the history
* Make sure to always send the correct 'item' member in SSE events.

If a change to item A causes visibility changes to item B, we previously
sent an SSE event for B including the new visibility for B, but included
item and state of A. This leads to client confusion, as it'll update its
internal state for the widget belonging to B with the item state of A.
Make sure to always send the item for B and to omit state in that case.

Closes openhab#690

Signed-off-by: Danny Baumann <[email protected]>
  • Loading branch information
maniac103 authored and cweitkamp committed May 25, 2019
1 parent 0d736a7 commit 36ae918
Showing 1 changed file with 20 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ private Set<SitemapEvent> constructSitemapEvents(Item item, State state, List<Wi
events.addAll(constructSitemapEvents(item, state, itemUIRegistry.getChildren((Frame) w)));
}

boolean skipWidget = (w.getItem() == null) || !w.getItem().equals(item.getName());
boolean itemBelongsToWidget = w.getItem() != null && w.getItem().equals(item.getName());
boolean skipWidget = !itemBelongsToWidget;
// We skip the chart widgets having a refresh argument
if (!skipWidget && w instanceof Chart) {
Chart chartWidget = (Chart) w;
Expand All @@ -231,15 +232,18 @@ private Set<SitemapEvent> constructSitemapEvents(Item item, State state, List<Wi
event.valuecolor = itemUIRegistry.getValueColor(w);
event.widgetId = itemUIRegistry.getWidgetId(w);
event.visibility = itemUIRegistry.getVisiblity(w);
// event.item contains data from the item including its state (in event.item.state)
// event.item contains the (potentially changed) data of the item belonging to
// the widget including its state (in event.item.state)
final Item itemToBeSent = itemBelongsToWidget ? item : getItemForWidget(w);
String widgetTypeName = w.eClass().getInstanceTypeName()
.substring(w.eClass().getInstanceTypeName().lastIndexOf(".") + 1);
boolean drillDown = "mapview".equalsIgnoreCase(widgetTypeName);
Predicate<Item> itemFilter = (i -> i.getType().equals(CoreItemFactory.LOCATION));
event.item = EnrichedItemDTOMapper.map(item, drillDown, itemFilter, null, null);
event.item = EnrichedItemDTOMapper.map(itemToBeSent, drillDown, itemFilter, null, null);

// event.state is an adjustment of the item state to the widget type.
event.state = itemUIRegistry.convertState(w, item, state).toFullString();
final State stateToBeSent = itemBelongsToWidget ? state : itemToBeSent.getState();
event.state = itemUIRegistry.convertState(w, itemToBeSent, stateToBeSent).toFullString();
// In case this state is identical to the item state, its value is set to null.
if (event.state != null && event.state.equals(event.item.state)) {
event.state = null;
Expand All @@ -251,6 +255,18 @@ private Set<SitemapEvent> constructSitemapEvents(Item item, State state, List<Wi
return events;
}

private Item getItemForWidget(Widget w) {
final String itemName = w.getItem();
if (itemName != null) {
try {
return itemUIRegistry.getItem(itemName);
} catch (ItemNotFoundException e) {
// fall through to returning null
}
}
return null;
}

private boolean definesVisibilityOrColor(Widget w, String name) {
for (VisibilityRule rule : w.getVisibility()) {
if (name.equals(rule.getItem())) {
Expand Down

0 comments on commit 36ae918

Please sign in to comment.