Software for control of 2 axis and 1 axis fire watch towers. To work in conjunction with the firmware at the repository fwt_firmware.
Go to file
pgdalmeida 032355e8fb
Merge keeping each tower's config, scan grid and camera profiles out of a deploy's reach
2026-10-06 19:49:12 +02:00
.claude Add CMake build and typed config with path resolution (remove hardcoded paths) 2026-06-22 12:08:18 +02:00
cmake Changed heading logic; added snapshot feature 2026-09-11 17:42:01 +02:00
config Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
docs Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
hardware Save raw 12-bit camera frames as 12-bit colour images, keep a waypoint's picture once the image has settled, and hold the scan when saving falls behind 2026-10-05 10:14:53 +02:00
include/fgc Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
scripts Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
src Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
tests Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
tools Add camera and image-saving test results for towers 121 and 111, the test tools, and a plan for saving 12-bit images 2026-10-05 08:47:34 +02:00
.deploy.env.example Set in config.ini whether the tower homes and which mode it starts in, instead of the --init and --start flags 2026-09-30 16:42:48 +02:00
.gitignore Add camera and image-saving test results for towers 121 and 111, the test tools, and a plan for saving 12-bit images 2026-10-05 08:47:34 +02:00
CMakeLists.txt Save raw 12-bit camera frames as 12-bit colour images, keep a waypoint's picture once the image has settled, and hold the scan when saving falls behind 2026-10-05 10:14:53 +02:00
README.md Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
deploy.sh Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00
ini.c Initial commit 2026-06-22 11:23:01 +02:00
ini.h Initial commit 2026-06-22 11:23:01 +02:00
main.cpp Keep each tower's config, scan grid and camera profiles in ~/.config/fire_gimbal_control, out of a deploy's reach 2026-10-05 22:02:49 +02:00

README.md

Fire Gimbal Control

The program that runs a fire-watch tower. It points a camera around the horizon on a motorised gimbal, keeps one well-exposed picture at every stop, saves it, and tells the ground station about it - all day, unattended, on a small PC at the top of a mast.

The dashboard of tower 111, live The dashboard of tower 111, captured live on 2026-09-25, seven minutes after a restart: both axes homed and ready, the camera mid-sweep at waypoint 6 of 15, the orientation and ambient sensors reporting, and every picture announced to the broker.


Contents


What it does

A fire-watch tower is a mast with a camera on a gimbal - a mount with two motors, one turning left and right (yaw), one tilting up and down (pitch). This program, fire_gimbal_control, runs on the tower's LattePanda PC and does the watching:

  1. Sweeps a scan grid. A list of directions - "0 deg, 10 deg up", "45 deg, 10 deg up", and so on - that together cover the view. Tower 111's grid has 15 stops.
  2. Keeps one good picture per stop. The camera runs continuously with its own auto-exposure; when the gimbal has stopped and settled, the newest frame is kept.
  3. Saves it as JPEG XL, a compact modern image format, one file per picture.
  4. Tells the ground station over MQTT - which camera, which direction, and when - so the picture can be fetched and checked for smoke.

It does this unattended: it starts at boot, homes the gimbal, and sweeps until it is told to stop. A person only needs to look in when something is wrong - and the dashboard, the log and the self-tests are there to show what.


How the pieces fit together

Two programs cooperate, on two different chips:

The firmware The host program (this repository)
Runs on the small motor board (an RP2040 on the newer IOTA towers, an ATmega32U4 "Leonardo" on the older Delta ones) the LattePanda PC
Lives in its own repository, GGS/fwt_firmware on the same git server, checked out beside this one as ../firmware here
Its job the muscles and reflexes: drive the two stepper-motor drivers, find the endstops, hold a position, stop the moment something is wrong the brain: decide where to point and when to take a picture, own every setting, run the camera, talk to the ground station

The firmware keeps no settings of its own. Every number that describes the motors - the currents, the speeds, the travel, how a stall is detected - lives on the PC, in a file called hardware.ini, and the program hands it to the firmware each time they connect. Until it has them, the firmware refuses to move - a motor running on guessed values can cook its driver or push the gimbal through its endstop, and both have happened on this project.

flowchart LR
    HW["hardware.ini<br/>what the tower IS"] --> APP
    CFG["config.ini<br/>what the tower DOES"] --> APP
    APP["fire_gimbal_control<br/>on the LattePanda"] -- "USB serial<br/>commands + settings" --> MCU["motor board<br/>firmware"]
    MCU -- "status, 4x a second" --> APP
    MCU -- SPI --> DRV["TMC5160<br/>stepper drivers"] --> MOT["yaw + pitch<br/>motors"]
    CAM["camera<br/>(USB3)"] -- frames --> APP
    APP --> JXL["pictures<br/>.jxl files"]
    APP -- MQTT --> BROKER["broker on the tower"] --> GS["ground station"]

The two files

Everything that makes one tower different from another is in two files:

File Where What goes in it Who writes it
hardware.ini /etc/fire_gimbal_control/ What the tower IS - the board, which axes and sensors are fitted, how the motor board is wired, each motor's currents, travel and speeds, the camera's id the installer, once; a person when the hardware changes
config.ini ~/.config/fire_gimbal_control/, with the scan grid and camera profiles What the tower DOES - its name, the scan grid, capture settings, the broker, logging, and calibration such as which way is north the installer (a first copy), the calibration commands, a person

Where both set the same thing, hardware.ini wins, and the program says so at start-up. Full reference: docs/configuration.md and config/hardware.example.ini.

How they start talking

Every time the program connects to the motor board - at boot, after a restart, after the firmware is updated - they go through the same short conversation:

sequenceDiagram
    participant F as Firmware (motor board)
    participant H as fire_gimbal_control (PC)
    Note over F: power-up: stop both drivers,<br/>refuse HOME / MOVE
    F->>H: BOOT build=...
    F->>H: NEED Y steps_per_rev run_irun ... (what it is missing)
    H->>F: SET Y steps_per_rev 177000
    H->>F: SET Y ... (every value, from hardware.ini)
    Note over F: all values in: axis ready to home
    H->>F: DUMP
    F->>H: DUMP ... (every value it now holds, and the pins it was built with)
    Note over H: compare with hardware.ini<br/>(this is `test hardware motor`)
    H->>F: HOME
    F->>H: ST Y:A,... P:A,...  (both axes READY)

So a tower is re-tuned by editing hardware.ini and restarting the program - no firmware update needed. Only the wiring (which pin drives which driver) is built into the firmware, and even that is read from the tower's own hardware.ini when the firmware is built.


A scan, step by step

flowchart TD
    A([next waypoint]) --> B["move yaw and pitch<br/>to the waypoint"]
    B --> C{"both axes<br/>stopped?"}
    C -- no --> C
    C -- yes --> D["hold still for settle_wait_ms<br/>(and, with settle_rule = brightness,<br/>until the brightness has settled)"]
    D --> W["wait out what is left of<br/>image_interval since the last picture"]
    W --> E["keep the newest frame<br/>the camera delivered"]
    E --> F["encode to JPEG XL<br/>save to the output folder"]
    F --> G["publish a CamEvent<br/>(camera, heading, pitch, time)"]
    G --> A

The camera never stops running. It free-runs at its profile's frame rate with its own auto-exposure following the light, and almost every frame is thrown away - their job is to keep the exposure right, so that the one frame kept at each stop is already correctly exposed and was taken with the gimbal at rest.

Which frame rate and exposure limits apply comes from a camera profile: a settings file exported from the camera itself. standard is for daylight, night for low light; switch with set camera profile night.


Running a tower

On a tower the program runs detached, inside tmux, so it keeps running when you close your ssh session. scripts/fgc does that for you:

scripts/fgc start                  # start it; config.ini [Startup] says whether it homes and sweeps
scripts/fgc attach                 # open the dashboard (Ctrl-b d to leave it running)
scripts/fgc status                 # is it running? since when? which PID?
scripts/fgc peek                   # a text snapshot of the dashboard, without attaching
scripts/fgc stop                   # a clean shutdown - camera and motors stopped properly
scripts/fgc restart                # stop, then start again

