udp_spec.rb 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. require 'api_client'
  2. require 'milight'
  3. RSpec.describe 'UDP servers' do
  4. before(:all) do
  5. @host = ENV.fetch('ESPMH_HOSTNAME')
  6. @client = ApiClient.new(@host, ENV.fetch('ESPMH_TEST_DEVICE_ID_BASE'))
  7. @client.upload_json('/settings', 'settings.json')
  8. @client.patch_settings( mqtt_parameters() )
  9. @client.patch_settings( mqtt_update_topic_pattern: '' )
  10. end
  11. before(:each) do
  12. @id_params = {
  13. id: @client.generate_id,
  14. type: 'rgbw',
  15. group_id: 1
  16. }
  17. @v6_id_params = {
  18. id: @client.generate_id,
  19. type: 'rgbw',
  20. group_id: 1
  21. }
  22. @client.delete_state(@id_params)
  23. @v5_udp_port = ENV.fetch('ESPMH_V5_UDP_PORT')
  24. @v6_udp_port = ENV.fetch('ESPMH_V6_UDP_PORT')
  25. @discovery_port = ENV.fetch('ESPMH_DISCOVERY_PORT')
  26. @client.patch_settings(
  27. gateway_configs: [
  28. [
  29. @id_params[:id], # device ID
  30. @v5_udp_port,
  31. 5 # protocol version (gem uses v5)
  32. ],
  33. [
  34. @v6_id_params[:id], # device ID
  35. @v6_udp_port,
  36. 6 # protocol version
  37. ]
  38. ]
  39. )
  40. @udp_client = Milight::Controller.new(ENV.fetch('ESPMH_HOSTNAME'), @v5_udp_port)
  41. @mqtt_client = create_mqtt_client()
  42. end
  43. context 'on/off commands' do
  44. it 'should result in state changes' do
  45. @udp_client.group(@id_params[:group_id]).on
  46. # Wait for packet to be processed
  47. sleep 1
  48. state = @client.get_state(@id_params)
  49. expect(state['status']).to eq('ON')
  50. @udp_client.group(@id_params[:group_id]).off
  51. # Wait for packet to be processed
  52. sleep 1
  53. state = @client.get_state(@id_params)
  54. expect(state['status']).to eq('OFF')
  55. end
  56. it 'should result in an MQTT update' do
  57. desired_state = {
  58. 'status' => 'ON',
  59. 'level' => 48
  60. }
  61. seen_state = false
  62. @mqtt_client.on_state(@id_params) do |id, message|
  63. seen_state = (id == @id_params && desired_state.all? { |k,v| v == message[k] })
  64. end
  65. @udp_client.group(@id_params[:group_id]).on.brightness(48)
  66. @mqtt_client.wait_for_listeners
  67. expect(seen_state).to eq(true)
  68. end
  69. end
  70. context 'color and brightness commands' do
  71. it 'should result in state changes' do
  72. desired_state = {
  73. 'status' => 'ON',
  74. 'level' => 48,
  75. 'hue' => 357
  76. }
  77. seen_state = false
  78. @mqtt_client.on_state(@id_params) do |id, message|
  79. seen_state = (id == @id_params && desired_state.all? { |k,v| v == message[k] })
  80. end
  81. @udp_client.group(@id_params[:group_id])
  82. .on
  83. .colour('#ff0000')
  84. .brightness(48)
  85. @mqtt_client.wait_for_listeners
  86. expect(seen_state).to eq(true)
  87. end
  88. end
  89. context 'discovery' do
  90. before(:all) do
  91. @client.patch_settings(
  92. discovery_port: ENV.fetch('ESPMH_DISCOVERY_PORT')
  93. )
  94. @discovery_host = '<broadcast>'
  95. @discovery_socket = UDPSocket.new
  96. @discovery_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_BROADCAST, true)
  97. @discovery_socket.bind('0.0.0.0', 0)
  98. end
  99. it 'should respond to v5 discovery' do
  100. @discovery_socket.send('Link_Wi-Fi', 0, @discovery_host, @discovery_port)
  101. # wait for response
  102. sleep 1
  103. response, _ = @discovery_socket.recvfrom_nonblock(1024)
  104. response = response.split(',')
  105. expect(response.length).to eq(2), "Should be a comma-separated list with two elements"
  106. expect(response[0]).to eq(@host)
  107. expect(response[1].to_i(16)).to eq(@id_params[:id])
  108. end
  109. it 'should respond to v6 discovery' do
  110. @discovery_socket.send('HF-A11ASSISTHREAD', 0, @host, @discovery_port)
  111. # wait for response
  112. sleep 1
  113. response, _ = @discovery_socket.recvfrom_nonblock(1024)
  114. response = response.split(',')
  115. expect(response.length).to eq(3), "Should be a comma-separated list with three elements"
  116. expect(response[0]).to eq(@host)
  117. expect(response[1].to_i(16)).to eq(@v6_id_params[:id])
  118. expect(response[2]).to eq('HF-LPB100')
  119. end
  120. end
  121. end