Web side for MeshCore logger firmware
- PHP
- MySQL or MariaDB
- PHP syntax check:
find . -name "*.php" | xargs php -l - JavaScript lint:
npm installthennpm run lint:js
- Setup MySQL database
- Open
setup.php, follow instructions - Flash logger node MeshCore logger firmware (Xiao S3 and T3S3 are currently supported)
- Connect to logger node via serial and set configuration:
log url https://172.30.1.98:6080/log.phpWhere data is sent (should point tolog.phpfile)log report 1800Self-report interval, can be 0 to disablelog auth SomeSecretSecret used for web authorizationwifi ssid YourWifiSSIDwifi password YourWifiPasswordset name Node Nameset lat xx.xxxxxset lon xx.xxxxxrebootApply changes
- Add reporter to database by going to
admin/Public Keymust match the logger/reporter public key.- HTTP ingest uses the
reporterfield from the logger payload. - MQTT ingest uses the topic key from
<prefix>/<iata>/<public_key>/(status|packets|debug)and falls back toorigin_idwhen no key can be parsed from the topic.
- HTTP ingest uses the
Authmust match the loggerlog authvalue. MeshLog expects this in HTTPAuthorization: Bearer <secret>from the logger firmware.- For MQTT ingest (
php mqtt.php), authorization header is not used, but the reporter must still exist and beauthorized = 1. - You can leave
Authempty for MQTT-only reporters.
MeshLog can ingest MeshCore packet logs from MQTT (for example from meshcoretomqtt) while keeping firmware HTTP logging active.
- Configure MQTT in
config.php(seeconfig.example.php)enabled:trueto activate MQTT ingesttransport:tcp,ssl,ws, orwsshost,port,topicusername/passwordfor authenticated brokers (or leave empty for anonymous)
- Ensure each MQTT reporter public key exists as a reporter
public_keyin MeshLog.- Preferred mapping is from the MQTT topic segment immediately before the final
(status|packets|debug)suffix (for example<prefix>/<iata>/<public_key>/packets). - If topic key extraction is not possible, MeshLog falls back to payload
origin_id,public_key,pubkey, orreporter. - Packet ingest still requires the MQTT
PACKETpayload to include the raw packet bytes inraw; otherwise MeshLog can identify the reporter for debug logging, but skips the packet as invalid. - Add it from
admin/with:public_key = <public_key from MQTT topic (or origin_id fallback)>authorized = checked- optional
auth(only needed for HTTP logger ingest)
- Preferred mapping is from the MQTT topic segment immediately before the final
- Run MQTT worker:
php mqtt.php- Optional: set
$config['mqtt']['debug'] = trueto print topic, reporter-key resolution, and mismatch diagnostics.
MeshLog can compare each reporter repeater's latest advertisement timestamp with a cached UTC reference from NTP and flag repeaters whose clocks drift too far from the platform time.
- Configure the optional
ntpblock inconfig.phpfor the NTP server, timeout, and cache behavior - Adjust the warning threshold in the admin Settings page via
TIME_SYNC_WARNING_THRESHOLD - NTP lookups are cached in the system temp directory to avoid querying on every refresh
The worker listens to packet topics. Unencrypted ADVERT packets (packet_type=4) are fully decoded and stored as ADV entries in the database; encrypted packet types (TXT_MSG, GRP_TXT, etc.) are stored as RAW packets. MQTT path values are normalized and hash prefix size is detected from the binary path_len byte (supports 1/2/3-byte routing hashes, MeshCore 1.14+ compatible).
- Binary MQTT
PACKETmessages are only fully decoded when the payload itself is not encrypted. ADVERT(packet_type=4) is decoded into normal ADV entries.TXT_MSG(packet_type=2) andGRP_TXT(packet_type=5) are still encrypted in MeshCore, so MeshLog cannot recover the message text or channel from the binary packet alone.- In the UI these encrypted packets are still stored as RAW packets, but are now labelled by subtype (
RAW MSG,RAW PUB, etc.) based on the packet header. - To ingest actual decoded direct/group messages, use the firmware HTTP logger path or a MQTT publisher that already sends structured
MSG/PUBJSON payloads instead of encrypted binaryPACKETframes.
If LetsMesh PACKET frames were ingested before the PACKET decoder ordering fix, older raw_packets rows may still contain the full radio frame instead of the extracted payload metadata. MeshLog ships a one-off CLI repair tool for those rows:
- Dry run:
php tools/backfill_letsmesh_raw_packets.php --limit=100 --verbose - Apply changes:
php tools/backfill_letsmesh_raw_packets.php --apply - Restrict scope:
--reporter-id=<id>or--packet-id=<raw_packets.id>
The repair tool updates historically mis-stored LetsMesh raw_packets rows in place, restores the real packet header/path/payload fields, regenerates decoded RAW metadata where possible, and rebuilds collector packet rollups so Stats reflects the repaired packet mix.
Channels can already be added in two ways:
-
Manual admin entry
- Open
admin/ - Go to the Channels section
- Add the channel
hash,name, and enabled flag - This uses the admin API at
admin/api/channels/
- Open
-
Automatic creation from structured group messages
- When MeshLog receives a decoded
PUBpayload (HTTP logger or structured MQTT JSON),insertGroupMessage()looks up the channel bychannel.hash - If the channel does not exist yet, MeshLog creates it automatically before saving the group message
- When MeshLog receives a decoded
Binary encrypted MQTT GRP_TXT packets do not contain enough information for MeshLog to auto-create channels, because the group payload remains encrypted and is therefore stored only as RAW.