Seite 2 von 4
Re: Funktion beenden
Verfasst: Mittwoch 8. März 2023, 18:01
von __deets__
Code: Alles auswählen
import uasyncio
import random
async def ir_system(callback):
while True:
await uasyncio.sleep(3)
# eines von zwei Kommandos, addr egal
callback(random.choice([1, 2]), None)
def callback(queue, val, _addr):
# Notwending, um die queue zu awaiten
uasyncio.create_task(queue.put(val))
async def task1():
while True:
print("task1")
await uasyncio.sleep(1)
async def task2():
while True:
print("task2")
await uasyncio.sleep(1)
async def dispatcher(queue):
task = None
while True:
command = await queue.get()
if task:
task.cancel()
coro = task1() if command == 1 else task2()
task = uasyncio.create_task(coro)
async def main():
command_queue = uasyncio.Queue()
# Simuliert das IR-System von dir, der callback
# muss die queue kennen, also benutze ich lambda
uasyncio.create_task(ir_system(lambda val, addr : callback(command_queue, val, addr)))
# verteilt die events auf die beiden tasks
await dispatcher(command_queue)
# main guard
if __name__ == '__main__':
uasyncio.run(main())
So klappt das. Die einzige Huerde ist das einfuegen in die Queue als asyncio-Task zu machen, weil die das natuerlich braucht, eigentlich macht man ja await q.put(..), aber da der callback synchron ist, muss man das als Task laufen lassen.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 14:45
von egon11
Danke. Aber wenn ich den Code 1:1 übernehme, dann kommt folgende Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "<stdin>", line 51, in <module>
File "uasyncio/core.py", line 1, in run
File "uasyncio/core.py", line 1, in run_until_complete
File "uasyncio/core.py", line 1, in run_until_complete
File "<stdin>", line 40, in main
File "uasyncio/__init__.py", line 1, in __getattr__
AttributeError: Queue
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 14:57
von __deets__
Das Programm ist notgedrungen auf dem Mac entstanden, und mit einem uasyncio-Emulationspaket. Da war die drin, und ich bin auf die gekommen wegen
https://github.com/peterhinch/micropyth ... d#35-queue
Fuer deine Plattform findet sich das wohl hier:
https://github.com/peterhinch/micropyth ... s/queue.py - er will, dass man das primitives Paket installiert. Musst du dann eben noch machen.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 15:05
von egon11
Nein das geht leider nicht zu installieren.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 15:07
von __deets__
Das ist bedauerlich, denn bei mir geht das immer problemlos. Dann kann man wohl nix machen.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 15:12
von egon11
Es geht im übrigen um den Raspberry Pico.
Aber es muss sich doch ein Weg finden, wie man eine Methode wieder beendet.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 15:20
von __deets__
Habe ich dir gezeigt. Das ist der Weg. Wenn du die dazu notwendigen Schritte nicht gehen kannst oder willst, erzeugt das keine magische Alternative, die dir vorher nur verschwiegen wurde.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 15:22
von egon11
OK wenn es nicht zu installieren geht ist es schade.
Trotzdem vielen dank.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 15:33
von __deets__
Da es bei mir problemlos(*) moeglich ist, Pakete auf meine micropython-basierten Controller zu packen, wuerde ich dazu raten, daran zu arbeiten.
* es ist manchmal schon etwas nervig, aber eigentlich muss man die dateien am Ende nur draufkopieren mit ampy zB.
Re: Funktion beenden
Verfasst: Donnerstag 9. März 2023, 19:34
von egon11
Jetzt habe ich die `Queue` Klassen direkt durch copy & paste eingefügt. Jetzt erkennt er auch Queue().
Wenn ich das richtig deute, funktioniert das ganze so, in der main-Klasse wird in uasyncio der Aufruf zum IR-System gemacht (in meinen Fall `ir = NEC_16(Pin(16, Pin.IN), callback)`) damit uasyncio weiß, das die callback-Methode zum asyncio gehört.
Anschließend wird in der main-Methode noch die Methode dispatcher aufgerufen und auch eine Instanz von Queue() übergeben.
In der Methode `dispatcher` wird mit `await queue.get()` ausgewertet, ob ein Befehl ausgeführt wurde? Dann wird geprüft ob task1 oder task2 ausgeführt werden soll.
Die Methoden callack kann ich mit meiner übersetzen und die Methode ir_system ist mit dem Befehl `ir = NEC_16(Pin(16, Pin.IN), callback)` gleichzusetzen.
Ist das so in etwa richtig?
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 10:53
von __deets__
Hm. Sind schon einige Fehlannahmen/Bezeichnungen dabei. Es gibt keine Klasse. Und der callback gehört genau nicht zum asyncio. Aber er delegiert den Queue.put Aufruf daran.
Versuch es umzubauen, zeig, was du hast, und man kann dazu Stellung beziehen.
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 12:07
von egon11
Mit `Queue` Klassen meinte ich, das ich die Module in /lib eingefügt habe.
Jetzt habe ich das Programm umgebaut, so dass es jetzt keinen Fehler ergibt.
Jetzt muss ich nur noch versuchen die jeweiligen Methoden zum starten und zum beenden bringen.
Warum starte ich die Methode `dispatcher` und die `ir_system` in main gleichzeitig?
Code: Alles auswählen
async def ir_system(callback):
ir = NEC_16(Pin(16, Pin.IN), callback)
def callback(queue, data, addr, ctrl):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
uasyncio.create_task(queue.put(val))
async def test1():
while True:
print("methode 1 zum ausfuhren")
await asyncio.sleep(1)
async def test2():
while True:
print("methode 2 zum ausfuhren")
await asyncio.sleep(1)
def callback(data, addr, ctrl):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
print(wert[data])
asyncio.run(start(wert[data]))
async def dispatcher(queue):
task = None
while True:
command = await queue.get()
if task:
task.cancel()
coro = task1() if command == 1 else task2()
task = uasyncio.create_task(coro)
async def main():
command_queue = Queue()
uasyncio.create_task(ir_system(lambda val, addr : callback(command_queue, val, addr)))
await dispatcher(command_queue)
if __name__ == '__main__':
uasyncio.run(main())
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 12:33
von __deets__
Du brauchst ir_System nicht. Das ist meine Simulation. Und du redest von Main-Klasse. Die gibts nicht.
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 13:24
von egon11
OK, ich muss also in mein() den callback aufrufen mit dem Argument der queue und gleichzeitig den dipatcher() aufrufen. Wenn in callback etwas passiert wird die Methode dispatcher aufgerufen und die Daten übermittelt. Ist das richtig?
Ich weiß jetzt nur nicht wie ich in main() den 'NEC_16(Pin(16, Pin.IN), callback)' Befehl aufrugfe. Es muss ja noch die queue übergeben werden.
Code: Alles auswählen
async def test1():
while True:
print("methode 1 zum ausfuhren")
await asyncio.sleep(1)
async def test2():
while True:
print("methode 2 zum ausfuhren")
await asyncio.sleep(1)
def callback(queue,data, addr, ctrl):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
uasyncio.create_task(queue.put(val))
async def dispatcher(queue):
task = None
while True:
command = await queue.get()
if task:
task.cancel()
coro = task1() if command == 1 else task2()
task = uasyncio.create_task(coro)
async def main():
command_queue = Queue()
uasyncio.create_task(NEC_16(Pin(16, Pin.IN), callback))
await dispatcher(command_queue)
if __name__ == '__main__':
uasyncio.run(main())
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 13:28
von __deets__
Ich zeige doch mit dem lambda wie man einen callback baut, der die definierten zwei Argumente bekommt, UND die queue weitergibt.
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 14:19
von egon11
Ja das stimmt, aber der das die Callback-Funktion nur mit der Referenz aufgerufen werden soll 'NEC_16(Pin(16, Pin.IN), callback)' kann ich ja keine Argumente übergeben.
Oder kann ich das anders lösen?
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 14:33
von __deets__
Nochmal: das geht genau so wie ich es vormache. Mit dem lambda.
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 14:44
von egon11
Genau, so habe ich es auch gemacht.
Code: Alles auswählen
uasyncio.create_task(NEC_16 (lambda val, addr : callback(command_queue, val, addr)))
und die callback-Funktion
Code: Alles auswählen
def callback(queue, data, addr, ctrl):
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
uasyncio.create_task(queue.put(val))
Leider funktioniert es so nicht.
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 14:58
von __deets__
“Funktioniert nicht” ist keine ordentliche Fehlermeldung.
Re: Funktion beenden
Verfasst: Freitag 10. März 2023, 15:23
von egon11
Eine Fehlermeldung gibt es nicht, sondern wenn ich auf der Fernbedienung etwas drücke, gibt es keine Ausgabe, es müsste wenigstens eine Ausgabe erfolgen.
Kann das sein, das durch die lambda und den verbundenen Klammern für die callback-Funktion nicht die Referenz übergeben wird, sondern die Methode direkt ausgeführt wird?
Edit: hab mal den Pico neu gestartet, war wohl etwas festgefahren, jetzt kommt gibt es eine Fehlermeldung aus:
Code: Alles auswählen
Traceback (most recent call last):
File "<stdin>", line 40, in <module>
File "uasyncio/core.py", line 1, in run
File "uasyncio/core.py", line 1, in run_until_complete
File "uasyncio/core.py", line 1, in run_until_complete
File "<stdin>", line 35, in main
TypeError: function takes 4 positional arguments but 3 were given
Code: Alles auswählen
import time
from machine import Pin
from ir_rx import NEC_16
import uasyncio
from queue import Queue
async def test1():
while True:
print("methode 1 zum ausfuhren")
await asyncio.sleep(1)
async def test2():
while True:
print("methode 2 zum ausfuhren")
await asyncio.sleep(1)
def callback(queue, data, addr,ctl):
print("huhu")
if data > 0: # NEC protocol sends repeat codes.
print('Data {:05x} Addr {:04x}'.format(data, addr))
uasyncio.create_task(queue.put(val))
async def dispatcher(queue):
task = None
while True:
command = await queue.get()
if task:
task.cancel()
coro = task1() if command == 1 else task2()
task = uasyncio.create_task(coro)
async def main():
command_queue = Queue()
uasyncio.create_task(NEC_16 (lambda val, addr : callback(command_queue, val, addr)))
# ir = NEC_16(Pin(16, Pin.IN), callback)
await dispatcher(command_queue)
if __name__ == '__main__':
uasyncio.run(main())
# ir = NEC_16(Pin(16, Pin.IN), callback)