Вот мои настройки:
Raspberry Pi 2 (192.168.1.101):
- Датчик записи температуры, давления и влажности.
- Скрипт Python3, подключенный к Raspberry Pi 3, считывающий данные датчика и отправляющий в Pi 3 в формате JSON каждые 5 секунд.
Raspberry Pi 3 (192.168.1.100):
- Сервер Node.js прослушивает клиент Python через порт 8888.
- Socket.io прослушивает веб-клиентов через порт 3000 (порты 3000 и 80 открыты на моем маршрутизаторе).
- Веб-сервер (на порте 80) с веб-сайтом, отображающим данные датчика.
- Соединение JavaScript с сервером узла, используя socket.io, через foobar.ddns.net:3000.
Разное:
- Я использую noip.com, чтобы иметь домен, обслуживающий мой динамический IP-адрес. Мой маршрутизатор сообщает noip, когда меняется мой публичный IP-адрес. У меня есть URL, который выглядит как foobar.ddns.net.
Эта настройка, кажется, работает. Сценарий Python отправляет данные на сервер узла, который передает их любому подключенному веб-клиенту, который правильно отображается на веб-сайте.
Моя проблема заключается в том, что веб-клиент отключается после 1 раунда пинг-понга между клиентом и сервером узла.
Вот журнал консоли chrome при подключении к серверу и получении данных:
Веб-клиент подключается, получает некоторые данные, выполняет пинг / понг с сервером, получает еще некоторые данные, затем, когда он снова должен пинг / понг, он отключается, затем через некоторое время пытается восстановить соединение, и цикл продолжается.
А вот журнал node.js:
Первое Новое соединение - это клиент Python (я не уверен, почему IP является адресом Pi3), остальные - это тот же веб-клиент, который подключается, отключается на время ожидания ping, а затем повторно подключается. Кажется, что клиент отключается на основе значений pingInterval + pingTimeout серверов.
Изменение значений pingTimeout и pingInterval просто задерживает отключение.
Вот мой код:
Клиент Python:
import json
import socket
import bme280_sensor
import time
import os
class Connection():
def __init__(self, host, port):
self.host = host
self.port = port
def connect(self):
print('Creating socket')
try:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error as msg:
print('Failed to create socket: %s' % msg)
raise
print('Socket created')
server_address = (self.host, self.port)
print('Connecting to %s:%s' % server_address)
try:
self.sock.connect(server_address)
except socket.error as msg:
print('Failed to connect: %s' % msg)
raise
print('Connected')
def shutdown(self):
print('Shutting down')
self.sock.shutdown(socket.SHUT_RDWR)
self.sock.close()
def measure_temp():
bme_data = bme280_sensor.read_all()
obj = {}
obj['temp'] = round(bme_data[2], 2)
obj['humidity'] = round(bme_data[0], 2)
obj['pressure'] = round(bme_data[1], 2)
return json.dumps(obj)
def sendData(sock):
print('Sending data')
while True:
try:
data = 'data,' + measure_temp()
sock.sendall(data.encode())
except socket.error as msg:
print("Cannot send to server: %s" % msg)
break
time.sleep(5)
connection = Connection('192.168.1.100', 8888)
while True:
try:
connection.connect()
sendData(connection.sock)
connection.shutdown()
break
except socket.error as msg:
print('Connection failed, retrying in 3 seconds.')
time.sleep(3)
print('Done')
Node.js Сервер:
var net = require('net');
var port = 8888;
var server = net.createServer();
// socket io listens for clients on port 3000
var io = require('socket.io')(3000,{
pingInterval: 10000,
pingTimeout: 5000,
});
// server listens for python client on port 8888
server.listen(port);
console.log('Server started');
// store the last data recorded, so when a socket.io client connects, they can get the last reading instead of waiting for the next one
global.last;
server.on('connection', function(socket){
console.log('New server connection ' + socket.address().address);
// when the server recieves data, send it to the connected socket clients
socket.on('data', function(data){
// strip the first 5 characters from the input string, parse json from the result
var actual = generateJSON(data.toString().substring(5));
// store the dta
global.last = actual;
//send the data
io.sockets.emit('data', actual);
});
});
io.on('connection', function(socket){
console.log('New io connection ' + socket.id);
// if the server has data previously recorded, send it to the new client
if(global.last){
io.emit('data', global.last);
}
socket.on('disconnect', function(reason){
console.log('io disconnect: ' + reason);
});
});
function generateJSON(data){
var dataJSON = JSON.parse(data);
var obj = new Object();
obj.temperature = dataJSON.temp;
obj.humidity = dataJSON.humidity;
obj.pressure = dataJSON.pressure;
obj.datetime = new Date().toString();
return JSON.stringify(obj);
}
Сайт Javascript:
var socket;
var connected = false;
function connect(){
console.log('connecting...')
if(socket){
socket.destroy()
delete socket;
socket = null;
}
socket = io.connect("http://foobar.ddns.net:3000", {
forceNew: true,
reconnection: true,
reconnectionDelay: 3000,
reconnectionDelayMax: 5000,
reconnectionAttempts: Infinity
});
console.log(socket);
socket.on("data", function(data){
var obj = JSON.parse(data);
console.log(data);
$('#temperature-value').text(obj.temperature);
$('#humidity-value').text(obj.humidity);
$('#pressure-value').text(obj.pressure);
lastUpdate = new Date();
});
socket.on('connect_error', function(error){
console.log('connection error: ' + error);
});
socket.on('connect_timeout', function(){
console.log('connection timeout');
});
socket.on('reconnect', function(){
console.log('reconnect');
});
socket.on('reconnect_attempt', function(){
console.log('reconnect attempt');
});
socket.on('reconnect_failed', function(){
console.log('reconnect_failed');
});
socket.on('reconnect_error', function(){
console.log('reconnect_error');
});
socket.on('reconnecting', function(){
console.log('reconnecting');
});
socket.on('ping', function(){
console.log('ping');
});
socket.on('pong', function(ms){
console.log('pong ' + ms + "ms");
});
socket.on('connect', function(){
console.log('connected to server');
connected = true;
});
socket.on('disconnect', function(reason){
console.log('disconnected from server: ' + reason);
connected = false;
});
}
$(document).ready(function(){
connect();
});
Я обращаюсь к сценарию socket.io.js с этим в моем index.html:
<script src="http://foobar.ddns.net:3000/socket.io/socket.io.js"></script>
Это функционально, но разъединения довольно раздражающие, я бы предпочел, чтобы клиент оставался на связи. У меня такое ощущение, что мой сервер node.js настроен неправильно, но я не могу понять, в чем проблема. Если есть лучший способ подачи данных из скрипта python> сервер node.js> веб-клиентов, пожалуйста, сообщите мне.
Спасибо