Compare commits

..

7 Commits

15 changed files with 274 additions and 92 deletions

View File

@@ -14,3 +14,4 @@ scripts/services.ps1
drizzle.config.ts
tsconfig.json
.includeCleanup
.env-example

View File

@@ -1,5 +1,6 @@
lstWrapper/publish
controller/lst_ctl.exe
controller/.env-example
scripts/update-controller-bumpBuild.ps1
scripts/update-controller-server.ps1
scripts/update-controller-zip.ps1

View File

@@ -5,7 +5,7 @@ meta {
}
post {
url: http://usmcd1vms036:8080/api/controller/update
url: http://usmar1vms006:8080/lst/api/controller/update
body: json
auth: inherit
}

View File

@@ -13,7 +13,7 @@ import (
socketio "github.com/googollee/go-socket.io"
)
func copyBuild(server *socketio.Server, plant string) {
func copyBuild(server *socketio.Server, plant string, drive string) {
// Load from environment in real-life code!
user := os.Getenv("ADM_USER")
pass := os.Getenv("ADM_PASS")
@@ -21,7 +21,7 @@ func copyBuild(server *socketio.Server, plant string) {
// latest build
latestbuild := lastestBuild()
src := latestbuild
plantServer := fmt.Sprintf("\\\\%v\\e$\\lst", plant)
plantServer := fmt.Sprintf("\\\\%v\\%v$\\lst", plant, drive)
// Build PowerShell
psScript := fmt.Sprintf(`

View File

@@ -31,6 +31,8 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/robfig/cron/v3 v3.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect

View File

@@ -55,6 +55,10 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E=
github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=

View File

@@ -74,6 +74,13 @@
</div>
<div id="logWindow"></div>
<div>
<button id="USMCD1VMS036">USMCD1VMS036</button>
<button id="USBET1VMS006">USBET1VMS006</button>
<button id="USBOW1VMS006">USBOW1VMS006</button>
<button id="USSLC1VMS006">USSLC1VMS006</button>
<button id="USSTP1VMS006">USSTP1VMS006</button>
</div>
<script>
// ✅ Define socket in global scope
@@ -198,6 +205,50 @@
};
};
// all the server copy buttons
document.getElementById("USMCD1VMS036").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USMCD1VMS036",
drive: "e",
}); // "frontend" = payload target
logMessage("info", "Copying to USMCD1VMS036");
};
document.getElementById("USBET1VMS006").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USBET1VMS006",
drive: "e",
}); // "frontend" = payload target
logMessage("info", "Copying to USBET1VMS006");
};
document.getElementById("USBOW1VMS006").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USBOW1VMS006",
drive: "e",
}); // "frontend" = payload target
logMessage("info", "Copying to USBOW1VMS006");
};
document.getElementById("USSLC1VMS006").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USSLC1VMS006",
drive: "e",
}); // "frontend" = payload target
logMessage("info", "Copying to USSLC1VMS006");
};
document.getElementById("USSTP1VMS006").onclick = () => {
socket.emit("update", {
action: "copy",
target: "USSTP1VMS006",
drive: "d",
}); // "frontend" = payload target
logMessage("info", "Copying to USSLC1VMS006");
};
socket.on("logs", (msg) => logMessage("logs", msg));
socket.on("errors", (msg) => logMessage("errors", msg));
socket.on("buildlogs", (msg) => logMessage("build", msg));

View File

@@ -0,0 +1,5 @@
package bot
func main() {
}

View File

@@ -6,11 +6,13 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/gin-gonic/gin"
socketio "github.com/googollee/go-socket.io"
"github.com/joho/godotenv"
"lst.net/pkg"
)
func main() {
@@ -90,13 +92,42 @@ func main() {
registerUpdateChannel(server)
// Broadcast logs to room
go func() {
for i := 0; ; i++ {
time.Sleep(2 * time.Second)
msg := fmt.Sprintf("Log line %d @ %s", i, time.Now().Format(time.RFC3339))
server.BroadcastToRoom("/", "logs", "logs", msg)
// go func() {
// for i := 0; ; i++ {
// time.Sleep(2 * time.Second)
// msg := fmt.Sprintf("Log line %d @ %s", i, time.Now().Format(time.RFC3339))
// server.BroadcastToRoom("/", "logs", "logs", msg)
// }
// }()
// go pkg.JobScheduler(server, "0 9 * * *", func() {
// fmt.Println("This is the time checker")
// server.BroadcastToRoom("/", "logs", "logs", "Just ran at 9:00 for example")
// })
// schedule the update checker
go pkg.JobScheduler(server, "0 8 * * 1-4", func() {
host, err := os.Hostname()
if err != nil {
server.BroadcastToRoom("/", "update", "updateLogs", "Could not retrieve hostname")
return
}
}()
if strings.Contains(host, "VMS") || strings.Contains(host, "vms") {
fmt.Println("On a server ok to start the update job")
server.BroadcastToRoom("/", "update", "updateLogs", "On a server ok to start the update job")
updates := UpdateApp(server)
fmt.Println("📦 Starting update loop")
for msg := range updates { // this will block until the channel closes
fmt.Println(msg)
server.BroadcastToRoom("/", "logs", "logs", msg)
}
fmt.Println("✅ Update process finished")
}
})
// Broadcast errors to room
go func() {

View File

@@ -0,0 +1,31 @@
package pkg
import (
"fmt"
"time"
_ "time/tzdata"
socketio "github.com/googollee/go-socket.io"
"github.com/robfig/cron/v3"
)
func JobScheduler(server *socketio.Server, cronTime string, jobFunc func()) {
// time zone helper https://nodatime.org/TimeZones
loc, err := time.LoadLocation(("America/Chicago"))
if err != nil {
fmt.Printf("There was an error getting location: %v", err)
server.BroadcastToRoom("/", "logs", "logs", fmt.Sprintf("There was an error getting location: %v", err))
}
crontJob := cron.New(cron.WithLocation(loc)) // cron.WithSeconds()
// reference for the cron time format https://pkg.go.dev/github.com/robfig/cron@v1.2.0#hdr-CRON_Expression_Format
// we can use 6 feilds but we need to add this in with cron.WithSeconds into our cron job other wise we can use use the standard 5 fields https://crontab.guru/
crontJob.AddFunc(cronTime, jobFunc)
crontJob.Start()
}

View File

@@ -17,6 +17,7 @@ import (
type UpdatePayload struct {
Action string `json:"action"`
Target string `json:"target"`
Drive string `json:"drive"`
}
func registerUpdateChannel(server *socketio.Server) {
@@ -31,7 +32,7 @@ func registerUpdateChannel(server *socketio.Server) {
server.OnEvent("/", "update", func(s socketio.Conn, payload UpdatePayload) {
switch strings.ToLower(payload.Action) {
case "copy":
copyLatestBuild(server, payload.Target)
copyLatestBuild(server, payload.Target, payload.Drive)
case "update":
updateServer(server, payload.Target)
@@ -80,10 +81,10 @@ func updateServer(server *socketio.Server, target string) {
}
}
func copyLatestBuild(server *socketio.Server, target string) {
func copyLatestBuild(server *socketio.Server, target string, drive string) {
server.BroadcastToRoom("/", "update", "updateLogs",
fmt.Sprintf("🚀 Copying latest build to %v", target))
copyBuild(server, target)
copyBuild(server, target, drive)
}
func triggerRemoteUpdate(server *socketio.Server, remoteURL string, payload UpdatePayload) {

View File

@@ -46,7 +46,7 @@ Please note that if you plan to utlize the scanner app you must use IIS to run a
- Change the phycical path to the path that you have the lst wrapper in, below is the example we used to install the app from the install instructions.
```bash
E:\LST\lstWrapper
E:\LST\lstWrapper\publish
```
![](/img/install/application.png)

View File

@@ -53,8 +53,6 @@ Lastly scan the cage of preforms, resin, or color you will be consuming to the l
## Consuming new manual material via LST.
NOTE: you will need to be logged in and permissions in lst to be able to consume material.
Click on material helper on the left side bar.
Enter the lot and running number and click consume, the card also comes with basic insturctions.

View File

@@ -5,7 +5,8 @@ function Update-Server {
[string]$AppRoot,
[string]$Destination,
[string]$Server,
[string]$Token
[string]$Token,
[string]$ControllerBuild
)
@@ -26,7 +27,8 @@ function Update-Server {
if ($num) {
$BuildNumber = $num + 1
} else {
}
else {
$BuildNumber = 1
}
}
@@ -35,7 +37,13 @@ function Update-Server {
$BuildNumber = $BuildNumber - 1
# Convert to string
$BuildNumber = $BuildNumber.ToString()
if ($ControllerBuild -eq "yes") {
$BuildNumber = $BuildNumber.ToString()
}
else {
$BuildNumber = ([int]$BuildNumber - 1).ToString()
}
# copy the latest build over
@@ -56,9 +64,11 @@ function Update-Server {
$zipFile = Join-Path $BuildFolder "controllers-$BuildNumber.zip"
Copy-Item -Path $zipFile -Destination "z:\" -Force
Write-Host "Files copied to $($Server)"
} catch {
}
catch {
Write-Host "Error: $_"
} finally {
}
finally {
# Remove the mapped drive after copying
if (Get-PSDrive -Name "z" -ErrorAction SilentlyContinue) {
Write-Host "Removing mapped drive..."
@@ -68,73 +78,78 @@ function Update-Server {
# do the stop services, unzip, and restart service and pool
$ControllerUpdate = {
$ControllerUpdate = {
param ($Server, $Token, $Destination, $BuildFile)
write-host "Running the update process now"
# Change the destination to be local
$LocalPath = $Destination -replace '\$', ':'
$BuildFileLoc = "$LocalPath\$BuildFile"
write-host "Running the update process now"
# Change the destination to be local
$LocalPath = $Destination -replace '\$', ':'
$BuildFileLoc = "$LocalPath\$BuildFile"
# where is nssm.exe
$nssmPath= Join-Path $LocalPath "nssm.exe"
$npmPath = "C:\Program Files\nodejs\npm.cmd"
# where is nssm.exe
#$nssmPath = Join-Path $LocalPath "nssm.exe"
#$npmPath = "C:\Program Files\nodejs\npm.cmd"
Write-Host "Stopping the services to do the updates, pkgs and db changes."
Write-Host "Stopping the services to do the updates, pkgs and db changes."
$Controller = "LST_ctl$(if ($Token -eq "usiow2") { "_2" })"
$Wrapper = "LogisticsSupportTool$(if ($token -eq "usiow2") { "_2" })"
$Controller = "LST_ctl$(if ($Token -eq "usiow2") { "_2" })"
$Wrapper = "LogisticsSupportTool$(if ($token -eq "usiow2") { "_2" })"
Write-Host "Stopping $($Controller)"
Stop-Service -DisplayName $Controller -Force
Start-Sleep -Seconds 1
Write-Host "Stopping $($Controller)"
Stop-Service -DisplayName $Controller -Force
Start-Sleep -Seconds 1
try {
Stop-WebAppPool -Name $Wrapper -ErrorAction Stop
Write-Host "Stopping $($Wrapper)"
try {
Stop-WebAppPool -Name $Wrapper -ErrorAction Stop
Start-Sleep -Seconds 2
$state = (Get-WebAppPoolState -Name $Wrapper).Value
Write-Host "Result: $state"
} catch {
Write-Error $_.Exception.Message
}
Start-Sleep -Seconds 2
$state = (Get-WebAppPoolState -Name $Wrapper).Value
Write-Host "Result: $state"
}
catch {
Write-Error $_.Exception.Message
}
Write-Host "Unzipping the folder..."
write-host $BuildFileLoc
write-host $LocalPath
Write-Host "Unzipping the folder..."
#write-host $BuildFileLoc
#write-host $LocalPath
# Extract the files to the build path
try {
# Expand the archive
Expand-Archive -Path $BuildFileLoc -DestinationPath $LocalPath -Force
} catch {
Write-Host "Error: $_"
exit 1 # Exit with a non-zero code if there's an error
}
# Extract the files to the build path
try {
# Expand the archive
Expand-Archive -Path $BuildFileLoc -DestinationPath $LocalPath -Force
}
catch {
Write-Host "Error: $_"
exit 1 # Exit with a non-zero code if there's an error
}
# Delete the zip file after extraction
Write-Host "Deleting the zip file..."
Remove-Item -Path $BuildFileLoc -Force
# Delete the zip file after extraction
Write-Host "Deleting the zip file..."
Remove-Item -Path $BuildFileLoc -Force
Start-Sleep -Seconds 1
Start-Sleep -Seconds 1
Write-Host "Starting $($Controller)"
Start-Service -DisplayName $Controller
Start-Sleep -Seconds 1
Write-Host "Starting $($Controller)"
Start-Service -DisplayName $Controller
Start-Sleep -Seconds 1
try {
Start-WebAppPool -Name $Wrapper
Start-Sleep -Seconds 2
$state = (Get-WebAppPoolState -Name $Wrapper).Value
Write-Host "Result: $state"
} catch {
Write-Error $_.Exception.Message
exit 1
}
Write-Host "Starting $($Wrapper)"
try {
Start-WebAppPool -Name $Wrapper
Start-Sleep -Seconds 2
$state = (Get-WebAppPoolState -Name $Wrapper).Value
Write-Host "Result: $state"
}
catch {
Write-Error $_.Exception.Message
exit 1
}
write-host "Controllers updated and restarted :D"
write-host "Controllers updated and restarted :D"
}

View File

@@ -1,8 +1,9 @@
param (
[string]$App_Path = "C:\Users\matthes01\Documents\lst", # with this it makes it optional to pass a new parameter over.
[string]$Server = "usmcd1vms036",
[string]$Token = "test3",
[string]$Remote_Path = "E$\LST"
[string]$Remote_Path = "E$\LST",
[string]$BuildController = "yes",
[string]$PlantToUpdate = "all"
)
# imports of the other functions
@@ -11,7 +12,19 @@ param (
. ".\update-controller-server"
# example string to pass over, you must be in the script dir when you run this script. or it will fail to find the linked scripts
# .\update-controllers.ps1 -App_Path "C:\Users\matthes01\Documents\lst" -Server "usmcd1vms036" -Token "test3" -Remote_Path "E$\LST"
# If we do not pass plant to update over it will auto do all plants if we want a specific plant we need to do like below
# .\update-controllers.ps1 -App_Path "C:\Users\matthes01\Documents\lst" -Token "test3" -BuildController no -PlantToUpdate "usmcd1vms006" -Remote_Path "E$\LST"
$Plants = @(
@{ Server = "usmcd1vms036"; Token = "test3"; Remote_Path = "E$\LST"}
@{ Server = "usmar1vms006"; Token = "usmar1" ; Remote_Path = "E$\LST"}
@{ Server = "usbet1vms006"; Token = "usbet1"; Remote_Path = "E$\LST" }
@{ Server = "usbow1vms006"; Token = "usbow1" ; Remote_Path = "E$\LST"}
@{ Server = "usslc1vms006"; Token = "usslc1" ; Remote_Path = "E$\LST"}
@{ Server = "usstp1vms006"; Token = "usstp1" ; Remote_Path = "D$\LST"}
)
$EnvFile = Join-Path $App_Path ".env"
if (-Not (Test-Path $EnvFile)) {
@@ -63,7 +76,7 @@ else {
if (![string]::IsNullOrWhiteSpace($content)) {
$BuildNumber = $content.Trim()
}
}
@@ -77,35 +90,64 @@ if (-Not (Test-Path $ControlIncludes)) {
# last one to make sure we have is the build folder
$BuildFolder = Join-Path $App_Path "controllerBuilds"
if (-Not (Test-Path $BuildFolder)) {
write-host "Build folder missing creating it"
New-Item -Path $BuildFolder -ItemType Directory | Out-Null
}
# now we can create the zip
Zip-Includes -IncludesFile $ControlIncludes -BuildNumber $BuildNumber -BuildFolder $BuildFolder -AppRoot $App_Path
Start-Sleep -Seconds 3
#------------------------------------------------------------------------------------
# Checking to make sure the server is up and online
Write-Output "Checking if $($Token) is online to update."
$pingResult = Test-Connection -ComputerName $Server -Count 2 -Quiet
if (-not $pingResult) {
Write-Output "Server $($Server), token $($Token) is NOT reachable. Exiting script."
exit 1 # Terminate the script with a non-zero exit code
# only rebuild if we push yes over
if ($BuildController -eq "yes") {
# now we can create the zip
Zip-Includes -IncludesFile $ControlIncludes -BuildNumber $BuildNumber -BuildFolder $BuildFolder -AppRoot $App_Path
Start-Sleep -Seconds 3
}
Write-Output "Server $($Server), token $($Token) is online."
else {
$BuildNumber = ([int]$BuildNumber - 1).ToString()
}
#------------------------------------------------------------------------------------
# now that the server is up lets update the server with the current build
# do the update to the plant.
Update-Server -ADM_USER $ADM_USER -ADM_PASS $ADM_PASS -AppRoot $App_Path -Destination $Remote_Path -Server $Server -Token $Token
if ($PlantToUpdate -ne "all") {
# Checking to make sure the server is up and online
Write-Output "Checking if $($Token) is online to update."
$pingResult = Test-Connection -ComputerName $Server -Count 2 -Quiet
if (-not $pingResult) {
Write-Output "Server $($PlantToUpdate), token $($Token) is NOT reachable. Exiting script."
exit 1 # Terminate the script with a non-zero exit code
}
Write-Output "Server $($PlantToUpdate), token $($Token) is online."
Update-Server -ADM_USER $ADM_USER -ADM_PASS $ADM_PASS -AppRoot $App_Path -Destination $Remote_Path -Server $PlantToUpdate -Token $Token -ControllerBuild $BuildController
}
else {
foreach ($plant in $Plants) {
# Checking to make sure the server is up and online
Write-Output "Checking if $($plant.Token) is online to update."
$pingResult = Test-Connection -ComputerName $plant.Server -Count 2 -Quiet
if (-not $pingResult) {
Write-Output "Server $($plant.Server), token $($plant.Token) is NOT reachable. Exiting script."
exit 1 # Terminate the script with a non-zero exit code
}
Write-Output "Server $($plant.Server), token $($plant.Token) is online."
Write-Output "Plant to update: $($plant.Token)"
Update-Server -ADM_USER $ADM_USER -ADM_PASS $ADM_PASS -AppRoot $App_Path -Destination $plant.Remote_Path -Server $plant.Server -Token $plant.Token
}
}
# bump the build number
$BuildNumber = Bump-Build -AppRoot $App_Path
if ($BuildController -eq "yes") {
$BuildNumber = Bump-Build -AppRoot $App_Path
}
# function to create the zip controller-1.zip