WebアプリをIoT AWSに接続する


8

Raspberry PiをWebサーバーとして使用しています。このWebは、次の図に示すようにCNCマシンを制御するためのものです。

CNCコントローラーUI

(私はそれをgitハブから取得しました)

私は手動でGコードを入力することができますか私は、Gコードファイルをアップロードすることができますが、今、私は私のページに自動的にGコードを送信するためにAmazon WebサービスのIoTにこのWebページを接続したい、長い検索の後、私は、この見つかったリンクを、それがどのように示していWeb IOTをAWS IOTに接続しますが、適用方法が本当にわからないので、それらの問題についてはまだサポートが必要だと思います。ここに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');
        }

    });

});

awとの間でg値を送信しますか?
mico

いいえ、gコードをWebページに送信します(オブジェクトがcncマシンに来ると、センサーがそのオブジェクトを感知するため、gコードを私のWebページに送信するとします
Balsam Qassem

それに対するあなたの特定の挑戦は何ですか?全体的な解決策、または明確化が必要な明確に定義された部分?
mico 2017


1
長い検索の結果、このリンクが見つかりました。これは、WebアプリをAWS IOTに接続する方法を示していますが、それを適用する方法が本当にわからないので、これらのことについてはまだサポートが必要だと思います。
Balsam Qassem 2017

回答:


6

あなたがリンクしたものは、あまりに複雑で、抽象化のレベルが低すぎるため、専門家がそれを読んで理解するのがさらに困難です。

nwsを介したaws-mqtt-clientは、私が見つけた最も簡単なソリューションです。npmをインストールして、awsサービスとクライアントコードを単純にするだけです。

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'
});

そこで正しい値を入力し、次のようにマシンからデータを公開します。

mqttClient.publish(MQTT_TOPIC, message);

そして、あなたがそれを得るデータを必要とするサイトで:

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

より詳しい情報:

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

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

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


OK、cncマシンが接続しているラップトップ上のユニバーサルg cod送信者ソフトウェアに公開したい場合、npm mqttも使用しますか@micoどうもありがとう
Balsam Qassem

たぶん、あなたはそれについてより詳細に新しい質問を投稿するべきです。データが時間とともに変化しない場合は、RESTもオプションとして考えます。上記の仕様では、どちらが正しいのかはわかりません。
mico 2017

私はこのyoutube.com/watch?v=jmKUV3aNLjk&t=215sを見つけたので、linuxcncを使用すると思います。@ micoとはどう思いますか
Balsam Qassem

ビデオノードでは、linuxcncからデータを取得するために赤が使用されています。これはIoTパーツを接続するためのグラフィカルツールであるため、自由に使用してください。インストールしたら、簡単に使用できるはずです。
mico 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.