openhab-scripting 5.21.0 → 5.22.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 756e126e160f646932df226702f4174537f335211766d9eba33c2d44cf1c1c70
4
- data.tar.gz: 6afda8cddcc7a0fd916fe061a2eb2dab4621d46cdcef75138b4c524db05b669d
3
+ metadata.gz: b2c5b8b2a28cbbda196f66340982141af673362693181e88588e89f9c4b1da29
4
+ data.tar.gz: 6a0483d0d94ae2a9492870e8089efd0b2a1afc400337d790a271b6fd9ca05ae3
5
5
  SHA512:
6
- metadata.gz: c57f40667e47bacb3c2a2cc62f6fce829413cf832502e1f743cb82fbbc0e5a962800907b27261bea5513020612a8f7652378a7817aa6b0d924c88220ccca7328
7
- data.tar.gz: 769878c8db809e0ed1815605551fc964de147329209e89517cab012a782b84e8a21e46fa445f3167723eea4f2454bd290a767991e39cfdb6495c742c874d295e
6
+ metadata.gz: 2115e707e47980b212827203b1401aeceb90c3c11fd0b8e91494581f12e728f4bc68d46c7f3b2991ff63a6f3db68ee45eb0b617e1a94ae642f6b2267de797f8c
7
+ data.tar.gz: ba2fd9524d6387287cbde50a8ff6cbc449069889836ced9e5b8cb79d8c7e3a4fe029804387d4866fed7b56b79e6aaba1584180fadc61d424555e0c755666cbbd
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Actions
6
+ #
7
+ # Provides methods for {https://next.openhab.org/addons/integrations/openhabcloud/#cloud-notification-actions
8
+ # openHAB Cloud Notification Actions}.
9
+ #
10
+ class Notification
11
+ class << self
12
+ #
13
+ # Send a notification using
14
+ # {https://next.openhab.org/addons/integrations/openhabcloud/#cloud-notification-actions
15
+ # openHAB Cloud Notification Action}.
16
+ #
17
+ # @param msg [String] The message to send.
18
+ # @param email [String, nil] The email address to send to. If `nil`, the message will be broadcasted.
19
+ # @param icon [String, Symbol, nil] The icon name
20
+ # (as described in {https://www.openhab.org/docs/configuration/items.html#icons Items}).
21
+ # @param tag [String, Symbol, nil] a name to group the type or severity of the notification.
22
+ # @param severity [String, Symbol, nil] Deprecated - an alias for `tag` for backwards compatibility.
23
+ # @param title [String, nil] The title of the notification.
24
+ # When `nil`, it defaults to `openHAB` inside the Android and iOS apps.
25
+ # @param id [String, nil] An optional reference ID which can then be used
26
+ # to {hide} or update the notification.
27
+ # Subsequent notifications using the same reference ID will
28
+ # update/overwrite the existing notification with the same ID.
29
+ # @param on_click [String, nil] The action to be performed when the user clicks on the notification.
30
+ # Specified using the {https://next.openhab.org/addons/integrations/openhabcloud/#action-syntax
31
+ # action syntax}.
32
+ # @param attachment [String, nil] The URL of the media attachment to be displayed with the notification.
33
+ # This URL must be reachable by the push notification client.
34
+ # @param buttons [Array<String>, Hash<String, String>, nil] Buttons to include in the notification.
35
+ # - In array form, each element is specified as `Title=$action`, where `$action` follows the
36
+ # {https://next.openhab.org/addons/integrations/openhabcloud/#action-syntax action syntax}.
37
+ # - In hash form, the keys are the button titles and the values are the actions.
38
+ #
39
+ # The maximum number of buttons is 3.
40
+ # @return [void]
41
+ #
42
+ # @note The parameters `title`, `id`, `on_click`, `attachment`, and `buttons` were added in openHAB 4.2.
43
+ #
44
+ # @see https://www.openhab.org/addons/integrations/openhabcloud/
45
+ #
46
+ # @example Send a broadcast notification via openHAB Cloud
47
+ # rule "Send an alert" do
48
+ # changed Alarm_Triggered, to: ON
49
+ # run { Notification.send "Red Alert!" }
50
+ # end
51
+ #
52
+ # @example Provide action buttons in a notification
53
+ # rule "Doorbell" do
54
+ # changed Doorbell, to: ON
55
+ # run do
56
+ # Notification.send "Someone pressed the doorbell!",
57
+ # title: "Doorbell",
58
+ # attachment: "http://myserver.local/cameras/frontdoor.jpg",
59
+ # buttons: {
60
+ # "Show Camera" => "ui:/basicui/app?w=0001&sitemap=cameras",
61
+ # "Unlock Door" => "command:FrontDoor_Lock:OFF"
62
+ # }
63
+ # end
64
+ # end
65
+ #
66
+ def send(
67
+ msg,
68
+ email: nil,
69
+ icon: nil,
70
+ tag: nil,
71
+ severity: nil,
72
+ id: nil,
73
+ title: nil,
74
+ on_click: nil,
75
+ attachment: nil,
76
+ buttons: nil
77
+ )
78
+ unless Actions.const_defined?(:NotificationAction)
79
+ raise NotImplementedError, "NotificationAction is not available. Please install the openHAB Cloud addon."
80
+ end
81
+
82
+ args = []
83
+ if email
84
+ args.push(:send_notification, email)
85
+ else
86
+ args.push(:send_broadcast_notification)
87
+ end
88
+ tag ||= severity
89
+ args.push(msg.to_s, icon&.to_s, tag&.to_s)
90
+
91
+ # @!deprecated OH 4.1
92
+ if Core.version >= Core::V4_2
93
+ buttons ||= []
94
+ buttons = buttons.map { |title, action| "#{title}=#{action}" } if buttons.is_a?(Hash)
95
+ raise ArgumentError, "buttons must contain (0..3) elements." unless (0..3).cover?(buttons.size)
96
+
97
+ args.push(title&.to_s,
98
+ id&.to_s,
99
+ on_click&.to_s,
100
+ attachment&.to_s,
101
+ buttons[0]&.to_s,
102
+ buttons[1]&.to_s,
103
+ buttons[2]&.to_s)
104
+ end
105
+
106
+ NotificationAction.__send__(*args)
107
+ end
108
+
109
+ #
110
+ # Hide a notification by ID or tag.
111
+ #
112
+ # Either the `id` or `tag` parameter must be provided.
113
+ # When both are provided, two calls will be made to the NotificationAction:
114
+ # - Notifications matching the `id` will be hidden, and
115
+ # - Notifications matching the `tag` will be hidden, independently from the given tag.
116
+ #
117
+ # @param email [String, nil] The email address to hide notifications for.
118
+ # If nil, hide broadcast notifications.
119
+ # @param id [String, nil] hide notifications associated with the given reference ID.
120
+ # @param tag [String, nil] hide notifications associated with the given tag.
121
+ # @return [void]
122
+ #
123
+ def hide(email: nil, id: nil, tag: nil)
124
+ unless Actions.const_defined?(:NotificationAction)
125
+ raise NotImplementedError, "NotificationAction is not available. Please install the openHAB Cloud addon."
126
+ end
127
+
128
+ raise ArgumentError, "Either id or tag must be provided." unless id || tag
129
+
130
+ args = []
131
+ if email
132
+ args.push(email)
133
+ notification = :notification
134
+ else
135
+ notification = :broadcast_notification
136
+ end
137
+
138
+ NotificationAction.__send__(:"hide_#{notification}_by_reference_id", *args, id) if id
139
+ NotificationAction.__send__(:"hide_#{notification}_by_tag", *args, tag) if tag
140
+ end
141
+
142
+ #
143
+ # Sends a log notification.
144
+ #
145
+ # Log notifications do not trigger a notification on the device.
146
+ #
147
+ # @param msg [String] The message to send.
148
+ # @param icon [String, Symbol, nil] The icon name
149
+ # @param tag [String, Symbol, nil] a name to group the type or severity of the notification.
150
+ # @return [void]
151
+ #
152
+ def log(msg, icon: nil, tag: nil)
153
+ NotificationAction.send_log_notification(msg.to_s, icon&.to_s, tag&.to_s)
154
+ end
155
+ end
156
+
157
+ Object.const_set(name.split("::").last, self)
158
+ end
159
+ end
160
+ end
161
+ end
@@ -17,9 +17,8 @@ module OpenHAB
17
17
  # * {Voice}
