8 Bytes zu Bit´s zu int

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
pumuckll
User
Beiträge: 56
Registriert: Donnerstag 30. August 2018, 17:45

Hallo Allerseits,

Der Code bei den ihr mir geholfen habet, läuft schon länger stabil auf verschieden Geräten.

Aktueller Code: https://bpa.st/UXWQ
link hier im Forum viewtopic.php?f=31&t=46798&start=15#p362337

Für ein neues Projekt möchte ich den Code Umschreiben, weil ich zusätzliche Ein und Ausgänge benötige.

damit es etwas übersichtlicher wird werde ich es Nurmehr für einen Geräte Typ auslegen.

Wenn ihr den Code kurz überfliegt, was sollte ich noch ändern?
Vermutlich sollte ich das Logging in eine Funkton verschieben, das hatte aber damals nicht funktioniert.
Hättet ihr da ein Beispiel bzw eine Anleitung zur Hand?


Mein Problem gleich am Anfang ist das Auslesen der Bits und zu Bytes zusammen Fasen.

Es werden bis zu 8 PCF8574 I2C IO Erweiterung Module , mit je 8 ein oder Ausgängen werden.

Den zustand dieser IO´s möchte ich auslesen und wieder per Udp als zahl versenden, wenn möglich au 2mal, also je 4 Bytes auf einmal.

Aber es sieht so aus als wäre die Variable nicht Groß Genugt, der Wert wir Negative wenn ich Bit 8 von Byte 4 auf 1 setze.

Code: Alles auswählen

>>> pcf_io_werte_in()
0
>>> pcf_io_werte_out()
-2122252032
>>>
der erste code zum Testen

Code: Alles auswählen

pi@keller-pi:~ $ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pcf8574 import PCF8574
>>> import numpy as np
>>>
>>> #Konstaten
... I2C_PORT_NUMMER = 1
>>> PCF1_ADDRESS = 0x20 #Eingänge
>>> PCF2_ADDRESS = 0x21 #Ausgänge
>>> PCF3_ADDRESS = 0x22 #Eingänge
>>> PCF4_ADDRESS = 0x23 #Ausgänge
>>> PCF5_ADDRESS = 0x24 #Eingänge
>>> PCF6_ADDRESS = 0x25 #Ausgänge
>>> PCF7_ADDRESS = 0x26   #reserve
>>> PCF7_ADDRESS = 0x27   #reserve
>>>
>>>
>>> #variablen werden noch in eine funktion geschrieben
... pcf1 = PCF8574(I2C_PORT_NUMMER, PCF1_ADDRESS)
>>> pcf3 = PCF8574(I2C_PORT_NUMMER, PCF3_ADDRESS)
>>> pcf5 = PCF8574(I2C_PORT_NUMMER, PCF5_ADDRESS)
>>> pcf7 = PCF8574(I2C_PORT_NUMMER, PCF5_ADDRESS)
>>>
>>> pcf2 = PCF8574(I2C_PORT_NUMMER, PCF2_ADDRESS)
>>> pcf4 = PCF8574(I2C_PORT_NUMMER, PCF4_ADDRESS)
>>> pcf6 = PCF8574(I2C_PORT_NUMMER, PCF6_ADDRESS)
>>> pcf8 = PCF8574(I2C_PORT_NUMMER, PCF6_ADDRESS)
>>>
>>>
>>> #zum Testen die Ein und Ausgänge in einen bestimmten zustand setzen
... pcf1.port = [False, False, False, False, False, False, False, False ]
>>> pcf2.port = [False, False, False, False, False, False, False, False ]
>>> pcf3.port = [False, False, False, False, False, False, False, False]
>>> pcf4.port = [True, False, False, False, False, False, False, True]
>>> pcf5.port = [False, False, False, False, False, False, False, False]
>>> pcf6.port = [False, False, False, False, False, False, False, False]
>>> pcf7.port = [False, False, False, False, False, False, False, False]
>>> pcf8.port = [True, False, False, False, False, False, False, True]
>>>
>>>
>>>
>>> def pcf_io_werte_in():
...     """pcf_io_werte auslesen
...        bitwise operations      """
...     try:
...         pcf_io_werte_1 = np.multiply(np.array(pcf1.port), 1)
...         pcf_io_werte_3 = np.multiply(np.array(pcf3.port), 1)
...         pcf_io_werte_5 = np.multiply(np.array(pcf5.port), 1)
...         pcf_io_werte_7 = np.multiply(np.array(pcf7.port), 1)
...         pcf_io_binär = np.concatenate((pcf_io_werte_7, pcf_io_werte_5, pcf_io_werte_3, pcf_io_werte_1))
...         pcf_io_integer = 0
...         for bit in pcf_io_binär:
...             pcf_io_integer = (pcf_io_integer << 1) | bit
...         return pcf_io_integer
...     except Exception:
...         print("error")
...
>>>
>>> def pcf_io_werte_out():
...     """pcf_io_werte auslesen
...        bitwise operations      """
...     try:
...         pcf_io_werte_2 = np.multiply(np.array(pcf2.port), 1)
...         pcf_io_werte_4 = np.multiply(np.array(pcf4.port), 1)
...         pcf_io_werte_6 = np.multiply(np.array(pcf6.port), 1)
...         pcf_io_werte_8 = np.multiply(np.array(pcf8.port), 1)
...         pcf_io_binär = np.concatenate((pcf_io_werte_8, pcf_io_werte_6, pcf_io_werte_4, pcf_io_werte_2,))
...         pcf_io_integer = 0
...         for bit in pcf_io_binär:
...             pcf_io_integer = (pcf_io_integer << 1) | bit
...         return pcf_io_integer
...     except Exception:
...         print("error")
...
>>>
>>> pcf_io_werte_in()
0
>>> pcf_io_werte_out()
-2122252032
>>>

