Fetch data from MQTT client via Phoenix

How do I fetch live data received by MQTT client (also in elixir) via Phoenix? I’m building an IoT dashboard and I want to check on devices current state. I’m thinking in subscribing to a topic (corresponding to a device) when a user connects via websockets and wait for any data sent by the MQTT client to this topic.
What’s the best approach to achieve this?

(Just a simple illustration of my problem)
Client <–websocket–> Phoenix <-- ?? --> MQTT Client

Thank you in advance

Welcome to the forum!

Seems ?? should be a MQTT Broker.

recommends VerneMQ

Caveat: Just some information based on some hasty online searches …


My first rough sketch:

See if its possible to use a plugin to store information in a “data-repo” application. Then use Phoenix “Phoenix-is-not-your-application style” to serve as the web front end for the data repo application.

Thank you for the reply @peerreynders. The broker is not the problem (I’m already using VerneMQ). I forgot to mention it on the diagram but it would be on the far right. Like this:
Client <–websocket–> Phoenix <-- ?? --> MQTT Client < ----> Broker < — > device

I’ll still try my luck with that plugin approach.

What is your technical hurdle to:

Client <– websocket –> Phoenix –> MQTT Client –> mqtt –> MQTT Broker <– mqtt –> device
  • The device status can’t be queried directly?
  • Need to “know” all devices status even after after a prolonged downtime of the Phoenix application?

My initial idea

Client <– websocket –> Phoenix –> Data Repo App <– plugin <- MQTT Broker <– mqtt –> device

was to place the “device status storage” outside of Phoenix (… provided the plugin solution is viable).

What do you mean with “Data repo app”? :s
The mqtt client is already persisting all incoming data from the broker to a database which can be queried by phoenix. Since I also want to send live data to a client I want a mechanism to communicate from phoenix to the mqtt client and vice-versa. My initial idea was to use a pubsub approach but I just can’t set it up inside phoenix so I’m looking for alternatives.

(Sorry for the confusion, I just got started with elixir)

It’s simply a way to decouple Phoenix from the “application”:

The mqtt client is already persisting all incoming data from the broker to a database which can be queried by phoenix.

“MQTT client” typically refers to a library that allows you to communicate with an MQTT Broker.

This is the part that is confusing me:

mechanism to communicate from phoenix to the MQTT client and vice-versa

By your description I’m imagining a Phoenix application that is using something like tortoise to talk to the MQTT broker.

So your Phoenix application should already be “seeing” all the messages.

Since I also want to send live data to a client I want a mechanism to communicate from phoenix to the mqtt client and vice-versa.

I assume “client” refers to the “web client”.

What is preventing you from propagating the information live, in parallel to storing it in the database?

Or are you possibly talking about the dash communicating directly to a particular IoT device? That seems to be an MQTT problem - this article talks about faking P2P on MQTT.

That’s my problem! (Thank you for describing it for me haha)

I already have an elixir application with tortoise receiving the data from the broker and a phoenix application with websockets running. I just don’t know how to / can’t:

  • Phoenix → Subscribe to device/id after some web client connects via websocket

  • Tortoise → Publish to device/id upon receiving data from this device and then MyPhoenixApp.Endpoint.broadcast so that the web client can see this data

Not only this but I also want to, for example:

  • Ping device from web client
  • Send reset message to device

Sorry for not expressing my point of view and thank you for your patience

One possible solution might be to integrate Phoenix.PubSub into “the application that uses tortoise”. That way your web backend (built with Phoenix) can subscribe with that app to receive live updates via distributed Erlang/Elixir.

See also: Using Phoenix.PubSub to send messages across processes.

Of course you can always roll your own using Registry.

See also: Three alternatives to using GenEvent in Elixir

(Don’t use GenEvent - it’s deprecated. Replacing GenEvent by a Supervisor + GenServer - Updated code using DynamicSupervisor.)

Some cursory inspection of available information seems to suggest that you would have to fake request/response with the publish/subscribe capabilities of MQTT.

2 Likes