Add Linux build support for headless deployment (issue #48)#50
Draft
chriskinal wants to merge 3 commits into
Draft
Add Linux build support for headless deployment (issue #48)#50chriskinal wants to merge 3 commits into
chriskinal wants to merge 3 commits into
Conversation
Refactor the platform-specific glue so AOG-TaskController can build and run on Linux as a headless console service, while leaving the Windows build and CI byte-compatible. Adds a Linux CI job and release tarball job that mirror the existing Windows ones. Cross-platform changes: - main.cpp: split entry point into WinMain (preserved, same lifecycle ordering as before) and POSIX main with SIGINT/SIGTERM handlers. Adds --can_adapter=socketcan with --can_channel=<iface>. - settings.cpp: portable config dir via std::filesystem. Windows still uses SHGetFolderPathA(CSIDL_APPDATA); Linux uses XDG_CONFIG_HOME or ~/.config; macOS uses ~/Library/Application Support. - logging.cpp / logging_utils.hpp: localtime_r on POSIX, localtime_s retained on Windows. - udp_connections.cpp: SO_REUSEADDR on both UDP sockets (required on Linux when binding 0.0.0.0 alongside a specific-IP socket). On POSIX enumerate interfaces via getifaddrs(3) because the hostname resolver returns 127.0.1.1 on stock Ubuntu and never matches a LAN subnet. - app.cpp / settings.hpp: add explicit <iostream> / <cstdint> includes that were arriving transitively through windows.h. - CMakeLists.txt: gate WIN32_EXECUTABLE, AppIcon.rc, and the four Windows DLL copy/install blocks behind if(WIN32). Default CAN_DRIVER per platform (Windows: PCAN+InnoMaker+TouCAN+SYS_TEC; Linux: SocketCAN; macOS: MacCANPCAN), still overridable via -DCAN_DRIVER=. CI / packaging: - .github/workflows/build.yml: add linux_build job (ubuntu-latest, Ninja) producing AOG-TaskController-linux-x86_64.tar.gz. - .github/workflows/release.yml: add linux_release job mirroring the Windows release (same develop-branch safety check, prerelease regex, attaches tarball to the GitHub Release). - resources/linux/: sample settings.json and a systemd unit file shipped inside the tarball. Smoke-tested on Ubuntu 24.04 aarch64 against vcan0: TC and TECU claim addresses with J1939-81 250ms delay, UDP binds cleanly, AgIO subnet detection rebind works, section-control-enable and 64-section state updates are received, SIGTERM triggers graceful shutdown. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GitHub provides hosted ubuntu-24.04-arm runners, so we can produce a native aarch64 binary alongside x86_64 without any cross-compile plumbing. The aarch64 tarball is what runs on Raspberry Pi (Zero 2 W, 3, 4, 5) under a 64-bit Raspberry Pi OS install. - build.yml linux_build job: matrix over (x86_64 on ubuntu-latest, aarch64 on ubuntu-24.04-arm). Two artifacts uploaded: 'Linux Tarball (x86_64)' and 'Linux Tarball (aarch64)'. - release.yml linux_release job: same matrix. Both tarballs attach to the same GitHub Release via softprops/action-gh-release@v2 (idempotent on tag_name). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two new documents under docs/ aimed at client authors and SBC operators: - LINUX_DAEMON.md walks through deploying AOG-TaskController as a headless Linux service: hardware targets (x86_64 and aarch64 tarballs), resource footprint, MCP2515/USB CAN setup, the systemd unit, settings.json, and troubleshooting. Covers Raspberry Pi (including Pi Zero 2 W) specifically. - PROTOCOL.md is a reference for anything writing a client against the TC: UDP packet framing (0x8081 start + checksum), ports 8888/9999, every PGN the TC sends/receives byte-by-byte, the ISOBUS/CAN side at a glance, settings + CLI reference, and Python + C# example clients (the latter targeting AgValonia on .NET 8+). readme.md links to both at the top so they're easy to find. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Draft PR to validate the cross-platform refactor on CI before proposing for merge. Addresses #48 — enables building and running AOG-TaskController as a headless Linux service on x86_64 and aarch64 (Raspberry Pi 3/4/5/Zero 2 W, generic Linux SBCs), and documents the UDP protocol for AgIO / AgValonia / third-party clients.
The Windows codepath is preserved bit-for-bit:
WinMain,AttachConsole, hidden tool window, message pump, and lifecycle ordering are unchanged.SHGetFolderPathA(CSIDL_APPDATA)is the same call the original build linked against — no new ole32 dependency.localtime_s,WIN32_EXECUTABLE,AppIcon.rc, and all DLL copy/install commands still execute on Windows.windows_buildandwindows_releaseworkflow jobs are untouched; the new Linux jobs run in parallel.What changed
Cross-platform code
src/main.cpp— split entry point:WinMain(Windows) andmain(argc,argv)(POSIX) withSIGINT/SIGTERMhandlers and a new--can_adapter=socketcanoption.src/settings.cpp— portable config dir viastd::filesystem. Windows:%APPDATA%\AOG-TaskController; Linux:$XDG_CONFIG_HOME/~/.config/AOG-TaskController; macOS:~/Library/Application Support/AOG-TaskController.src/logging.cpp/include/logging_utils.hpp—localtime_ron POSIX,localtime_son Windows.src/udp_connections.cpp—SO_REUSEADDRon both UDP sockets (needed on Linux when binding0.0.0.0alongside a specific-IP socket) andgetifaddrs(3)interface enumeration on POSIX (the hostname resolver returns127.0.1.1on stock Ubuntu and never matches a LAN subnet).src/app.cpp/include/settings.hpp— explicit<iostream>/<cstdint>that were arriving transitively throughwindows.h.CMake
WIN32_EXECUTABLE,AppIcon.rc, and all four Windows DLL copy/install blocks gated behindif(WIN32).CAN_DRIVERdefaults per platform — Windows: PCAN+InnoMaker+TouCAN+SYS_TEC; Linux: SocketCAN; macOS: MacCANPCAN. Still overridable via-DCAN_DRIVER=.CI / packaging
.github/workflows/build.yml— newlinux_buildjob with a matrix producing bothlinux-x86_64(ubuntu-latest) andlinux-aarch64(ubuntu-24.04-arm) tarballs. The aarch64 tarball is what runs on Raspberry Pi under 64-bit Raspberry Pi OS..github/workflows/release.yml—linux_releasemirrors the Windows release with the same matrix; both tarballs attach to the same GitHub Release viasoftprops/action-gh-release@v2(idempotent on tag_name).resources/linux/— samplesettings.jsonand a systemd unit shipped inside the tarball.Documentation
docs/LINUX_DAEMON.md— deployment guide for running the TC as a headless Linux service. Covers hardware targets, resource footprint (CPU/RAM/network), MCP2515 HAT and USB-CAN setup, the systemd unit,settings.json, and troubleshooting. Pi Zero 2 W is called out specifically.docs/PROTOCOL.md— UDP wire-protocol reference for client authors. Frame format (0x8081start + checksum), ports 8888/9999, every PGN the TC sends/receives byte-by-byte (0xC9,0xE5,0xF0,0xF1,0xF2), settings + CLI reference, ISOBUS/CAN overview, and Python + C# example clients (the latter targeting AgValonia on .NET 8+).readme.md— links both new docs at the top.Test plan
Already verified on Ubuntu 24.04 aarch64 against
vcan0:--help/--versionworkvcan0getifaddrsSIGTERMtriggers graceful shutdownCI status (latest run):
Not testable from this branch alone:
SHGetFolderPathreplaced by~/Library/Application Supporton__APPLE__;CAN_DRIVER=MacCANPCANdefault), but no CI runner added and no host to compile on. Can be added later if/when needed.🤖 Generated with Claude Code