Tip - detach, don't quit. Inside the dashboard, Ctrl-b d leaves the program running. The dashboard's own q asks whether you want to quit the program or background it; background does the same as Ctrl-b d.

At boot, a tower with the boot service starts itself the same way - through fgc, so the dashboard is still there to attach to:

sudo systemctl status fire-gimbal-control     # is the service running?
sudo systemctl restart fire-gimbal-control    # restart it (it homes the gimbal again)

What the program does as it starts is set in config.ini, not by flags:

[Startup]
home = true     ; home the gimbal at every start
mode = auto     ; manual (wait for someone) or auto (sweep at once)

home = true is what a tower in service needs: the motor board forgets its position whenever it loses power. Tower 111 homes and starts in auto, so after a power cut it is back to capturing within about a minute, with nobody touching it. A new tower starts with mode = manual until it is proven. See configuration.md.

Only one copy can run at a time. Two would fight over the motor board and the camera, so a second one refuses to start and says which process holds the lock. After a crash or a power cut there is nothing to clean up.

The log is kept per run in ~/.local/share/fire_gimbal_control/logs/fgc_<date>-<time>.<n>.log, more detailed than what the dashboard shows:

tail -F "$(ls -t ~/.local/share/fire_gimbal_control/logs/fgc_*.log | head -1)"

More in docs/deployment.md.


The dashboard

The dashboard (the "TUI", for terminal user interface) is what scripts/fgc attach opens. It updates live, and everything on it is read-only unless you press a key that acts.

The main view

Panel What it shows
Header the tower's name, the program's build, its mode (AUTO, PAN, MANUAL), LIVE (or PAUSED), how long it has been up
GIMBAL g each axis: its state (READY, HOMING, ERROR...), the angle it is at and the one it is heading for, the motor and encoder counts, and flags - STILL/MOVE, STALL, over-temperature OT, endstops L/R
SENSORS s the orientation sensor (IMU) (roll, pitch, yaw) and the ambient temperature and humidity, each marked live or not
CAMERAS c whether it is capturing and how fast, the active profile, and the last picture: which camera, where it pointed, how long ago
CONNECTIVITY n the broker connection, the tower name the messages carry, the mode as published
LOG the latest log lines, and in its title the file they are written to; warnings in yellow, errors in red. It always shows the newest line - pause (f) to page back
ACTIVITY what is running right now (a sweep, a pan, a homing, a test, a heading setup) and the result of the last one
Key bar the keys that do something in this view

Keys

Key Does
a / p / m auto mode (sweep the scan grid) / pan 30° around where the gimbal points now / manual mode (stop, take it by hand)
h home the gimbal
g s c n open the full-screen gimbal, sensors, cameras or connectivity view; press it again to close
? the built-in help: every command on one page (:help <topic> for examples)
: type a command, exactly as in the command list
f freeze the display, to select and copy text or to page back through the log (the program keeps running)
PgUp PgDn scroll the log, or the open view - the only scroll keys
arrows nudge the gimbal by hand, from any view - manual mode only (up/down only on a tower with pitch)
Space take one picture now (snapshot) - manual mode only
r continuous capture on/off (capture on / capture off) - manual mode only
Esc close a view; with no view open, cancel whatever is running (a test, a homing, a calibration, a heading setup)
q quit or background the program - it asks which
Ctrl-b d leave the dashboard and keep the program running (a tmux key)

The full-screen views

Gimbal (g) - both axes in detail: positions, the motor driver's live registers decoded into words, how well the encoder is tracking, the homed limits and the calibration. The first time it opens it asks the firmware for a full dump; d refreshes it.

The gimbal view

Sensors (s) - the orientation sensor's (IMU's) full output (acceleration, turn rate, magnetic field, its internal temperature) and configuration, and the ambient sensor with the bus it is on.

The sensors view

Cameras (c) - the camera itself (model, frame size, exposure, gain, temperature, frames delivered and dropped, stream restarts), its profile and encoding, and the whole scan grid with the current waypoint marked.

The cameras view

Connectivity (n) - the broker connection, message counters, the topics the tower listens and speaks on, and the most recent messages, exactly as sent.