18
18
  #
19
19
  # From add-ons, e.g.:
20
- # * NotificationAction (from
21
- # [openHAB Cloud Connector](https://www.openhab.org/addons/integrations/openhabcloud/);
22
- # see {notify notify})
20
+ # * {Notification NotificationAction} from
21
+ # [openHAB Cloud Connector](https://www.openhab.org/addons/integrations/openhabcloud/)
23
22
  #
24
23
  # Thing-specific actions can be accessed from the {Things::Thing Thing} object.
25
24
  # See {Things::Thing#actions Thing#actions}.
@@ -51,85 +50,12 @@ module OpenHAB
51
50
  module_function
52
51
 
53
52
  #
54
- # Send a notification using
55
- # {https://next.openhab.org/addons/integrations/openhabcloud/#cloud-notification-actions
56
- # openHAB Cloud Notification Action}.
53
+ # @!method notify(msg, email: nil, icon: nil, tag: nil, severity: nil, id: nil, title: nil, on_click: nil, attachment: nil, buttons: nil)
54
+ # @deprecated Use {Notification.send Notification.send} instead.
57
55
  #
58
- # @param msg [String] The message to send.
59
- # @param email [String, nil] The email address to send to. If `nil`, the message will be broadcast.
60
- # @param icon [String, Symbol, nil] The icon name
61
- # (as described in {https://next.openhab.org/docs/configuration/items.html#icons Items}).
62
- # @param severity [String, Symbol, nil] A description of the severity of the incident.
63
- # @param title [String, nil] The title of the notification.
64
- # When `nil`, it defaults to `openHAB` inside the Android and iOS apps.
65
- # @param on_click [String, nil] The action to be performed when the user clicks on the notification.
66
- # Specified using the {https://next.openhab.org/addons/integrations/openhabcloud/#action-syntax action syntax}.
67
- # @param attachment [String, nil] The URL of the media attachment to be displayed with the notification.
68
- # This URL must be reachable by the push notification client.
69
- # @param buttons [Array<String>, Hash<String, String>, nil] Buttons to include in the notification.
70
- # - In array form, each element is specified as `Title=$action`, where `$action` follows the
71
- # {https://next.openhab.org/addons/integrations/openhabcloud/#action-syntax action syntax}.
72
- # - In hash form, the keys are the button titles and the values are the actions.
73
- #
74
- # The maximum number of buttons is 3.
75
- # @return [void]
76
- #
77
- # @note The parameters `title`, `on_click`, `attachment`, and `buttons` were added in openHAB 4.2.
78
- #
79
- # @see https://www.openhab.org/addons/integrations/openhabcloud/
80
- #
81
- # @example Send a broadcast notification via openHAB Cloud
82
- # rule "Send an alert" do
83
- # changed Alarm_Triggered, to: ON
84
- # run { notify "Red Alert!" }
85
- # end
86
- #
87
- # @example Provide action buttons in a notification
88
- # rule "Doorbell" do
89
- # changed Doorbell, to: ON
90
- # run do
91
- # notify "Someone pressed the doorbell!",
92
- # title: "Doorbell",
93
- # attachment: "http://myserver.local/cameras/frontdoor.jpg",
94
- # buttons: {
95
- # "Show Camera" => "ui:/basicui/app?w=0001&sitemap=cameras",
96
- # "Unlock Door" => "command:FrontDoor_Lock:OFF"
97
- # }
98
- # end
99
- # end
100
- #
101
- def notify(
102
- msg,
103
- email: nil,
104
- icon: nil,
105
- severity: nil,
106
- title: nil,
107
- on_click: nil,
108
- attachment: nil,
109
- buttons: nil
110
- )
111
- unless Actions.const_defined?(:NotificationAction)
112
- raise NotImplementedError, "NotificationAction is not available. Please install the openHAB Cloud addon."
113
- end
114
-
115
- args = []
116
- if email
117
- args.push(:send_notification, email)
118
- else
119
- args.push(:send_broadcast_notification)
120
- end
121
- args.push(msg.to_s, icon&.to_s, severity&.to_s)
122
-
123
- # @!deprecated OH 4.1
124
- if Core.version >= Core::V4_2
125
- buttons ||= []
126
- buttons = buttons.map { |title, action| "#{title}=#{action}" } if buttons.is_a?(Hash)
127
- raise ArgumentError, "buttons must contain (0..3) elements." unless (0..3).cover?(buttons.size)
128
-
129
- args.push(title&.to_s, on_click&.to_s, attachment&.to_s, buttons[0]&.to_s, buttons[1]&.to_s, buttons[2]&.to_s)
130
- end
131
-
132
- NotificationAction.__send__(*args)
56
+ def notify(*args, **kwargs)
57
+ logger.warn("`notify` method is deprecated. Use `Notification.send` instead.")
58
+ Notification.send(*args, **kwargs)
133
59
  end
