2

I got 10 Raspberry Pis and each of them records video from a USB camera. I want to control them simultaneously with simple commands like "start" or "stop" the recording script. Is there a way to connect all of them to another Raspberry Pi and send those commands from that Raspberry Pi over direct (I don't want the system to be dependent on an internet connection) wireless connection? All the Raspberry Pis have USB Wi-fi dongles and they are placed close to each other.

Thank you.

goldilocks
  • 58,859
  • 17
  • 112
  • 227
dnzzcn
  • 103
  • 1
  • 2
  • 10
  • You could use ethernet to connect them and a message que to send commands – Steve Robillard Feb 03 '16 at 18:58
  • 1
    Have a look at the MQTT example I gave in this very similar question. It seems perfect for your usage. http://raspberrypi.stackexchange.com/questions/24338/how-to-control-multiple-raspberry-pis-at-once-over-ethernet/24349#24349 – joan Feb 03 '16 at 19:11
  • You should be able to either set up one as an access point for the others, or configure them all as ad hoc nodes. Both of these may depend upon capabilities of the wifi adapters. – goldilocks Feb 03 '16 at 19:29
  • I've edited your title because there seems to be some confusing about the fundamental issue in your question. There are limitless ways to send messages between connected machines, the complication in this case is actually connecting them. – goldilocks Feb 03 '16 at 19:31
  • I'm still a little confused by the question. Is the requirement for no router, or no internet connection, or both? – goobering Feb 03 '16 at 19:42
  • joan thanks for the answer you shared I'll take a look at it. – dnzzcn Feb 03 '16 at 19:44
  • goldilocks thank you for the correction.

    goobering, I'm looking for a solution that goldilocks mentions, where one RPi is an access point for the others. So, it works as a router I guess.

    – dnzzcn Feb 03 '16 at 19:51
  • You can use a wireless router to set up a local network, it doesn't have to be connected to the internet. Alternatively why not just buy a 16 port switch and connect all the Pis via ethernet. I thought your question was more about the software than setting up a local network. – joan Feb 03 '16 at 20:19
  • The question is about creating a local network using a Raspberry Pi, not a router; and then, sending commands to other RPis. MQTT seems to be the answer for the second part. However, I want to setup a local network using a Raspberry Pi, which will also be the publisher of the MQTT connection, not a wireless router. – dnzzcn Feb 03 '16 at 23:42

2 Answers2

3

Yes. Your 'other raspberry pi' would be set up as an access point like this: https://learn.adafruit.com/setting-up-a-raspberry-pi-as-a-wifi-access-point/overview

The raspberry pis will then be able to connect to this in the same way as they would to any wireless router (configure the ssid and password). If you needed a laptop connected for manual control or logging in to Pis in your cluster, that could also connect to the access point.

Once the networking layer is set up, you can then use http, mqtt, or whatever network protocol you fancy to coordinate the Pis as suggested by others on this question.

lwr20
  • 312
  • 2
  • 10
-1

There are many ways to get the Raspberry Pi's to talk to each other. Since you say each of them have a WiFi dongle, I assume you want to get them to communicate over the WiFi network. Even after making that assumption, there are still many ways to skin the cat, e.g. Use HTTP or MQTT, etc.

A lot of beginners find using Javascript and NodeJS easy. So if you are familiar with JavaScript, you could very easily host NodeJS HTTP servers on all your Raspberry Pis and have one master server control all of them over a simple RESTful interface. Every Pi has a unique IP address that can be used by the master server. Also if you prefer to use MQTT, you can still use NodeJS and modify the logic to use that instead of HTTP. Here is the NPM module for MQTT: https://www.npmjs.com/package/mqtt. But for now I am assuming you are okay with HTTP and my code examples below are for running it over HTTP:

Here is some example code for each of the slaves:

var express = require('express');
var app = express();

var start = function start() {
    console.log("process start...this is run within the event loop so try to make it snappy");
};

var stop = function stop() {
    console.log("process stop...this is run within the event loop so try to make it snappy");
};

app.get('/', function (req, res) {
        res.send('Hello World!');
    });

app.get('/start', function (req, res) {
        start();
        res.send('Start!');
    });

app.get('/stop', function(req, res) {
        stop();
        res.send('Stop!');
    });

app.listen(3000, function () {
        console.log('Example app listening on port 3000!');
    });

With the above code, you have a HTTP server listening on port 3000 and provides support for GET requests on 3 paths: '/', '/start', '/stop'.

Here is an example of master that you can use (you can modify this to connect to different IP addresses by simple code modifications). In the example below, the user has a command line interface to type "start", "stop", "home" and "exit" commands, and each of those result in a HTTP GET request to the server at IP address 10.0.1.5:

const request = require('request');
const readline = require('readline');

const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout
    });

