Looking for fix for this BrokenPipeError in my python project socket/Threads

83 Views Asked by At

first time questioner here! I´m currently working on a python project that´s supposed to read soil moisture through a sensor on a raspberry pi, which then sends the data to another laptop through a socket connection. That other laptop displays the data in a UI. That UI is also capable of controllig the script flow. My Server starts up just fine, but when the client connects to it(connection itself works), I get the following Error Stack:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(self._args, **self._kwargs)
  File "/home/pi/Py_Scripts/MoistureSensor/Server.py", line 77, in worker_recv
    self.JSON_Control = pickle.loads(self.data_recv)
EOFError: Ran out of input

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.5/threading.py", line 862, in run
    self._target(self._args, **self._kwargs)
  File "/home/pi/Py_Scripts/MoistureSensor/Server.py", line 70, in worker_send
    self.conn.send(self.data_send)
BrokenPipeError: [Errno 32] Broken pipe

My Scripts look as follows:

Client-side:

import sys
from socket import *
from threading import Thread
from time import sleep
import pickle
from PySide6 import QtWidgets, QtGui


class MyClient: 
    def __init__(self, server_port, buf_size, host):
        self.server_port = server_port
        self.buf_size = buf_size
        self.host = host
        self.data_send = None
        self.data_recv = None
        self.exit = False

        self.JSON_Control = {
            "measure": False,
            "exit": False,
        }

        self.JSON_Moisture = {
            "moisture_level": 0
        }

        self.socket_connection = socket(AF_INET, SOCK_STREAM)
        self.socket_connection.connect((self.host, self.server_port))
        print("Connected with Server: %s: " % self.host)

        # thread for sending
        self.thread_send = Thread(target=self.worker_send)
        # thread for receiving
        self.thread_recv = Thread(target=self.worker_recv)

        # starting Threads
        self.thread_send.start()
        self.thread_recv.start()

    def worker_send(self):
        while not self.exit:
            self.data_send = pickle.dumps(self.JSON_Control)
            self.socket_connection.send(self.data_send)
            sleep(0.5)

    def worker_recv(self):
        while not self.exit:
            self.data_recv = self.socket_connection.recv(self.buf_size)
            if self.data_recv is not None:
                self.JSON_Moisture = pickle.loads(self.data_recv)


class UiDisplay(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.moisture_label = None
        self.moisture_level = None
        self.start_button = None
        self.refresh_button = None
        self.stop_button = None
        self.reset_button = None
        self.quit_button = None
        self.create_widgets()

    def create_widgets(self):
        # create a label to display the current time
        self.moisture_label = QtWidgets.QLabel(self)
        self.moisture_label.setFont(QtGui.QFont("Helvetica", 16))
        self.moisture_level = client.JSON_Moisture["moisture_level"]
        self.moisture_label.setText('Bodenfeuchtigkeit: ' + str(self.moisture_level)[:3] + '%')

        # button to start the weight measuring
        self.start_button = QtWidgets.QPushButton("Start measuring", self)
        self.start_button.clicked.connect(self.measure_moisture)

        # button to refresh the Weight label
        self.refresh_button = QtWidgets.QPushButton("Refresh", self)
        self.refresh_button.clicked.connect(self.refresh)

        # button to stop measuring
        self.stop_button = QtWidgets.QPushButton("Stop measuring", self)
        self.stop_button.clicked.connect(self.stop_measuring)

        # button to quit the program
        self.quit_button = QtWidgets.QPushButton("Quit", self)
        self.quit_button.clicked.connect(self.quit)

        # create a layout to hold the widgets
        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.moisture_label)
        layout.addWidget(self.start_button)
        layout.addWidget(self.refresh_button)
        layout.addWidget(self.stop_button)
        layout.addWidget(self.reset_button)
        layout.addWidget(self.quit_button)
        self.setLayout(layout)

    def measure_moisture(self):
        client.JSON_Control["measure"] = True
    def refresh(self):
        # get current weight ( niederlag auf ein qm rechnen fehlt noch)
        self.moisture_level = round(client.JSON_Moisture["moisture_level"] - 2.7) / (1 - 2.7)
        print(self.moisture_level)
        # umrechnen von analogem Wert zu Prozentanteil
        print(self.moisture_level)
        # update the weight label with the current time
        self.moisture_label.setText('Bodenfeuchtigkeit:  ' + str(self.moisture_level)[:5] + '%')

    def stop_measuring(self):
        if client.JSON_Control["measure"]:
            client.JSON_Control["measure"] = False
        else:
            pass

    def quit(self):
        QtWidgets.QApplication.instance().quit()
        client.JSON_Control["exit"] = True
        sleep(2)
        client.exit = True
        client.thread_recv.join()
        client.thread_send.join()
        client.socket_connection.close()
        print("Server connection is closed")
        print('exiting...')
        sleep(1)
        sys.exit()


