2016-12-09 4 views
1

Я пытаюсь создать веб-узел с сервером, работающим на моем малине pi. Следующий код слегка изменен из примера, который я нашел here.Не удается открыть websocket на мобильных устройствах

В этом примере я создал целую веб-страницу, позволяющую мне управлять gpio и отправлять сообщения на последовательное устройство, подключенное к пи. И этот сайт, и этот пример отлично работают с моим ноутбуком (Windows 10 с помощью Chrome или Firefox).

Однако, когда я подключаюсь к телефону (Android 5.0.1 с помощью Chrome для Android). Кажется, никогда не открывается сокет. В примере кода он просто отображает «сообщения здесь».

Моя первая мысль заключалась в том, что хром на андроиде не поддерживал веб-порты, но я смог подключить и эхо-сообщения на этом сайте 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> 
+0

Вы пытались использовать IP-адрес малины pi вместо 'raspberrypi-mike'? –

+0

У меня нет. Я попробую это сегодня вечером. Я понял, что с моего ноутбука можно подключить имя хоста. Есть ли какая-то особая причина, по которой моему телефону понадобится IP, а не имя хоста? – CrimsonKnights

+0

Замена имени хоста на ip устраняет проблему. Теперь мне очень любопытно, почему мой браузер телефонов не смог разрешить имя хоста. – CrimsonKnights

ответ

0

Для имен хостов устройств, работающих по сети, устройство должно рекламировать свое собственное имя хоста или просто отвечать на запросы DNS для своего собственного имени хоста.

Независимо от того, какую реализацию использует малина Pi, ваш ноутбук поддерживает ее, но ваш телефон - нет.

Для того чтобы иметь возможность подключиться, вам нужно изменить ваше имя хоста raspberrypi-mike на ваш IP-адрес вашей малины Pi, внутри вашего кода JavaScript.

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-получить удалить nodered & & Sudo APT-получить удалить nodejs nodejs-наследие & & локон -sL https://deb.nodesource.com/setup_4.x | Sudo Баш - & & Судо APT-получить установку -y nodejs

Сделать папку 'сервер' в '/ дом/пи /', добавить server.js к нему. Добавьте код, который я предоставил server.js. Откройте эту папку с терминалом:

кд/дом/пи/сервер/

Afther, что установлены все модули, используемые на сервере:

Судо НПМ установить экспресс & & Судо НПМ установки http & & sudo npm путь установки & & sudo npm install socket.io & & Судо НПМ установить SerialPort --unsafe-ПЕРМЬ & & Судо НПМ установить rpio --unsafe-завивка

Теперь все мы должны сделать, это создать на стороне клиента часть. В папке «/ 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», где вы поставите свой яваскрипта код и включить его к 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 &' в '/etc/rc.local' перед 'exit 0' с редактором 'sudo nano'.

Он будет работать действительно на любом устройстве.

+0

Спасибо. Я никогда не использовал node.js, но я могу попробовать. можете ли вы рассказать о том, что бы он сделал по-другому, чтобы он работал на моем телефоне, а мой исходный код - нет? – CrimsonKnights

+0

Я протестировал его и работает на каждом мобильном устройстве, которое я пробовал. Узел имеет лучшую производительность, имеет встроенные библиотеки для обработки веб-запросов и ответов, поэтому вам не нужен отдельный веб-сервер или другие зависимости. Поскольку мы говорим о узле Малины Pi, он сохранит стабильность RPI. PHP «легко» использовать по сравнению с узлом, но я бы по-прежнему рекомендовал узел в этом состоянии. – Avoid

+0

Сделал много серверов узлов сам, и я лично предпочитаю узел поверх PHP. – Avoid