Skip to content

Instantly share code, notes, and snippets.

@jsinai
Created May 25, 2017 16:08
Show Gist options
  • Save jsinai/665fb6d77172ca0ad155b77afc371870 to your computer and use it in GitHub Desktop.
Save jsinai/665fb6d77172ca0ad155b77afc371870 to your computer and use it in GitHub Desktop.
A script suitable for serving from an Option 43 DHCP server.
'This script will bootstrap a BrightSign and is suitable for use with DHCP option
'43. It's job is to download an application/presentation zip file, and/or a
'firmware update.
'
'The application zip file is a standard zip file that can contain any combination
'of files that can run on a BrightSign. The only requirement is that it contains
' an autorun.brs to bootstrap the application.
'
'There are several tokens that need to be filled in for this script to work. It
'is designed to download two files at once, usually the application zip and a
'firmware update. But it can be used to download just one file also.
'
' ##fileName1##
'The name of the file when downloaded to the sd card. E.g. autorun.zip.
' ##fileType1##
'"presentation" or "firmware"
' ##url1##
'Where to get the file. E.g. "https://my.company.com/brightsign/application"
' ##addBsHeaders1##
'Whether to add headers to the request like serial number and firmware version.
'Value: true or false.
' ##optionalHeaders##
'Optional headers to add. These get added if addBsHeaders is true. Example of an
'authentication header:
' "xfer.AddHeader(\"Authorization\", \"Bearer " + authToken + "\")"
'
'The second set of download parameters is the same (##fileName2##, ##fileType2##
'etc.). If not required, set their values to invalid or false, as the case may
'be.
'
' ##recoveryUrl##
'This is the option 43 url that this script was originally downloaded from.
'
'Note that this url must obey the recovery rules, namely, it should examine the
'storagestatus header, and if an autorun is present (it's probably enough to look
'for the string "autorun" in the header), return http status 204. Otherwise,
'return 200 and this script in the body.
'
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub Main()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
CheckStorageDriveIsWritable()
modelObject = CreateObject("roDeviceInfo")
msgPort = CreateObject("roMessagePort")
drive$ = GetDefaultDrive()
file1AA = {
fileName: ##fileName1##
fileType: ##fileType1##
url: ##url1##
addBsHeaders: ##addBsHeaders1##
downloadingFile: false
downloadedFile: false
}
print "=== file1AA: ";file1AA
file2AA = {
fileName: ##fileName2##
fileType: ##fileType2##
url: ##url2##
addBsHeaders: ##addBsHeaders2##
downloadingFile: false
downloadedFile: false
}
print "=== file2AA: ";file2AA
xfer1 = CreateXfer(modelObject, msgPort, file1AA)
xfer2 = CreateXfer(modelObject, msgPort, file2AA)
DownloadFile(file1AA, drive$, xfer1, modelObject)
DownloadFile(file2AA, drive$, xfer2, modelObject)
recoveryUrl$ = ##recoveryUrl##
while true
event = wait(0, msgPort)
print "Received event ";type(event)
If (type(event) = "roUrlEvent") Then
ProcessDownloadEvent(event, xfer1, file1AA, file2AA, drive$, recoveryUrl$)
ProcessDownloadEvent(event, xfer2, file2AA, file1AA, drive$, recoveryUrl$)
End If
End while
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub CheckStorageDriveIsWritable()
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
ok = false
' get mounted drive and attempt to write to it
drive$ = GetMountedDrive()
If drive$ <> "" Then
SetDefaultDrive(drive$)
' determine If the storage drive is writable
tmpFileName$ = "bs~69-96.txt"
WriteAsciiFile(tmpFileName$, "1")
readValue$ = ReadAsciiFile(tmpFileName$)
If len(readValue$) = 1 and readValue$ = "1" Then
DeleteFile(tmpFileName$)
ok = true
End If
End If
If not ok Then
videoMode = CreateObject("roVideoMode")
resX = videoMode.GetResX()
resY = videoMode.GetResY()
videoMode = invalid
r = CreateObject("roRectangle", 0, 0, resX, resY)
twParams = CreateObject("roAssociativeArray")
twParams.LineCount = 1
twParams.TextMode = 2
twParams.Rotation = 0
twParams.Alignment = 1
tw=CreateObject("roTextWidget",r,1,2,twParams)
tw.PushString("")
tw.Show()
r=CreateObject("roRectangle",0,resY/2-resY/32,resX,resY/32)
tw=CreateObject("roTextWidget",r,1,2,twParams)
tw.PushString("The attached storage drive is write protected.")
tw.Show()
r2=CreateObject("roRectangle",0,resY/2,resX,resY/32)
tw2=CreateObject("roTextWidget",r2,1,2,twParams)
tw2.PushString("Remove it, enable writing, and reboot the device.")
tw2.Show()
msgPort = CreateObject("roMessagePort")
msg = wait(0, msgPort)
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetMountedDrive() As String
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
drives = ["USB1:/","SD:/","SD2:/","SSD:/"]
for each drive in drives
If DriveIsMounted(drive) Then
return drive
End If
next
return ""
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function DriveIsMounted(driveName$ As String) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
du = CreateObject("roStorageInfo", driveName$)
If type(du) = "roStorageInfo" Then
return true
End If
return false
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub Notify(message As String, delay As Integer)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
print message
videoMode = CreateObject("roVideoMode")
resX = videoMode.GetResX()
resY = videoMode.GetResY()
videoMode = invalid
rectangle = CreateObject("roRectangle", 0, resY/2-resY/64, resX, resY/32)
textParameters = CreateObject("roAssociativeArray")
textParameters.LineCount = 1
textParameters.TextMode = 2
textParameters.Rotation = 0
textParameters.Alignment = 1
textWidget = CreateObject("roTextWidget", rectangle, 1, 2, textParameters)
textWidget.PushString(message)
textWidget.Show()
If delay = -1 Then
while true
sleep(1000)
End while
Else
sleep(delay)
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub DownloadFile(fileAA As Object, drive$ As String, xfer As Object, modelObject As Object)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If fileAA.url <> invalid Then
firmwareVersion$ = modelObject.GetVersion()
' If the filename contains the firmware version, we are up to date
If fileAA.filetype = "firmware" And fileAA.fileName.Instr(firmwareVersion$) > -1 Then
Notify("Firmware is up to date, no download necessary. Version: " + firmwareVersion$ + ".", 3000)
Else
xfer.SetUrl(fileAA.url)
Notify("Downloading " + fileAA.fileType + " files.", 3000)
print "File source: " + fileAA.url + "."
print "File destination: " + drive$ + fileAA.fileName + "."
fileAA.downloadingFile = xfer.AsyncGetToFile(drive$ + fileAA.fileName)
print "File status at start of download: ";fileAA.downloadingFile;"."
End If
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function CreateXfer(modelObject As Object, msgPort As Object, fileAA As Object)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
xfer = CreateObject("roUrlTransfer")
xfer.SetPort(msgPort)
If fileAA.addBsHeaders Then
deviceUniqueID$ = modelObject.GetDeviceUniqueId()
deviceModel$ = modelObject.GetModel()
deviceFamily$ = modelObject.GetFamily()
firmwareVersion$ = modelObject.GetVersion()
xfer.AddHeader("DeviceID", deviceUniqueID$)
xfer.AddHeader("DeviceModel", deviceModel$)
xfer.AddHeader("DeviceFamily", deviceFamily$)
xfer.AddHeader("DeviceFWVersion", firmwareVersion$)
##optionalHeaders##
End If
return xfer
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub DoReboot(drive$ As String)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
isSuccess = RebootSystem()
If not isSuccess Then
Notify("Error while rebooting device.", -1)
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub ProcessDownloadEvent(event As Object, xfer As Object, myFileAA as Object, otherFileAA as Object, drive$ As String, recoveryUrl$ As String)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If xfer <> invalid And event.GetSourceIdentity() = xfer.GetIdentity() Then
code = event.GetResponseCode()
If code = 200 Then
myFileAA.downloadedFile = true
' Upon successful download, save the recovery URL for the application to the registry
If myFileAA.filetype = "presentation" Then
SaveRecoveryUrl(recoveryUrl$)
End If
If otherFileAA.downloadingFile Then
If otherFileAA.downloadedFile Then
Notify("Successfully downloaded " + myFileAA.fileType + " files. Player will reboot.", 3000)
DoUnzip(drive$, myFileAA.filename)
DoReboot(drive$)
Else
Notify("Successfully downloaded " + myFileAA.fileType + " files.", 3000)
End If
Else
Notify("Successfully downloaded " + myFileAA.fileType + " files. Player will reboot.", 3000)
DoUnzip(drive$, myFileAA.filename)
DoReboot(drive$)
End If
Else
Notify("Error while downloading " + myFileAA.fileType + " files: " + str(code) + ". Failure reason: " + xfer.GetFailureReason() + ".", -1)
End If
End If
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub SaveRecoveryUrl(recoveryUrl$ As String)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
registrySection = CreateObject("roRegistrySection", "networking")
registrySection.Write("ru", recoveryUrl$)
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub DoUnzip(drive$, filename$)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
If Len(filename$) > 4 And Lcase(Right(filename$, 4)) = ".zip" Then
package = CreateObject("roBrightPackage", drive$ + filename$)
package.Unpack(drive$)
MoveFile(drive$ + filename$, drive$ + filename$ + "_invalid")
End If
end Sub
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment