Binärdaten in Text konvertieren | Raute mit Fragezeichen...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
root76
User
Beiträge: 6
Registriert: Donnerstag 1. Juli 2021, 08:03

Hallo Forum,

Das ist mein erster Beitrag hier und ich bin ein absoluter Python-Neuling! :roll:
Ich versuche zwischen zwei Raspis eine LoRa-Datenübertragung hinzubekommen. Dazu gab es vom Hersteller ein Demo-Programm auf dem ich jetzt aufbaue und es erweitere...

Das Programm gibt sekündlich einen Textstring aus. Zudem kann man in dem Modul (https://www.waveshare.com/wiki/SX1268_4 ... figuration) ein Bit setzen dass am Ende des Strings noch den RSSI (Aussage zur Signalstärke der Verbindung) gibt. Laut Datenblatt geschieht das in Form eines Bytes.

Die Ausgabe im Terminal des Raspis ist z.B. 30.06.2021 23:14:34 mit RSSI: �
Und da seht ihr es. Dieses Karo mit dem Fragezeichen drin. Das ist mein Problem.

Wie ich es verstehe sind es Binärdaten und kein Text, daher muss ich diesen Teil konvertieren. Hier mal ein Stück Code:

Code: Alles auswählen

if r_buff != "" :
                                        print(r_buff)
                                        rssi = (r_buff[-1:])
                                        rssi = rssi.decode("utf-8")
                                        print(rssi)
                                        r_buff = ""
r_buff ist natürlich der receive-buffer. Den gebe ich testweise erstmal einfach aus. Dann habe ich gelernt wie man daraus einen Teil extrahiert, also nur das Zeichen. Das habe ich dann bisher vergeblich versucht zu wandeln. Die Zeile mit dem utf-8 funktioniert nicht.

So, viel geschrieben. Kann mir jemand helfen? Wie kann ich dieses Zeichen konvertieren?
Sirius3
User
Beiträge: 17759
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast kein Zeichen, sondern ein Byte, und dieses Byte kannst Du einfach als Zahl weiterverarbeiten:

Code: Alles auswählen

if received_bytes:
    rssi = received_bytes[-1]
    print(rssi)
root76
User
Beiträge: 6
Registriert: Donnerstag 1. Juli 2021, 08:03

Mit diesem Code kommt immer noch die Raute mit Fragezeichen.
Ich habe mal mit

Code: Alles auswählen

print(type(rssi))
den Typ ermitteln lassen. Die Ausgabe ist: <type 'str'>
Aber im Datenblatt des Moduls steht, "After enabling, data sent to serial port is added with a RSSI byte after receiving". Komisch.
Sonst noch eine Idee? :wink:
Sirius3
User
Beiträge: 17759
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn das vom Typ String ist, dann mußt Du schon vorher angreifen. Wie sieht denn der gesamte Code zum Lesen aus?
root76
User
Beiträge: 6
Registriert: Donnerstag 1. Juli 2021, 08:03

Kann gerade nicht auf den Raspi zugreifen. Aber der Originalcode steht auf https://github.com/aparcar/waveshare_sx ... sparent.py
Ich habe das Programm gekürzt/verschlankt. Die wesentliche Funktion ist aber identisch.
Relevant ist hier der Bereich um Zeile 78.

Dieses Standard Demoprogramm wird auf zwei Raspis mit diesen LoRA-Hats ausgeführt. Ein Sender und ein Empfänger. Das Ganze geht über die UART Schnittstelle. Im Standardprogramm wird nur ein normaler Text übertragen, nicht dieser RSSI Wert. Daher gibt es im Standardprogramm auch kein Problem mit der Raute mit Fragezeichen...

Danke für die Mühen schonmal.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Arbeitest du noch mit Python 2? Das ist ein ☠️ 🐴. Nimm Python 3, und dann wird Sirius3 Hinweis auch passen.
Sirius3
User
Beiträge: 17759
Registriert: Sonntag 21. Oktober 2012, 17:20

An dem Code sind die üblichen Probleme.
Warnungen sollte man beheben, nicht ignorieren. Eine falsche Benutzung von `except`. Keine Funktionen, sondern ein langer Block Spaghetti-Code.
Die Einrückungen sind inkonsistent. Eingerückt wird immer mit 4 Leerzeichen pro Ebene.
So wie das Lesen von der Seriellen Schnittstelle gestaltet ist, ist das nicht sehr robust.
Die Implementierung mischt die Konfiguration des Moduls mit der Übertragung. Das kann funktionieren, aber niemand versteht es und es ist unmöglich, da Fehler zu finden.

Wenn Du immer als Typ str bekommst, dann benutzt Du noch Python2. Steig auf Python3 um.

Code: Alles auswählen

#!/usr/bin/python3
from RPi import GPIO
import serial
import time
import sys
	
PIN_M0 = 22
PIN_M1 = 27

CONFIGURATION = {
    "BROADCAST_AND_MONITOR": (
        b'\xC2\x00\x09\xFF\xFF\x00\x62\x00\x17\x03\x00\x00', # send
        b'\xC1\x00\x09\xFF\xFF\x00\x62\x00\x17\x03\x00\x00', # recv
    ),
    "P2P": (
        b'\xC2\x00\x09\x00\x00\x00\x62\x00\x17\x03\x00\x00', # send
        b'\xC1\x00\x09\x00\x00\x00\x62\x00\x17\x03\x00\x00', # recv
    )
}


def initialize(ser, mode):
    GPIO.setmode(GPIO.BCM)
    GPIO.setup([PIN_M0, PIN_M1], GPIO.OUT)
    GPIO.output(PIN_M0, GPIO.LOW)
    GPIO.output(PIN_M1, GPIO.HIGH)
    time.sleep(1)
    configuration, expected_answer = CONFIGURATION[mode]
    ser.reset_input_buffer()
    ser.write(configuration)
    answer = ser.read(len(expected_answer))
    if expected_answer != answer:
        print("something went wrong")
    print(f"{mode} mode is activated")
    GPIO.output(PIN_M1, GPIO.LOW)
    time.sleep(0.01)

def main():
    if len(sys.argv) != 2 or sys.argv[1] not in CONFIGURATION:
        print("you must provide one argument: BROADCAST_AND_MONITOR or P2P")
        sys.exit(1)

    try:
        with serial.Serial("/dev/ttyS0", 9600) as ser:
            initialize(ser, sys.argv[1])
            ser.timeout = 20
            while True:
                line = ser.read_until("\n")
                if line:
                    print('received message')
                    print(line)
                else:
                    print('send message')
                    ser.write("This is a P2P message\r\n".encode())
    finally:
        GPIO.cleanup()

if __name__ == "__main__":
    main()
root76
User
Beiträge: 6
Registriert: Donnerstag 1. Juli 2021, 08:03

Ich habe das Programm bisher immer einfach mit "sudo python rx4.py "gestartet. Das ist also python ohne 3 :-) Mit python3 gab es eine Fehlermeldung aber mit Python hat es erstmal funktioniert, deshalb bin ich dabei geblieben. Bin ja wie gesagt Anfänger (arbeite sonst immer mit shellscript und selten mal mit C++).

