| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- require 'socket'
- require 'set'
- require 'net/http'
- STD_COMMAND_PREFIX = [ 0x31, 0x00, 0x00, 0x08 ]
- STD_COMMAND_SUFFIX = [ 0x00, 0x00, 0x00 ]
- class Commands
- def self.std_command(*cmd)
- ->() { STD_COMMAND_PREFIX + cmd + STD_COMMAND_SUFFIX }
- end
- def self.arg_command(prefix)
- ->(val) { STD_COMMAND_PREFIX + [prefix, val] + STD_COMMAND_SUFFIX }
- end
- VALUES = [
- LIGHT_ON = std_command(0x04, 0x01),
- LIGHT_OFF = std_command(0x04, 0x02),
- SATURATION = arg_command(0x02),
- BRIGHTNESS = arg_command(0x03),
- KELVIN = arg_command(0x05),
- WHITE_ON = std_command(0x05, 0x64),
- LINK = ->() { [ 0x3D, 0x00, 0x00, 0x08, 0x00, 0x00 ] + STD_COMMAND_SUFFIX },
- UNLINK = ->() { [ 0x3D, 0x00, 0x00, 0x08, 0x00, 0x00 ] + STD_COMMAND_SUFFIX },
- COLOR = ->(value) { STD_COMMAND_PREFIX + [0x01] + ([value]*4) }
- ]
- end
- class Milight
- ADDR = ['<broadcast>', 5987]
-
- attr_reader :socket
-
- def initialize
- @socket = UDPSocket.new
- socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
- @sequence = 0
- end
-
- def hex_to_bytes(s)
- s.strip.split(' ').map { |x| x.to_i(16) }.pack('C*')
- end
- def send(msg)
- socket.send(msg, 0, ADDR[0], ADDR[1])
- end
- def recv
- socket.recvfrom(1000)[0]
- end
- def start_session
- tries = 5
- begin
- Timeout.timeout(5) do
- send(hex_to_bytes("20 00 00 00 16 02 62 3A D5 ED A3 01 AE 08 2D 46 61 41 A7 F6 DC AF D3 E6 00 00 1E"))
- msg = recv
- @session = msg[-3..-2].bytes
- end
- rescue Exception => e
- puts "Error: #{e}"
- retry if (tries -= 1) > 0
- end
- end
- def send_command(cmd, zone = 0)
- start_session if !@session
-
- msg = [0x80, 0, 0, 0, 0x11, @session[0], @session[1], 0, @sequence, 0]
- msg += cmd
- msg += [zone,0]
- msg += [msg[-11..-1].reduce(&:+)&0xFF]
-
- send(msg.pack('C*'))
-
- @sequence = (@sequence + 1) % 0xFF
-
- #recv
- end
- end
- def get_file(cmd, value, group)
- name = "../../packet_captures/sidoh_wifibox1/rgbcct_group#{group}_#{cmd}#{value.nil? ? "" : "_#{value}"}.txt"
- File.expand_path(File.join(__FILE__, name))
- end
- def get_packet
- Net::HTTP.get('10.133.8.167', '/gateway_traffic/rgb_cct').split("\n").last.strip
- end
- milight = Milight.new
- (1..4).each do |group|
- (0..0xFF).each do |value|
- seen_keys = Set.new
- last_val = 0
-
- file = get_file("color", value, group)
-
- if File.exists?(file)
- File.read(file).split("\n").each { |x| seen_keys << x.split(' ').first }
- end
-
- puts "Processing: #{file}"
-
- File.open(file, 'a') do |f|
- while seen_keys.size < 255
- t = Thread.new do
- packet = get_packet
- key = packet.split(' ')[0]
- seen_keys << key
- f.write "#{packet}\n"
- f.flush
- end
-
- while %w(sleep run).include?(t.status)
- milight.send_command(Commands::COLOR.call(value), group)
- sleep 0.1
- print "."
- end
-
- print '*'
-
- puts "\n#{file} - #{seen_keys.length}" if last_val < seen_keys.length
- last_val = seen_keys.length
- end
- end
- end
- end
- # 10000.times do
- # milight.send_command(, 1).inspect
- # print "."
- # sleep 0.1
- # end
|