Grüsse
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Du verwendest numpy-Datentypen, um genau zu sein, 64bit mit Vorzeichen.
Das ist nicht nur unglaublich umständlich und sehr langsam, sondern führt ja auch zu komischem Verhalten.
Das Exception-Handling ist hier und in Deinem verlinkten Code allesamt fehlerhaft. Exceptions behandelt man nur, wenn man damit auch sinnvoll was anfangen kann. Sinnvoll ist es jedenfalls nicht, fast jeden Fehler durch eine nichtssagende Meldung zu ersetzen, und dann so weiter zu machen, als ob nichts gewesen wäre.

Code: Alles auswählen

def pcf_io_werte_out(pcfs):
    """pcf_io_werte auslesen
       bitwise operations      """
    result = 0
    for pcf in pcfs:
        for bit in pcf.port:
            result = (result << 1) | bit
    return result

pcf_io_werte_out([pcf8, pcf6, pcf4, pfc2])
pumuckll
User
Beiträge: 56
Registriert: Donnerstag 30. August 2018, 17:45

Danke Dir
mein Ansatz war mal wieder zu kompliziert

wenn man pcf ausliest erhölt man:

Code: Alles auswählen

[True, False, False, False, False, False, False, True]
die wollte ich zuerst in Zahlen umwandeln, Google hat mich dann zu numpy gebracht.

ich hätte noch eine grundlegende Frage.

das sind Konstanten:

Code: Alles auswählen

#Konstaten
I2C_PORT_NUMMER = 1
PCF1_ADDRESS = 0x20 #Eingänge
PCF2_ADDRESS = 0x21 #Ausgänge
PCF3_ADDRESS = 0x22 #Eingänge
PCF4_ADDRESS = 0x23 #Ausgänge
PCF5_ADDRESS = 0x24 #Eingänge
PCF6_ADDRESS = 0x25 #Ausgänge
PCF7_ADDRESS = 0x26   #reserve
PCF8_ADDRESS = 0x27   #reserve