The connectivity view

Help (?) - every command, grouped, with an explanation and an example. The same text is available anywhere as help or help <topic>.

The help view


The plain console

Without the dashboard, the program prints its log lines to the terminal and reads commands from the keyboard, one per line. That is what you get with --no-tui, with [UI] enable_tui = false in config.ini, or whenever the output goes somewhere that is not a terminal - a pipe, a file, a script.

The plain console Tower 111 on 2026-09-25, run by hand. It loads its settings, opens the motor board, the sensors and the camera, hands the firmware its settings, homes, and starts sweeping in auto mode. The typed commands (in bold) switch it to manual, run test hardware, and put it back in auto. Two firmware register dumps, dozens of wide lines each, are left out.

Type any command from the list below and press Enter; exit (or Ctrl-D) stops the program cleanly. Nothing here needs a mouse or a large window, which makes it the easiest way to run the program by hand while bringing a tower up.

For scripts, --test runs one self-test and exits with its verdict:

./build/fire_gimbal_control --no-mqtt --test hardware
echo $?        # 0 = PASS, 4 = FAIL, 5 = could not start (the log says why)

Everyday commands

A tower is always in one of three modes. In auto it sweeps its scan grid by itself - the normal state, and where it starts at boot. In pan it watches one direction: mode pan 90 30 sweeps 75° to 105°, a picture every 6°, over and over. In manual it does nothing by itself and a person drives it. Auto and pan refuse anything that would move the gimbal or change a setting, so mode manual comes first; the tower publishes its mode on MQTT (StatusCode: 0 auto, 1 pan, 2 manual).

The same commands work at the : prompt in the dashboard, in the plain console, and over MQTT: a web maintenance interface can send any of them on GGS/FWT/<tower>/Command and read the answer on CommandReply - the lines the command logged, and whether it succeeded. That topic is always live and withholds nothing (exit included), so who may publish to it is the broker's job. Details, payloads and safety rules: docs/mqtt-api.md.

Command Does
mode auto / mode manual sweep the scan grid / stop and take the gimbal by hand (it stays homed and powered)
mode pan <heading> <span> [<pitch>] watch one direction: mode pan 90 30 covers 75°-105°, a picture every 6°
gimbal home find the endstops and centre - needed after every power-up
gimbal move <yaw>[,<pitch>] point at a true bearing (0 = north) and an elevation, in degrees; without a pitch only yaw moves. A yaw-only tower ignores the pitch and refuses pitch-only commands
gimbal nudge <yaw|pitch> <+/-percent> a small move by hand
snapshot take one picture now (manual mode)
capture on / capture off keep taking pictures where the gimbal is aimed, at the sweep's pace (manual mode; the gimbal can still be nudged)
test [<subsystem> [<test>]] run self-tests - see below
gimbal heading setup tie the yaw axis to true north by sighting landmarks
set camera profile <name> switch the camera profile, e.g. night
camera reset reboot the camera and put it back on its profile - for a camera that has stopped sending pictures
gimbal dump show everything the firmware is holding
debug more detail in the log, or back to normal
trace <serial|mqtt|camera|control|all|off> log every message to and from a part, word for word
help [<topic>] the full list, with examples
exit stop everything and quit

The complete list, with every option, is in the built-in help and in docs/configuration.md.


Is the tower healthy?

One command checks almost everything, and changes nothing:

scripts/install-tower --verify
== verify ==
  ok    usbfs_memory_mb        1000 (want >= 1000)
  ok    camera USB3 LPM        0 (want 0)
  ok    config files load      cleanly, 0 shadowed key(s)
  ok    hardware.ini complete  0 TODO(s)
  ok    firmware pins          running build=a0b1e4a ...; declared ... Y=8,7 P=1,0
  ok    test hardware          PASS
  ok    test camera            PASS
  ok    boot service           enabled
  ok    user lingering         yes

>> all checks pass

Tower 111, 2026-09-24.

