ledenet_api 1.2.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c112b458368c3f972704f893137b3b0beb90351b
4
- data.tar.gz: 0858ba4f9ca296a3d43dd3927f236ecd9f060076
3
+ metadata.gz: f8da932bc83469d8b334561d08eabd1030db8849
4
+ data.tar.gz: 2f241cab885aa1cfc4ef122724a918d919f1b9d6
5
5
  SHA512:
6
- metadata.gz: 2ef300b491b7636e9b271b8a78386074bd7be8b7a179aa69eeb88022fde35edecf1b07da21e36251e6a86d8d7528175f3ba58e5516f7784004a7f2bcdfa0e879
7
- data.tar.gz: 7bef60358efe62a5e03a72bb826fa797a492d4bbcc4166cebd8e8efc8f482de4913c226595ae350d41e750c3fd271fadd5857a1bfbc6bb7b7bbb7ea658489046
6
+ metadata.gz: 6eed4e0f31aa24481f0991d2d868ca297cb6441626f80dbb8091b3e6f1a0e13a31a78bd2607c7fe0abbd7dab2c0f10f8c248388e059665464f4d820999dafbc3
7
+ data.tar.gz: 098e2b9799d91d21d3f07c829493937f4da485979072613afa373ff902a41f09372c4f5cf5ce997f2960779a42f55c4b52e8d3f2c9fe9eeeb6aa7d62a3b3615d
data/README.md CHANGED
@@ -39,9 +39,11 @@ $ ledenet-ufo
39
39
  -w, --warm-white [VALUE] Set warm white to VALUE
40
40
  --on Turn on the controller
41
41
  --off Turn off the controller
42
- -l, --list Prints a list of available devices and exists
42
+ -l, --list Prints a list of available devices and exits
43
43
  -s, --status Prints status as JSON
44
44
  -h, --help Prints this help message
45
+ --function-id [VALUE] Set function id to VALUE
46
+ -f, --function [VALUE] Set function to VALUE.
45
47
  ```
46
48
 
47
49
  When using it, you can specify the IP address, hardware (mac) address, or let `ledenet_api` choose an arbitrary device on the local network (this would work well if you only have one).
@@ -76,6 +78,12 @@ $ ledenet-ufo --on -r 200 -g 0 -b 255 --warm-white 0 --status
76
78
  $ ledenet-ufo --off
77
79
  ```
78
80
 
81
+ #### Set function
82
+
83
+ ```
84
+ $ ledenet-ufo --function seven_color_cross_fade --speed 10
85
+ ```
86
+
79
87
  ### Ruby API
80
88
 
81
89
  #### Device discovery
@@ -161,3 +169,27 @@ api.update_color_data(red: 100)
161
169
 
162
170
  api.update_color_data(blue: 255, warm_white: 0)
