Topic mit Leerzeichen oder Doppelpunkt funktioniert nicht

Begonnen von John, 29 Dezember 2017, 00:25:19

Vorheriges Thema - Nächstes Thema

John

ich möchte folgendes Kommando absetzen:

set MyBroker publish  hm/set/HM-LC-Bl1PBU-FM OEQ0294000:1/LEVEL 1

Das klappt leider nicht, da sich im Topic ("hm/set/HM-LC-Bl1PBU-FM OEQ0294000:1/LEVEL") ein Leerzeichen befindet.

Gibt es hierzu eine Lösung ?
CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

hexenmeister

Wird nicht klappen. Beim publish wird die Eingabe ja bereits zerlegt geliefert. Ein Teil wird zum Topic, der Rest wieder per join und als Value gesendet.
Warum muss der Topic genau so heißen?
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

John

Am Aufbau der Topics kann ich nicht wirklich was ändern.

Ich verwende in der CCU2 das Addon HM2MQTT, das genau diese Art von Topics generiert.

https://github.com/owagner/hm2mqtt

Subscribe funktioniert tadellos, nur beim Publishen kommt es zu den beschriebenen Problemen.

Ein Topic mit einem Leerzeichen vom MQTT-Standard verboten ?

CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

hexenmeister

Bis auf einen kleinen Rest (mehrefache Leerzeichen nacheinander werden zu einem), müsste 'parseParams' (https://wiki.fhem.de/wiki/DevelopmentModuleAPI#parseParams) die Lösung sein. Dann könnte man mit ' oder " Zeichen arbeiten. Was MQTT-Standard zu den Leerzeichen sagt, weiß ich jedoch nicht.
Jetzt muss man nur implementieren, testen, 'nen Patch erstellen und den Maintainer um die Übername bitten.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

John

Danke für den Hinweis.

Was der Standard zum Aufbau von Topics sagt:


ZitatTopic name
A UTF-encoded string.
This must not contain Topic wildcard characters.
When received by a client that subscribed using wildcard characters, this string will
be the absolute topic specified by the originating publisher and not  the subscription string used by the client.
CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

John

#5
Auch ein Doppelpunkt im Topic macht Probleme.
Habe daher den Titel des Threads geändert.

Dieser wird als Separator in den key/value-parametern wie "qos" verwendet.

Das Problem betrifft mindestens auch das Modul MQTT_DEVICE.

CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

hexenmeister

Mist. Damit wird eine abwärtskompatibele Lösung schwierig  >:(
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

John

Ich habe nun einige Anpassungen bei den Modulen im Anhang vorgenommen:

* Topics können nun in Hochkommata gesetzt werden, so daß Leerzeichen und Doppelpunkt nicht als Separator interpretiert werden
* diese Maßnahmen sind nur beim den "set Publish" Kommandos berücksichtigt, beim Subscriben gab es ohnehin keine Probleme

funktionierendes Beispiel für MQTT_DEVICE mit Doppelpunkt und Leerzeichen im Topic

attr EG.HW.HM.ROLL publishSet_LEVEL 0 1 'hm/set/HM-LC-Bl1PBU-FM OEQ0294212:1/LEVEL'


Das MQTT-Modul kann  nun mit folgendem Befehl umgehen:


set MyBroker publish 'hm/set/HM-LC-Bl1PBU-FM OEQ0294212:1/LEVEL' 0.7


Vielleicht mag der eine oder andere die Änderungen noch gegen seine Installation testen.

In etwa einer Woche werde ich dem Maintainer den Änderungsvorschlag unterbreiten.

CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP


hexenmeister

Ähhhm... Darf ich fragen, warum die Methode 'parseParams' in die 00_MQTT.pm reinkopiert wurde anstatt sie aus fhem.pl zu benutzen? :o
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

eisler

parseParams  fhem.pl
my ($key, $value) = split( '=', $param, 2 );
parseParams 00_MQTT.pm
my ( $key, $value ) = split( ':', $param, 2 );

Grüße
Stephan

hexenmeister

Stimmt, danke. Irgendwie trotzdem suboptimal. Schade, dass die Originalmethode nicht parametrisierbar ist. :(
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Definitiv suboptimal. Habe nach dem Update auf meinem Entwicklung-FHEM mich nicht schlecht gewundert, dass nichts mehr geht... Tja, in meinem MQTT_GENERIC_BRIDGE-Modul nutze ich auch Methode parseParams (aus fhem.pl) und importiere Methoden aus den Packages main und MQTT. Dort wird jetzt eine Methode mit dem selben Namen definiert und auch exportiert. Hat natürlich mein Modul auch diese neue 'gefunden' und es hat nichts mehr gepasst :o
Ich wäre zumindest für einen neuen Namen. Ich kann auch gerne bei Gelegenheit einen Patch erstellen.
Habe meine Problem jetzt durch Eingabe von Package gelöst.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

eisler

doof.  :( Quickfix finde ich nicht so toll dann lieber ein Patch der auch auf MQTT_GENERIC_BRIDGE abgestimmt ist.

Grüße
Stephan

hexenmeister

Ja, muss man schauen, wie man das am saubersten löst. Eine bahnbrechende Idee habe ich noch nicht.  :-\
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

persching

Also irgendwie hab ich immer noch das Problem, dass ich keine Doppelpunkte bei subscribeReading_Status state/socket/switch/EC:FA:BC:13:0E:01
Das Ganze hat folgenden Hintergrund:
Ich habe aufgrund des Berichtes in der c´t die Sonoff Steckdosen mit der zugehörigen Software geflashed. Und um mehrere gleichzeitig nutzen zu können und nicht ständig einen neuen Sketch zu erstellen habe ich gedachte ich verwende einfach die MAC-Adresse im Topic. Das funktioniert beim publishSet ohne Probleme, ich kann die Steckdose ein- und ausschalten. Einzig die Rückmeldung funktioniert in Verbindung mit der MAC-Adresse nicht. Wenn ich die Doppelpunkte entferne kommt keine Fehlermeldung, mit den Doppelpunkten kommt "Topic may not be empty"

hexenmeister

#16
Habe ein wenig getestet. Die Lösung ist leider nicht vollständig.
Grundsätzlich wird wohl versucht, den String in Anführungszeichen als Ganze zu betrachten. Funktioniert komischerweise auch, wenn dabei darin ein Leerzeichen vorkommt. Aber nur, wenn dieser vor dem ersten Doppelpunkt steht. Sonst wird der Doppelpunkt, trotz Anführungszeichen, als Trenner verstanden (aber nur der erste!).

Das geht beides nicht:

fhem> {Dumper(MQTT::parseParams('state/socket/switch/EC:FA:BC:13:0E:01'))}
$VAR1 = [];
$VAR2 = {
          'state/socket/switch/EC' => 'FA:BC:13:0E:01'
        };

fhem> {Dumper(MQTT::parseParams('"state/socket/switch/EC:FA:BC:13:0E:01"'))}
$VAR1 = [];
$VAR2 = {
          '"state/socket/switch/EC' => 'FA:BC:13:0E:01"'
        };


Das schon (man beachte den Leerzeichen):

fhem> {Dumper(MQTT::parseParams('"state/socket/swi tch/EC:FA:BC:13:0E:01"'))}
$VAR1 = [
          'state/socket/swi tch/EC:FA:BC:13:0E:01'
        ];
$VAR2 = {};


Ohne Anführungszeichen wieder nicht:

fhem> {Dumper(MQTT::parseParams('state/socket/swi tch/EC:FA:BC:13:0E:01'))}
$VAR1 = [
          'state/socket/swi'
        ];
$VAR2 = {
          'tch/EC' => 'FA:BC:13:0E:01'
        };


Das dann auch nicht (auch ein Leerzeichen, jedoch nach dem Doppelpunkt):

fhem> {Dumper(MQTT::parseParams('"state/socket/switch/EC:F A:BC:13:0E:01"'))}
$VAR1 = [];
$VAR2 = {
          '"state/socket/switch/EC' => 'F',
          'A' => 'BC:13:0E:01"'
        };


Die Methode muss leider bezüglich Anführungzeichen korrigiert werden.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Lösungsvorschlag:

Nach dem Block

        # the key can not start with a { -> it must be a perl expression # vim:}
        }
        elsif ( $key =~ m/^\s*{/ ) {    # for vim: }
            $value = $param;
            $key   = undef;
        }

noch eine ähnliche Prüfung für Anführungszeichen einzubauen:

        # the key can not start with a ' or "  # vim:"'
        elsif ( $key =~ m/^\s*('|")/ ) {    # for vim: "'
            $value = $param;
            $key   = undef;
        }


Ich habe kurz getestet, scheint korrekt zu funktionieren. Muss aber jemand am besten noch drüber schauen. Mir ist es heute schon zu spät (und der Wecker klingelt in 4 Stunden >:().

Komplette Methode:
sub parseParams($;$$) {

    my ( $cmd, $separator, $joiner ) = @_;
    $separator = ' '        if ( !$separator );
    $joiner    = $separator if ( !$joiner );   # needed if separator is a regexp
    my ( @a, %h );

    my @params;
    if ( ref($cmd) eq 'ARRAY' ) {
        @params = @{$cmd};
    }
    else {
        @params = split( $separator, $cmd );
    }

    while (@params) {
        my $param = shift(@params);
        next if ( $param eq "" );
        my ( $key, $value ) = split( ':', $param, 2 );

        if ( !defined($value) ) {
            $value = $key;
            $key   = undef;

        # the key can not start with a { -> it must be a perl expression # vim:}
        }
        elsif ( $key =~ m/^\s*{/ ) {    # for vim: }
            $value = $param;
            $key   = undef;
        }
        # the key can not start with a ' or "  # vim:"'
        elsif ( $key =~ m/^\s*('|")/ ) {    # for vim: "'
            $value = $param;
            $key   = undef;
        }

        #collect all parts until the closing ' or "
        while ( $param && $value =~ m/^('|")/ && $value !~ m/$1$/ ) {
            my $next = shift(@params);
            last if ( !defined($next) );
            $value .= $joiner . $next;
        }

        #remove matching ' or " from the start and end
        if ( $value =~ m/^('|")/ && $value =~ m/$1$/ ) {
            $value =~ s/^.(.*).$/$1/;
        }

        #collect all parts until opening { and closing } are matched
        if ( $value =~ m/^\s*{/ ) {    # } for match
            my $count = 0;
            for my $i ( 0 .. length($value) - 1 ) {
                my $c = substr( $value, $i, 1 );
                ++$count if ( $c eq '{' );
                --$count if ( $c eq '}' );
            }

            while ( $param && $count != 0 ) {
                my $next = shift(@params);
                last if ( !defined($next) );
                $value .= $joiner . $next;

                for my $i ( 0 .. length($next) - 1 ) {
                    my $c = substr( $next, $i, 1 );
                    ++$count if ( $c eq '{' );
                    --$count if ( $c eq '}' );
                }
            }
        }

        if ( defined($key) ) {
            $h{$key} = $value;
        }
        else {
            push @a, $value;
        }

    }
    return ( \@a, \%h );
}
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Ich würde sages, es funktioniert.
Patch und die ganze geänderte Datei im Anhang.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

persching

Ich habe die komplett geänderte Datei in /opt/fhem/FHEM kopiert, den Owner und die Berechtigungen analog der anderen Dateien gesetzt, shutdown restart ausgeführt und versucht den die Doppelpunkte in der MAC-Adresse wieder einzufügen und ich bekomme weiterhin die Fehlermeldung "topic may not be empty". Mache ich was falsch? Muss die .patch-Datei auch wohin?

hexenmeister

Funktioniert wunderbar mit genau deinen Parametern. Ich nehme an, du hast vergessen, den Wert in die Anführungszeichen zu nehmen.
attr MQ_ESP_TEST3 subscribeReading_Status "state/socket/switch/EC:FA:BC:13:0E:01"

Patchdatei brauchst Du nicht.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

persching

Ja du hast recht, ich hab keine Anführungszeichen verwendet. Jetzt geht's! Danke!

Franka

Hi Hexenmeister, eisler

Sorry to put this in English, my Deutsch is not good enough :-(

First let me start by thanking you both for this very usefull piece of code. Using it for controlling my self designed esp8266 dimming devices.

I'm running into a problem since this patch (http://svn.fhem.de/trac/changeset/16252/trunk) went life.
Issue is with this line in my config:
attr l_kamer_hoek publishSet on off switch:on,off switch:on,off dim/2/0/dim

The parts that say "switch:on,off" and "switch:on,off" are being ignored completely; no slider is visible in the UI.
It looks like this is because of this part in 00_MQTT.pm:
my ( $key, $value ) = split( ':', $param, 2 );
because when I change the ':' by for instance '#' the configline is interpreted fine and a slider is visible.

Unfortunately I've just started Perl and therefore not yet handy enough to handle this myself without invalidating , and maybe even my analysis is wrong.

Thanks for any help, Regards, Frank

hexenmeister

Hey Frank
I'm sorry for my english. : D

That's gone stupid :(
You're right, Sliders disappeared on my test server (the main server is not yet updated). Unfortunately I have not really looked at the patch. I think I can see the problem: before the change, it was separated only after 'qos' and 'retain' at colon, the rest was not changed. Now is always separated and the UI parameters break down. Is also unavoidable when using 'parseParams'. Maybe their use is not such a good idea. The patch author should look at it again.
A workaround until then: take the parameter with colon in quotation marks:
attr l_kamer_hoek publishSet on off "switch:on,off" "switch:on,off" dim/2/0/dim

this works for me

Regards,
Alexander
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Franka

Thanks for your reply Alexander!

Unfortunately your workaround doesn't work on my system. I have no clue why. Also tried single quotes, but also without success.
I guess I best stick with the previous version of the MQTT modules and regularly check this thread for updates. It's a pitty I'm still not able to solve it myself (living in the C and assembler world).
Thanks again (also to Stephan) for all your hard work!

hexenmeister

if you have time, you can try with the following versions. for me that works (with quotation marks), but are my extensions of the current state, which are not now included in the official version.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Franka

Just tried your version on my setup. Works great with quotation marks; I got back my slider and switch!
Also slider function and switch are working like they should. Nice job!
Suggest I use this versions a couple of days, play with it and then come back with results, ok?

hexenmeister

Here you have a more recent version. I'm trying to create a final corrected version in the near future and send it to the maintainer
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

Ich habe versucht, die paar hier herumgeisternde Probleme (Topics mit $, Doppelpunkt oder Leerzeichen, Zusatz-UI-Parameter, wie slider:...) gemeinsam zu beseitigen.
Aus meiner Sicht auch gelungen. Wäre toll, wenn möglichst viele das testen würden. :)

NB: Topics mit Leerzeichen drin müssen in Anführungszeichen genommen werden.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

hexenmeister

@Franka:
This version should solve the problems. Now it does not matter to be used on quotes, it is also recognized without it. If everything works, I write to the maintainer.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

Franka

I declared the UI-Parameters without quotes and everything works like a charm with this latest version :-)
I don't use any space or colon in the queue-names so I couldn't test this.
Thanks for your hard (and late) work Alexander!

andreas_n

Wäre es auch möglich JSON Telegramme von Owntracks zu unterstützen. Diese müssen wohl mit {} eingerahmt werden.
Dies ist z.Z wohl nicht erlaubt, und die Nutzdaten werden nicht übertragen.

hexenmeister

Jep, war ein Fehler, danke fürs finden :)
Teste bitte die neue Version (reicht nur die 0_MQTT zu nehmen).
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy

andreas_n

Diese Verson erzeugt nun das korrekte Ergebnis. Mein Problem wäre damit gelöst. Danke!
Nun ist es möglich eine Positionsmeldung via MQTT über Owntracks aufs Handy anzuzeigen. Ich nutze dies um mit Hilfe von IBeacons den letzten Stellplatz des Autos anzuzeigen.

hexenmeister

Prima! Danke für die Rückmeldung. Ich werde einen neuen Thread aufmachen, es sind ja mehr Korrekturen drin, als die, um die hier geht.
Maintainer: MQTT_GENERIC_BRIDGE, SYSMON, SMARTMON, systemd_watchdog, MQTT, MQTT_DEVICE, MQTT_BRIDGE
Contrib: dev_proxy