Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .github/workflows/synapse_manager.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Synapse Manager

on:
push:
branches: [main]
paths:
- "synapse_manager/**"
pull_request:
paths:
- "synapse_manager/**"

jobs:
format:
name: Format + Lint
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: synapse_manager/src-tauri

- name: Rust fmt check
working-directory: synapse_manager/src-tauri
run: cargo fmt --all -- --check

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install frontend deps
working-directory: synapse_manager
run: npm ci

- name: Prettier check
working-directory: synapse_manager
run: npx prettier . --check

build:
name: Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
- uses: actions/checkout@v4

- name: Install Linux dependencies (Tauri)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
pkg-config \
build-essential

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: synapse_manager/src-tauri

- name: Build Rust backend
working-directory: synapse_manager/src-tauri
run: cargo build --release

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: synapse_manager/package-lock.json

- name: Install frontend deps
working-directory: synapse_manager
run: npm ci

- name: Build frontend
working-directory: synapse_manager
run: npm run build
108 changes: 108 additions & 0 deletions .github/workflows/synapse_manager_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Synapse Manager Release

on:
push:
tags:
- "v*"

jobs:
build:
name: Build (${{ matrix.os }})
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
label: linux
- os: windows-latest
label: windows
- os: macos-latest
label: macos

steps:
- uses: actions/checkout@v4

- name: Install Linux dependencies (Tauri)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-3-dev \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
pkg-config \
build-essential

- name: Install Rust
uses: dtolnay/rust-toolchain@stable

- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: synapse_manager/src-tauri

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: synapse_manager/package-lock.json

- name: Install frontend deps
working-directory: synapse_manager
run: npm ci

- name: Build Tauri app
working-directory: synapse_manager
run: npm run tauri build

- name: Rename artifacts (Linux/macOS)
if: runner.os != 'Windows'
run: |
VERSION=${GITHUB_REF_NAME}

mkdir -p out

find synapse_manager/src-tauri/target/release/bundle -type f \( -name "*.AppImage" -o -name "*.dmg" -o -name "*.deb" \) | while read file; do
ext="${file##*.}"
cp "$file" "out/synapse_manager_${{ matrix.label }}_${VERSION}.${ext}"
done

- name: Rename artifacts (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
$version = $env:GITHUB_REF_NAME

New-Item -ItemType Directory -Force -Path out | Out-Null

Get-ChildItem synapse_manager/src-tauri/target/release/bundle -Recurse -Include *.msi | ForEach-Object {
Copy-Item $_.FullName "out/synapse_manager_windows_$version.msi"
}

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: synapse-${{ matrix.label }}
path: out/*

release:
name: Publish GitHub Release
runs-on: ubuntu-latest
needs: build

steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: dist

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: dist/**/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7 changes: 5 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ format:
@python3 -m ruff format . >$(NULL) 2>&1 || echo ruff format failed
@echo Isort format...
@python3 -m isort . >$(NULL) 2>&1 || echo isort failed
@echo Prettier format...
@echo Synapse UI format...
@$(CD) synapse_ui && npm run format
@echo Synapse Manager format...
@$(CD) ..
@$(CD) synapse_manager && npm run format
@echo ProtoBuf format...
@cd ..
@$(CD) ..
@$(CD) synapse_net/proto && \
buf format -w
@cd ..
Expand Down
24 changes: 23 additions & 1 deletion synapse_core/src/synapse/core/synapse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@
# SPDX-FileCopyrightText: 2026 Dan Peled
#
# SPDX-License-Identifier: GPL-3.0-or-later

import asyncio
import os
import threading
import time
import traceback
from multiprocessing import Process
from pathlib import Path
from typing import Any, List, Optional

import psutil
from synapse.__version__ import SYNAPSE_VERSION
from synapse_installer.util import IsValidIP
from synapse_net.devicenetworking import NetworkingManager
from synapse_net.file_server import FileServer
Expand All @@ -22,6 +23,7 @@
SetDefaultPipelineMessageProto, SetNetworkSettingsProto,
SetPipelineIndexMessageProto, SetPipelineNameMessageProto,
SetPipleineSettingMessageProto)
from synapse_net.manager_discover import UDPDeviceResponder
from synapse_net.nt_client import NtClient, RemoteConnectionIP
from synapse_net.socketServer import (SocketEvent, WebSocketServer, assert_set,
createMessage)
Expand Down Expand Up @@ -63,6 +65,8 @@ def __init__(self) -> None:
self.networkingManager = NetworkingManager()
self.ntClient: NtClient = NtClient()
self.fileServer: Optional[FileServer] = None
self.managerResponder: Optional[UDPDeviceResponder] = None
self.managerResponderProcess: Optional[Process] = None

def init(
self,
Expand Down Expand Up @@ -148,6 +152,19 @@ def init(
f"Network Config:\n Team Number: {config.network.teamNumber}\n Name: {config.network.name}\n Is Server: {self.__isServer}\n Is Sim: {self.__isSim}"
)

self.managerResponder = UDPDeviceResponder(
config.network.name,
config.network.teamNumber,
SYNAPSE_VERSION,
)

self.managerResponderProcess = Process(
target=self.managerResponder.run,
daemon=True, # auto-kill when main process exits
)

self.managerResponderProcess.start()

nt_good = self.__init_networktables(config.network)
if nt_good:
self.runtimeHandler.setup(Path(os.getcwd()))
Expand Down Expand Up @@ -370,6 +387,11 @@ async def run_server():
log("WebSocket server started on ws://localhost:8765")

def cleanup(self):
if self.managerResponderProcess is not None:
if self.managerResponderProcess.is_alive():
self.managerResponderProcess.terminate()
self.managerResponderProcess.join(timeout=5)

if NtClient.INSTANCE is not None:
NtClient.INSTANCE.cleanup()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
Setting, SettingsValue, SynapseCamera,
pipelineResult)
from synapse.core.settings_api import (BooleanConstraint, EnumeratedConstraint,
FileConstraint, NumberConstraint,
settingField)
NumberConstraint, settingField)
from synapse.hardware.deploy_dir import DeployDirectory
from synapse.log import warn
from synapse.pipelines.apriltag.apriltag_detector import (
Expand Down Expand Up @@ -73,7 +72,6 @@ def getIgnoredDataByVerbosity(verbosity: ApriltagVerbosity) -> Optional[Set[str]


class ApriltagPipelineSettings(PipelineSettings):
example_test = settingField(FileConstraint({"jpg", "mjpeg"}), default=None)
tag_size = settingField(
NumberConstraint(minValue=0, maxValue=None),
default=units.meters(0.1651),
Expand Down
24 changes: 24 additions & 0 deletions synapse_manager/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
3 changes: 3 additions & 0 deletions synapse_manager/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["tauri-apps.tauri-vscode", "rust-lang.rust-analyzer"]
}
7 changes: 7 additions & 0 deletions synapse_manager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Tauri + React + Typescript

This template should help get you started developing with Tauri, React and Typescript in Vite.

## Recommended IDE Setup

- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
25 changes: 25 additions & 0 deletions synapse_manager/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-nova",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "src/App.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
14 changes: 14 additions & 0 deletions synapse_manager/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri + React + Typescript</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading
Loading