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
- #init ⇒ Object
-
#initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: true, &block) ⇒ Device
constructor
A new instance of Device.
- #inspect ⇒ Object
- #join ⇒ Object
- #publish ⇒ Object
- #published? ⇒ Boolean
- #remove_node(id) ⇒ Object
- #topic ⇒ Object
Constructor Details
#initialize(id, name, root_topic: nil, mqtt: nil, clear_topics: 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 |
# File 'lib/mqtt/homie/device.rb', line 15 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 # 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
79 80 81 |
# File 'lib/mqtt/homie/device.rb', line 79 def [](id) @nodes[id] end |
#clear_topics ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/mqtt/homie/device.rb', line 159 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
87 88 89 |
# File 'lib/mqtt/homie/device.rb', line 87 def count @nodes.count end |
#device ⇒ Object
44 45 46 |
# File 'lib/mqtt/homie/device.rb', line 44 def device self end |
#disconnect ⇒ Object
133 134 135 136 137 |
# File 'lib/mqtt/homie/device.rb', line 133 def disconnect @published = false mqtt.disconnect @subscription_thread&.kill end |
#each(&block) ⇒ Object
83 84 85 |
# File 'lib/mqtt/homie/device.rb', line 83 def each(&block) @nodes.each_value(&block) end |
#init ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'lib/mqtt/homie/device.rb', line 146 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
40 41 42 |
# File 'lib/mqtt/homie/device.rb', line 40 def inspect "#<MQTT::Homie::Device #{topic} name=#{name.inspect}, $state=#{state.inspect}>" end |
#join ⇒ Object
139 140 141 142 143 144 |
# File 'lib/mqtt/homie/device.rb', line 139 def join @subscription_thread&.join rescue => e e.set_backtrace(e.backtrace + ["<from Homie MQTT thread>"] + caller) raise e end |
#publish ⇒ Object
95 96 97 98 99 100 101 102 103 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 |
# File 'lib/mqtt/homie/device.rb', line 95 def publish return if published? mqtt.batch_publish do mqtt.publish("#{topic}/$homie", VERSION, 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) yield if block_given? mqtt.publish("#{topic}/$state", (@state = :ready).to_s, retain: true, qos: 1) end @published = true end |
#published? ⇒ Boolean
91 92 93 |
# File 'lib/mqtt/homie/device.rb', line 91 def published? @published end |
#remove_node(id) ⇒ Object
68 69 70 71 72 73 74 75 76 77 |
# File 'lib/mqtt/homie/device.rb', line 68 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
48 49 50 |
# File 'lib/mqtt/homie/device.rb', line 48 def topic "#{root_topic}/#{id}" end |