Anel IP Steckdosen ansteuern bzw Status auslesen

Begonnen von Groej, 24 Juli 2016, 11:45:55

Vorheriges Thema - Nächstes Thema

Groej

Hallo,

von der Firma Anel (http://anel-elektronik.de) habe ich einige Steckdosenleisten. Darunter auch eine Hutschienenversion über die mit Hilfe von Magnetventilen meine Gartenbewässerung läuft.

Ich habe auch schon eine kleine Anbindung im FHEM hinbekommen um die Ausgänge zu schalten. Vielleicht nicht schön gemacht aber funktioniert. Meine programmierkenntisse sind leider nicht sehr gut werden aber durch FHEM besser :). Hab ja schon viel geschafft.

fhem.cfg
Zitatdefine anel_bln_7 dummy
attr anel_bln_7 alias Anel Bln Dose 7
attr anel_bln_7 devStateIcon on:taster_ch_an_gruen off:taster_ch_aus_rot
attr anel_bln_7 group Berlin Test
attr anel_bln_7 room Power Control
attr anel_bln_7 setList state:on,off
attr anel_bln_7 sortby 1
attr anel_bln_7 webCmd state

define Anel_bln7_on notify anel_bln_7 {\
Anel('192.168.10.4','Sw_'.$EVENT.'7udpudp\x00\n');;\
}

99_myUtils.pm
Zitatsub Anel($$) {
my ($leisteip,$status) = @_;
    use IO::Socket;
   my $sock = new IO::Socket::INET (
           PeerAddr => $leisteip,
           PeerPort => '75',
           Proto => 'udp',
        );
    die "Could not create socket: $!\n" unless $sock;
        print $sock "$status";
        close($sock);
}

Nun würde ich aber gerne das der Status der Ausgänge auch von der Steckdosenleiste ausgelesen wird im FHEM und nicht nur einfach FHEM den Status setzt oder ein Dummy der den Status anzeigt.

