Python variable ändern (erhöhen oder verringern)?
Ich bin ein absoluter Anfänger was programmieren angeht, lerne aber immer mehr und mehr dazu. Ich möchte für etwas ein Python Script erstellen, was auf meinem Pi die ganze Zeit läuft und die MQTT Nachrichten mitliest, um diese auszuführen und/oder eine Nachricht zurück zu senden.
Ich habe versucht eine Nachricht zu senden der den wert der Variable um 1 erhöhen soll und damit auch die While schleife aktivieren soll. Jedoch funktioniert es nicht, da die variable nicht in "def on_message" verfügbar ist und es die Erhöhung quasi nicht nach außen austrägt.
Was gibt es für Möglichkeiten die variable zu erhöhen, sodass sich die while schleife aktiviert? Und gibt es auch andere Ansätze wie man eine diese Schleife machen kann?
Script:
import paho.mqtt.client as mqtt
import os
import subprocess
import time
import smbus2
import bme280
#Bme280_basic Temperature
# BME280 sensor address (default address)
address = 0x76
# Initialize I2C bus
bus = smbus2.SMBus(1)
# Load calibration parameters
calibration_params = bme280.load_calibration_params(bus, address)
# to activate loop
y = int(1)
#Temperature loop
while y == 2:
data = bme280.sample(bus, address, calibration_params)
# Extract temperature, pressure, and humidity
temperature_celsius = data.temperature
# Print the readings
print("Temperature: {:.2f} °C".format(temperature_celsius))
# Wait for a few seconds before the next reading
time.sleep(2)
#print(y)
else:
print("stopped")
#Connection successfull
def on_connect(client, userdata, flags, rc):
print("Connected to MQTT broker")
#Checking for messages to execute code
def on_message(client, userdata, msg):
print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))
if msg.payload.decode() == "temp_bme280_start":
print("Calling script to for temperature start...")
# activate loop by adding 1
y += 1
print(y)
if msg.payload.decode() == "temp_bme280_stop":
print("Calling script to for temperature stop...")
# deactivate loop by remove 1
y -= 1
print(y)
def on_subscribe(client, userdata, mid, granted_qos):
print("Subscribed to topic : " + str(mid) +" with QoS" + str(granted_qos))
client = mqtt.Client()
client.username_pw_set( "userxxx" , "passwortxxx" )
client.connect( "192.16x.xxx.xxx", 1883, 60)
client.subscribe( "frame/monitor" , qos=1)
client.on_connect = on_connect
client.on_message = on_message
client.loop_forever()
Würde Chat GPT sowas lösen können?
2 Antworten
Deine Frage demonstriert, dass man Programmieren schrittweise lernen und nicht die Grundlagen überspringen sollte. ChatGPT nutzt dir auch nicht viel, wenn du nicht beurteilen kannst, ob der Code richtig ist.
Die Variable y ist in den Funktionen nicht fürs Schreiben sichtbar, wie du richtig bemerkt hast.
Jetzt hast du grob gesagt zwei Möglichkeiten:
- Die nicht sehr schöne, aber "einfache": du machst diese globale Variable auch innerhalb der Funktionen beschreibbar. Das geht mit dem Schlüsselwort global.
- Die korrekte. Bei solchen Callback-APIs gibt es praktisch immer die Möglichkeit, Benutzerdaten mitzugeben - eben genau damit man diese lesen und schreiben kann. Du siehst das ja auch in den Parameterlisten der Callbacks, da gibt es einen Parameter "userdata". Was da hineinkommt, bestimmst du selbst, siehe https://eclipse.dev/paho/files/paho.mqtt.python/html/client.html#paho.mqtt.client.Client.user_data_set - sinnvollerweise übergibt man da irgendeine Datenstruktur, die in sich veränderlich ist. Eine einfache Möglichkeit ist ein Dictionary, und da kannst du dann nach Herzenslust Werte ändern. Dieser Ansatz ist übrigens auch in der Einführung anhand eines Beispiels dokumentiert: https://pypi.org/project/paho-mqtt/#callbacks
y = int(1)
while y == 2:
Die Schleife kann gar nicht betreten werden, wenn y nie 2 wird, das ist ein offenkundiges Problem. Gibt es einen spezifischen Grund, warum Du y auf 1 anstatt 2 initialisierst?
Daß in Deinen Eventhandler y nicht geändert werden kann (wegen des Scopings) könnte man auch durch Nutzung einer Klasse lösen.
client = mqtt.Client()
client.username_pw_set( "userxxx" , "passwortxxx" )
client.connect( "192.16x.xxx.xxx", 1883, 60)
client.subscribe( "frame/monitor" , qos=1)
client.on_connect = on_connect
client.on_message = on_message
client.loop_forever()
Die Reihenfolge hier ist fehlerhaft.
Du führst erst einen connect aus, um danach den Callback für den erfolgten Connect zu registrieren, callbacks werden vorher registriert (siehe Doku).
Also, instanziieren, Callbacks registrieren, Nutzerdaten setzen, Verbindung herstellen.
Bezüglich des anderen Themas, Du willst eigentlich ein Synchronisierungsprimitiv nutzen auf das Deine Callbacks wirken.
Nur wird on_message eben nicht VOR der Schleife ausgeführt, sondern asynchron als Callback, irgendwann nachdem loop_forver() aufgerufen wurde.
Ja es gibt einen Grund, denn die Schleife soll nicht von Anfang an laufen, sondern soll sich aktivieren und deaktivieren. Also wenn ich den y Wert auf 2 setze sollte es sich aktivieren und zurück auf 1 soll diese Deaktiviert werden.
Was genau ist an der Reihenfolge fehlerhaft? Und wieso? Habe diese aus dem Internet übernommen aus einem anderen script, was den selben Ansatz folgt wie mein python Code.