var pendingRequests = [];

rl.on('line', function(cmd) {
        switch (cmd) {
        case "start":
            handleStart();
            break;
        case "stop":
            handleStop();
            break;
        case "home":
            handleHome();
            break;
        case "exit":
            handleExit();
            break;
        default:
            console.log("unknown command: " + cmd);
            break;
        };
    });

const handleExit = function handleExit() {
    var r;
    //abort all pending requests
    while(pendingRequests.length) {
        r = pendingRequests.pop();
        r.abort();
    }
    rl.close();
};

const handleHome = function handleHome() {
    var r = request('http://10.0.1.5:3000', function (error, response, body) {
            var index = pendingRequests.indexOf(r);
            if(index < 0) {
                console.log("Fatal Error: request not found in pendingRequests Array"); //this should never happen
                process.exit(1);
            } else {
                pendingRequests.splice(index, 1);
            }

            if (error) {
                console.log(error);
            }

            if (!error && response.statusCode == 200) {
                console.log(body) // Print the response
            }
        });
    pendingRequests.push(r);
};

const handleStart = function handleStart() {
    var r = request('http://10.0.1.5:3000/start', function (error, response, body) {
            var index = pendingRequests.indexOf(r);
            if(index < 0) {
                console.log("Fatal Error: request not found in pendingRequests Array"); //this should never happen
                process.exit(1);
            } else {
                pendingRequests.splice(index, 1);
            }

            if (error) {
                console.log(error);
            }

            if (!error && response.statusCode == 200) {
                console.log(body) // Print the response
            }
        });
    pendingRequests.push(r);
};

const handleStop = function handleStop() {
    var r = request('http://10.0.1.5:3000/stop', function (error, response, body) {
            var index = pendingRequests.indexOf(r);
            if(index < 0) {
                console.log("Fatal Error: request not found in pendingRequests Array"); //this should never happen
                process.exit(1);
            } else {
                pendingRequests.splice(index, 1);
            }

            if (error) {
                console.log(error);
            }

            if (!error && response.statusCode == 200) {
                console.log(body) // Print the response
            }
        });
    pendingRequests.push(r);
};

You can modify the boilerplate above and extend it as you please. You can download the code from my github repo here: https://github.com/ashishbajaj99/http-node-example

To install NodeJS, you can easily download NodeJS source code from here: https://nodejs.org/en/download/stable/ and compile the executable on Raspberry Pi. I've done that on my Pi - I am running a Raspbian Jessie image and had no trouble at all. There are some other alternatives - here are a couple of links: http://www.andrewconnell.com/blog/setup-node-js-on-raspberry-pi-2-b http://blog.wia.io/installing-node-js-v4-0-0-on-a-raspberry-pi/ https://stackoverflow.com/questions/32563173/installing-node-js-on-raspberry-pi-2

Let me know if you want to use MQTT or other alternatives and I can give you a detailed answer like above. Cheers.

Ashish
  • 109
  • 3
  • This isn't an answer to the question. You're describing your preferred method of HTTP based communication. The OP is asking how to connect wirelessly without relying on routers or an external network. – goldilocks Feb 03 '16 at 19:27
  • Yes he says he doesn't want to rely on external network, but I don't see him saying he doesn't want to rely on his home router. Given that he has WiFi dongles on each of his Rasp-Pi, he can use MQTT OR HTTP or any other IP protocol. I've clarified this in my answer and given the OP example code on how to use it as well! – Ashish Feb 04 '16 at 10:27
  • Ashish thank you for detailed explanation. I'm not sure if it's the correct terminology, but by saying "direct wireless connection" I meant a connection directly between two Raspberry Pis, without any other network host. I'm trying to setup a portable system and a home router dependent system wouldn't work outside. – dnzzcn Feb 04 '16 at 15:37
  • But, it's still possible to use your approach after setting up a raspberry pi to work as a router right? – dnzzcn Feb 04 '16 at 15:44
  • Okay so you want a peer to peer connection then? Irrespective, the suggested approach of HTTP would still continue to work. A couple of things to keep in mind though: first you eliminate the router by configuring the Rasp-pi in AP mode. @lwr20 provided this link that you can use: https://learn.adafruit.com/setting-up-a-raspberry-pi-as-a-wifi-access-point/overview. Then you just need to configure the Rasp-Pi router to perform DHCP reservations for all the other Rasp-Pi's in your network, that way at every boot up their IP address remains fixed. You can follow my approach from then on... – Ashish Feb 04 '16 at 16:24