98_UbiquitiMP.pm 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. ################################################################
  2. #
  3. # $Id: 98_UbiquitiMP.pm 14319 2017-05-19 19:44:53Z Wzut $
  4. #
  5. # (c) 2015 Copyright: Wzut
  6. # forum : http://forum.fhem.de/index.php/topic,35722.0.html
  7. # All rights reserved
  8. #
  9. # This code is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 2 of the License, or
  12. # (at your option) any later version.
  13. # The GNU General Public License can be found at
  14. # http://www.gnu.org/copyleft/gpl.html.
  15. # A copy is found in the textfile GPL.txt and important notices to the license
  16. # from the author is found in LICENSE.txt distributed with these scripts.
  17. # This script is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. ################################################################
  23. # Changelog:
  24. # 25.03.15 add force for set on and off
  25. # 10.04.15 add enable/disable
  26. # 18.04.15 add toggle
  27. # 20.04.15 add Groups
  28. # first svn Version
  29. # 23.04.15 add Set Extensions for 1 Port Ubi , change Client to UbiquitiOut,
  30. # 25.06.15 add german docu, fix some timing problems
  31. # 02.05.15 fix groupPorts change at runtime
  32. # 19.05.17 change decode_json
  33. package main;
  34. use strict;
  35. use warnings;
  36. use Time::HiRes qw(gettimeofday);
  37. use Blocking; # http://www.fhemwiki.de/wiki/Blocking_Call
  38. use SetExtensions;
  39. use Net::Telnet;
  40. use JSON;
  41. #use Data::Dumper;
  42. my %sets = ();
  43. my $setcmds = "on,off,toggle,enable,disable,lock,unlock,reset";
  44. #########################################################################
  45. sub UbiquitiMP_Initialize($)
  46. {
  47. my ($hash) = @_;
  48. $hash->{DefFn} = "UbiquitiMP_Define";
  49. $hash->{UndefFn} = "UbiquitiMP_Undef";
  50. $hash->{SetFn} = "UbiquitiMP_Set";
  51. $hash->{GetFn} = "UbiquitiMP_Get";
  52. $hash->{AttrFn} = "UbiquitiMP_Attr";
  53. $hash->{FW_summaryFn} = "UbiquitiMP_summaryFn";
  54. $hash->{AttrList} = "interval timeout user password subDevices:0,1 ignoreList ledconnect:off,blue,yellow,both,alternate groupPorts ".$readingFnAttributes;
  55. }
  56. sub UbiquitiMP_updateConfig($)
  57. {
  58. # this routine is called 5 sec after the last define of a restart
  59. # this gives FHEM sufficient time to fill in attributes
  60. my ($hash) = @_;
  61. my $name = $hash->{NAME};
  62. if (!$init_done)
  63. {
  64. RemoveInternalTimer($hash);
  65. InternalTimer(gettimeofday()+5,"UbiquitiMP_updateConfig", $hash, 0);
  66. return;
  67. }
  68. $hash->{INTERVAL} = AttrVal($name, "interval", 300);
  69. $hash->{".led"} = AttrVal($name, "ledconnect", 0);
  70. if ($hash->{".led"}) # Farben nach Kommando
  71. {
  72. $hash->{".led"} = "0" if ($hash->{".led"} eq "off");
  73. $hash->{".led"} = "1" if ($hash->{".led"} eq "blue");
  74. $hash->{".led"} = "2" if ($hash->{".led"} eq "yellow");
  75. $hash->{".led"} = "3" if ($hash->{".led"} eq "both");
  76. $hash->{".led"} = "4" if ($hash->{".led"} eq "alternate");
  77. }
  78. $hash->{MAC} = "";
  79. $hash->{lastcmd} = "Init";
  80. $hash->{".init"} = 1;
  81. RemoveInternalTimer($hash);
  82. InternalTimer(gettimeofday()+5, "UbiquitiMP_GetStatus",$hash, 0);
  83. return undef;
  84. }
  85. ################################################################################
  86. sub UbiquitiMP_Define($$) {
  87. my ($hash, $def) = @_;
  88. my $name = $hash->{NAME};
  89. my @a = split("[ \t][ \t]*", $def);
  90. return "wrong syntax: define <name> UbiquitiMP <IP or FQDN>" if(int(@a) < 3);
  91. $hash->{".host"} = $a[2];
  92. if( !defined( $attr{$a[0]}{user} ) ) { $attr{$a[0]}{user} = "ubnt";}
  93. $hash->{".user"} = $attr{$a[0]}{user};
  94. if( !defined( $attr{$a[0]}{password} ) ) { $attr{$a[0]}{password} = "ubnt";}
  95. $hash->{".pwd"} = $attr{$a[0]}{password};
  96. if( !defined( $attr{$a[0]}{subDevices} ) ) { $attr{$a[0]}{subDevices} = "1";}
  97. if( !defined( $attr{$a[0]}{timeout} ) ) { $attr{$a[0]}{timeout} = "5"}
  98. $hash->{".timeout"} = (int($attr{$a[0]}{timeout}) > 1) ? $attr{$a[0]}{timeout} : "5";
  99. if( !defined( $attr{$a[0]}{subDevices} ) ) { $attr{$a[0]}{subDevices} = "1"}
  100. $hash->{".subdevices"} = $attr{$a[0]}{subDevices};
  101. $hash->{Clients} = ":UbiquitiOut:";
  102. $hash->{PORTS} = 0;
  103. $hash->{force} = 0;
  104. $hash->{ERRORCOUNT} = 0;
  105. $hash->{".grouplist"} = "";
  106. readingsSingleUpdate($hash, "state", "defined",0);
  107. RemoveInternalTimer($hash);
  108. InternalTimer(gettimeofday()+5, "UbiquitiMP_updateConfig",$hash,0); # in 5 Sekunden machen wir den Rest
  109. return undef;
  110. }
  111. ################################################################################
  112. sub UbiquitiMP_Undef($$)
  113. {
  114. my ($hash, $arg) = @_;
  115. RemoveInternalTimer($hash);
  116. if(defined($hash->{helper}{RUNNING_PID}))
  117. {
  118. BlockingKill($hash->{helper}{RUNNING_PID});
  119. }
  120. return undef;
  121. }
  122. ################################################################################
  123. sub UbiquitiMP_force($)
  124. {
  125. my ($hash) = @_;
  126. my $name = $hash->{NAME};
  127. my $cmdlist = $hash->{lastcmd};
  128. Log3 $name, 4, "$name, force called for $cmdlist";
  129. $hash->{helper}{RUNNING_PID} = BlockingCall("UbiquitiMP_BCStart", $cmdlist, "UbiquitiMP_BCDone",(int($hash->{".timeout"})*3),"UbiquitiMP_BCAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
  130. RemoveInternalTimer($hash);
  131. if($hash->{helper}{RUNNING_PID})
  132. {
  133. Log3 $name, 5, "$name, BC force process started with PID(".$hash->{helper}{RUNNING_PID}{pid}.") cmd : $cmdlist";
  134. }
  135. else
  136. { # das war wohl schon wieder nix :(
  137. InternalTimer(gettimeofday()+(int($hash->{".timeout"})*3), "UbiquitiMP_force",$hash, 0);
  138. }
  139. return undef;
  140. }
  141. ################################################################################
  142. sub UbiquitiMP_Attr(@)
  143. {
  144. my ($cmd,$name, $attrName,$attrVal) = @_;
  145. my $hash = $defs{$name};
  146. if ($cmd eq "set")
  147. {
  148. if ($attrName eq "timeout")
  149. {
  150. if (int($attrVal) < 2) {$attrVal="5";}
  151. $hash->{".timeout"} = $attrVal;
  152. $attr{$name}{timeout} = $attrVal;
  153. }
  154. elsif ($attrName eq "user")
  155. {
  156. $hash->{".user"} = $attrVal;
  157. $attr{$name}{user} = $attrVal;
  158. }
  159. elsif ($attrName eq "password")
  160. {
  161. $hash->{".pwd"} = $attrVal;
  162. $attr{$name}{password} = $attrVal;
  163. }
  164. elsif ($attrName eq "interval")
  165. {
  166. $hash->{INTERVAL} = $attrVal;
  167. $attr{$name}{interval} = $attrVal;
  168. }
  169. elsif ($attrName eq "subDevices")
  170. {
  171. $hash->{".subdevices"} = $attrVal;
  172. $attr{$name}{subDevices} = $attrVal;
  173. }
  174. elsif ($attrName eq "ledconnect")
  175. {
  176. $hash->{".led"} = "0" if ($attrVal eq "off");
  177. $hash->{".led"} = "1" if ($attrVal eq "blue");
  178. $hash->{".led"} = "2" if ($attrVal eq "yellow");
  179. $hash->{".led"} = "3" if ($attrVal eq "both");
  180. $hash->{".led"} = "4" if ($attrVal eq "alternate");
  181. $attr{$name}{ledconnect} = $attrVal;
  182. }
  183. elsif ($attrName eq "groupPorts")
  184. {
  185. $attr{$name}{groupPorts} = $attrVal;
  186. UbiquitiMP_createSets($hash);
  187. }
  188. }
  189. elsif ($cmd eq "del")
  190. {
  191. if ($attrName eq "groupPorts")
  192. {
  193. $attr{$name}{groupPorts} = "";
  194. UbiquitiMP_createSets($hash);
  195. }
  196. }
  197. return undef;
  198. }
  199. ################################################################################
  200. sub UbiquitiMP_Get($@) {
  201. my ($hash, $name , @a) = @_;
  202. my $cmd = $a[0];
  203. return "get $name needs one argument" if (int(@a) != 1);
  204. return "Unknown argument $cmd, choose one of status:noArg info:noArg reboot:noArg" if($cmd !~ /^(status|info|reboot)$/);
  205. $hash->{force} = 0; # Get setzt IMMER force zurueck !
  206. if ($cmd eq "info")
  207. { $cmd = $name."#info#cat /etc/board.info | grep board;"; $hash->{lastcmd} ="GetInfo";}
  208. elsif ($cmd eq "status")
  209. { $cmd = $name."#status#/sbin/cgi /usr/www/mfi/sensors.cgi#awk '{print \"u=\"\$1}' < /proc/uptime#awk '{print \"l=\"\$1\" \"\$2\" \"\$3}' < /proc/loadavg#cat /proc/power/energy_sum* | tr '\\n' ' '"; $hash->{lastcmd} ="GetStatus";}
  210. elsif ($cmd eq "reboot")
  211. { $cmd = $name."#reboot#reboot"; $hash->{lastcmd} ="GetReboot";}
  212. else { return undef; } # sollte eigentlich nie vorkommen
  213. $hash->{helper}{RUNNING_PID} = BlockingCall("UbiquitiMP_BCStart", $cmd, "UbiquitiMP_BCDone",(int($hash->{".timeout"})*2),"UbiquitiMP_BCAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
  214. if($hash->{helper}{RUNNING_PID})
  215. {
  216. RemoveInternalTimer($hash);
  217. Log3 $name, 5, "$name, BC process started with PID(".$hash->{helper}{RUNNING_PID}{pid}.") cmd : $cmd";
  218. }
  219. else
  220. { # das war wohl nix :(
  221. Log3 $name, 3, "$name, BC process start failed, cmd : $cmd ";
  222. return $name.", can't execute get command as NonBlockingCall";
  223. }
  224. return undef;
  225. }
  226. ################################################################################
  227. sub UbiquitiMP_Set($@) {
  228. my ($hash, @a) = @_;
  229. my $name = $hash->{NAME};
  230. my ($port,$cmd,$subcmd);
  231. return undef if (!$hash->{PORTS}); # ohne bekannte Ports geht hier nichts :)
  232. UbiquitiMP_createSets($hash) if(!defined($sets{Out1}) && $hash->{PORTS}); # neu aufbauen nach reload;
  233. if (int($hash->{PORTS}) > 1)
  234. {
  235. $port = (defined($a[1])) ? $a[1] : "?" ;
  236. $cmd = (defined($a[2])) ? $a[2] : "";
  237. $subcmd = (defined($a[3])) ? $a[3] : "";
  238. if(!defined($sets{$port}))
  239. {
  240. my @commands = ();
  241. foreach my $key (sort keys %sets)
  242. {
  243. push @commands, $sets{$key} ? $key.":".join(",",$sets{$key}) : $key;
  244. }
  245. return "Unknown port $port, choose one of " . join(" ", @commands);
  246. }
  247. return "$name wrong command, please use on of on,off,toggle,lock,unlock,enable,disable or reset" if($cmd !~ /^(on|off|lock|unlock|reset|enable|disable|toggle)$/);
  248. }
  249. else # die mPower mini
  250. {
  251. $port = "Out1";
  252. $cmd = (defined($a[1])) ? $a[1] : "";
  253. $subcmd = (defined($a[2])) ? $a[2] : "";
  254. $setcmds =~ s/\,/ /g;
  255. shift(@a);
  256. return SetExtensions($hash,$setcmds,$name,@a) if($cmd !~ /^(on|off|lock|unlock|reset|enable|disable|toggle)$/);
  257. }
  258. my $cmdlist = "$name#$cmd";
  259. if ($hash->{force})
  260. {
  261. my $ret = "a force command is already active -> PID ".$hash->{force}." cmd : ".$hash->{lastcmd};
  262. Log3 $name, 3, "$name, $ret";
  263. return $ret;
  264. }
  265. if ((substr($port,0,3) eq "Out") && (int(substr($port,3,1)) > 0) && (int(substr($port,3,1)) <= int($hash->{PORTS})))
  266. { $cmdlist .= "#".substr($port,3,1); } # normaler einzelner Port
  267. else # oder doch eine Port Gruppe ?
  268. {
  269. @a = split("," ,$hash->{"group_".$port});
  270. foreach (@a)
  271. {
  272. return "Unknown port $_ in group list $port !" if ((int($_) < 1) || (int($_) > int($hash->{PORTS})));
  273. $cmdlist .="#".$_;
  274. }
  275. }
  276. $hash->{lastcmd} = $cmdlist;
  277. $hash->{helper}{RUNNING_PID} = BlockingCall("UbiquitiMP_BCStart", $cmdlist, "UbiquitiMP_BCDone",(int($hash->{".timeout"})*3),"UbiquitiMP_BCAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
  278. if($hash->{helper}{RUNNING_PID})
  279. {
  280. RemoveInternalTimer($hash);
  281. $hash->{force} = ($subcmd eq "force") ? $hash->{helper}{RUNNING_PID}{pid} : 0;
  282. Log3 $name, 5, "$name, BC process started with PID(".$hash->{helper}{RUNNING_PID}{pid}.") cmd : $cmdlist , subcmd : $subcmd";
  283. }
  284. else
  285. { # das war wohl nix :(
  286. Log3 $name, 3, "$name, BC process start failed , cmd : $cmdlist , subcmd : $subcmd";
  287. UbiquitiMP_force($hash) if ($hash->{force}) ; # muessen wir das wiederholen ?
  288. return $name.", can't execute set as NonBlockingCall";
  289. }
  290. return undef;
  291. }
  292. ################################################################################
  293. sub UbiquitiMP_BCStart($)
  294. {
  295. my ($string) = @_;
  296. return unless(defined($string));
  297. my (@ret, $c, $v);
  298. my @a = split("\#" ,$string);
  299. my $output = $a[0]; # Name
  300. shift(@a);
  301. my $cmd = $a[0];
  302. shift(@a);
  303. my $hash = $defs{$output};
  304. my $name = $hash->{NAME};
  305. my $onoff = (($cmd eq "on") || ($cmd eq "lock") || ($cmd eq "enable")) ? "1" : "0";
  306. Log3 $name, 5, "$name, BC cmd : $cmd -> ".join(" ",@a);
  307. my $sock = new Net::Telnet(Timeout => $hash->{".timeout"}, Errmode => 'return');
  308. $sock->open( Host => $hash->{".host"}, Port => 23 );
  309. if (!$sock->errmsg)
  310. {
  311. $sock->login( Name => $hash->{".user"}, Password => $hash->{".pwd"} );
  312. if (!$sock->errmsg)
  313. {
  314. $sock->cmd("echo '".$hash->{".led"}."' >/proc/led/status") if ($hash->{".led"} ne "0");
  315. if (($cmd eq "reset") || ($cmd eq "toggle") ||
  316. ($cmd eq "lock") || ($cmd eq "unlock") ||
  317. ($cmd eq "enable") || ($cmd eq "disable") ||
  318. ($cmd eq "on") || ($cmd eq "off"))
  319. {
  320. $output .= "|1|status|"; # Rueckgabe wie eine Statusabfrage
  321. foreach (@a)
  322. {
  323. if ($cmd eq "reset")
  324. {
  325. $sock->cmd("cat /proc/power/relay".$_." > /tmp/relay".$_.".tmp"); # Akt. Zustand retten
  326. $sock->cmd("echo 0 > /proc/power/reset".$_); # Messwerte Reset
  327. $sock->cmd("cat /tmp/relay".$_.".tmp > /proc/power/output".$_); # alter Zustand wiederherstellen
  328. }
  329. elsif ($cmd eq "toggle")
  330. {
  331. @ret = $sock->cmd("awk '{print \$1=!\$1}' < /proc/power/relay".$_); # Akt. Zustand invers
  332. $sock->cmd("echo '".$ret[0]."' > /proc/power/output".$_);
  333. # ToDo : wer weiss wie man es in nur einer Zeile macht ?
  334. # ala : awk '{print $1=!$1}' < /proc/power/relayX > /proc/power/outputX
  335. }
  336. elsif (($cmd eq "on") || ($cmd eq "off"))
  337. {
  338. $sock->cmd("echo $onoff > /proc/power/output".$_);
  339. }
  340. elsif (($cmd eq "lock") || ($cmd eq "unlock"))
  341. {
  342. $sock->cmd("echo $onoff > /proc/power/lock".$_);
  343. }
  344. elsif (($cmd eq "enable") || ($cmd eq "disable"))
  345. {
  346. $sock->cmd("echo $onoff > /proc/power/enabled".$_);
  347. }
  348. } # foreach
  349. select(undef, undef, undef, 0.25); # 250 ms warten !
  350. @ret = $sock->cmd("/sbin/cgi /usr/www/mfi/sensors.cgi"); # neue Statuswerte holen
  351. if($ret[2])
  352. {
  353. ($ret[2],undef) = split("MF",$ret[2]); $output .= $ret[2];
  354. }
  355. }
  356. else #
  357. {
  358. $output .= "|1|$cmd|";
  359. foreach(@a)
  360. {
  361. select(undef, undef, undef, 0.25);
  362. @ret = $sock->cmd($_);
  363. Log3 $name, 5, "$name, ret -> ".$ret[0] if ($ret[0]);
  364. if ($cmd eq "status") { if($ret[2]) { ($ret[2],undef) = split("MF",$ret[2]); $output .= $ret[2]; } else { if ($ret[0]) {$ret[0] =~s/^MF.*//g; $output .= "|".$ret[0];}}}
  365. if ($cmd eq "info") { $c = join(";",@ret); $c =~s/\$//g; $c =~s/\"//g; ($c,$v) = split("MF.v",$c); $output .= $c; $output .= "version=$v";}
  366. }
  367. }
  368. $sock->cmd("echo '0' >/proc/led/status") if ($hash->{".led"} ne "0");
  369. $sock->close;
  370. $output =~s/\n//g;
  371. return $output;
  372. } else { return $output."|0|$cmd|".$sock->errmsg; }
  373. } else { return $output."|0|$cmd|".$sock->errmsg; }
  374. }
  375. sub UbiquitiMP_BCDone($)
  376. {
  377. my ($string) = @_;
  378. return unless(defined($string));
  379. my ($h,$ret,$cmd,$msg,@a) = split("\\|",$string);
  380. my $hash = $defs{$h};
  381. $msg = "" if (!defined($msg)) ;
  382. if ($hash->{helper}{RUNNING_PID}{pid})
  383. {
  384. Log3 $h, 4, "$h, BCDone : PID ".$hash->{helper}{RUNNING_PID}{pid};
  385. delete($hash->{helper}{RUNNING_PID});
  386. }
  387. Log3 $h, 5, "$h, BCDone : $string";
  388. if ($ret eq "0")
  389. {
  390. $hash->{ERRORMSG} = $msg;
  391. $hash->{ERRORTIME} = TimeNow();
  392. $hash->{ERRORCOUNT}++;
  393. Log3 $h, 2, "$h, Error[".$hash->{ERRORCOUNT}."] cmd $cmd -> $msg";
  394. $hash->{INTERVAL} = 3600 if ($hash->{INTERVAL} && ($hash->{ERRORCOUNT}>9));
  395. readingsSingleUpdate($hash,"state","error",1);
  396. if ($hash->{force}) # muessen wir wiederholen ?
  397. {
  398. UbiquitiMP_force($hash);
  399. return;
  400. }
  401. }
  402. else # das ging ja schon mal gut
  403. {
  404. $hash->{INTERVAL} = AttrVal($h, "interval", 300) if ($hash->{ERRORCOUNT} >9);
  405. $hash->{ERRORCOUNT} = 0;
  406. $hash->{force} = 0;
  407. if ($cmd eq "info") { UbiquitiMP_Info($hash,$msg); }
  408. elsif ($cmd eq "status")
  409. {
  410. if($msg ne "") # haben wir wieder mal einen leeren Status bekommen ?
  411. {
  412. UbiquitiMP_Status($hash,$msg,@a) if($msg ne "") ;
  413. }
  414. else
  415. {
  416. # etwas warten und versuchen den Status doch noch abzuschliessen
  417. InternalTimer(gettimeofday()+$hash->{".timeout"}, "UbiquitiMP_GetStatus",$hash, 0);
  418. return ;
  419. }
  420. }
  421. }
  422. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "UbiquitiMP_GetStatus",$hash, 0) if ($hash->{INTERVAL});
  423. }
  424. ################################################################################
  425. sub UbiquitiMP_BCAborted($)
  426. {
  427. my ($hash) = @_;
  428. delete($hash->{helper}{RUNNING_PID});
  429. $hash->{ERRORCOUNT}++;
  430. $hash->{ERRORTIME} = TimeNow();
  431. Log3 $hash->{NAME}, 3, $hash->{NAME}.", BlockingCall for ".$hash->{NAME}." cmd ".$hash->{lastcmd}." aborted EC : ".$hash->{ERRORCOUNT};
  432. $hash->{INTERVAL} = 3600 if ($hash->{INTERVAL} && ($hash->{ERRORCOUNT}>9));
  433. if ($hash->{force}) # ein abgebrochenes force ?
  434. {
  435. UbiquitiMP_force($hash);
  436. }
  437. elsif ($hash->{lastcmd} eq "GetStatus") # war das ein erfolgloses auto status update ?
  438. {
  439. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "UbiquitiMP_GetStatus",$hash, 0) if($hash->{INTERVAL});
  440. }
  441. return;
  442. }
  443. ################################################################################
  444. sub UbiquitiMP_Status($$@)
  445. {
  446. my ($hash,$js,@a) = @_;
  447. my $name = $hash->{NAME};
  448. my $devstate;
  449. my $devname;
  450. my $state;
  451. my $sum_current;
  452. my $sum_power;
  453. my $sum_month;
  454. my $sum_prevmonth;
  455. my $sum_energy;
  456. my @ener;
  457. #my $json = ();
  458. #my %json = JSON->new->utf8(0)->decode($js);
  459. my $json = eval{decode_json($js)};
  460. if($@)
  461. {
  462. Log3 $name, 2, "$name, error decode JSON: ".$@;
  463. readingsSingleUpdate($hash, "state", "error", 1);
  464. return undef;
  465. }
  466. my $sensors = 0; # es gibt z.Z. in Deutschland nur die Ausführungen mit 1,3 & 6 Port
  467. $sensors = 1 if defined($json->{sensors}[0]);
  468. $sensors = 3 if defined($json->{sensors}[2]);
  469. $sensors = 6 if defined($json->{sensors}[5]);
  470. Log3 $name, 2, "$name - sensors : $sensors";
  471. if ((!$hash->{PORTS}) && ($sensors > 0)) # nur einmal zu Begin bzw nach reload
  472. {
  473. $hash->{PORTS} = $sensors;
  474. UbiquitiMP_createSets($hash);
  475. }
  476. # bei der 1 Port Ubi default keine Subdevices , bei den anderen ja
  477. my $subdev = (int($hash->{PORTS}) >1) ? AttrVal($name, "subDevices", 1) : AttrVal($name, "subDevices", 0);
  478. @ener = split(" ",$a[2]) if (defined($a[2]));
  479. readingsBeginUpdate($hash);
  480. for (my $i=0; $i<$sensors; $i++)
  481. {
  482. if (index(AttrVal($name, "ignoreList", "") , $i+1) == -1) # welche Ports ignorieren ?
  483. {
  484. my $thismonth = ($json->{sensors}[$i]{thismonth}) ? sprintf("%.0f", $json->{sensors}[$i]{thismonth}*0.3125) : 0; # Verbrauch aktueller Monat
  485. my $prevmonth = ($json->{sensors}[$i]{prevmonth}) ? sprintf("%.0f", $json->{sensors}[$i]{prevmonth}*0.3125) : 0; # Verbrauch letzter Monat , in welcher Einheit ?
  486. my $powerfactor = sprintf("%.2f", $json->{sensors}[$i]{powerfactor}); $powerfactor +=0; # wer will 0.00 ?
  487. my $output = $json->{sensors}[$i]{output}; # 1/0 fuer on/off
  488. my $port = $json->{sensors}[$i]{port}; # Port Nr. 1- n
  489. my $voltage = sprintf("%.0f", $json->{sensors}[$i]{voltage}); # V
  490. my $power = sprintf("%.0f", $json->{sensors}[$i]{power}); # W
  491. my $current = sprintf("%.2f", $json->{sensors}[$i]{current}); $current +=0; # A
  492. my $lock = $json->{sensors}[$i]{lock};
  493. my $label = $json->{sensors}[$i]{label};
  494. my $enabled = $json->{sensors}[$i]{enabled}; # wann wird das angefasst ?
  495. my $energy = (defined($ener[$i])) ? sprintf("%.2f",$ener[$i]*0.3125) : 0; $energy += 0; #kW/h
  496. my $eState ="E:$energy P:$power I:$current U:$voltage i:$powerfactor";
  497. $sum_current += (defined($json->{sensors}[$i]{current})) ? $json->{sensors}[$i]{current} : 0;
  498. $sum_month += (defined($json->{sensors}[$i]{thismonth})) ? $json->{sensors}[$i]{thismonth}*0.3125 : 0;
  499. $sum_prevmonth += (defined($json->{sensors}[$i]{prevmonth})) ? $json->{sensors}[$i]{prevmonth}*0.3125 : 0;
  500. $sum_power += (defined($json->{sensors}[$i]{power})) ? $json->{sensors}[$i]{power} : 0;
  501. $sum_energy += (defined($ener[$i])) ? $ener[$i]*0.3125 : 0;
  502. $devstate = ($output eq "0") ? "off" : "on";
  503. $state .= ($i == $sensors) ? $devstate : $devstate." ";
  504. $devname = "Out".$port; # Port kann eigenen Namen haben
  505. $hash->{helper}{$devname}{state} = $output;
  506. $hash->{helper}{$devname}{name} = $devname;
  507. $hash->{helper}{$devname}{lock} = $lock;
  508. if ($subdev) # aufteilen oder lieber alles am Stueck ?
  509. {
  510. my $defptr = $modules{UbiquitiOut}{defptr}{$name.$port};
  511. if (defined($defptr))
  512. {
  513. readingsBeginUpdate($defptr);
  514. readingsBulkUpdate($defptr, "state" , $devstate);
  515. readingsBulkUpdate($defptr, "eState" , $eState);
  516. readingsBulkUpdate($defptr, "power" , $power);
  517. readingsBulkUpdate($defptr, "voltage" , $voltage);
  518. readingsBulkUpdate($defptr, "current" , $current);
  519. readingsBulkUpdate($defptr, "pf" , $powerfactor);
  520. readingsBulkUpdate($defptr, "month" , $thismonth);
  521. readingsBulkUpdate($defptr, "prevmonth" , $prevmonth) if ($prevmonth);
  522. readingsBulkUpdate($defptr, "lock" , $lock);
  523. readingsBulkUpdate($defptr, "label" , $label) if ($label);
  524. readingsBulkUpdate($defptr, "enabled" , $enabled);
  525. readingsBulkUpdate($defptr, "energy" , $energy);
  526. readingsEndUpdate($defptr, 1 );
  527. }
  528. else
  529. {
  530. Log3 $name, 3, "$name, autocreate sub device for $devname Port $port";
  531. CommandDefine(undef, $name."_".$devname." UbiquitiOut $name $port");
  532. }
  533. }
  534. else # all in one
  535. {
  536. if (int($hash->{PORTS}) > 1)
  537. {
  538. readingsBulkUpdate($hash, $devname."_state" , $devstate);
  539. readingsBulkUpdate($hash, $devname."_eState" , $eState);
  540. readingsBulkUpdate($hash, $devname."_power" , $power);
  541. readingsBulkUpdate($hash, $devname."_voltage" , $voltage);
  542. readingsBulkUpdate($hash, $devname."_current" , $current);
  543. readingsBulkUpdate($hash, $devname."_pf" , $powerfactor);
  544. readingsBulkUpdate($hash, $devname."_month" , $thismonth);
  545. readingsBulkUpdate($hash, $devname."_prevmonth" , $prevmonth) if ($prevmonth);
  546. readingsBulkUpdate($hash, $devname."_lock" , $lock);
  547. readingsBulkUpdate($hash, $devname."_label" , $label) if ($label);
  548. readingsBulkUpdate($hash, $devname."_enabled" , $enabled);
  549. readingsBulkUpdate($hash, $devname."_energy" , $energy);
  550. }
  551. else # 1 Port Dose
  552. {
  553. readingsBulkUpdate($hash, "eState" , $eState);
  554. readingsBulkUpdate($hash, "power" , $power);
  555. readingsBulkUpdate($hash, "voltage" , $voltage);
  556. readingsBulkUpdate($hash, "current" , $current);
  557. readingsBulkUpdate($hash, "pf" , $powerfactor);
  558. readingsBulkUpdate($hash, "month" , $thismonth);
  559. readingsBulkUpdate($hash, "prevmonth" , $prevmonth) if ($prevmonth);
  560. readingsBulkUpdate($hash, "lock" , $lock);
  561. readingsBulkUpdate($hash, "label" , $label) if ($label);
  562. readingsBulkUpdate($hash, "enabled" , $enabled);
  563. readingsBulkUpdate($hash, "energy" , $energy);
  564. } # 1 Port
  565. } # all in one
  566. } # if
  567. } # for
  568. if(defined($a[0]) && (substr($a[0],0,2) eq "u=")) # uptime
  569. {
  570. my $sec;
  571. (undef,$sec) = split("=",$a[0]); # u=xxxx.yyy
  572. if (int($sec) > 0)
  573. {
  574. my ($seconds, $microseconds) = gettimeofday();
  575. my @t = localtime($seconds-int($sec));
  576. $hash->{powerd_on} = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $t[5]+1900,$t[4]+1,$t[3],$t[2],$t[1],$t[0]);
  577. my($d,$h,$m,$s,$up);
  578. $d=int($sec/(24*60*60));
  579. $h=($sec/(60*60))%24;
  580. $m=($sec/60)%60;
  581. $s=$sec%60;
  582. $up = "$d days, " if($d > 1);
  583. $up = "1 day, " if($d == 1);
  584. $up .= sprintf("%02s:%02s:%02s", $h, $m, $s);
  585. readingsBulkUpdate($hash, "uptime", $up);
  586. }
  587. }
  588. if (defined($a[1]) && (substr($a[1],0,2) eq "l=")) # load
  589. {
  590. my $load;
  591. (undef , $load) = split("=",$a[1]); # l=xxx yyy zzz
  592. $hash->{load} = $load if ($load);
  593. }
  594. if(int($hash->{PORTS}) > 1)
  595. {
  596. readingsBulkUpdate($hash, "all_current", sprintf("%.2f", $sum_current));
  597. readingsBulkUpdate($hash, "all_power", sprintf("%.2f", $sum_power));
  598. readingsBulkUpdate($hash, "all_month", sprintf("%.2f", $sum_month/1000));
  599. readingsBulkUpdate($hash, "all_prevmonth", sprintf("%.2f", $sum_prevmonth/1000));
  600. readingsBulkUpdate($hash, "all_energy", sprintf("%.2f", $sum_energy));
  601. }
  602. readingsBulkUpdate($hash, "state",$state);
  603. readingsEndUpdate($hash, 1 );
  604. return undef;
  605. }
  606. ################################################################################
  607. sub UbiquitiMP_Info($$)
  608. {
  609. my ($hash,$info) = @_;
  610. my $name = $hash->{NAME};
  611. my $var;
  612. my $val;
  613. my $ports;
  614. my $board_id;
  615. my @a = split(";" , $info);
  616. foreach (@a)
  617. {
  618. ($var,$val) = split("=" , $_);
  619. Log3 $name, 5, "$name, $var = $val";
  620. $board_id = $val if ($var eq "board.sysid");
  621. $hash->{BNAME} = $val if ($var eq "board.name");
  622. $hash->{SNAME} = $val if ($var eq "board.shortname");
  623. $hash->{VERSION} = $val if ($var eq "version");
  624. $hash->{MAC} = lc($val) if ($var eq "board.hwaddr");
  625. }
  626. if (($board_id) && (!$hash->{PORTS}))
  627. {
  628. if ($board_id eq "0xe648") { $ports = 8; }
  629. elsif ($board_id eq "0xe656") { $ports = 6; }
  630. elsif (($board_id eq "0xe653") ||
  631. ($board_id eq "0xe643")){ $ports = 3; }
  632. elsif ($board_id eq "0xe642") { $ports = 2; }
  633. else { $ports = 1; }
  634. if ($ports > 0)
  635. {
  636. $hash->{PORTS} = $ports;
  637. UbiquitiMP_createSets($hash);
  638. }
  639. }
  640. if (defined($hash->{VERSION}))
  641. {
  642. my $v = $hash->{VERSION};
  643. my $msg = "Old version ".$hash->{VERSION}." found, please update to >= 2.1.8 !";
  644. $v =~s/\.//g;
  645. if (int($v) < 218)
  646. {
  647. $hash->{VERSION} = $msg;
  648. Log3 $name, 1, "$name, $msg";
  649. }
  650. }
  651. if ($hash->{".init"}) # kommen wir ueber einen Neustart ?
  652. {
  653. readingsSingleUpdate($hash,"state","Initialized",1);
  654. delete($hash->{".init"});
  655. InternalTimer(gettimeofday()+$hash->{".timeout"}, "UbiquitiMP_GetStatus",$hash, 0);
  656. }
  657. return undef;
  658. }
  659. ################################################################################
  660. sub UbiquitiMP_GetStatus($)
  661. {
  662. my ($hash) = @_;
  663. my $name = $hash->{NAME};
  664. my $cmd = $name;
  665. Log3 $name, 5, "$name, GetStatus Interval : ".$hash->{INTERVAL};
  666. if ($hash->{".init"}) # kommen wir ueber einen Neustart ?
  667. {
  668. $cmd .= "#info#cat /etc/board.info | grep board";
  669. }
  670. else
  671. {
  672. $cmd .= "#status#/sbin/cgi /usr/www/mfi/sensors.cgi";
  673. $cmd .= "#awk '{print\"u=\" \$1}' /proc/uptime";
  674. $cmd .= "#awk '{print \"l=\"\$1\" \"\$2\" \"\$3}' < /proc/loadavg";
  675. $cmd .= "#cat /proc/power/energy_sum* | tr '\\n' ' '";
  676. }
  677. $hash->{helper}{RUNNING_PID} = BlockingCall("UbiquitiMP_BCStart", $cmd, "UbiquitiMP_BCDone",(int($hash->{".timeout"})*2),"UbiquitiMP_BCAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
  678. if($hash->{helper}{RUNNING_PID})
  679. {
  680. Log3 $name, 5, "$name, BC process started with PID(".$hash->{helper}{RUNNING_PID}{pid}.") cmd : $cmd";
  681. $hash->{lastcmd} = "GetStatus";
  682. }
  683. else
  684. { # das ging schief wiederholen nach doppelter timeout Wartezeit
  685. Log3 $name, 3, "$name, BC process GetStatus start failed !";
  686. InternalTimer(gettimeofday()+(int($hash->{".timeout"})*2), "UbiquitiMP_GetStatus",$hash, 0);
  687. }
  688. return;
  689. }
  690. ################################################################################
  691. sub UbiquitiMP_summaryFn($$$$) {
  692. my ($FW_wname, $hash, $room, $pageHash) = @_;
  693. $hash = $defs{$hash};
  694. my $state = $hash->{STATE};
  695. my $name = $hash->{NAME};
  696. return if ((AttrVal($name, "stateFormat", "")) || (int($hash->{PORTS}) < 2));
  697. my ($icon,$html,$cmd,$i,$title,$txt,$a,$b);
  698. $html ="<nobr>";
  699. if (($state ne "defined") && ($state ne "error") && ($state ne "Initialized"))
  700. {
  701. for ($i=1; $i<= $hash->{PORTS}; $i++)
  702. {
  703. if (defined($hash->{helper}{"Out".$i}{state}))
  704. {
  705. if ($hash->{helper}{"Out".$i}{state})
  706. {
  707. $cmd = "Out".$i." off";
  708. $title = $hash->{helper}{"Out".$i}{name}. " on";
  709. ($icon, undef, undef) = FW_dev2image($name,"on");
  710. ($a,$b) = split('title=\"on\"' , FW_makeImage($icon, "on"));
  711. $txt = $a."title=\"".$title."\"".$b;
  712. }
  713. else
  714. {
  715. $cmd = "Out".$i." on";
  716. $title = $hash->{helper}{"Out".$i}{name}. " off";
  717. ($icon, undef, undef) = FW_dev2image($name,"off");
  718. ($a,$b) = split('title=\"off\"' , FW_makeImage($icon, "off"));
  719. $txt = $a."title=\"".$title."\"".$b;
  720. }
  721. if (!$hash->{helper}{"Out".$i}{lock})
  722. {
  723. $html .= "<a href=\"/fhem?cmd.$name=set $name ".$cmd."&room=$room&amp;room=$room\">$txt</a>";
  724. }
  725. else { $html .= $txt; }
  726. $html .= "&nbsp;&nbsp;";
  727. }
  728. }
  729. } else { $html .= $state };
  730. $html .= "</nobr>";
  731. return $html;
  732. }
  733. ################################################################################
  734. sub UbiquitiMP_createSets($)
  735. {
  736. my ($hash) = @_;
  737. my $name = $hash->{NAME};
  738. my $list = AttrVal($name, "groupPorts", "");
  739. my (@a, @b);
  740. return if (!$hash->{PORTS});
  741. %sets = ();
  742. # bei nur einem Port macht eine Gruppe keinen Sinn
  743. if (int($hash->{PORTS}) == 1)
  744. {
  745. @a = split("," ,$setcmds);
  746. foreach (@a) { $sets{$_} = "noArg"; }
  747. #%sets = ($setcmds);
  748. return;
  749. }
  750. $hash->{group_ALL} = "";
  751. for (my $j=1; $j<= $hash->{PORTS}; $j++) { $sets{"Out".$j} = $setcmds; $hash->{group_ALL} .= "$j,"; }
  752. $sets{"ALL"} = $setcmds;
  753. chop($hash->{group_ALL}); # das letzte Komma weg
  754. if ($hash->{".grouplist"})
  755. {
  756. @a = split("," , $hash->{".grouplist"});
  757. foreach (@a) { delete $hash->{"group_".$_}; }
  758. $hash->{".grouplist"} = "";
  759. }
  760. if ($list)
  761. {
  762. @a = split(" " , $list);
  763. foreach (@a)
  764. {
  765. @b = split("=" , $_);
  766. if ($b[0] && (index($b[1],",") > 0))
  767. {
  768. $hash->{"group_".$b[0]} = $b[1];
  769. $sets{$b[0]} = $setcmds;
  770. $hash->{".grouplist"} .= $b[0].",";
  771. }
  772. }
  773. chop($hash->{".grouplist"});
  774. }
  775. return;
  776. }
  777. 1;
  778. =pod
  779. =item device
  780. =item summary controls Ubiquiti mPower 1 to 6 port WLAN switches
  781. =item summary_DE steuert Ubiquiti mPower 1-6 Port WLAN Schaltsteckdosen
  782. =begin html
  783. <a name="UbiquitiMP"></a>
  784. <h3>UbiquitiMP</h3>
  785. <ul>
  786. FHEM module for the Ubiquiti mFi mPower modules<br>
  787. Please read also the <a href="https://wiki.fhem.de/wiki/Ubiquit_mFi/mPower">Wiki</a> at https://wiki.fhem.de/wiki/Ubiquit_mFi/mPower<br>
  788. FHEM Forum : http://forum.fhem.de/index.php/topic,35722.0.html
  789. <a name="UbiquitiMPdefine"></a>
  790. <b>Define</b>
  791. <ul>
  792. <code>define &lt;name&gt; UbiquitiMP &lt;IP or FQDN&gt;</code><br>
  793. example :<br>
  794. define myUbi UbiquitiMP 192.168.0.100<br>
  795. define myUbi UbiquitiMP myhost.mynet.net<br>
  796. Perl Net::Telnet and JSON module are required. On a Raspberry you can install them with :<br>
  797. sudo apt-get install libjson-perl<br>
  798. sudo apt-get install libnet-telnet-perl
  799. </ul>
  800. <br>
  801. <a name="UbiquitiMPset"></a>
  802. <b>Set </b>
  803. <ul>
  804. <li>Outx on / off (force) -> turns Port x on or off</li>
  805. <li>Outx toggle -> toggle port </li>
  806. <li>Outx lock / unlock -> protects port to switch port on/off</li>
  807. <li>Outx reset -> reset power counter for this port</li>
  808. <li>Outx enable / disable -> power counting for this port</li>
  809. </ul>
  810. <a name="UbiquitiMPget"></a>
  811. <b>Get</b>
  812. <ul>
  813. <li>status -> returns the status of all Outs</li>
  814. <li>info -> returns some internal informations of the device</li>
  815. <li>reboot -> reboot the device</li><br>
  816. </ul>
  817. <a name="UbiquitiMPattr"></a>
  818. <b>Attributes</b>
  819. <ul>
  820. <li>ignoreList -> list of ignored ports<br> e.g. attr name ignoreList 456<br>ignores all values of ports 4,5 & 6<br></li>
  821. <li>groupPorts -> space separeted list to group ports so you can use them like a single device<br>
  822. e.g. attr name groupPorts TV=12 Media=4,5,6 (GroupName=Port numbers in the group)<br>
  823. set name TV on or set name Media toggle </li>
  824. <li>ledconnect -> led color since fhem connect</li>
  825. <li>subDevices -> use a single sub devices for each out port<br>
  826. (default 1 for the 3 and 6 port mPower, default 0 for the mPower mini) requires 98_UbiquitiOut.pm</li>
  827. <li>interval -> polling interval in seconds, set to 0 to disable polling (default 300)</li>
  828. <li>timeout -> seconds to wait for a answer from the Power Module (default 5 seconds)</li>
  829. <li>user -> defined user on the Power Module (default ubnt)</li>
  830. <li>password -> password for user (default ubnt)</li>
  831. </ul>
  832. <br>
  833. </ul>
  834. =end html
  835. =begin html_DE
  836. <a name="UbiquitiMP"></a>
  837. <h3>UbiquitiMP</h3>
  838. <ul>
  839. FHEM Modul f&uuml;r die Ubiquiti mFi mPower Schaltsteckdosen<br>
  840. Mehr Informationen zu den verschiedenen mPower Modellen im <a href="https://wiki.fhem.de/wiki/Ubiquit_mFi/mPower">Wiki</a> unter https://wiki.fhem.de/wiki/Ubiquit_mFi/mPower<br>
  841. FHEM Forum : http://forum.fhem.de/index.php/topic,35722.0.html
  842. <a name="UbiquitiMPdefine"></a>
  843. <b>Define</b>
  844. <ul>
  845. <code>define &lt;name&gt; UbiquitiMP &lt;IP oder FQDN&gt;</code><br>
  846. Beispiel :<br>
  847. define myUbi UbiquitiMP 192.168.0.100<br>
  848. define myUbi UbiquitiMP myhost.mynet.net<br>
  849. Das Perl Net::Telnet und sowie das JSON Modul werden unbedingt ben&ouml;tigt.
  850. Auf einem Raspberry Pi k&ouml;nnen diese mit den folgenden beiden Kommandos installiert werden:<br>
  851. sudo apt-get install libjson-perl<br>
  852. sudo apt-get install libnet-telnet-perl
  853. </ul>
  854. <br>
  855. <a name="UbiquitiMPset"></a>
  856. <b>Set </b>
  857. <ul>
  858. <li>Outx on / off (force) -> schaltet den Port x an oder aus</li>
  859. <li>Outx toggle -> schaltet den Port aus wenn er an ist und umgekehrt</li>
  860. <li>Outx lock / unlock -> Ist lock bei einem Port gesetzt kann er nicht mehr an oder aus geschaltet werden</li>
  861. <li>Outx reset -> setzt den internen Verbrauchsz&auml;hler f&uuml;r diesen Port zur&uuml;ck</li>
  862. <li>Outx enable / disable -> interne Verbrauchsmessung f&uuml;r diesen Port ein / aus schalten</li>
  863. <br><b>Bei der mPower mini entf&auml;llt die Angabe von Outx !</b><br>
  864. Zus&auml;tzlich unterst&uuml;tzt die mini die <a href="#setExtensions">set Extensions</a> direkt
  865. </ul>
  866. <a name="UbiquitiMPget"></a>
  867. <b>Get</b>
  868. <ul>
  869. <li>status -> Gibt den aktuellen Status aller Ports zur&uuml;ck</li>
  870. <li>info -> liefert einige interne Parameter des Ger&auml;tes</li>
  871. <li>reboot -> Startet das Ger&auml;t neu</li><br>
  872. </ul>
  873. <a name="UbiquitiMPattr"></a>
  874. <b>Attributes</b>
  875. <ul>
  876. <li>ignoreList -> Liste der Ports die bei Abfragen ignoriert werden sollen, Bsp. <code>attr Ubi ignoreList 456</code><br>
  877. ignoriert alle Werte der Ports 4,5 und 6</li><br>
  878. <li>groupPorts -> Durch Kommatas getrennte Liste um Ports in Gruppen zusammen zu fassen.<br>
  879. Die Gruppen k&ouml;nnen danach wie win einzelner Port behandelt werden.<br>
  880. Bsp. <code>attr Ubi groupPorts TV=12 Media=4,5,6</code> (GruppenName=Port Nummer des Ports in der Gruppe)<br>
  881. <code>set Ubi TV on</code> oder <code>set Ubi Media toggle</code></li><br>
  882. <li>ledconnect -> Farbe der LED beim Zugriff mit fhem</li><br>
  883. <li>subDevices -> Legt f&uuml;r jeden Port ein eigenes Subdevice an<br>
  884. (Default 1 f&uuml;r die 3 and 6 Port mPower, Default 0 f&uuml;r die mPower 1 Port mini) ben&ouml;tigt zus&auml;tzlich das Modul 98_UbiquitiOut.pm</li><br>
  885. <li>interval -> Abfrage Interval in Sekunden, kann ausgeschaltet werden mit dem Wert 0 (Default ist 300)</li><br>
  886. <li>timeout -> Wartezeit in Sekunden bevor eine Abfrage mit einer Fehlermeldung abgebrochen wird (Default ist 5 Sekunden)<br>
  887. Werte unter zwei Sekunden werden vom Modul nicht angenommen !</li><br>
  888. <li>user -> Login Username (Default ubnt)</li><br>
  889. <li>password -> Login Passwort (Default ubnt)</li>
  890. </ul>
  891. <br>
  892. </ul>
  893. =end html_DE
  894. =cut