Skip to content

feat: allow starting z2m without mqtt (Frontend+WebSocket / WebSocket only mode) - #32314

Open
marmurek wants to merge 3 commits into
Koenkk:devfrom
marmurek:no-mqtt-mode
Open

feat: allow starting z2m without mqtt (Frontend+WebSocket / WebSocket only mode)#32314
marmurek wants to merge 3 commits into
Koenkk:devfrom
marmurek:no-mqtt-mode

Conversation

@marmurek

Copy link
Copy Markdown

I know this might seem strange, given that the project name is Zigbee2MQTT, but sometimes MQTT communication and an additional MQTT broker process running alongside aren't really necessary - we have an excellent replacement in WebSocket.

Based on #16590, #19524 and, for example, how ioBroker substitutes a dummy MQTT server just to start the application correctly and use WebSocket as the main channel later on, I decided to implement an additional toggle for the MQTT settings.

This is my first PR, so I'm not entirely sure if I did everything correctly. If anything is wrong, please let me know.

@Nerivec

Nerivec commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

This will not result in the intended behavior.
The entire Z2M API assumes MQTT is available and valid once Z2M has started; this only prevents connection, it does not refactor the whole MQTT aspect behind branching. Everything would still try to pub/sub, and fail.
Doing this cleanly would require a much bigger API change (optional MQTT instance), and would have to handle special cases where it can't be disabled (e.g. HA). It would also end up a breaking change, at least for external extensions (mqtt arg would no longer necessarily be valid).

PS: bumping settings version & adding settings migrations is only for breaking changes that require migrating to keep on working.

@marmurek

Copy link
Copy Markdown
Author

I was able to start z2m without MQTT connection, successfully pair and control the devices using only Frontend + Websocket, without any errors, so it seems it wont fail while trying to pub/sub.
Isn't it the case that the core of the application is actually the event system and eventBus, not MQTT client itself?

Fair enough, that it may require deeper look e.g. regarding the HA and not bumping settings version if not needed.

@Nerivec

Nerivec commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

You'd have to be hitting code paths like this:

zigbee2mqtt/lib/mqtt.ts

Lines 225 to 231 in fd8bafc

if (!this.isConnected()) {
if (!finalOptions.skipLog) {
logger.error("Not connected to MQTT server!");
logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
}
return;
}

But something like this should not be relying on that kind of code in any case (even if it somewhat works). If no mqtt, mqtt should not be instanciated at all, otherwise the potential for weird bugs goes off the chart.

@marmurek

marmurek commented Jun 15, 2026

Copy link
Copy Markdown
Author

Actually, its like that:
https://github.com/marmurek/zigbee2mqtt/blob/b7706f78fd9c76e97b19c6d04983cd57cff36cc5/lib/mqtt.ts#L225-L234

        if (!this.isConnected()) {
            if (!finalOptions.skipLog && settings.get().mqtt.enabled) {
                logger.error("Not connected to MQTT server!");
                logger.error(`Cannot send message: topic: '${topic}', payload: '${payload}`);
            }
            return;
        }

Not creating instances is actually a much, much nicer approach, but - it looks like WebSocket shares some of the logic with the current parts around mqtt and wow, it in fact seems to be a lot of work.

@marmurek
marmurek force-pushed the no-mqtt-mode branch 2 times, most recently from bfe10fe to 3d0d4bf Compare July 23, 2026 16:01
@marmurek

marmurek commented Jul 23, 2026

Copy link
Copy Markdown
Author

Ok, I had some time to work on this again.

  1. The existing MQTT class has been split into:

    • MessageBus, responsible for local message exchange, retained messages, topic handling, and communication with extensions through the existing API.
    • MqttClient, an optional transport adapter responsible only for the MQTT broker connection, MQTT.js configuration, publishing, and subscriptions. It is only connected when mqtt.enabled is true.

    This separates application-level messaging from MQTT client while keeping the existing extension behavior intact. MessageBus can remain available without a client, while MqttClient is responsible for the optional external transport.
    I am aware that this is not a complete separation. This could be done much nicer, and can separate the dependencies on the Mqtt client, MessageBus, and EventBus even better, but as you said, it seems like it would require breaking the API in a number of places. Current approach will preserve backward compatibility.

  2. Configuration validation has been added: Home Assistant requires MQTT to be active, as discovery and status handling depend on MQTT publications and subscriptions.

  3. Controller.messageBus replaces the old Controller.mqtt. A deprecated getter alias is retained for external API compatibility.. The extension constructor contract remains unchanged.

  4. Simplified MQTT tests:

    • Added a semantic mock state helper: setMockMQTTConnectionState().
    • Removed test references to private controller.mqttClient.client fields.

    Tests now verify observable transport state rather than MQTT.js implementation details, making them less coupled to the concrete client.

@Nerivec @Koenkk
What do you guys think about these changes now? Do you think it's worth pursuing further? I'm not sure if this will be useful to a wider group of Z2m users - for my local needs I can achieve it much more easily - since I dont use HA etc.

@Koenkk

Koenkk commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Thanks, but unless many people are interested in such feature, I don't think we should support it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants