无法在移动设备上打开websocket

时间:2016-12-09 04:46:17

标签: python websocket raspberry-pi

我正在尝试设置一个在我的覆盆子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>

2 个答案:

答案 0 :(得分:1)

添加了一些额外代码

我建议使用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&amp;&amp; sudo apt-get remove nodejs nodejs-legacy&amp;&amp;   curl -sL https://deb.nodesource.com/setup_4.x | sudo bash - &amp;&amp;须藤   apt-get install -y nodejs

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

  

cd / home / pi / server /

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

  

sudo npm install express&amp;&amp; sudo npm安装http&amp;&amp; sudo npm install path&amp;&amp;   sudo npm install socket.io&amp;&amp; sudo npm install serialport --unsafe-perm&amp;&amp;   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 node /home/pi/server/server.js&'使用'sudo nano'编辑器在'exit 0'之前'/etc/rc.local'。

它可以在任何设备上运行良好。

答案 1 :(得分:0)

要使设备的主机名跨网络工作,设备必须公布自己的主机名,或者只响应DNS查询以获取自己的主机名。

无论Raspberry Pi使用什么实现,您的笔记本电脑都支持它,但您的手机却不支持。

因此,为了能够连接,您需要在JavaScript代码中将主机名raspberrypi-mike更改为Raspberry Pi的IP地址。