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