134
60
  end
135
61
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Events
6
+ java_import org.openhab.core.thing.link.events.AbstractItemChannelLinkRegistryEvent,
7
+ org.openhab.core.thing.link.events.ItemChannelLinkAddedEvent,
8
+ org.openhab.core.thing.link.events.ItemChannelLinkRemovedEvent
9
+
10
+ #
11
+ # The {AbstractEvent} sent when an {Things::ItemChannelLink} is added or removed
12
+ # from its registry.
13
+ #
14
+ # @!attribute [r] link
15
+ # @return [DTO::ItemChannelLinkDTO] The link that triggered this event.
16
+ #
17
+ class AbstractItemChannelLinkRegistryEvent < AbstractEvent; end
18
+
19
+ #
20
+ # The {AbstractEvent} sent with an `channel_linked` trigger.
21
+ #
22
+ class ItemChannelLinkAddedEvent < AbstractItemChannelLinkRegistryEvent; end
23
+
24
+ #
25
+ # The {AbstractEvent} sent with an `channel_unlinked` trigger.
26
+ #
27
+ class ItemChannelLinkRemovedEvent < AbstractItemChannelLinkRegistryEvent; end
28
+ end
29
+ end
30
+ end
@@ -25,6 +25,9 @@ module OpenHAB
25
25
  #
26
26
  # The {AbstractEvent} sent with an `item_updated` trigger.
27
27
  #
28
+ # @!attribute [r] old_item
29
+ # @return [DTO::ItemDTO] the old item before the update.
30
+ #
28
31
  class ItemUpdatedEvent < AbstractItemRegistryEvent; end
29
32
 
30
33
  #
@@ -28,6 +28,9 @@ module OpenHAB
28
28
  # The {AbstractEvent} sent with a
29
29
  # {DSL::Rules::BuilderDSL#thing_updated thing_updated trigger}.
30
30
  #
31
+ # @!attribute [r] old_thing
32
+ # @return [DTO::AbstractThingDTO] the old thing before the update.
33
+ #
31
34
  class ThingUpdatedEvent < AbstractThingRegistryEvent; end
32
35
 
