lifx-lan 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/.yardopts +3 -0
- data/CHANGES.md +45 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +23 -0
- data/README.md +15 -0
- data/Rakefile +20 -0
- data/bin/lifx-snoop +50 -0
- data/examples/auto-off/auto-off.rb +34 -0
- data/examples/blink/blink.rb +19 -0
- data/examples/identify/identify.rb +69 -0
- data/examples/travis-build-light/build-light.rb +57 -0
- data/lib/bindata_ext/bool.rb +30 -0
- data/lib/bindata_ext/record.rb +11 -0
- data/lib/lifx-lan.rb +27 -0
- data/lib/lifx/lan/client.rb +149 -0
- data/lib/lifx/lan/color.rb +199 -0
- data/lib/lifx/lan/config.rb +17 -0
- data/lib/lifx/lan/firmware.rb +60 -0
- data/lib/lifx/lan/gateway_connection.rb +185 -0
- data/lib/lifx/lan/light.rb +440 -0
- data/lib/lifx/lan/light_collection.rb +111 -0
- data/lib/lifx/lan/light_target.rb +185 -0
- data/lib/lifx/lan/logging.rb +14 -0
- data/lib/lifx/lan/message.rb +168 -0
- data/lib/lifx/lan/network_context.rb +188 -0
- data/lib/lifx/lan/observable.rb +66 -0
- data/lib/lifx/lan/protocol/address.rb +25 -0
- data/lib/lifx/lan/protocol/device.rb +387 -0
- data/lib/lifx/lan/protocol/header.rb +24 -0
- data/lib/lifx/lan/protocol/light.rb +142 -0
- data/lib/lifx/lan/protocol/message.rb +19 -0
- data/lib/lifx/lan/protocol/metadata.rb +23 -0
- data/lib/lifx/lan/protocol/payload.rb +12 -0
- data/lib/lifx/lan/protocol/sensor.rb +31 -0
- data/lib/lifx/lan/protocol/type.rb +204 -0
- data/lib/lifx/lan/protocol/wan.rb +51 -0
- data/lib/lifx/lan/protocol/wifi.rb +102 -0
- data/lib/lifx/lan/protocol_path.rb +85 -0
- data/lib/lifx/lan/required_keyword_arguments.rb +12 -0
- data/lib/lifx/lan/routing_manager.rb +114 -0
- data/lib/lifx/lan/routing_table.rb +48 -0
- data/lib/lifx/lan/seen.rb +25 -0
- data/lib/lifx/lan/site.rb +97 -0
- data/lib/lifx/lan/tag_manager.rb +111 -0
- data/lib/lifx/lan/tag_table.rb +49 -0
- data/lib/lifx/lan/target.rb +24 -0
- data/lib/lifx/lan/thread.rb +13 -0
- data/lib/lifx/lan/timers.rb +29 -0
- data/lib/lifx/lan/transport.rb +46 -0
- data/lib/lifx/lan/transport/tcp.rb +91 -0
- data/lib/lifx/lan/transport/udp.rb +87 -0
- data/lib/lifx/lan/transport_manager.rb +43 -0
- data/lib/lifx/lan/transport_manager/lan.rb +169 -0
- data/lib/lifx/lan/utilities.rb +36 -0
- data/lib/lifx/lan/version.rb +5 -0
- data/lifx-lan.gemspec +26 -0
- data/spec/color_spec.rb +43 -0
- data/spec/gateway_connection_spec.rb +30 -0
- data/spec/integration/client_spec.rb +42 -0
- data/spec/integration/light_spec.rb +56 -0
- data/spec/integration/tags_spec.rb +42 -0
- data/spec/light_collection_spec.rb +37 -0
- data/spec/message_spec.rb +183 -0
- data/spec/protocol_path_spec.rb +109 -0
- data/spec/routing_manager_spec.rb +25 -0
- data/spec/routing_table_spec.rb +23 -0
- data/spec/spec_helper.rb +56 -0
- data/spec/transport/udp_spec.rb +44 -0
- data/spec/transport_spec.rb +14 -0
- metadata +187 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LIFX
|
4
|
+
module LAN
|
5
|
+
describe 'tags', integration: true do
|
6
|
+
let(:color) { Color.hsb(rand(360), 0.3, 0.3) }
|
7
|
+
|
8
|
+
specify 'Clearing, setting and using tags' do
|
9
|
+
light.add_tag('Foo')
|
10
|
+
expect(light.tags).to include('Foo')
|
11
|
+
|
12
|
+
test_tag = lights.with_tag('Foo')
|
13
|
+
test_tag.turn_on
|
14
|
+
test_tag.set_color(color, duration: 0)
|
15
|
+
flush
|
16
|
+
sleep 1 # Set messages are scheduled 250ms if no at_time is set
|
17
|
+
# It also returns the current light state rather than the
|
18
|
+
# final state
|
19
|
+
light.refresh
|
20
|
+
wait { expect(light.color).to be_similar_to(color) }
|
21
|
+
|
22
|
+
light.remove_tag('Foo')
|
23
|
+
wait { expect(light.tags).not_to include('Foo') }
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'deletes tags when no longer assigned to a light' do
|
27
|
+
light.add_tag('TempTag')
|
28
|
+
light.remove_tag('TempTag')
|
29
|
+
expect(lifx.unused_tags).to include('TempTag')
|
30
|
+
lifx.purge_unused_tags!
|
31
|
+
expect(lifx.unused_tags).to be_empty
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'handles non-ascii tags' do
|
35
|
+
light.add_tag('_tést')
|
36
|
+
expect(light.tags).to include('_tést')
|
37
|
+
light.remove_tag('_tést')
|
38
|
+
lifx.purge_unused_tags!
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LIFX
|
4
|
+
module LAN
|
5
|
+
describe LightCollection do
|
6
|
+
subject(:collection) { LightCollection.new(context: double) }
|
7
|
+
|
8
|
+
describe '#with_id' do
|
9
|
+
let(:light) { double(Light, id: 'id') }
|
10
|
+
before { allow(collection).to receive(:lights).and_return([light]) }
|
11
|
+
|
12
|
+
it 'returns a Light with matching id' do
|
13
|
+
expect(collection.with_id('id')).to eq light
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'returns nil when none matches' do
|
17
|
+
ret = collection.with_id('wrong id')
|
18
|
+
expect(ret).to eq nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#with_label' do
|
23
|
+
let(:light) { double(Light, label: 'label') }
|
24
|
+
before { allow(collection).to receive(:lights).and_return([light]) }
|
25
|
+
|
26
|
+
it 'returns a Light with matching label' do
|
27
|
+
expect(collection.with_label('label')).to eq light
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns nil' do
|
31
|
+
ret = collection.with_label('wrong label')
|
32
|
+
expect(ret).to eq nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LIFX::LAN::Message do
|
4
|
+
context 'unpacking' do
|
5
|
+
let(:data) do
|
6
|
+
"\x39\x00\x00\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31" \
|
7
|
+
"\x6c\x69\x66\x78\x31\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x67\x00" \
|
8
|
+
"\x00\x00\x00\x01\x00\x00\xff\xff\xff\xff\xac\x0d\xc8\x00\x00\x00\x00" \
|
9
|
+
"\x00\x80\x3f\x00\x00\x00".b
|
10
|
+
end
|
11
|
+
let(:msg) { LIFX::LAN::Message.unpack(data) }
|
12
|
+
|
13
|
+
it 'unpacks without errors' do
|
14
|
+
expect(msg).not_to be_nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns the correct frame data' do
|
18
|
+
expect(msg.msg_size).to eq 57
|
19
|
+
expect(msg.protocol).to eq 1024
|
20
|
+
expect(msg).to be_addressable
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns the correct address data' do
|
24
|
+
expect(msg.raw_site).to eq '1lifx1'
|
25
|
+
expect(msg.raw_target).to eq "\x00" * 8
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has correct ProtocolPath data' do
|
29
|
+
expect(msg.path).to be_a(LIFX::LAN::ProtocolPath)
|
30
|
+
expect(msg.path.site_id).to eq '316c69667831'
|
31
|
+
expect(msg.path.tag_ids).to eq []
|
32
|
+
expect(msg.path.device_id).to be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns the correct metadata' do
|
36
|
+
expect(msg.at_time).to eq 0
|
37
|
+
expect(msg.type_).to eq 103
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:payload) { msg.payload }
|
41
|
+
it 'returns the payload' do
|
42
|
+
expect(payload.class).to eq LIFX::LAN::Protocol::Light::SetWaveform
|
43
|
+
expect(payload.stream).to eq 0
|
44
|
+
expect(payload.transient).to eq(true)
|
45
|
+
expect(payload.color.hue).to eq 0
|
46
|
+
expect(payload.color.saturation).to eq 65_535
|
47
|
+
expect(payload.color.brightness).to eq 65_535
|
48
|
+
expect(payload.color.kelvin).to eq 3_500
|
49
|
+
expect(payload.period).to eq 200
|
50
|
+
expect(payload.cycles).to eq 1.0
|
51
|
+
expect(payload.skew_ratio).to eq 0
|
52
|
+
expect(payload.waveform).to eq 0
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'repacks to the same data' do
|
56
|
+
expect(msg.pack).to eq data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'packing' do
|
61
|
+
context 'no attributes' do
|
62
|
+
let(:msg) { LIFX::LAN::Message.new }
|
63
|
+
|
64
|
+
it 'throws an exception' do
|
65
|
+
expect { msg.pack }.to raise_error(LIFX::LAN::Message::NoPayload)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'no path' do
|
70
|
+
let(:msg) { LIFX::LAN::Message.new(payload: LIFX::LAN::Protocol::Device::SetPower.new) }
|
71
|
+
|
72
|
+
it 'defaults to null site and target' do
|
73
|
+
unpacked = LIFX::LAN::Message.unpack(msg.pack)
|
74
|
+
expect(unpacked.path.site_id).to eq('000000000000')
|
75
|
+
expect(unpacked.path.device_id).to eq('000000000000')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'passed in via hash' do
|
80
|
+
let(:msg) do
|
81
|
+
LIFX::LAN::Message.new({
|
82
|
+
path: LIFX::LAN::ProtocolPath.new(tagged: false, raw_target: 'abcdefgh'),
|
83
|
+
at_time: 9001,
|
84
|
+
payload: LIFX::LAN::Protocol::Wifi::SetAccessPoint.new(
|
85
|
+
interface: 1,
|
86
|
+
ssid: 'who let the dogs out',
|
87
|
+
pass: 'woof, woof, woof woof!',
|
88
|
+
security: 1
|
89
|
+
)
|
90
|
+
})
|
91
|
+
end
|
92
|
+
# let(:unpacked) { LIFX::Message.unpack(msg.pack) }
|
93
|
+
|
94
|
+
it 'sets the size' do
|
95
|
+
expect(msg.msg_size).to eq 134
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'packs correctly' do
|
99
|
+
expect(msg.pack).to eq "\x86\x00\x00\x14\x00\x00\x00\x00abcdefgh\x00" \
|
100
|
+
"\x00\x00\x00\x00\x00\x00\x00)#\x00\x00\x00" \
|
101
|
+
"\x00\x00\x001\x01\x00\x00\x01who let the " \
|
102
|
+
"dogs out\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
|
103
|
+
"\x00\x00\x00woof, woof, woof woof!\x00\x00" \
|
104
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
|
105
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
|
106
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
|
107
|
+
"\x00\x00\x00\x00\x00\x00\x00\x01".b
|
108
|
+
expect(msg.protocol).to eq 1024
|
109
|
+
expect(msg.path).not_to be_tagged
|
110
|
+
expect(msg).to be_addressable
|
111
|
+
expect(msg.path.raw_target).to eq 'abcdefgh'
|
112
|
+
expect(msg.at_time).to eq 9001
|
113
|
+
expect(msg.type_).to eq 305
|
114
|
+
expect(msg.payload.class).to eq LIFX::LAN::Protocol::Wifi::SetAccessPoint
|
115
|
+
expect(msg.payload.interface).to eq 1
|
116
|
+
expect(msg.payload.ssid).to eq 'who let the dogs out'
|
117
|
+
expect(msg.payload.pass).to eq 'woof, woof, woof woof!'
|
118
|
+
expect(msg.payload.security).to eq 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context 'packing with tags' do
|
123
|
+
let(:msg) do
|
124
|
+
LIFX::LAN::Message.new({
|
125
|
+
path: LIFX::LAN::ProtocolPath.new(tag_ids: [0, 1]),
|
126
|
+
at_time: 9001,
|
127
|
+
payload: LIFX::LAN::Protocol::Device::GetTime.new
|
128
|
+
})
|
129
|
+
end
|
130
|
+
|
131
|
+
let(:unpacked) { LIFX::LAN::Message.unpack(msg.pack) }
|
132
|
+
|
133
|
+
it 'packs the tag correctly' do
|
134
|
+
expect(msg.pack).to eq "$\x00\x004\x00\x00\x00\x00\x03\x00\x00\x00" \
|
135
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
|
136
|
+
"\x00)#\x00\x00\x00\x00\x00\x00\x04\x00\x00" \
|
137
|
+
"\x00".b
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'sets tagged' do
|
141
|
+
expect(unpacked.path).to be_tagged
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'sets tags' do
|
145
|
+
expect(unpacked.path.tag_ids).to eq [0, 1]
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'device should be nil' do
|
149
|
+
expect(unpacked.path.device_id).to be_nil
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'packing with device' do
|
154
|
+
let(:msg) do
|
155
|
+
LIFX::LAN::Message.new({
|
156
|
+
path: LIFX::LAN::ProtocolPath.new(device_id: '0123456789ab', site_id: '0' * 12),
|
157
|
+
at_time: 9001,
|
158
|
+
payload: LIFX::LAN::Protocol::Device::GetTime.new
|
159
|
+
})
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:unpacked) { LIFX::LAN::Message.unpack(msg.pack) }
|
163
|
+
|
164
|
+
it 'packs the tag correctly' do
|
165
|
+
expect(msg.pack).to eq "$\x00\x00\x14\x00\x00\x00\x00\x01#Eg\x89\xAB" \
|
166
|
+
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)#" \
|
167
|
+
"\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00".b
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'sets tagged to false' do
|
171
|
+
expect(unpacked.path).not_to be_tagged
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'sets device' do
|
175
|
+
expect(unpacked.path.device_id).to eq '0123456789ab'
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'tags should be nil' do
|
179
|
+
expect(unpacked.path.tag_ids).to be_nil
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LIFX
|
4
|
+
module LAN
|
5
|
+
describe ProtocolPath do
|
6
|
+
describe 'initializing from raw data' do
|
7
|
+
subject do
|
8
|
+
ProtocolPath.new(raw_site: '1lifx1', raw_target: target, tagged: tagged)
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'device target' do
|
12
|
+
let(:target) { "\xAB\xCD\xEF\x12\x34\x56\x00\x00" }
|
13
|
+
let(:tagged) { false }
|
14
|
+
|
15
|
+
it 'returns site_id in hex' do
|
16
|
+
expect(subject.site_id).to eq '316c69667831'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns device_id in hex' do
|
20
|
+
expect(subject.device_id).to eq 'abcdef123456'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns tagged as false' do
|
24
|
+
expect(subject).not_to be_tagged
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns nil for tag_ids' do
|
28
|
+
expect(subject.tag_ids).to be_nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'tagged target' do
|
33
|
+
let(:target) { "\x03\x00\x00\x00\x00\x00\x00\x00" }
|
34
|
+
let(:tagged) { true }
|
35
|
+
|
36
|
+
it 'returns site_id in hex' do
|
37
|
+
expect(subject.site_id).to eq '316c69667831'
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns device_id as nil' do
|
41
|
+
expect(subject.device_id).to be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns tagged as true' do
|
45
|
+
expect(subject).to be_tagged
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns the tag_ids' do
|
49
|
+
expect(subject.tag_ids).to eq [0, 1]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'initializing from strings' do
|
55
|
+
context 'device target' do
|
56
|
+
subject do
|
57
|
+
ProtocolPath.new(site_id: '316c69667831', device_id: 'abcdef123456')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'sets raw_site correctly' do
|
61
|
+
expect(subject.raw_site).to eq '1lifx1'
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'sets raw_target correctly' do
|
65
|
+
expect(subject.raw_target).to eq "\xAB\xCD\xEF\x12\x34\x56\x00\x00".b
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'sets tagged to false' do
|
69
|
+
expect(subject).to_not be_tagged
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'tagged target' do
|
74
|
+
subject do
|
75
|
+
ProtocolPath.new(site_id: '316c69667831', tag_ids: [0, 1])
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'sets raw_site properly' do
|
79
|
+
expect(subject.raw_site).to eq '1lifx1'
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'sets raw_target correctly' do
|
83
|
+
expect(subject.raw_target).to eq "\x03\x00\x00\x00\x00\x00\x00\x00".b
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns tagged as true' do
|
87
|
+
expect(subject).to be_tagged
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'tagged target with no site' do
|
92
|
+
subject { ProtocolPath.new(tagged: true) }
|
93
|
+
|
94
|
+
it 'raw_site should be null string' do
|
95
|
+
expect(subject.raw_site).to eq "\x00\x00\x00\x00\x00\x00".b
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'sets raw_target correctly' do
|
99
|
+
expect(subject.raw_target).to eq "\x00\x00\x00\x00\x00\x00\x00\x00".b
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'returns tagged as true' do
|
103
|
+
expect(subject).to be_tagged
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LIFX
|
4
|
+
module LAN
|
5
|
+
describe RoutingManager do
|
6
|
+
describe '#tags_for_device_id' do
|
7
|
+
subject(:manager) { RoutingManager.new(context: double(timers: double(every: double))) }
|
8
|
+
|
9
|
+
before do
|
10
|
+
['Some label', 'Another label', 'Much label'].each_with_index do |lbl, i|
|
11
|
+
manager.tag_table.update_table(device_id: 'device', tag_id: i, label: lbl)
|
12
|
+
end
|
13
|
+
|
14
|
+
manager.routing_table
|
15
|
+
.update_table(site_id: 'site', device_id: 'device', tag_ids: [0, 2])
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'resolves tags' do
|
19
|
+
tags = manager.tags_for_device_id('device')
|
20
|
+
expect(tags).to eq ['Some label', 'Much label']
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module LIFX
|
4
|
+
module LAN
|
5
|
+
describe RoutingTable do
|
6
|
+
describe '#clear_stale_entries' do
|
7
|
+
subject(:table) { RoutingTable.new }
|
8
|
+
|
9
|
+
before do
|
10
|
+
table.update_table(site_id: 'site', device_id: 'stale device', last_seen: Time.now - 305)
|
11
|
+
table.update_table(site_id: 'site', device_id: 'recent device', last_seen: Time.now)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'clears only entries older than 5 minutes' do
|
15
|
+
expect(table.entries.count).to eq(2)
|
16
|
+
table.clear_stale_entries
|
17
|
+
expect(table.entries.count).to eq(1)
|
18
|
+
expect(table.entries.first.device_id).to eq('recent device')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.require
|
3
|
+
begin
|
4
|
+
require 'pry'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'lifx-lan'
|
9
|
+
require 'lifx/lan/utilities'
|
10
|
+
|
11
|
+
shared_context 'integration', integration: true do
|
12
|
+
def lifx
|
13
|
+
$lifx ||= begin
|
14
|
+
c = LIFX::LAN::Client.lan
|
15
|
+
begin
|
16
|
+
c.discover! do
|
17
|
+
c.tags.include?('_Test') && c.lights.with_tag('_Test').count > 0
|
18
|
+
end
|
19
|
+
rescue LIFX::Client::DiscoveryTimeout
|
20
|
+
raise "Could not find any lights with tag _Test in #{c.lights.inspect}"
|
21
|
+
end
|
22
|
+
c
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def flush
|
27
|
+
lifx.flush
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:lights) { lifx.lights.with_tag('_Test') }
|
31
|
+
let(:light) { lights.first }
|
32
|
+
end
|
33
|
+
|
34
|
+
module SpecHelpers
|
35
|
+
def wait(timeout: 5, retry_wait: 0.1, &block)
|
36
|
+
Timeout.timeout(timeout) do
|
37
|
+
begin
|
38
|
+
block.call
|
39
|
+
rescue RSpec::Expectations::ExpectationNotMetError
|
40
|
+
lights.refresh
|
41
|
+
sleep(retry_wait)
|
42
|
+
retry
|
43
|
+
end
|
44
|
+
end
|
45
|
+
rescue Timeout::Error
|
46
|
+
block.call
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
LIFX::LAN::Config.logger = Yell.new(STDERR) if ENV['DEBUG']
|
51
|
+
|
52
|
+
RSpec.configure do |config|
|
53
|
+
config.include(SpecHelpers)
|
54
|
+
config.formatter = 'documentation'
|
55
|
+
config.color = true
|
56
|
+
end
|