OK, danke erstmal. Ich versuchs mal mit python3 und melde mich später wieder.
root76
User
Beiträge: 6
Registriert: Donnerstag 1. Juli 2021, 08:03

Soo, nun. Das ist jetzt erstmal das gekürzte Programm welches ich auf der Empfängerseite laufen lasse:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import RPi.GPIO as GPIO
import serial
import time
import sys

M0 = 22
M1 = 27

CFG_REG = b'\xC2\x00\x09\x00\x00\x00\x62\x00\x17\x83\x29\xA3' # Konfiguration siehe Datei "param"
RET_REG = b'\xC1\x00\x09\x00\x00\x00\x62\x00\x17\x83\x29\xA3'

r_buff = ""
delay_temp = 1

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(M0,GPIO.OUT)
GPIO.setup(M1,GPIO.OUT)

GPIO.output(M0,GPIO.LOW)
GPIO.output(M1,GPIO.HIGH) # In Config-Modus schalten
time.sleep(1)

ser = serial.Serial("/dev/ttyAMA0",9600)
ser.flushInput()
try :
                if ser.isOpen() :
                        ser.write(CFG_REG) # Das Register wird konfiguriert, einmalig
                while True :
                        if ser.inWaiting() > 0 :
                                time.sleep(0.1)
                                r_buff = ser.read(ser.inWaiting())
                                if r_buff == RET_REG : #
                                        #print("P2P mode was actived")
                                        GPIO.output(M1,GPIO.LOW) # Config-Modus abschalten, fertig konfiguriert
                                        time.sleep(0.01)
                                        r_buff = ""
                                if r_buff != "" :
                                        print(r_buff)
                                        rssi = r_buff[-1]
                                        print(rssi)
                                        r_buff = ""
except :
        if ser.isOpen() :
                ser.close()
        GPIO.cleanup()
Wenn ich es mit "sudo python rx4.py" starte lautet die Ausgabe:
01.07.2021 21:52:10 mit RSSI: �

01.07.2021 21:52:11 mit RSSI: �

01.07.2021 21:52:13 mit RSSI: �

01.07.2021 21:52:14 mit RSSI: �

und so weiter...

Wenn ich es, wie vorgeschlagen, mit "sudo python3 rx4.py" starte bekomme ich:
Traceback (most recent call last):
File "rx4.py", line 5, in <module>
import serial
ModuleNotFoundError: No module named 'serial'


Ich kann da keinen Fehler finden in Zeile 5...
So weit. Habt ihr noch eine Idee? Sollte ich den Zeileneinschub wie vorgeschlagen anpassen, oder ist das nur Kosmetik? Habe schon bemerkt dass es eine Rolle spielt, in Python.
Sirius3
User
Beiträge: 17759
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast pySerial nicht für Python3 installiert, daher der Fehler.
Und wie ich schon geschrieben habe, ist das ganze Programm nicht sauber programmiert.
root76
User
Beiträge: 6
Registriert: Donnerstag 1. Juli 2021, 08:03

Sagenhaft! Jetzt funktionierts. :)
Hätte nicht gedacht dass ich diese Komponente separat dazu installieren muss (sudo apt install python3-serial).
So komme ich erstmal ein erhebliches Stück weiter mit dem Projekt. Mal sehen wo es als nächstes hängt...
Die Ausgabe ist jetzt:
b'02.07.2021 09:04:36 mit RSSI: \xdb'
219
b'02.07.2021 09:04:37 mit RSSI: \xdc'
220
b'02.07.2021 09:04:38 mit RSSI: \xdc'
220
und so weiter... Werde das schon hinbekommen...

Also vielen Dank an euch!!
Antworten