99)
1010
1111# Script configuration
12- $ScriptVersion = " 1.0 .0"
12+ $ScriptVersion = " 1.1 .0"
1313$ErrorActionPreference = " Stop"
1414
1515# Global variables
@@ -26,6 +26,37 @@ $ServiceInstalled = $false
2626$DockerInstalled = $false
2727$UpdatingExisting = $false
2828
29+ # Create version info file with installer version and git hash
30+ function New-VersionInfo {
31+ $gitHash = " unknown"
32+ $gitBranch = $Branch
33+ $gitRepo = $Repo
34+
35+ # Try to resolve the branch/tag to a specific commit hash via GitHub API
36+ try {
37+ $apiUrl = " https://api.github.com/repos/$gitRepo /commits/$gitBranch "
38+ $response = Invoke-WebRequest - Uri $apiUrl - UseBasicParsing
39+ $json = $response.Content | ConvertFrom-Json
40+ $gitHash = $json.sha.Substring (0 , 7 )
41+ }
42+ catch {
43+ Write-Host " WARNING: Could not fetch git hash from GitHub API" - ForegroundColor Yellow
44+ }
45+
46+ # Create version info JSON file
47+ $versionInfo = @ {
48+ installer_version = $ScriptVersion
49+ git_hash = $gitHash
50+ git_branch = $gitBranch
51+ git_repo = $gitRepo
52+ install_date = (Get-Date ).ToUniversalTime().ToString(" yyyy-MM-ddTHH:mm:ssZ" )
53+ } | ConvertTo-Json - Depth 2
54+
55+ $versionInfo | Out-File - FilePath (Join-Path $InstallDir " .version_info" ) - Encoding UTF8
56+
57+ Write-Host " INFO: Version info saved: $ScriptVersion -$gitHash ($gitRepo @$gitBranch )" - ForegroundColor Blue
58+ }
59+
2960# Helper function for Windows Bluetooth API pairing
3061function Invoke-BluetoothPairing {
3162 param (
@@ -115,15 +146,15 @@ EOF
115146 Remove-Item $tempScript - ErrorAction SilentlyContinue
116147
117148 if ($wslResult -match " Pairing successful" -or $gitBashResult -match " Pairing successful" ) {
118- return $true
149+ return $true
119150 } else {
120151 Write-Host " DEBUG: bluetoothctl pairing failed" - ForegroundColor Gray
121- return $false
122- }
152+ return $false
153+ }
123154
124155 } catch {
125156 Write-Host " DEBUG: bluetoothctl approach failed: $ ( $_.Exception.Message ) " - ForegroundColor Gray
126- return $false
157+ return $false
127158 }
128159}
129160
@@ -158,9 +189,9 @@ function Configure-SingleMqttBroker {
158189
159190 $envLocal = Join-Path $InstallDir " .env.local"
160191
161- Write-Host " "
192+ Write-Host " "
162193 Write-Host " INFO: Configuring MQTT Broker $BrokerNum " - ForegroundColor Blue
163- Write-Host " "
194+ Write-Host " "
164195
165196 # Server configuration
166197 $server = Read-Host " MQTT Server hostname/IP"
@@ -350,7 +381,7 @@ function Start-Installation {
350381 Write-Host " SUCCESS: Installation directory created" - ForegroundColor Green
351382
352383 # Check Python
353- Write-Host " "
384+ Write-Host " "
354385 Write-Host " INFO: Checking Python installation..." - ForegroundColor Blue
355386
356387 try {
@@ -366,7 +397,7 @@ function Start-Installation {
366397 Write-Host " SUCCESS: Python 3 found: $pythonVersion " - ForegroundColor Green
367398
368399 # Download files first
369- Write-Host " "
400+ Write-Host " "
370401 Write-Host " INFO: Downloading application files..." - ForegroundColor Blue
371402
372403 if ($env: LOCAL_INSTALL ) {
@@ -380,9 +411,12 @@ function Start-Installation {
380411 if (Test-Path " $env: LOCAL_INSTALL \.env" ) {
381412 Copy-Item " $env: LOCAL_INSTALL \.env" $InstallDir \
382413 }
414+ # Create version info file
415+ New-VersionInfo
416+
383417 Write-Host " SUCCESS: Files copied from local directory" - ForegroundColor Green
384- }
385- else {
418+ }
419+ else {
386420 # Download from GitHub
387421 Write-Host " INFO: Downloading from GitHub ($Repo @ $Branch )..." - ForegroundColor Blue
388422
@@ -403,6 +437,9 @@ function Start-Installation {
403437 }
404438 }
405439
440+ # Create version info file
441+ New-VersionInfo
442+
406443 Write-Host " SUCCESS: Files downloaded and verified" - ForegroundColor Green
407444 }
408445
@@ -412,8 +449,8 @@ function Start-Installation {
412449 if (-not (Test-Path (Join-Path $InstallDir " venv" ))) {
413450 python - m venv (Join-Path $InstallDir " venv" )
414451 Write-Host " SUCCESS: Virtual environment created" - ForegroundColor Green
415- }
416- else {
452+ }
453+ else {
417454 Write-Host " SUCCESS: Using existing virtual environment" - ForegroundColor Green
418455 }
419456
@@ -467,7 +504,7 @@ function Start-Installation {
467504 Write-Host " SUCCESS: Selected Serial Connection" - ForegroundColor Green
468505
469506 # Detect serial devices
470- Write-Host " "
507+ Write-Host " "
471508 Write-Host " INFO: Detecting serial devices..." - ForegroundColor Blue
472509
473510 $devices = @ ()
@@ -517,8 +554,8 @@ function Start-Installation {
517554 Write-Host " $ ( $i + 1 ) ) $ ( $devices [$i ]) " - ForegroundColor Blue
518555 }
519556 Write-Host " $ ( $devices.Count + 1 ) ) Enter path manually" - ForegroundColor Blue
520- Write-Host " "
521-
557+ Write-Host " "
558+
522559 while ($true ) {
523560 $choice = Read-Host " Select device [1-$ ( $devices.Count + 1 ) ]"
524561 if ($choice -match ' ^\d+$' -and [int ]$choice -ge 1 -and [int ]$choice -le ($devices.Count + 1 )) {
@@ -529,8 +566,8 @@ function Start-Installation {
529566 $script :SelectedSerialDevice = $devices [([int ]$choice - 1 )]
530567 }
531568 break
532- }
533- else {
569+ }
570+ else {
534571 Write-Host " ERROR: Invalid selection. Please enter a number between 1 and $ ( $devices.Count + 1 ) " - ForegroundColor Red
535572 }
536573 }
@@ -621,8 +658,8 @@ function Start-Installation {
621658 $script :SelectedBleName = $selectedDevice.FriendlyName
622659 }
623660 break
624- }
625- else {
661+ }
662+ else {
626663 Write-Host " ERROR: Invalid selection. Please enter a number between 1 and $ ( $pairedMeshCoreDevices.Count + 1 ) " - ForegroundColor Red
627664 }
628665 }
@@ -694,8 +731,8 @@ function Start-Installation {
694731 if ([int ]$choice -eq ($meshcoreDevices.Count + 1 )) {
695732 $script :SelectedBleDevice = Read-Host " Enter BLE device MAC address" " "
696733 $script :SelectedBleName = Read-Host " Enter device name (optional)" " "
697- }
698- else {
734+ }
735+ else {
699736 $selectedDevice = $meshcoreDevices [([int ]$choice - 1 )]
700737 # Extract MAC address from Address if it's a Windows device ID
701738 $macAddress = $selectedDevice.Address
@@ -711,8 +748,8 @@ function Start-Installation {
711748 $script :SelectedBleName = $selectedDevice.Name
712749 }
713750 break
714- }
715- else {
751+ }
752+ else {
716753 Write-Host " ERROR: Invalid selection. Please enter a number between 1 and $ ( $meshcoreDevices.Count + 1 ) " - ForegroundColor Red
717754 }
718755 }
@@ -723,7 +760,7 @@ function Start-Installation {
723760 Write-Host " - Powered on and within range" - ForegroundColor Blue
724761 Write-Host " - In pairing mode (if not already paired)" - ForegroundColor Blue
725762 Write-Host " - Not connected to another device" - ForegroundColor Blue
726- Write-Host " "
763+ Write-Host " "
727764 $script :SelectedBleDevice = Read-Host " Enter BLE device MAC address" " "
728765 $script :SelectedBleName = Read-Host " Enter device name (optional)" " "
729766 }
@@ -750,8 +787,8 @@ function Start-Installation {
750787
751788 if ($pairedDevice -and $pairedDevice.Status -eq " OK" ) {
752789 Write-Host " SUCCESS: Device is already paired and ready to use" - ForegroundColor Green
753- }
754- else {
790+ }
791+ else {
755792 Write-Host " INFO: Device requires pairing" - ForegroundColor Blue
756793 Write-Host " INFO: Attempting to pair programmatically..." - ForegroundColor Blue
757794
@@ -850,9 +887,9 @@ function Start-Installation {
850887 Write-Host " WARNING: Pairing attempt failed: $ ( $_.Exception.Message ) " - ForegroundColor Yellow
851888 Write-Host " INFO: Please pair the device manually using Windows Bluetooth settings" - ForegroundColor Blue
852889 }
853- }
854- }
855- catch {
890+ }
891+ }
892+ catch {
856893 Write-Host " WARNING: Could not check pairing status: $ ( $_.Exception.Message ) " - ForegroundColor Yellow
857894 Write-Host " INFO: You may need to pair the device manually" - ForegroundColor Blue
858895 }
@@ -921,46 +958,46 @@ PACKETCAPTURE_ADVERT_INTERVAL_HOURS=11
921958 Set-Content - Path $envLocal - Value $configContent
922959
923960 # Configure IATA code
924- Write-Host " "
961+ Write-Host " "
925962 Write-Host " INFO: IATA code is a 3-letter airport code identifying your geographic region" - ForegroundColor Blue
926963 Write-Host " INFO: Example: SEA (Seattle), LAX (Los Angeles), NYC (New York), LON (London)" - ForegroundColor Blue
927- Write-Host " "
928-
929- $script :Iata = " "
930- while (-not $script :Iata -or $script :Iata -eq " XXX" ) {
931- $script :Iata = Read-Host " Enter your IATA code (3 letters)"
932- $script :Iata = $script :Iata.ToUpper ().Trim()
933-
934- if (-not $script :Iata ) {
964+ Write-Host " "
965+
966+ $script :Iata = " "
967+ while (-not $script :Iata -or $script :Iata -eq " XXX" ) {
968+ $script :Iata = Read-Host " Enter your IATA code (3 letters)"
969+ $script :Iata = $script :Iata.ToUpper ().Trim()
970+
971+ if (-not $script :Iata ) {
935972 Write-Host " ERROR: IATA code cannot be empty" - ForegroundColor Red
936- }
937- elseif ($script :Iata -eq " XXX" ) {
973+ }
974+ elseif ($script :Iata -eq " XXX" ) {
938975 Write-Host " ERROR: Please enter your actual IATA code, not XXX" - ForegroundColor Red
939- }
940- elseif ($script :Iata.Length -ne 3 ) {
976+ }
977+ elseif ($script :Iata.Length -ne 3 ) {
941978 Write-Host " WARNING: IATA code should be 3 letters, you entered: $script :Iata " - ForegroundColor Yellow
942979 $response = Read-Host " Use '$script :Iata ' anyway? (y/N)"
943980 if ($response -notmatch ' ^[yY]' ) {
944981 $script :Iata = " XXX" # Reset to force re-prompt
945- }
946- }
947- }
948-
949- # Update IATA in config
982+ }
983+ }
984+ }
985+
986+ # Update IATA in config
950987 $content = Get-Content $envLocal
951- $content = $content -replace " ^PACKETCAPTURE_IATA=.*" , " PACKETCAPTURE_IATA=$script :Iata "
988+ $content = $content -replace " ^PACKETCAPTURE_IATA=.*" , " PACKETCAPTURE_IATA=$script :Iata "
952989 Set-Content - Path $envLocal - Value $content
953990 Write-Host " SUCCESS: IATA code set to: $script :Iata " - ForegroundColor Green
954991
955992 # Configure MQTT brokers
956- Write-Host " "
993+ Write-Host " "
957994 Write-Host " INFO: MQTT Broker Configuration" - ForegroundColor Blue
958995 Write-Host " INFO: Enable the LetsMesh.net Packet Analyzer (mqtt-us-v1.letsmesh.net) broker?" - ForegroundColor Blue
959996 Write-Host " • Real-time packet analysis and visualization" - ForegroundColor Blue
960997 Write-Host " • Network health monitoring" - ForegroundColor Blue
961998 Write-Host " • Requires meshcore-decoder for authentication" - ForegroundColor Blue
962- Write-Host " "
963-
999+ Write-Host " "
1000+
9641001 $response = Read-Host " Enable LetsMesh Packet Analyzer? (y/N)"
9651002 if ($response -match ' ^[yY]' ) {
9661003 $letsMeshConfig = @"
@@ -979,17 +1016,17 @@ PACKETCAPTURE_MQTT1_KEEPALIVE=120
9791016 Write-Host " SUCCESS: LetsMesh Packet Analyzer enabled" - ForegroundColor Green
9801017
9811018 # Configure topics for LetsMesh
982- Write-Host " "
1019+ Write-Host " "
9831020 Write-Host " INFO: MQTT Topic Configuration for Broker 1" - ForegroundColor Blue
9841021 Write-Host " INFO: MQTT topics define where different types of data are published." - ForegroundColor Blue
9851022 Write-Host " INFO: You can use template variables: {IATA}, {IATA_lower}, {PUBLIC_KEY}" - ForegroundColor Blue
986- Write-Host " "
1023+ Write-Host " "
9871024 Write-Host " Choose topic configuration:" - ForegroundColor Blue
9881025 Write-Host " 1) Default pattern (meshcore/{IATA}/{PUBLIC_KEY}/status, meshcore/{IATA}/{PUBLIC_KEY}/packets)" - ForegroundColor Blue
9891026 Write-Host " 2) Classic pattern (meshcore/status, meshcore/packets, meshcore/raw)" - ForegroundColor Blue
9901027 Write-Host " 3) Custom topics (enter your own)" - ForegroundColor Blue
991- Write-Host " "
992-
1028+ Write-Host " "
1029+
9931030 $topicChoice = Read-Host " Select topic configuration [1-3]" " 1" " 1"
9941031
9951032 switch ($topicChoice ) {
@@ -1000,17 +1037,17 @@ PACKETCAPTURE_MQTT1_KEEPALIVE=120
10001037 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_STATUS=meshcore/{IATA}/{PUBLIC_KEY}/status"
10011038 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_PACKETS=meshcore/{IATA}/{PUBLIC_KEY}/packets"
10021039 Write-Host " SUCCESS: Default pattern topics configured" - ForegroundColor Green
1003- }
1004- " 2" {
1040+ }
1041+ " 2" {
10051042 # Classic pattern (simple meshcore topics, needed for map.w0z.is)
10061043 Add-Content - Path $envLocal - Value " "
10071044 Add-Content - Path $envLocal - Value " # MQTT Topics for Broker 1 - Classic Pattern"
10081045 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_STATUS=meshcore/status"
10091046 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_PACKETS=meshcore/packets"
10101047 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_RAW=meshcore/raw"
10111048 Write-Host " SUCCESS: Classic pattern topics configured" - ForegroundColor Green
1012- }
1013- " 3" {
1049+ }
1050+ " 3" {
10141051 # Custom topics
10151052 Write-Host " "
10161053 Write-Host " INFO: Enter custom topic paths (use {IATA}, {IATA_lower}, {PUBLIC_KEY} for templates)" - ForegroundColor Blue
@@ -1025,8 +1062,8 @@ PACKETCAPTURE_MQTT1_KEEPALIVE=120
10251062 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_STATUS=$statusTopic "
10261063 Add-Content - Path $envLocal - Value " PACKETCAPTURE_MQTT1_TOPIC_PACKETS=$packetsTopic "
10271064 Write-Host " SUCCESS: Custom topics configured" - ForegroundColor Green
1028- }
1029- default {
1065+ }
1066+ default {
10301067 Write-Host " ERROR: Invalid choice, using default pattern" - ForegroundColor Red
10311068 Add-Content - Path $envLocal - Value " "
10321069 Add-Content - Path $envLocal - Value " # MQTT Topics for Broker 1 - Default Pattern"
@@ -1036,7 +1073,7 @@ PACKETCAPTURE_MQTT1_KEEPALIVE=120
10361073 }
10371074
10381075 # Ask if user wants to configure additional MQTT brokers
1039- Write-Host " "
1076+ Write-Host " "
10401077 $addMoreBrokers = Read-Host " Would you like to configure additional MQTT brokers? (y/N)"
10411078 if ($addMoreBrokers -match ' ^[yY]' ) {
10421079 Configure- AdditionalMqttBrokers
0 commit comments