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

routing_manager[R]

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager

tag_manager[R]

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager

transport_manager[R]

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager

Public Class Methods

new(transport_manager: required!('transport_manager')) click to toggle source
# 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

all_lights() click to toggle source
# File lib/lifx/lan/network_context.rb, line 150
def all_lights
  @devices.values
end
discover() click to toggle source
# File lib/lifx/lan/network_context.rb, line 38
def discover
  @transport_manager.discover
end
flush(**options) click to toggle source
# File lib/lifx/lan/network_context.rb, line 136
def flush(**options)
  @transport_manager.flush(**options)
end
inspect()
Alias for: to_s
lights() click to toggle source
# File lib/lifx/lan/network_context.rb, line 146
def lights
  LightCollection.new(context: self)
end
refresh(force: true) click to toggle source
# File lib/lifx/lan/network_context.rb, line 42
def refresh(force: true)
  @routing_manager.refresh(force: force)
end
register_device(device) click to toggle source
# 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
reset!() click to toggle source
# 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
send_message(target: required!(:target), payload: required!(:payload), acknowledge: false, at_time: nil) click to toggle source

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
stop() click to toggle source
# 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
stop_discovery() click to toggle source
# File lib/lifx/lan/network_context.rb, line 51
def stop_discovery
  @transport_manager.stop_discovery
end
sync(delay: 0, &block) click to toggle source
# 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
tags_for_device(device) click to toggle source
# File lib/lifx/lan/network_context.rb, line 162
def tags_for_device(device)
  @routing_manager.tags_for_device_id(device.id)
end
to_s() click to toggle source
# File lib/lifx/lan/network_context.rb, line 166
def to_s
  %Q{#<LIFX::LAN::NetworkContext transport_manager=#{transport_manager}>}
end
Also aliased as: inspect

Protected Instance Methods

handle_message(message, ip, transport) click to toggle source
# 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
within_sync?() click to toggle source
# File lib/lifx/lan/network_context.rb, line 87
def within_sync?
  !!Thread.current[:sync_enabled]
end