-
-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[expiry] extend ExpiryManager to allow ignoring state updates #2739
Changes from 6 commits
3c75ae2
f597110
1a84c89
bf43121
9d7962d
fb5dff9
f7e4a72
c70c5c9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,7 @@ | |
import org.openhab.core.items.events.GroupItemStateChangedEvent; | ||
import org.openhab.core.items.events.ItemCommandEvent; | ||
import org.openhab.core.items.events.ItemEventFactory; | ||
import org.openhab.core.items.events.ItemStateChangedEvent; | ||
import org.openhab.core.items.events.ItemStateEvent; | ||
import org.openhab.core.library.types.StringType; | ||
import org.openhab.core.types.Command; | ||
|
@@ -72,15 +73,15 @@ public class ExpireManager implements EventSubscriber, RegistryChangeListener<It | |
protected static final String METADATA_NAMESPACE = "expire"; | ||
protected static final String PROPERTY_ENABLED = "enabled"; | ||
|
||
private static final Set<String> SUBSCRIBED_EVENT_TYPES = Set.of(ItemStateEvent.TYPE, ItemCommandEvent.TYPE, | ||
GroupItemStateChangedEvent.TYPE); | ||
private static final Set<String> SUBSCRIBED_EVENT_TYPES = Set.of(ItemStateEvent.TYPE, ItemStateChangedEvent.TYPE, | ||
ItemCommandEvent.TYPE, GroupItemStateChangedEvent.TYPE); | ||
|
||
private final Logger logger = LoggerFactory.getLogger(ExpireManager.class); | ||
|
||
private Map<String, @Nullable Optional<ExpireConfig>> itemExpireConfig = new ConcurrentHashMap<>(); | ||
private Map<String, Instant> itemExpireMap = new ConcurrentHashMap<>(); | ||
private final Map<String, @Nullable Optional<ExpireConfig>> itemExpireConfig = new ConcurrentHashMap<>(); | ||
private final Map<String, Instant> itemExpireMap = new ConcurrentHashMap<>(); | ||
|
||
private ScheduledExecutorService threadPool = ThreadPoolManager | ||
private final ScheduledExecutorService threadPool = ThreadPoolManager | ||
.getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON); | ||
|
||
private final EventPublisher eventPublisher; | ||
|
@@ -140,10 +141,13 @@ protected void deactivate() { | |
itemExpireMap.clear(); | ||
} | ||
|
||
private void processEvent(String itemName, Type type) { | ||
logger.trace("Received '{}' for item {}", type, itemName); | ||
private void processEvent(String itemName, Type type, boolean isStateUpdate) { | ||
logger.trace("Received '{}' for item {}, state update = {}", type, itemName, isStateUpdate); | ||
ExpireConfig expireConfig = getExpireConfig(itemName); | ||
if (expireConfig != null) { | ||
if (isStateUpdate && expireConfig.ignoreStateUpdates) { | ||
return; | ||
} | ||
Command expireCommand = expireConfig.expireCommand; | ||
State expireState = expireConfig.expireState; | ||
|
||
|
@@ -166,7 +170,7 @@ private void processEvent(String itemName, Type type) { | |
private @Nullable ExpireConfig getExpireConfig(String itemName) { | ||
Optional<ExpireConfig> itemConfig = itemExpireConfig.get(itemName); | ||
if (itemConfig != null) { | ||
return itemConfig.isPresent() ? itemConfig.get() : null; | ||
return itemConfig.orElse(null); | ||
} else { | ||
Metadata metadata = metadataRegistry.get(new MetadataKey(METADATA_NAMESPACE, itemName)); | ||
if (metadata != null) { | ||
|
@@ -240,13 +244,13 @@ public void receive(Event event) { | |
} | ||
if (event instanceof ItemStateEvent) { | ||
ItemStateEvent isEvent = (ItemStateEvent) event; | ||
processEvent(isEvent.getItemName(), isEvent.getItemState()); | ||
processEvent(isEvent.getItemName(), isEvent.getItemState(), true); | ||
} else if (event instanceof ItemCommandEvent) { | ||
ItemCommandEvent icEvent = (ItemCommandEvent) event; | ||
processEvent(icEvent.getItemName(), icEvent.getItemCommand()); | ||
} else if (event instanceof GroupItemStateChangedEvent) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a specific reason to remove this? I can see a use case for the expire functionality on a group (e.g. to turn off all lights in a group if they stay on for too long). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
GroupItemStateChangedEvent gcEvent = (GroupItemStateChangedEvent) event; | ||
processEvent(gcEvent.getItemName(), gcEvent.getItemState()); | ||
processEvent(icEvent.getItemName(), icEvent.getItemCommand(), false); | ||
} else if (event instanceof ItemStateChangedEvent) { | ||
ItemStateChangedEvent icEvent = (ItemStateChangedEvent) event; | ||
processEvent(icEvent.getItemName(), icEvent.getItemState(), false); | ||
} | ||
} | ||
|
||
|
@@ -296,19 +300,18 @@ static class ExpireConfig { | |
protected static final Pattern DURATION_PATTERN = Pattern | ||
.compile("(?:([0-9]+)H)?\\s*(?:([0-9]+)M)?\\s*(?:([0-9]+)S)?", Pattern.CASE_INSENSITIVE); | ||
|
||
@Nullable | ||
final Command expireCommand; | ||
@Nullable | ||
final State expireState; | ||
final @Nullable Command expireCommand; | ||
final @Nullable State expireState; | ||
final String durationString; | ||
final Duration duration; | ||
final boolean ignoreStateUpdates; | ||
|
||
/** | ||
* Construct an ExpireConfig from the config string. | ||
* | ||
* Valid syntax: | ||
* | ||
* {@code <duration>[,[state=|command=|]<stateOrCommand>]}<br> | ||
* {@code <duration>[,(state=|command=|)<stateOrCommand>][,ignoreStateUpdates]}<br> | ||
* if neither state= or command= is present, assume state | ||
* | ||
* @param item the item to which we are bound | ||
|
@@ -325,6 +328,16 @@ public ExpireConfig(Item item, String configString) throws IllegalArgumentExcept | |
? configString.substring(commaPos + 1).trim() | ||
: null; | ||
|
||
if (stateOrCommand != null && stateOrCommand.endsWith(",ignoreStateUpdates")) { | ||
stateOrCommand = stateOrCommand.substring(0, stateOrCommand.lastIndexOf(",")); | ||
ignoreStateUpdates = true; | ||
} else if ("ignoreStateUpdates".equals(stateOrCommand)) { | ||
stateOrCommand = null; | ||
ignoreStateUpdates = true; | ||
} else { | ||
ignoreStateUpdates = false; | ||
} | ||
|
||
if ((stateOrCommand != null) && (stateOrCommand.length() > 0)) { | ||
if (stateOrCommand.startsWith(COMMAND_PREFIX)) { | ||
String commandString = stateOrCommand.substring(COMMAND_PREFIX.length()); | ||
|
@@ -384,7 +397,7 @@ private Duration parseDuration(String durationString) throws IllegalArgumentExce | |
@Override | ||
public String toString() { | ||
return "duration='" + durationString + "', s=" + duration.toSeconds() + ", state='" + expireState | ||
+ "', command='" + expireCommand + "'"; | ||
+ "', command='" + expireCommand + "', ignoreStateUpdates=" + ignoreStateUpdates; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return itemConfig.get() may be enough. You should remove the Nullable annotation on the itemExpireConfig map value. As it is a ConcurrentHashMap, null values are not allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mistake on my side, you do need the code you put in, but you can still remove the @nullable annotation from the declaration.