Connexion de l'application Web à IoT AWS

8

J'utilise Raspberry Pi comme serveur Web, ce site Web est destiné à contrôler la machine CNC, comme vous pouvez le voir sur l'image suivante.

Interface utilisateur du contrôleur CNC

(Je l'ai pris de git hub)

Je peux entrer le code g manuellement ou je peux télécharger le fichier de code g mais maintenant je veux connecter cette page Web à Amazon Web Services IoT pour envoyer automatiquement le code g à ma page, après une longue recherche, j'ai trouvé ce lien, il montre comment connecter une application web à AWS IOT, mais je pense que j'ai encore besoin d'aide pour ces choses car je ne comprends pas vraiment comment l'appliquer. Voici le fichier server.js:

var config = require('./config');
var serialport = require("serialport");
var SerialPort = serialport.SerialPort; // localize object constructor
var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs');
var static = require('node-static');
var EventEmitter = require('events').EventEmitter;
var url = require('url');
var qs = require('querystring');
var http = require('http');

// test for webcam
config.showWebCam = false;

http.get('http://127.0.0.1:8080', function(res) {
    // valid response, enable webcam
    console.log('enabling webcam');
    config.showWebCam = true;
}).on('socket', function(socket) {
    // 2 second timeout on this socket
    socket.setTimeout(2000);
    socket.on('timeout', function() {
        this.abort();
    });
}).on('error', function(e) {
    console.log('Got error: '+e.message+' not enabling webcam')
});

app.listen(config.webPort);
var fileServer = new static.Server('./i');

function handler (req, res) {

    //console.log(req.url);

    if (req.url.indexOf('/api/uploadGcode') == 0 && req.method == 'POST') {
        // this is a gcode upload, probably from jscut
        console.log('new data from jscut');
        var b = '';
        req.on('data', function (data) {
            b += data;
            if (b.length > 1e6) {
                req.connection.destroy();
            }
        });
        req.on('end', function() {
            var post = qs.parse(b);
            //console.log(post);
            io.sockets.emit('gcodeFromJscut', {'val':post.val});
            res.writeHead(200, {"Content-Type": "application/json"});
            res.end(JSON.stringify({'data':'ok'}));
        });
    } else {
        fileServer.serve(req, res, function (err, result) {
            if (err) console.log('fileServer error: ',err);
        });
    }
}

function ConvChar( str ) {
  c = {'<':'&lt;', '>':'&gt;', '&':'&amp;', '"':'&quot;', "'":'&#039;',
       '#':'&#035;' };
  return str.replace( /[<&>'"#]/g, function(s) { return c[s]; } );
}

var sp = [];
var allPorts = [];

serialport.list(function (err, ports) {

    // if on rPi - http://www.hobbytronics.co.uk/raspberry-pi-serial-port
    if (fs.existsSync('/dev/ttyAMA0') && config.usettyAMA0 == 1) {
        (ports = ports || []).push({comName:'/dev/ttyAMA0',manufacturer: undefined,pnpId: 'raspberryPi__GPIO'});
        console.log('adding /dev/ttyAMA0 because it is enabled in config.js, you may need to enable it in the os - http://www.hobbytronics.co.uk/raspberry-pi-serial-port');
    }

    allPorts = ports;

    for (var i=0; i<ports.length; i++) {
    !function outer(i){

        sp[i] = {};
        sp[i].port = ports[i].comName;
        sp[i].q = [];
        sp[i].qCurrentMax = 0;
        sp[i].lastSerialWrite = [];
        sp[i].lastSerialReadLine = '';
        // 1 means clear to send, 0 means waiting for response
        sp[i].handle = new SerialPort(ports[i].comName, {
            parser: serialport.parsers.readline("\n"),
            baudrate: config.serialBaudRate
        });
        sp[i].sockets = [];

        sp[i].handle.on("open", function() {

            console.log('connected to '+sp[i].port+' at '+config.serialBaudRate);

            // line from serial port
            sp[i].handle.on("data", function (data) {
                serialData(data, i);
            });

            // loop for status ?
            setInterval(function() {
                // console.log('writing ? to serial');
                sp[i].handle.write('?');
            }, 1000);

        });

    }(i)
    }

});

function emitToPortSockets(port, evt, obj) {
    for (var i=0; i<sp[port].sockets.length; i++) {
        sp[port].sockets[i].emit(evt, obj);
    }
}

function serialData(data, port) {

    // handle ?
    if (data.indexOf('<') == 0) {
        // https://github.com/grbl/grbl/wiki/Configuring-Grbl-v0.8#---current-status

        // remove first <
        var t = data.substr(1);

        // remove last >
        t = t.substr(0,t.length-2);

        // split on , and :
        t = t.split(/,|:/);

        emitToPortSockets(port, 'machineStatus', {'status':t[0], 'mpos':[t[2], t[3], t[4]], 'wpos':[t[6], t[7], t[8]]});

        return;
    }

    if (queuePause == 1) {
        // pause queue
        return;
    }

    data = ConvChar(data);

    if (data.indexOf('ok') == 0) {

        // ok is green
        emitToPortSockets(port, 'serialRead', {'line':'<span style="color: green;">RESP: '+data+'</span>'});

        // run another line from the q
        if (sp[port].q.length > 0) {
            // there are remaining lines in the q
            // write one
            sendFirstQ(port);
        }

        // remove first
        sp[port].lastSerialWrite.shift();

    } else if (data.indexOf('error') == 0) {

        // error is red
        emitToPortSockets(port, 'serialRead', {'line':'<span style="color: red;">RESP: '+data+'</span>'});

        // run another line from the q
        if (sp[port].q.length > 0) {
            // there are remaining lines in the q
            // write one
            sendFirstQ(port);
        }

        // remove first
        sp[port].lastSerialWrite.shift();

    } else {
        // other is grey
        emitToPortSockets(port, 'serialRead', {'line':'<span style="color: #888;">RESP: '+data+'</span>'});
    }

    if (sp[port].q.length == 0) {
        // reset max once queue is done
        sp[port].qCurrentMax = 0;
    }

    // update q status
    emitToPortSockets(port, 'qStatus', {'currentLength':sp[port].q.length, 'currentMax':sp[port].qCurrentMax});

    sp[port].lastSerialReadLine = data;

}

var currentSocketPort = {};

function sendFirstQ(port) {

    if (sp[port].q.length < 1) {
        // nothing to send
        return;
    }
    var t = sp[port].q.shift();

    // remove any comments after the command
    tt = t.split(';');
    t = tt[0];
    // trim it because we create the \n
    t = t.trim();
    if (t == '' || t.indexOf(';') == 0) {
        // this is a comment or blank line, go to next
        sendFirstQ(port);
        return;
    }
    //console.log('sending '+t+' ### '+sp[port].q.length+' current q length');

    // loop through all registered port clients
    for (var i=0; i<sp[port].sockets.length; i++) {
        sp[port].sockets[i].emit('serialRead', {'line':'<span style="color: black;">SEND: '+t+'</span>'+"\n"});
    }
    sp[port].handle.write(t+"\n")
    sp[port].lastSerialWrite.push(t);
}

var queuePause = 0;
io.sockets.on('connection', function (socket) {

    socket.emit('ports', allPorts);
    socket.emit('config', config);

    // do soft reset, this has it's own clear and direct function call
    socket.on('doReset', function (data) {
        // soft reset for grbl, send ctrl-x ascii \030
        sp[currentSocketPort[socket.id]].handle.write("\030");
        // reset vars
        sp[currentSocketPort[socket.id]].q = [];
        sp[currentSocketPort[socket.id]].qCurrentMax = 0;
        sp[currentSocketPort[socket.id]].lastSerialWrite = [];
        sp[currentSocketPort[socket.id]].lastSerialRealLine = '';
    });

    // lines from web ui
    socket.on('gcodeLine', function (data) {

        if (typeof currentSocketPort[socket.id] != 'undefined') {

            // valid serial port selected, safe to send
            // split newlines
            var nl = data.line.split("\n");
            // add to queue
            sp[currentSocketPort[socket.id]].q = sp[currentSocketPort[socket.id]].q.concat(nl);
            // add to qCurrentMax
            sp[currentSocketPort[socket.id]].qCurrentMax += nl.length;
            if (sp[currentSocketPort[socket.id]].q.length == nl.length) {
                // there was no previous q so write a line
                sendFirstQ(currentSocketPort[socket.id]);
            }

        } else {
            socket.emit('serverError', 'you must select a serial port');
        }

    });

    socket.on('clearQ', function(data) {
        // clear the command queue
        sp[currentSocketPort[socket.id]].q = [];
        // update the status
        emitToPortSockets(currentSocketPort[socket.id], 'qStatus', {'currentLength':0, 'currentMax':0});
    });

    socket.on('pause', function(data) {
        // pause queue
        if (data == 1) {
            console.log('pausing queue');
            queuePause = 1;
        } else {
            console.log('unpausing queue');
            queuePause = 0;
            sendFirstQ(currentSocketPort[socket.id]);
        }
    });

    socket.on('disconnect', function() {

        if (typeof currentSocketPort[socket.id] != 'undefined') {
            for (var c=0; c<sp[currentSocketPort[socket.id]].sockets.length; c++) {
                if (sp[currentSocketPort[socket.id]].sockets[c].id == socket.id) {
                    // remove old
                    sp[currentSocketPort[socket.id]].sockets.splice(c,1);
                }
            }
        }

    });

    socket.on('usePort', function (data) {

        console.log('user wants to use port '+data);
        console.log('switching from '+currentSocketPort[socket.id]);

        if (typeof currentSocketPort[socket.id] != 'undefined') {
            for (var c=0; c<sp[currentSocketPort[socket.id]].sockets.length; c++) {
                if (sp[currentSocketPort[socket.id]].sockets[c].id == socket.id) {
                    // remove old
                    sp[currentSocketPort[socket.id]].sockets.splice(c,1);
                }
            }
        }

        if (typeof sp[data] != 'undefined') {
            currentSocketPort[socket.id] = data;
            sp[data].sockets.push(socket);
        } else {
            socket.emit('serverError', 'that serial port does not exist');
        }

    });

});
Balsam Qassem
la source
Voulez-vous envoyer une valeur g vers ou depuis aws?
mico
non, je veux envoyer le code g à la page Web (lorsque l'objet arrive à la machine cnc, le capteur détectera cet objet donc il suppose d'envoyer le code g à ma page Web
Balsam Qassem
Quel est votre défi particulier à ce sujet? Solution globale ou une partie bien définie qui a besoin de clarification?
mico
1
Continuons cette discussion dans le chat .
mico
1
Après une longue recherche, j'ai trouvé ce lien, il montre comment connecter une application Web à AWS IOT, mais je pense que j'ai encore besoin d'aide pour ces choses car je ne comprends pas vraiment comment l'appliquer.
Balsam Qassem

Réponses:

6

Ce que vous avez lié est beaucoup trop compliqué et à un niveau d'abstraction trop faible pour un professionnel, même difficile à lire et à suivre.

aws-mqtt-client via npm est la solution la plus simple que j'ai pu trouver. Il vous suffit d'installer npm et de rendre le service aws et le code client assez simples:

const mqttClient = new AWSMqtt({
    accessKeyId: AWS_ACCESS_KEY,
    secretAccessKey: AWS_SECRET_ACCESS_KEY,
    sessionToken: AWS_SESSION_TOKEN,
    endpointAddress: AWS_IOT_ENDPOINT_HOST,
    region: 'us-east-1'
});

Vous y remplissez des valeurs correctes et publiez les données de votre machine comme ceci:

mqttClient.publish(MQTT_TOPIC, message);

Et sur le site qui a besoin des données que vous obtenez:

mqttClient.on('connect', () => {
    mqttClient.subscribe('test-topic');
    console.log('connected to iot mqtt websocket');
});
mqttClient.on('message', (topic, message) => {
    console.log(message.toString());
});

Plus d'informations:

https://www.npmjs.com/package/aws-mqtt-client

https://www.npmjs.com/get-npm

https://aws.amazon.com/iot-platform/getting-started/

mico
la source
OK, et si je veux publier sur le logiciel d'expéditeur universel de morue g sur mon ordinateur portable où la machine cnc se connecte, dois-je utiliser npm mqtt aussi @mico merci beaucoup pour votre aide
Balsam Qassem
Vous devriez peut-être poster une nouvelle question à ce sujet avec plus de détails. Je pense aussi à REST comme une option, si les données ne changent pas à temps. Avec ces spécifications, je ne peux pas dire quel est le cas.
mico
je pense que j'utiliserai linuxcnc parce que j'ai trouvé ce youtube.com/watch?v=jmKUV3aNLjk&t=215s , ce que vous pensez @mico
Balsam Qassem
Dans le nœud vidéo, le rouge est utilisé pour obtenir des données de linuxcnc. C'est un outil graphique pour connecter des pièces IoT, alors n'hésitez pas à l'utiliser, il devrait être facile à utiliser une fois installé.
mico