Jump to content

Onewire Bricklet Threadsafe?


Recommended Posts

Hallo Zusammen,

ich Versuche eine Python Methode zu schreiben welche über einen eigenen Thread DS18B20 Temperatursensoren ausließt und in eine globale Variable schreibt. Der Code funktioniert auch wenn ich ihn nicht in einen Thread auslagere Vielleicht kann mir jemand sagen was ich falsch mache?

Hier der Code:

import time
import threading

from tinkerforge.ip_connection import IPConnection
from tinkerforge.bricklet_one_wire import BrickletOneWire

HOST = "localhost"
PORT = 4223

tempsensors = [
    {"sensor": 0, "address": "123", "found": False, "temperature": 0.0, "identifier": 0, "deviceobject": None}, \
    {"sensor": 1, "address": "123", "found": False, "temperature": 0.0, "identifier": 0, "deviceobject": None}, \
    {"sensor": 2, "address": "3456", "found": False, "temperature": 0.0, "identifier": 0, "deviceobject": None}, \
    ]  # Hier sollen alle Sensoren die bekannt sind und verwendet werden aufgeführt sein. Achtung das muss händisch erledigt werden
tempsensorsnew = []  # Hier sollen alle Sensoren Automatisch eingetragen werden welche noch nicht in die Liste aufgenommen wurden

class Rugged:
    def __init__(self):
        self.onewire = []   # Liste erzeugen wo die Onewire geräte eingefügt werden
        self.__threadonewire = threading.Thread(target=self.__getonewire)

        self.ipcon = IPConnection()     # Create IP Connection

        self.ipcon.register_callback(IPConnection.CALLBACK_ENUMERATE, self.cb_enumerate)    # Register Callback
        self.ipcon.register_callback(IPConnection.CALLBACK_CONNECTED, self.cb_connected)    # Register Callback
        self.ipcon.connect(HOST, PORT)

        self.ipcon.enumerate()

    def cb_enumerate(self, uid, connected_uid, position, hardware_version, firmware_version, device_identifier, enumeration_type):
        global onewire
        if enumeration_type == IPConnection.ENUMERATION_TYPE_CONNECTED or enumeration_type == IPConnection.ENUMERATION_TYPE_AVAILABLE:
            if device_identifier == BrickletOneWire.DEVICE_IDENTIFIER:
                if not self.onewire:
                    self.onewire = [BrickletOneWire(uid, self.ipcon)]
                    time.sleep(0.5)
                else:
                    for i in self.onewire:
                        if i.get_identity() == uid:
                            break  # Wenn das Onewire Modul schon als Object in der Liste ist wird abgebrochen
                    self.onewire.append(BrickletOneWire(uid, self.ipcon))
                    time.sleep(0.5)
                if not self.__threadonewire.is_alive():
                    self.__threadonewire.start()
                #self.__getonewire() # Wenn die funktion direkt anstatt des Threads ausgeführt wird funktioniert es



    def cb_connected(self, connected_reason):
        # Enumerate devices again. If we reconnected, the Bricks/Bricklets
        # may have been offline and the configuration may be lost.
        # In this case we don't care for the reason of the connection
        self.ipcon.enumerate()

    def __getonewire(self):
        global tempsensors
        global tempsensorsnew
        while True:
            print(tempsensors)

            print(tempsensorsnew)
            for i in self.onewire:
                i.reset_bus()  # setzt den Bus zurück
                searched = i.search_bus()
                i.write(78)  # WRITE SCRATCHPAD
                i.write(0)  # ALARM H (unused)
                i.write(0)  # ALARM L (unused)
                i.write(127)  # CONFIGURATION: 12-bit mode

                i.write(68)  # CONVERT T (start temperature conversion)
                time.sleep(1)  # Wait for conversion to finish

                for x in searched[0]:
                    i.write_command(x, 190)  # READ SCRATCHPAD
                    t_low = i.read().data
                    t_high = i.read().data
                    temperature = t_low | (t_high << 8)
                    if temperature > 1 << 12:
                        temperature -= 1 << 16
                    temperature = temperature / 16.0
                    crc = hex(x)[2:4]
                    family = hex(x)[-2:]
                    address = hex(x)[(2 + len(crc)):(len(hex(x)) - len(family))]
                    #print("Family: " + hex(x)[-2:])
                    #print("CRC: " + hex(x)[2:4])
                    #print("Address: " + address.upper())
                    sensorfound = False
                    for g in tempsensors:
                        if g["address"].upper() == address.upper():
                            sensorfound = True
                            g["found"] = True
                            g["identifier"] = x
                            g["deviceobject"] = i
                            g["temperature"] = temperature
                            break
                        else:
                            sensorfound = False
                    if not sensorfound:
                        for g in tempsensorsnew:
                            if g["address"].upper() == address.upper():
                                sensorfound = True
                                g["temperature"] = temperature
                                break
                            else:
                                sensorfound = False
                        if not sensorfound:
                            tempsensorsnew.append({"sensornew": len(tempsensorsnew), "address": address, "temperature": temperature, "identifier": x, "deviceobject": i})


if __name__ == "__main__":
    Rugged()
    input('Press key to exit\n')

 

Danke für eure Hilfe.

Folgender Fehler kommt:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Program Files (x86)\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Program Files (x86)\Python38-32\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "C:/...Control.py", line 74, in __getonewire
    searched = i.search_bus()
  File "C:\...Control\venv\lib\site-packages\tinkerforge\bricklet_one_wire.py", line 329, in search_bus
    ret = self.search_bus_low_level()
  File "C:\...Control\venv\lib\site-packages\tinkerforge\bricklet_one_wire.py", line 122, in search_bus_low_level
    return SearchBusLowLevel(*self.ipcon.send_request(self, BrickletOneWire.FUNCTION_SEARCH_BUS_LOW_LEVEL, (), '', 'H H 7Q B'))
  File "C:\...Control\venv\lib\site-packages\tinkerforge\ip_connection.py", line 1220, in send_request
    raise Error(Error.TIMEOUT, msg, suppress_context=True)
tinkerforge.ip_connection.Error: Did not receive response for function 1 in time (-1)

 

Edited by DoIT
Link to comment
Share on other sites

Ich habe mir das jetzt nicht alles im Detail angesehen, aber zumindest das hier tut nicht das was du denkst:

for i in self.onewire:
    if i.get_identity() == uid:
        break  # Wenn das Onewire Modul schon als Object in der Liste ist wird abgebrochen
self.onewire.append(BrickletOneWire(uid, self.ipcon))

Die get_identity() Funktion gibt ein namedtuple zurück. Das mit uid zu vergleichen ist immer False. Du musst uid mit dem uid Feld des namedtuple vergleichen.

Dann ist das break da nicht das richtige. Das bricht die for Schleife ab, aber der append() Aufruf danach wird trotzdem ausgeführt. Da muss du ein return verwenden um den gesamten Aufruf von cb_enumerate zu beenden.

Etwa so:

for i in self.onewire:
    if i.get_identity().uid == uid:
        return  # Wenn das Onewire Modul schon als Object in der Liste ist wird abgebrochen
self.onewire.append(BrickletOneWire(uid, self.ipcon))

So wie du es aktuell hast fügst du das Bricklet zweimal in deine Liste ein. Das könnte schon das ganze Problem sein.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...