33
36
  #
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @deprecated OH3.4 this guard is not needed on OH4
4
+ return unless OpenHAB::Core.version >= OpenHAB::Core::V4_0
5
+
6
+ module OpenHAB
7
+ module Core
8
+ module Events
9
+ java_import org.openhab.core.events.system.StartlevelEvent
10
+
11
+ #
12
+ # The {AbstractEvent} sent when the system start level changed.
13
+ #
14
+ # @!attribute [r] startlevel
15
+ # @return [Integer] The new start level.
16
+ #
17
+ class StartlevelEvent < AbstractEvent; end
18
+ end
19
+ end
20
+ end
@@ -25,6 +25,31 @@ module OpenHAB
25
25
  # UV_Index.average_since(1.hour.ago, :influxdb)
26
26
  # Power_Usage.average_since(12.hours.ago, :rrd4j)
27
27
  #
28
+ # @example Time of day shortcuts
29
+ # # Persistence methods accept any object that responds to #to_zoned_date_time, which includes
30
+ # # LocalTime, LocalDate, and Ruby's Time, Date, and DateTime.
31
+ # # This allows for easy querying of start of day
32
+ # logger.info Power_Usage.average_since(LocalTime::MIDNIGHT)
33
+ # logger.info Power_Usage.average_since(LocalDate.now)
34
+ # # Ruby's Date can be used too
35
+ # logger.info Power_Usage.average_since(Date.today)
36
+ #
37
+ # # Yesterday
38
+ # logger.info Power_Usage.average_between(Date.today - 1, Date.today)
39
+ # # or
40
+ # logger.info Power_Usage.average_between(LocalDate.now - 1, LocalDate.now)
41
+ #
42
+ # # When passing the local time, today's date is assumed
43
+ # logger.info Power_Usage.average_between(LocalTime.parse("4pm"), LocalTime.parse("9pm"))
44
+ # # or
45
+ # logger.info Power_Usage.average_between(Time.parse("4pm"), Time.parse("9pm"))
46
+ #
47
+ # # Beware that Date, LocalDate, and LocalTime arithmetics will produce the same type, so
48
+ # Power_Usage.average_between(LocalTime.parse("4pm") - 1.day, LocalTime.parse("9pm") - 1.day)
49
+ # # Will still give you TODAY's data between 4pm and 9pm
50
+ # # To get yesterday's data, use Time.parse, i.e.
51
+ # Power_Usage.average_between(Time.parse("4pm") - 1.day, Time.parse("9pm") - 1.day)
52
+ #
28
53
  # @example Comparison using Quantity
29
54
  # # Because Power_Usage has a unit, the return value
30
55
  # # from average_since is a QuantityType
@@ -42,10 +67,17 @@ module OpenHAB
42
67
  #
43
68
  # A wrapper for {org.openhab.core.persistence.HistoricItem HistoricItem} that delegates to its state.
44
69
  #
70
+ # A {PersistedState} object can be directly used in arithmetic operations with {State} and
71
+ # other {PersistedState} objects.
72
+ #
45
73
  # @example
46
74
  # max = Power_Usage.maximum_since(LocalTime::MIDNIGHT)
47
75
  # logger.info "Highest power usage: #{max} occurred at #{max.timestamp}" if max > 5 | "kW"
48
76
  #
77
+ # @example Arithmetic operations
78
+ # todays_rate = Energy_Prices.persisted_state(Date.today) # Energy_Prices' unit is "<CURRENCY>/kWh"
79
+ # todays_cost = Daily_Energy_Consumption.state * todays_rate
80
+ #
49
81
  class PersistedState < SimpleDelegator
50
82
  extend Forwardable
51
83
 
@@ -65,6 +97,11 @@ module OpenHAB
65
97
  @historic_item = historic_item
66
98
  super(state || historic_item.state)
67
99
  end
100
+
101
+ # @!visibility private
102
+ def inspect
103
+ "#<#{self.class} #{state} at: #{timestamp} item: #{name}>"
104
+ end
68
105
  end
69
106
 
70
107
  # @deprecated Use {PersistedState} instead
@@ -146,8 +146,8 @@ module OpenHAB
146
146
  # elsif other.is_a?(java.math.BigDecimal)
147
147
  # self.class.new(to_big_decimal.add(other))
148
148
  # elsif other.respond_to?(:to_d)
149
- # result = to_d + other
150
- # # result could already be a QuantityType
149
+ # result = to_d + other.to_d
150
+ # # result could already be a NumericType
151
151
  # result = self.class.new(result) unless result.is_a?(NumericType)
152
152
  # result
153
153
  # elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
@@ -163,8 +163,8 @@ module OpenHAB
163
163
  elsif other.is_a?(java.math.BigDecimal)
