Class: LIFX::LAN::NetworkContext

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
RequiredKeywordArguments
Defined in:
lib/lifx/lan/network_context.rb

Constant Summary collapse

NSEC_PER_SEC =
Note:

This is alpha

Synchronize asynchronous set_color, set_waveform and set_power messages to multiple devices. You cannot use synchronous methods in the block

Yields:

  • Block to synchronize commands in

Returns:

  • (Float)

    Delay before messages are executed

1_000_000_000
AT_TIME_DELTA =
0.002

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from RequiredKeywordArguments

#required!

Constructor Details

#initialize(transport_manager: required!('transport_manager')) ⇒ NetworkContext

Returns a new instance of NetworkContext.


23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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

Instance Attribute Details

#routing_managerObject (readonly)

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager


21
22
23
# File 'lib/lifx/lan/network_context.rb', line 21

def routing_manager
  @routing_manager
end

#tag_managerObject (readonly)

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager


21
22
23
# File 'lib/lifx/lan/network_context.rb', line 21

def tag_manager
  @tag_manager
end

#transport_managerObject (readonly)

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager


21
22
23
# File 'lib/lifx/lan/network_context.rb', line 21

def transport_manager
  @transport_manager
end

Instance Method Details

#all_lightsObject


150
151
152
# File 'lib/lifx/lan/network_context.rb', line 150

def all_lights
  @devices.values
end

#discoverObject


38
39
40
# File 'lib/lifx/lan/network_context.rb', line 38

def discover
  @transport_manager.discover
end

#flush(**options) ⇒ Object


136
137
138
# File 'lib/lifx/lan/network_context.rb', line 136

def flush(**options)
  @transport_manager.flush(**options)
end

#lightsObject


146
147
148
# File 'lib/lifx/lan/network_context.rb', line 146

def lights
  LightCollection.new(context: self)
end

#refresh(force: true) ⇒ Object


42
43
44
# File 'lib/lifx/lan/network_context.rb', line 42

def refresh(force: true)
  @routing_manager.refresh(force: force)
end

#register_device(device) ⇒ Object


140
141
142
143
144
# 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!Object


46
47
48
49
# 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) ⇒ Object

Sends a message to their destination(s)

Parameters:

  • target: (Target) (defaults to: required!(:target))

    Target of the message

  • payload: (Protocol::Payload) (defaults to: required!(:payload))

    Message payload

  • acknowledge: (Boolean) (defaults to: false)

    If recipients must acknowledge with a response

  • at_time: (Integer) (defaults to: nil)

    Unix epoch in milliseconds to run the payload. Only applicable to certain payload types.


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 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

#stopObject


55
56
57
58
59
60
61
62
63
# 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_discoveryObject


51
52
53
# File 'lib/lifx/lan/network_context.rb', line 51

def stop_discovery
  @transport_manager.stop_discovery
end

#sync(delay: 0, &block) ⇒ Object


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
132
133
134
# 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) ⇒ Object


162
163
164
# File 'lib/lifx/lan/network_context.rb', line 162

def tags_for_device(device)
  @routing_manager.tags_for_device_id(device.id)
end

#to_sObject Also known as: inspect


166
167
168
# File 'lib/lifx/lan/network_context.rb', line 166

def to_s
  %Q{#<LIFX::LAN::NetworkContext transport_manager=#{transport_manager}>}
end