User avatar
piglet
Posts: 897
Joined: Sat Aug 27, 2011 1:16 pm

Lookign for some advise on best way to proceed - synchronisation/remote control

Fri Sep 28, 2018 2:07 pm

Hi,

I have a server raspberry pi (3b). It has a lot of things running on it including a web server. I have some Perl scripts on the server providing a UI to the settings on remote hardware

The remote hardware is a range of other things - Raspberry Pi, ESP32 and ESP8266 which periodically poll a Perl script on the pi webserver to get information they need to do their thing.

That periodic polling is a bit rubbish - but was very easy to implement in an evening and has worked up to now.

What I want to do now is to synchronise the activity a bit better. When configuration changes are made on the UI I'd prefer to push out the change to the all the appropriate remote hardware so that they have this change at pretty much the same time.

I wondered about UDP broadcast, but that's something I've never tried. They all need the same information...so it sounds tempting

I wondered whether the remote hardware could be in webserver mode and each be sent the same information as a query string. The server could find the IP addresses of the connected hardware from the DNS screen of the router (or I could assign static addresses).

I wondered about tcp socket connection, but while I have a little experience in this on the server Pi (setting up as a stats server for a remote internet game server), I'm out of my depth there.

Hmmm - many ways to skin this cat but I don't know what's simplest and easiest to achieve.

What's the best way to go about this? Any advice gratefully accepted

Andyroo
Posts: 3351
Joined: Sat Jun 16, 2018 12:49 am
Location: Lincs U.K.

Re: Lookign for some advise on best way to proceed - synchronisation/remote control

Fri Sep 28, 2018 4:41 pm

Problem with UDP is that it’s not always 100% reliable though that may not be an issue in your case.

Given the mix of kit I would look to use MQTT with the web server being the broker and all device either subscribing to one queue or the web server sending data to each queue. The first is simpler to code at both ends but the second gives you more flexibility to send devices separate commands in the future if needed.

Saves having to code a web server for each device and a POST driver from the main host. You can even set reliability QOS to make sure the data gets to the destination if you want.
Need Pi spray - these things are breeding in my house...

stevend
Posts: 209
Joined: Fri Oct 11, 2013 12:28 pm

Re: Lookign for some advise on best way to proceed - synchronisation/remote control

Fri Sep 28, 2018 4:45 pm

With UDP, there's no guarantee that the message is received.
So I suggest you send a UDP broadcast to simply say that updated information is available, maybe with a version number.
Any recipient of that broadcast then immediately triggers its polling cycle to get the updated information.
Minimal change, but synchronises the update.
If the recipients restart a timer each time they poll, you've got a fail-safe against broadcasts getting lost - just poll each time the timer expires.

If you include a version number in the broadcast, you can send it at regular intervals regardless. The recipients can then compare the version against that last downloaded, and update if necessary.

User avatar
DougieLawson
Posts: 35378
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: Lookign for some advise on best way to proceed - synchronisation/remote control

Fri Sep 28, 2018 4:48 pm

Use MQTT (probably Mosquitto).

Get everyone to sync their clocks and subscribe to your c&c channel on the MQTT broker.

When you want something to run sync'd publish a "Do action 3 at 17:48" . All subscribers then watch their clock until the time arrives then triggers the event.
Note: Having anything remotely humorous in your signature is completely banned on this forum.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

User avatar
piglet
Posts: 897
Joined: Sat Aug 27, 2011 1:16 pm

Re: Lookign for some advise on best way to proceed - synchronisation/remote control

Fri Sep 28, 2018 10:25 pm

MQTT is new to me. Wow! It sure makes life easy for you to get connectivity. Thanks for the recommendation.

That lets me concentrate on getting the functionality I need rather than messing about with socket programming like I thought I might have to.

Image

User avatar
DougieLawson
Posts: 35378
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: Lookign for some advise on best way to proceed - synchronisation/remote control

Fri Sep 28, 2018 11:01 pm

MQTT is a layer four protocol, which is always easier to use than anything at layer 3 (socket programming).

If you work in C++ this routine will nicely wait until the exact turn of a minute

Code: Select all

#include <iostream>
#include <iomanip>
#include <thread>
#include <chrono>

void wait3min()
{
        using std::chrono::system_clock;
        std::time_t tt = system_clock::to_time_t (system_clock::now());
        struct std::tm *ptm = std::localtime(&tt);
        // std::cout << "Current time: " << std::put_time(ptm, "%X") << std::endl;
        int offset = 3 - (ptm->tm_min % 3);
        // std::cout << "Waiting for " << offset << " minutes ..." << std::endl;
        ptm->tm_min+=offset; ptm->tm_sec=0;
        std::this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
        // std::cout << std::put_time(ptm,"%X") << " reached!" << std::endl;
}
MQTT programming with C++ isn't too difficult.

Code: Select all

#include <mosquittopp.h>
#include <iostream>

static int run = -1;

class mosquittopp_test : public mosqpp::mosquittopp
{
        public:
                mosquittopp_test(const char *id);

                void on_connect(int rc);
                void on_disconnect(int rc);
                void on_subscribe(int mid, int qos_count, const int *granted_qos);
                void on_message(const mosquitto_message *message);
};

mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}

void mosquittopp_test::on_connect(int rc)
{
        if(rc){
                exit(1);
        }else{
                subscribe(NULL, "+/out/+", 1);
        }
}

void mosquittopp_test::on_disconnect(int rc)
{
        run = rc;
}

void mosquittopp_test::on_subscribe(int mid, int qos_count, const int *granted_qos)
{
        //disconnect();
}

void mosquittopp_test::on_message(const mosquitto_message *message)
{
        std::cout << "Topic " << message->topic << " Payload Len" << message->payloadlen << " Payload " << (char*)message->payload << std::endl;
}

int main(int argc, char *argv[])
{
        struct mosquittopp_test *mosq;
        mosqpp::lib_init();
        mosq = new mosquittopp_test("subscribe-qos1-test");
        mosq->connect("192.168.3.14", 1883, 60);
        while(run == -1){
                mosq->loop();
        }
        mosqpp::lib_cleanup();
        return run;
}
Note: Having anything remotely humorous in your signature is completely banned on this forum.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

Return to “Other projects”