sind das dann theoretisch auch Konstanten oder?

Code: Alles auswählen

#variablen werden noch in eine funktion geschrieben
pcf1 = PCF8574(I2C_PORT_NUMMER, PCF1_ADDRESS)
pcf3 = PCF8574(I2C_PORT_NUMMER, PCF3_ADDRESS)
pcf5 = PCF8574(I2C_PORT_NUMMER, PCF5_ADDRESS)
pcf7 = PCF8574(I2C_PORT_NUMMER, PCF5_ADDRESS)

pcf2 = PCF8574(I2C_PORT_NUMMER, PCF2_ADDRESS)
pcf4 = PCF8574(I2C_PORT_NUMMER, PCF4_ADDRESS)
pcf6 = PCF8574(I2C_PORT_NUMMER, PCF6_ADDRESS)
pcf8 = PCF8574(I2C_PORT_NUMMER, PCF8_ADDRESS)
Da sie vom Code nicht mehr verändert werden.

so ist es Vermutlich übersichtlicher, aber sollte ich das auf einen Block reduzieren?
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@pumuckll
True und False sind in Python gleichwertig zu 1 und 0. Sie sind von int abgeleitet und man kann auch mit ihnen rechnen.

Code: Alles auswählen

>>> isinstance(True, int)
True
>>> int(True)
1
>>> True + True
2
Dieser Umstand wird zB gerne zum Zählen bestimmter Eigenschaften verwendet:

Code: Alles auswählen

sum(zahl >= 3 for zahl in range(10))
pumuckll
User
Beiträge: 56
Registriert: Donnerstag 30. August 2018, 17:45

Im Großen und Ganzen habe habe ich die Funktionen zum auslesen uns setzten der IO erstellt.

Ich habe aber Probleme bei der Integration in meinen Vorhanden Code, bevor ich das dict automatisch erstelle wollte ich den Befehl testen.




Einzeln funktioniert die Funktion zum setzen eines ausgangs.
Per UDP Klappt es nicht.

hier der Code, auf das wesentliche reduziert:

Code: Alles auswählen

#!/usr/bin/env python3
"""V3.1
   Diese Script Sendet und empfängt UDP Nachrichten,
   um Ausgänge zu schalten und um  den Status von Eingängen, Ausgängen sowie von 1Wire Sensoren  auszugeben.
   Verwendbar für Raspberrypi 3 und 4, orangepi zero """

import logging
import socket
import threading
from functools import partial
from logging.handlers import TimedRotatingFileHandler
from time import sleep
from pcf8574 import PCF8574
from RPi import GPIO  # RaspberryPi

#Logger
# logging.DEBUG  logging.INFO

LOGGER_KONSTANTE = logging.DEBUG

#pcf8574
I2C_PORT_NUMMER = 1
PCF1_ADDRESS = 0x20 #Eingänge
PCF2_ADDRESS = 0x21 #Ausgänge   RM2 K1-K8 pcf_io_1-8
PCF3_ADDRESS = 0x22 #Eingänge
PCF4_ADDRESS = 0x23 #Ausgänge   RM3 K1-K8 pcf_io_9-16
PCF5_ADDRESS = 0x24 #Eingänge
PCF6_ADDRESS = 0x25 #Ausgänge   RM4 K1-K8  pcf_io_17-24
PCF7_ADDRESS = 0x24   #reserve
PCF8_ADDRESS = 0x25   #reserve RM4 K1-K8  pcf_io_25-32

pcfs_in =[PCF8574(I2C_PORT_NUMMER, PCF7_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF5_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF3_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF1_ADDRESS)]
pcfs_out =[PCF8574(I2C_PORT_NUMMER, PCF8_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF6_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF4_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF2_ADDRESS)]


# logger
logger = logging.getLogger("Rotating Log")
logger.setLevel(LOGGER_KONSTANTE)
handler = TimedRotatingFileHandler("in_out.log", when='D', interval=1, backupCount=7, encoding=None,
                                   delay=False, utc=False, atTime=None)
