python - 无法在移动设备上打开 websocket

标签 python websocket raspberry-pi

我正在尝试设置一个 websocket,并在我的树莓派上运行服务器。以下代码是根据我发现的示例稍微修改的 here .

我围绕这个示例构建了一个完整的网页,允许我控制 gpio 并向插入 pi 的串行设备发送消息。该网站和此示例都可以在我的笔记本电脑上完美运行(使用 Chrome 或 Firefox 的 Windows 10)。

但是,当我从手机(Android 5.0.1,使用 Chrome for android)连接时。它似乎永远不会打开套接字。在示例代码中,它仅显示“消息转到此处。

我的第一个想法是 android 上的 chrome 不支持 websockets,但我能够连接并回显此网站上的消息 http://www.websocket.org/echo.html 。所以看来该功能已经存在。

还有什么会阻止套接字打开?

pysocket.py

import tornado.httpserver
import tornado.websocket
import tornado.ioloop
import tornado.web

class WSHandler(tornado.websocket.WebSocketHandler):

  def check_origin(self, origin):
    return True

  def open(self):
    print 'New connection was opened'
    self.write_message("Welcome to my websocket!")

  def on_message(self, message):
    print 'Incoming message:', message
    self.write_message("You said: " + message)

  def on_close(self):
    print 'Connection was closed...'

application = tornado.web.Application([
  (r'/ws', WSHandler),
])

if __name__ == "__main__":
  http_server = tornado.httpserver.HTTPServer(application)
  http_server.listen(8888)
  tornado.ioloop.IOLoop.instance().start()

pysocket.php

<!doctype html>
<html>
  <head>
    <title>WebSockets with Python & Tornado</title>
    <meta charset="utf-8" />
    <style type="text/css">
      body {
        text-align: center;
        min-width: 500px;
      }
    </style>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script>
      $(function(){
        var ws;
        var logger = function(msg){
          var now = new Date();
          var sec = now.getSeconds();
          var min = now.getMinutes();
          var hr = now.getHours();
          $("#log").html($("#log").html() + "<br/>" + hr + ":" + min + ":" + sec + " ___ " +  msg);
          //$("#log").animate({ scrollTop: $('#log')[0].scrollHeight}, 100);
          $('#log').scrollTop($('#log')[0].scrollHeight);
        }

        var sender = function() {
          var msg = $("#msg").val();
          if (msg.length > 0)
            ws.send(msg);
          $("#msg").val(msg);
        }

        ws = new WebSocket("ws://raspberrypi-mike:8888/ws");
        ws.onmessage = function(evt) {

          logger(evt.data);
        };
        ws.onclose = function(evt) { 
          $("#log").text("Connection was closed..."); 
          $("#thebutton #msg").prop('disabled', true);
        };
        ws.onopen = function(evt) { $("#log").text("Opening socket..."); };

        $("#msg").keypress(function(event) {
          if (event.which == 13) {
             sender();
           }
        });

        $("#thebutton").click(function(){
          sender();
        });
      });
    </script>
  </head>

  <body>
    <h1>WebSockets with Python & Tornado</h1>
    <div id="log" style="overflow:scroll;width:500px; height:200px;background-color:#ffeeaa; margin:auto; text-align:left">Messages go here</div>

    <div style="margin:10px">
      <input type="text" id="msg" style="background:#fff;width:200px"/>
      <input type="button" id="thebutton" value="Send" />
    </div>

    <a href="http://lowpowerlab.com/blog/2013/01/17/raspberrypi-websockets-with-python-tornado/">www.LowPowerLab.com</a>
  </body>
</html>

最佳答案

添加了一些额外代码

我建议使用node.js:

var express = require("express");
var app = express();
var http = require("http").Server(app);
var path = require("path");
var io = require('socket.io')(http);
var SerialPort = require('serialport');
var gpio = require('rpio');

http.listen(3000);

var serialPort = new SerialPort.SerialPort("/dev/ttyAMA0", {
    baudrate: 115200,
    dataBits: 8,
    parity: "none",
    stopBits: 1,
    flowControl: false
});

