From b7d61f69f9d54de8f2fd216639d7c071ff09835c Mon Sep 17 00:00:00 2001 From: Chris Gerth Date: Sun, 29 Jun 2025 18:34:00 -0500 Subject: [PATCH 1/9] WIP systemcore app test --- .github/workflows/make_ipks.yml | 30 ++++++ systemcore-apps/system-view/build.sh | 93 ++++++++++++++++++ systemcore-apps/system-view/control/control | 13 +++ systemcore-apps/system-view/control/postinst | 29 ++++++ systemcore-apps/system-view/control/postrm | 15 +++ systemcore-apps/system-view/control/prerm | 27 +++++ .../systemd/system/pv-system-viewer.service | 23 +++++ .../overlay/usr/share/pv-system-viewer.png | Bin 0 -> 112848 bytes 8 files changed, 230 insertions(+) create mode 100644 .github/workflows/make_ipks.yml create mode 100644 systemcore-apps/system-view/build.sh create mode 100644 systemcore-apps/system-view/control/control create mode 100644 systemcore-apps/system-view/control/postinst create mode 100644 systemcore-apps/system-view/control/postrm create mode 100644 systemcore-apps/system-view/control/prerm create mode 100644 systemcore-apps/system-view/overlay/etc/systemd/system/pv-system-viewer.service create mode 100644 systemcore-apps/system-view/overlay/usr/share/pv-system-viewer.png diff --git a/.github/workflows/make_ipks.yml b/.github/workflows/make_ipks.yml new file mode 100644 index 0000000000..0174a56b43 --- /dev/null +++ b/.github/workflows/make_ipks.yml @@ -0,0 +1,30 @@ +name: Make IPKs + +on: + push: + branches: + - "*" + tags-ignore: + - "*" + pull_request: + release: + types: [published] + +jobs: + + build-system-viewer: + name: Build IPK for SystemViewer + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Build IPK (SystemCore) + run: cd systemcore-apps/system-view && ./build.sh + - name: Upload development artifact (SystemCore) + uses: actions/upload-artifact@v4 + with: + name: advantagescopelite-systemcore + path: systemcore-apps/system-view/pv-system-view_*.ipk + + diff --git a/systemcore-apps/system-view/build.sh b/systemcore-apps/system-view/build.sh new file mode 100644 index 0000000000..56b1e30d20 --- /dev/null +++ b/systemcore-apps/system-view/build.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +set -e + +# Extract package info from control/control file +if [ ! -f "control/control" ]; then + echo "Error: control/control not found!" + echo "Create a control/control file with package metadata" + exit 1 +fi + +PACKAGE_NAME=$(grep "^Package:" control/control | cut -d' ' -f2- | tr -d ' ') +PACKAGE_VERSION=$(grep "^Version:" control/control | cut -d' ' -f2- | tr -d ' ') + +# Validate required fields +if [ -z "$PACKAGE_NAME" ] || [ -z "$PACKAGE_VERSION" ]; then + echo "Err: Package and Version must be set in control/control" + echo "Package: my-package" + echo "Version: 1.0.0" + exit 1 +fi + +PACKAGE_DIR="${PACKAGE_NAME}_${PACKAGE_VERSION}" +BUILD_DIR="build" + +echo "Building IPK package from overlay structure..." +echo "Package: ${PACKAGE_NAME}_${PACKAGE_VERSION}.ipk" + +if [ ! -d "overlay" ]; then + echo "overlay/ directory not found" + exit 1 +fi + +if [ ! -d "control" ]; then + echo "Error: control/ directory not found!" + echo "Create control/ with control, postinst, prerm, postrm files" + exit 1 +fi + +echo "Cleaning previous build..." +rm -rf "$BUILD_DIR" +mkdir -p "$BUILD_DIR/$PACKAGE_DIR" + +echo "Copying overlay structure..." +cp -r overlay/* "$BUILD_DIR/$PACKAGE_DIR/" + +echo "Copying CONTROL files..." +mkdir -p "$BUILD_DIR/$PACKAGE_DIR/CONTROL" +cp control/* "$BUILD_DIR/$PACKAGE_DIR/CONTROL/" + +echo "Setting file permissions..." + +# Make scripts executable +find "$BUILD_DIR/$PACKAGE_DIR" -name "*.py" -exec chmod +x {} \; + +if [ -d "$BUILD_DIR/$PACKAGE_DIR/CONTROL" ]; then + chmod +x "$BUILD_DIR/$PACKAGE_DIR/CONTROL"/* 2>/dev/null || true +fi + +find "$BUILD_DIR/$PACKAGE_DIR" -name "*.sh" -exec chmod +x {} \; + +echo "Building IPK dir structure" +cd "$BUILD_DIR" + +echo "Creating data.tar.gz" +tar --exclude='CONTROL' -czf data.tar.gz -C "$PACKAGE_DIR" . + +echo "Creating control.tar.gz" +tar -czf control.tar.gz -C "$PACKAGE_DIR/CONTROL" . + +echo "Creating IPK..." +ar r "../${PACKAGE_NAME}_${PACKAGE_VERSION}.ipk" control.tar.gz data.tar.gz + +cd .. + +echo "" +echo "IPK package created." +echo "Package: ${PACKAGE_NAME}_${PACKAGE_VERSION}.ipk" +echo "" +echo "Package structure:" +echo " CONTROL files:" +find control -type f | sort | sed 's/^/ /' +echo " Overlay files (will be installed):" +find overlay -type f | sort | sed 's/^overlay/ /' | head -15 + +if [ $(find overlay -type f | wc -l) -gt 15 ]; then + echo " ... and $(($(find overlay -type f | wc -l) - 15)) more files" +fi + +rm -rf "$BUILD_DIR" + +echo "" +echo "Build complete" \ No newline at end of file diff --git a/systemcore-apps/system-view/control/control b/systemcore-apps/system-view/control/control new file mode 100644 index 0000000000..881d1220e8 --- /dev/null +++ b/systemcore-apps/system-view/control/control @@ -0,0 +1,13 @@ +Package: pv-system-viewer +Version: 0.1.0 +Description: PhotonVision System Viewer - A simple interface to see all PhotonVision cameras. +Section: development +Priority: optional +Maintainer: PhotonVision Team +Architecture: all +Source: local +X-Port: 5804 +X-Has-UI: true +X-Auto-Start: true +X-Icon-Path: /usr/share/pv-system-viewer.png +X-Display-Name: PhotonVision System Viewer \ No newline at end of file diff --git a/systemcore-apps/system-view/control/postinst b/systemcore-apps/system-view/control/postinst new file mode 100644 index 0000000000..91ac587af2 --- /dev/null +++ b/systemcore-apps/system-view/control/postinst @@ -0,0 +1,29 @@ +#!/bin/sh +PACKAGE_NAME="pv-system-viewer" + +echo "Configuring service for $PACKAGE_NAME" + +systemctl daemon-reload +sleep 1 + +echo "Enabling service for auto-start on boot..." +systemctl enable $PACKAGE_NAME.service + +echo "Starting service..." +if systemctl start $PACKAGE_NAME.service; then + echo "Service started successfully" + + sleep 2 + + if systemctl is-active $PACKAGE_NAME.service >/dev/null 2>&1; then + echo "Service is now running" + else + echo "Service may have an issue" + fi +else + echo "Failed to start service automatically" +fi + +echo "Package installation complete" + +exit 0 \ No newline at end of file diff --git a/systemcore-apps/system-view/control/postrm b/systemcore-apps/system-view/control/postrm new file mode 100644 index 0000000000..8078e7e217 --- /dev/null +++ b/systemcore-apps/system-view/control/postrm @@ -0,0 +1,15 @@ +#!/bin/sh +PACKAGE_NAME="pv-system-viewer" + +systemctl daemon-reload +systemctl reset-failed $PACKAGE_NAME.service 2>/dev/null || true + +if systemctl list-unit-files | grep -q "$PACKAGE_NAME.service"; then + echo "Service still appears in systemd unit files (normal until next boot)" +else + echo "Service removed from systemd" +fi + +echo "Service cleanup complete." + +exit 0 \ No newline at end of file diff --git a/systemcore-apps/system-view/control/prerm b/systemcore-apps/system-view/control/prerm new file mode 100644 index 0000000000..a5c473fb47 --- /dev/null +++ b/systemcore-apps/system-view/control/prerm @@ -0,0 +1,27 @@ +#!/bin/sh +PACKAGE_NAME="pv-system-viewer" + +echo "Stopping $PACKAGE_NAME service..." + +if systemctl is-active $PACKAGE_NAME.service >/dev/null 2>&1; then + echo "Service is running, stopping it..." + if systemctl stop $PACKAGE_NAME.service; then + echo "Service stopped successfully" + else + echo "Service stop may have failed, continuing anyway..." + fi +else + echo "Service was not running" +fi + +# Disable the service +echo "Disabling service auto-start..." +if systemctl disable $PACKAGE_NAME.service 2>/dev/null; then + echo "Service auto-start disabled" +else + echo "Service was not enabled or disable failed" +fi + +echo "Service stopped and disabled" + +exit 0 \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/etc/systemd/system/pv-system-viewer.service b/systemcore-apps/system-view/overlay/etc/systemd/system/pv-system-viewer.service new file mode 100644 index 0000000000..7cbc05b587 --- /dev/null +++ b/systemcore-apps/system-view/overlay/etc/systemd/system/pv-system-viewer.service @@ -0,0 +1,23 @@ +[Unit] +Description=PhotonVision System Viewer - A simple interface to check all connected PhotonVision Coprocessor statuses +After=network.target +Wants=network.target + +[Service] +Type=simple +User=root +Group=root +ExecStart=/usr/local/bin/pv-system-viewer/pv-system-viewer.py +Restart=always +RestartSec=5 +TimeoutStartSec=3 +TimeoutStopSec=3 + +NoNewPrivileges=true +PrivateTmp=true +ProtectSystem=strict +ProtectHome=true +ReadWritePaths=/var/log + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/share/pv-system-viewer.png b/systemcore-apps/system-view/overlay/usr/share/pv-system-viewer.png new file mode 100644 index 0000000000000000000000000000000000000000..5646beaa0e36467ce5ea2def3866e606e4bdfdf9 GIT binary patch literal 112848 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 Date: Sun, 29 Jun 2025 18:35:34 -0500 Subject: [PATCH 2/9] I said build darn it. --- .github/workflows/make_ipks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/make_ipks.yml b/.github/workflows/make_ipks.yml index 0174a56b43..4a9646f927 100644 --- a/.github/workflows/make_ipks.yml +++ b/.github/workflows/make_ipks.yml @@ -20,7 +20,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 - name: Build IPK (SystemCore) - run: cd systemcore-apps/system-view && ./build.sh + run: cd systemcore-apps/system-view && chmod +x build.sh && ./build.sh - name: Upload development artifact (SystemCore) uses: actions/upload-artifact@v4 with: From 9a19a66db50d731aca7cd44eafc85552e6d1d4a2 Mon Sep 17 00:00:00 2001 From: Chris Gerth Date: Sun, 29 Jun 2025 18:36:39 -0500 Subject: [PATCH 3/9] spelling --- .github/workflows/make_ipks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/make_ipks.yml b/.github/workflows/make_ipks.yml index 4a9646f927..4bd8d9f004 100644 --- a/.github/workflows/make_ipks.yml +++ b/.github/workflows/make_ipks.yml @@ -25,6 +25,6 @@ jobs: uses: actions/upload-artifact@v4 with: name: advantagescopelite-systemcore - path: systemcore-apps/system-view/pv-system-view_*.ipk + path: systemcore-apps/system-view/pv-system-viewer_*.ipk From 0dfb7291f0d837301ce15b25b425398b6d014946 Mon Sep 17 00:00:00 2001 From: Chris Gerth Date: Sun, 29 Jun 2025 18:38:07 -0500 Subject: [PATCH 4/9] nope sorry jonah --- .github/workflows/make_ipks.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/make_ipks.yml b/.github/workflows/make_ipks.yml index 4bd8d9f004..db733ab4cb 100644 --- a/.github/workflows/make_ipks.yml +++ b/.github/workflows/make_ipks.yml @@ -24,7 +24,6 @@ jobs: - name: Upload development artifact (SystemCore) uses: actions/upload-artifact@v4 with: - name: advantagescopelite-systemcore path: systemcore-apps/system-view/pv-system-viewer_*.ipk From 841dae0cbc5ae577a81c57efc6192945211852cb Mon Sep 17 00:00:00 2001 From: Chris Gerth Date: Sun, 29 Jun 2025 18:39:45 -0500 Subject: [PATCH 5/9] "artifact" is a stupid default name --- .github/workflows/make_ipks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/make_ipks.yml b/.github/workflows/make_ipks.yml index db733ab4cb..b651c2b3c0 100644 --- a/.github/workflows/make_ipks.yml +++ b/.github/workflows/make_ipks.yml @@ -24,6 +24,7 @@ jobs: - name: Upload development artifact (SystemCore) uses: actions/upload-artifact@v4 with: + name: pv-system-viewer.ipk path: systemcore-apps/system-view/pv-system-viewer_*.ipk From ede9adc54cc8f686205eaaec2aea12f8955e8d8a Mon Sep 17 00:00:00 2001 From: Chris Gerth Date: Sun, 29 Jun 2025 19:04:13 -0500 Subject: [PATCH 6/9] helps if I actually include the whole overlay. --- systemcore-apps/system-view/.gitignore | 2 + .../usr/local/bin/pv-system-viewer/404.html | 5 + .../bin/pv-system-viewer/pv-system-viewer.py | 114 ++++ .../bin/pv-system-viewer/www/favicon.svg | 23 + .../www/interfaces/NT4_CalInf.js | 130 ++++ .../pv-system-viewer/www/interfaces/calobj.js | 17 + .../www/interfaces/dummy_NT4.js | 184 ++++++ .../www/interfaces/msgpack/msgpack.js | 564 ++++++++++++++++++ .../pv-system-viewer/www/interfaces/nt4.js | 547 +++++++++++++++++ .../www/interfaces/signalDAQ_NT4.js | 120 ++++ .../bin/pv-system-viewer/www/systemViewer.css | 99 +++ .../pv-system-viewer/www/systemViewer.html | 26 + .../bin/pv-system-viewer/www/systemViewer.js | 169 ++++++ 13 files changed, 2000 insertions(+) create mode 100644 systemcore-apps/system-view/.gitignore create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/404.html create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/pv-system-viewer.py create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/favicon.svg create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/NT4_CalInf.js create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/calobj.js create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/dummy_NT4.js create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/msgpack/msgpack.js create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/nt4.js create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/signalDAQ_NT4.js create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.css create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.html create mode 100644 systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.js diff --git a/systemcore-apps/system-view/.gitignore b/systemcore-apps/system-view/.gitignore new file mode 100644 index 0000000000..f0961fc12b --- /dev/null +++ b/systemcore-apps/system-view/.gitignore @@ -0,0 +1,2 @@ +!overlay/ +!overlay/** \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/404.html b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/404.html new file mode 100644 index 0000000000..e0b1f01921 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/404.html @@ -0,0 +1,5 @@ + + + +

