Metadata-Version: 2.4
Name: majal-edge
Version: 0.2.1
Summary: Majal edge agent: connects PX4 and ArduPilot drones to the Majal UTM platform by ScaleX Innovation
Author-email: ScaleX Innovation <support@scalexi.ai>
License: Apache-2.0
Project-URL: Homepage, https://scalexi.ai
Keywords: UTM,drone,MAVLink,PX4,ArduPilot,telemetry,Majal
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering
Classifier: Environment :: No Input/Output (Daemon)
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: pymavlink<3,>=2.4.41
Requires-Dist: pyserial<4,>=3.5
Requires-Dist: paho-mqtt<3,>=2.1
Requires-Dist: cryptography>=41
Dynamic: license-file

# majal-edge

Connects a PX4 or ArduPilot drone to **Majal**, the UAS traffic management (UTM) platform by
[ScaleX Innovation](https://scalexi.ai). It runs on the drone's companion computer (Raspberry Pi,
Jetson, …) or on a ground laptop with a telemetry radio, and sends the vehicle's live MAVLink 2
telemetry to Majal over MQTT with TLS.

## Connect a drone

1. In Majal, open **Fleet**, choose the aircraft and click **Connect**. You get a one-time code,
   valid for 15 minutes.
2. On the companion computer, wired to the flight controller (TELEM2 or USB):

```bash
pip install majal-edge
sudo majal-edge enroll https://<your-majal-address> ABCD-2345
sudo majal-edge install-service        # start now and on every boot (Linux / systemd)
```

The aircraft appears on the live map once the autopilot has a position fix.

## What it does

- **Finds the flight controller**: USB flight controllers (Pixhawk, Cube, Holybro, CUAV, …), the
  companion computer's UART (`/dev/serial0`, `/dev/ttyAMA0`, `/dev/ttyTHS1`) at 921600 / 57600 /
  115200 baud, then MAVLink UDP 14540 / 14550. It only listens while probing.
  `majal-edge detect` shows what it finds; `enroll --autopilot /dev/ttyACM0` skips detection.
- **Gets its identity from the server**: the code is exchanged over HTTPS for a device id and a
  broker login that belong to this device only. The device id, not the MAVLink system id,
  identifies the aircraft, so drones left on system id 1 never collide.
- **Sends telemetry**: position, altitude, speed, heading, battery, mode and armed state
  (requested at 4 Hz / 1 Hz to save mobile data).
- **Reads the autopilot's parameters on the drone** (0.2+): the full list at start and every
  10 minutes, and again when one changes, so Majal can show the safety settings (geofence,
  return-home altitude, battery and link-loss actions), their history, and a pre-flight check.
- **Obeys no command unless you allow it on the drone** (0.2+). With
  `majal-edge allow-commands land,return_home`, it accepts those commands from Majal only when
  they are signed by the platform for this drone, less than 30 seconds old and never seen
  before; it then sends the standard MAVLink command to the autopilot and reports whether the
  autopilot accepted and executed it. Raw MAVLink from the platform is never forwarded. The
  workspace and the aircraft must also allow commands in Majal, and the remote pilot keeps
  priority: a mode change on the handset overrides any command.
- **Handles weak links**: reconnects by itself; while offline, telemetry is dropped rather than
  queued, because a stale position is worse than a gap.

## Security

- Enrollment needs `https://` (plain `http://` only for local / private test addresses or with
  `--allow-http`). Codes are single-use and expire after 15 minutes.
- The broker login can only use this device's own topics (telemetry, parameters, command answers,
  and the signed commands meant for it). It can be revoked from the Fleet page at any time, which
  disconnects the device immediately.
- Commands are verified on the drone with the platform's Ed25519 public key received at
  enrollment (signature, device, 30-second expiry, single use). When the platform rotates its key
  (0.2.1+), the agent fetches the new public key from the platform over HTTPS, at most once a minute.
- The configuration file holding the login is readable by its owner only
  (`/etc/majal-edge/config.json` as root, otherwise `~/.config/majal-edge/config.json`). The
  systemd service runs as an unprivileged `majal-edge` user with the `dialout` group.

## Commands

| Command | |
|---|---|
| `majal-edge enroll <server> <code>` | redeem the code from Fleet → Connect |
| `majal-edge run` | forward telemetry (what the service runs) |
| `sudo majal-edge install-service` | install and start the systemd service |
| `majal-edge detect` | find the flight controller |
| `majal-edge status` | show the configuration and test the broker login |
| `majal-edge allow-commands land,return_home` | commands this drone obeys: `land`, `return_home`, `hold`, `takeoff`, `goto`, `all` or `none` (default) |

Requires Python 3.9+. Licensed under Apache 2.0. © ScaleX Innovation. Support: support@scalexi.ai