If the program is running, the tests run inside it - the sweep pauses for a few seconds and carries on afterwards. The two tests that matter most:

  • test hardware - is this the tower hardware.ini describes? The declared axes answer, the firmware holds exactly the declared settings and was built for the declared wiring, the orientation and ambient sensors (if fitted) are really there, the camera opened, and the USB settings the camera needs are in place.

  • test camera - does the camera work, whatever it is looking at? It never judges the picture - fog, night or a lens cap would all make a bad picture out of a healthy camera. Instead it uses the camera's own settings:

    • frames - whole pictures arrive, in time;
    • dark - at the shortest exposure and lowest gain, every pixel goes black;
    • bright - at the highest gain and a long exposure, the picture becomes clearly different from the dark one. That can only happen if the sensor is alive and took the settings.

    Afterwards the camera goes back on its profile.

A test that could not run - no ambient sensor fitted, say - says not checked, never PASS. Every run is written to ~/.local/share/fire_gimbal_control/logs/test_*.log and compared with the one before. More: docs/test-command.md.

Other test groups need a homed gimbal and move it: test gimbal (homing repeatability, encoder, friction, backlash, balance) and test imu. test host checks the PC itself (temperature, disk, memory, load).


Setting up and updating a tower

A new tower - or one set up before any of this existed - is installed by one script, run on the tower:

scripts/install-tower --dry-run   # look, ask, show the plan; change nothing
scripts/install-tower             # the same, then do it after one "yes"

It installs the packages and USB settings, the camera SDK, builds this program and the firmware, writes the two files (asking only what it cannot find out for itself), flashes the firmware, runs the tests, and sets up the boot service. It never guesses a motor value: anything nobody has measured is written as a ; TODO, and the firmware is not flashed until it is filled in. It only homes the gimbal after someone says they are standing at it. Re-running it on a working tower is safe; it changes only what is out of date. The whole story: docs/tower-installation.md.

Updating is done from a development machine, with each repository's deploy.sh, and always in this order:

  1. this program first - ./deploy.sh here copies the code to the tower and builds it there; restart it to use the new version;
  2. the firmware second - ./deploy.sh in the firmware repository builds it on the tower and flashes the motor board.

Host first, because a new firmware asks for its settings the moment it starts, and an older program would not know how to answer. Details: docs/deployment.md.


For developers

The shape of the code

The program is a core that needs no hardware or proprietary SDKs, plus a real and a stand-in version of each part that touches the outside world. That is what lets the whole thing run on any Linux machine, with nothing attached.

flowchart TB
    core["fgc_core - no hardware, no SDKs<br/>Config · CaptureScheduler · TestRunner<br/>parsers for telemetry, DUMP and commands"]
    core --> I1[IMotorController] & I2[IControlChannel] & I3[ICameraSource]
    I1 --> R1[SerialMotorController] & M1[MockMotorController]
    I2 --> R2[MqttControlChannel] & M2[NullControlChannel]
    I3 --> R3["VimbaCameraSource<br/>(Allied Vision Vimba X)"] & M3[MockCameraSource]
    R3 --> P[ImagePipeline] --> J[".jxl files + CamEvent"]

Real on the left of each pair, stand-in on the right. There are stand-ins for the orientation and ambient sensors too. The full design is in docs/architecture.md.

Build

cmake -B build                                # full build: needs Vimba X, fetches Paho MQTT
cmake --build build -j"$(nproc)"             # -> build/fire_gimbal_control, build/fgc-config

cmake -B build -DWITH_VIMBA=OFF -DWITH_MQTT=OFF   # no proprietary SDKs: stand-ins only

Dependencies (OpenCV, Boost, libjxl, the Vimba X SDK) are in docs/build-and-setup.md.

Run with nothing attached

./build/fire_gimbal_control --mock-serial --mock-camera --no-mqtt --tui

The stand-in motor board, camera and broker behave like the real ones closely enough to drive the dashboard, run a sweep and run most self-tests. [Features] mock_needcfg = true makes the stand-in motor board ask for its settings the way the real firmware does.

Command-line options

