Author Topic: Betaversion der MQTT-Bindings 2.0  (Read 496 times)

rtrbt

  • Administrator
  • Newbie
  • *****
  • Posts: 20
    • View Profile
Betaversion der MQTT-Bindings 2.0
« on: January 24, 2019, 16:21:14 »
Moin,

Seit heute ist eine Beta-Version der MQTT-Bindings 2.0 verfügbar. Experimentiert damit, wir freuen uns auf Feedback, Bugs und mehr.

Die MQTT-Bindings werden jetzt, genau wie die Bindings anderer Programmiersprachen, automatisch generiert. Alle Bricks und Bricklets werden unterstützt. Die Bindings bilden die API der Python-Bindings ab, weshalb sie nicht rückwärtskompatibel zur alten MQTT-Proxy sind. Die MQTT-Proxy ist damit abgekündigt.

Die aktuellen Bindings, sowie Beispiele im examples-Ordner, sind angehangen.

Die Bindings hängen von Python >= 2.7.9 oder >= 3.4 und der Paho-Bibliothek (>= 1.3.1), die hier verfügbar ist, ab.

Die Dokumentation ist hier zu finden

Viel Spaß!

Erik

Edit:
Version 2.0.1:
- Fehlerbehandlung für JSON-Fehler in Python 2 überarbeitet.
« Last Edit: January 25, 2019, 12:33:27 by rtrbt »

Nic

  • Hero Member
  • *****
  • Posts: 1.418
  • Pano.photogr. - Just for fun: Delphi, C#...
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #1 on: January 28, 2019, 13:37:06 »
Hi Erik,
prima, dass ihr weiterhin das Mqtt Protokoll unterstützt.
Am alten Proxy habe ich immer geschätzt, dass man ohne eine Codezeile schreiben zu müssen, in einem Mqtt Client die Brick Daten adhoc sofort sehen konnte.

Verhält sich die neue Variante genauso, sprich auf Kommandozeile starten und anschließend mit Clients verbinden und subscriben?

Ev. habe ich das in den Doku übersehen: wie oder wo lässt sich der Mqtt-Broker Host/IP und Port angeben?

Gruß,
Nic

rtrbt

  • Administrator
  • Newbie
  • *****
  • Posts: 20
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #2 on: January 28, 2019, 13:53:50 »
Hi,
Die Bindings brauchen etwas mehr manuelle Arbeit als die alte Proxy. Damit ein MQTT-Client die Daten erhält, muss ein Callback registriert, oder (periodisch) ein Getter aufgerufen werden. Die MQTT-Bindings verhalten sich hier genauso wie die Bindings der Programmiersprachen.

MQTT-Broker-Verbindungsdaten lassen sich mit --broker-host [HOSTNAME/IP] und --broker-port [PORT] konfigurieren. Es gibt noch weitere Parameter für Authentisierung, Zertifikate usw., die mit --help angezeigt werden können. Ich werde das ganze aber mal noch in die Dokumentation einbauen.

Gruß,
Erik

piwo

  • Jr. Member
  • **
  • Posts: 69
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #3 on: February 07, 2019, 02:22:13 »
grossartig. alles gelesen. nix vestanden.
entweder bin ich ein trottel, oder ...
dacapo.

danke

piwo

  • Jr. Member
  • **
  • Posts: 69
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #4 on: February 10, 2019, 16:35:36 »
meine kommentare:

1)

(ich habe den code des "alten mqtt-proxys" wenigsten dazu nutzen könnnen, damit ich irgendwo mal ALLE möglichen imports finden kann :

die braucht man ja als erstes, wenn man include-code-generatoren für beliebige stacks schreiben will.

ein "import tinkerforge" ist ja eine noop !

2)

ich habe nirgends (aber vllt. bin ich auch zu deppert) code gefunden, wo zumindest ALLE deviceids in einer datenstruktur versammelt wären, die mir helfen bei meinen include-code-generatoren ...

geschweige denn fand ich subpackage-names und class-names mit key deviceid ...

3)

der naming-wahnsinn geht aber hier weiter ...

bisherige "essentielle" bezeichner z.b. f.d. temperatur bricklet in der 2. version :

- bricklet_temperature_v2 : import subpackage API
- BrickletTemperatureV2   : classname API
- 2113                    : deviceid API

nun kommt dazu :

- temperature_v2_bricklet  : mqtt-name
- TemperatureV2Bricklet    : classname mqtt-proxy
- Temperature Bricklet 2.0 : displayname mqtt-proxy