404 error

+ \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/pv-system-viewer.py b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/pv-system-viewer.py new file mode 100644 index 0000000000..5ab9b4d199 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/pv-system-viewer.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 +import http.server +import socketserver +import threading +import signal +import sys +import os +import json +from datetime import datetime + +import mimetypes +# Ensure mimetypes are set for common file types +mimetypes.add_type('application/javascript', '.js') + + +class PVSystemViewerHandler(http.server.BaseHTTPRequestHandler): + def do_GET(self): + script_dir = os.path.dirname(os.path.abspath(__file__)) + www_dir = os.path.join(script_dir, 'www') # Path to the www folder + + if self.path == '/': + file_path = os.path.join(www_dir, 'systemViewer.html') + else: + # Serve the requested file + file_path = os.path.join(www_dir, self.path.lstrip('/')) + + # Check if the file exists and is within the www directory + if os.path.commonpath([www_dir, os.path.abspath(file_path)]) != www_dir or not os.path.isfile(file_path): + self.send_response(404) + self.send_header('Content-type', 'text/html') + self.end_headers() + self.wfile.write(b'

404 Not Found

') + return + + # Determine the MIME type of the file + mime_type, _ = mimetypes.guess_type(file_path) + print(mime_type) + self.send_response(200) + self.send_header('Content-type', mime_type or 'application/octet-stream') + self.end_headers() + + # Serve the file content + with open(file_path, 'rb') as f: + self.wfile.write(f.read()) + + def log_message(self, format, *args): + timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + print(f"[{timestamp}] {format % args}") + +class PVSystemViewerServer: + def __init__(self, port=5804): + self.port = port + self.httpd = None + self.server_thread = None + self.shutdown_event = threading.Event() + + def start(self): + try: + self.httpd = socketserver.TCPServer(("", self.port), PVSystemViewerHandler) + # Allow socket reuse to prevent "Address already in use" errors + self.httpd.allow_reuse_address = True + + self.server_thread = threading.Thread(target=self.httpd.serve_forever) + self.server_thread.daemon = True + self.server_thread.start() + print(f"PhotonVision System Viewer server started on port {self.port}") + return True + except Exception as e: + print(f"Failed to start server: {e}") + return False + + def stop(self): + print("Stopping PhotonVision System Viewer server...") + self.shutdown_event.set() + + if self.httpd: + self.httpd.shutdown() + self.httpd.server_close() + + if self.server_thread and self.server_thread.is_alive(): + self.server_thread.join(timeout=2) + + print("PhotonVision System Viewer server stopped") + +# Global server instance for signal handler +server_instance = None + +def signal_handler(signum, frame): + print(f"\nReceived signal {signum}, stopping server...") + if server_instance: + server_instance.stop() + sys.exit(0) + +def main(): + global server_instance + + # Register signal handlers + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + server_instance = PVSystemViewerServer(5804) + + if server_instance.start(): + print("PhotonVision System Viewer service is running. Managed by systemd.") + try: + server_instance.shutdown_event.wait() + except KeyboardInterrupt: + signal_handler(signal.SIGINT, None) + else: + print("Failed to start PhotonVision System Viewer service") + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/favicon.svg b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/favicon.svg new file mode 100644 index 0000000000..88643de263 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/favicon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/NT4_CalInf.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/NT4_CalInf.js new file mode 100644 index 0000000000..9602093c7f --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/NT4_CalInf.js @@ -0,0 +1,130 @@ +///////////////////////////////////////////////////////////////////////// +// Calibration - wrapper around NT4 to specifically extract cal information +// and allow clients to interact with one or more calibrations +// +// Mirroring (I assume) NT4 architecture, it's heavily callback driven +///////////////////////////////////////////////////////////////////////// + +import { NT4_Client } from "./nt4.js"; +import { CalObj } from "./calobj.js"; + +export class NT4_CalInf { + + /////////////////////////////////////// + // Public API + + constructor(onNewCalAdded_in, //Gets called when a new calibration is available + onCalValueUpdated_in, //Gets called when one calibration's value has changed. + onConnect_in, //Gets called once client completes initial handshake with server + onDisconnect_in) { //Gets called once client detects server has disconnected + this.onNewCalAdded = onNewCalAdded_in; + this.onCalValueUpdated = onCalValueUpdated_in; + this.onConnect = onConnect_in; + this.onDisconnect = onDisconnect_in; + + this.allCals = new Map(); + + + this.nt4Client = new NT4_Client(window.location.hostname, + this.topicAnnounceHandler.bind(this), + this.topicUnannounceHandler.bind(this), + this.valueUpdateHandler.bind(this), + this.onConnect.bind(this), + this.onDisconnect.bind(this) + ); + + this.nt4Client.subscribeAllSamples(["/Calibrations"]); + this.nt4Client.ws_connect(); + + } + + //Submit a new calibration value + setCalibrationValue(name, value){ + var valTopic = this.calNameToTopic(name, "desValue"); + this.nt4Client.addSample(valTopic, this.nt4Client.getServerTime_us(), value); + } + + /////////////////////////////////////////// + // Internal implementations + + topicAnnounceHandler(topic){ + + if(this.isCalTopic(topic, "curValue")){ + var calName = this.topicToCalName(topic); + + //we got something new related to calibrations... + + //ensure we've got an object for this cal + if(!this.allCals.has(calName)){ + var newCal = new CalObj(); + newCal.name = calName; + newCal.units = topic.properties.units; + newCal.min = topic.properties.min_cal; + newCal.max = topic.properties.max_cal; + newCal.default = topic.properties.default_val; + + if(newCal.min == null){ + newCal.min = -Infinity; + } + + if(newCal.max == null){ + newCal.max = Infinity; + } + + //Publish a desVal topic for every curVal topic + var desValTopic = this.nt4Client.publishNewTopic(this.calNameToTopic(calName, "desValue"), topic.type); + this.nt4Client.setProperties(desValTopic, false, true); + + this.allCals.set(calName, newCal); + this.onNewCalAdded(newCal); + + } + } + } + + topicUnannounceHandler(topic){ + if(this.isCalTopic(topic, "curValue")){ + var oldTopic = this.allCals.get(this.topicToCalName(topic)); + this.allCals.delete(this.topicToCalName(topic)); + //TODO call user hook + //TODO unpublish desired + } + } + + + valueUpdateHandler(topic, timestamp, value){ + if(this.isCalTopic(topic, "curValue")){ + var calName = this.topicToCalName(topic); + var updatedCal = this.allCals.get(calName); + updatedCal.value = value; + this.onCalValueUpdated(updatedCal); + } + } + + + ///////////////////////////////////////////////// + // Helper Utiltiies + + calNameToTopic(name, suffix){ + return "/Calibrations/" + name + "/" + suffix; + } + + isCalTopic(topic, suffix){ + if(suffix === undefined){ + suffix = ".*"; + } + var replace = "\/Calibrations\/[a-zA-Z0-9 \._]+\/"+suffix; + var re = new RegExp(replace,"g"); + return re.test(topic.name); + } + + topicToCalName(topic){ + var replace = "\/Calibrations\/([a-zA-Z0-9 \._]+)\/"; + var re = new RegExp(replace,"g"); + var arr = re.exec(topic.name); + return arr[1]; + } + + + +} \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/calobj.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/calobj.js new file mode 100644 index 0000000000..2d6caaa6a3 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/calobj.js @@ -0,0 +1,17 @@ +export class CalObj { + name = null; + units = null; + min = null; + max = null; + default = null; + value = null; + + isFullyAnnounced() { + return this.name != null && + this.units != null && + this.min != null && + this.max != null && + this.default != null && + this.value != null; + } +} \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/dummy_NT4.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/dummy_NT4.js new file mode 100644 index 0000000000..2a15f503ea --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/dummy_NT4.js @@ -0,0 +1,184 @@ +export class NT4_Client { + + + constructor(serverAddr, + onTopicAnnounce_in, //Gets called when server announces enough topics to form a new signal + onTopicUnAnnounce_in, //Gets called when server unannounces any part of a signal + onNewTopicData_in, //Gets called when any new data is available + onConnect_in, //Gets called once client completes initial handshake with server + onDisconnect_in) { //Gets called once client detects server has disconnected + + this.onTopicAnnounce = onTopicAnnounce_in; + this.onTopicUnAnnounce = onTopicUnAnnounce_in; + this.onNewTopicData = onNewTopicData_in; + this.onConnect = onConnect_in; + this.onDisconnect = onDisconnect_in; + + this.subscriptions = new Set(); + + + //TEST ONLY - fake data source loop and events + setTimeout(this.testConnect.bind(this),500); + setTimeout(this.testAnnounceSignals.bind(this),750); + this.loopCount = 0; + + } + + announceTopic(name, defaultVal){ + this.testTopicsMap.set(name, defaultVal); + this.onTopicAnnounce(name, defaultVal); + } + + unAnnounceTopic(name){ + this.testTopicsMap.delete(name); + this.onTopicUnAnnounce(name); + } + + addSample(name, timestamp, value){ + this.testTopicsMap.set(name, value); + this.onNewTopicData(name, timestamp, value); + } + + subscribe(topicPattern){ + this.subscriptions.add(topicPattern); + } + + unSubscribe(topicPattern){ + this.subscriptions.delete(topicPattern); + } + + clearAllSubscriptions(){ + this.subscriptions.clear(); + } + + getMostRecentValue(name){ + if(this.testTopicsMap.has(name)){ + return this.testTopicsMap.get(name); + } else { + return null; + } + } + + //Gets a timestamp in the NT4 time scaling & domain + // I have no idea ift his will be useful going forward but.. + getServerTime_us(){ + return new Date().getTime()*1000000; + } + + + // TEST ONLY - this is a periodic loop which simulates + // a NT server with signals and data in it + testDataSourceLoop(){ + var curWallTime = window.performance.now()/1000.0; + var curTimeSec = this.loopCount * 0.020; //20ms robot code; + + + while(curTimeSec < curWallTime){ + //Calculate values for each signal + var testSlowSin1 = 50+50*Math.sin( curTimeSec * 2 * Math.PI * 0.1); + var testFastSin1 = 50+30*Math.sin( curTimeSec* 2 * Math.PI * 1.0); + var testFastSin2 = 20*Math.sin( (curTimeSec + 0.2 )* 2 * Math.PI * 1.0); + var testSquare1 = (Math.round(curTimeSec*1000) % 1000 > 500) ? 1.0 : 0.0; + var testSquare2 = (Math.round(curTimeSec*200) % 1000 > 500) ? 2.0 : 1.0; + var testAzmth = 180*Math.sin( curTimeSec * 2 * Math.PI * 0.1); + var testSpeed = Math.sin( curTimeSec * 2 * Math.PI * 0.2); + + this.testPublishNewTopicData("Signals/TestFastSin1/Value", curTimeSec, testFastSin1); + this.testPublishNewTopicData("Signals/TestFastSin2/Value", curTimeSec, testFastSin2); + this.testPublishNewTopicData("Signals/TestSlowSin/Value", curTimeSec, testSlowSin1); + this.testPublishNewTopicData("Signals/TestSquare/Value", curTimeSec, testSquare1); + this.testPublishNewTopicData("Signals/AnotherTestSquare/Value", curTimeSec, testSquare2); + this.testPublishNewTopicData("testText", curTimeSec, testSlowSin1.toPrecision(3).toString() + " PSI"); + + this.testPublishNewTopicData("modFL_azmthDes", curTimeSec, testAzmth*-1.0); + this.testPublishNewTopicData("modFL_azmthAct", curTimeSec, testAzmth); + this.testPublishNewTopicData("modFL_speedDes", curTimeSec, testSpeed*-1.0); + this.testPublishNewTopicData("modFL_speedAct", curTimeSec, testSpeed); + this.testPublishNewTopicData("modFR_azmthDes", curTimeSec, testAzmth); + this.testPublishNewTopicData("modFR_azmthAct", curTimeSec, testAzmth); + this.testPublishNewTopicData("modFR_speedDes", curTimeSec, testSpeed); + this.testPublishNewTopicData("modFR_speedAct", curTimeSec, testSpeed); + this.testPublishNewTopicData("modBL_azmthDes", curTimeSec, testAzmth*-0.2); + this.testPublishNewTopicData("modBL_azmthAct", curTimeSec, testAzmth); + this.testPublishNewTopicData("modBL_speedDes", curTimeSec, testSpeed); + this.testPublishNewTopicData("modBL_speedAct", curTimeSec, testSpeed); + this.testPublishNewTopicData("modBR_azmthDes", curTimeSec, testAzmth*0.8); + this.testPublishNewTopicData("modBR_azmthAct", curTimeSec, testAzmth); + this.testPublishNewTopicData("modBR_speedDes", curTimeSec, testSpeed); + this.testPublishNewTopicData("modBR_speedAct", curTimeSec, testSpeed); + + this.loopCount++; + curTimeSec = this.loopCount * 0.020; + } + + this.testPublishNewTopicData("Autonomous/curVal", curTimeSec, this.testTopicsMap.get("Autonomous/desVal")); + this.testPublishNewTopicData("Autonomous/curValDelay", curTimeSec, this.testTopicsMap.get("Autonomous/desValDelay")); + + + } + + testPublishNewTopicData(name, timestamp, value){ + this.testTopicsMap.set(name, value); //Update "most-recent" value + + //If subscribed, broadcast the data with timestamp + this.subscriptions.forEach(subPattern => { + if(name.includes(subPattern)){ + this.onNewTopicData(name, timestamp, value); + } + }) + } + + testAnnounceSignals(){ + this.testTopicsMap.forEach((value,name) => { + this.onTopicAnnounce(name); + }) + } + + testConnect(){ + + this.testTopicsMap = new Map(); + this.testTopicsMap.set("Signals/TestFastSin1/Value", 0); + this.testTopicsMap.set("Signals/TestFastSin1/Units", "RPM"); + this.testTopicsMap.set("Signals/TestFastSin2/Value", 0); + this.testTopicsMap.set("Signals/TestFastSin2/Units", "V"); + this.testTopicsMap.set("Signals/TestSlowSin/Value", 0); + this.testTopicsMap.set("Signals/TestSlowSin/Units", ""); + this.testTopicsMap.set("Signals/TestSquare/Value", 0); + this.testTopicsMap.set("Signals/TestSquare/Units", "A"); + this.testTopicsMap.set("Signals/AnotherTestSquare/Value", 0); + this.testTopicsMap.set("Signals/AnotherTestSquare/Units", "A"); + this.testTopicsMap.set("Calibrations/ShooterSetpoint/Value", 1000); + this.testTopicsMap.set("Calibrations/ShooterSetpoint/Units", "RPM"); + this.testTopicsMap.set("Calibrations/ShooterSetpoint/Min", 500); + this.testTopicsMap.set("Calibrations/ShooterSetpoint/Max", 2500); + this.testTopicsMap.set("Calibrations/ShooterSetpoint/Default", 1000); + this.testTopicsMap.set("testText", ""); + this.testTopicsMap.set("Autonomous/curVal", 0); + this.testTopicsMap.set("Autonomous/desVal", 0); + this.testTopicsMap.set("Autonomous/curValDelay", 0); + this.testTopicsMap.set("Autonomous/desValDelay", 0); + this.testTopicsMap.set("modFL_azmthDes",0); + this.testTopicsMap.set("modFL_azmthAct",0); + this.testTopicsMap.set("modFL_speedDes",0); + this.testTopicsMap.set("modFL_speedAct",0); + this.testTopicsMap.set("modFR_azmthDes",0); + this.testTopicsMap.set("modFR_azmthAct",0); + this.testTopicsMap.set("modFR_speedDes",0); + this.testTopicsMap.set("modFR_speedAct",0); + this.testTopicsMap.set("modBL_azmthDes",0); + this.testTopicsMap.set("modBL_azmthAct",0); + this.testTopicsMap.set("modBL_speedDes",0); + this.testTopicsMap.set("modBL_speedAct",0); + this.testTopicsMap.set("modBR_azmthDes",0); + this.testTopicsMap.set("modBR_azmthAct",0); + this.testTopicsMap.set("modBR_speedDes",0); + this.testTopicsMap.set("modBR_speedAct",0); + + setInterval(this.testDataSourceLoop.bind(this), 75); + + this.onConnect(); + } + + + +} diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/msgpack/msgpack.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/msgpack/msgpack.js new file mode 100644 index 0000000000..7f0266e580 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/msgpack/msgpack.js @@ -0,0 +1,564 @@ +(function () { + "use strict"; + + // Serializes a value to a MessagePack byte array. + // + // data: The value to serialize. This can be a scalar, array or object. + // options: An object that defined additional options. + // - multiple: Indicates whether multiple values in data are concatenated to multiple MessagePack arrays. + // - invalidTypeReplacement: The value that is used to replace values of unsupported types, or a function that returns such a value, given the original value as parameter. + function serialize(data, options) { + if (options && options.multiple && !Array.isArray(data)) { + throw new Error("Invalid argument type: Expected an Array to serialize multiple values."); + } + const pow32 = 0x100000000; // 2^32 + let floatBuffer, floatView; + let array = new Uint8Array(128); + let length = 0; + + var th = ""; + if(options && options.typeHint){ + th = options.typeHint; + } + + if (options && options.multiple) { + for (let i = 0; i < data.length; i++) { + append(data[i], false, th); + } + } + else { + append(data, false, th); + } + return array.subarray(0, length); + + function append(data, isReplacement, th) { + switch (typeof data) { + case "undefined": + appendNull(data); + break; + case "boolean": + appendBoolean(data); + break; + case "number": + appendNumber(data, th); + break; + case "string": + appendString(data); + break; + case "object": + if (data === null) + appendNull(data); + else if (data instanceof Date) + appendDate(data); + else if (Array.isArray(data)) + appendArray(data); + else if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) + appendBinArray(data); + else if (data instanceof Int8Array || data instanceof Int16Array || data instanceof Uint16Array || + data instanceof Int32Array || data instanceof Uint32Array || + data instanceof Float32Array || data instanceof Float64Array) + appendArray(data); + else + appendObject(data); + break; + default: + if (!isReplacement && options && options.invalidTypeReplacement) { + if (typeof options.invalidTypeReplacement === "function") + append(options.invalidTypeReplacement(data), true, th); + else + append(options.invalidTypeReplacement, true, th); + } + else { + throw new Error("Invalid argument type: The type '" + (typeof data) + "' cannot be serialized."); + } + } + } + + function appendNull(data) { + appendByte(0xc0); + } + + function appendBoolean(data) { + appendByte(data ? 0xc3 : 0xc2); + } + + function appendNumber(data, th) { + var isInteger = (th === "int") || + (isFinite(data) && Math.floor(data) === data && th !== "double" && th !== "float"); + if (isInteger) { + // Integer + if (data >= 0 && data <= 0x7f) { + appendByte(data); + } + else if (data < 0 && data >= -0x20) { + appendByte(data); + } + else if (data > 0 && data <= 0xff) { // uint8 + appendBytes([0xcc, data]); + } + else if (data >= -0x80 && data <= 0x7f) { // int8 + appendBytes([0xd0, data]); + } + else if (data > 0 && data <= 0xffff) { // uint16 + appendBytes([0xcd, data >>> 8, data]); + } + else if (data >= -0x8000 && data <= 0x7fff) { // int16 + appendBytes([0xd1, data >>> 8, data]); + } + else if (data > 0 && data <= 0xffffffff) { // uint32 + appendBytes([0xce, data >>> 24, data >>> 16, data >>> 8, data]); + } + else if (data >= -0x80000000 && data <= 0x7fffffff) { // int32 + appendBytes([0xd2, data >>> 24, data >>> 16, data >>> 8, data]); + } + else if (data > 0 && data <= 0xffffffffffffffff) { // uint64 + // Split 64 bit number into two 32 bit numbers because JavaScript only regards + // 32 bits for bitwise operations. + let hi = data / pow32; + let lo = data % pow32; + appendBytes([0xd3, hi >>> 24, hi >>> 16, hi >>> 8, hi, lo >>> 24, lo >>> 16, lo >>> 8, lo]); + } + else if (data >= -0x8000000000000000 && data <= 0x7fffffffffffffff) { // int64 + appendByte(0xd3); + appendInt64(data); + } + else if (data < 0) { // below int64 + appendBytes([0xd3, 0x80, 0, 0, 0, 0, 0, 0, 0]); + } + else { // above uint64 + appendBytes([0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]); + } + } + else { + // Float + if (!floatView) { + floatBuffer = new ArrayBuffer(8); + floatView = new DataView(floatBuffer); + } + floatView.setFloat64(0, data); + appendByte(0xcb); + appendBytes(new Uint8Array(floatBuffer)); + } + } + + function appendString(data) { + let bytes = encodeUtf8(data); + let length = bytes.length; + + if (length <= 0x1f) + appendByte(0xa0 + length); + else if (length <= 0xff) + appendBytes([0xd9, length]); + else if (length <= 0xffff) + appendBytes([0xda, length >>> 8, length]); + else + appendBytes([0xdb, length >>> 24, length >>> 16, length >>> 8, length]); + + appendBytes(bytes); + } + + function appendArray(data) { + let length = data.length; + + if (length <= 0xf) + appendByte(0x90 + length); + else if (length <= 0xffff) + appendBytes([0xdc, length >>> 8, length]); + else + appendBytes([0xdd, length >>> 24, length >>> 16, length >>> 8, length]); + + for (let index = 0; index < length; index++) { + append(data[index]); + } + } + + function appendBinArray(data) { + let length = data.length; + + if (length <= 0xf) + appendBytes([0xc4, length]); + else if (length <= 0xffff) + appendBytes([0xc5, length >>> 8, length]); + else + appendBytes([0xc6, length >>> 24, length >>> 16, length >>> 8, length]); + + appendBytes(data); + } + + function appendObject(data) { + let length = 0; + for (let key in data) { + if (data[key] !== undefined) { + length++; + } + } + + if (length <= 0xf) + appendByte(0x80 + length); + else if (length <= 0xffff) + appendBytes([0xde, length >>> 8, length]); + else + appendBytes([0xdf, length >>> 24, length >>> 16, length >>> 8, length]); + + for (let key in data) { + let value = data[key]; + if (value !== undefined) { + append(key); + append(value); + } + } + } + + function appendDate(data) { + let sec = data.getTime() / 1000; + if (data.getMilliseconds() === 0 && sec >= 0 && sec < 0x100000000) { // 32 bit seconds + appendBytes([0xd6, 0xff, sec >>> 24, sec >>> 16, sec >>> 8, sec]); + } + else if (sec >= 0 && sec < 0x400000000) { // 30 bit nanoseconds, 34 bit seconds + let ns = data.getMilliseconds() * 1000000; + appendBytes([0xd7, 0xff, ns >>> 22, ns >>> 14, ns >>> 6, ((ns << 2) >>> 0) | (sec / pow32), sec >>> 24, sec >>> 16, sec >>> 8, sec]); + } + else { // 32 bit nanoseconds, 64 bit seconds, negative values allowed + let ns = data.getMilliseconds() * 1000000; + appendBytes([0xc7, 12, 0xff, ns >>> 24, ns >>> 16, ns >>> 8, ns]); + appendInt64(sec); + } + } + + function appendByte(byte) { + if (array.length < length + 1) { + let newLength = array.length * 2; + while (newLength < length + 1) + newLength *= 2; + let newArray = new Uint8Array(newLength); + newArray.set(array); + array = newArray; + } + array[length] = byte; + length++; + } + + function appendBytes(bytes) { + if (array.length < length + bytes.length) { + let newLength = array.length * 2; + while (newLength < length + bytes.length) + newLength *= 2; + let newArray = new Uint8Array(newLength); + newArray.set(array); + array = newArray; + } + array.set(bytes, length); + length += bytes.length; + } + + function appendInt64(value) { + // Split 64 bit number into two 32 bit numbers because JavaScript only regards 32 bits for + // bitwise operations. + let hi, lo; + if (value >= 0) { + // Same as uint64 + hi = value / pow32; + lo = value % pow32; + } + else { + // Split absolute value to high and low, then NOT and ADD(1) to restore negativity + value++; + hi = Math.abs(value) / pow32; + lo = Math.abs(value) % pow32; + hi = ~hi; + lo = ~lo; + } + appendBytes([hi >>> 24, hi >>> 16, hi >>> 8, hi, lo >>> 24, lo >>> 16, lo >>> 8, lo]); + } + } + + // Deserializes a MessagePack byte array to a value. + // + // array: The MessagePack byte array to deserialize. This must be an Array or Uint8Array containing bytes, not a string. + // options: An object that defined additional options. + // - multiple: Indicates whether multiple concatenated MessagePack arrays are returned as an array. + function deserialize(array, options) { + const pow32 = 0x100000000; // 2^32 + let pos = 0; + if (array instanceof ArrayBuffer) { + array = new Uint8Array(array); + } + if (typeof array !== "object" || typeof array.length === "undefined") { + throw new Error("Invalid argument type: Expected a byte array (Array or Uint8Array) to deserialize."); + } + if (!array.length) { + throw new Error("Invalid argument: The byte array to deserialize is empty."); + } + if (!(array instanceof Uint8Array)) { + array = new Uint8Array(array); + } + let data; + if (options && options.multiple) { + // Read as many messages as are available + data = []; + while (pos < array.length) { + data.push(read()); + } + } + else { + // Read only one message and ignore additional data + data = read(); + } + return data; + + function read() { + const byte = array[pos++]; + if (byte >= 0x00 && byte <= 0x7f) return byte; // positive fixint + if (byte >= 0x80 && byte <= 0x8f) return readMap(byte - 0x80); // fixmap + if (byte >= 0x90 && byte <= 0x9f) return readArray(byte - 0x90); // fixarray + if (byte >= 0xa0 && byte <= 0xbf) return readStr(byte - 0xa0); // fixstr + if (byte === 0xc0) return null; // nil + if (byte === 0xc1) throw new Error("Invalid byte code 0xc1 found."); // never used + if (byte === 0xc2) return false; // false + if (byte === 0xc3) return true; // true + if (byte === 0xc4) return readBin(-1, 1); // bin 8 + if (byte === 0xc5) return readBin(-1, 2); // bin 16 + if (byte === 0xc6) return readBin(-1, 4); // bin 32 + if (byte === 0xc7) return readExt(-1, 1); // ext 8 + if (byte === 0xc8) return readExt(-1, 2); // ext 16 + if (byte === 0xc9) return readExt(-1, 4); // ext 32 + if (byte === 0xca) return readFloat(4); // float 32 + if (byte === 0xcb) return readFloat(8); // float 64 + if (byte === 0xcc) return readUInt(1); // uint 8 + if (byte === 0xcd) return readUInt(2); // uint 16 + if (byte === 0xce) return readUInt(4); // uint 32 + if (byte === 0xcf) return readUInt(8); // uint 64 + if (byte === 0xd0) return readInt(1); // int 8 + if (byte === 0xd1) return readInt(2); // int 16 + if (byte === 0xd2) return readInt(4); // int 32 + if (byte === 0xd3) return readInt(8); // int 64 + if (byte === 0xd4) return readExt(1); // fixext 1 + if (byte === 0xd5) return readExt(2); // fixext 2 + if (byte === 0xd6) return readExt(4); // fixext 4 + if (byte === 0xd7) return readExt(8); // fixext 8 + if (byte === 0xd8) return readExt(16); // fixext 16 + if (byte === 0xd9) return readStr(-1, 1); // str 8 + if (byte === 0xda) return readStr(-1, 2); // str 16 + if (byte === 0xdb) return readStr(-1, 4); // str 32 + if (byte === 0xdc) return readArray(-1, 2); // array 16 + if (byte === 0xdd) return readArray(-1, 4); // array 32 + if (byte === 0xde) return readMap(-1, 2); // map 16 + if (byte === 0xdf) return readMap(-1, 4); // map 32 + if (byte >= 0xe0 && byte <= 0xff) return byte - 256; // negative fixint + console.debug("msgpack array:", array); + throw new Error("Invalid byte value '" + byte + "' at index " + (pos - 1) + " in the MessagePack binary data (length " + array.length + "): Expecting a range of 0 to 255. This is not a byte array."); + } + + function readInt(size) { + let value = 0; + let first = true; + while (size-- > 0) { + if (first) { + let byte = array[pos++]; + value += byte & 0x7f; + if (byte & 0x80) { + value -= 0x80; // Treat most-significant bit as -2^i instead of 2^i + } + first = false; + } + else { + value *= 256; + value += array[pos++]; + } + } + return value; + } + + function readUInt(size) { + let value = 0; + while (size-- > 0) { + value *= 256; + value += array[pos++]; + } + return value; + } + + function readFloat(size) { + let view = new DataView(array.buffer, pos + array.byteOffset, size); + pos += size; + if (size === 4) + return view.getFloat32(0, false); + if (size === 8) + return view.getFloat64(0, false); + } + + function readBin(size, lengthSize) { + if (size < 0) size = readUInt(lengthSize); + let data = array.subarray(pos, pos + size); + pos += size; + return data; + } + + function readMap(size, lengthSize) { + if (size < 0) size = readUInt(lengthSize); + let data = {}; + while (size-- > 0) { + let key = read(); + data[key] = read(); + } + return data; + } + + function readArray(size, lengthSize) { + if (size < 0) size = readUInt(lengthSize); + let data = []; + while (size-- > 0) { + data.push(read()); + } + return data; + } + + function readStr(size, lengthSize) { + if (size < 0) size = readUInt(lengthSize); + let start = pos; + pos += size; + return decodeUtf8(array, start, size); + } + + function readExt(size, lengthSize) { + if (size < 0) size = readUInt(lengthSize); + let type = readUInt(1); + let data = readBin(size); + switch (type) { + case 255: + return readExtDate(data); + } + return { type: type, data: data }; + } + + function readExtDate(data) { + if (data.length === 4) { + let sec = ((data[0] << 24) >>> 0) + + ((data[1] << 16) >>> 0) + + ((data[2] << 8) >>> 0) + + data[3]; + return new Date(sec * 1000); + } + if (data.length === 8) { + let ns = ((data[0] << 22) >>> 0) + + ((data[1] << 14) >>> 0) + + ((data[2] << 6) >>> 0) + + (data[3] >>> 2); + let sec = ((data[3] & 0x3) * pow32) + + ((data[4] << 24) >>> 0) + + ((data[5] << 16) >>> 0) + + ((data[6] << 8) >>> 0) + + data[7]; + return new Date(sec * 1000 + ns / 1000000); + } + if (data.length === 12) { + let ns = ((data[0] << 24) >>> 0) + + ((data[1] << 16) >>> 0) + + ((data[2] << 8) >>> 0) + + data[3]; + pos -= 8; + let sec = readInt(8); + return new Date(sec * 1000 + ns / 1000000); + } + throw new Error("Invalid data length for a date value."); + } + } + + // Encodes a string to UTF-8 bytes. + function encodeUtf8(str) { + // Prevent excessive array allocation and slicing for all 7-bit characters + let ascii = true, length = str.length; + for (let x = 0; x < length; x++) { + if (str.charCodeAt(x) > 127) { + ascii = false; + break; + } + } + + // Based on: https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330 + let i = 0, bytes = new Uint8Array(str.length * (ascii ? 1 : 4)); + for (let ci = 0; ci !== length; ci++) { + let c = str.charCodeAt(ci); + if (c < 128) { + bytes[i++] = c; + continue; + } + if (c < 2048) { + bytes[i++] = c >> 6 | 192; + } + else { + if (c > 0xd7ff && c < 0xdc00) { + if (++ci >= length) + throw new Error("UTF-8 encode: incomplete surrogate pair"); + let c2 = str.charCodeAt(ci); + if (c2 < 0xdc00 || c2 > 0xdfff) + throw new Error("UTF-8 encode: second surrogate character 0x" + c2.toString(16) + " at index " + ci + " out of range"); + c = 0x10000 + ((c & 0x03ff) << 10) + (c2 & 0x03ff); + bytes[i++] = c >> 18 | 240; + bytes[i++] = c >> 12 & 63 | 128; + } + else bytes[i++] = c >> 12 | 224; + bytes[i++] = c >> 6 & 63 | 128; + } + bytes[i++] = c & 63 | 128; + } + return ascii ? bytes : bytes.subarray(0, i); + } + + // Decodes a string from UTF-8 bytes. + function decodeUtf8(bytes, start, length) { + // Based on: https://gist.github.com/pascaldekloe/62546103a1576803dade9269ccf76330 + let i = start, str = ""; + length += start; + while (i < length) { + let c = bytes[i++]; + if (c > 127) { + if (c > 191 && c < 224) { + if (i >= length) + throw new Error("UTF-8 decode: incomplete 2-byte sequence"); + c = (c & 31) << 6 | bytes[i++] & 63; + } + else if (c > 223 && c < 240) { + if (i + 1 >= length) + throw new Error("UTF-8 decode: incomplete 3-byte sequence"); + c = (c & 15) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63; + } + else if (c > 239 && c < 248) { + if (i + 2 >= length) + throw new Error("UTF-8 decode: incomplete 4-byte sequence"); + c = (c & 7) << 18 | (bytes[i++] & 63) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63; + } + else throw new Error("UTF-8 decode: unknown multibyte start 0x" + c.toString(16) + " at index " + (i - 1)); + } + if (c <= 0xffff) str += String.fromCharCode(c); + else if (c <= 0x10ffff) { + c -= 0x10000; + str += String.fromCharCode(c >> 10 | 0xd800) + str += String.fromCharCode(c & 0x3FF | 0xdc00) + } + else throw new Error("UTF-8 decode: code point 0x" + c.toString(16) + " exceeds UTF-16 reach"); + } + return str; + } + + // The exported functions + let msgpack = { + serialize: serialize, + deserialize: deserialize, + + // Compatibility with other libraries + encode: serialize, + decode: deserialize + }; + + // Environment detection + if (typeof module === "object" && module && typeof module.exports === "object") { + // Node.js + module.exports = msgpack; + } + else { + // Global object + window[window.msgpackJsName || "msgpack"] = msgpack; + } + +})(); diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/nt4.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/nt4.js new file mode 100644 index 0000000000..1dc5edc402 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/nt4.js @@ -0,0 +1,547 @@ +import "./msgpack/msgpack.js"; + +var typestrIdxLookup = { + NT4_TYPESTR: 0, + "double": 1, + "int": 2, + "float": 3, + "string": 4, + "json": 4, + "raw": 5, + "rpc": 5, + "msgpack": 5, + "protobuf": 5, + "boolean[]": 16, + "double[]": 17, + "int[]": 18, + "float[]": 19, + "string[]": 20 +} + +class NT4_TYPESTR { + static BOOL = "boolean"; + static FLOAT_64 = "double"; + static INT = "int"; + static FLOAT_32 = "float"; + static STR = "string"; + static JSON = "json"; + static BIN_RAW = "raw"; + static BIN_RPC = "rpc"; + static BIN_MSGPACK = "msgpack"; + static BIN_PROTOBUF = "protobuf"; + static BOOL_ARR = "boolean[]"; + static FLOAT_64_ARR = "double[]"; + static INT_ARR = "int[]"; + static FLOAT_32_ARR = "float[]"; + static STR_ARR = "string[]"; +} + +export class NT4_ValReq { + topics = new Set(); + + toGetValsObj() { + return { + "topics": Array.from(this.topics), + }; + } +} + +export class NT4_Subscription { + topics = new Set(); + options = new NT4_SubscriptionOptions(); + uid = -1; + + toSubscribeObj() { + return { + "topics": Array.from(this.topics), + "options": this.options.toObj(), + "subuid": this.uid, + }; + } + + toUnSubscribeObj() { + return { + "subuid": this.uid, + }; + } +} + +export class NT4_SubscriptionOptions { + periodicRate_s = 0.1; + all = false; + topicsonly = false; + prefix = true; //nonstandard default + + toObj() { + return { + "periodic": this.periodicRate_s, + "all": this.all, + "topicsonly": this.topicsonly, + "prefix": this.prefix, + }; + } +} + +export class NT4_Topic { + name = ""; + type = ""; + id = 0; + pubuid = 0; + properties = {}; //Properties are free-form, might have anything in them + + toPublishObj() { + return { + "name": this.name, + "type": this.type, + "pubuid": this.pubuid, + } + } + + toUnPublishObj() { + return { + "name": this.name, + "pubuid": this.pubuid, + } + } + + toPropertiesObj() { + return { + "name": this.name, + "update": this.properties, + } + } + + getTypeIdx() { + return typestrIdxLookup[this.type]; + } +} + +export class NT4_Client { + + + constructor(serverAddr, + onTopicAnnounce_in, //Gets called when server announces enough topics to form a new signal + onTopicUnAnnounce_in, //Gets called when server unannounces any part of a signal + onNewTopicData_in, //Gets called when any new data is available + onConnect_in, //Gets called once client completes initial handshake with server + onDisconnect_in) { //Gets called once client detects server has disconnected + + this.onTopicAnnounce = onTopicAnnounce_in; + this.onTopicUnAnnounce = onTopicUnAnnounce_in; + this.onNewTopicData = onNewTopicData_in; + this.onConnect = onConnect_in; + this.onDisconnect = onDisconnect_in; + + this.subscriptions = new Map(); + this.subscription_uid_counter = 0; + this.publish_uid_counter = 0; + + this.clientPublishedTopics = new Map(); + this.announcedTopics = new Map(); + + this.timeSyncBgEvent = setInterval(this.ws_sendTimestamp.bind(this), 5000); + + // WS Connection State (with defaults) + this.serverBaseAddr = serverAddr; + this.clientIdx = 0; + this.serverAddr = ""; + this.serverConnectionActive = false; + this.serverTimeOffset_us = 0; + + + } + + ////////////////////////////////////////////////////////////// + // PUBLIC API + + // Add a new subscription which requests announcment of topics + subscribeTopicNames(topicPatterns) { + var newSub = new NT4_Subscription(); + newSub.uid = this.getNewSubUID(); + newSub.options.topicsonly = true; + newSub.options.periodicRate_s = 1.0; + newSub.topics = new Set(topicPatterns); + + this.subscriptions.set(newSub.uid, newSub); + if (this.serverConnectionActive) { + this.ws_subscribe(newSub); + } + return newSub; + } + + // Add a new subscription. Returns a subscription object + subscribePeriodic(topicPatterns, period) { + var newSub = new NT4_Subscription(); + newSub.uid = this.getNewSubUID(); + newSub.options.periodicRate_s = period; + newSub.topics = new Set(topicPatterns); + + this.subscriptions.set(newSub.uid, newSub); + if (this.serverConnectionActive) { + this.ws_subscribe(newSub); + } + return newSub; + } + + // Add a new subscription. Returns a subscription object + subscribeAllSamples(topicPatterns) { + var newSub = new NT4_Subscription(); + newSub.uid = this.getNewSubUID(); + newSub.topics = new Set(topicPatterns); + newSub.options.all = true; + + this.subscriptions.set(newSub.uid, newSub); + if (this.serverConnectionActive) { + this.ws_subscribe(newSub); + } + return newSub; + } + + // Given an existing subscription, unsubscribe from it. + unSubscribe(sub) { + this.subscriptions.delete(sub.uid); + if (this.serverConnectionActive) { + this.ws_unsubscribe(sub); + } + } + + // Unsubscribe from all current subscriptions + clearAllSubscriptions() { + for (const sub of this.subscriptions.values()) { + this.unSubscribe(sub); + } + } + + // Set the properties of a particular topic + setProperties(topic, isPersistent, isRetained) { + topic.properties.persistent = isPersistent; + topic.properties.retained = isRetained; + if (this.serverConnectionActive) { + this.ws_setproperties(topic); + } + } + + // Publish a new topic from this client with the provided name and type + publishNewTopic(name, type) { + var newTopic = new NT4_Topic(); + newTopic.name = name; + newTopic.type = type; + this.publishTopic(newTopic); + return newTopic; + } + + // Publish an existing topic to the server + publishTopic(topic) { + topic.pubuid = this.getNewPubUID(); + this.clientPublishedTopics.set(topic.name, topic); + if (this.serverConnectionActive) { + this.ws_publish(topic); + } + } + + // UnPublish a previously-published topic from this client. + unPublishTopic(oldTopic) { + this.clientPublishedTopics.delete(oldTopic.name); + if (this.serverConnectionActive) { + this.ws_unpublish(oldTopic); + } + } + + // Send some new value to the server + // Timestamp is whatever the current time is. + addSample(topic, value) { + var timestamp = this.getServerTime_us(); + this.addSample(topic, timestamp, value); + } + + // Send some new timestamped value to the server + addSample(topic, timestamp, value) { + + if (typeof topic === 'string') { + var topicFound = false; + //Slow-lookup - strings are assumed to be topic names for things the server has already announced. + for (const topicIter of this.announcedTopics.values()) { + if (topicIter.name === topic) { + topic = topicIter; + topicFound = true; + break; + } + } + if (!topicFound) { + throw "Topic " + topic + " not found in announced server topics!"; + } + } + + var sourceData = [topic.pubuid, timestamp, topic.getTypeIdx(), value]; + var txData = msgpack.serialize(sourceData); + + this.ws_sendBinary(txData); + } + + ////////////////////////////////////////////////////////////// + // Server/Client Time Sync Handling + + getClientTime_us() { + return Math.round(performance.now() * 1000.0); + } + + getServerTime_us() { + return this.getClientTime_us() + this.serverTimeOffset_us; + } + + ws_sendTimestamp() { + var timeTopic = this.announcedTopics.get(-1); + if (timeTopic) { + var timeToSend = this.getClientTime_us(); + this.addSample(timeTopic, 0, timeToSend); + } + } + + ws_handleReceiveTimestamp(serverTimestamp, clientTimestamp) { + var rxTime = this.getClientTime_us(); + + //Recalculate server/client offset based on round trip time + var rtt = rxTime - clientTimestamp; + var serverTimeAtRx = serverTimestamp - rtt / 2.0; + this.serverTimeOffset_us = serverTimeAtRx - rxTime; + + } + + ////////////////////////////////////////////////////////////// + // Websocket Message Send Handlers + + ws_subscribe(sub) { + this.ws_sendJSON("subscribe", sub.toSubscribeObj()); + } + + ws_unsubscribe(sub) { + this.ws_sendJSON("unsubscribe", sub.toUnSubscribeObj()); + } + + ws_publish(topic) { + this.ws_sendJSON("publish", topic.toPublishObj()); + } + + ws_unpublish(topic) { + this.ws_sendJSON("unpublish", topic.toUnPublishObj()); + } + + ws_setproperties(topic) { + this.ws_sendJSON("setproperties", topic.toPropertiesObj()); + } + + ws_sendJSON(method, params) { //Sends a single json message + if (this.ws.readyState === WebSocket.OPEN) { + var txObj = [{ + "method": method, + "params": params + }]; + var txJSON = JSON.stringify(txObj); + + //console.log("[NT4] Client Says: " + txJSON); + + this.ws.send(txJSON); + } + } + + ws_sendBinary(data) { + if (this.ws.readyState === WebSocket.OPEN) { + this.ws.send(data); + } + } + + ////////////////////////////////////////////////////////////// + // Websocket connection Maintenance + + ws_onOpen() { + + // Add default time topic + var timeTopic = new NT4_Topic(); + timeTopic.name = "Time"; + timeTopic.id = -1; + timeTopic.pubuid = -1; + timeTopic.type = NT4_TYPESTR.INT; + this.announcedTopics.set(timeTopic.id, timeTopic); + + // Set the flag allowing general server communication + this.serverConnectionActive = true; + + //Publish any existing topics + for (const topic of this.clientPublishedTopics.values()) { + this.ws_publish(topic); + this.ws_setproperties(topic); + } + + //Subscribe to existing subscriptions + for (const sub of this.subscriptions.values()) { + this.ws_subscribe(sub); + } + + // User connection-opened hook + this.onConnect(); + } + + ws_onClose(e) { + //Clear flags to stop server communication + this.ws = null; + this.serverConnectionActive = false; + + // User connection-closed hook + this.onDisconnect(); + + //Clear out any local cache of server state + this.announcedTopics.clear(); + + console.log('[NT4] Socket is closed. Reconnect will be attempted in 0.5 second.', e.reason); + setTimeout(this.ws_connect.bind(this), 500); + + if (!e.wasClean) { + console.error('Socket encountered error!'); + } + + } + + ws_onError(e) { + console.log("[NT4] Websocket error - " + e.toString()); + this.ws.close(); + } + + ws_onMessage(e) { + if (typeof e.data === 'string') { + //console.log("[NT4] Server Says: " + e.data); + //JSON Message + var rxArray = JSON.parse(e.data); + + rxArray.forEach(function (msg) { + + //Validate proper format of message + if (typeof msg !== 'object') { + console.log("[NT4] Ignoring text message, JSON parsing did not produce an object."); + return; + } + + if (!("method" in msg) || !("params" in msg)) { + console.log("[NT4] Ignoring text message, JSON parsing did not find all required fields."); + return; + } + + var method = msg["method"]; + var params = msg["params"]; + + if (typeof method !== 'string') { + console.log("[NT4] Ignoring text message, JSON parsing found \"method\", but it wasn't a string."); + return; + } + + if (typeof params !== 'object') { + console.log("[NT4] Ignoring text message, JSON parsing found \"params\", but it wasn't an object."); + return; + } + + // Message validates reasonably, switch based on supported methods + if (method === "announce") { + + //Check to see if we already knew about this topic. If not, make a new object. + + var newTopic = null; + for (const topic of this.clientPublishedTopics.values()) { + if (params.name === topic.name) { + newTopic = topic; //Existing topic, use it. + } + } + + // Did not know about the topic. Make a new one. + if(newTopic === null){ + newTopic = new NT4_Topic(); + } + + newTopic.name = params.name; + newTopic.id = params.id; + + //Strategy - if server sends a pubid use it + // otherwise, preserve whatever we had? + //TODO - ask peter about this. It smells wrong. + if (params.pubid != null) { + newTopic.pubuid = params.pubuid; + } + + newTopic.type = params.type; + newTopic.properties = params.properties; + this.announcedTopics.set(newTopic.id, newTopic); + this.onTopicAnnounce(newTopic); + } else if (method === "unannounce") { + var removedTopic = this.announcedTopics.get(params.id); + if (!removedTopic) { + console.log("[NT4] Ignorining unannounce, topic was not previously announced."); + return; + } + this.announcedTopics.delete(removedTopic.id); + this.onTopicUnAnnounce(removedTopic); + + } else if (method === "properties") { + //TODO support property changes + } else { + console.log("[NT4] Ignoring text message - unknown method " + method); + return; + } + }, this); + + } else { + //MSGPack + var rxArray = msgpack.deserialize(e.data, { multiple: true }); + + rxArray.forEach(function (unpackedData) { //For every value update... + var topicID = unpackedData[0]; + var timestamp_us = unpackedData[1]; + var typeIdx = unpackedData[2]; + var value = unpackedData[3]; + + if (topicID >= 0) { + var topic = this.announcedTopics.get(topicID); + this.onNewTopicData(topic, timestamp_us, value); + } else if (topicID === -1) { + this.ws_handleReceiveTimestamp(timestamp_us, value); + } else { + console.log("[NT4] Ignoring binary data - invalid topic id " + topicID.toString()); + } + }, this); + + } + } + + ws_connect() { + + this.clientIdx = Math.floor(Math.random() * 99999999); //Not great, but using it for now + + var port = 5810; //fallback - unsecured + var prefix = "ws://"; + + this.serverAddr = prefix + this.serverBaseAddr + ":" + port.toString() + "/nt/" + "JSClient_" + this.clientIdx.toString(); + + this.ws = new WebSocket(this.serverAddr, "v4.1.networktables.first.wpi.edu"); + this.ws.binaryType = "arraybuffer"; + this.ws.onopen = this.ws_onOpen.bind(this); + this.ws.onmessage = this.ws_onMessage.bind(this); + this.ws.onclose = this.ws_onClose.bind(this); + this.ws.onerror = this.ws_onError.bind(this); + + console.log("[NT4] Connected with idx " + this.clientIdx.toString()); + } + + + + ////////////////////////////////////////////////////////////// + // General utilties + + getNewSubUID() { + this.subscription_uid_counter++; + return this.subscription_uid_counter + this.clientIdx; + } + + getNewPubUID() { + this.publish_uid_counter++; + return this.publish_uid_counter + this.clientIdx; + } + + +} diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/signalDAQ_NT4.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/signalDAQ_NT4.js new file mode 100644 index 0000000000..d9cb6e7ba6 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/interfaces/signalDAQ_NT4.js @@ -0,0 +1,120 @@ +///////////////////////////////////////////////////////////////////////// +// SignalDAQ - wrapper around NT4 to specifically extract signal information +// and allow clients to request one or more signals +// +// Mirroring (I assume) NT4 architecture, it's heavily callback driven +///////////////////////////////////////////////////////////////////////// + +import { NT4_Client } from "./nt4.js"; + +export class SignalDAQNT4 { + + + constructor(onSignalAnnounce_in, //Gets called when server announces enough topics to form a new signal + onSignalUnAnnounce_in, //Gets called when server unannounces any part of a signal + onNewSampleData_in, //Gets called when any new data is available + onConnect_in, //Gets called once client completes initial handshake with server + onDisconnect_in, //Gets called once client detects server has disconnected + statusTextCallback_in) { + this.onSignalAnnounce = onSignalAnnounce_in; + this.onSignalUnAnnounce = onSignalUnAnnounce_in; + this.onNewSampleData = onNewSampleData_in; + this.onConnect = onConnect_in; + this.onDisconnect = onDisconnect_in; + this.statusTextCallback = statusTextCallback_in; + + this.daqSignalList = new Set(); //start assuming no signals. + + this.daqRunning = false; + + this.rxCount = 0; + + this.timeOffset = 0; + + this.nt4Client = new NT4_Client(window.location.hostname, + this.topicAnnounceHandler.bind(this), + this.topicUnannounceHandler.bind(this), + this.valueUpdateHandler.bind(this), + this.localOnConnect.bind(this), + this.onDisconnect.bind(this) + ); + + this.statusTextCallback("Starting connection..."); + this.nt4Client.ws_connect(); + this.statusTextCallback("NT4 Connected."); + } + + localOnConnect() { + this.nt4Client.subscribeTopicNames(["/SmartDashboard"]); + this.onConnect(); + } + + topicAnnounceHandler( newTopic ) { + //If a signal units topic is announced, request what those units value actually is. + var sigName = newTopic.name; + var sigUnits = ""; + if(newTopic.properties.units){ + sigUnits = newTopic.properties.units; + } + this.onSignalAnnounce(sigName, sigUnits); //Announce signal when we know the value of its units + } + + topicUnannounceHandler( removedTopic ) { + this.onSignalUnAnnounce(removedTopic.name); + } + + valueUpdateHandler(topic, timestamp, value){ + // Got a new sample + var sigName = topic.name; + this.onNewSampleData(sigName, timestamp - this.timeOffset, value); + if(this.daqRunning){ + this.rxCount++; + } + this.updateStatusText(); + } + + //Request a signal get added to the DAQ + addSignal(signalNameIn){ + this.daqSignalList.add(signalNameIn); + } + + //Call to remove a signal from the DAQ + removeSignal(signalNameIn){ + this.daqSignalList.delete(signalNameIn); + } + + clearSignalList(){ + this.daqSignalList.clear(); + } + + //Request RIO start sending periodic updates with data values + startDAQ(){ + this.daqRunning = true; + this.daqSignalList.forEach(sigName => { + this.nt4Client.subscribeAllSamples([sigName]); + }); + this.rxCount = 0; + this.timeOffset = this.nt4Client.getServerTime_us(); + this.updateStatusText(); + } + + //Request RIO stop sending periodic updates + stopDAQ(){ + this.nt4Client.clearAllSubscriptions(); + this.daqRunning = false; + this.updateStatusText(); + } + + updateStatusText(){ + var text = ""; + if(this.daqRunning){ + text += "DAQ Running"; + } else { + text += "DAQ Stopped"; + } + text += " RX Count: " + this.rxCount.toString(); + this.statusTextCallback(text); + } + + +} \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.css b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.css new file mode 100644 index 0000000000..aa2b5c0a2e --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.css @@ -0,0 +1,99 @@ +/* Color variables for PhotonVision */ +:root { + --pv-primary: #006492; + --pv-accent: #FFD843; + --pv-accent2: #FFFFFF; + --pv-bg: oklch(27.4% .006 286.033); +} + +body { + background: var(--pv-bg); + padding: 0.25em; + margin: 0; + font-size: 16px; + font-family: "Lato", Verdana, sans-serif; + color: var(--pv-accent2); +} + +html, body { + height: 99vh; +} + + +.outlined { + border: 2px solid var(--pv-accent); + border-radius: 10px; + margin: 1px; +} + +.tile-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 16px; + padding: 16px; +} + +.tile { + width: 300px; + height: 200px; + background: var(--pv-primary); + border: 2px solid var(--pv-accent); + border-radius: 10px; + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0 2px 8px rgba(0,0,0,0.25); +} + +.tile-content { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; +} + +.cam-name { + font-weight: bold; + background: var(--pv-primary); + color: var(--pv-accent2); + padding: 6px 8px; + text-align: center; + border-bottom: 2px solid var(--pv-primary); + font-size: 1.1em; + z-index: 1; + letter-spacing: 0.03em; +} + +.tile img { + flex: 1 1 auto; + object-fit: contain; + background: var(--pv-bg); + width: 100%; + height: 100%; + border-bottom-left-radius: 10px; + border-bottom-right-radius: 10px; +} + +img:fullscreen { + width: 100vw; + height: 100vh; + object-fit: contain; + background: var(--pv-bg); + display: block; +} + +hr { + border: none; + border-top: 2px solid var(--pv-accent); + margin: 16px 0; +} + +::-webkit-scrollbar { + width: 10px; + background: var(--pv-bg); +} +::-webkit-scrollbar-thumb { + background: var(--pv-primary); + border-radius: 5px; +} \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.html b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.html new file mode 100644 index 0000000000..d270170462 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.html @@ -0,0 +1,26 @@ + + + + + + + + PhotonVision System + + + + + +
+ +
+ +
+
Not yet connected...
+
+ + + + + + \ No newline at end of file diff --git a/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.js b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.js new file mode 100644 index 0000000000..b445870350 --- /dev/null +++ b/systemcore-apps/system-view/overlay/usr/local/bin/pv-system-viewer/www/systemViewer.js @@ -0,0 +1,169 @@ +import { NT4_Client } from "/interfaces/nt4.js"; + +var nt4Client = new NT4_Client(window.location.hostname, + topicAnnounceHandler, + topicUnannounceHandler, + valueUpdateHandler, + onConnect, + onDisconnect + ); + + +console.log("Starting connection..."); +nt4Client.ws_connect(); +console.log("Connection Triggered"); + +var subscription = null; + +function topicAnnounceHandler( newTopic ) { + + // If topic is a photonvision camera stream, show it in a card. + console.log("New topic announced: " + newTopic.name); + + if(isCamStreamTopic(newTopic.name)) { + console.log("Camera stream topic detected: " + newTopic.name); + + // Create or update the tile with the MJPEG stream URL + createOrUpdateTile(topicToCamName(newTopic.name), newTopic.value); + } +} + +function topicUnannounceHandler( removedTopic ) { + if(isCamStreamTopic(removedTopic.name)) { + removeTile(topicToCamName(removedTopic.name)); + } +} + +function valueUpdateHandler(topic, timestamp_us, value) { + // If topic is a photonvision camera stream, update the card with the new value. + if(isCamStreamTopic(topic.name)) { + console.log("Value update for topic: " + topic.name); + console.log("Value: ", value); + // Create or update the tile with the MJPEG stream URL + createOrUpdateTile(topicToCamName(topic.name), value); + } +} + +function topicToCamName(topicName) { + // Extract the camera name from the topic name + // Strips prefix and suffix, and replaces _ with spaces + // For example for the topic /CameraPublisher/photonvision_Port_1181_Input_MJPEG_Server/streams + // The name shall be "Port 1181 Input" + return topicName.split("/")[2].replace("photonvision_", "").replace("_MJPEG_Server", "").replace(/_/g, " "); +} + +function isCamStreamTopic(topicName) { + // Check if the topic is a photonvision camera stream + return topicName.startsWith("/CameraPublisher/") && topicName.endsWith("/streams"); +} + +function onConnect() { + + document.getElementById("status").innerHTML = "Connected to Server"; + removeAllTiles(); + subscribeToCamerServer(); +} + +function onDisconnect() { + document.getElementById("status").innerHTML = "Disconnected from Server"; + subscription = null; +} + + +function subscribeToCamerServer() { + if(subscription == null){ + subscription = nt4Client.subscribePeriodic(["/CameraPublisher/"], 0.5); + } +} + +function createOrUpdateTile(camName, mjpegUrlList) { + let tileId = camName + "-tile"; + + const grid = document.getElementById('tileGrid'); + let tile = document.getElementById(tileId); + + if (!tile) { + tile = document.createElement('div'); + tile.className = 'tile'; + tile.id = tileId; + grid.appendChild(tile); + } + + // Clear previous content + tile.innerHTML = ''; + + // Create a container for the cam name and image + const content = document.createElement('div'); + content.className = 'tile-content'; + + // Camera name element + const camNameElement = document.createElement('div'); + camNameElement.className = 'cam-name'; + camNameElement.textContent = camName; + + // Filter and clean up the MJPEG URLs + let urls = (Array.isArray(mjpegUrlList) ? mjpegUrlList : []) + .filter(entry => typeof entry === "string" && entry.startsWith("mjpg:")) + .map(entry => entry.replace("mjpg:", "")); + + // Prefer IPv4 addresses over DNS/mDNS + const ipv4Regex = /https?:\/\/(\d{1,3}\.){3}\d{1,3}/; + urls = urls.sort((a, b) => { + const aIsIp = ipv4Regex.test(a); + const bIsIp = ipv4Regex.test(b); + return (aIsIp === bIsIp) ? 0 : aIsIp ? -1 : 1; + }); + + if (urls.length === 0) { + tile.textContent = camName + ": No valid MJPEG stream found."; + return; + } + + // Create the img element + const img = document.createElement('img'); + img.style.width = '100%'; + img.style.height = '100%'; + img.alt = 'Stream'; + + let currentIdx = 0; + img.src = urls[currentIdx]; + + img.onerror = function () { + currentIdx++; + if (currentIdx < urls.length) { + img.src = urls[currentIdx]; + } else { + tile.textContent = camName + ": All MJPEG streams failed to load."; + } + }; + + img.onclick = function () { + if (img.requestFullscreen) { + img.requestFullscreen(); + } else if (img.webkitRequestFullscreen) { // Safari + img.webkitRequestFullscreen(); + } else if (img.msRequestFullscreen) { // IE11 + img.msRequestFullscreen(); + } +}; + + content.appendChild(camNameElement); + content.appendChild(img); + tile.appendChild(content); +} + + +function removeTile(camName) { + let tileId = camName + "-tile"; + const tile = document.getElementById(tileId); + if (tile) { + tile.remove(); + } +} + +function removeAllTiles() { + const grid = document.getElementById('tileGrid'); + while (grid.firstChild) { + grid.removeChild(grid.firstChild); + } +} \ No newline at end of file From 6b394cc7b255d27379d19fa7633dae599d9cc69b Mon Sep 17 00:00:00 2001 From: samfreund Date: Fri, 4 Jul 2025 13:06:22 -0500 Subject: [PATCH 7/9] use dark version for logos update favicon to round icon --- .../overlay/usr/share/pv-system-viewer.png | Bin 112848 -> 34792 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/systemcore-apps/system-view/overlay/usr/share/pv-system-viewer.png b/systemcore-apps/system-view/overlay/usr/share/pv-system-viewer.png index 5646beaa0e36467ce5ea2def3866e606e4bdfdf9..b46064ca8196d044d4758c7e588becf3b74cc6dc 100644 GIT binary patch literal 34792 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

)94)`stFsfk?(w`dM;P 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 literal 112848 zcmeFaby!?YvoE>^w*&}IaCc^KcXtax0}SpC2^t_kaMuvr-8F%P5G=SPI0ScsJKP~} zzHje+&c4r)=idJ^Jg`=G*Q&1mbyatD_39x^O-1$*8ZjCG0FUJ5q%;5kVIKhCPEe3w zIc;k%-C!4xtA?xuP&q`h1xp}UiYto)Kurw#jR_(wjp`()>k0r*V1!THKnoV+FJTXa zT5IXJ=_o4+m^#|CnV303&DmbsJHe;{KuGkZlZmOVxf=!4+|t@XnEs%xgPy|LOql*T zw=!7SNz&ZPTF%SGT+>TM%hb!(l;4bAROAtw&`SXr2YYij6N;Dib`GurFNLXoGZui| zKV-90i3quvSqNxI$^4;!rG%-h+}xZ5*x5ZjJ=r`t*&JOg*&+P={On*3b`B0!7zL~A zD+f1|m#hx1)PERAnY)_0SUb5{J33H2Ff@TWy1NNexw~7N30Rm|a6`?^xLKhloMx;L zh?xnii5Vw^)r^zVjF%h2$6*11QvIpk&D!EW>UVJc0|N{Y_J zm=q6Hia>;Zm;aYMA@&DB{*z!L|Kz~h3cLF^G7m8Q8(nh;7^I#s>{t?0(E*SkovDe0 z&coHl-5v_-2Qt{z%#_2)1i%KcUIRcW!1vA>{&xld@Z$WTlKqFu{=ZVWyEq6uPzvyx zbD8jP@^Z8Cm~etwxh%}gS)u%9s^0w14>Ys_cE{S}bxUKxd>Okg$h|P4@XjIrroyv`=lZlz!L!JM8KEDX z1tTkF4G!}ct;|dX+^pT~%&o2MO)SmXoE$9wlV$(_$L*h9{zoA>O#d4*{x=>l#o!ox z=;pCEy2zh%L3D(afx7U#;6Qjza3I{%Y{!>Bl zBP3L&5V?@^M<5UeA^=u^5Q7Pk;GZGDV_-iwhe|%^ktVDctsN{S#UYQt=nrM+7zj${ z4z3U^@Z*Oh8V0hKi@Uj#wJ8K0jQWs+gah|X6HG?%h=UspfpBtwIeEBv^k7Mzew
#Eok4Am0oOZ^N&yii&k$Wh4}4BoHDZG6;kq4i*Iq|0@j!g+Ts{ zdmbiiZvSA&_AqOi+dxfC*qz*=cGjkz=1_K+>AJbQvOAi(I)O
Z3)#2jl*W4?M!Z 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 Date: Fri, 4 Jul 2025 13:22:03 -0500 Subject: [PATCH 8/9] run formatter --- .github/workflows/make_ipks.yml | 2 -- systemcore-apps/system-view/.gitignore | 2 +- systemcore-apps/system-view/build.sh | 2 +- systemcore-apps/system-view/control/control | 2 +- systemcore-apps/system-view/control/postinst | 6 +++--- systemcore-apps/system-view/control/postrm | 2 +- systemcore-apps/system-view/control/prerm | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) mode change 100644 => 100755 systemcore-apps/system-view/build.sh diff --git a/.github/workflows/make_ipks.yml b/.github/workflows/make_ipks.yml index b651c2b3c0..fd8d0adb3c 100644 --- a/.github/workflows/make_ipks.yml +++ b/.github/workflows/make_ipks.yml @@ -26,5 +26,3 @@ jobs: with: name: pv-system-viewer.ipk path: systemcore-apps/system-view/pv-system-viewer_*.ipk - - diff --git a/systemcore-apps/system-view/.gitignore b/systemcore-apps/system-view/.gitignore index f0961fc12b..83c41fb10f 100644 --- a/systemcore-apps/system-view/.gitignore +++ b/systemcore-apps/system-view/.gitignore @@ -1,2 +1,2 @@ !overlay/ -!overlay/** \ No newline at end of file +!overlay/** diff --git a/systemcore-apps/system-view/build.sh b/systemcore-apps/system-view/build.sh old mode 100644 new mode 100755 index 56b1e30d20..87b34a869d --- a/systemcore-apps/system-view/build.sh +++ b/systemcore-apps/system-view/build.sh @@ -90,4 +90,4 @@ fi rm -rf "$BUILD_DIR" echo "" -echo "Build complete" \ No newline at end of file +echo "Build complete" diff --git a/systemcore-apps/system-view/control/control b/systemcore-apps/system-view/control/control index 881d1220e8..be143b6de8 100644 --- a/systemcore-apps/system-view/control/control +++ b/systemcore-apps/system-view/control/control @@ -10,4 +10,4 @@ X-Port: 5804 X-Has-UI: true X-Auto-Start: true X-Icon-Path: /usr/share/pv-system-viewer.png -X-Display-Name: PhotonVision System Viewer \ No newline at end of file +X-Display-Name: PhotonVision System Viewer diff --git a/systemcore-apps/system-view/control/postinst b/systemcore-apps/system-view/control/postinst index 91ac587af2..e719783f7c 100644 --- a/systemcore-apps/system-view/control/postinst +++ b/systemcore-apps/system-view/control/postinst @@ -12,9 +12,9 @@ systemctl enable $PACKAGE_NAME.service echo "Starting service..." if systemctl start $PACKAGE_NAME.service; then echo "Service started successfully" - + sleep 2 - + if systemctl is-active $PACKAGE_NAME.service >/dev/null 2>&1; then echo "Service is now running" else @@ -26,4 +26,4 @@ fi echo "Package installation complete" -exit 0 \ No newline at end of file +exit 0 diff --git a/systemcore-apps/system-view/control/postrm b/systemcore-apps/system-view/control/postrm index 8078e7e217..6fe3eb6778 100644 --- a/systemcore-apps/system-view/control/postrm +++ b/systemcore-apps/system-view/control/postrm @@ -12,4 +12,4 @@ fi echo "Service cleanup complete." -exit 0 \ No newline at end of file +exit 0 diff --git a/systemcore-apps/system-view/control/prerm b/systemcore-apps/system-view/control/prerm index a5c473fb47..861055929d 100644 --- a/systemcore-apps/system-view/control/prerm +++ b/systemcore-apps/system-view/control/prerm @@ -24,4 +24,4 @@ fi echo "Service stopped and disabled" -exit 0 \ No newline at end of file +exit 0 From 2b6b8547832ed626887db3c5635873423ff2de70 Mon Sep 17 00:00:00 2001 From: samfreund Date: Fri, 4 Jul 2025 13:24:04 -0500 Subject: [PATCH 9/9] ignore all .ipk files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index dda0d4712f..4522bf02ea 100644 --- a/.gitignore +++ b/.gitignore @@ -147,3 +147,5 @@ photon-server/src/main/resources/web/* node_modules dist components.d.ts + +*.ipk