164
164
  self.class.new(to_big_decimal.#{java_op}(other, java.math.MathContext::DECIMAL128))
165
165
  elsif other.respond_to?(:to_d)
166
- result = to_d #{ruby_op} other
167
- # result could already be a QuantityType
166
+ result = to_d #{ruby_op} other.to_d
167
+ # result could already be a NumericType
168
168
  result = self.class.new(result) unless result.is_a?(NumericType)
169
169
  result
170
170
  elsif other.respond_to?(:coerce) && (lhs, rhs = other.coerce(to_d))
@@ -179,6 +179,7 @@ module OpenHAB
179
179
  class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
180
180
  # def +(other)
181
181
  # logger.trace("#{self} + #{other} (#{other.class})")
182
+ # other = other.state if other.is_a?(Core::Items::Persistence::PersistedState)
182
183
  # if other.is_a?(QuantityType)
183
184
  # add_quantity(other)
184
185
  # elsif (thread_unit = DSL.unit(dimension))
@@ -203,6 +204,7 @@ module OpenHAB
203
204
  <<~RUBY, __FILE__, __LINE__ + 1
204
205
  def #{ruby_op}(other)
205
206
  logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
207
+ other = other.state if other.is_a?(Core::Items::Persistence::PersistedState)
206
208
  if other.is_a?(QuantityType)
207
209
  #{java_op}_quantity(other)
208
210
  elsif (thread_unit = DSL.unit(dimension))
@@ -235,6 +237,7 @@ module OpenHAB
235
237
  class_eval( # rubocop:disable Style/DocumentDynamicEvalDefinition https://github.com/rubocop/rubocop/issues/10179
236
238
  # def *(other)
237
239
  # logger.trace("#{self} * #{other} (#{other.class})")
240
+ # other = other.state if other.is_a?(Core::Items::Persistence::PersistedState)
238
241
  # if other.is_a?(QuantityType)
239
242
  # multiply_quantity(other)
240
243
  # elsif other.is_a?(DecimalType)
@@ -252,6 +255,7 @@ module OpenHAB
252
255
  <<~RUBY, __FILE__, __LINE__ + 1
253
256
  def #{ruby_op}(other)
254
257
  logger.trace("\#{self} #{ruby_op} \#{other} (\#{other.class})")
258
+ other = other.state if other.is_a?(Core::Items::Persistence::PersistedState)
255
259
  if other.is_a?(QuantityType)
256
260
  #{java_op}_quantity(other).unitize
257
261
  elsif other.is_a?(DecimalType)
data/lib/openhab/core.rb CHANGED
@@ -15,9 +15,10 @@ module OpenHAB
15
15
  V4_2 = Gem::Version.new("4.2.0").freeze
16
16
 
17
17
  # @return [Gem::Version] Returns the current openHAB version as a Gem::Version object
18
+ # Note, this strips off snapshots, milestones and RC versions and returns the release version.
18
19
  # @!visibility private
19
20
  def self.version
20
- @version ||= Gem::Version.new(VERSION).freeze
21
+ @version ||= Gem::Version.new(VERSION).release.freeze
21
22
  end
22
23
 
23
24
  raise "`openhab-scripting` requires openHAB >= 3.4.0" unless version >= Gem::Version.new("3.4.0")
@@ -89,6 +89,7 @@ module OpenHAB
89
89
  # @param [Command] command to send to object
90
90
  # @param [Duration] for duration for item to be in command state
91
91
  # @param [Command] on_expire Command to send when duration expires
92
+ # @param [true, false] only_when_ensured if true, only start the timed command if the command was ensured
92
93
  # @yield If a block is provided, `on_expire` is ignored and the block
93
94
  # is expected to set the item to the desired state or carry out some
94
95
  # other action.
@@ -104,27 +105,46 @@ module OpenHAB
104
105
  # @example
105
106
  # Dimmer.on(for: 5.minutes) { |event| Dimmer.off if Light.on? }
106
107
  #
107
- def command(command, for: nil, on_expire: nil, &block)
108
+ # @example Only start a timed command if the command was ensured
109
+ # rule "Motion Detected" do
110
+ # received_command Motion_Sensor, command: ON
111
+ # run do
112
+ # # Start the timer only if the command was ensured
113
+ # # i.e. the light was off before the command was sent
114
+ # # but if the timer was already started, extend it
115
+ # FrontPorchLight.ensure.on for: 30.minutes, only_when_ensured: true
116
+ # end
117
+ # end
118
+ #
119
+ def command(command, for: nil, on_expire: nil, only_when_ensured: false, &block)
108
120
  duration = binding.local_variable_get(:for)
109
121
  return super(command) unless duration
110
122
 
111
123
  on_expire = block if block
112
124
 
125
+ create_ensured_timed_command = proc do
126
+ on_expire ||= default_on_expire(command)
127
+ if only_when_ensured
128
+ DSL.ensure_states do
129
+ create_timed_command(command, duration: duration, on_expire: on_expire) if super(command)
130
+ end
131
+ else
132
+ super(command)
133
+ create_timed_command(command, duration: duration, on_expire: on_expire)
134
+ end
135
+ end
136
+
113
137
  TimedCommand.timed_commands.compute(self) do |_key, timed_command_details|
114
138
  if timed_command_details.nil?
115
139
  # no prior timed command
116
- on_expire ||= default_on_expire(command)
117
- super(command)
118
- create_timed_command(command, duration: duration, on_expire: on_expire)
140
+ create_ensured_timed_command.call
119
141
  else
120
142
  timed_command_details.mutex.synchronize do
121
143
  if timed_command_details.resolution
122
144
  # timed command that finished, but hadn't removed itself from the map yet
123
145
  # (it doesn't do so under the mutex to prevent a deadlock).
124
146
  # just create a new one
125
- on_expire ||= default_on_expire(command)
126
- super(command)
127
- create_timed_command(command, duration: duration, on_expire: on_expire)
147
+ create_ensured_timed_command.call
128
148
  else
129
149
  # timed command still pending; reset it
130
150
  logger.trace "Outstanding Timed Command #{timed_command_details} encountered - rescheduling"
@@ -132,7 +152,7 @@ module OpenHAB
132
152
  timed_command_details.timer.reschedule(duration)
133
153
  # disable the cancel rule while we send the new command
134
154
  DSL.rules[timed_command_details.rule_uid].disable
135
- super(command)
155
+ super(command) # This returns nil when "ensured"
136
156
  DSL.rules[timed_command_details.rule_uid].enable
137
157
  timed_command_details
138
158
  end
@@ -135,7 +135,7 @@ module OpenHAB
135
135
  # # return the script object into a variable
136
136
  # door_check = script "Check all doors", id: "door_check", tags: :security do
137
137
  # open_doors = gDoors.members.select(&:open?).map(&:label).join(", ")
138
- # notify("The following doors are open: #{open_doors}") unless open_doors.empty?
138
+ # Notification.send("The following doors are open: #{open_doors}") unless open_doors.empty?
139
139
  # end
140
140
  #
141
141
  # # run is an alias of trigger
@@ -145,7 +145,7 @@ module OpenHAB
145
145
  # # This script expects to be called with `message` as context/parameter
146
146
  # DESTINATION_EMAIL = "myemail@example.com"
147
147
  # script "Send Notifications", id: "send_alert" do
148
- # notify(message)
148
+ # Notification.send(message)
149
149
  # things["mail:smtp:local"].send_mail(DESTINATION_EMAIL, "OpenHAB Alert", message)
150
150
  # end
151
151
  #
@@ -744,7 +744,7 @@ module OpenHAB
744
744
  # changed Door_State
745
745
  # debounce_for 10.minutes
746
746
  # only_if { Door_State.open? }
747
- # run { notify("The Door has been open for 10 minutes!") }
747
+ # run { Notification.send("The Door has been open for 10 minutes!") }
748
748
  # end
749
749
  #
750
750
  def debounce_for(debounce_time)
@@ -898,6 +898,8 @@ module OpenHAB
898
898
  # supports one or more channels with one or more triggers. `thing` is an optional
899
899
  # parameter that makes it easier to set triggers on multiple channels on the same thing.
900
900
  #
901
+ # The `event` passed to run blocks will be a {Core::Events::ChannelTriggeredEvent}.
902
+ #
901
903
  # @param [String, Core::Things::Channel, Core::Things::ChannelUID] channels
902
904
  # channels to create triggers for in form of 'binding_id:type_id:thing_id#channel_id'
903
905
  # or 'channel_id' if thing is provided.
@@ -992,6 +994,8 @@ module OpenHAB
992
994
  #
993
995
  # Creates a channel linked trigger
994
996
  #
997
+ # The `event` passed to run blocks will be an {Core::Events::ItemChannelLinkAddedEvent}.
998
+ #
995
999
  # @param [Item, String, nil] item The item to create a trigger for. If nil, all items are matched.
996
1000
  # @param [Core::Things::Channel, Core::Things::ChannelUID, String, nil] channel
997
1001
  # The channel to create a trigger for. If nil, all channels are matched.
@@ -1016,6 +1020,8 @@ module OpenHAB
1016
1020
  #
1017
1021
  # Creates a channel unlinked trigger
1018
1022
  #
1023
+ # The `event` passed to run blocks will be an {Core::Events::ItemChannelLinkRemovedEvent}.
1024
+ #
1019
1025
  # Note that the item or the thing it's linked to may no longer exist,
1020
1026
  # so if you try to access those objects they'll be nil.
1021
1027
  #
@@ -1054,7 +1060,7 @@ module OpenHAB
1054
1060
  # {Core::Events::ThingStatusInfoChangedEvent} depending on if the
1055
1061
  # triggering element was an item or a thing.
1056
1062
  #
1057
- # @param [Item, GroupItem::Members, Thing] items Objects to create trigger for.
1063
+ # @param [Item, GroupItem::Members, Thing, ThingUID, Things::Registry] items Objects to create trigger for.
1058
1064
  # @param [State, Array<State>, #===, nil] from
1059
1065
  # Only execute rule if previous state matches `from` state(s).
1060
1066
  # @param [State, Array<State>, #===, nil] to
@@ -1141,6 +1147,14 @@ module OpenHAB
1141
1147
  # run { |event| logger.info("Thing #{event.uid} status <trigger> to #{event.status}") }
1142
1148
  # end
1143
1149
  #
1150
+ # @example Trigger when any Thing changes status
1151
+ # rule "Thing status monitoring" do
1152
+ # changed things, to: :offline
1153
+ # run do |event|
1154
+ # Notification.send("Thing #{event.thing.uid} is offline")
1155
+ # end
1156
+ # end
1157
+ #
1144
1158
  # @example Real World Example
1145
1159
  # rule "Log (or notify) when an exterior door is left open for more than 5 minutes" do
1146
1160
  # changed ExteriorDoors.members, to: OPEN, for: 5.minutes
@@ -1160,11 +1174,13 @@ module OpenHAB
1160
1174
  case item
1161
1175
  when Core::Things::Thing,
1162
1176
  Core::Things::ThingUID,
1177
+ Core::Things::Registry,
1163
1178
  Core::Items::Item,
1164
1179
  Core::Items::GroupItem::Members
1165
1180
  nil
1166
1181
  else
1167
- raise ArgumentError, "items must be an Item, GroupItem::Members, Thing, or ThingUID"
1182
+ raise ArgumentError,
1183
+ "items must be an Item, GroupItem::Members, Thing, ThingUID, or Things::Registry"
1168
1184
  end
1169
1185
 
1170
1186
  logger.trace { "Creating changed trigger for entity(#{item}), to(#{to.inspect}), from(#{from.inspect})" }
@@ -1180,6 +1196,8 @@ module OpenHAB
1180
1196
  #
1181
1197
  # Create a cron trigger
1182
1198
  #
1199
+ # The `event` passed to run blocks will be a {Core::Events::TimerEvent}.
1200
+ #
1183
1201
  # @overload cron(expression, attach: nil)
1184
1202
  # @param [String, nil] expression [openHAB style cron expression](https://www.openhab.org/docs/configuration/rules-dsl.html#time-based-triggers)
1185
1203
  # @param [Object] attach object to be attached to the trigger
@@ -1258,6 +1276,8 @@ module OpenHAB
1258
1276
  #
1259
1277
  # Create a rule that executes at the specified interval.
1260
1278
  #
1279
+ # The `event` passed to run blocks will be a {Core::Events::TimerEvent}.
1280
+ #
1261
1281
  # @param [String,
1262
1282
  # Duration,
1263
1283
  # java.time.MonthDay,
@@ -1400,6 +1420,8 @@ module OpenHAB
1400
1420
  #
1401
1421
  # Creates a trigger that executes when openHAB reaches a certain start level
1402
1422
  #
1423
+ # The `event` passed to run blocks will be a {Core::Events::StartlevelEvent}.
1424
+ #
1403
1425
  # This will only trigger once during openHAB start up. It won't trigger on script reloads.
1404
1426
  #
1405
1427
  # @param [Integer,:rules,:ruleengine,:ui,:things,:complete] at_level
@@ -1570,6 +1592,8 @@ module OpenHAB
1570
1592
  #
1571
1593
  # Creates an item added trigger
1572
1594
  #
1595
+ # The `event` passed to run blocks will be an {Core::Events::ItemAddedEvent}.
1596
+ #
1573
1597
  # @param [String, nil] pattern The pattern to match items against
1574
1598
  # @param [Object] attach object to be attached to the trigger
1575
1599
  # @return [void]
@@ -1591,6 +1615,8 @@ module OpenHAB
1591
1615
  #
1592
1616
  # Creates an item removed trigger
1593
1617
  #
1618
+ # The `event` passed to run blocks will be an {Core::Events::ItemRemovedEvent}.
1619
+ #
1594
1620
  # @param [String, nil] pattern The pattern to match items against
1595
1621
  # @param [Object] attach object to be attached to the trigger
1596
1622
  # @return [void]
@@ -1612,6 +1638,8 @@ module OpenHAB
1612
1638
  #
1613
1639
  # Creates an item updated trigger
1614
1640
  #
1641
+ # The `event` passed to run blocks will be an {Core::Events::ItemUpdatedEvent}.
1642
+ #
1615
1643
  # @param [String, nil] pattern The pattern to match items against
1616
1644
  # @param [Object] attach object to be attached to the trigger
1617
1645
  # @return [void]
@@ -1632,6 +1660,8 @@ module OpenHAB
1632
1660
  #
1633
1661
  # Creates a thing added trigger
1634
1662
  #
1663
+ # The `event` passed to run blocks will be a {Core::Events::ThingAddedEvent}.
1664
+ #
1635
1665
  # @param [String, nil] pattern The pattern to match things against
1636
1666
  # @param [Object] attach object to be attached to the trigger
1637
1667
  # @return [void]
@@ -1653,6 +1683,8 @@ module OpenHAB
1653
1683
  #
1654
1684
  # Creates a thing removed trigger
1655
1685
  #
1686
+ # The `event` passed to run blocks will be a {Core::Events::ThingRemovedEvent}.
1687
+ #
1656
1688
  # @param [String, nil] pattern The pattern to match things against
1657
1689
  # @param [Object] attach object to be attached to the trigger
1658
1690
  # @return [void]
@@ -1674,6 +1706,8 @@ module OpenHAB
1674
1706
  #
1675
1707
  # Creates a thing updated trigger
1676
1708
  #
1709
+ # The event passed to run blocks will be a {Core::Events::ThingUpdatedEvent}.
1710
+ #
1677
1711
  # @param [String, nil] pattern The pattern to match things against
1678
1712
  # @param [Object] attach object to be attached to the trigger
1679
1713
  # @return [void]
@@ -1734,6 +1768,8 @@ module OpenHAB
1734
1768
  # To trigger just on the time portion of the item, use {every} instead, e.g.
1735
1769
  # `every :day, at: MyDateTimeItem`.
1736
1770
  #
1771
+ # The `event` passed to run blocks will be a {Core::Events::TimerEvent}.
1772
+ #
1737
1773
  # @param [Item, String, Symbol] item The item (or its name)
1738
1774
  # @return [void]
1739
1775
  #
@@ -79,6 +79,8 @@ module OpenHAB
79
79
  when Core::Things::Thing,
80
80
  Core::Things::ThingUID
81
81
  thing(thing: item, from: from, to: to)
82
+ when Core::Things::Registry
83
+ thing(thing: "*", from: from, to: to)
82
84
  else
83
85
  item(item: item, from: from, to: to)
84
86
  end
@@ -112,11 +112,11 @@ module OpenHAB
112
112
  #
113
113
  # @example Extend an existing timer, or schedule a new one
114
114
  # # This is technically the same functionality as just calling `after()` with an `id`,
115
- # # but allows you to performa extra steps if the timer is actually scheduled.
115
+ # # but allows you to perform extra steps if the timer is actually scheduled.
116
116
  # timers.schedule(item) do |timer|
117
117
  # next timer.tap(&:reschedule) if timer
118
118
  #
119
- # notify("The lights were turned on")
119
+ # Notification.send("The lights were turned on")
120
120
  #
121
121
  # after(30.seconds) { item.off }
122
122
  # end
@@ -4,6 +4,6 @@ module OpenHAB
4
4
  module DSL
5
5
  # Version of openHAB helper libraries
6
6
  # @return [String]
7
- VERSION = "5.21.0"
7
+ VERSION = "5.22.1"
8
8
  end
9
9
  end
@@ -11,29 +11,47 @@ module OpenHAB
11
11
  email,
12
12
  msg,
13
13
  icon,
14
- severity,
14
+ tag,
15
15
  title = nil,
16
+ id = nil,
16
17
  on_click = nil,
17
18
  attachment = nil,
18
19
  button1 = nil,
19
20
  button2 = nil,
20
21
  button3 = nil
21
22
  )
22
- logger.debug("send_notification: #{email}, #{msg}, #{icon}, #{severity}, #{title}, #{on_click}, #{attachment}, #{button1}, #{button2}, #{button3}") # rubocop:disable Layout/LineLength
23
+ logger.debug("send_notification: #{email}, #{msg}, #{icon}, #{tag}, #{title}, #{id}, #{on_click}, #{attachment}, #{button1}, #{button2}, #{button3}") # rubocop:disable Layout/LineLength
23
24
  end
24
25
 
25
26
  def send_broadcast_notification(
26
27
  msg,
27
28
  icon,
28
- severity,
29
+ tag,
29
30
  title = nil,
31
+ id = nil,
30
32
  on_click = nil,
31
33
  attachment = nil,
32
34
  button1 = nil,
33
35
  button2 = nil,
34
36
  button3 = nil
35
37
  )
36
- logger.debug("send_broadcast_notification: #{msg}, #{icon}, #{severity}, #{title}, #{on_click}, #{attachment}, #{button1}, #{button2}, #{button3}") # rubocop:disable Layout/LineLength
38
+ logger.debug("send_broadcast_notification: #{msg}, #{icon}, #{tag}, #{title}, #{id}, #{on_click}, #{attachment}, #{button1}, #{button2}, #{button3}") # rubocop:disable Layout/LineLength
39
+ end
40
+
41
+ def hide_notification_by_reference_id(email, id)
42
+ logger.debug("hide_notification_by_reference_id: #{email}, #{id}")
43
+ end
44
+
45
+ def hide_notification_by_tag(email, tag)
46
+ logger.debug("hide_notification_by_tag: #{email}, #{tag}")
47
+ end
48
+
49
+ def hide_broadcast_notification_by_reference_id(id)
50
+ logger.debug("hide_broadcast_notification_by_reference_id: #{id}")
51
+ end
52
+
53
+ def hide_broadcast_notification_by_tag(tag)
54
+ logger.debug("hide_broadcast_notification_by_tag: #{tag}")
37
55
  end
38
56
  end
39
57
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openhab-scripting
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.21.0
4
+ version: 5.22.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian O'Connell
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2024-06-28 00:00:00.000000000 Z
13
+ date: 2024-07-06 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -238,6 +238,7 @@ files:
238
238
  - lib/openhab/core/actions/ephemeris.rb
239
239
  - lib/openhab/core/actions/exec.rb
240
240
  - lib/openhab/core/actions/http.rb
241
+ - lib/openhab/core/actions/notification.rb
241
242
  - lib/openhab/core/actions/ping.rb
242
243
  - lib/openhab/core/actions/transformation.rb
243
244
  - lib/openhab/core/actions/voice.rb
@@ -250,6 +251,7 @@ files:
250
251
  - lib/openhab/core/entity_lookup.rb
251
252
  - lib/openhab/core/events.rb
252
253
  - lib/openhab/core/events/abstract_event.rb
254
+ - lib/openhab/core/events/abstract_item_channel_link_registry_event.rb
253
255
  - lib/openhab/core/events/abstract_item_registry_event.rb
254
256
  - lib/openhab/core/events/abstract_thing_registry_event.rb
255
257
  - lib/openhab/core/events/channel_triggered_event.rb
@@ -259,6 +261,7 @@ files:
259
261
  - lib/openhab/core/events/item_state_event.rb
260
262
  - lib/openhab/core/events/item_state_updated_event.rb
261
263
  - lib/openhab/core/events/item_time_series_updated_event.rb
264
+ - lib/openhab/core/events/startlevel_event.rb
262
265
  - lib/openhab/core/events/thing_status_info_event.rb
263
266
  - lib/openhab/core/events/timer_event.rb
264
267
  - lib/openhab/core/items.rb