4)

ich habe ja den verdacht, dass ihr gar keine transparenz wollt.
geschweige denn, dass man

- API-funktionen von stacks dynamisch nutzen kann

- auch nur IN ANSATZ IRGENDETWAS wie introspektion (selbst mit dem vorhandenen source-code) zusammenbringt

5)

der neue mqtt-proxy ist wiederum eine "neuimplementierung" eines brickd

prozedural und wenig transparent.

keineswegs universell einsetzbar : denn es erfolgt keine klare architekturtrennung zwischen PSEUDO-BRICKD / ANWENDUNGSSCHICHT

ein weiteres indiz für meine hypothese, dass es kein interesse gibt, mehr transparenz und benutzerfreundlichkeit umzusetzen.
das gegenteil scheint mir der fall zu sein.

lg wp

borg

  • Administrator
  • Hero Member
  • *****
  • Posts: 2.980
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #5 on: February 11, 2019, 00:16:21 »
Ich glaube da hast du etwas missverstanden. Die MQTT-Bindings sind dazu da damit man Bricks/Bricklets per MQTT ansprechen kann. Die sind nicht dazu da um irgendetwas per Python zu machen. Das ist sozusagen ein Binary welches du ausführen kannst. Das wir den Code auch veröffentlichen ist nur Zugabe.

Zum Beispiel kann man damit über die MQTT-Anbindung von Node-RED Bricks/Brickelts nutzen.

Was du dir da anschaust ist generierter Code (genauso wie die Python-Bindings übrigens). Das ist so als würdest du dir generierten X86-Assembler anschauen und dich darüber wundern das es schlecht lesbar ist.

Wenn du wissen möchtest wie die MQTT-Bindings zustande kommen musst du hier schauen: https://github.com/Tinkerforge/generators/tree/master/mqtt
« Last Edit: February 11, 2019, 00:19:13 by borg »
Wir sind die Borg, Widerstand ist Spannung durch Stromstärke!

borg

  • Administrator
  • Hero Member
  • *****
  • Posts: 2.980
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #6 on: February 11, 2019, 01:16:05 »
Bezüglich deiner dynamischen ID + Name + Klasse-Problematik: Du kannst da dynamisch wie folgt dran kommen:

Code: [Select]
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from tinkerforge import device_factory

for device_id in device_factory.DEVICE_CLASSES:
    name = device_factory.get_device_display_name(device_id)
    cls  = device_factory.get_device_class(device_id)

    print("Device ID: {0}, Name: {1}, Class: {2}".format(device_id, name, cls))
Wir sind die Borg, Widerstand ist Spannung durch Stromstärke!

rtrbt

  • Administrator
  • Newbie
  • *****
  • Posts: 20
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #7 on: February 11, 2019, 09:22:18 »
Die MQTT-Bindings übersetzen die device_id übrigens automatisch auf den Devicenamen wie er in Topics verwendet wird und hängen in enumerate-Callback- und get_identity-Antworten den Display-Namen als _display_name-Feld an.

piwo

  • Jr. Member
  • **
  • Posts: 69
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #8 on: February 11, 2019, 10:32:43 »
ad device_factory :

... da hätte ich mir viel lebenszeit erspart, wenn man da mal in den docs mit der nase draufgestossen worden ware ...

piwo

  • Jr. Member
  • **
  • Posts: 69
    • View Profile
Re: Betaversion der MQTT-Bindings 2.0
« Reply #9 on: February 11, 2019, 11:39:58 »
bezüglich code-generatoren :

nicht nur ihr erzeugt code dynamisch.
das erzeugen von python-code, der anschliessend ausgeführt wird, ist ja essentiell bei dieser API-struktur ;-)

was aber ganz entscheidend fehlt, ist eine subclassierung aller funktionen in (daten)-getter/setter/callbacks,reine servicefunktionen und sonstige funktionen ...

eine introspektion oder sonstiger generatorcode, der das für jedes bricklet macht : nämlich die oben genannten (daten)-getter/setter/callbacks einer konkreten Bricklet-API als *** halbwegs klar lesbare datenstrukturen *** als python-code visuaisieren, damit man das auch sinnvoll debuggen bzw. den generator anpassen kann ....

am besten wärs ja, wenn man den generierten code gar nicht mehr bearbeiten oder modifizieren muss, weil alles notwendige zur laufzeit handle-bar ist ....

sowas macht z.b. der mqtt-proxy. ... einmal die bindings rein .... speziellen hooks dran um das dann von app-klassen nutzbar zu machen ....

