lib/mqtt/homie/device.rb in mqtt-homie-0.1.0 vs lib/mqtt/homie/device.rb in mqtt-homie-0.1.1
- old
+ new
@@ -1,97 +1,108 @@
require "sys/uname"
+require "socket"
module MQTT
module Homie
class Device < HomieObject
+ class << self
+ include Network
+ end
+
HOMIE_VERSION = "3.0.1"
DEFAULT_STAT_REFRESH = 60 # seconds
- DEFAULT_IMPLEMENTATION = "mqtt-homie"
+ DEFAULT_IMPLEMENTATION = "mqtt-homie-#{VERSION}"
- attr_reader :nodes, :id, :mac, :fw_name, :fw_version, :name, :implementation, :interval
- attr_accessor :state
+ class Firmware < HomieObject
+ class << self
+ def default_fw_name
+ uname.sysname rescue uname.caption rescue "Unknown"
+ end
+ def default_fw_version
+ uname.release rescue uname.build_number rescue "Unknown"
+ end
+
+ def uname
+ @uname ||= Sys::Uname.uname
+ end
+ end
+
+ homie_attr :name, default: default_fw_name, required: true
+ homie_attr :version, default: default_fw_version, required: true
+ end
+
+ # statistics should be sent every interval seconds
+ # homie/device_id/$stats
+ class Statistics < HomieObject
+ homie_attr :interval, required: true, default: 60
+ homie_attr :boot_time, default: lambda { |i| Time.now }, hidden: true
+ homie_attr :signal, datatype: Integer
+ homie_attr :cputemp, datatype: Integer
+ homie_attr :cpuload, datatype: Float
+ homie_attr :battery, datatype: Integer
+ homie_attr :freeheap, datatype: Integer
+ homie_attr :supply, datatype: Float
+
+ def homie_attributes
+ super.merge("uptime" => (Time.now - @boot_time).to_i)
+ end
+ end
+
+ attr_reader :fw, :stats
+ attr_accessor :use_stats, :use_fw
+
+ homie_id
+ homie_attr :name, required: true
+ homie_attr :state, default: :init, required: true
+ homie_attr :nodes, datatype: Array, default: [], immutable: true
+ homie_attr :localip, default: default_localip, required: true
+ homie_attr :mac, default: default_mac, required: true
+ homie_attr :implementation, default: DEFAULT_IMPLEMENTATION
+
def initialize(options = {})
super(options)
- @name = options[:name]
- @start_time = Time.now
- @interval = set(options, :interval, default: DEFAULT_STAT_REFRESH)
- @nodes = set(options, :nodes, data_type: Array, default: [])
- @state = :init
- @localip = set(options, :localip, default: default_localip)
- @mac = set(options, :mac, default: default_mac)
- @implementation = set(options, :implementation, default: DEFAULT_IMPLEMENTATION)
- @fw_name = set(options, :fw_name, default: default_fw_name)
- @fw_version = set(options, :fw_version, default: default_fw_version)
- end
+ @stats = Statistics.new(options)
+ @fw = Firmware.new(subhash(options, "fw_"))
- def topic
- @id
+ @use_stats = options.include?(:use_stats) ? options[:use_stats] : true
+ @use_fw = options.include?(:use_fw) ? options[:use_fw] : true
end
def node(id)
@nodes.find { |i| i.id == id }
end
# device attributes must be sent when connection to broker is established or re-established
# homie/device_id/
def homie_attributes
- data = {
+ data = super.merge({
"$homie" => HOMIE_VERSION,
- "$name" => @name,
- "$localip" => @localip,
- "$mac" => @mac,
- "$fw/name" => @fw_name || "mqtt-homie",
- "$fw/version" => @fw_version || MQTT::Homie::VERSION,
- "$nodes" => @nodes.collect { |i| i.id }.join(","),
- "$implementation" => @implementation,
- "$state" => @state.to_s,
- }
+ })
+
+ data.merge!({
+ "$fw/name" => @fw.name,
+ "$fw/version" => @fw.version,
+ }) if @use_fw
+
@nodes.each do |node|
node.homie_attributes.each do |k, v|
data[node.topic + "/" + k] = v
end
end
data
end
- # statistics should be sent every INTERVAL seconds
- # homie/device_id/$stats
- def statistics
- {
- "uptime" => (Time.now - @start_time).to_i,
- #"signal" => 100, # TODO wifi signal strength
- #"cputemp" => 0,
- #"cpuload" => stats.load_average.one_minute,
- #"battery" => 100,
- #"freeheap" => stats.memory.free,
- #"supply" => 5,
- "interval" => @interval * 2,
- }
- end
+ private
- def update(time, node)
- # node value updated
- end
-
- def default_localip
- nil # TODO
- end
-
- def default_mac
- nil # TODO
- end
-
- def default_fw_name
- uname.sysname rescue uname.caption rescue "Unknown"
- end
-
- def default_fw_version
- uname.release rescue uname.build_number rescue "Unknown"
- end
-
- def uname
- @uname ||= Sys::Uname.uname
+ def subhash(data, prefix)
+ result = {}
+ data.each do |key, value|
+ next unless key.to_s.start_with?(prefix)
+ key = key.to_s.sub(/^#{prefix}/, "")
+ result[key.to_sym] = value
+ end
+ result
end
end
end
end