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 +4 -4
- data/lib/openhab/core/actions/notification.rb +161 -0
- data/lib/openhab/core/actions.rb +7 -81
- data/lib/openhab/core/events/abstract_item_channel_link_registry_event.rb +30 -0
- data/lib/openhab/core/events/abstract_item_registry_event.rb +3 -0
- data/lib/openhab/core/events/abstract_thing_registry_event.rb +3 -0
- data/lib/openhab/core/events/startlevel_event.rb +20 -0
- data/lib/openhab/core/items/persistence.rb +37 -0
- data/lib/openhab/core/types/decimal_type.rb +4 -4
- data/lib/openhab/core/types/quantity_type.rb +4 -0
- data/lib/openhab/core.rb +2 -1
- data/lib/openhab/dsl/items/timed_command.rb +28 -8
- data/lib/openhab/dsl/rules/builder.rb +41 -5
- data/lib/openhab/dsl/rules/triggers/changed.rb +2 -0
- data/lib/openhab/dsl/timer_manager.rb +2 -2
- data/lib/openhab/dsl/version.rb +1 -1
- data/lib/openhab/rspec/openhab/core/actions.rb +22 -4
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2c5b8b2a28cbbda196f66340982141af673362693181e88588e89f9c4b1da29
|
4
|
+
data.tar.gz: 6a0483d0d94ae2a9492870e8089efd0b2a1afc400337d790a271b6fd9ca05ae3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/openhab/core/actions.rb
CHANGED
@@ -17,9 +17,8 @@ module OpenHAB
|
|
17
17
|
# * {Voice}
|
18
18
|
#
|
19
19
|
# From add-ons, e.g.:
|
20
|
-
# * NotificationAction
|
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
|
-
#
|
55
|
-
# {
|
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
|
-
|
59
|
-
|
60
|
-
|
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
|
@@ -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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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 {
|
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,
|
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
|
#
|
@@ -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
|
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
|
-
#
|
119
|
+
# Notification.send("The lights were turned on")
|
120
120
|
#
|
121
121
|
# after(30.seconds) { item.off }
|
122
122
|
# end
|
data/lib/openhab/dsl/version.rb
CHANGED
@@ -11,29 +11,47 @@ module OpenHAB
|
|
11
11
|
email,
|
12
12
|
msg,
|
13
13
|
icon,
|
14
|
-
|
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}, #{
|
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
|
-
|
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}, #{
|
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.
|
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
|
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
|