fileformatter = logging.Formatter('%(asctime)s : %(levelname)s : %(name)s : %(message)s')
handler.setFormatter(fileformatter)
logger.addHandler(handler)
logger.info("logger started")


def create_command_dictionary(udp_socket):
    command_to_func = {
        b"tor_auf_zu": partial(tor_auf_zu, udp_socket),
        b"reply_loxone": partial(reply_loxone, udp_socket),
        b"pcf_io_01_ein": partial(set_io, pcfs_out, 1, 0, False)
    }
    return command_to_func


def reply_loxone(udp_socket, command):
    udp_socket.sendto(command, TARGET_HOST[DEVICE])

def tor_auf_zu(udp_socket, command):
    """tor öffner wird gedrückt"""
    udp_socket.sendto(command, TARGET_HOST[DEVICE])
    print("ok")

#pcf abschnitt
def pcf_io_werte(pcfs):
    """pcf_io_werte auslesen
       bitwise operations      """
    result = 0
    for pcf in pcfs:
        for bit in pcf.port:
            result = (result << 1) | bit
    return result

def set_io_false(pcfs):
    for pcf in pcfs:
        pcf.port = [False, False, False, False, False, False, False, False]


def set_io(pcfs,pcf_stelle, io_bit, io_bit_wert):
    pcfs[pcf_stelle].port[io_bit] = io_bit_wert
    print(pcfs[pcf_stelle].port[io_bit])



def main():
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    udp_socket.bind(SERVER[DEVICE])
    command_to_function = create_command_dictionary(udp_socket)
    logger.info("dictionary created : {} ".format(command_to_function))
    set_io_false(pcfs_out)
    set_io_false(pcfs_in)
    ergebniss= pcf_io_werte(pcfs_in)
    print(ergebniss)
    ergebniss1= pcf_io_werte(pcfs_out)
    print(ergebniss1)
    set_io(pcfs_out, 1, 0, True)
    ergebniss= pcf_io_werte(pcfs_in)
    print(ergebniss)
    ergebniss1= pcf_io_werte(pcfs_out)
    print(ergebniss1)

    #
    try:
        print("UDPServer Waiting for client on port : {} ".format(SERVER[DEVICE]))
        logger.info("UDPServer Waiting for client on port : {} ".format(SERVER[DEVICE]))
        while True:
            command, _addr = udp_socket.recvfrom(BUFFER_SIZE)
            logger.info("UDPServer command : {} ".format(command))
            try:
                function = command_to_function[command]
                print(command)
            except KeyError:
                udp_socket.sendto(f"Unknown command {command!a}".encode("ascii"), TARGET_HOST[DEVICE])
                logger.exception("KeyError")
            else:
                print("noch ok")
                function(command)
                logger.info(" function {} ".format(function))

    finally:
        print("end")


if __name__ == "__main__":
    main()
das ist das Ergebnis bzw die Fehlermeldung:

Code: Alles auswählen

pi@keller-pi:~ $ python3 in_out.py
0
0
True
0
2155872256
UDPServer Waiting for client on port : ('', 8014)
b'blabla'
noch ok
b'reply_loxone'
noch ok
b'reply_loxone'
noch ok
b'tor_auf_zu'
ok
noch ok
b'pcf_io_01_ein'
end
Traceback (most recent call last):
  File "in_out.py", line 143, in <module>
    main()
  File "in_out.py", line 135, in main
    function(command)
TypeError: set_io() takes 4 positional arguments but 5 were given
pi@keller-pi:~ $
ich sehe nicht warum ein Argumet Zuviel ist

woran liegt es?

grüsse
Benutzeravatar
sparrow
User
Beiträge: 4187
Registriert: Freitag 17. April 2009, 10:28

Lass dir doch mal anzeigen, was "command" bei dem Funktionsaufruf für einen Wert hat.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Dann vergleich mal die Definition von reply_loxone oder tor_auf_zu mit set_io.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1017
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

