Module: OpenHAB::DSL::Items::TimedCommand
- Included in:
- Core::Items::GenericItem, Core::Items::GroupItem
- Defined in:
- lib/openhab/dsl/items/timed_command.rb
Overview
Extensions for Item to implement timed commands
All items have an implicit timer associated with them, enabling to easily set an item into a specific state for a specified duration and then at the expiration of that duration have the item automatically change to another state. These timed commands are reentrant, meaning if the same timed command is triggered while an outstanding timed command exist, that timed command will be rescheduled rather than creating a distinct timed command.
Timed commands are initiated by using the 'for:' argument with the command. This is available on both the 'command' method and any command-specific methods, e.g. Core::Items::SwitchItem#on.
The timer will be cancelled, and the item's state will not be changed to the on_expire state if:
- The item receives any command within the timed command duration.
- The item is updated to a different state, even if it is then updated back to the same state.
For example, if you have a Switch on a timer and another rule sends a command to that item, even when it's commanded to the same state, the timer will be automatically canceled.
Sending a different duration (for:) value for the timed command will reschedule the timed command for that new duration.
Defined Under Namespace
Classes: TimedCommandDetails
Instance Method Summary collapse
-
#command(command, for: nil, on_expire: nil, only_when_ensured: false) {|timed_command| ... } ⇒ self
Sends command to an item for specified duration, then on timer expiration sends the expiration command to the item.
Instance Method Details
#command(command, for: nil, on_expire: nil, only_when_ensured: false) {|timed_command| ... } ⇒ self
If a block is provided, and the timer is canceled because the item changed state while it was waiting, the block will still be executed. The timed command can be reinstated by calling #resume or #reschedule.
If the timer expired, the timed command can be rescheduled from inside the block by calling #reschedule.
Be sure to check #expired? and/or #cancelled? to determine why the block was called.
Sends command to an item for specified duration, then on timer expiration sends the expiration command to the item
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/openhab/dsl/items/timed_command.rb', line 152 def command(command, for: nil, on_expire: nil, only_when_ensured: false, &block) duration = binding.local_variable_get(:for) return super(command) unless duration on_expire = block if block create_ensured_timed_command = proc do on_expire ||= default_on_expire(command) if only_when_ensured DSL.ensure_states do create_timed_command(command, duration: duration, on_expire: on_expire) if super(command) end else super(command) create_timed_command(command, duration: duration, on_expire: on_expire) end end TimedCommand.timed_commands.compute(self) do |_key, timed_command_details| if timed_command_details.nil? # no prior timed command create_ensured_timed_command.call else timed_command_details.mutex.synchronize do if timed_command_details.resolution # timed command that finished, but hadn't removed itself from the map yet # (it doesn't do so under the mutex to prevent a deadlock). # just create a new one create_ensured_timed_command.call else # timed command still pending; reset it logger.trace "Outstanding Timed Command #{timed_command_details} encountered - rescheduling" timed_command_details.on_expire = on_expire unless on_expire.nil? timed_command_details.timer.reschedule(duration) # disable the cancel rule while we send the new command DSL.rules[timed_command_details.rule_uid].disable super(command) # This returns nil when "ensured" DSL.rules[timed_command_details.rule_uid].enable timed_command_details end end end end self end |