Class: MQTT::Homie::Device
Constant Summary collapse
- VERSION =
the Homie spec version
"4.0.0"
Constants inherited from Base
Instance Attribute Summary collapse
-
#logger ⇒ Object
Returns the value of attribute logger.
-
#mqtt ⇒ Object
readonly
Returns the value of attribute mqtt.
-
#out_of_band_topic_proc ⇒ Object
Returns the value of attribute out_of_band_topic_proc.
-
#root_topic ⇒ Object
readonly
Returns the value of attribute root_topic.
-
#state ⇒ Object
readonly
Returns the value of attribute state.
Attributes inherited from Base
Instance Method Summary collapse
- #[](id) ⇒ Object
- #clear_topics ⇒ Object
- #count ⇒ Object
- #device ⇒ Object
- #disconnect ⇒ Object
- #each(&block) ⇒ Object
- #empty? ⇒ Boolean
- #init ⇒ Object
-
#initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: true, metadata: true, &block) ⇒ Device
constructor
A new instance of Device.
- #inspect ⇒ Object
- #join ⇒ Object
- #metadata? ⇒ Boolean
- #publish ⇒ Object
- #published? ⇒ Boolean
- #remove_node(id) ⇒ Object
- #topic ⇒ Object
Constructor Details
#initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: true, metadata: true, &block) ⇒ Device
Returns a new instance of Device.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/mqtt/homie/device.rb', line 15 def initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: true, metadata: true, &block) super(id, name) @root_topic = root_topic || "homie" @state = :init @nodes = {} @published = false @out_of_band_topic_proc = block @metadata = # retry forever mqtt = MQTT::Client.new(mqtt, reconnect_limit: nil) if mqtt.is_a?(String) mqtt = MQTT::Client.new(reconnect_limit: nil, **mqtt) if mqtt.is_a?(Hash) @mqtt = mqtt || MQTT::Client.new(reconnect_limit: nil) @mqtt.set_will("#{topic}/$state", "lost", retain: true, qos: 1) @mqtt.on_reconnect do each do |node| node.each(&:subscribe) end mqtt.publish("#{topic}/$state", :init, retain: true, qos: 1) mqtt.publish("#{topic}/$state", state, retain: true, qos: 1) unless state == :init end @mqtt.connect self.clear_topics if clear_topics end |
Instance Attribute Details
#logger ⇒ Object
Returns the value of attribute logger.
13 14 15 |
# File 'lib/mqtt/homie/device.rb', line 13 def logger @logger end |
#mqtt ⇒ Object (readonly)
Returns the value of attribute mqtt.
12 13 14 |
# File 'lib/mqtt/homie/device.rb', line 12 def mqtt @mqtt end |
#out_of_band_topic_proc ⇒ Object
Returns the value of attribute out_of_band_topic_proc.
13 14 15 |
# File 'lib/mqtt/homie/device.rb', line 13 def out_of_band_topic_proc @out_of_band_topic_proc end |
#root_topic ⇒ Object (readonly)
Returns the value of attribute root_topic.
12 13 14 |
# File 'lib/mqtt/homie/device.rb', line 12 def root_topic @root_topic end |
#state ⇒ Object (readonly)
Returns the value of attribute state.
12 13 14 |
# File 'lib/mqtt/homie/device.rb', line 12 def state @state end |
Instance Method Details
#[](id) ⇒ Object
80 81 82 |
# File 'lib/mqtt/homie/device.rb', line 80 def [](id) @nodes[id] end |
#clear_topics ⇒ Object
170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/mqtt/homie/device.rb', line 170 def clear_topics raise ArgumentError, "cannot clear topics once published" if published? @mqtt.subscribe("#{topic}/#") @mqtt.unsubscribe("#{topic}/#", wait_for_ack: true) until @mqtt.queue_empty? packet = @mqtt.get @mqtt.publish(packet.topic, retain: true, qos: 0) end true end |
#count ⇒ Object
88 89 90 |
# File 'lib/mqtt/homie/device.rb', line 88 def count @nodes.count end |
#device ⇒ Object
45 46 47 |
# File 'lib/mqtt/homie/device.rb', line 45 def device self end |
#disconnect ⇒ Object
144 145 146 147 148 |
# File 'lib/mqtt/homie/device.rb', line 144 def disconnect @published = false mqtt.disconnect @subscription_thread&.kill end |
#each(&block) ⇒ Object
84 85 86 |
# File 'lib/mqtt/homie/device.rb', line 84 def each(&block) @nodes.each_value(&block) end |
#empty? ⇒ Boolean
92 93 94 |
# File 'lib/mqtt/homie/device.rb', line 92 def empty? @nodes.empty? end |
#init ⇒ Object
157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/mqtt/homie/device.rb', line 157 def init return yield state if state == :init prior_state = state mqtt.publish("#{topic}/$state", (@state = :init).to_s, retain: true, qos: 1) result = nil mqtt.batch_publish do result = yield prior_state end mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1) result end |
#inspect ⇒ Object
41 42 43 |
# File 'lib/mqtt/homie/device.rb', line 41 def inspect "#<MQTT::Homie::Device #{topic} name=#{name.inspect}, $state=#{state.inspect}>" end |
#join ⇒ Object
150 151 152 153 154 155 |
# File 'lib/mqtt/homie/device.rb', line 150 def join @subscription_thread&.join rescue => e e.set_backtrace(e.backtrace + ["<from Homie MQTT thread>"] + caller) raise e end |
#metadata? ⇒ Boolean
100 101 102 |
# File 'lib/mqtt/homie/device.rb', line 100 def @metadata end |
#publish ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/mqtt/homie/device.rb', line 104 def publish return if published? mqtt.batch_publish do if mqtt.publish("#{topic}/$homie", VERSION, retain: true, qos: 1) mqtt.publish("#{topic}/$name", name, retain: true, qos: 1) end mqtt.publish("#{topic}/$state", @state.to_s, retain: true, qos: 1) @subscription_thread = Thread.new do # you'll get the exception when you call `join` Thread.current.report_on_exception = false mqtt.get do |packet| logger&.debug("received packet at #{packet.topic} with payload #{packet.payload.inspect}") match = packet.topic.match(topic_regex) node = @nodes[match[:node]] if match property = node[match[:property]] if node unless property&.settable? @out_of_band_topic_proc&.call(packet.topic, packet.payload) next end property.set(packet.payload) end end mqtt.publish("#{topic}/$nodes", @nodes.keys.join(","), retain: true, qos: 1) if @nodes.each_value(&:publish) yield if block_given? mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1) end @published = true end |
#published? ⇒ Boolean
96 97 98 |
# File 'lib/mqtt/homie/device.rb', line 96 def published? @published end |
#remove_node(id) ⇒ Object
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/mqtt/homie/device.rb', line 69 def remove_node(id) return false unless (node = @nodes[id]) init do node.unpublish @nodes.delete(id) mqtt.publish("#{topic}/$nodes", @nodes.keys.join(","), retain: true, qos: 1) if published? end true end |
#topic ⇒ Object
49 50 51 |
# File 'lib/mqtt/homie/device.rb', line 49 def topic "#{root_topic}/#{id}" end |