class MQTT::Homie::Device
Attributes
logger[RW]
mqtt[R]
out_of_band_topic_proc[RW]
root_topic[R]
state[R]
Public Class Methods
new(id, name, root_topic: nil, mqtt: nil, clear_topics: true, &block)
click to toggle source
Calls superclass method
MQTT::Homie::Base::new
# File lib/mqtt/homie/device.rb, line 13 def initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: true, &block) super(id, name) @root_topic = @root_topic || "homie" @state = :init @nodes = {} @published = false @out_of_band_topic_proc = block mqtt = MQTT::Client.new(mqtt) if mqtt.is_a?(String) @mqtt = mqtt || MQTT::Client.new @mqtt.set_will("#{topic}/$state", "lost", retain: true, qos: 1) @mqtt.on_reconnect do each do |node| node.each do |property| property.subscribe end 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
Public Instance Methods
[](id)
click to toggle source
# File lib/mqtt/homie/device.rb, line 72 def [](id) @nodes[id] end
clear_topics()
click to toggle source
# File lib/mqtt/homie/device.rb, line 143 def clear_topics raise ArgumentError, "cannot clear topics once published" if @published @mqtt.subscribe("#{topic}/#") @mqtt.unsubscribe("#{topic}/#", wait_for_ack: true) while !@mqtt.queue_empty? packet = @mqtt.get @mqtt.publish(packet.topic, retain: true, qos: 0) end true end
device()
click to toggle source
# File lib/mqtt/homie/device.rb, line 38 def device self end
disconnect()
click to toggle source
# File lib/mqtt/homie/device.rb, line 115 def disconnect @published = false mqtt.disconnect @subscription_thread&.kill end
each(&block)
click to toggle source
# File lib/mqtt/homie/device.rb, line 76 def each(&block) @nodes.each_value(&block) end
init() { |state| ... }
click to toggle source
# File lib/mqtt/homie/device.rb, line 128 def init if state == :init return yield state end 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
join()
click to toggle source
# File lib/mqtt/homie/device.rb, line 121 def join @subscription_thread&.join rescue => e e.set_backtrace(e.backtrace + ["<from Homie MQTT thread>"] + caller) raise e end
node(id, *args) { |node| ... }
click to toggle source
# File lib/mqtt/homie/device.rb, line 46 def node(id, *args) raise ArgumentError, "Node '#{id}' already exists" if @nodes.key?(id) init do |prior_state| node = Node.new(self, id, *args) @nodes[id] = node yield node if block_given? if prior_state == :ready node.publish mqtt.publish("#{topic}/$nodes", @nodes.keys.join(","), retain: true, qos: 1) end node end end
publish()
click to toggle source
# File lib/mqtt/homie/device.rb, line 80 def publish return if @published mqtt.batch_publish do mqtt.publish("#{topic}/$homie", "4.0.0", retain: true, qos: 1) mqtt.publish("#{topic}/$name", name, retain: true, qos: 1) 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) @nodes.each_value(&:publish) mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1) end @published = true end
remove_node(id)
click to toggle source
# File lib/mqtt/homie/device.rb, line 62 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()
click to toggle source
# File lib/mqtt/homie/device.rb, line 42 def topic "#{root_topic}/#{id}" end
Private Instance Methods
topic_regex()
click to toggle source
# File lib/mqtt/homie/device.rb, line 157 def topic_regex @topic_regex ||= Regexp.new("^#{Regexp.escape(topic)}/(?<node>#{REGEX})/(?<property>#{REGEX})/set$") end