Querying IoT devices from Phoenix

Hi everyone!

Noob here. I created a minimalistic Phoenix project (LiveView included) were I can switch On and Off a virtual switch (for controlling lights on/off) and I can interact with it in “real time” from a web browser.

This is deployed on Nerves, not sure if this is relevant, however what I want to achieve is to send a command to the physical switch via the Web interface.

I managed to send manual commands to the switch already with HTTPoison, but I want to use Phoenix as interface.

The switches are from the brand Sonoff (MiniR2 ref. below) and are connected to the net via wireless. They offer a REST API to change their status and query them.

Now, I saw some similar answers and it was suggested to use PubSub solution, but honestly I don’t understand how this could fit in this case. I cannot subscribe to the switches because they do not publish anything, unless it is requested (pulled from them).
The switches cannot subscribe to Phoenix, because that is not available on their REST API interface.

My quickest solution would be to instantiate one HTTPoison per each switch when the page is loaded and then send them a command and hook it to the event that handles the click event (LiveView) on the controller. However, I would like to get some proposals from the experts.

I prepared a nice image describing the deployment but then I found out I cannot attach it. ( will just add the PlantUml for it :wink: in case you are curious.

MiniR2 API ref:

Image:

@startuml

skinparam BackgroundColor transparent
skinparam roundCorner 10

card Home {

card "Nerves on RBP3" {
    node  "Phoenix" as ph
}

card "IoT environment" {
    card  "Sonoff 1" as sn1
    card  "Sonoff 2" as sn2
}

}
cloud Internet as inter

card “Client browser” as pc

sn1 <… ph
sn2 <… ph
pc → inter
inter → ph
@enduml

1 Like

Fun project! It looks like you can query the devices on your local network using mDNS, I’ve written an mdns library for this very purpose. mdns | Hex

After you query your devices, it probably makes sense to start a process per device to maintain their state within your application. Stuff like the IP, current status, etc.

How you register the names of the processes is up to you. I would ideally start the “switch” processes under a supervisor, with no name registration and use something like Registry to associate the switch PID with a display name, something for the UI.

From there it’s as simple as exposing a public interface to your switch module/process that you can call from your LiveView process from handle_in

2 Likes

Some other libraries that may provide some inspiration.

Thank you, Entone, I appreciate your help.

Also, you can paste multiline code snippets using opening and closing triple ticks

@startuml

skinparam BackgroundColor transparent
skinparam roundCorner 10

card Home {

    card "Nerves on RBP3" {
        node  "Phoenix" as ph
    }

    card "IoT environment" {
        card  "Sonoff 1" as sn1
        card  "Sonoff 2" as sn2
    }
}

cloud Internet as inter {

    card “Client browser” as pc{
        sn1 <… ph
        sn2 <… ph
        pc → inter
        inter → ph
    }
}
@enduml
1 Like