2023-04-05 07:54:48 +02:00
<#
2023-04-04 07:48:11 +02:00
# © 2023 Peter Cole
#
# This file is part of EX-CommandStation
#
# This is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# It is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CommandStation. If not, see <https://www.gnu.org/licenses/>.
2023-04-05 07:54:48 +02:00
#>
2023-04-04 07:48:11 +02:00
2023-04-05 07:54:48 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
For script errors set ExecutionPolicy :
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass
############################################>
2023-04-04 07:48:11 +02:00
2023-04-05 07:54:48 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Optional command line parameters :
$buildDirectory - specify an existing directory rather than generating a new unique one
2023-04-10 11:52:31 +02:00
$configDirectory - specify a directory containing existing files as per $configFiles
2023-04-05 07:54:48 +02:00
############################################>
2023-04-04 21:30:00 +02:00
Param (
2023-04-04 07:48:11 +02:00
[ Parameter ( ) ]
2023-04-05 07:54:48 +02:00
[ String ] $buildDirectory ,
[ Parameter ( ) ]
2023-04-06 07:06:22 +02:00
[ String ] $configDirectory
2023-04-04 07:48:11 +02:00
)
2023-04-07 22:57:09 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Define global parameters here such as known URLs etc .
############################################>
2023-04-10 11:52:31 +02:00
$installerVersion = " v0.0.7 "
$configFiles = @ ( " config.h " , " myAutomation.h " , " myHal.cpp " , " mySetup.h " )
$wifiBoards = @ ( " arduino:avr:mega " , " esp32:esp32:esp32 " )
2023-04-08 00:38:02 +02:00
$userDirectory = $env:USERPROFILE + " \ "
2023-04-07 22:57:09 +02:00
$gitHubAPITags = " https://api.github.com/repos/DCC-EX/CommandStation-EX/git/refs/tags "
$gitHubURLPrefix = " https://github.com/DCC-EX/CommandStation-EX/archive/ "
if ( ( Get-WmiObject win32_operatingsystem | Select-Object osarchitecture ) . osarchitecture -eq " 64-bit " ) {
$arduinoCLIURL = " https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.zip "
2023-04-08 00:38:02 +02:00
$arduinoCLIZip = $userDirectory + " Downloads\ " + " arduino-cli_latest_Windows_64bit.zip "
2023-04-07 22:57:09 +02:00
} else {
$arduinoCLIURL = " https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_32bit.zip "
2023-04-08 00:38:02 +02:00
$arduinoCLIZip = $userDirectory + " Downloads\ " + " arduino-cli_latest_Windows_32bit.zip "
2023-04-07 22:57:09 +02:00
}
2023-04-08 00:39:42 +02:00
$arduinoCLIDirectory = $userDirectory + " arduino-cli "
2023-04-07 22:57:09 +02:00
$arduinoCLI = $arduinoCLIDirectory + " \arduino-cli.exe "
2023-04-07 00:06:32 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
List of supported devices with FQBN in case clones used that aren ' t detected
############################################>
$supportedDevices = @ (
@ {
name = " Arduino Mega or Mega 2560 "
fqbn = " arduino:avr:mega "
} ,
@ {
name = " Arduino Nano "
fqbn = " arduino:avr:nano "
} ,
@ {
name = " Arduino Uno "
fqbn = " arduino:avr:uno "
2023-04-10 11:52:31 +02:00
} ,
@ {
name = " ESP32 Dev Module "
fqbn = " esp32:esp32:esp32 "
}
)
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
List of supported displays and scroll modes
############################################>
$displayList = @ (
@ {
option = " LCD 16 columns x 2 rows "
configLine = " #define LCD_DRIVER 0x27,16,2 "
} ,
@ {
option = " LCD 16 columns x 4 rows "
configLine = " #define LCD_DRIVER 0x27,16,4 "
} ,
@ {
option = " OLED 128 x 32 "
configLine = " #define OLED_DRIVER 128,32,0x3c "
} ,
@ {
option = " OLED 128 x 64 "
configLine = " #define OLED_DRIVER 128,64,0x3c "
}
)
$scrollList = @ (
@ {
mode = " Continuous - fill screen if possible "
configLine = " #define SCROLLMODE 0 "
} ,
@ {
mode = " Page (default) - alternate between pages "
configLine = " #define SCROLLMODE 1 "
} ,
@ {
mode = " Row - move up one row at a time "
configLine = " #define SCROLLMODE 2 "
2023-04-07 00:06:32 +02:00
}
)
2023-04-05 07:54:48 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Set default action for progress indicators , warnings , and errors
############################################>
$global:ProgressPreference = " SilentlyContinue "
$global:WarningPreference = " SilentlyContinue "
$global:ErrorActionPreference = " SilentlyContinue "
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
If $buildDirectory not provided , generate a new time / date stamp based directory to use
############################################>
if ( ! $PSBoundParameters . ContainsKey ( 'buildDirectory' ) ) {
$buildDate = Get-Date -Format 'yyyyMMdd-HHmmss'
2023-04-08 00:38:02 +02:00
$buildDirectory = $userDirectory + " EX-CommandStation-Installer\ " + $buildDate
2023-04-05 07:54:48 +02:00
}
$commandStationDirectory = $buildDirectory + " \CommandStation-EX "
2023-04-04 07:48:11 +02:00
2023-04-05 07:54:48 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Write out intro message and prompt to continue
############################################>
@"
Welcome to the DCC-EX PowerShell installer for EX-CommandStation ( $installerVersion )
2023-04-04 07:48:11 +02:00
2023-04-05 07:54:48 +02:00
Current installer options :
2023-04-10 11:52:31 +02:00
2023-04-05 07:54:48 +02:00
- EX-CommandStation will be built in $commandStationDirectory
2023-04-10 11:52:31 +02:00
- Arduino CLI will downloaded and extracted to $arduinoCLIDirectory
2023-04-07 00:06:32 +02:00
2023-04-10 11:52:31 +02:00
Before continuing , please ensure :
- Your computer is connected to the internet
- The device you wish to install EX-CommandStation on is connected to a USB port
2023-04-04 07:48:11 +02:00
2023-04-10 11:52:31 +02:00
This installer will obtain the Arduino CLI ( if not already present ) , and then download and install your chosen version of EX-CommandStation
" @
2023-04-04 07:48:11 +02:00
2023-04-05 07:54:48 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2023-04-10 11:52:31 +02:00
Prompt user to confirm all is ready to proceed
2023-04-05 07:54:48 +02:00
############################################>
2023-04-10 11:52:31 +02:00
$confirmation = Read-Host " Enter 'Y' or 'y' then press <Enter> to confirm you are ready to proceed, any other key to exit "
if ( $confirmation -ne " Y " -and $confirmation -ne " y " ) {
Exit
} else {
Write-Output " Proceeding to obtain the Arduino CLI... "
2023-04-05 07:54:48 +02:00
}
2023-04-04 07:48:11 +02:00
2023-04-05 07:54:48 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
See if we have the Arduino CLI already , otherwise download and extract it
############################################>
if ( ! ( Test-Path -PathType Leaf -Path $arduinoCLI ) ) {
if ( ! ( Test-Path -PathType Container -Path $arduinoCLIDirectory ) ) {
try {
New-Item -ItemType Directory -Path $arduinoCLIDirectory | Out-Null
}
catch {
Write-Output " Arduino CLI does not exist and cannot create directory $arduinoCLIDirectory "
Exit
}
}
Write-Output " Downloading and extracting Arduino CLI "
try {
Invoke-WebRequest -Uri $arduinoCLIURL -OutFile $arduinoCLIZip
}
catch {
Write-Output " Failed to download Arduino CLI "
Exit
}
try {
Expand-Archive -Path $arduinoCLIZip -DestinationPath $arduinoCLIDirectory -Force
}
catch {
Write-Output " Failed to extract Arduino CLI "
}
}
2023-04-10 11:52:31 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Make sure Arduino CLI core index updated and list of boards populated
############################################>
# Need to do an initial board list to download everything first
try {
& $arduinoCLI core update-index | Out-Null
}
catch {
Write-Output " Failed to update Arduino CLI core index "
Exit
}
# Need to do an initial board list to download everything first
try {
& $arduinoCLI board list | Out-Null
}
catch {
Write-Output " Failed to update Arduino CLI board list "
Exit
}
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Identify available board ( s )
############################################>
try {
$boardList = & $arduinoCLI board list - -format jsonmini | ConvertFrom-Json
}
catch {
Write-Output " Failed to obtain list of boards "
Exit
}
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Get user to select board
############################################>
if ( $boardList . count -eq 0 ) {
Write-Output " Could not find any attached devices, please ensure your device is plugged in to a USB port and Windows recognises it "
Exit
} else {
@"
Devices attached to COM ports :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
" @
$boardSelect = 1
foreach ( $board in $boardList ) {
if ( $board . matching_boards . name ) {
$boardName = $board . matching_boards . name
} else {
$boardName = " Unknown device "
}
$port = $board . port . address
Write-Output " $boardSelect - $boardName on port $port "
$boardSelect + +
}
Write-Output " $boardSelect - Exit "
$userSelection = 0
do {
[ int ] $userSelection = Read-Host " `r `n Select the device to use from the list above "
} until (
( ( $userSelection -ge 1 ) -and ( $userSelection -le ( $boardList . count + 1 ) ) )
)
if ( $userSelection -eq ( $boardList . count + 1 ) ) {
Write-Output " Exiting installer "
Exit
} else {
$selectedBoard = $userSelection - 1
}
}
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
If the board is unknown , need to choose which one
############################################>
if ( $null -eq $boardList [ $selectedBoard ] . matching_boards . name ) {
Write-Output " The device selected is unknown, these boards are supported: `r `n "
$deviceSelect = 1
foreach ( $device in $supportedDevices ) {
Write-Output " $deviceSelect - $( $supportedDevices [ $deviceSelect - 1 ] . name ) "
$deviceSelect + +
}
Write-Output " $deviceSelect - Exit "
$userSelection = 0
do {
[ int ] $userSelection = Read-Host " Select the board type from the list above "
} until (
( ( $userSelection -ge 1 ) -and ( $userSelection -le ( $supportedDevices . count + 1 ) ) )
)
if ( $userSelection -eq ( $supportedDevices . count + 1 ) ) {
Write-Output " Exiting installer "
Exit
} else {
$deviceName = $supportedDevices [ $userSelection - 1 ] . name
$deviceFQBN = $supportedDevices [ $userSelection - 1 ] . fqbn
$devicePort = $boardList [ $selectedBoard ] . port . address
}
} else {
$deviceName = $boardList [ $selectedBoard ] . matching_boards . name
$deviceFQBN = $boardList [ $selectedBoard ] . matching_boards . fqbn
$devicePort = $boardList [ $selectedBoard ] . port . address
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2023-04-05 21:31:11 +02:00
Get the list of tags
2023-04-06 07:06:22 +02:00
############################################>
2023-04-05 21:31:11 +02:00
try {
2023-04-06 07:06:22 +02:00
$gitHubTags = Invoke-RestMethod -Uri $gitHubAPITags
2023-04-05 21:31:11 +02:00
}
catch {
Write-Output " Failed to obtain list of available EX-CommandStation versions "
Exit
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Get our GitHub tag list in a hash so we can sort by version numbers and extract just the ones we want
############################################>
$versionMatch = " .*?v(\d+)\.(\d+).(\d+)-(.*) "
$tagList = @ { }
foreach ( $tag in $gitHubTags ) {
$tagHash = @ { }
$tagHash [ " Ref " ] = $tag . ref
$version = $tag . ref . split ( " / " ) [ 2 ]
$null = $version -match $versionMatch
$tagHash [ " Major " ] = [ int ] $Matches [ 1 ]
$tagHash [ " Minor " ] = [ int ] $Matches [ 2 ]
$tagHash [ " Patch " ] = [ int ] $Matches [ 3 ]
$tagHash [ " Type " ] = $Matches [ 4 ]
$tagList . Add ( $version , $tagHash )
2023-04-05 21:31:11 +02:00
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Get latest two Prod and Devel for user to select
############################################>
$userList = @ { }
$prodCount = 1
$devCount = 1
$select = 1
foreach ( $tag in $tagList . Keys | Sort-Object { $tagList [ $_ ] [ " Major " ] } , { $tagList [ $_ ] [ " Minor " ] } , { $tagList [ $_ ] [ " Patch " ] } -Descending ) {
if ( ( $tagList [ $tag ] [ " Type " ] -eq " Prod " ) -and $prodCount -le 2 ) {
$userList [ $select ] = $tag
$select + +
$prodCount + +
} elseif ( ( $tagList [ $tag ] [ " Type " ] -eq " Devel " ) -and $devCount -le 2 ) {
$userList [ $select ] = $tag
$select + +
$devCount + +
2023-04-05 21:31:11 +02:00
}
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Display options for user to select and get the selection
############################################>
2023-04-08 00:38:02 +02:00
@"
Available EX-CommandStation versions :
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
" @
2023-04-06 07:06:22 +02:00
foreach ( $selection in $userList . Keys | Sort-Object $selection ) {
Write-Output " $selection - $( $userList [ $selection ] ) "
}
Write-Output " 5 - Exit "
$userSelection = 0
do {
2023-04-07 00:06:32 +02:00
[ int ] $userSelection = Read-Host " `r `n Select the version to install from the list above (1 - 5) "
2023-04-06 07:06:22 +02:00
} until (
( ( $userSelection -ge 1 ) -and ( $userSelection -le 5 ) )
)
if ( $userSelection -eq 5 ) {
Write-Output " Exiting installer "
Exit
} else {
$downloadURL = $gitHubURLPrefix + $tagList [ $userList [ $userSelection ] ] [ " Ref " ] + " .zip "
}
2023-04-10 11:52:31 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Create build directory if it doesn ' t exist , or fail
############################################>
if ( ! ( Test-Path -PathType Container -Path $buildDirectory ) ) {
try {
New-Item -ItemType Directory -Path $buildDirectory | Out-Null
}
catch {
Write-Output " Could not create build directory $buildDirectory "
Exit
}
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Download the chosen version to the build directory
############################################>
$downladFile = $buildDirectory + " \CommandStation-EX.zip "
Write-Output " Downloading and extracting $( $userList [ $userSelection ] ) "
try {
Invoke-WebRequest -Uri $downloadURL -OutFile $downladFile
}
catch {
Write-Output " Error downloading EX-CommandStation zip file "
Exit
}
2023-04-07 00:06:32 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
If folder exists , bail out and tell user
############################################>
if ( Test-Path -PathType Container -Path " $buildDirectory \CommandStation-EX " ) {
Write-Output " EX-CommandStation directory already exists, please ensure you have copied any user files then delete manually: $buildDirectory \CommandStation-EX "
Exit
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Extract and rename to CommandStation-EX to allow building
############################################>
try {
Expand-Archive -Path $downladFile -DestinationPath $buildDirectory -Force
}
catch {
Write-Output " Failed to extract EX-CommandStation zip file "
Exit
}
$folderName = $buildDirectory + " \CommandStation-EX- " + ( $userList [ $userSelection ] -replace " ^v " , " " )
try {
Rename-Item -Path $folderName -NewName $commandStationDirectory
}
catch {
Write-Output " Could not rename folder "
Exit
}
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
If config directory provided , copy files here
############################################>
2023-04-07 11:30:15 +02:00
if ( $PSBoundParameters . ContainsKey ( 'configDirectory' ) ) {
if ( Test-Path -PathType Container -Path $configDirectory ) {
foreach ( $file in $configFiles ) {
if ( Test-Path -PathType Leaf -Path " $configDirectory \ $file " ) {
Copy-Item -Path " $configDirectory \ $file " -Destination " $commandStationDirectory \ $file "
}
}
} else {
2023-04-10 11:52:31 +02:00
Write-Output " User provided configuration directory $configDirectory does not exist, skipping "
2023-04-07 11:30:15 +02:00
}
2023-04-10 11:52:31 +02:00
} else {
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2023-04-10 11:52:31 +02:00
If no config directory provided , prompt for display option , and WiFi if using Mega
2023-04-06 07:06:22 +02:00
############################################>
2023-04-10 11:52:31 +02:00
Write-Output " `r `n If you have an LCD or OLED display connected, you can configure it here `r `n "
$displaySelect = 1
foreach ( $display in $displayList ) {
Write-Output " $displaySelect - $( $displayList [ $displaySelect - 1 ] . option ) "
$displaySelect + +
2023-04-07 00:06:32 +02:00
}
2023-04-10 11:52:31 +02:00
Write-Output " $( $displayList . Count + 1 ) - I have no display "
Write-Output " $( $displayList . Count + 2 ) - Exit "
2023-04-07 00:06:32 +02:00
do {
2023-04-10 11:52:31 +02:00
[ int ] $displayChoice = Read-Host " `r `n Select a display option "
2023-04-07 00:06:32 +02:00
} until (
2023-04-10 11:52:31 +02:00
( $displayChoice -ge 1 -and $displayChoice -le ( $displayList . Count + 2 ) )
2023-04-07 00:06:32 +02:00
)
2023-04-10 11:52:31 +02:00
if ( $displayChoice -eq ( $displayList . Count + 2 ) ) {
2023-04-07 00:06:32 +02:00
Exit
2023-04-10 11:52:31 +02:00
} elseif ( $displayChoice -le ( $displayList . Count + 1 ) ) {
$displayLine = $displayList [ $displayChoice - 1 ] . configLine
$scrollSelect = 1
$defaultScroll = 1
Write-Host " `r `n Select a scroll option, or press <Enter> to accept the default [ $( $defaultScroll ) ] "
foreach ( $scroll in $scrollList ) {
Write-Output " $scrollSelect - $( $scrollList [ $scrollSelect - 1 ] . mode ) "
$scrollSelect + +
}
Write-Output " $( $scrollList . Count + 1 ) - Exit "
do {
[ int ] $displayScroll = Read-Host " `r `n Select a scroll option, or press <Enter> to accept the default [ $( $defaultScroll ) ] "
} until (
( ( $displayScroll -ge 1 -and $displayScroll -le ( $scrollList . Count + 1 ) ) -or $displayScroll -eq " " )
)
if ( $displayScroll -eq ( $scrollList . Count + 1 ) ) {
Exit
} elseif ( $displayScroll -eq " " ) {
$displayScroll = $defaultScroll
}
$scrollLine = $scrollList [ $displayScroll - 1 ]
}
if ( $wifiBoards . Contains ( $deviceFQBN ) ) {
# WiFi prompt
2023-04-07 00:06:32 +02:00
}
}
2023-04-06 07:06:22 +02:00
2023-04-07 00:06:32 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2023-04-10 11:52:31 +02:00
If display or WiFi options set , create config . h
2023-04-07 00:06:32 +02:00
############################################>
2023-04-10 11:52:31 +02:00
2023-04-06 07:06:22 +02:00
2023-04-07 22:22:09 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Install core libraries for the platform
############################################>
$platformArray = $deviceFQBN . split ( " : " )
$platform = $platformArray [ 0 ] + " : " + $platformArray [ 1 ]
try {
& $arduinoCLI core install $platform
}
catch {
Write-Output " Error install core libraries "
Exit
}
2023-04-06 07:06:22 +02:00
<# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
Upload the sketch to the selected board
############################################>
#$arduinoCLI upload -b fqbn -p port $commandStationDirectory
2023-04-07 11:30:15 +02:00
Write-Output " Compiling and uploading to $deviceName on $devicePort "
2023-04-07 00:06:32 +02:00
try {
2023-04-07 11:30:15 +02:00
$output = & $arduinoCLI compile -b $deviceFQBN -u -t -p $devicePort $commandStationDirectory - -format jsonmini | ConvertFrom-Json
2023-04-07 00:06:32 +02:00
}
catch {
Write-Output " Failed to compile "
Exit
}
2023-04-07 22:22:09 +02:00
if ( $output . success -eq " True " ) {
Write-Output " `r `n Congratulations! DCC-EX EX-CommandStation $( $userList [ $userSelection ] ) has been installed on your $deviceName `r `n "
} else {
Write-Output " `r `n There was an error installing $( $userList [ $userSelection ] ) on your $( $deviceName ) , please take note of the errors provided: `r `n "
if ( $null -ne $output . compiler_err ) {
Write-Output " Compiler error: $( $output . compiler_err ) `r `n "
}
if ( $null -ne $output . builder_result ) {
Write-Output " Builder result: $( $output . builder_result ) `r `n "
}
}