11 Commits

Author SHA1 Message Date
bsncubed 41103e3b5e Licences: MIT for the AES67 core and web page, GPL-3.0 for the rest
- LICENSE (GPL-3.0) at the root; an MIT LICENSE in each components/aes67_*
  and in web/, so they travel with the code when reused.
- THIRD_PARTY.md: third-party code and licences, and the known conflict of
  the Espressif binary audio libraries with GPL-3.0 (firmware contains cspot).
- CLAUDE.md: rule to keep GPL code out of the core; phase 2 item to replace
  the Espressif binaries (opencore-aacdec, Speex resampler).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 08:37:38 +10:00
bsncubed b36419477c Network: static IP addressing
net.dhcp = false applies ip/mask/gw/dns on link up (DHCP client stopped).
PTP/TX/SAP sockets are bound to the address, so a changed IP setup reboots
the device; with DHCP on, the static fields (UI fills them with the lease)
don't count as a change. Validation: contiguous netmask, not the network or
broadcast address, gateway in the subnet. The page follows the device to the
new address after saving. Checked: DHCP -> static .245 (PTP, TX, SAP, SDP
origin, mDNS on the new address) -> DHCP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 00:01:34 +10:00
bsncubed c4468c4af0 Network: status reports mask/gw/dns; UI shows the DHCP lease in the static fields
With DHCP on, the greyed-out IP/netmask/gateway/DNS fields show the
addresses in use. Unticking DHCP keeps them as the starting point for a
static setup. (Static addressing itself is not applied yet.)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 23:42:35 +10:00
bsncubed 3d05768f00 Step 4.1: /stream.sdp from the live config and PTP GM
- aes67_sdp_sap: aes67_sdp_build() builds the AES67 SDP (RFC 4566 +
  RFC 7273) with the same lines and order as the web UI preview;
  GET /stream.sdp serves it as application/sdp.
- aes67_ptp: public aes67_ptp_gm_id(), aes67_ptp_locked(),
  aes67_ptp_now_ns(). Clock IDs are now uppercase (RFC 7273 style), also
  in status.ptp, which the UI copies into ts-refclk.
- aes67_net: aes67_net_netif() returns the AES67 interface.
- Verified on board: /stream.sdp byte-identical to the UI's sdp() for
  the same config/status; mono, L16, ptime 0.333, ttl 8, clk_offset
  4294967295 and session_ver all follow the config.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 06:38:55 +10:00
bsncubed 07e16e6163 DHCP hostname: send net.hostname in DHCP requests
- aes67_net: esp_netif_set_hostname() before the interface starts, and
  in the net apply callback (takes effect at the next lease renewal).
- Verified: the router's DNS (lan.apointless.space) resolves p4-aes67
  to 192.168.192.244.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 23:16:39 +10:00
bsncubed 30c32e702b Step 2a (2/2): LLDP transmit, switch shows name and IP
- aes67_net/lldp.c: IEEE 802.1AB LLDPDU sent as a raw frame with
  esp_eth_transmit every 30 s (TTL 120 s) and immediately on a new IP
  or hostname change. TLVs: chassis/port ID (MAC), port description,
  system name (net.hostname), system description (project + version),
  capabilities station-only, IPv4 management address.
- Docs: LLDP in the core Network section; step 2a ticked.
- Verified on an HP 2530-8G-PoE+ (show lldp info remote-device 2): all
  fields shown, management address 192.168.192.244.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 23:14:09 +10:00
bsncubed 979420a6bb Step 2a (1/2): mDNS hostname.local and _http._tcp
- aes67_net: espressif/mdns 1.13.1 (managed component, pinned in
  dependencies.lock). Advertises <net.hostname>.local and the web UI as
  _http._tcp port 80. net apply callback renames live.
- First config value actually applied: net.hostname.
- Docs: mDNS in the core Network section; build order gets step 2a
  (mDNS, then LLDP).
- Verified on board: p4-aes67.local resolves via raw mDNS and getent,
  http://p4-aes67.local/ answers, service shows in _http._tcp browse;
  live rename to p4-rename and back works (after ~1 s probing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 23:08:51 +10:00
bsncubed c2621f192a Step 2.2: config registry and NVS store, GET/POST /api/config
- aes67_web/cfg.c: cfg_register(group, defaults, validate, apply),
  cfg_override_defaults() for project defaults, cfg_get(). Stored values
  are loaded on register and merged over defaults (known keys, matching
  types). NVS keeps only keys that differ from defaults, one JSON string
  per group, so new firmware defaults still reach untouched settings.
- POST /api/config: type check against defaults, per-group validation,
  nothing stored unless every group passes; 400 "group.key: reason".
  Unknown keys/groups are ignored. Returns the new config.
- Core groups registered by their components with the UI's ranges:
  ptp (aes67_ptp), aes67 (aes67_tx, incl. multicast range and mono_sum
  => 1 channel), net/inet (aes67_net), log (aes67_syslog).
- Project: PROJECT.def overrides (hostname p4-aes67, name P4 AES67) and
  the "source" group in main/project_cfg.c.
- Config is stored only; nothing is applied live yet.
- Verified on board: defaults, valid save, 8 rejected values (nothing
  stored), persistence across reboot, restore to defaults.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 23:00:55 +10:00
bsncubed 35275b8ccf Step 2.1: web server, embedded UI, /api/status, /api/reboot
- aes67_web: httpd (wildcard URI matching), serves web/index.html embedded
  via EMBED_TXTFILES, status registry (status_register) and route registry
  (web_register_uri), GET /api/status, POST /api/reboot (restarts 0.5 s
  after the response).
- Status fields come from each core component: aes67_net (ip, aes67_ip,
  mac, link), aes67_health (fw, uptime_s, heap_free, psram_free),
  aes67_tx stub (tx_packets, underruns = 0). No ptp object yet, so the UI
  shows "no data".
- Verified on board: / serves index.html byte-identical (27601 B),
  /api/status returns live values, reboot via API returns in ~12 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:56:06 +10:00
bsncubed 69b4e18118 Step 1: Ethernet up (IP101/RMII), DHCP, link and IP logged
- aes67_board: Waveshare ESP32-P4-ETH pin profile and EMAC + IP101 driver
  install (PHY addr 1, reset GPIO51, ref clock in on GPIO50).
- aes67_net: Ethernet netif with DHCP client; logs link up/down (speed,
  duplex, MAC) and the DHCP lease.
- Verified on board: 100 Mbps full duplex, DHCP lease in ~8 s, ping
  0% loss, ~0.2 ms RTT.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:52:08 +10:00
bsncubed bbfd3506bf Step 0: IDF project skeleton for esp32p4 with core component stubs
- Board checked with esptool: ESP32-P4 rev v1.3 (engineering silicon),
  32 MB GigaDevice flash. Rev <3 support and 32 MB set in sdkconfig.defaults.
- OTA partition layout: nvs, otadata, phy_init, ota_0/ota_1 (6 MB each,
  below 16 MB), coredump; no factory app. Partition table at 0x10000 so
  the bootloader can grow.
- App rollback enabled in the bootloader from the start.
- PROJECT_VER from git describe --tags --always --dirty.
- Empty stubs for the nine aes67_* core components; main logs version
  and chip revision.
- Built with ESP-IDF v5.5.5; not yet flashed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-24 22:47:21 +10:00