fix: MQTT listener credentials and live sync of machine counts - #336
Merged
jakub-przepiora merged 3 commits intoOct 4, 2026
Merged
jakub-przepiora merged 3 commits into
jakub-przepiora merged 3 commits into
Conversation
php-mqtt/client ConnectionSettings is immutable: every setter returns a modified clone. buildSettings() discarded those return values, so the username, password and TLS options never reached the connection. Brokers with anonymous access disabled rejected the listener as "not authorised", with nothing pointing at the missing credentials. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
mqtt-listener was pinned to BROADCAST_CONNECTION=log. CollectionChanged is ShouldBroadcastNow, so it is dispatched by the process that writes the row; work order quantities updated from MQTT messages were logged instead of sent to Reverb, and open pages only showed them after a manual reload. Use reverb with the same REVERB_* settings as backend and queue-worker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…s rows mqtt-listener was not the only service pinned away from Reverb. modbus-poller and queue-worker set no BROADCAST_CONNECTION at all, so they fell back to the config default — reverb — with no REVERB_HOST, REVERB_PORT or REVERB_SCHEME. That resolves to https://:443, which goes nowhere. The failure is invisible by design: CollectionBroadcaster::safeBroadcast() reports the exception and swallows it, because a broadcast must never break the write that triggered it. So the counter reading lands in the database and the browser keeps showing the old number until someone reloads. modbus-poller writes machine counter readings and queue-worker sends every queued ShouldBroadcast event, so both need the same block the listener now has. opcua-gateway is unaffected: it posts to the backend API, and the backend both writes the row and broadcasts it. Also adds a unit test for MqttListenCommand::buildSettings(). ConnectionSettings is immutable, so a setter whose result is discarded is a no-op that nothing reports; two of the four assertions fail without the credentials fix in this branch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two small fixes found while running OpenMES with a real MQTT piece counter (ESP8266 + laser sensor → Mosquitto →
mqtt-listener→ work order quantity) on a Raspberry Pi.1. MQTT credentials and TLS were never applied (
MqttListenCommand::buildSettings())php-mqtt/client'sConnectionSettingsis immutable — every setter returns a modified clone.buildSettings()calledsetUsername(),setPassword(),setUseTls()andsetTlsCertificateAuthorityFile()without assigning the result, so none of them reached the connection. Against a broker with anonymous access disabled, the listener was rejected asnot authorised, with nothing indicating that the credentials had not been sent. The fix assigns each result back to$settings.2. Machine counts from MQTT did not live-sync to the browser (
docker-compose.yml)mqtt-listeneris pinned toBROADCAST_CONNECTION: log.CollectionChangedisShouldBroadcastNow, so it is dispatched by the process that writes the row — for quantities coming from MQTT that ismqtt-listener. The deltas went to the log instead of Reverb, so the work order list and dashboard only showed new counts after a manual reload. The service now usesreverbwith the sameREVERB_*settings asbackendandqueue-worker.Type of change
Related issue
None filed.
Testing
Verified manually on a running deployment (Raspberry Pi 3B, Mosquitto with anonymous access disabled, MQTT mapping
$.licznik→update_work_order_qty,qty_increment: false):with fix 1 the listener authenticates (
u'openmes'in the broker log) and messages are stored with statusok; without it the broker rejects the connection;with fix 2
produced_qtyupdates live in the admin work order list; without it a reload was required.Tested manually in browser
php artisan testpasses — not run; neither change touches code paths covered by the suiteTested as Operator / Supervisor / Admin role (if UI change) — not a UI change
Checklist
.envsecrets committed$fillableupdated if new model columns added — n/acomposer auditclean — no dependency changesNotes (not in this PR)
Pages/admin/work-orders/Show.jsx) has no live refresh, unlike the list and dashboard, so counts there still need a reload.backendis the only service that does not receiveAPP_KEYfrom the host.env; its entrypoint generates its own key, while the sidecars use the host one and sharebootstrap/cache. In our setup this producedDecryptException: The MAC is invalidinmqtt-listenerfor the MQTT password saved in the panel. Not fixed here because simply passing an emptyAPP_KEYtobackendwould break installs that rely on the generated key — worth a separate issue.🤖 Generated with Claude Code
Added after review (jakub-przepiora)
Correction to point 2 above:
queue-workerhas noREVERB_*settings and noBROADCAST_CONNECTIONeither — the original wording here was wrong. Checking that turned up the same defect in two more services, so this branch now closes the whole family rather than one case of it.3.
modbus-pollerandqueue-workerhad the same problem, differently shapedNeither sets
BROADCAST_CONNECTION, so both fall back to the config default —reverb— but with noREVERB_HOST,REVERB_PORTorREVERB_SCHEME.config/reverb.phpdefaults those to an empty host on port 443 over https, which resolves to nowhere.It is invisible by design:
CollectionBroadcaster::safeBroadcast()reports the exception and swallows it, because a broadcast must never break the write that triggered it. The row is stored and the browser keeps showing the old value until someone reloads — exactly the symptom this PR started from, one layer along.modbus-pollerwrites machine counter readings, so a Modbus counter had the same live-sync gap as the MQTT onequeue-workersends every queuedShouldBroadcasteventopcua-gatewayis unaffected — it posts to the backend API, and the backend both writes the row and broadcasts it4. Unit test for
buildSettings()tests/Unit/Connectivity/MqttConnectionSettingsTest.php— four cases: credentials reach the connection, an anonymous broker is left without them, TLS and its CA file are applied, and the saved timings survive. Two of the four fail without the immutability fix in this branch, which is what makes them worth having;buildSettings()is private, so the test reaches it by reflection rather than widening the command's API for a test's sake.php artisan test --filter=MqttConnectionSettingsTest→ 4 passed.