通过 Pi 与 python 之间的套接字通信 (TCP/IP) 发送传感器数据
Send sensor data over socket communication (TCP/IP) between Pi's with python
大家好,
我对某些套接字通信编码有疑问。我有两个 pi 通过 TCP/IP 与 python 脚本进行通信。这个想法是一个 pi(客户端)读取 temperature/humidity 传感器数据并将其发送到另一个 pi(服务器),它将存储在 SQLite 数据库中。将来我希望多个 pi(客户端)将传感器数据发送到一个带有数据库的(网络)服务器,以在本地网站上显示数据。
我已经为服务器端和客户端编写了一些 python 代码,并且运行良好。如果我启动服务器端,它将监听其他连接。当我启动客户端时,它将生成传感器数据并将其发送到服务器。服务器接收数据。但是当我想关闭连接以为(未来的其他 pi)腾出空间时,它会完全终止脚本并且不监听新的 "calls"。双方请参见下面的代码。代码写在Python2.7。
这个项目的目标:在一个动物园设置监控和记录多个展品和水族馆的温度和湿度,在每个展品的 LCD 上显示信息,使用 LED 作为警告,并有一个 store/log 数据的中央服务器,用中央计算机显示。
RaspiServer - 服务器端
import socket
from LED import callLED
host = ''
port = 5560
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
except socket.error as msg:
print(msg)
print("Socket bind complete.")
return s
def setupConnection():
s.listen(1)
conn, address = s.accept()
print("Connected to: " + address[0] + ":" + str(address[1]))
return conn
def dataTransfer(conn):
while True:
data = conn.recv(1024)
data = data.decode('utf-8')
dataMessage = data.split(":", 2)
command = dataMessage[0]
humidity = dataMessage[1]
temperature = dataMessage[2]
if command == 'DATA':
print("Received: " + humidity + " : " + temperature)
callLED()
elif command == 'EXIT':
print("Disconnected with Client")
break
else:
reply = 'Unknow Command'
conn.sendall(str.encode(reply))
Print("Reply has been send.")
conn.close()
s = setupServer()
while True:
try:
conn = setupConnection()
dataTransfer(conn)
except:
break
在客户端有三个 python 脚本,其中主要的 python 脚本与其他脚本进行通信。我决定将它拆分成多个脚本,以便将它们也用作独立的(闪烁的 LED、在 LCD 上显示数据等)。
RaspiMonitor - 客户端
Run this script on client-side
from time import sleep
from client_sensordata import GetTemp
from monitor_client import transmit
sleepTime = 20
def tempMonitorServer():
humidity, temperature = GetTemp()
temp = str(temperature)
hum = str(humidity)
message = "DATA:" + hum + ":" + temp
print("Transmitting Data.")
response = transmit(message)
print(response)
while True:
tempMonitorServer()
sleep(sleepTime)
Use this script to send and receive data over TCP/IP
import socket
host = '192.168.2.3'
port = 5560
def setupSocket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
return s
def sendReceive(s, message):
s.send(str.encode(message))
print("Message transmitted")
reply = s.recv(1024)
print("We have received a reply.")
print("Send closing message.")
s.send(str.encode("EXIT"))
s.close()
reply = reply.decode('utf-8')
return reply
def transmit(message):
s = setupSocket()
response = sendReceive(s, message)
return response
Use this script to retrieve sensor data
def GetReading():
import sys
import Adafruit_DHT
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 17)
if humidity is not None and temperature is not None:
print('Reading sensor data')
return humidity, temperature
else:
print('no sensor data')
def GetTemp():
humidity, temperature = GetReading()
name = "DHT22Client1"
print('Read sensor: {0} humidity: {1:0.2f}% temperature: {2:0.2f}C'.format(name, humidity, temperature))
return humidity, temperature
终端输出
Terminal output, left server and right the client
任何人都可以提供一些提示或帮助,或者告诉我为什么如何解决这个问题吗?我已经搜索了多个线程和其他帖子,但找不到解决方案。
在此先感谢您提供的所有帮助。
您的服务器套接字设置可能有一些错误。服务器套接字的工作方式是它应该始终打开侦听新连接。当您接受来自客户端 (s.accept) 的连接时,它会创建到客户端的连接。如果关闭该连接,它应该不会影响服务器监听传入的套接字,客户端或连接到客户端的数量仅受您在服务器中指定的数量限制 socket.listen(NUMBER)。当达到该数量时,传入连接将被拒绝。
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print(msg)
print("Socket bind complete.")
return s
然后从设置连接中删除 s.listen
我还建议您在新线程中处理数据传输(),以便能够同时处理传入连接而不是连续处理。
与其反复关闭和打开新的套接字,不如在服务器端维护多个打开的套接字连接,并使用 select() 方法处理每个套接字。
https://docs.python.org/2/library/select.html
Can a server handle multiple sockets in a single thread?
目前可用的代码(仍在建设中以添加更多功能)是:
服务器端
import socket
import sys
from LED import callLED
from monitor_log3 import ExtractStoreData
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('', 5560)
print >>sys.stderr, 'Starting up on %s port %s' % server_address
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
while True:
# Wait for a connection
print >>sys.stderr, 'Waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'Connection from', client_address
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(1024)
data = data.decode('utf-8')
message = data
if data:
print >>sys.stderr, 'Send data receive confirmation'
connection.sendall(data)
callLED()
ExtractStoreData(message)
else:
print >>sys.stderr, 'No more data from', client_address
break
finally:
# Clean up the connection
print >>sys.stderr, 'Closing connection'
print >>sys.stderr, '------------------'
connection.close()
客户端看起来像这样:
客户端
import socket
import sys
import datetime
from time import sleep
from client_sensordata import GetTemp
timeSleep = 10
def ClientSocket():
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = ('192.168.2.3', 5560)
print >>sys.stderr, 'Connecting to: %s port: %s' % server_address
sock.connect(server_address)
try:
# Send data
name, humidity, temperature = GetTemp()
Sensorname = str(name)
temp = str(temperature)
hum = str(humidity)
print(Sensorname + ":" + temp + ":" + hum)
message = (Sensorname + ":" + temp + ":" + hum)
print("Transmitting data...")
print >>sys.stderr, 'Sending data...'
sock.send(str.encode(message))
# Look for the response
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(1024)
amount_received += len(data)
print >>sys.stderr, 'Send data'
finally:
print >>sys.stderr, 'Closing connection'
print >>sys.stderr, '------------------'
sock.close()
while True:
print("Start external server measurement at " + datetime.datetime.now().strftime("%H:%M:%S"))
ClientSocket()
sleep(timeSleep)
for t2 in range(5):
print("Start internal display measurement at " + datetime.datetime.now().strftime("%H:%M:%S"))
GetTemp()
print("------------------")
sleep(timeSleep)
它正在循环5个循环进行内部测量(在LCD显示器上),然后将数据发送一次到服务器,服务器将把它存储在数据库(SQlite3)中。仍然想添加更多功能(读取时 LED,低于或超过限制时警告 LED,警报声,连接 LCD。当有进展时我会更新代码。
当然欢迎任何提示和建议!
大家好,
我对某些套接字通信编码有疑问。我有两个 pi 通过 TCP/IP 与 python 脚本进行通信。这个想法是一个 pi(客户端)读取 temperature/humidity 传感器数据并将其发送到另一个 pi(服务器),它将存储在 SQLite 数据库中。将来我希望多个 pi(客户端)将传感器数据发送到一个带有数据库的(网络)服务器,以在本地网站上显示数据。
我已经为服务器端和客户端编写了一些 python 代码,并且运行良好。如果我启动服务器端,它将监听其他连接。当我启动客户端时,它将生成传感器数据并将其发送到服务器。服务器接收数据。但是当我想关闭连接以为(未来的其他 pi)腾出空间时,它会完全终止脚本并且不监听新的 "calls"。双方请参见下面的代码。代码写在Python2.7。
这个项目的目标:在一个动物园设置监控和记录多个展品和水族馆的温度和湿度,在每个展品的 LCD 上显示信息,使用 LED 作为警告,并有一个 store/log 数据的中央服务器,用中央计算机显示。
RaspiServer - 服务器端
import socket
from LED import callLED
host = ''
port = 5560
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
except socket.error as msg:
print(msg)
print("Socket bind complete.")
return s
def setupConnection():
s.listen(1)
conn, address = s.accept()
print("Connected to: " + address[0] + ":" + str(address[1]))
return conn
def dataTransfer(conn):
while True:
data = conn.recv(1024)
data = data.decode('utf-8')
dataMessage = data.split(":", 2)
command = dataMessage[0]
humidity = dataMessage[1]
temperature = dataMessage[2]
if command == 'DATA':
print("Received: " + humidity + " : " + temperature)
callLED()
elif command == 'EXIT':
print("Disconnected with Client")
break
else:
reply = 'Unknow Command'
conn.sendall(str.encode(reply))
Print("Reply has been send.")
conn.close()
s = setupServer()
while True:
try:
conn = setupConnection()
dataTransfer(conn)
except:
break
在客户端有三个 python 脚本,其中主要的 python 脚本与其他脚本进行通信。我决定将它拆分成多个脚本,以便将它们也用作独立的(闪烁的 LED、在 LCD 上显示数据等)。
RaspiMonitor - 客户端
Run this script on client-side
from time import sleep
from client_sensordata import GetTemp
from monitor_client import transmit
sleepTime = 20
def tempMonitorServer():
humidity, temperature = GetTemp()
temp = str(temperature)
hum = str(humidity)
message = "DATA:" + hum + ":" + temp
print("Transmitting Data.")
response = transmit(message)
print(response)
while True:
tempMonitorServer()
sleep(sleepTime)
Use this script to send and receive data over TCP/IP
import socket
host = '192.168.2.3'
port = 5560
def setupSocket():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
return s
def sendReceive(s, message):
s.send(str.encode(message))
print("Message transmitted")
reply = s.recv(1024)
print("We have received a reply.")
print("Send closing message.")
s.send(str.encode("EXIT"))
s.close()
reply = reply.decode('utf-8')
return reply
def transmit(message):
s = setupSocket()
response = sendReceive(s, message)
return response
Use this script to retrieve sensor data
def GetReading():
import sys
import Adafruit_DHT
humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT22, 17)
if humidity is not None and temperature is not None:
print('Reading sensor data')
return humidity, temperature
else:
print('no sensor data')
def GetTemp():
humidity, temperature = GetReading()
name = "DHT22Client1"
print('Read sensor: {0} humidity: {1:0.2f}% temperature: {2:0.2f}C'.format(name, humidity, temperature))
return humidity, temperature
终端输出
Terminal output, left server and right the client
任何人都可以提供一些提示或帮助,或者告诉我为什么如何解决这个问题吗?我已经搜索了多个线程和其他帖子,但找不到解决方案。
在此先感谢您提供的所有帮助。
您的服务器套接字设置可能有一些错误。服务器套接字的工作方式是它应该始终打开侦听新连接。当您接受来自客户端 (s.accept) 的连接时,它会创建到客户端的连接。如果关闭该连接,它应该不会影响服务器监听传入的套接字,客户端或连接到客户端的数量仅受您在服务器中指定的数量限制 socket.listen(NUMBER)。当达到该数量时,传入连接将被拒绝。
def setupServer():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print("Socket created.")
try:
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print(msg)
print("Socket bind complete.")
return s
然后从设置连接中删除 s.listen
我还建议您在新线程中处理数据传输(),以便能够同时处理传入连接而不是连续处理。
与其反复关闭和打开新的套接字,不如在服务器端维护多个打开的套接字连接,并使用 select() 方法处理每个套接字。
https://docs.python.org/2/library/select.html
Can a server handle multiple sockets in a single thread?
目前可用的代码(仍在建设中以添加更多功能)是:
服务器端
import socket
import sys
from LED import callLED
from monitor_log3 import ExtractStoreData
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('', 5560)
print >>sys.stderr, 'Starting up on %s port %s' % server_address
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
while True:
# Wait for a connection
print >>sys.stderr, 'Waiting for a connection'
connection, client_address = sock.accept()
try:
print >>sys.stderr, 'Connection from', client_address
# Receive the data in small chunks and retransmit it
while True:
data = connection.recv(1024)
data = data.decode('utf-8')
message = data
if data:
print >>sys.stderr, 'Send data receive confirmation'
connection.sendall(data)
callLED()
ExtractStoreData(message)
else:
print >>sys.stderr, 'No more data from', client_address
break
finally:
# Clean up the connection
print >>sys.stderr, 'Closing connection'
print >>sys.stderr, '------------------'
connection.close()
客户端看起来像这样:
客户端
import socket
import sys
import datetime
from time import sleep
from client_sensordata import GetTemp
timeSleep = 10
def ClientSocket():
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
server_address = ('192.168.2.3', 5560)
print >>sys.stderr, 'Connecting to: %s port: %s' % server_address
sock.connect(server_address)
try:
# Send data
name, humidity, temperature = GetTemp()
Sensorname = str(name)
temp = str(temperature)
hum = str(humidity)
print(Sensorname + ":" + temp + ":" + hum)
message = (Sensorname + ":" + temp + ":" + hum)
print("Transmitting data...")
print >>sys.stderr, 'Sending data...'
sock.send(str.encode(message))
# Look for the response
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(1024)
amount_received += len(data)
print >>sys.stderr, 'Send data'
finally:
print >>sys.stderr, 'Closing connection'
print >>sys.stderr, '------------------'
sock.close()
while True:
print("Start external server measurement at " + datetime.datetime.now().strftime("%H:%M:%S"))
ClientSocket()
sleep(timeSleep)
for t2 in range(5):
print("Start internal display measurement at " + datetime.datetime.now().strftime("%H:%M:%S"))
GetTemp()
print("------------------")
sleep(timeSleep)
它正在循环5个循环进行内部测量(在LCD显示器上),然后将数据发送一次到服务器,服务器将把它存储在数据库(SQlite3)中。仍然想添加更多功能(读取时 LED,低于或超过限制时警告 LED,警报声,连接 LCD。当有进展时我会更新代码。
当然欢迎任何提示和建议!