Neues Modul: USR-WM1 (Wifi relays)

Begonnen von superbert, 14 Januar 2015, 21:44:30

Vorheriges Thema - Nächstes Thema

superbert

Hallo,

Ich habe angefangen ein Modul zu schreiben für ein Wifi Relais (USR-WM1): http://www.usriot.com/Product/98.html

Das Relais ist bi-directionel; Wenn mann ein Befehl schickt bekommt man eine Rückmeldung :) Wenn man den Taster (eingebaut oder externer) gibt das Relais eine Meldung an den Server.

Um eine Verbindung da zu stellen habe Ich DevIo benutzt.

Im FHEM Web-oberfläche möchte Ich das gerät als On/Off (mit das Lampe Symbol) zeigen. Das hat geklappt durch setzen von "STATE" (von dem hash) auf "on/off"....aber DevIo benutzt auch den "STATE" internal für den TCP-socket.

Sollte Ich das "Zweistufiges Modell" benutzen oder gibt es eine einfachere Lösung? Gibt es vielleicht andere Module die das gleiche Problem schon beseitigt haben?

Danke für die Hilfe.

Eeg.

rudolfkoenig

Wenn ich es richtig verstehe, bietet das Geraet die Moeglichkeit einen Schalter ueber Netzwerk zu bedienen. In diesem Fall sehe ich keine Vorteile einer zweistufigen Loesung.
Das Setzen von STATE sollte nicht im Weg stehen, wenn das Modul es danach ueberschreibt.

superbert

Okay, danke! Dan werde Ich "STATE" einfach immer überschreiben mit "on" oder "off" (Abhängig von der Gerät Antwort).

rudolfkoenig

Der richtige Weg ist das Readig "state" via readingsSingleUpdate zu setzen, STATE wird dann passend uebernommen.

superbert

#4
@Rudolf: Danke, geht schon besser jetzt


###################################
sub
USR_Read($)
{
  my ($hash) = @_;
  my $buf = DevIo_SimpleRead($hash);
  my %responses = (
   "810100"    => "off",
   "820101"    => "on",
   "830100"    => "off",
   "830101"    => "on",
   "8a0101"    => "on",
   "8a0100"    => "off"
  );

  return "" if(!defined($buf));

  $buf = unpack('H*', $buf);
  $hash->{Buffer} = $buf;
  my @a = unpack("(A2)*", $buf); #split the octets of the message into an array for easier handling
  my $validation = USR_validate(@a);
  if ($validation eq "OK") {
        my $command = $a[5];
        my $length = $a[2] . $a[3];
        my $param; #Retrieving the command parameters from the message
        for (my $i = 0; $i < ($length -2); $i++) {
                $param = $param . $a[$i + 6];}
        readingsSingleUpdate($hash,"state",$responses{$command . $param},1);
#$hash->{STATE} = $responses{$command . $param};
        Log 2, $buf;
        Log 2, $command . $param;

} else {
        Log 2, "USR:" . $validation . " - " . $buf;
        #Provide logging with reason for failed validation
        #Set "STATE" to "?" or we could retrieve the state....maybe even better!
        readingsSingleUpdate($hash,"state","?",1);
}
return $buf;
}


Ich habe jetzt folgendes Problem:
Manchmal zerbricht das Gerät die Verbindung (TCP Socket). Im log sehe Ich "Disappeared" und schnell danach (<1s) "Reappeared". "State" steht dan auf "opened" (von erstellen des TCP Socket).


2015.01.16 09:39:51 1: 192.168.178.28:8899 disconnected, waiting to reappear (testUSR)
2015.01.16 09:39:51 1: 192.168.178.28:8899 reappeared (testUSR)


Wie kan Ich eine erneuerte Status-Abfrage einbinden? Also, Ich möchte nach dem "Reappeared" die Status von das Relais über Commando abfragen.

Soll Ich das in FnReady (USR_Ready in mein fall) machen?


#####################################
sub
USR_Ready($)
{
        my ($hash) = @_;
        return DevIo_OpenDev($hash, 1, undef )
          if ( $hash->{STATE} eq "disconnected" );
# This is relevant for windows/USB only
        my $po = $hash->{TCPDev};
        my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po->status;

        #In case state does not equal "disconnected, send password to device"
        DevIo_SimpleWrite( $hash, "746573740d0a", 1);
        my $ret = DevIo_SimpleReadWithTimeout( $hash, 2);
        #Todo: password via attribute, check if result is "OK" -> Not sure if it does something at all...
        Log 2, "USR password-result after recovery:" . $ret;
        DevIo_SimpleWrite( $hash, "55aa0002000a0c", 1); #Command 0a is sent to retrieve relays status

        # This is relevant for windows/USB only
        # maybe this should be moved to top after conditional return?
        return ( $InBytes > 0 );
}


Ich weiß das die Code "quick & dirty" ist....aber Ich versuche zuerst ze verstehen wie es funktioniert
;)

Grüße,

Eeg.

superbert

Ich habe die lösung gefunden  ;D


#####################################
sub
USR_Ready($)
{
        my ($hash) = @_;
        if ( $hash->{STATE} eq "disconnected" ) {
                DevIo_OpenDev($hash, 1, undef );
                if ( $hash->{STATE} eq "opened" ) {
                        DevIo_SimpleWrite( $hash, "746573740d0a", 1);
                        my $ret = DevIo_SimpleReadWithTimeout( $hash, 2);
                        #Todo: password via attribute, check if result is "OK" -> Not sure if it does something at all...
                        Log 2, "USR password-result after recovery:" . $ret;
                        DevIo_SimpleWrite( $hash, "55aa0002000a0c", 1); #Command 0a is sent to retrieve relays status (ReadFn handles the response)
                }
                return

        }
# This is relevant for windows/USB only
        my $po = $hash->{TCPDev};
        my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po->status;
        return ( $InBytes > 0 );



Jetzt wird die Status des Relais abgefragt nachdem die TCP Verbindung wieder da ist!