class LIFX::LAN::NetworkContext
Constants
- AT_TIME_DELTA
- NSEC_PER_SEC
Synchronize asynchronous set_color, set_waveform and set_power messages to multiple devices. You cannot use synchronous methods in the block @note This is alpha @param delay: [Float] The delay to add to sync commands when dealing with latency. @yield Block to synchronize commands in @return [Float] Delay before messages are executed
Attributes
NetworkContext
stores lights and ties together TransportManager
, TagManager
and RoutingManager
NetworkContext
stores lights and ties together TransportManager
, TagManager
and RoutingManager
NetworkContext
stores lights and ties together TransportManager
, TagManager
and RoutingManager
Public Class Methods
# File lib/lifx/lan/network_context.rb, line 23 def initialize(transport_manager: required!('transport_manager')) @devices = {} @transport_manager = transport_manager @transport_manager.context = WeakRef.new(self) @transport_manager.add_observer(self, :message_received) do |message: nil, ip: nil, transport: nil| handle_message(message, ip, transport) end reset! @threads = [] @threads << initialize_timer_thread end
Public Instance Methods
# File lib/lifx/lan/network_context.rb, line 150 def all_lights @devices.values end
# File lib/lifx/lan/network_context.rb, line 38 def discover @transport_manager.discover end
# File lib/lifx/lan/network_context.rb, line 136 def flush(**options) @transport_manager.flush(**options) end
# File lib/lifx/lan/network_context.rb, line 146 def lights LightCollection.new(context: self) end
# File lib/lifx/lan/network_context.rb, line 42 def refresh(force: true) @routing_manager.refresh(force: force) end
# File lib/lifx/lan/network_context.rb, line 140 def register_device(device) return if device.site_id == NULL_SITE_ID device_id = device.id @devices[device_id] = device # What happens when there's already one registered? end
# File lib/lifx/lan/network_context.rb, line 46 def reset! @routing_manager = RoutingManager.new(context: self) @tag_manager = TagManager.new(context: self, tag_table: @routing_manager.tag_table) end
Sends a message to their destination(s) @param target: [Target] Target
of the message @param payload: [Protocol::Payload] Message
payload @param acknowledge: [Boolean] If recipients must acknowledge with a response @param at_time: [Integer] Unix epoch in milliseconds to run the payload. Only applicable to certain payload types.
# File lib/lifx/lan/network_context.rb, line 70 def send_message(target: required!(:target), payload: required!(:payload), acknowledge: false, at_time: nil) paths = @routing_manager.resolve_target(target) messages = paths.map do |path| Message.new(path: path, payload: payload, acknowledge: acknowledge, at_time: at_time) end if within_sync? Thread.current[:sync_messages].push(*messages) return end messages.each do |message| @transport_manager.write(message) end end
# File lib/lifx/lan/network_context.rb, line 55 def stop @transport_manager.stop stop_timers @threads.each do |thread| thread.abort thread.join end @threads = nil end
# File lib/lifx/lan/network_context.rb, line 51 def stop_discovery @transport_manager.stop_discovery end
# File lib/lifx/lan/network_context.rb, line 100 def sync(delay: 0, &block) if within_sync? raise "You cannot nest sync" end messages = Thread.start do Thread.current[:sync_enabled] = true Thread.current[:sync_messages] = messages = [] block.call Thread.current[:sync_enabled] = false messages end.join.value time = nil failed_lights = [] try_until -> { time }, timeout: 5, action_interval: 1 do light = (lights.alive - failed_lights).sample begin time = light && light.send_message!(Protocol::Device::GetTime.new, wait_for: Protocol::Device::StateTime, wait_timeout: 1, retry_interval: 0.5) do |payload| Time.at(payload.time.to_f / NSEC_PER_SEC) end rescue => ex logger.debug("!!! Add light failed") failed_lights << light end end delay += (messages.count + 1) * (1.0 / @transport_manager.message_rate) at_time = ((time.to_f + delay) * NSEC_PER_SEC).to_i messages.each_with_index do |m, i| m.at_time = at_time + (i * AT_TIME_DELTA * NSEC_PER_SEC).to_i @transport_manager.write(m) end flush delay end
# File lib/lifx/lan/network_context.rb, line 166 def to_s %Q{#<LIFX::LAN::NetworkContext transport_manager=#{transport_manager}>} end
Protected Instance Methods
# File lib/lifx/lan/network_context.rb, line 173 def handle_message(message, ip, transport) logger.debug("<- #{self} #{transport}: #{message}") @routing_manager.update_from_message(message) if !message.tagged? if @devices[message.device_id].nil? && message.payload.is_a?(Protocol::Light::State) device = Light.new(context: self, id: message.device_id, site_id: message.site_id) end device = @devices[message.device_id] return if !device # Virgin bulb device.handle_message(message, ip, transport) end end
# File lib/lifx/lan/network_context.rb, line 87 def within_sync? !!Thread.current[:sync_enabled] end