wifibox.rb 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. require 'socket'
  2. require 'set'
  3. require 'net/http'
  4. class Commands
  5. VALUES = [
  6. LIGHT_ON = ->() { [0x04, 0x01] },
  7. LIGHT_OFF = ->() { [0x04, 0x02] },
  8. SATURATION = ->(val) { [0x02, val] },
  9. BRIGHTNESS = ->(val) { [0x03, val] },
  10. KELVIN = ->(val) { [0x05, val] }
  11. ]
  12. end
  13. class Milight
  14. ADDR = ['<broadcast>', 5987]
  15. attr_reader :socket
  16. def initialize
  17. @socket = UDPSocket.new
  18. socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
  19. @sequence = 0
  20. end
  21. def hex_to_bytes(s)
  22. s.strip.split(' ').map { |x| x.to_i(16) }.pack('C*')
  23. end
  24. def send(msg)
  25. socket.send(msg, 0, ADDR[0], ADDR[1])
  26. end
  27. def recv
  28. socket.recvfrom(1000)[0]
  29. end
  30. def start_session
  31. tries = 5
  32. begin
  33. Timeout.timeout(5) do
  34. 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"))
  35. msg = recv
  36. @session = msg[-3..-2].bytes
  37. end
  38. rescue Exception => e
  39. puts "Error: #{e}"
  40. retry if (tries -= 1) > 0
  41. end
  42. end
  43. def send_command(cmd, zone = 0)
  44. start_session if !@session
  45. msg = [0x80, 0, 0, 0, 0x11, @session[0], @session[1], 0, @sequence, 0]
  46. msg += [0x31, 0, 0, 8]
  47. msg += cmd
  48. msg += [0,0,0,zone,0]
  49. msg += [msg[-11..-1].reduce(&:+)&0xFF]
  50. send(msg.pack('C*'))
  51. @sequence = (@sequence + 1) % 0xFF
  52. #recv
  53. end
  54. end
  55. def get_file(cmd, value, group)
  56. File.expand_path(File.join(__FILE__, "../../packet_captures/sidoh_wifibox1/rgbcct_group#{group}_#{cmd}_#{value}.txt"))
  57. end
  58. def get_packet
  59. Net::HTTP.get('10.133.8.167', '/gateway_traffic/rgb_cct').split("\n").last.strip
  60. end
  61. milight = Milight.new
  62. (1..4).each do |group|
  63. (0..0x10).each do |value|
  64. seen_keys = Set.new
  65. last_val = 0
  66. file = get_file("brightness", value, group)
  67. if File.exists?(file)
  68. File.read(file).split("\n").each { |x| seen_keys << x.split(' ').first }
  69. end
  70. puts "Processing: #{value}"
  71. File.open(file, 'a') do |f|
  72. while seen_keys.size < 255
  73. t = Thread.new do
  74. packet = get_packet
  75. key = packet.split(' ')[0]
  76. seen_keys << key
  77. f.write "#{packet}\n"
  78. f.flush
  79. end
  80. while %w(sleep run).include?(t.status)
  81. milight.send_command(Commands::BRIGHTNESS.call(value), group)
  82. sleep 0.1
  83. print "."
  84. end
  85. print '*'
  86. puts "\n#{value} - #{seen_keys.length}" if last_val < seen_keys.length
  87. last_val = seen_keys.length
  88. end
  89. end
  90. end
  91. end
  92. # 10000.times do
  93. # milight.send_command(, 1).inspect
  94. # print "."
  95. # sleep 0.1
  96. # end