Topic mit Leerzeichen oder Doppelpunkt funktioniert nicht

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

Vorheriges Thema - Nächstes Thema

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