From eb253665d4dee7020ca3a806a7abb0f080e0b98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joan=20F=C3=ADsica?= Date: Fri, 13 Jun 2025 20:48:32 +0200 Subject: [PATCH 1/6] Get BLCU id from ADJ --- backend/cmd/main.go | 26 +++++++++++++------------- backend/pkg/boards/blcu.go | 12 +++++++----- backend/pkg/vehicle/vehicle.go | 2 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 8f9875fa6..3138663fc 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -88,7 +88,7 @@ var currentVersion string func main() { // update() // FIXME: Updater disabled due to cross-platform and reliability issues - + traceFile := initTrace(*traceLevel, *traceFile) defer traceFile.Close() @@ -230,7 +230,7 @@ func main() { BackoffFactor: config.TFTP.BackoffFactor, EnableProgress: config.TFTP.EnableProgress, } - blcuBoard := boards.NewWithTFTPConfig(blcuIP, tftpConfig) + blcuBoard := boards.NewWithTFTPConfig(blcuIP, tftpConfig, abstraction.BoardId(adj.Info.BoardIds["BLCU"])) vehicle.AddBoard(blcuBoard) trace.Info().Str("ip", blcuIP).Msg("BLCU board registered") } @@ -259,10 +259,10 @@ func main() { if uploadOrderId == 0 { uploadOrderId = boards.BlcuUploadOrderId } - + transp.SetIdTarget(abstraction.PacketId(downloadOrderId), abstraction.TransportTarget("BLCU")) transp.SetIdTarget(abstraction.PacketId(uploadOrderId), abstraction.TransportTarget("BLCU")) - + // Use BLCU address from config, ADJ, or default blcuIP := config.Blcu.IP if blcuIP == "" { @@ -289,23 +289,23 @@ func main() { } // Create TCP client config with custom parameters from config clientConfig := tcp.NewClientConfig(backendTcpClientAddr) - + // Apply custom timeout if specified if config.TCP.ConnectionTimeout > 0 { clientConfig.Timeout = time.Duration(config.TCP.ConnectionTimeout) * time.Millisecond } - + // Apply custom keep-alive if specified if config.TCP.KeepAlive > 0 { clientConfig.KeepAlive = time.Duration(config.TCP.KeepAlive) * time.Millisecond } - + // Apply custom backoff parameters if config.TCP.BackoffMinMs > 0 || config.TCP.BackoffMaxMs > 0 || config.TCP.BackoffMultiplier > 0 { minBackoff := 100 * time.Millisecond // default - maxBackoff := 5 * time.Second // default - multiplier := 1.5 // default - + maxBackoff := 5 * time.Second // default + multiplier := 1.5 // default + if config.TCP.BackoffMinMs > 0 { minBackoff = time.Duration(config.TCP.BackoffMinMs) * time.Millisecond } @@ -315,13 +315,13 @@ func main() { if config.TCP.BackoffMultiplier > 0 { multiplier = config.TCP.BackoffMultiplier } - + clientConfig.ConnectionBackoffFunction = tcp.NewExponentialBackoff(minBackoff, multiplier, maxBackoff) } - + // Apply max retries (0 or negative means infinite) clientConfig.MaxConnectionRetries = config.TCP.MaxRetries - + go transp.HandleClient(clientConfig, fmt.Sprintf("%s:%d", adj.Info.Addresses[board.Name], adj.Info.Ports[TcpServer])) i++ } diff --git a/backend/pkg/boards/blcu.go b/backend/pkg/boards/blcu.go index 641cf83d5..8608754a6 100644 --- a/backend/pkg/boards/blcu.go +++ b/backend/pkg/boards/blcu.go @@ -14,7 +14,7 @@ import ( // TODO! Get from ADE const ( BlcuName = "BLCU" - BlcuId = abstraction.BoardId(1) + BlcuId = abstraction.BoardId(7) AckId = abstraction.BoardEvent("ACK") DownloadEventId = abstraction.BoardEvent("DOWNLOAD") @@ -37,6 +37,7 @@ type BLCU struct { ackChan chan struct{} ip string tftpConfig TFTPConfig + id abstraction.BoardId } func New(ip string) *BLCU { @@ -46,18 +47,19 @@ func New(ip string) *BLCU { TimeoutMs: 5000, BackoffFactor: 2, EnableProgress: true, - }) + }, BlcuId) } -func NewWithTFTPConfig(ip string, tftpConfig TFTPConfig) *BLCU { +func NewWithTFTPConfig(ip string, tftpConfig TFTPConfig, id abstraction.BoardId) *BLCU { return &BLCU{ ackChan: make(chan struct{}), ip: ip, tftpConfig: tftpConfig, + id: id, } } -func (boards *BLCU) Id() abstraction.BoardId { - return BlcuId +func (board *BLCU) Id() abstraction.BoardId { + return board.id } func (boards *BLCU) Notify(boardNotification abstraction.BoardNotification) { diff --git a/backend/pkg/vehicle/vehicle.go b/backend/pkg/vehicle/vehicle.go index fe1405861..2899502b5 100644 --- a/backend/pkg/vehicle/vehicle.go +++ b/backend/pkg/vehicle/vehicle.go @@ -91,7 +91,7 @@ func (vehicle *Vehicle) UserPush(push abstraction.BrokerPush) error { case "blcu/downloadRequest": download := push.(*blcu_topic.DownloadRequest) - + // TODO: get BLCU id from ADJ if board, exists := vehicle.boards[boards.BlcuId]; exists { board.Notify(abstraction.BoardNotification( &boards.DownloadEvent{ From ac2bff5f453ef5783c4b75b0d46f87596a0b2f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joan=20F=C3=ADsica?= Date: Mon, 16 Jun 2025 20:46:32 +0200 Subject: [PATCH 2/6] Add Blcu Id to vehicle to get the Id from the ADJ --- backend/cmd/main.go | 1 + backend/pkg/vehicle/constructor.go | 5 +++++ backend/pkg/vehicle/notification.go | 2 +- backend/pkg/vehicle/vehicle.go | 9 +++++---- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 3138663fc..21bb2b77f 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -232,6 +232,7 @@ func main() { } blcuBoard := boards.NewWithTFTPConfig(blcuIP, tftpConfig, abstraction.BoardId(adj.Info.BoardIds["BLCU"])) vehicle.AddBoard(blcuBoard) + vehicle.SetBlcuId(abstraction.BoardId(adj.Info.BoardIds["BLCU"])) trace.Info().Str("ip", blcuIP).Msg("BLCU board registered") } diff --git a/backend/pkg/vehicle/constructor.go b/backend/pkg/vehicle/constructor.go index 93c2944fd..e71cd407b 100644 --- a/backend/pkg/vehicle/constructor.go +++ b/backend/pkg/vehicle/constructor.go @@ -75,3 +75,8 @@ func (vehicle *Vehicle) SetIpToBoardId(ipToBoardId map[string]abstraction.BoardI vehicle.ipToBoardId = ipToBoardId vehicle.trace.Info().Msg("set ip to board id") } + +func (vehicle *Vehicle) SetBlcuId(id abstraction.BoardId) { + vehicle.BlcuId = id + vehicle.trace.Info().Uint16("blcu_id", uint16(id)).Msg("set blcu id") +} diff --git a/backend/pkg/vehicle/notification.go b/backend/pkg/vehicle/notification.go index 164b4147a..72fde59c3 100644 --- a/backend/pkg/vehicle/notification.go +++ b/backend/pkg/vehicle/notification.go @@ -131,7 +131,7 @@ func (vehicle *Vehicle) handlePacketNotification(notification transport.PacketNo return errors.Join(fmt.Errorf("remove state orders (state orders from %s to %s)", notification.From, notification.To), err) } case *blcu_packet.Ack: - vehicle.boards[boards.BlcuId].Notify(abstraction.BoardNotification( + vehicle.boards[vehicle.BlcuId].Notify(abstraction.BoardNotification( &boards.AckNotification{ ID: boards.AckId, }, diff --git a/backend/pkg/vehicle/vehicle.go b/backend/pkg/vehicle/vehicle.go index 2899502b5..b067bef3c 100644 --- a/backend/pkg/vehicle/vehicle.go +++ b/backend/pkg/vehicle/vehicle.go @@ -33,6 +33,7 @@ type Vehicle struct { updateFactory *update_factory.UpdateFactory idToBoardName map[uint16]string ipToBoardId map[string]abstraction.BoardId + BlcuId abstraction.BoardId trace zerolog.Logger } @@ -91,12 +92,12 @@ func (vehicle *Vehicle) UserPush(push abstraction.BrokerPush) error { case "blcu/downloadRequest": download := push.(*blcu_topic.DownloadRequest) - // TODO: get BLCU id from ADJ - if board, exists := vehicle.boards[boards.BlcuId]; exists { + + if board, exists := vehicle.boards[vehicle.BlcuId]; exists { board.Notify(abstraction.BoardNotification( &boards.DownloadEvent{ BoardEvent: boards.DownloadEventId, - BoardID: boards.BlcuId, + BoardID: vehicle.BlcuId, Board: download.Board, }, )) @@ -124,7 +125,7 @@ func (vehicle *Vehicle) UserPush(push abstraction.BrokerPush) error { return nil } - if board, exists := vehicle.boards[boards.BlcuId]; exists { + if board, exists := vehicle.boards[vehicle.BlcuId]; exists { board.Notify(abstraction.BoardNotification(uploadEvent)) } else { fmt.Fprintf(os.Stderr, "BLCU board not registered\n") From 5f067d43f64a225e94f6e69cf01ccf080d82ce5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joan=20F=C3=ADsica?= Date: Mon, 16 Jun 2025 21:10:25 +0200 Subject: [PATCH 3/6] Change blcu name constant on main --- backend/cmd/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 21bb2b77f..8696c1100 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -67,7 +67,7 @@ import ( const ( BACKEND = "backend" - BLCU = "blcu" + BLCU = "BLCU" TcpClient = "TCP_CLIENT" TcpServer = "TCP_SERVER" UDP = "UDP" From acbfa6487e06eb7a5149571ca13f447af496648c Mon Sep 17 00:00:00 2001 From: Marc Sanchis Date: Tue, 17 Jun 2025 16:49:39 +0200 Subject: [PATCH 4/6] grab BLCU ID from ADJ --- backend/cmd/main.go | 41 +++++++++++++++++++++---------- backend/pkg/boards/blcu.go | 49 +++++++++++++++++++++++++------------- 2 files changed, 62 insertions(+), 28 deletions(-) diff --git a/backend/cmd/main.go b/backend/cmd/main.go index 8696c1100..0c7b54882 100644 --- a/backend/cmd/main.go +++ b/backend/cmd/main.go @@ -223,17 +223,34 @@ func main() { // <--- BLCU Board ---> // Register BLCU board for handling bootloader operations if blcuIP, exists := adj.Info.Addresses[BLCU]; exists { - tftpConfig := boards.TFTPConfig{ - BlockSize: config.TFTP.BlockSize, - Retries: config.TFTP.Retries, - TimeoutMs: config.TFTP.TimeoutMs, - BackoffFactor: config.TFTP.BackoffFactor, - EnableProgress: config.TFTP.EnableProgress, + blcuId, idExists := adj.Info.BoardIds["BLCU"] + if !idExists { + trace.Error().Msg("BLCU IP found in ADJ but board ID missing") + } else { + // Get configurable order IDs or use defaults + downloadOrderId := config.Blcu.DownloadOrderId + uploadOrderId := config.Blcu.UploadOrderId + if downloadOrderId == 0 { + downloadOrderId = boards.DefaultBlcuDownloadOrderId + } + if uploadOrderId == 0 { + uploadOrderId = boards.DefaultBlcuUploadOrderId + } + + tftpConfig := boards.TFTPConfig{ + BlockSize: config.TFTP.BlockSize, + Retries: config.TFTP.Retries, + TimeoutMs: config.TFTP.TimeoutMs, + BackoffFactor: config.TFTP.BackoffFactor, + EnableProgress: config.TFTP.EnableProgress, + } + blcuBoard := boards.NewWithConfig(blcuIP, tftpConfig, abstraction.BoardId(blcuId), downloadOrderId, uploadOrderId) + vehicle.AddBoard(blcuBoard) + vehicle.SetBlcuId(abstraction.BoardId(blcuId)) + trace.Info().Str("ip", blcuIP).Int("id", int(blcuId)).Uint16("download_order_id", downloadOrderId).Uint16("upload_order_id", uploadOrderId).Msg("BLCU board registered") } - blcuBoard := boards.NewWithTFTPConfig(blcuIP, tftpConfig, abstraction.BoardId(adj.Info.BoardIds["BLCU"])) - vehicle.AddBoard(blcuBoard) - vehicle.SetBlcuId(abstraction.BoardId(adj.Info.BoardIds["BLCU"])) - trace.Info().Str("ip", blcuIP).Msg("BLCU board registered") + } else { + trace.Warn().Msg("BLCU not found in ADJ configuration - bootloader operations unavailable") } // <--- transport ---> @@ -255,10 +272,10 @@ func main() { downloadOrderId := config.Blcu.DownloadOrderId uploadOrderId := config.Blcu.UploadOrderId if downloadOrderId == 0 { - downloadOrderId = boards.BlcuDownloadOrderId + downloadOrderId = boards.DefaultBlcuDownloadOrderId } if uploadOrderId == 0 { - uploadOrderId = boards.BlcuUploadOrderId + uploadOrderId = boards.DefaultBlcuUploadOrderId } transp.SetIdTarget(abstraction.PacketId(downloadOrderId), abstraction.TransportTarget("BLCU")) diff --git a/backend/pkg/boards/blcu.go b/backend/pkg/boards/blcu.go index 8608754a6..315f771c7 100644 --- a/backend/pkg/boards/blcu.go +++ b/backend/pkg/boards/blcu.go @@ -11,17 +11,17 @@ import ( dataPacket "github.com/HyperloopUPV-H8/h9-backend/pkg/transport/packet/data" ) -// TODO! Get from ADE +// TODO! Get from ADJ const ( BlcuName = "BLCU" - BlcuId = abstraction.BoardId(7) AckId = abstraction.BoardEvent("ACK") DownloadEventId = abstraction.BoardEvent("DOWNLOAD") UploadEventId = abstraction.BoardEvent("UPLOAD") - BlcuDownloadOrderId = 701 - BlcuUploadOrderId = 700 + // Default order IDs - can be overridden via config.toml + DefaultBlcuDownloadOrderId = 701 + DefaultBlcuUploadOrderId = 700 ) type TFTPConfig struct { @@ -33,13 +33,16 @@ type TFTPConfig struct { } type BLCU struct { - api abstraction.BoardAPI - ackChan chan struct{} - ip string - tftpConfig TFTPConfig - id abstraction.BoardId + api abstraction.BoardAPI + ackChan chan struct{} + ip string + tftpConfig TFTPConfig + id abstraction.BoardId + downloadOrderId uint16 + uploadOrderId uint16 } +// Deprecated: Use NewWithConfig with proper board ID and order IDs from configuration func New(ip string) *BLCU { return NewWithTFTPConfig(ip, TFTPConfig{ BlockSize: 131072, // 128kB @@ -47,15 +50,29 @@ func New(ip string) *BLCU { TimeoutMs: 5000, BackoffFactor: 2, EnableProgress: true, - }, BlcuId) + }, 0) // Board ID 0 indicates missing configuration } +// Deprecated: Use NewWithConfig for proper order ID configuration func NewWithTFTPConfig(ip string, tftpConfig TFTPConfig, id abstraction.BoardId) *BLCU { return &BLCU{ - ackChan: make(chan struct{}), - ip: ip, - tftpConfig: tftpConfig, - id: id, + ackChan: make(chan struct{}), + ip: ip, + tftpConfig: tftpConfig, + id: id, + downloadOrderId: DefaultBlcuDownloadOrderId, + uploadOrderId: DefaultBlcuUploadOrderId, + } +} + +func NewWithConfig(ip string, tftpConfig TFTPConfig, id abstraction.BoardId, downloadOrderId, uploadOrderId uint16) *BLCU { + return &BLCU{ + ackChan: make(chan struct{}), + ip: ip, + tftpConfig: tftpConfig, + id: id, + downloadOrderId: downloadOrderId, + uploadOrderId: uploadOrderId, } } func (board *BLCU) Id() abstraction.BoardId { @@ -98,7 +115,7 @@ func (boards *BLCU) SetAPI(api abstraction.BoardAPI) { func (boards *BLCU) download(notification DownloadEvent) error { // Notify the BLCU ping := dataPacket.NewPacketWithValues( - abstraction.PacketId(BlcuDownloadOrderId), + abstraction.PacketId(boards.downloadOrderId), map[dataPacket.ValueName]dataPacket.Value{ BlcuName: dataPacket.NewEnumValue(dataPacket.EnumVariant(notification.Board)), }, @@ -171,7 +188,7 @@ func (boards *BLCU) download(notification DownloadEvent) error { } func (boards *BLCU) upload(notification UploadEvent) error { - ping := dataPacket.NewPacketWithValues(abstraction.PacketId(BlcuUploadOrderId), + ping := dataPacket.NewPacketWithValues(abstraction.PacketId(boards.uploadOrderId), map[dataPacket.ValueName]dataPacket.Value{ BlcuName: dataPacket.NewEnumValue(dataPacket.EnumVariant(notification.Board)), }, From ffb2aef678fb5c58c93c487ae1e55374b5d2c042 Mon Sep 17 00:00:00 2001 From: Marc Sanchis Date: Tue, 17 Jun 2025 16:50:10 +0200 Subject: [PATCH 5/6] BLCU simple test --- backend/pkg/boards/blcu_simple_test.go | 60 ++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/backend/pkg/boards/blcu_simple_test.go b/backend/pkg/boards/blcu_simple_test.go index 2fcf4ddae..7ff5633e8 100644 --- a/backend/pkg/boards/blcu_simple_test.go +++ b/backend/pkg/boards/blcu_simple_test.go @@ -3,24 +3,76 @@ package boards_test import ( "testing" + "github.com/HyperloopUPV-H8/h9-backend/pkg/abstraction" "github.com/HyperloopUPV-H8/h9-backend/pkg/boards" blcu_topic "github.com/HyperloopUPV-H8/h9-backend/pkg/broker/topics/blcu" "github.com/HyperloopUPV-H8/h9-backend/pkg/vehicle" "github.com/rs/zerolog" ) -// TestBLCUBoardRegistration tests that BLCU board can be registered +// TestBLCUBoardRegistration tests that BLCU board can be registered with different configurations func TestBLCUBoardRegistration(t *testing.T) { logger := zerolog.New(nil).Level(zerolog.Disabled) v := vehicle.New(logger) - // Create and register BLCU board + // Test deprecated constructor (should use board ID 0) blcuBoard := boards.New("192.168.0.10") v.AddBoard(blcuBoard) + // Verify board is registered with ID 0 (missing configuration) + if blcuBoard.Id() != 0 { + t.Errorf("Expected board ID 0 for deprecated constructor, got %d", blcuBoard.Id()) + } +} + +// TestBLCUWithCustomConfiguration tests BLCU with custom board ID and order IDs +func TestBLCUWithCustomConfiguration(t *testing.T) { + logger := zerolog.New(nil).Level(zerolog.Disabled) + v := vehicle.New(logger) + + // Test new constructor with custom configuration + tftpConfig := boards.TFTPConfig{ + BlockSize: 131072, + Retries: 3, + TimeoutMs: 5000, + BackoffFactor: 2, + EnableProgress: true, + } + + customBoardId := abstraction.BoardId(7) + customDownloadOrderId := uint16(801) + customUploadOrderId := uint16(802) + + blcuBoard := boards.NewWithConfig("192.168.0.10", tftpConfig, customBoardId, customDownloadOrderId, customUploadOrderId) + v.AddBoard(blcuBoard) + + // Verify board is registered with custom ID + if blcuBoard.Id() != customBoardId { + t.Errorf("Expected board ID %d, got %d", customBoardId, blcuBoard.Id()) + } +} + +// TestBLCUWithDefaultConfiguration tests BLCU with default order IDs +func TestBLCUWithDefaultConfiguration(t *testing.T) { + logger := zerolog.New(nil).Level(zerolog.Disabled) + v := vehicle.New(logger) + + // Test deprecated constructor (should use default order IDs) + tftpConfig := boards.TFTPConfig{ + BlockSize: 131072, + Retries: 3, + TimeoutMs: 5000, + BackoffFactor: 2, + EnableProgress: true, + } + + boardId := abstraction.BoardId(7) + blcuBoard := boards.NewWithTFTPConfig("192.168.0.10", tftpConfig, boardId) + v.AddBoard(blcuBoard) + // Verify board is registered - if blcuBoard.Id() != boards.BlcuId { - t.Errorf("Expected board ID %d, got %d", boards.BlcuId, blcuBoard.Id()) + if blcuBoard.Id() != boardId { + t.Errorf("Expected board ID %d, got %d", boardId, blcuBoard.Id()) } } From a83b53ecb50e186da754091dd5de4146bcb5d93c Mon Sep 17 00:00:00 2001 From: Marc Sanchis Date: Tue, 17 Jun 2025 16:53:13 +0200 Subject: [PATCH 6/6] remove TODO --- backend/pkg/boards/blcu.go | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/pkg/boards/blcu.go b/backend/pkg/boards/blcu.go index 315f771c7..9c4534404 100644 --- a/backend/pkg/boards/blcu.go +++ b/backend/pkg/boards/blcu.go @@ -11,7 +11,6 @@ import ( dataPacket "github.com/HyperloopUPV-H8/h9-backend/pkg/transport/packet/data" ) -// TODO! Get from ADJ const ( BlcuName = "BLCU"