Flag Effect
-c, --config <path> use this config.ini (otherwise $FGC_CONFIG, then ~/.config/fire_gimbal_control/config.ini, then ./config.ini, ...)
--hardware <path> use this hardware.ini (otherwise $FGC_HARDWARE, then /etc/fire_gimbal_control/hardware.ini, then beside config.ini)
--test <selection> run one self-test and exit: 0 PASS, 4 FAIL, 5 could not start
--tui / --no-tui the dashboard / the plain console (overrides [UI] enable_tui)
--mock-serial, --mock-camera, --mock-env stand-ins instead of the motor board, camera, ambient sensor
--no-mqtt no broker
--degraded start even though hardware.ini declares a part that is missing (field triage)
--log-level <level> trace, debug, info, warn, error, off - for the screen
--log-file-level <level>, --no-log-file the log file's level / no log file this run
--trace <parts> log every message to and from serial, mqtt, camera, control, all
--no-lock, --lock-file <path> skip / move the single-instance lock (development only)
-h, --help all of the above

Watching the wires

Two separate knobs control what is logged:

  • the level (--log-level, debug, [Logging] level) - how much ordinary detail. At info, a running sweep is nearly silent;
  • traces (--trace, trace <part>, [Logging] trace) - every single message exchanged with a part, word for word, whatever the level. Off by default; the camera one is busy.
14:02:01.234 [SERIAL]  TX MOVE -90,0
14:02:01.250 [SERIAL]  RX ST Y:A,982,969,80084000,0,8,8,Se P:A,...
14:02:02.000 [MQTT]    PUB GGS/FWT/Tower/StatusCode 0
14:02:02.500 [CAMERA]  TX trigger cam0
14:02:02.910 [CAMERA]  RX frame cam0 1936x1216 7064576B

Tests

cmake -B build-test -DWITH_VIMBA=OFF -DWITH_MQTT=OFF -DBUILD_TESTING=ON
cmake --build build-test -j"$(nproc)"
ctest --test-dir build-test --output-on-failure

Over 360 unit tests, needing no hardware and no SDKs: configuration and the two files, the parsers, the capture scheduler, the self-test checks against the stand-ins, the firmware handshake, the camera checks, the config-file editor.

Repository layout

CMakeLists.txt        build (WITH_VIMBA, WITH_MQTT, WITH_TUI, BUILD_TESTING)
main.cpp              entry point: command line -> Application
include/fgc/          headers: the interfaces, config, scheduler, tests, ...
  mock/               the stand-in implementations
src/
  core/               the core: Application, config, scheduler, parsers, tests, ...
  camera/             Vimba X camera, image pipeline, JPEG XL encoder
  serial/             motor board and orientation-sensor links
  mqtt/               MQTT control channel
  sensors/            ambient sensor (SHT41) over I2C
  ui/                 the dashboard and the plain console
tests/                unit tests (doctest)
tools/fgc_config.cpp  fgc-config: edits config.ini / hardware.ini safely
config/               config.example.ini, hardware.example.ini, scan grids, camera profiles
hardware/             per-board setup kits (LattePanda IOTA, LattePanda 3 Delta)
scripts/              fgc, install-tower, the boot service, camera-profile export
docs/                 everything longer than a README
ini.c, ini.h          the bundled INI parser (inih)

Documentation

Document Read it for
docs/tower-installation.md installing a tower, step by step, and what each step is for
docs/deployment.md running and updating a tower: deploy.sh, fgc, the boot service, the log, troubleshooting
docs/configuration.md every key in config.ini, every flag, every command
docs/test-command.md the self-tests: groups, profiles, reports, baselines
docs/mqtt-api.md the MQTT topics and what each message contains
docs/known-issues.md what is known to be wrong or unfinished
docs/architecture.md the design: parts, threads, data flow, the capture cycle
docs/modules-reference.md file by file
docs/build-and-setup.md building, dependencies, the camera SDK
docs/hardware-config-plan.md why hardware.ini exists, and the firmware handshake
docs/hardware-porting-plan.md moving towers to the LattePanda IOTA
docs/lattepanda-iota.md the IOTA board
docs/roadmap.md, docs/test-roadmap.md what comes next

Ownership

Internal tooling for the GGS fire-watch tower network. No license file is present in the repository.