Es gibt im Forum von Anel einen Beitrag zur UDP Steuerung (http://www.anel-elektronik.de/forum_neu/viewtopic.php?f=16&t=207)
UDP Steuerungsprotokoll:

Es sind zwei UDP Kanäle nötig:

Port 75 zum Senden. Port 77 zum Empfangen (listen).
Die Portnummern sind konfigurierbar. UDP Kommunikation muss erlaubt sein (Einstellung/LAN).

Abfragen aller Leisten im Netzwerk:
Senden: Broadcast (IP = 255.255.255.255) - ,,wer da?" - String.

Antwort: Port 77 UDP
NET-PwrCtrl:(Name):(I.P):(M.A.S.K):(G.a.t.e.w.a.y):(M.A.C):
(Name der Steckdose Nr. 1 , Schaltzustand {1=on;0=off}):(Name der Steckdose Nr. 2 , Schaltzustand {1=on;0=off}):
(Name der Steckdose Nr. 3 , Schaltzustand {1=on;0=off}):(Name der Steckdose Nr. 4 , Schaltzustand {1=on;0=off}):
(Name der Steckdose Nr. 5 , Schaltzustand {1=on;0=off}):(Name der Steckdose Nr. 6 , Schaltzustand {1=on;0=off}):
(Name der Steckdose Nr. 7 , Schaltzustand {1=on;0=off}):(Name der Steckdose Nr. 8 , Schaltzustand {1=on;0=off}):
Gesperrte_Steckdosen:
HTTP-Port:
(Name des IO Nr. 1, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 2, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 3, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 4, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 5, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 6, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 7, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
(Name des IO Nr. 8, Richtung {1=Eingang;0=Ausgang}, Schaltzustand {1=on;0=off}):
Temperatur:
Firmware_Version:
ab FW 6.0
{
Typ {a = ADV; i = IO; h = HUT; o = ONE}:
Power Messung {p = mit Power Messung {:VoltageRMS:CurrentRMS:LineFrequency:ActivePower:ApparentPower:ReactivePower:PowerFactor}; n = ohne}:
}
(0x0D)(0x0A)

Beispiel:
NET-PwrCtrl:NET-CONTROL :192.168.178.148:255.255.255.0:192.168.178.1:0.4.163.10.9.107:Nr. 1,1:Nr. 2,1:Nr. 3,1:Nr. 4,0:Nr. 5,0:Nr. 6,0:Nr. 7,1:Nr. 8,1:0:80:IO-1,0,0:IO-2,0,0:IO-3,0,0:IO-4,0,0:IO-5,0,0:IO-6,0,0:IO-7,0,0:IO-8,0,0:27.7°C:NET-PWRCTRL_06.0:
o:p:225.9:0.0004:50.056:0.04:0.00:0.0:1.0000

bei Geräten mit Power Messung:
Senden: ,,pow" - String.
Antwort:
NET-PwrCtrl:(Name):(I.P):VoltageRMS:CurrentRMS:LineFrequency:ActivePower:ApparentPower:ReactivePower:PowerFactor(0x0D)(0x0A)

Beispiel:
NET-PwrCtrl:NET-CONTROL-ONE:192.168.188.75:226.2:0.0004:50.044:0.03:0.00:0.05:1.0000

--------------------------------------------------------------------------------------------------------------------------------

ab FW 6.0 kann User+Passwort (als ganzes) in BASE64 kodiert werden.

Segment = Steckdosennummer As String;
Passwort = Passwort As String;
User = User As String

Schalten
"Sw_on" + Segment + User + Passwort //einschalten
"Sw_off" + Segment + User + Passwort //ausschalten

Beispiel: Sw_on1adminanel

alle Steckdosen schalten
"Sw" + Steckdosen + User + Passwort
Steckdosen = Zustand aller Steckdosen binär
LSB = Steckdose 1, MSB (Bit 8)= Steckdose 8 (PRO, POWER), Bit 2 = Steckdose 3 (HOME).
Soll nur 1 & 5 eingeschaltet werden=00010001 = 17 = 0x11 (HEX)

Beispiel: Swdadminanel
Ascii d=100 decimal = 1100100 binär = Dosen 8,7,3 eingeschaltet 6,5,2,1 ausgeschaltet.

Steckdose zeit-verzögert abschalten
"St_off" + Segment + Zeit[Sek] + User + Passwort
Zeit als 16 Bit Integer in Sekunden = max. 65535 Sek.

IO schalten
"IO_on" + Segment + User + Passwort //einschalten
"IO_off" + Segment + User + Passwort //ausschalten


alle IO schalten
"IO" + IO + User + Passwort
IO = Zustand aller IO's binär
LSB = IO 1, MSB = IO 8, analog zu den Steckdosen

Eingänge können nicht geschaltet werden. ,,wer da?" - Frage auf die Adresse der Leiste liefert die Antwort um die Eingänge auswerten zu können.

Reset
"Reset:"+ User + Passwort

Beispiel: Reset:adminanel


Nun gibt es auch in diesen Forum Beispiele für die UDP Steuerung. Darunter auch diesen vom Benutzer Evil.2000:

/**
* Switch Anel NET-PwrCtrl surge via UDP and check the result
*
* @param string   $ip
* @param integer   $surge_no
* @param integer   $state
* @param integer   $port
* @param string   $password
* @return boolean
*/
function surge_switch($ip="192.168.0.244",$surge_no=0,$state=0,$port=75,$password="user") {
   $port = intval($port);
   $surge_no = intval($surge_no);
   
   // Do some input checks.
   if(!$ip || !$port || !strlen($password) || !$surge_no)
      return false;

   // Create the command for sending to the surge switch
   $cmd = (!$state ? "Sw_off" : "Sw_on").$surge_no.$password.chr(0)."\r\n";

   // Bind to port $port (send and recieve port are the same for compatibility reasons)
   $opts = array('socket' => array('bindto' => '0.0.0.0:'.$port));
   $context = stream_context_create($opts);
   $fp = stream_socket_client("udp://".$ip.":".$port, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
   // Check if the binding succeded
   if (!$fp) {
      //echo $errstr;
      return false;
   }
   // Loop until the surge has switched to the wanted state
   do {
       fwrite($fp, $cmd);
       // Give surge 500ms time to switch
       usleep(500000);
       // Send the "wer da?" packet
       fwrite($fp, "wer da?\r\n");
       // Read and parse the data
       $data = fread($fp,1024);
       $surgeinfo = parse_surge_switch_response($data);
       // loop until the surge has switched to the wanted state
    } while ($surgeinfo["surge"][$surge_no]["state"] != $state);

    // Close the UDP connection.
    fclose($fp);

    return true;
}

/**
* Parse the response of the "wer da?" packet from the Anel NET-PwrCtrl surge switch
*
* @param string $data
* @return array
*/
function parse_surge_switch_response($data) {
   // Create an array with named keys out of the $data variable
   $surgeinfo = array_combine(array("type","name","ip","mask","gateway","mac","surge1","surge2","surge3","surge4","surge5","surge6","surge7","surge8","disabled","http_port",),explode(":",trim($data)));
    // Loop through the array and put surge1 ..2 ..3 into a single array
   foreach ($surgeinfo as $k=>$v) {
      // Parse the key if ist is surge1 ..2 ..3
       if (preg_match("/^surge(\d)$/i",$k,$regs)) {
          $no = $regs[1];
          // Parse "name" and "state" into a subarray
          $surgeinfo["surge"][$no] = array_combine(array("name","state"),explode(",",$v));
          // Parse the "disabled" value and place it into a seperate key for this surge
          $surgeinfo["surge"][$no]["disabled"] = ($surgeinfo["disabled"] & pow(2,$no-1)) >> ($no-1);
          // Finally, delete the surge1 ..2 ..3 entry
          unset($surgeinfo[$k]);
       }
    }
    // Remove the "disabled" entry.
    unset($surgeinfo["disabled"]);
    // Parse the MAC which is in decimal into hexdecimal format
    $surgeinfo["mac"] = array_reduce(explode(".",$surgeinfo["mac"]),create_function('$a,$b','return strtoupper((strlen($a) ? $a.":" : "").($b>15 ? dechex($b) : "0".dechex($b)));'));
    // Finished :-)
    return $surgeinfo;
}



Ist es möglich diesen für FEHM umzuschreiben? Wenn ja bitte Tipps wie ich an der Stelle anfangen sollte. Muss dafür gleich ein eigens Modul im FHEM geschrieben werden oder reicht da ein eigenes 99_Utilsxx.pm? Gut is ja quasi dann ein Modul :).
Meine Idee wäre am Ende ja mit fhem set den Status der Dummys zu setzen. Wenn ich das so richtig sehen ist das ja schon PHP oder?

Danke schon mal für Tipps und Hinweise wie ich das anstellen soll.

Gruß

Jörg

FHEM - RaspPi2 - KNXD - KNX - CUL 868 - FS20 - HMS - WH3080 - Signalduino 433 MHz - Telegram - Anel Elektronik IP Steckdosen - BME280