Skip to content

Instantly share code, notes, and snippets.

@chap

chap/mfg-server.rb

Last active Jul 27, 2016
Embed
What would you like to do?
Sinatra app for particle.io testing and programming.
require 'sinatra'
require 'active_record'
require 'httparty'
COM_PORT = "COM8"
api_host = 'https://...'
api_auth_token = '...'
SYSTEM_FIRMWARE_VERSION = '0.5.3-rc.1'
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:database => 'mfg-v4.sqlite3.db'
)
SETUP_STEPS = [
{ name:'save_device_id' },
{ name:'flash_light_test' },
{ name:'light_test', human_required: true },
{ name:'set_ssid' },
{ name:'verify_ssid' },
{ name:'flash_system_update' },
{ name:'flash_wifi_test' },
{ name:'claim_particle_device' },
{ name:'clear_credentials' },
{ name:'flash_production' },
{ name:'setup_complete' }
]
class Event < ActiveRecord::Base
end
class Device < ActiveRecord::Base
has_many :events
def flash_firmware(firmware)
if firmware.start_with?('system-update')
version = SYSTEM_FIRMWARE_VERSION
version = '0.4.9' if firmware.include?('0.4.9')
if OS.windows?
# force DFU
%x(mode #{COM_PORT} BAUD=14400)
sleep(1)
# require ending with tinker otherwise device remains in DFU
# give it 2 seconds to reset
result = %x(cd \\dependencies && particle flash --usb \\mfg-firmware\\system-part1-#{version}-photon.bin && particle flash --usb \\mfg-firmware\\system-part2-#{version}-photon.bin && particle flash --usb tinker)
sleep(2)
return result
else
# force DFU
%x(stty -f /dev/cu.usbmodem1411 14400)
sleep(1)
# require ending with tinker otherwise device remains in DFU
# give it 2 seconds to reset
result = %x(particle flash --usb ../mfg-firmware/system-part1-#{version}-photon.bin && particle flash --usb ../mfg-firmware/system-part2-#{version}-photon.bin && particle flash --usb tinker)
sleep(2)
return result
end
elsif firmware == 'tinker'
return %x(echo | particle flash --serial tinker)
else
if OS.windows?
return %x(echo | particle flash --serial \\mfg-firmware\\#{firmware})
else
return %x(echo | particle flash --serial ../mfg-firmware/#{firmware})
end
end
end
end
before '/devices/:id*' do
@device = Device.find_by! "lower(serial_number) = ?", params['id'].try(:downcase)
end
# STEP 1
# input serial_number
get '/' do\
erb :index
end
# STEP 2
# check serial_number exists in DB
get '/lookup-engraved-url' do\
@device = Device.find_by "lower(serial_number) = ?", params['serial_number'].try(:downcase)
if @device
redirect to("devices/#{@device.serial_number}")
else
Event.create({ name: "FAIL serial_number lookup", description:params })
redirect to("/?error=not-found")
end
end
# STEP 3
# store device id in DB
get '/devices/:id/save_device_id' do\
identify_output = %x(particle identify)
match = /Your device id is (.+)\n.+/.match(identify_output)
event = @device.events.new({ name: "Saved device id", description:identify_output, step: 'save_device_id' })
if !match.nil? && match[1] != 'undefined'
@device.update_attributes(device_id:match[1])
@device.update_attributes(save_device_id:1)
event.event_type = 'success'
else
@device.update_attributes(save_device_id:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 4
# load firmware to test switch and light
get '/devices/:id/flash_light_test' do\
content_type :json
flash_output = @device.flash_firmware("light-test-ssid.bin")
event = @device.events.new({ name: "Flashed light test", description:flash_output, step: 'flash_light_test' })
if flash_output.include?('Flash success!')
@device.update_attributes(flash_light_test:1)
event.event_type = 'success'
else
@device.update_attributes(flash_light_test:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 5
# record light test results
get '/devices/:id/light_test' do\
event = @device.events.new({ name: "Light test", description:params, step: 'light_test' })
if params['results'] == 'pass'
@device.update_attributes(light_test:1)
event.event_type = 'success'
else
@device.update_attributes(light_test:-1)
event.event_type = 'fail'
end
event.save!
redirect to("/devices/#{@device.serial_number}")
end
# STEP 6
# set device SSID
get '/devices/:id/set_ssid' do\
content_type :json
ssid_param = "ssid#{sprintf('%02d',@device.serial_number.length)}#{@device.serial_number}"
event = @device.events.new({ name: "Set SSID", description:"ssid_param=#{ssid_param}\n#{params}", step: 'set_ssid' })
if OS.windows?
# %x(set /p x="#{ssid}" <nul >\\\\.\\COM7)
ssid_response = %x(echo #{ssid_param} > "#{COM_PORT}")
@device.update_attributes(set_ssid:1)
# I think this always succeeds
event.event_type = 'success'
else
@device.update_attributes(set_ssid:1)
event.event_type = 'success'
event.description = "Only works on windows, faking success for now!\n#{event.description}"
end
event.save!
event.to_json
end
# STEP 7
# verify device SSID
get '/devices/:id/verify_ssid' do\
content_type :json
description = "No output"
ssid = "#{@device.serial_number}-MAKE"
event = @device.events.new({ name: "Verify SSID", step: 'verify_ssid' })
if OS.windows?
log_path = "wifi-scans\\#{@device.serial_number}.txt"
%x(\\dependencies\\Homedale.exe /l #{log_path} /e /t 5000 /c)
file = File.open(log_path, "rb")
description = file.read
else
description = %x(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s)
end
event.description = description
if description.include?(ssid)
@device.update_attributes(verify_ssid:1)
event.event_type = 'success'
else
@device.update_attributes(verify_ssid:-1)
event.description = "SSID=#{ssid} not found:\r#{description}"
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 8
# update system firmware
get '/devices/:id/flash_system_update' do\
content_type :json
# ?system-firmware-version=-0.4.9
flash_output = @device.flash_firmware('system-update#{params[:system_firmware_version]}')
event = @device.events.new({ name: "Flashed system update", step: 'flash_system_update', description: flash_output })
if flash_output.include?('Flash success!')
@device.update_attributes(flash_system_update:1)
event.event_type = 'success'
else
@device.update_attributes(flash_system_update:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 9
# flash wifi test
get '/devices/:id/flash_wifi_test' do\
content_type :json
flash_output = @device.flash_firmware('wifi-test.bin')
event = @device.events.new({ name: "Flashed wifi test", step: 'flash_wifi_test', description: flash_output })
if flash_output.include?('Flash success!')
@device.update_attributes(flash_wifi_test:1)
event.event_type = 'success'
else
@device.update_attributes(flash_wifi_test:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 10
# claim-particle-device
get '/devices/:id/claim_particle_device' do\
content_type :json
# give it 10 seconds to connect
sleep(10)
response = ::HTTParty.post("#{api_host}/api/v1/clocks/#{@device.serial_number}/claim", { headers: { "Authorization" => "Token token=#{api_auth_token}" }, body: { device_id: @device.device_id } } )
event = @device.events.new({ name: "Claim particle device", step: 'claim_particle_device', description: response })
parsed_response = JSON.parse(response.body) rescue ({})
if parsed_response['ok'].to_s == 'true'
@device.update_attributes(claim_particle_device:1)
event.event_type = 'success'
else
@device.update_attributes(claim_particle_device:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 11
# flash production
get '/devices/:id/clear_credentials' do\
content_type :json
flash_output = @device.flash_firmware('clear-credentials.bin')
event = @device.events.new({ name: "Clear credentials", step: 'clear_credentials', description: flash_output })
if flash_output.include?('Flash success!')
@device.update_attributes(clear_credentials:1)
event.event_type = 'success'
else
@device.update_attributes(clear_credentials:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 12
# flash production
get '/devices/:id/flash_production' do\
content_type :json
flash_output = @device.flash_firmware('production.bin')
event = @device.events.new({ name: "Flashed production", step: 'flash_wifi_test', description: flash_output })
if flash_output.include?('Flash success!')
@device.update_attributes(flash_production:1)
event.event_type = 'success'
else
@device.update_attributes(flash_production:-1)
event.event_type = 'fail'
end
event.save!
event.to_json
end
# STEP 13
# all good
get '/devices/:id/setup_complete' do\
content_type :json
@device.update_attributes(setup_complete:1)
@device.events.create!({ name: "Setup complete", step: 'setup_complete', event_type: 'success' }).to_json
end
get '/devices/:id' do\
erb :show
end
module OS
def OS.windows?
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
end
def OS.mac?
(/darwin/ =~ RUBY_PLATFORM) != nil
end
def OS.unix?
!OS.windows?
end
def OS.linux?
OS.unix? and not OS.mac?
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment