草庐IT

python - 通过 Pi 与 python 之间的套接字通信 (TCP/IP) 发送传感器数据

coder 2023-09-19 原文

大家好,

我对某些套接字通信编码有疑问。我有两个 pi 通过 TCP/IP 与 python 脚本进行通信。这个想法是一个 pi(客户端)读取温度/湿度传感器数据并将其发送到另一个 pi(服务器),它将存储在 SQLite 数据库中。将来我希望多个 pi(客户端)将传感器数据发送到一个带有数据库的(网络)服务器,以在本地网站上显示数据。

我已经为服务器端和客户端编写了一些 python 代码,并且运行良好。如果我启动服务器端,它将监听其他连接。当我启动客户端时,它将生成传感器数据并将其发送到服务器。服务器接收数据。但是当我想关闭连接以为( future 的其他 pi)腾出空间时,它会完全终止脚本并且不监听新的“调用”。双方请参见下面的代码。代码是用Python2.7编写的。

这个项目的目标:在一个动物园设置中监控和记录多个展品和水族馆的温度和湿度,在每个展品的 LCD 上显示信息,使用 LED 作为警告,并有一个中央 -服务器存储/记录数据,显示在中央计算机上。

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

然后从 setup connection() 中移除 s.listen

我还建议您在新线程中处理数据传输(),以便能够同时处理传入连接,而不是连续处理。

这是一个引用:https://docs.python.org/2/howto/sockets.html

关于python - 通过 Pi 与 python 之间的套接字通信 (TCP/IP) 发送传感器数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49691763/

有关python - 通过 Pi 与 python 之间的套接字通信 (TCP/IP) 发送传感器数据的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  5. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  6. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  7. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  8. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  9. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  10. ruby - 从 Ruby 中的主机名获取 IP 地址 - 2

    我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge

随机推荐