pumuckll hat geschrieben: Sonntag 11. Oktober 2020, 12:27 Danke Dir
mein Ansatz war mal wieder zu kompliziert

wenn man pcf ausliest erhölt man:

Code: Alles auswählen

[True, False, False, False, False, False, False, True]
die wollte ich zuerst in Zahlen umwandeln, Google hat mich dann zu numpy gebracht.

Das geht recht einfach. Angenommen Index 0 ist das höchstwertige Bit (MSB):

Code: Alles auswählen

def binlist_to_int(sequence, mode="msb"):
    if mode.lower() == "msb":
        sequence = reversed(sequence)
    elif mode.lower() != "lsb":
        raise ValueError("Only lsb or msb for mode")
    value = 0
    for bit, element in enumerate(sequence):
        if element:
            value += 2 ** bit
    return value
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
pumuckll
User
Beiträge: 56
Registriert: Donnerstag 30. August 2018, 17:45

Schönen Sonntag euch allen,

Danke für eure Tips und Hinweise.

"command" von partial hat mich von Anfang an verwirrt, aber ich denke jetzt hab ich es Verstanden.

Die Funktionen für i2C auslesen und setzen funktionieren soweit.

Ich habe aber noch zwei Schönheitsfehler:
1.

Code: Alles auswählen

print(b"Rm%d_K%d_%d" % (pcf_stelle+2, io_bit+1,io_bit_wert))
io_bit_wert liefert hier"0" oder "1", aber ich hätte gerne "False" oder "True"

wenn ich %s verwende, bekomm ich die meldung das b" nicht bool sein kann.

Wie könnte ich das am einfachsten lösen?

2.

die pcf Ein und Ausgänge sind aktive wenn das Bit False ist.

Das würde ich gerne Rückmelden.
Mit welcher Funktion kann ich die Einzelenen Bits invertieren.

also
pcf1.port = [True, True, True, True, True, True, True, True]
sollte 0 rückmelden

vermutlich sollte ich sie gleich nach dem auslesen invertieren.



Code: Alles auswählen

#!/usr/bin/env python3
"""V3.1
   Diese Script Sendet und empfängt UDP Nachrichten,
   um Ausgänge zu schalten und um  den Status von Eingängen, Ausgängen sowie von 1Wire Sensoren  auszugeben.
   """

import logging
import socket
import threading
from functools import partial
from logging.handlers import TimedRotatingFileHandler
from time import sleep
from pcf8574 import PCF8574
from RPi import GPIO  # RaspberryPi
#import OPi.GPIO as GPIO  # OrangePi

#Programm Einstellungen
# 1wire einstellungen True ode False
ONEWIRE_VORHANDEN = False
#Logger
# logging.DEBUG  logging.INFO
LOGGER_KONSTANTE = logging.DEBUG

# gpio und UDP für "keller", "garage", "door" oder "loxberry" einstellen
DEVICE = "keller-pi"
CLIENT = "10.10.10.30"

BUFFER_SIZE = 8192

SERVER = {"keller": ("", 8006), "garage": ("", 8008), "door": ("", 8010),
          "loxberry": ("", 8012),"keller-pi": ("", 8014)}
TARGET_HOST = {"keller": (CLIENT, 8005), "garage": (CLIENT, 8007),"door": (CLIENT, 8009),
               "loxberry": (CLIENT, 8011), "keller-pi": (CLIENT, 8013)}


#pcf8574
I2C_PORT_NUMMER = 1
PCF1_ADDRESS = 0x20 #Ausgänge   RM2 K1-K8 pcf_io_1-8
PCF2_ADDRESS = 0x21 #Ausgänge   RM3 K1-K8 pcf_io_9-16
PCF3_ADDRESS = 0x22 #Ausgänge   RM4 K1-K8  pcf_io_17-24
PCF4_ADDRESS = 0x24 #reserve Ausgänge RM4 K1-K8  pcf_io_25-32
PCF5_ADDRESS = 0x26 #Eingänge
PCF6_ADDRESS = 0x26 #Eingänge
PCF7_ADDRESS = 0x26 #Eingänge
PCF8_ADDRESS = 0x26 # reserve Eingänge

