JavascriptとPythonでリアルタイム通信

ブラウザとRaspberryPiの間でリアルタイム通信をする機会があったので紹介します。

具体的には、ブラウザからWebsocketを使ってリアルタイムに文字列をRaspberryPiのPythonプログラムに送る。
Python側は、接続中の複数のデバイスにその情報を送る。

というプログラムです。

実行環境

  • Chrome(ブラウザ)
  • RaspberryPi
  • Apache
  • Python3
  • JavaScript

今回はJavascriptとPythonのプログラムをいきなり書き始めるます。
予めRaspberryPiやApacheのセットアップは終わらせておいてください。

プログラム

クライアント(JavaScript)

ChromeやFirefoxなどのブラウザの場合すでにAPIが存在するので面倒なプログラムは全くいりません。

Websocket client

//Websocket
var uri = 'ws://接続先アドレス:ポート番号';

window.onload = function () {
    connection = new WebSocket(uri);
    connection.onopen = onOpen;
    connection.onmessage = onMessage;
}

function onOpen(event) {
    console.log("Connect successful!");
}

function onMessage(event) {
    //Incoming data
    console.log(event.data);
}

function websocketSend(data) {
    //Send data
    connection.send(data);
}

サーバ(Python)

こちらのプログラムもpipでライブラリをインストールしてしまえば面倒なプログラムは必要ないです。

まずはpip3でwebsocket_serverをインストールします。

pip3

pip3 install websocket_server

あとはプログラムです。

Websocket Server

from websocket_server import WebsocketServer

def new_client(client, server):
    server.send_message_to_all("New client has joined")

def send_msg_allclient(client, server, message):
    server.send_message_to_all(message)

server = WebsocketServer(ポート番号, host='起動するサーバのアドレス')
server.set_fn_new_client(new_client)
server.set_fn_message_received(send_msg_allclient)
server.run_forever()
MEMO
Raspi等で立ち上げる際は、起動するサーバのアドレスはRaspiのIPアドレスにしてください。

サンプルコード

PythonとJSのコードは紹介しましたが、JSのコードだけだと動かないので一応HTMLやCSSをつけたサンプルコードを載せておきます。

index.html

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Chat</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<script>
    var uri = 'ws://サーバのアドレス:9999';

    window.onload = function () {
        connection = new WebSocket(uri);
        connection.onopen = onOpen;
        connection.onmessage = onMessage;
    }

    function onOpen(event) {
        console.log("Connect successful!");
    }

    function onMessage(event) {
        //Incoming data
        console.log(event.data);
        addRow(event.data);
    }

    function websocketSend(data) {
        //Send data
        connection.send(data);
    }

    function prepareSend() {
        var form = document.forms.form;
        if (form.message.value != "") {
            websocketSend(form.message.value);
        }
    }

    function addRow(data){
        var table = document.getElementById("table");
        var a = document.createElement('a');
        var text = document.createTextNode(data);
        var br = document.createElement('br');
        a.appendChild(text);
        table.appendChild(a);
        table.appendChild(br);
        
    }
</script>

<style>
    #sendButton {

        margin: 10px;
        background-color: gray;
        color: white;
        height: 20px;
        width: 100px;

    }

    .table {
        height: 50px;
        width: 300px;
    }

</style>

<body>
    <center>
        <form name='form'>
            <input type="text" name="message">
        </form>
        <div id="sendButton" onclick="prepareSend()">SEND</div>
        <div id="table"></div>
    </center>
</body>

</html>

実行

ここまで一通り書き終わったら、実行してみてください。
正常に機能していればこのように実行されるはずです。

タブを複数開いたりしてもすべてのタブに文字が追加されるのが確認できると思います。

MEMO
サーバのアドレスの部分をWebsocketサーバのIPアドレスにしてあげるとローカルネットワーク上で動作させることができます。

JSONを送る

今回は文字列しか送りませんでしたが、JSONファイルを送ることも可能です。
Websocketで送るもしくは受け取った文字列に以下のJSONMakerやPerserをかませることで簡単にJSONとして送ることができるようになります。
基本的にサーバ側のコードは文字列をエコーするだけなので、変更する必要がありません。

json.js

function JSONMaker(strData) {
    var JSON_DATA = "";
    JSON_DATA = {
        data: strData,
    };
    return JSON.stringify(JSON_DATA)
}

function JSONPerser(JSON_DATA)
{
    json = JSON.parse(JSON_DATA);
    let strData = json.data;
    return strData;
}

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください