diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish.yml similarity index 95% rename from .github/workflows/publish-release.yml rename to .github/workflows/publish.yml index 61ef5e5..cfa06d9 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish.yml @@ -1,4 +1,4 @@ -name: Publish GitHub Release +name: Publish Release on: push: diff --git a/Automation_Custom_Script.sh b/Automation_Custom_Script.sh index 34394c9..d0c9ffc 100644 --- a/Automation_Custom_Script.sh +++ b/Automation_Custom_Script.sh @@ -3,23 +3,27 @@ # Configure X708 HAT G_CONFIG_INJECT "alias poweroff=/boot/sailtrack/sailtrack-x708_softsd" "alias poweroff=/boot/sailtrack/sailtrack-x708_softsd" /etc/bash.bashrc -# Remove unused services +# Remove unused components G_EXEC rm /etc/systemd/system/dietpi-vpn.service G_EXEC rm /etc/systemd/system/dietpi-cloudshell.service - -# Uninstall OpenSSH Client /boot/dietpi/dietpi-software uninstall 0 -# Install Telegraf +# Install required packages G_AGI telegraf +G_EXEC pip3 install gpiozero +G_EXEC pip3 install paho-mqtt +G_EXEC pip3 install smbus2 +G_EXEC pip3 install timeloop # Enable services G_EXEC systemctl enable sailtrack-x708_asd G_EXEC systemctl enable sailtrack-x708_pwr G_CONFIG_INJECT "+ telegraf" "+ telegraf" /boot/dietpi/.dietpi-services_include_exclude G_CONFIG_INJECT "+ sailtrack-status" "+ sailtrack-status" /boot/dietpi/.dietpi-services_include_exclude +G_CONFIG_INJECT "+ sailtrack-timesync" "+ sailtrack-timesync" /boot/dietpi/.dietpi-services_include_exclude G_EXEC /boot/dietpi/dietpi-services dietpi_controlled telegraf G_EXEC /boot/dietpi/dietpi-services dietpi_controlled sailtrack-status +G_EXEC /boot/dietpi/dietpi-services dietpi_controlled sailtrack-timesync # Configure DietPi Banner settings=(1 1 1 0 0 1 0 1 0 0 0 0 0 0 0 0) @@ -29,4 +33,3 @@ done # Reboot after first boot is completed (while [ -f "/root/AUTO_CustomScript.sh" ]; do sleep 1; done; /usr/sbin/reboot) > /dev/null 2>&1 & - diff --git a/dietpi.txt b/dietpi.txt index d2a6fd5..086aa5f 100644 --- a/dietpi.txt +++ b/dietpi.txt @@ -131,6 +131,7 @@ AUTO_SETUP_GLOBAL_PASSWORD=dietpi # - DietPi will automatically install all dependencies, like ALSA/X11 for desktops etc. # - E.g. the following (without the leading "#") will install the LXDE desktop automatically on first boot: #AUTO_SETUP_INSTALL_SOFTWARE_ID=23 +AUTO_SETUP_INSTALL_SOFTWARE_ID=130 # Python 3 + Pip AUTO_SETUP_INSTALL_SOFTWARE_ID=72 # I2C AUTO_SETUP_INSTALL_SOFTWARE_ID=60 # WiFi Hotspot AUTO_SETUP_INSTALL_SOFTWARE_ID=123 # Mosquitto @@ -240,7 +241,7 @@ SOFTWARE_OWNCLOUD_DATADIR=/mnt/dietpi_userdata/owncloud_data SOFTWARE_NEXTCLOUD_DATADIR=/mnt/dietpi_userdata/nextcloud_data # WiFi Hotspot -SOFTWARE_WIFI_HOTSPOT_SSID=SailTrack-Net +SOFTWARE_WIFI_HOTSPOT_SSID=SailTrack-CoreNet # - Key requires a minimum of 8 characters SOFTWARE_WIFI_HOTSPOT_KEY=sailtracknet SOFTWARE_WIFI_HOTSPOT_CHANNEL=1 diff --git a/rootfs/etc/default/telegraf b/rootfs/etc/default/telegraf index 90fe021..9b66ddb 100644 --- a/rootfs/etc/default/telegraf +++ b/rootfs/etc/default/telegraf @@ -1,6 +1,6 @@ -INFLUX_URL="http://localhost:8086" +INFLUX_URL="http://192.168.42.1:8086" INFLUX_USER="admin" INFLUX_PASSWORD="dietpi" -MQTT_SERVER="tcp://localhost:1883" +MQTT_SERVER="tcp://192.168.42.1:1883" MQTT_USER="mosquitto" MQTT_PASSWORD="dietpi" diff --git a/rootfs/etc/sailtrack/sailtrack.conf b/rootfs/etc/sailtrack/sailtrack.conf new file mode 100644 index 0000000..f3933b9 --- /dev/null +++ b/rootfs/etc/sailtrack/sailtrack.conf @@ -0,0 +1,7 @@ +[mqtt] +host = 192.168.42.1 +username = mosquitto +password = dietpi + +[log] +format = [%(name)s] [%(levelname)s] %(message)s diff --git a/rootfs/etc/systemd/system/sailtrack-status.service b/rootfs/etc/systemd/system/sailtrack-status.service index d3593d5..542c9c5 100644 --- a/rootfs/etc/systemd/system/sailtrack-status.service +++ b/rootfs/etc/systemd/system/sailtrack-status.service @@ -2,6 +2,7 @@ Description=SailTrack-Status [Service] +Restart=on-failure ExecStart=/boot/sailtrack/sailtrack-status [Install] diff --git a/rootfs/etc/systemd/system/sailtrack-timesync.service b/rootfs/etc/systemd/system/sailtrack-timesync.service index 8dda3ae..b24000c 100644 --- a/rootfs/etc/systemd/system/sailtrack-timesync.service +++ b/rootfs/etc/systemd/system/sailtrack-timesync.service @@ -2,6 +2,7 @@ Description=SailTrack-TimeSync [Service] +Restart=on-failure ExecStart=/boot/sailtrack/sailtrack-timesync [Install] diff --git a/rootfs/etc/systemd/system/sailtrack-x708_asd.service b/rootfs/etc/systemd/system/sailtrack-x708_asd.service index 058f720..4bc123e 100644 --- a/rootfs/etc/systemd/system/sailtrack-x708_asd.service +++ b/rootfs/etc/systemd/system/sailtrack-x708_asd.service @@ -4,6 +4,7 @@ After=dietpi-ramlog.service Before=dietpi-preboot.service [Service] +Restart=on-failure ExecStart=/boot/sailtrack/sailtrack-x708_asd [Install] diff --git a/rootfs/etc/systemd/system/sailtrack-x708_pwr.service b/rootfs/etc/systemd/system/sailtrack-x708_pwr.service index d313711..fb639ff 100644 --- a/rootfs/etc/systemd/system/sailtrack-x708_pwr.service +++ b/rootfs/etc/systemd/system/sailtrack-x708_pwr.service @@ -4,6 +4,7 @@ After=dietpi-ramlog.service Before=dietpi-preboot.service [Service] +Restart=on-failure ExecStart=/boot/sailtrack-x708_pwr [Install] diff --git a/rootfs/etc/telegraf/telegraf.conf b/rootfs/etc/telegraf/telegraf.conf index 674069e..a61348e 100644 --- a/rootfs/etc/telegraf/telegraf.conf +++ b/rootfs/etc/telegraf/telegraf.conf @@ -28,7 +28,7 @@ omit_hostname = true [[inputs.mqtt_consumer]] servers = ["${MQTT_SERVER}"] topics = ["#"] - client_id = "sailtrack-core" + client_id = "telegraf" username = "${MQTT_USER}" password = "${MQTT_PASSWORD}" data_format = "json" diff --git a/sailtrack/sailtrack-status b/sailtrack/sailtrack-status old mode 100644 new mode 100755 index 05a7907..ce71fd6 --- a/sailtrack/sailtrack-status +++ b/sailtrack/sailtrack-status @@ -1,2 +1,103 @@ -#!/bin/bash +#!/usr/bin/env python3 +import json +import logging +import os +import struct +import sys +from configparser import ConfigParser +from datetime import timedelta + +from gpiozero import DigitalInputDevice, CPUTemperature, LoadAverage, DiskUsage +from paho.mqtt.client import Client +from smbus2 import SMBus +from timeloop import Timeloop + +# -------------------------- Configuration -------------------------- # + +MQTT_PUBLISH_FREQ_HZ = 0.1 +LOG_PRINT_FREQ_HZ = 0.1 + +MQTT_CLIENT_ID = "sailtrack-status" +CONFIG_FILE_PATH = "/etc/sailtrack/sailtrack.conf" + +I2C_BUS_NUM = 1 +I2C_ADDR = 0x36 +I2C_BATTERY_VOLTAGE_REG = 0x02 +I2C_BATTERY_CAPACITY_REG = 0x04 + +CHARGE_PIN = 6 + +MQTT_JOB_INTERVAL_SEC = 1 / MQTT_PUBLISH_FREQ_HZ +LOG_JOB_INTERVAL_SEC = 1 / LOG_PRINT_FREQ_HZ + +# ------------------------------------------------------------------- # + +published_messages = 0 +received_messages = 0 + + +def on_publish_callback(client, userdata, mid): + global published_messages + published_messages += 1 + + +def get_battery_voltage(): + regval = bus.read_word_data(I2C_ADDR, I2C_BATTERY_VOLTAGE_REG) + regval = struct.unpack("H", regval))[0] + return regval * 1.25 / 1000 / 16 + + +def get_battery_capacity(): + regval = bus.read_word_data(I2C_ADDR, I2C_BATTERY_CAPACITY_REG) + regval = struct.unpack("H", regval))[0] + return regval / 256 + + +config = ConfigParser() +config.read(CONFIG_FILE_PATH) +bus = SMBus(I2C_BUS_NUM) +mqtt = Client(MQTT_CLIENT_ID) +mqtt.username_pw_set(config["mqtt"]["username"], config["mqtt"]["password"]) +mqtt.on_publish = on_publish_callback +mqtt.connect(config["mqtt"]["host"]) +tl = Timeloop() +formatter = logging.Formatter(config.get("log", "format", raw=True)) +logging.getLogger("timeloop").handlers[0].setFormatter(formatter) +logger = logging.getLogger(MQTT_CLIENT_ID) +logger.setLevel(logging.INFO) +handler = logging.StreamHandler() +handler.setFormatter(formatter) +logger.addHandler(handler) +battery_charging = DigitalInputDevice(CHARGE_PIN) +cpu_temperature = CPUTemperature() +cpu_load = LoadAverage() +disk_load = DiskUsage() + + +@tl.job(interval=timedelta(seconds=MQTT_JOB_INTERVAL_SEC)) +def mqtt_job(): + sys.stdout = open(os.devnull, 'w') + mqtt.publish("status/core", json.dumps({ + "battery": { + "voltage": get_battery_voltage(), + "capacity": get_battery_capacity(), + "charging": not battery_charging.value + }, + "cpu": { + "temperature": cpu_temperature.temperature, + "load": cpu_load.load_average + }, + "disk": { + "load": disk_load.value + } + })) + sys.stdout = sys.__stdout__ + + +@tl.job(interval=timedelta(seconds=LOG_JOB_INTERVAL_SEC)) +def log_job(): + logger.info(f"Published messages: {published_messages}, Received messages: {received_messages}") + + +tl.start(block=True) diff --git a/sailtrack/sailtrack-status.py b/sailtrack/sailtrack-status.py deleted file mode 100644 index e991405..0000000 --- a/sailtrack/sailtrack-status.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python3 - -import json -import logging -import os -import struct -import sys -from configparser import ConfigParser -from datetime import timedelta - -import smbus -from gpiozero import DigitalInputDevice, CPUTemperature, LoadAverage, DiskUsage -from paho.mqtt.client import Client -from timeloop import Timeloop - -PUBLISH_RATE = 0.1 -LOG_RATE = 0.1 - - -def on_publish(client, userdata, mid): - global published_messages - published_messages += 1 - - -def read_voltage(bus): - address = 0x36 - read = bus.read_word_data(address, 2) - swapped = struct.unpack('H', read))[0] - voltage = swapped * 1.25 / 1000 / 16 - return voltage - - -def read_capacity(bus): - address = 0x36 - read = bus.read_word_data(address, 4) - swapped = struct.unpack('H', read))[0] - capacity = swapped / 256 - return capacity - - -bus = smbus.SMBus(1) -mqtt = Client('core-status') -mqtt.username_pw_set('mosquitto', 'dietpi') -mqtt.on_publish = on_publish -mqtt.connect('localhost') - -tl = Timeloop() - -logging.getLogger('timeloop').removeHandler(logging.getLogger('timeloop').handlers[0]) -logging.basicConfig(format='[%(name)s] [%(levelname)s] %(message)s', level=logging.INFO) -published_messages = 0 - - -@tl.job(interval=timedelta(seconds=1/PUBLISH_RATE)) -def publish_job(): - sys.stdout = open(os.devnull, 'w') - mqtt.publish('module/core', json.dumps({ - 'battery': { - 'voltage': read_voltage(bus), - 'capacity': read_capacity(bus), - 'charging': not DigitalInputDevice(6).value - }, - 'cpu': { - 'temperature': CPUTemperature().temperature, - 'load': LoadAverage().load_average - }, - 'disk': { - 'usage': DiskUsage().usage - }, - 'measurement': 'core' - })) - sys.stdout = sys.__stdout__ - - -@tl.job(interval=timedelta(seconds=1/LOG_RATE)) -def log_job(): - logging.getLogger('log_job').info(f"Published Messages: {published_messages}") - - -tl.start(block=True) diff --git a/sailtrack/sailtrack-timesync b/sailtrack/sailtrack-timesync old mode 100644 new mode 100755 index 05a7907..7f298ba --- a/sailtrack/sailtrack-timesync +++ b/sailtrack/sailtrack-timesync @@ -1,2 +1,41 @@ -#!/bin/bash +#!/usr/bin/env python3 +import json +import logging +import time +from configparser import ConfigParser + +from paho.mqtt.client import Client + +# -------------------------- Configuration -------------------------- # + +MQTT_CLIENT_ID = "sailtrack-timesync" +CONFIG_FILE_PATH = "/etc/sailtrack/sailtrack.conf" + +# ------------------------------------------------------------------- # + + +def on_message_callback(client, userdata, message): + doc = json.loads(message.payload) + if "epoch" in doc and doc["epoch"]: + logger.info(f"Received epoch: {doc['epoch']}") + time.clock_settime(time.CLOCK_REALTIME, doc["epoch"]) + logger.info("Time synced successfully!") + logger.info("Exiting...") + exit() + + +config = ConfigParser() +config.read(CONFIG_FILE_PATH) +mqtt = Client(MQTT_CLIENT_ID) +mqtt.username_pw_set(config["mqtt"]["username"], config["mqtt"]["password"]) +mqtt.on_message = on_message_callback +mqtt.connect(config["mqtt"]["host"]) +mqtt.subscribe("sensor/gps0") +logger = logging.getLogger(MQTT_CLIENT_ID) +logger.setLevel(logging.INFO) +handler = logging.StreamHandler() +handler.setFormatter(logging.Formatter(config.get("log", "format", raw=True))) +logger.addHandler(handler) +logger.info("Waiting for epoch...") +mqtt.loop_forever() diff --git a/sailtrack/sailtrack-x708_asd b/sailtrack/sailtrack-x708_asd old mode 100644 new mode 100755 index be0330f..c8cc7c2 --- a/sailtrack/sailtrack-x708_asd +++ b/sailtrack/sailtrack-x708_asd @@ -1,11 +1,15 @@ #!/bin/bash POWEROFF_VOLTAGE=2.5 +I2C_BUS_NUM=1 +I2C_ADDR=0x36 +I2C_BATTERY_VOLTAGE_REG=0x02 +SLEEP_TIME_MS=10 while : ; do - read=$(i2cget -y 1 0x36 0x02 w) - swapped=${read:4:2}${read:2:2} - voltage=$(awk 'BEGIN {printf "%.2f", ARGV[1] * 1.25 / 1000 / 16}' "$(( 16#$swapped ))") - if awk "BEGIN {exit ARGV[1] > ARGV[2]}" "$voltage" "$POWEROFF_VOLTAGE"; then sudo /usr/sbin/poweroff; fi - sleep 10 + regval=$(i2cget -y $I2C_BUS_NUM $I2C_ADDR $I2C_BATTERY_VOLTAGE_REG w) + regval=${regval:4:2}${regval:2:2} + voltage=$(awk 'BEGIN {printf "%.2f", ARGV[1] * 1.25 / 1000 / 16}' "$((16#$regval))") + if awk "BEGIN {exit ARGV[1] > ARGV[2]}" "$voltage" "$POWEROFF_VOLTAGE"; then poweroff; fi + sleep $SLEEP_TIME_MS done diff --git a/sailtrack/sailtrack-x708_pwr b/sailtrack/sailtrack-x708_pwr old mode 100644 new mode 100755 index 03bb47c..533d49a --- a/sailtrack/sailtrack-x708_pwr +++ b/sailtrack/sailtrack-x708_pwr @@ -1,29 +1,30 @@ #!/bin/bash -SHUTDOWN=5 -REBOOTPULSEMINIMUM=200 -REBOOTPULSEMAXIMUM=600 -echo "$SHUTDOWN" > /sys/class/gpio/export -echo "in" > /sys/class/gpio/gpio$SHUTDOWN/direction -BOOT=12 -echo "$BOOT" > /sys/class/gpio/export -echo "out" > /sys/class/gpio/gpio$BOOT/direction -echo "1" > /sys/class/gpio/gpio$BOOT/value +SHUTDOWN_PIN=5 +BOOT_PIN=12 +REBOOT_PULSE_MIN_MS=200 +REBOOT_PULSE_MAX_MS=600 + +echo $SHUTDOWN_PIN > /sys/class/gpio/export +echo "in" > /sys/class/gpio/gpio$SHUTDOWN_PIN/direction +echo $BOOT_PIN > /sys/class/gpio/export +echo "out" > /sys/class/gpio/gpio$BOOT_PIN/direction +echo "1" > /sys/class/gpio/gpio$BOOT_PIN/value while : ; do - shutdownSignal=$( /sys/class/gpio/export +echo "out" > /sys/class/gpio/gpio$BUTTON_PIN/direction -echo "$BUTTON" > /sys/class/gpio/export -echo "out" > /sys/class/gpio/gpio$BUTTON/direction -echo "1" > /sys/class/gpio/gpio$BUTTON/value - -SLEEP=${1:-4} - -re='^[0-9\.]+$' -if ! [[ $SLEEP =~ $re ]] ; then - echo "error: sleep time not a number" >&2; exit 1 -fi - -/bin/sleep "$SLEEP" - -# Restore GPIO 13 -echo "0" > /sys/class/gpio/gpio$BUTTON/value +echo "1" > /sys/class/gpio/gpio$BUTTON_PIN/value +/bin/sleep $SLEEP_TIME_SEC +echo "0" > /sys/class/gpio/gpio$BUTTON_PIN/value