sowas ist nicht die einzige anwendung, die sowas "braucht".
das macht mehr oder minder JEDE intelligente anwendung, die nicht so wie in euren beispielen statisch definiert wird :

mal den/die zielstacks runterenumierieren, die ipconn in entdlosschleife am leben erhalten und mit den gefundenen bricklets halt dann was sinnvolles machen ...

ich bevorzuge ja :

for stackdef in stackdefs: stack_start(stackdef)
"""
host,port,....
uids{} # key uid # meta-informationen der app bzw. wiring von/zur app
"""

def stack_starts(stackdef):
"""
ipconn starten, bei den dynamisch enumerierten mastern die "root master" zu finden, die dann resetten, warten, bricklet-uids der stackdef mit der ipconn initialisieren und dann einfach ein "stackstarted" callback an die app absetzen. irgendwelche exceptions, die sich durch einen impliziten disconnect oder sonstige troubles am stack ergeben wandern in ein "stackexception" callback, das die app dann auswertet und entweder den stack ewig neu startet, oder die app beendet nach einem retry_failure_count > N

RETURNS:

stack_callback_wrappers[] # status-callbacks f. exceptions bzw. die pseudo-exception "stack_started"

bricklet_function_wrappers{} # key : uid # generische wrapper zur bricklet-ansteuerung. entweder "direct-calls" oder mit funktionen aus den app-metainformationen angereichert
"""

damit hat man dann mal schon einen "running stack". ok.
was aber NICHT getan ist, ist ein GENERISCHES WIRING zwischen app und stack ...

für jedes bricklet muss ich mehr oder weniger auch metainformationen aus der doku einbringen, d.h. konkrete implementierungsschritte.

ich schreibe eine app für alle STACKS ja mit bestimmten klassen von bricklets : z.b. 2x irgendein temperatur-sensor, 1x *** irgendein aktor der die heizung schaltet ***

dieser aktor kann ALLES MÖGLICHE SEIN : ein digital-out der ein externes ssr schaltet oder auch ein ssr-bricklet direkt
aber auch die temperatur kann von einem ptc kommen oder auch was anderem. gott weiss.

KONSEQUENZ :

a) ich brauche klassen oder einen funktionsarray für ein generisches "turn on/turn off" bzw. "temperature" auf einer ganzen reihe von Bricklets, welche das denn zur laufzeit sind - gott weiss - aber dafür gibts dann ja die stackdef ;-)

b) selbst bei verschiedenen Bricklets ist nicht nur ein getter notwendig. so ist z.b. beim RemoteSwitch-Bricklet eine ganze funktionskette notwendig (da KANN ich gar nicht "blocking" arbeiten, sondern es muss eben exceptions wie "try_later" geben !!!)

c) desweiteren kann man nicht bei jedem Bricklet einfach EINE art von callback-struktur voraussetzen, die "einfach daten liefert". auch da ist oft eine ganze funktionslogik notwendig um die sonder- und sonstigen fälle abzudecken. für gewisse "alarm"-funktionen sind aber threshholds unabdingbar, weil getter ev. "zu spät" kommen und ein polling viel zu langsam ist (z.b.. distance-ir) ...

d) C O N C L U S I O

"GENERISCHES WIRING" ist daher nur möglich

1) zur LAUFZEIT für ALLE KLASSEN VON BRICKLETS
2) beim "mapping" auf konkrete stacks mit code-generatoren

introspektion bzw. LESBARE strukturen welche alle bricklets abstrakt definieren sind somit unabdingbar

---

ich löse DERZEIT das so, dass ich in der stackdef (siehe oben) generierten code verwende der möglichst eine generische weiterverwendung durch die app ermöglicht bzw. abstrakte klassen wie ACTOR/SENSOR die auf ganzen subsets von Bricklets arbeiten :

denn was wird man schon von einem Bricklet wollen : seine daten, egal wie es das liefert - bzw. es soll was machen, egal was das ist ;-) ...

... und damit bin ich wieder bein mqtt-proxy. dort läuft ziemlich genau DAS.

... wenn man DAS in einer beliebigen app kriegt, dann trifft das 100%

... und ich seh nicht ein, dass JEDER der tf-komponenten kauft GENAU DIESES RAD JEDESMAL NEU ERFINDEN BZW. NEI IMPLEMENTIEREN MUSS ...
« Last Edit: February 11, 2019, 12:37:02 by piwo »