163
171
  ```
172
+
173
+ #### Functions
174
+
175
+ The UFO devices ship with 20 pre-programmed lighting functions. ledenet_api has support for these:
176
+
177
+ ```ruby
178
+ LEDENET::Functions.all_functions
179
+ #=> [:SEVEN_COLOR_CROSS_FADE, :RED_GRADUAL_CHANGE, :GREEN_GRADUAL_CHANGE, :BLUE_GRADUAL_CHANGE, :YELLOW_GRADUAL_CHANGE, :CYAN_GRADUAL_CHANGE, :PURPLE_GRADUAL_CHANGE, :WHITE_GRADUAL_CHANGE, :RED_GREEN_CROSS_FADE, :RED_BLUE_CROSS_FADE, :SEVEN_COLOR_STROBE_FLASH, :RED_STROBE_FLASH, :GREEN_STROBE_FLASH, :BLUE_STROBE_FLASH, :YELLOW_STROBE_FLASH, :CYAN_STROBE_FLASH, :PURPLE_STROBE_FLASH, :WHITE_STROBE_FLASH, :SEVEN_COLOR_JUMPING_CHANGE, :GREEN_BLUE_CROSS_FADE]
180
+ ```
181
+
182
+ ```ruby
183
+ fn = LEDENET::Functions::SEVEN_COLOR_CROSS_FADE
184
+ speed = 0 # very slow
185
+
186
+ api.update_function(fn, speed)
187
+
188
+ api.update_function(:blue_green_cross_fade, 100) # Very fast
189
+ ```
190
+
191
+ To quit the function and return to a constant color, simply update a color value:
192
+
193
+ ```ruby
194
+ api.update_color_data(warm_white: 255)
195
+ ```
data/bin/ledenet-ufo CHANGED
@@ -99,12 +99,6 @@ if options[:list] && options.count > 1
99
99
  exit 1
100
100
  end
101
101
 
102
- if options[:function].nil? != options[:speed].nil?
103
- warn "--funciton and --speed must be specified together. You provide " <<
104
- "one without also providing the other."
105
- exit 1
106
- end
107
-
108
102
  begin
109
103
  if options[:list]
110
104
  devices = LEDENET.discover_devices(expected_devices: 1000)
@@ -136,22 +130,28 @@ begin
136
130
 
137
131
  api = LEDENET::Api.new(ip)
138
132
 
139
- api.set_power(options[:on?]) unless options[:on?].nil?
140
-
141
133
  color_params = options.select do |k,_|
142
134
  %w{red green blue warm_white}.include?(k.to_s)
143
135
  end
144
- api.update_color_data(color_params) unless color_params.empty?
145
136
 
146
- if options[:function] && options[:speed]
147
- api.update_function(options[:function], options[:speed])
137
+ if !options[:on?].nil?
138
+ api.set_power(options[:on?])
148
139
  end
149
140
 
150
- if options[:print_status?]
151
- status = api.current_color_data
152
- status = status.merge(is_on: api.on?)
141
+ if color_params.any?
142
+ api.update_color_data(color_params)
143
+ end
153
144
 
154
- puts status.to_json
145
+ if options[:function]
146
+ api.update_function(options[:function])
147
+ end
148
+
149
+ if options[:speed]
150
+ api.update_function_speed(options[:speed])
151
+ end
152
+
153
+ if options[:print_status?]
154
+ puts api.status.to_json
155
155
  end
156
156
  end
157
157
  rescue Exception => e
data/lib/ledenet/api.rb CHANGED
@@ -16,6 +16,13 @@ module LEDENET
16
16
  @options = DEFAULT_OPTIONS.merge(options)
17
17
  end
18
18
 
19
+ def status
20
+ response = request_status
21
+ status = { is_on: on?(response) }
22
+ status.merge!(current_color_data(response))
23
+ status.merge!(current_function_data(response))
24
+ end
25
+
19
26
  def on
20
27
  send_packet(LEDENET::Packets::SetPowerRequest.on_request)
21
28
  end
@@ -28,8 +35,8 @@ module LEDENET
28
35
  v ? on : off
29
36
  end
30
37
 
31
- def on?
32
- status.on?
38
+ def on?(response = request_status)
39
+ response.on?
33
40
  end
34
41
 
35
42
  def update_rgb(r, g, b)
@@ -53,20 +60,47 @@ module LEDENET
53
60
  current_color_data[:warm_white]
54
61
  end
55
62
 
56
- def current_color_data
57
- status_response = status
58
- color_data = %w{red green blue warm_white}.map do |x|
59
- [x.to_sym, status_response.send(x)]
60
- end
61
- Hash[color_data]
63
+ def current_color_data(response = request_status)
64
+ select_status_keys(response, *%w{red green blue warm_white})
62
65
  end
63
66
 
64
- def update_function(fn, speed)
67
+ def update_function(fn)
65
68
  if fn.is_a?(String) or fn.is_a?(Symbol)
66
69
  fn = LEDENET::Functions.const_get(fn.upcase)
67
70
  end
71
+ update_function_data(function_id: fn)
72
+ end
68
73
 
69
- send_packet(LEDENET::Packets::SetFunctionRequest.new(function_id: fn, speed: speed))
74
+ def update_function_speed(s)
75
+ update_function_data(speed: s)
76
+ end
77
+
78
+ def update_function_data(o)
79
+ o = {}.merge(o)
80
+ current_data = current_function_data
81
+ updated_data = {
82
+ function_id: current_data[:function_id],
83
+ speed: current_data[:speed_packet_value]
84
+ }
85
+
86
+ if o[:speed]
87
+ speed = LEDENET::FunctionSpeed.from_value(o.delete(:speed))
88
+ updated_data[:speed] = speed.packet_value
89
+ end
90
+ updated_data.merge!(o)
91
+
92
+ send_packet(LEDENET::Packets::SetFunctionRequest.new(updated_data))
93
+ end
94
+
95
+ def current_function_data(response = request_status)
96
+ raw_function_data = select_status_keys(response, *%w{mode speed})
97
+ function_data = {
98
+ running_function?: raw_function_data[:mode] != LEDENET::Functions::NO_FUNCTION,
99
+ speed: FunctionSpeed.from_packet_value(raw_function_data[:speed]).value,
100
+ speed_packet_value: raw_function_data[:speed],
101
+ function_name: LEDENET::Functions.value_of(raw_function_data[:mode]),
102
+ function_id: raw_function_data[:mode]
103
+ }
70
104
  end
71
105
 
72
106
  def reconnect!
@@ -85,8 +119,17 @@ module LEDENET
85
119
  end
86
120
 
87
121
  private
88
- def status
89
- send_packet(LEDENET::Packets::StatusRequest.new)
122
+ def select_status_keys(status_response, *keys)
123
+ color_data = keys.map do |x|
124
+ [x.to_sym, status_response.send(x)]
125
+ end
126
+ Hash[color_data]
127
+ end
128
+
129
+ def request_status
130
+ s = send_packet(LEDENET::Packets::StatusRequest.new)
131
+ puts s.inspect
132
+ s
90
133
  end
91
134
 
92
135
  def create_socket
@@ -0,0 +1,36 @@
1
+ module LEDENET
2
+ class FunctionSpeed
3
+ # Speed range exposed through API
4
+ INTERFACE_SPEED_RANGE = (1..100)
5
+
6
+ # Speed value is in [0x01, 0x1F], with 0x00 being the fastest.
7
+ PACKET_SPEED_RANGE = (0x01..0x1F)
8
+
9
+ attr_reader :value
10
+
11
+ def initialize(value)
12
+ @value = value
13
+ end
14
+
15
+ def packet_value
16
+ FunctionSpeed.convert_range(value, INTERFACE_SPEED_RANGE, PACKET_SPEED_RANGE)
17
+ end
18
+
19
+ def self.from_value(value)
20
+ FunctionSpeed.new(value)
21
+ end
22
+
23
+ def self.from_packet_value(value)
24
+ v = FunctionSpeed.convert_range(value, PACKET_SPEED_RANGE, INTERFACE_SPEED_RANGE)
25
+ FunctionSpeed.new(v)
26
+ end
27
+
28
+ private
29
+ def self.convert_range(value, from, to)
30
+ scaled_speed = (value / (from.max.to_f / to.max)).round
31
+ scaled_speed = [to.min, scaled_speed].max
32
+ scaled_speed = [to.max, scaled_speed].min
33
+ to.max - scaled_speed
34
+ end
35
+ end
36
+ end
@@ -20,11 +20,16 @@ module LEDENET
20
20
  CYAN_STROBE_FLASH = 0x35,
21
21
  PURPLE_STROBE_FLASH = 0x36,
22
22
  WHITE_STROBE_FLASH = 0x37,
23
- SEVEN_COLOR_JUMPING_CHANGE = 0x38
23
+ SEVEN_COLOR_JUMPING_CHANGE = 0x38,
24
+ NO_FUNCTION = 0x61
24
25
  ]
25
26
 
26
27
  def self.all_functions
27
28
  LEDENET::Functions.constants.reject { |x| x == :VALUES }
28
29
  end
30
+
31
+ def self.value_of(i)
32
+ all_functions.select { |x| self.const_get(x) == i }.first
33
+ end
29
34
  end
30
35
  end
@@ -5,30 +5,11 @@ require 'ledenet/packets/empty_response'
5
5
 
6
6
  module LEDENET::Packets
7
7
  class SetFunctionRequest < BinData::Record
8
- VALID_SPEED_RANGE = (0..100)
9
-
10
- # Speed value is in [0x00, 0x20], with 0x00 being the fastest.
11
- PACKET_SPEED_RANGE = (0x00..0x20)
12
-
13
8
  hide :checksum
14
- mandatory_parameter :function_id
15
- mandatory_parameter :speed
16
9
 
17
10
  uint8 :packet_id, value: 0x61
18
- uint8 :function_id_val, value: ->() { function_id }
19
-
20
- uint8 :speed_val, value: ->() do
21
- if !VALID_SPEED_RANGE.include?(speed)
22
- raise "Speed should be between #{VALID_SPEED_RANGE.min} and #{VALID_SPEED_RANGE.max}"
23
- end
24
-
25
- scaled_speed = (speed / (VALID_SPEED_RANGE.max / PACKET_SPEED_RANGE.max)).round
26
- scaled_speed = [PACKET_SPEED_RANGE.min, scaled_speed].max
27
- scaled_speed = [PACKET_SPEED_RANGE.max, scaled_speed].min
28
-
29
- PACKET_SPEED_RANGE.max - scaled_speed
30
- end
31
-
11
+ uint8 :function_id
12
+ uint8 :speed
32
13
  uint8 :remote_or_local, value: 0x0F
33
14
  checksum :checksum, packet_data: ->() { snapshot }
34
15
 
@@ -21,7 +21,7 @@ module LEDENET::Packets
21
21
  uint8 :blue
22
22
  uint8 :warm_white
23
23
 
24
- uint16be :unused_payload
24
+ uint24be :unused_payload
25
25
  uint8 :checksum
26
26
 
27
27
  def on?
@@ -1,3 +1,3 @@
1
1
  module LEDENET
2
- VERSION = '1.2.2'
2
+ VERSION = '1.4.0'
3
3
  end
data/lib/ledenet_api.rb CHANGED
@@ -2,3 +2,4 @@ require 'ledenet/version'
2
2
  require 'ledenet/device_discovery'
3
3
  require 'ledenet/api'
4
4
  require 'ledenet/functions'
5
+ require 'ledenet/function_speed'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ledenet_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Mullins
@@ -98,6 +98,7 @@ files:
98
98
  - ledenet_api.gemspec
99
99
  - lib/ledenet/api.rb
100
100
  - lib/ledenet/device_discovery.rb
101
+ - lib/ledenet/function_speed.rb
101
102
  - lib/ledenet/functions.rb
102
103
  - lib/ledenet/packets/empty_response.rb
103
104
  - lib/ledenet/packets/fields/checksum.rb