diff --git a/.build/sailtrack-build b/.build/sailtrack-build deleted file mode 100755 index eae3461..0000000 --- a/.build/sailtrack-build +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# `sailtrack-build` - Script that builds the SailTrack OS image starting from a DietPi image. - -debian_release_name="Bookworm" -dietpi_image_name="DietPi_RPi-ARMv8-$debian_release_name" -sailtrack_image_name="SailTrack-Core_RPi-ARMv8-$debian_release_name" - -# Download and extract DietPi image -wget -N "https://dietpi.com/downloads/images/$dietpi_image_name.img.xz" -P /tmp/sailtrack-build || exit 1 -7z e -aoa -o"/tmp/sailtrack-build/$dietpi_image_name" "/tmp/sailtrack-build/$dietpi_image_name.img.xz" - -# Mount image -fp_loop=$(losetup --show -fP "/tmp/sailtrack-build/$dietpi_image_name/$dietpi_image_name.img") -mkdir -p /tmp/sailtrack-build/mnt -mount "${fp_loop}p2" /tmp/sailtrack-build/mnt -mount "${fp_loop}p1" /tmp/sailtrack-build/mnt/boot - -# Copy SailTrack files -cp -v LICENSE /tmp/sailtrack-build/mnt/boot/sailtrack-LICENSE.txt -cp -v README.md /tmp/sailtrack-build/mnt/boot/sailtrack-README.md -cp -v dietpi.txt /tmp/sailtrack-build/mnt/boot/dietpi.txt -cp -v Automation_Custom_Script.sh /tmp/sailtrack-build/mnt/boot/Automation_Custom_Script.sh -cp -vr sailtrack /tmp/sailtrack-build/mnt/boot/sailtrack -cp -vrT rootfs /tmp/sailtrack-build/mnt - -# Unmount image -umount -R /tmp/sailtrack-build/mnt -losetup -d "$fp_loop" - -# Rename DietPi image to SailTrack image -mv "/tmp/sailtrack-build/$dietpi_image_name/$dietpi_image_name.img" "/tmp/sailtrack-build/$dietpi_image_name/$sailtrack_image_name.img" - -# Update hashes -echo -n "Generating hashes..." -cat << EOF > "/tmp/sailtrack-build/$dietpi_image_name/hash.txt" -FILE: $sailtrack_image_name.img -DATE: $(date -u) -MD5: $(md5sum "/tmp/sailtrack-build/$dietpi_image_name/$sailtrack_image_name.img" | mawk '{print $1}') -SHA1: $(sha1sum "/tmp/sailtrack-build/$dietpi_image_name/$sailtrack_image_name.img" | mawk '{print $1}') -SHA256: $(sha256sum "/tmp/sailtrack-build/$dietpi_image_name/$sailtrack_image_name.img" | mawk '{print $1}') -EOF -echo "done" - -# Update README -cp -v README.md "/tmp/sailtrack-build/$dietpi_image_name" - -# Create archive -(( $(free -m | mawk '/Mem:/{print $2}') < 1750 && $(nproc) > 2 )) && limit_threads='-mmt2' -7z a -m0=lzma2 -mx=9 $limit_threads "$sailtrack_image_name.7z" "/tmp/sailtrack-build/$dietpi_image_name/*" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 5f0aed0..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Build Image - -on: - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Run SailTrack-Build - run: sudo ./.build/sailtrack-build - - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: SailTrack-Core_RPi-ARMv8-Bookworm.7z - path: SailTrack-Core_RPi-ARMv8-Bookworm.7z - compression-level: 0 diff --git a/.github/workflows/make.yml b/.github/workflows/make.yml new file mode 100644 index 0000000..dceaf7f --- /dev/null +++ b/.github/workflows/make.yml @@ -0,0 +1,19 @@ +name: Make + +on: + push: + pull_request: + types: [opened, reopened] + +env: + CLICOLOR_FORCE: 1 + CARGO_TERM_COLOR: always + +jobs: + make: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo install cross --git https://github.com/cross-rs/cross + - run: cargo install cargo-make + - run: cargo make diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml new file mode 100644 index 0000000..cb03ad4 --- /dev/null +++ b/.github/workflows/package.yml @@ -0,0 +1,22 @@ +name: Package + +on: + workflow_dispatch: + +env: + CLICOLOR_FORCE: 1 + CARGO_TERM_COLOR: always + +jobs: + package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo install cross --git https://github.com/cross-rs/cross + - run: cargo install cargo-make + - run: sudo cargo make package + - uses: actions/upload-artifact@v4 + with: + name: SailTrack-Core_RPi-ARMv8-Bookworm.7z + path: SailTrack-Core_RPi-ARMv8-Bookworm.7z + compression-level: 0 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 930f462..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Publish Release - -on: - push: - tags: - - 'v*.*.*' - -jobs: - publish: - runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Run SailTrack-Build - run: sudo ./.build/sailtrack-build - - - name: Publish release - uses: softprops/action-gh-release@v1 - with: - files: SailTrack-Core_RPi-ARMv8-Bookworm.7z - generate_release_notes: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..87f3fba --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,23 @@ +name: Release + +on: + push: + tags: + - 'v*.*.*' + +env: + CLICOLOR_FORCE: 1 + CARGO_TERM_COLOR: always + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: cargo install cross --git https://github.com/cross-rs/cross + - run: cargo install cargo-make + - run: sudo cargo make package + - uses: softprops/action-gh-release@v2 + with: + files: SailTrack-Core_RPi-ARMv8-Bookworm.7z + generate_release_notes: true diff --git a/.gitignore b/.gitignore index 1197d70..2e0b03d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,52 +1,7 @@ +# Created by https://www.toptal.com/developers/gitignore/api/linux,macos,python,windows,visualstudiocode,intellij+all,rust +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,python,windows,visualstudiocode,intellij+all,rust -# Created by https://www.toptal.com/developers/gitignore/api/macos,windows,linux,python,pycharm+all,visualstudiocode -# Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows,linux,python,pycharm+all,visualstudiocode - -### Linux ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# KDE directory preferences -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### PyCharm+all ### +### Intellij+all ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 @@ -110,6 +65,9 @@ atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml +# SonarLint plugin +.idea/sonarlint/ + # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties @@ -122,21 +80,62 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser -### PyCharm+all Patch ### -# Ignores the whole .idea folder and all .iml files -# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 +### Intellij+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + +### Linux ### +*~ -.idea/ +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* -# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 +# KDE directory preferences +.directory -*.iml -modules.xml -.idea/misc.xml -*.ipr +# Linux trash folder which might appear on any partition or disk +.Trash-* -# Sonarlint plugin -.idea/sonarlint +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud ### Python ### # Byte-compiled / optimized / DLL files @@ -235,7 +234,22 @@ ipython_config.py # install all needed dependencies. #Pipfile.lock -# PEP 582; used by e.g. github.com/David-OConnor/pyflow +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff @@ -278,17 +292,52 @@ dmypy.json # Cython debug symbols cython_debug/ +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +debug/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + ### VisualStudioCode ### .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json -*.code-workspace +!.vscode/*.code-snippets # Local History for Visual Studio Code .history/ +# Built Visual Studio Code Extensions +*.vsix + ### VisualStudioCode Patch ### # Ignore all local history of files .history @@ -320,7 +369,7 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk -# End of https://www.toptal.com/developers/gitignore/api/macos,windows,linux,python,pycharm+all,visualstudiocode +# End of https://www.toptal.com/developers/gitignore/api/linux,macos,python,windows,visualstudiocode,intellij+all,rust ### VisualStudioCode Patch ### # Ignore .vscode folder diff --git a/.make/sailtrack-package b/.make/sailtrack-package new file mode 100755 index 0000000..d3acfda --- /dev/null +++ b/.make/sailtrack-package @@ -0,0 +1,56 @@ +#!/bin/bash + +# `sailtrack-package` - Script that builds the SailTrack OS image starting from a DietPi image. + +debian_release_name="Bookworm" +dietpi_image_name="DietPi_RPi-ARMv8-$debian_release_name" +sailtrack_image_name="SailTrack-Core_RPi-ARMv8-$debian_release_name" + +# Download and extract DietPi image +wget -N "https://dietpi.com/downloads/images/$dietpi_image_name.img.xz" -P /tmp/sailtrack-package || exit 1 +7z e -aoa -o"/tmp/sailtrack-package/$dietpi_image_name" "/tmp/sailtrack-package/$dietpi_image_name.img.xz" + +# Mount image +fp_loop=$(losetup --show -fP "/tmp/sailtrack-package/$dietpi_image_name/$dietpi_image_name.img") +root_dir=/tmp/sailtrack-package/mnt +mkdir -p $root_dir +mount "${fp_loop}p2" $root_dir +mount "${fp_loop}p1" $root_dir/boot + +# Copy SailTrack files +cp -v LICENSE $root_dir/boot/sailtrack-LICENSE.txt +cp -v README.md $root_dir/boot/sailtrack-README.md +cp -v dietpi.txt $root_dir/boot/dietpi.txt +cp -v Automation_Custom_Script.sh $root_dir/boot/Automation_Custom_Script.sh +mkdir -p $root_dir/boot/sailtrack +cp -vr sailtrack $root_dir/boot/sailtrack +for binary in src/bin/*.rs +do + cp -v target/armv7-unknown-linux-gnueabihf/release/"$(basename "$binary" .rs)" $root_dir/boot/sailtrack +done +cp -vrT rootfs $root_dir + +# Unmount image +umount -R $root_dir +losetup -d "$fp_loop" + +# Rename DietPi image to SailTrack image +mv "/tmp/sailtrack-package/$dietpi_image_name/$dietpi_image_name.img" "/tmp/sailtrack-package/$dietpi_image_name/$sailtrack_image_name.img" + +# Update hashes +echo -n "Generating hashes..." +cat << EOF > "/tmp/sailtrack-package/$dietpi_image_name/hash.txt" +FILE: $sailtrack_image_name.img +DATE: $(date -u) +MD5: $(md5sum "/tmp/sailtrack-package/$dietpi_image_name/$sailtrack_image_name.img" | mawk '{print $1}') +SHA1: $(sha1sum "/tmp/sailtrack-package/$dietpi_image_name/$sailtrack_image_name.img" | mawk '{print $1}') +SHA256: $(sha256sum "/tmp/sailtrack-package/$dietpi_image_name/$sailtrack_image_name.img" | mawk '{print $1}') +EOF +echo "done" + +# Update README +cp -v README.md "/tmp/sailtrack-package/$dietpi_image_name" + +# Create archive +(( $(free -m | mawk '/Mem:/{print $2}') < 1750 && $(nproc) > 2 )) && limit_threads='-mmt2' +7z a -m0=lzma2 -mx=9 $limit_threads "$sailtrack_image_name.7z" "/tmp/sailtrack-package/$dietpi_image_name/*" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a25a448 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "sailtrack-core" +version = "0.1.0" +edition = "2021" + +[dependencies] +rumqttc = "0.24" diff --git a/Cross.toml b/Cross.toml new file mode 100644 index 0000000..703c6cb --- /dev/null +++ b/Cross.toml @@ -0,0 +1,2 @@ +[build] +default-target = "armv7-unknown-linux-gnueabihf" diff --git a/DEVELOPER.md b/DEVELOPER.md index 19dcbc4..88073cf 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -1,85 +1,119 @@ # Developer's Guide + This guide is intended to introduce new developers to all the aspects needed to contribute to SailTrack Core. -If you haven't already, read the [documentation repository](https://github.com/metis-vela-unipd/sailtrack-docs) carefully to familiarize yourself with the SailTrack project and its components. +If you haven't already, read the [project repository](https://github.com/metisvela/sailtrack) carefully to familiarize yourself with the SailTrack project and its components. In this guide, we will assume that you're already familiar with the overall behavior of the system. ## Overview -SailTrack Core is based on [DietPi](https://dietpi.com), a modified version of [Raspberry Pi OS](https://www.raspberrypi.com/software/), which is itself a modified version of [Debian](https://www.debian.org). + +SailTrack Core is based on [DietPi](https://dietpi.com), a modified version of [Raspberry Pi OS](https://www.raspberrypi.com/software/), which is in turn a modified version of [Debian](https://www.debian.org). When the OS boots up, the following tasks are performed continuously until shutdown: -* Serving the Wi-Fi access point (i.e. the "SailTrack-CoreNet" WiFi network) +* Serving the Wi-Fi access point (i.e. the "SailTrack-CoreNet" Wi-Fi network) * Running the MQTT broker (i.e. [Mosquitto](https://mosquitto.org)) * Running the database (i.e. [InfluxDB](https://www.influxdata.com)) * Running the metrics collector (i.e. [Telegraf](https://www.influxdata.com/time-series-platform/telegraf/), which takes the metrics coming from the sensors via MQTT, sends them to Grafana for live visualization, and sends them to InfluxDB for storing) * Running the visualization tool (i.e. [Grafana](https://grafana.com)) * Running the SailTrack scripts (more info in the [section below](#sailtrack-scripts)) -## Development Workflow -The idea behind the development of the SailTrack Core software is to have in this repository everything that is needed to automatically setup the Raspberry Pi from a clean state. +## Development + +The idea behind the development of the SailTrack Core software is to have in this repository everything that is needed to automatically set up the Raspberry Pi from a clean state. This is done to avoid any non-reproducible and non-trackable manual work on the Raspberry Pi. In this way, if for any reason there's a need to erase all the data and restore the Raspberry Pi to a stable state, this can be done easily. Therefore, any change to any software component in the Raspberry Pi system should be present in this repository. -Changes are submitted via [Pull Requests](https://github.com/metis-vela-unipd/sailtrack-core/pulls). -For internal development, the [Gitflow Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow) is used. +Changes are submitted via [Pull Requests](https://github.com/metisvela/sailtrack-core/pulls), following the [GitHub Flow](https://docs.github.com/en/get-started/using-github/github-flow). The following are the common guidelines when adding new files to the repository: -* Scripts (e.g. Python scripts, Bash scripts, etc.) should be added to the `sailtrack` directory. -* Static files (e.g. configuration files, images, dashboards, maps, etc.) should be added in a sub-directory of `rootfs` according to the desired location of the file in the filesystem. +* Interpreted scripts (e.g. Python scripts, Bash scripts, etc.) should be added to the [`sailtrack`](sailtrack) directory. +* Compiled scripts (currently only Rust scripts are supported) should be added to the [`src/bin`](src/bin) directory. +* Static files (e.g. configuration files, images, dashboards, maps, etc.) should be added in a subdirectory of [`rootfs`](rootfs) according to the desired location of the file in the filesystem. A very common example is the addition of a script with a correspondent service file. According to the development workflow, this addition must not be done only directly in the running instance of SailTrack Core OS. Instead, it must be applied in the repository too. -For this particular case, according to the guidelines, the script should go in `sailtrack`, and the service file should go in `rootfs/etc/systemd/system`, because service files must be placed in `/etc/systemd/system` on the Raspberry Pi. +For this particular case, according to the guidelines, the script should go in `sailtrack` (if interpreted) or `src/bin` (if compiled), and the service file should go in `rootfs/etc/systemd/system`, because service files must be placed in `/etc/systemd/system` in the Raspberry Pi. + +> [!WARNING] +> If both an interpreted and a compiled script exist with the same name, the compiled script will take precedence and will be included in the OS. + +### Using Rust + +Developing Rust scripts requires some more effort compared to other interpreted scripts, which can be just placed in the `sailtrack` folder. +Rust scripts must go through the compilation process to produce the binary that can be embedded in the OS. +Moreover, the source files must be cross-compiled to produce a binary that can be run on the Raspberry Pi. +This extra effort comes with the advantage of having more reliable and performant scripts that can handle heavier traffic and computations. + +The following tools are needed to use Rust in SailTrack Core: + +* [The Rust toolchain](https://www.rust-lang.org/tools/install) +* [Docker](https://docs.docker.com/engine/install) (required for cross-compilation) +* [Cross](https://github.com/cross-rs/cross#installation) (required for cross-compilation) +* [Cargo Make](https://github.com/sagiegurari/cargo-make?tab=readme-ov-file#installation) (required for deployment) + +The development workflow for Rust follows the same workflow of any normal Rust crate, with the [`Cargo.toml`](Cargo.toml) manifest defining the project metadata and the binaries under [`src/bin`](src/bin). +On top of the normal Cargo commands that can be used when developing Rust (e.g. `build`, `test`, `fmt`, `clippy`, etc.), the default Cargo Make task can be used to perform an overall check of the project: +```bash +cargo make +``` + +This command will: + +* Cross-compile the binaries in release mode for the Raspberry Pi +* Run `clippy` to lint the code +* Check the formatting + +Additionally, the [Make](https://github.com/metisvela/sailtrack-core/actions/workflows/make.yml) GitHub Action runs `cargo make` on every push and pull request. -The following section will go deeper into the deployment process. +## Deployment -## Deployment Process The deployment process has the goal of creating the SailTrack Core OS image that can be easily flashed onto the Raspberry Pi SD card. To make the installation process as seamless as possible, the provided image contains an automated procedure that, after having installed the OS, sets up all the necessary components and scripts. This is achieved in an automated way using [GitHub Actions](https://github.com/features/actions) and [DietPi-Automation](https://dietpi.com/docs/usage/#how-to-do-an-automatic-base-installation-at-first-boot-dietpi-automation). -The deployment process starts with the "[Publish Release](https://github.com/metis-vela-unipd/sailtrack-core/blob/main/.github/workflows/publish.yml)" GitHub Action, which gets triggered whenever a tag following the [Semantic Versioning](https://semver.org) format (eg. `v1.2.3`) is pushed. -The GitHub Action starts by running the [`sailtrack-build`](https://github.com/metis-vela-unipd/sailtrack-core/blob/main/.build/sailtrack-build) build script, which performs the following: +The deployment process starts with the [Release](https://github.com/metisvela/sailtrack-core/actions/workflows/release.yml) GitHub Action, which gets triggered whenever a tag following the [Semantic Versioning](https://semver.org) format (e.g. `v1.2.3`) is pushed. +The GitHub Action starts by running the `cargo make package` task, which checks and compiles all the binaries and runs the [`sailtrack-package`](.make/sailtrack-package) script, which performs the following: * Downloads the latest DietPi OS image * Mounts the image (needed for copying files into it) * Copies the contents of the repository to the appropriate locations, in particular: - * All the files in the repository except the `rootfs` directory and unnecessary files and directories (like this one, the `hardware` directory, the `.gitignore`, etc.) get copied to the `/boot` folder, preserving the sub-directories structure. - * All the files in the `rootfs` folder get copied to the root folder (`/`), preserving the sub-directories structure. + * All the files in the repository except the `rootfs` directory and unnecessary files and directories (like this one, the `hardware` directory, the `.gitignore`, etc.) get copied to the `/boot` folder, preserving the subdirectories structure. + * All the files in the `rootfs` folder get copied to the root folder (`/`), preserving the subdirectories structure. * Performs the final steps (renaming the image, including the hashes, compressing the file, etc.) -Once this first job has been completed, the GitHub Action proceeds to publish a [GitHub Release](https://github.com/metis-vela-unipd/sailtrack-core/releases), including the generated image as an asset. +Once these first jobs have been completed, the GitHub Action proceeds to publish a [GitHub Release](https://github.com/metisvela/sailtrack-core/releases), including the generated image as an asset. The built image will have the files in the `/boot` folder easily accessible for in-field modifications by plugging the SD card into a PC, and the files copied from the `rootfs` folder will automatically be placed in the required locations. > [!NOTE] -> The SailTrack OS image can be built by manually running the [Build Image](https://github.com/metisvela/sailtrack-core/actions/workflows/build.yml) GitHub Action and downloading the produced artifact. +> The SailTrack OS image can be built by manually running the [Package](https://github.com/metisvela/sailtrack-core/actions/workflows/package.yml) GitHub Action and downloading the produced artifact. Once the OS image is flashed and running on the Raspberry Pi, the first-run setup will take place. -The first-run setup uses Dietpi-Automation, which is configured in the [`dietpi.txt`](https://github.com/metis-vela-unipd/sailtrack-core/blob/main/dietpi.txt) and [`Automation_Custom_Script.sh`](https://github.com/metis-vela-unipd/sailtrack-core/blob/main/Automation_Custom_Script.sh) files. +The first-run setup uses Dietpi-Automation, which is configured in the [`dietpi.txt`](dietpi.txt) and [`Automation_Custom_Script.sh`](Automation_Custom_Script.sh) files. The `dietpi.txt` file contains all the settings for DietPi (such as the networking configuration, the time zone, etc.) and the automation configuration, such as the software to install and how to configure it. Since DietPi-Automation's built-in features aren't enough to fully configure the OS, a bash script is needed, namely `Automation_Custom_Script.sh`. This script runs after the DietPi configuration, and it finishes the steps needed to set up SailTrack Core (e.g. it installs the missing packages, it sets up authentication tokens, etc.). Once the script ends, the Raspberry Pi is rebooted, and SailTrack Core is then successfully deployed. - ## Components + In this section, each component of the system will be analyzed in detail. -### WiFi -The WiFi access point is served using the DietPi's built-in "WiFi Hotspot" software package. +### Wi-Fi + +The Wi-Fi access point is served using the DietPi's built-in "Wi-Fi Hotspot" software package. All it's needed is to enable the installation of the software package and configure the details of the WiFi network in the `dietpi.txt` file (under `AUTO_SETUP_INSTALL_SOFTWARE_ID`), and DietPi-Automation will take care of installing and setting it up. ### MQTT Broker (Mosquitto) The MQTT broker is installed using the DietPi's built-in "Mosquitto" software package, which installs and sets up the Mosquitto broker. -As for the WiFi, the installation is enabled in the `dietpi.txt` file. +As for the Wi-Fi, the installation is enabled in the `dietpi.txt` file. ### Time-Series Database (InfluxDB) The time-series database is installed using the DietPi built-in "InfluxDB" software package, which installs and sets up the InfluxDB database. -Also here, all it's needed is to enable the software package in the `dietpi.txt` file. +Again here, all it's needed is to enable the software package in the `dietpi.txt` file. ### Metrics Collector (Telegraf) @@ -87,7 +121,7 @@ Unlike the other components, the metrics collector is not included in the built- This is done in the `Automation_Custom_Script.sh` script, using a DietPi function called `G_AGI`, which calls the `apt install` command. Additionally, Telegraf requires a configuration file in `etc/telegraf`. -As for the guidelines, the addition of a static configuration file is done by adding it in `rootfs/etc/telegraf`. +As for the guidelines, the addition of a static configuration file is done by adding it in [`rootfs/etc/telegraf`](rootfs/etc/telegraf). ### Visualization Tool (Grafana) @@ -98,6 +132,7 @@ Additionally, Grafana requires some configuration files, assets for the dashboar This is done by configuring Grafana in `Automation_Custom_Script.sh` and putting the configuration files and assets in `rootfs` accordingly. ### SailTrack Scripts + * [`sailtrack-x708_softsd`](sailtrack/sailtrack-x708_softsd) - Shell script that powers off the Raspberry Pi by sending an impulse to the [Geekworm X708](https://wiki.geekworm.com/X708) power HAT. This is required in order to perform a full software shutdown (software shutdown + battery power disconnected). Otherwise, you will only be able to perform a software shutdown. @@ -105,13 +140,13 @@ This is done by configuring Grafana in `Automation_Custom_Script.sh` and putting This is needed to perform a full shutdown or reboot using a physical power button (the HAT sends the signal to this script, which performs the software shutdown/reboot, and then the HAT cuts the power). * [`sailtrack-timesync`](sailtrack/sailtrack-timesync) - Python script that continuously listens to the `sensor/gps0` topic for a message that contains the `epoch` field, setting the system time accordingly to the received epoch. This is needed because the Raspberry Pi has no RTC clock built-in and will therefore lose track of the time and date as soon as it is shut down. - Instead, [SailTrack Radio](https://github.com/metis-vela-unipd/sailtrack-radio) has a built-in RTC clock for the GPS, and therefore it sends, along with the GPS data, the current time and date. + Instead, [SailTrack Radio](https://github.com/metisvela/sailtrack-radio) has a built-in RTC clock for the GPS, and therefore it sends, along with the GPS data, the current time and date. * [`sailtrack-status`](sailtrack/sailtrack-status) - Python script that periodically sends the status data (e.g. battery voltage, CPU load, CPU temperature, etc.) of the module. Needed for logging purposes. * [`sailtrack-processor`](sailtrack/sailtrack-processor) - Python script that processes the incoming sensor data. This is required for calculating metrics (such as drift) and filtering (such as speed, latitude, and longitude). -All of the tasks listed above are run as [systemd](https://en.wikipedia.org/wiki/Systemd) services, which means that systemd will start them, log their output in the system journal, and restart them if they fail. +All the tasks listed above are run as [systemd](https://en.wikipedia.org/wiki/Systemd) services, which means that systemd will start them, log their output in the system journal, and restart them if they fail. If you are unfamiliar with systemd, check out one of the many [online tutorials](https://www.digitalocean.com/community/tutorials/systemd-essentials-working-with-services-units-and-the-journal). Every systemd service is defined by a unit file. The unit files of the custom scripts are all located in [`rootfs/etc/systemd/system`](rootfs/etc/systemd/system). @@ -156,5 +191,5 @@ These commands switch to the temporary database, copy data to the original datab ```bash rm ~/saitrack_core_db_backup.tar.gz -rm -r ~//sailtrack_core_db_backup +rm -r ~/sailtrack_core_db_backup ``` diff --git a/Makefile.toml b/Makefile.toml new file mode 100644 index 0000000..7789e74 --- /dev/null +++ b/Makefile.toml @@ -0,0 +1,18 @@ +[tasks.default] +clear = true +dependencies = [ + "check-format", + "clippy", + "build-release", +] + +[tasks.build-release] +command = "cross" + +[tasks.package] +clear = true +condition = { platforms = [ "linux" ] } +dependencies = [ + "default" +] +script = { file = ".make/sailtrack-package" } diff --git a/README.md b/README.md index 7aa3158..772ee53 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@
- +
# SailTrack Core diff --git a/src/bin/sailtrack-dummy.rs b/src/bin/sailtrack-dummy.rs new file mode 100644 index 0000000..0672e51 --- /dev/null +++ b/src/bin/sailtrack-dummy.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, World!"); +}