pcfs_out =[PCF8574(I2C_PORT_NUMMER, PCF1_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF2_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF3_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF4_ADDRESS)]
pcfs_in =[PCF8574(I2C_PORT_NUMMER, PCF5_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF6_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF7_ADDRESS), PCF8574(I2C_PORT_NUMMER, PCF8_ADDRESS)]


# logger
logger = logging.getLogger("Rotating Log")
logger.setLevel(LOGGER_KONSTANTE)
handler = TimedRotatingFileHandler("in_out.log", when='D', interval=1, backupCount=7, encoding=None,
                                   delay=False, utc=False, atTime=None)
fileformatter = logging.Formatter('%(asctime)s : %(levelname)s : %(name)s : %(message)s')
handler.setFormatter(fileformatter)
logger.addHandler(handler)
logger.info("logger started")


def create_command_dictionary(udp_socket):
    command_to_func = {
        b"tor_auf_zu": partial(tor_auf_zu, udp_socket),
        b"reply_loxone": partial(reply_loxone, udp_socket),
    }
    for pcf_stelle in range(0, 4):
        for bit in range(0, 8):
            command_to_func["Rm{}_K{}_ein".format(pcf_stelle + 2, bit + 1).encode()] = partial(set_io,
                                                                                               pcfs_out[pcf_stelle],
                                                                                               pcf_stelle, bit, False,
                                                                                               udp_socket)
    for pcf_stelle in range(0, 4):
        for bit in range(0, 8):
            command_to_func["Rm{}_K{}_aus".format(pcf_stelle + 2, bit + 1).encode()] = partial(set_io,
                                                                                               pcfs_out[pcf_stelle],
                                                                                               pcf_stelle, bit, True,
                                                                                               udp_socket)
    return command_to_func

udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udp_socket.bind(SERVER[DEVICE])



def reply_loxone(udp_socket, command):
    udp_socket.sendto(command, TARGET_HOST[DEVICE])

def tor_auf_zu(udp_socket, command):
    """tor öffner wird gedrückt"""
    udp_socket.sendto(command, TARGET_HOST[DEVICE])
    print("ok")

#pcf abschnitt

def set_io(pcfs,pcf_stelle, io_bit, io_bit_wert,udp_socket, command):
    pcfs.port[io_bit] = io_bit_wert
    print(pcfs.port[io_bit])
    print(b"Rm%d_K%d_%d" % (pcf_stelle+2, io_bit+1,io_bit_wert))
    udp_socket.sendto(command, TARGET_HOST[DEVICE])
    udp_socket.sendto(b"Rm%d_K%d_%d" % (pcf_stelle+2, io_bit+1,io_bit_wert), TARGET_HOST[DEVICE])
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Zu 1) gib doch einen String aus:

Code: Alles auswählen

print("Rm%d_K%d_%s" % (pcf_stelle+2, io_bit+1, io_bit_wert))
Wenn du immer nur pcf_stelle+2 benutzt, warum ist dann der Wert nicht von Anfang an 2 größer?

Code: Alles auswählen

def create_command_dictionary(udp_socket):
    command_to_func = {
        b"tor_auf_zu": partial(tor_auf_zu, udp_socket),
        b"reply_loxone": partial(reply_loxone, udp_socket),
    }
    for pcf_stelle in range(2, 6):
        for bit in range(0, 8):
            command_to_func["Rm{}_K{}_ein".format(pcf_stelle, bit + 1).encode()] = partial(set_io,
                                                                                               pcfs_out[pcf_stelle],
                                                                                               pcf_stelle, bit, False,
                                                                                               udp_socket)
            command_to_func["Rm{}_K{}_aus".format(pcf_stelle, bit + 1).encode()] = partial(set_io,
                                                                                               pcfs_out[pcf_stelle],
                                                                                               pcf_stelle, bit, True,
                                                                                               udp_socket)
    return command_to_func
