Class: LIFX::NetworkContext

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
RequiredKeywordArguments
Defined in:
lib/lifx/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

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


22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/lifx/network_context.rb', line 22

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


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

def routing_manager
  @routing_manager
end

#tag_managerObject (readonly)

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager


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

def tag_manager
  @tag_manager
end

#transport_managerObject (readonly)

NetworkContext stores lights and ties together TransportManager, TagManager and RoutingManager


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

def transport_manager
  @transport_manager
end

Instance Method Details

#all_lightsObject


144
145
146
# File 'lib/lifx/network_context.rb', line 144

def all_lights
  @devices.values
end

#discoverObject


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

def discover
  @transport_manager.discover
end

#flush(**options) ⇒ Object


130
131
132
# File 'lib/lifx/network_context.rb', line 130

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

#lightsObject


140
141
142
# File 'lib/lifx/network_context.rb', line 140

def lights
  LightCollection.new(context: self)
end

#refresh(force: true) ⇒ Object


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

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

#register_device(device) ⇒ Object


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

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


45
46
47
48
# File 'lib/lifx/network_context.rb', line 45

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)


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/lifx/network_context.rb', line 65

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


50
51
52
53
54
55
56
57
58
# File 'lib/lifx/network_context.rb', line 50

def stop
  @transport_manager.stop
  stop_timers
  @threads.each do |thread|
    thread.abort
    thread.join
  end
  @threads = nil
end

#sync(delay: 0, &block) ⇒ 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
# File 'lib/lifx/network_context.rb', line 95

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
      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


156
157
158
# File 'lib/lifx/network_context.rb', line 156

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

#to_sObject Also known as: inspect


160
161
162
# File 'lib/lifx/network_context.rb', line 160

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