io.on('connection', function(socket){
    console.log('Connected');
    socket.on("WriteSerial:get",function(data){
            var hex = new Buffer (data, "hex"); //be careful passing data
            writeSerial(serialPort, hex);
            io.emit("WriteSerial:response", "Data writen!");
    });
    socket.on("ReadGPIO:get",function(data){
            var input = readPin(data.pin); 
            io.emit("ReadGPIO:response", input); 
    }); 
    socket.on("WriteGPIO:get",function(data){
            writePin(data.pin, data.time); 
            io.emit("WriteGPIO:response", "Set!"); 
    }); 
    socket.on("unWriteGPIO:get",function(data){
            unwritePin(data); 
            io.emit("unWriteGPIO:response", "Set!"); 
    });        
}
app.use(express.static(path.join(__dirname, '/')));
app.get("/home",function(req,res,next){
    res.sendFile(path.join(__dirname + "/index.html"));
});

function writeSerial (port, data)   {
    port.write(data, function(err) {
        if (err) {
            return console.log('Error on write: ', err.message);
        } else {
            console.log('Data written: ' + data);
        }
    });
}

function readPin(pin){
    rpio.open(pin, rpio.INPUT);
    var read = rpio.read(pin) ? 'high' : 'low';
    return read;
}

function writePin(pin, timeInMs){
    rpio.open(pin, rpio.OUTPUT, rpio.LOW);
    rpio.write(pin, rpio.HIGH);
    if (timeInMs > 0) {
        setTimeout(function(){
            rpio.write(pin, rpio.LOW); 
        }, timeInMs);
    } //You can put 0 if You want it to be high until You shut it down 
}

function unWritePin(pin){
    if(readPin(pin) === 'high') {
        rpio.write(pin, rpio.LOW);
    } else {
        console.log("Pin already low!");
    }
}

确保您已经安装了正确版本的node.js。如果不在终端中执行此操作:

sudo apt-get remove nodered && sudo apt-get remove nodejs nodejs-legacy && curl -sL https://deb.nodesource.com/setup_4.x | sudo bash - && sudo apt-get install -y nodejs

在“/home/pi/”中创建一个文件夹“server”,将server.js添加到其中。将我提供的代码添加到 server.js。使用终端打开该文件夹:

cd /home/pi/server/

之后安装服务器上使用的所有模块:

sudo npm install express && sudo npm install http && sudo npm install path && sudo npm install socket.io && sudo npm install serialport --unsafe-perm && sudo npm install rpio --unsafe-perm

现在我们要做的就是创建客户端部分。在文件夹“/home/pi/server”中创建index.html 文件并添加名为“js”的文件夹。在文件夹“js”中添加客户端的socket.io.js,您可以在文件夹“/home/pi/server/node_modules/socket.io/node_modules/socket.io-client/”中找到它 .

将客户端的 socket.io.js 包含到您的 index.html 中,如下所示:

<script type="text/javascript" src="js/socket.io.js" /></script>

还将 main.js 文件添加到“js”文件夹中,您将在其中放置 javascript 代码并将其包含到 index.html 中:

<script type="text/javascript" src="js/main.js" /></script>
<script type="text/javascript" src="js/jquery.js" /></script>

我不会制作任何图形,但这里有一些 main.js 代码:

$(document).ready(function() {
    var socket = io.connect('http://your_ip_address_rpi:3000');

    $( "#myButton" ).click(function(){
        io.emit("WriteSerial:get", $("#myTextHolder").val()); //"FAAF531C" this is string of hex, should be added some filter to pass error when char is not part of HEX!
    });
    $( "#myButton2" ).click(function(){
        io.emit("WriteGPIO:get", {"pin" : $("#myPinHolder").val(), "time" : $("#myTimeHolder").val()})

}

要在 RPI 启动时运行服务器,请使用“sudo nano”编辑器将“sudo node/home/pi/server/server.js &”添加到“/etc/rc.local”中“exit 0”之前。

它在任何设备上都能很好地工作。

关于python - 无法在移动设备上打开 websocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41053285/

相关文章:

websocket - 如何在 celery 中为 Tornado 中的 websocket 请求启动任务?

Python 请求 'Connection aborted.' 如果它将以 cronjob 开始

python - Matplotlib 没有给出错误,但没有绘制任何内容

python - 比较python中的时间增量

ssl - 带 SSL 的 WebSocket

flutter - 在 Flutter 应用程序中使用 Charles 代理检查 WebSocket 包

python - 用于 chrome 打包应用程序中客户端/服务器通信的 Websockets

Python URLLib/URLLib2 POST

linux - 从 RaspberryPi3 上的 U-boot 获取 SD 卡序列号/oemid

python - 我尝试在我的树莓派上导入数据库,但它不起作用