Zu 2) der Operator heißt not.
pumuckll
User
Beiträge: 56
Registriert: Donnerstag 30. August 2018, 17:45

Zu 1) gib doch einen String aus:
Das hatte ich schon versucht, da bekomm ich diese Fehlermeldung.

Code: Alles auswählen

UDPServer Waiting for client on port : ('', 8014)
b'Rm2_K1_aus'
noch ok
b'Rm2_K1_aus'
True
end
Traceback (most recent call last):
  File "in_out.py", line 154, in <module>
    main()
  File "in_out.py", line 146, in main
    function(command)
  File "in_out.py", line 94, in set_io
    print(b"Rm%d_K%d_%s" % (pcf_stelle+2, io_bit+1,io_bit_wert))
TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'bool'
Wenn du immer nur pcf_stelle+2 benutzt, warum ist dann der Wert nicht von Anfang an 2 größer?
das dict hat die Einträge 0-3, die i2c relais fanegn bei Rm2 an, weil Rm1 von den gpio´s angesteuert wird.
Deswegen hab ich es so gelöst.
Sirius3
User
Beiträge: 17738
Registriert: Sonntag 21. Oktober 2012, 17:20

Mit "gib doch einen String aus" meinte ich, gib doch einen String aus:

Code: Alles auswählen

print("Rm%d_K%d_%s" % (pcf_stelle+2, io_bit+1,io_bit_wert))
Und statt irgendwelche künstlichen Indices zu verwenden, verwende doch die richtigen:

Code: Alles auswählen

#pcf8574
I2C_PORT_NUMMER = 1
PCF_ADDRESSES = {
    2: 0x20, # Ausgänge   RM2 K1-K8 pcf_io_1-8
    3: 0x21, # Ausgänge   RM3 K1-K8 pcf_io_9-16
    4: 0x22, # Ausgänge   RM4 K1-K8  pcf_io_17-24
    5: 0x24, # reserve Ausgänge RM4 K1-K8  pcf_io_25-32
}
PCFS_OUT = {
    port: PCF8574(I2C_PORT_NUMMER, address)
    for port, address in PCF_ADDRESSES.items()
}
pumuckll
User
Beiträge: 56
Registriert: Donnerstag 30. August 2018, 17:45

Sirius3 hat geschrieben: Sonntag 18. Oktober 2020, 13:10 Mit "gib doch einen String aus" meinte ich, gib doch einen String aus:

Code: Alles auswählen

print("Rm%d_K%d_%s" % (pcf_stelle+2, io_bit+1,io_bit_wert))
das Problem hab ich eher hier, aber diese Zeile benötige ich eigentlich nicht mehr und kommt weg

Code: Alles auswählen

udp_socket.sendto(b"Rm%d_K%d_%d" % (pcf_stelle, io_bit+1,io_bit_wert), TARGET_HOST)

das habe ich so umgesetzt danke
Sirius3 hat geschrieben: Sonntag 18. Oktober 2020, 13:10 Und statt irgendwelche künstlichen Indices zu verwenden, verwende doch die richtigen:

Code: Alles auswählen

#pcf8574
I2C_PORT_NUMMER = 1
PCF_ADDRESSES = {
    2: 0x20, # Ausgänge   RM2 K1-K8 pcf_io_1-8
    3: 0x21, # Ausgänge   RM3 K1-K8 pcf_io_9-16
    4: 0x22, # Ausgänge   RM4 K1-K8  pcf_io_17-24
    5: 0x24, # reserve Ausgänge RM4 K1-K8  pcf_io_25-32
}
PCFS_OUT = {
    port: PCF8574(I2C_PORT_NUMMER, address)
    for port, address in PCF_ADDRESSES.items()
}
Der code läuft soweit, exeptions und logging muss ich noch sinnvoll überarbeiten


