Search code examples
pythonraspberry-pitcpclienttcptcpserver

Send sensor data over socket communication (TCP/IP) between Pi's with python


Hello everyone,

I have a problemen with some socket communication coding. I have two pi's communicating over TCP/IP with python scripts. The idea is that one pi (client)reads temperature/humidity sensor data and sends it over to the other pi (server), where it will be stored in a SQLite database. In the future I want multiple pi's (clients) sends over sensor data to one (web)server with database to display data on a local website.

I have written some python code for server and client side and it works pretty well. If I start the server side it will listen for other connections. When I start the client side it will generate sensor data and send it to the server. The server receives the data. But when I want to close to connection to make room for (a future other pi) it terminates completely the script and don't listens for new "calls". See code below for both sides. Code is written in Python2.7.

Goal of this project: Within a zoo setting monitor and log multiple exhibits and aquariums on temperature and humidity, display the information on LCD in every exhibit, use LED as warning, and have a central-server to store/log data, that is displayed with a central computer.

RaspiServer - server-side

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

On the client-side there are three python scripts, where the main python scripts communicate with other scripts. I have decides to split it in multiple script to use them also as stand-alone (blinking LED, display data on LCD etc.).

RaspiMonitor - client-side

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

Terminal output, left server and right the client

Could anyone give some tips or help, or tell me why how to fix this problemen? I searched already multiple threads and other posts, but can't find the solution.

Thanks in advance for every help you give.


Solution

  • Rather than closing and opening new sockets repeatedly, I would suggest maintaining multiple open socket connections server side and handling each socket using the select() method.

    https://docs.python.org/2/library/select.html

    https://pymotw.com/2/select/

    Can a server handle multiple sockets in a single thread?