client = MyClient(1957, 1024, "192.168.86.121")

app = QtWidgets.QApplication()
window = UiDisplay()
window.show()
app.exec()


--------------------------------------------------------

The Server-side:


import sys
from socket import *
from threading import Thread
import pickle
from time import sleep
import Adafruit_ADS1x15


adc_channel_0 = 0


class SoilMoistureSensor:
    def __init__(self, gain, sps, dry_voltage, saturated_voltage):
        self.adc = Adafruit_ADS1x15.ADS1115()
        self.raw_data = None
        self.moisture_level = None
        # self.voltage = None
        self.gain = gain
        self.sps = sps
        self.dry_voltage = dry_voltage
        self.saturated_voltage = saturated_voltage


class MyServer:
    def __init__(self, echo_port, buf_size):
        self.buf_size = buf_size
        self.echo_port = echo_port
        self.data_send = None
        self.data_recv = None
        self.exit = False
        self.data_json = None
        self.moisture_sensor = SoilMoistureSensor(2, 32, 1, 2.7)  # gain, sps, saturated_voltage,             dry_voltage

        self.JSON_Control = {
            "measure": False,
            "exit": False
        }

        self.JSON_Moisture = {
            "moisture_level": 0,
        }

        self.socket_connection = socket(AF_INET, SOCK_STREAM)
        self.socket_connection.bind(("", self.echo_port))
        self.socket_connection.listen(1)

        print("Server gestartet")
        print("Name des Hosts: ", gethostname())
        print("IP des Hosts: ", gethostbyname(gethostname()))

        self.conn, (self.remotehost, self.remoteport) = self.socket_connection.accept()
        print("Verbunden mit %s %s " % (self.remotehost, self.remoteport))

        # thread for sending
        self.thread_send = Thread(target=self.worker_send)
        # thread for receiving
        self.thread_recv = Thread(target=self.worker_recv)
        # thread for checking Json Control
        self.thread_check_json_control = Thread(target=self.check_json_control)

        # starting Threads
        self.thread_send.start()
        self.thread_recv.start()
        self.thread_check_json_control.start()

    def worker_send(self):
        while not self.exit:
            self.data_send = pickle.dumps(self.JSON_Moisture)
            self.conn.send(self.data_send)
            sleep(0.5)

    def worker_recv(self):
        while not self.exit:
            self.data_recv = self.conn.recv(self.buf_size)
            if self.data_recv is not None:
                self.JSON_Control = pickle.loads(self.data_recv)

    def measure_moisture(self, channel):
        channel = adc_channel_0
        self.moisture_sensor.raw_data = self.moisture_sensor.adc.read_adc(
            channel, self.moisture_sensor.gain, self.moisture_sensor.sps)
        self.JSON_Moisture["moisture_level"] = self.moisture_sensor.raw_data
        print(self.moisture_sensor.raw_data)

    def stop_connection(self):
        self.thread_recv.join()
        self.thread_send.join()
        self.thread_check_json_control.join()
        self.socket_connection.close()
        print("Server connection is closed")
        print('exiting...')
        sys.exit()

    def check_json_control(self):
        while not self.exit:
            if self.JSON_Control["measure"]:
                self.measure_moisture(0)
            if self.JSON_Control["exit"]:
                self.stop_connection()
            sleep(0.5)


server = MyServer(1957, 1024)

I´d be ever so grateful for help and I´m incredibly sorry if I´ve disregarded any question conventions. Cheers!

0

There are 0 best solutions below