https://bpa.st/TQ7A

Code: Alles auswählen

#pcf8574
I2C_PORT_NUMMER = 1

PCF_OUT_ADDRESSES = {
    2: 0x20, # Ausgänge   RM2 K1-K8 pcf_io_1-8
    3: 0x21, # Ausgänge   RM3 K1-K8 pcf_io_9-16
    4: 0x22, # Ausgänge   RM4 K1-K8  pcf_io_17-24
    5: 0x24, # reserve Ausgänge RM4 K1-K8  pcf_io_25-32
}
PCFS_OUT = {
    port: PCF8574(I2C_PORT_NUMMER, address)
    for port, address in PCF_OUT_ADDRESSES.items()
}

PCF_IN_ADDRESSES = {
    2: 0x26, #Eingänge
    3: 0x26, #Eingänge
    4: 0x26, #Eingänge
    5: 0x26, # reserve Eingänge
    
def create_command_dictionary(udp_socket):
    command_to_func = {
        b"reply_loxone": partial(reply_loxone, udp_socket),
        b"set_io_false_in": partial(set_io_tf, PCFS_IN, udp_socket, False),
        b"set_io_false_out": partial(set_io_tf, PCFS_OUT, udp_socket, False),
        b"set_io_true_in": partial(set_io_tf, PCFS_IN, udp_socket, True),
        b"set_io_true_out": partial(set_io_tf, PCFS_OUT, udp_socket, True),
    }

    for aus_nummer, aus_pin, initial_wert in zip(enumerate(PIN_AUS, start=1), PIN_AUS, INITIAL_AUS):
        command_to_func["ausgang_{}_ein".format(aus_nummer[0]).encode()] = partial(
            ausgang_setzen, udp_socket, aus_pin, not bool(initial_wert))
        command_to_func["ausgang_{}_aus" .format(aus_nummer[0]).encode()] = partial(
            ausgang_setzen, udp_socket, aus_pin, bool(initial_wert))

    for pcf_stelle in range(2, 6):
        for bit in range(0, 8):
            command_to_func["Rm{}_K{}_ein".format(pcf_stelle, bit + 1).encode()] = partial(set_io,
                                                                                           PCFS_OUT[pcf_stelle],
                                                                                           pcf_stelle, bit, False,
                                                                                           udp_socket)
            command_to_func["Rm{}_K{}_aus".format(pcf_stelle, bit + 1).encode()] = partial(set_io,
                                                                                           PCFS_OUT[pcf_stelle],
                                                                                           pcf_stelle, bit, True,
                                                                                           udp_socket)

    return command_to_func

#pcf abschnitt

def set_io(pcfs,pcf_stelle, io_bit, io_bit_wert,udp_socket, command):
    pcfs.port[io_bit] = io_bit_wert
    udp_socket.sendto(command, TARGET_HOST)
    udp_socket.sendto(b"Rm%d_K%d_%d" % (pcf_stelle, io_bit+1,io_bit_wert), TARGET_HOST)

def set_io_tf(pcfs, udp_socket, bool_wert, command):
    for index in range(2, 6):
        pcfs[index].port= [bool_wert, bool_wert, bool_wert, bool_wert, bool_wert, bool_wert, bool_wert, bool_wert]
        udp_socket.sendto(command, TARGET_HOST)

def pcf_io_werte(pcfs):
    """pcf_io_werte auslesen
       bitwise operations      """
    result = 0
    for index in range(5, 1,-1):
        for bit in pcfs[index].port:
            result = (result << 1) | (not bit)
    return result
Die einzelnen Bytes konnte ich umdrehen, aber die Reihenfolge der Bits stimmt noch nicht.

bei pcf_io_werte wir für das Relais K1 das bit8 gesetzt wird.

Ich finde aber keinen Ansatz um pcfs[index].port umzudrehen.

wie kann ich das machen?
Antworten