tests.rb 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. require_relative 'helpers'
  2. COLOR_S2_BASES = [0x5A, 0x22, 0x30, 0x11]
  3. KELVIN_S2_BASES = COLOR_S2_BASES.map { |x| x + 0x80 }
  4. SATURATION_BRIGHTNESS_S2_BASES = [0x9A, 0x62, 0x70, 0x51]
  5. # saturation bases + 0x80
  6. COMMAND_BASES = [0x1A, 0xE2, 0xF0, 0xD1]
  7. GROUP_BASES = [0xAF, 0x04, 0xDD, 0x07]
  8. OFFSETTING_S2_FN = ->(bases, s, e) do
  9. ->(b0) do
  10. value = bases[ (b0 % 4) ]
  11. if b0 >= s && b0 <= e
  12. value = (value + 0x80) % 0x100
  13. end
  14. [value]
  15. end
  16. end
  17. extra_args = {
  18. kelvin: {
  19. increments: 2,
  20. s1_range: [0x0C],
  21. s2_range: OFFSETTING_S2_FN.call(KELVIN_S2_BASES, 0x14, 0x93)
  22. },
  23. color: {
  24. s1_range: [0x15],
  25. s2_range: OFFSETTING_S2_FN.call(COLOR_S2_BASES, 0x14, 0x93)
  26. },
  27. brightness: {
  28. s1_range: [0x0F],
  29. s2_range: OFFSETTING_S2_FN.call(SATURATION_BRIGHTNESS_S2_BASES, 0x54, 0xD3)
  30. },
  31. saturation: {
  32. invert_key: true,
  33. s1_range: [0x0E],
  34. s2_range: OFFSETTING_S2_FN.call(SATURATION_BRIGHTNESS_S2_BASES, 0x54, 0xD3)
  35. },
  36. on_seq: {
  37. s1_range: [0x00],
  38. },
  39. group: {
  40. s1_range: [0x00],
  41. s2_range: OFFSETTING_S2_FN.call(GROUP_BASES, 0x54, 0xD3)
  42. },
  43. checksum: {
  44. s1_range: ->(x) do
  45. lsn = (((x & 0xF)^2) + 7) % 0x10
  46. (0..0xF).map { |msn| (msn << 4) + lsn }
  47. end,
  48. s2_range: [ 0xA1, 0x53, 0x78, 0xA4 ]
  49. }
  50. }
  51. type_overrides = {
  52. checksum: 'on_seq'
  53. }
  54. lengths = {
  55. color: 256,
  56. brightness: 0x64,
  57. kelvin: 0x64,
  58. saturation: 0x64,
  59. on_seq: 30,
  60. checksum: 0xFF,
  61. group: 40
  62. }
  63. columns = {
  64. on_seq: 6,
  65. group: 7,
  66. checksum: 8
  67. }
  68. extract_fns = {
  69. group: ->(b0) do
  70. get_group_sequence(type: 'on', col: 7, key: b0, group_range: (0..100))
  71. end
  72. }
  73. # PACKET_TYPES = %w(color brightness saturation kelvin on_seq checksum)
  74. PACKET_TYPES = %w(color brightness kelvin saturation group)
  75. (0x00..0xFF).each do |b0|
  76. k = xor_key(b0)
  77. results = {}
  78. PACKET_TYPES.each do |type|
  79. type_args = extra_args[type.to_sym] || {}
  80. file_type = type_overrides[type.to_sym] || type
  81. if extract_fn = extract_fns[type.to_sym]
  82. packet_str = extract_fn.call(b0)
  83. else
  84. packet_str = get_sequence(file_type, b0, columns[type.to_sym] || 5)
  85. end
  86. max_len = lengths[type.to_sym]*2
  87. if packet_str.length > max_len
  88. packet_str = packet_str[0...max_len]
  89. end
  90. args = {}.merge(extra_args[type.to_sym] || {})
  91. if args[:s1_range].is_a?(Proc)
  92. args[:s1_range] = args[:s1_range].call(b0)
  93. end
  94. if args[:s2_range].is_a?(Proc)
  95. args[:s2_range] = args[:s2_range].call(b0)
  96. end
  97. args = {
  98. seq: packet_str,
  99. xor_range: [k]
  100. }.merge(args)
  101. results[type] = search_sequence(args)
  102. end
  103. num_fns = results.values.map { |x| x[:scramble_fns].length }.max
  104. printf "0x%02X", b0
  105. (0...num_fns).each do |i|
  106. printf "\t\t"
  107. PACKET_TYPES.each do |type|
  108. result = results[type]
  109. fns = result[:scramble_fns]
  110. if i < fns.length
  111. fn = result[:scramble_fns][i]
  112. printf "0x%02X\t0x%02X\t0x%02X\t%d\t", fn[:a], fn[:x], fn[:b], result[:num_misses]
  113. else
  114. printf "\t\t\t\t"
  115. end
  116. end
  117. printf "\n"
  118. end
  119. end
  120. # Dir.glob("#{CAPTURES_DIR}/**.txt").each do |filename|
  121. # puts File.basename(filename)
  122. # capture = parse_capture(filename)
  123. #
  124. # pp first_byte_determines_next(capture, 3)
  125. #
  126. # # a = capture
  127. # # .group_by { |x| x[0] }
  128. # # .sort
  129. # # .map { |_, packets| [packets.first[0], packets.first[1]] }
  130. # # mappings = Hash[a]
  131. # # perms = []
  132. # # current_perm = []
  133. # # elem = a.first
  134. # # current_perm = [elem[0]]
  135. # # visited = Set.new([elem[0]])
  136. # # perm_visited = Set.new([elem[0]])
  137. # #
  138. # # while visited.length < mappings.length
  139. # # new_elem = nil
  140. # #
  141. # # puts visited.inspect
  142. # #
  143. # # if !mappings.include?(elem[1]) || perm_visited.include?(mappings[elem[1]])
  144. # # new_elem = (Set.new(mappings.keys) - visited).first
  145. # # perms << current_perm
  146. # # current_perm = []
  147. # # perm_visited = Set.new
  148. # # else
  149. # # new_elem = [elem[1], mappings[elem[1]]]
  150. # # end
  151. # #
  152. # # visited << new_elem[0]
  153. # # perm_visited << new_elem[0]
  154. # # elem = new_elem
  155. # # end
  156. # #
  157. # # perms << current_perm
  158. # #
  159. # # pp perms
  160. #
  161. # a = capture
  162. # .group_by { |x| x[0] }
  163. # .sort
  164. # .map { |_, packets| [packets.first[0], packets.first[1]] }
  165. # .sort { |x,y| x[1] <=> y[1] }
  166. # a = a
  167. # .each_with_index.map do |x, i|
  168. # [x[1],x[0],if a[i-1][1] == x[1]-1
  169. # (x[0]-a[i-1][0])
  170. # else
  171. # nil
  172. # end]
  173. # end
  174. # .to_a
  175. # # # .group_by { |x| x[1] }
  176. # # # .sort
  177. # # # .to_a
  178. #
  179. # pp a
  180. #
  181. # # a = capture
  182. # # .group_by { |x| x[0] }
  183. # # .map { |_, packets| packets.first }
  184. # # .sort #{ |x, y| x[1] <=> y[1] }
  185. # # .map { |x| x }
  186. # # .to_a
  187. # #
  188. # end
  189. # on1 = parse_capture("#{CAPTURES_DIR}/rgbwcct_group1_on.txt")
  190. # on2 = parse_capture("#{CAPTURES_DIR}/rgbwcct_group2_on.txt")
  191. #
  192. # on1_g = on1.group_by { |x| x[0] }
  193. # on2_g = on2.group_by { |x| x[0] }
  194. #
  195. # a = (on1 + on2)
  196. # .map { |x| x[0] }
  197. # .sort
  198. # .uniq
  199. # .map do |key|
  200. # {key: key, vals: {on1: (on1_g[key]||[]).map { |x| x[1] }, on2: (on2_g[key]||[]).map { |x| x[1] } }}
  201. # end
  202. # .to_a
  203. # pp a