88_xs1Bridge.pm 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. #################################################################
  2. # $Id: 88_xs1Bridge.pm 16681 2018-04-30 18:23:25Z HomeAuto_User $
  3. #################################################################
  4. # physisches Modul - Verbindung zur Hardware
  5. #
  6. # note / ToDo´s / Bugs:
  7. # - Port Check ???
  8. # - Sendeausgabe im LOG anpassen
  9. #
  10. #
  11. #################################################################
  12. package main;
  13. # Laden evtl. abhängiger Perl- bzw. FHEM-Module
  14. use HttpUtils; # um Daten via HTTP auszutauschen https://wiki.fhem.de/wiki/HttpUtils
  15. use strict;
  16. use warnings; # Warnings
  17. use Net::Ping;
  18. my $missingModul = "";
  19. my $xs1_ConnectionTry = 1; # disable Funktion sobald 10x keine Verbindung (Schutzabschaltung)
  20. my $xs1_id;
  21. eval "use Encode qw(encode encode_utf8 decode_utf8);1" or $missingModul .= "Encode ";
  22. eval "use JSON;1" or $missingModul .= "JSON ";
  23. eval "use Net::Ping;1" or $missingModul .= "Net::Ping ";
  24. #$| = 1; #Puffern abschalten, Hilfreich für PEARL WARNINGS Search
  25. sub xs1Bridge_Initialize($) {
  26. my ($hash) = @_;
  27. $hash->{WriteFn} = "xs1Bridge_Write";
  28. $hash->{Clients} = ":xs1Dev:";
  29. $hash->{MatchList} = { "1:xs1Dev" => '[x][s][1][D][e][v][#][A][k][t][o][r]#[0-6][0-9].*|[x][s][1][D][e][v][#][S][e][n][s][o][r]#[0-6][0-9].*' }; ## https://regex101.com/ Testfunktion
  30. $hash->{DefFn} = "xs1Bridge_Define";
  31. $hash->{AttrFn} = "xs1Bridge_Attr";
  32. $hash->{UndefFn} = "xs1Bridge_Undef";
  33. $hash->{AttrList} = "debug:0,1,2 ".
  34. "ignore:0,1 ".
  35. "update_only_difference:0,1 ".
  36. "view_Device_name:0,1 ".
  37. "view_Device_function:0,1 ".
  38. "xs1_blackl_aktor ".
  39. "xs1_blackl_sensor ".
  40. "xs1_control:0,1 ".
  41. "xs1_interval:0,30,60,180,360 ";
  42. ##$readingFnAttributes; ## die Standardattribute von FHEM
  43. foreach my $d(sort keys %{$modules{xs1Bridge}{defptr}}) {
  44. my $hash = $modules{xs1Bridge}{defptr}{$d};
  45. }
  46. }
  47. sub xs1Bridge_Define($$) {
  48. my ($hash, $def) = @_;
  49. my @arg = split("[ \t][ \t]*", $def);
  50. my $name = $hash->{NAME}; ## Der Definitionsname, mit dem das Gerät angelegt wurde.
  51. my $typ = $hash->{TYPE}; ## Der Modulname, mit welchem die Definition angelegt wurde.
  52. my $debug = AttrVal($hash->{NAME},"debug",0);
  53. my $viewDeviceName = AttrVal($hash->{NAME},"view_Device_name",0);
  54. my $viewDeviceFunction = AttrVal($hash->{NAME},"view_Device_function",0);
  55. my $update_only_difference = AttrVal($hash->{NAME},"update_only_difference",0);
  56. # 0 1 2
  57. return "Usage: define <NAME> $name <IP>" if(@arg != 3);
  58. #return "Usage: define <NAME> $name <IP> <PORT>" if(@arg != 4);
  59. return "Your IP is not valid. Please Check!" if not($arg[2] =~ /[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}/s);
  60. #return "Your PORT is not valid. Please Check!" if not($arg[3] =~ /[0-9]{2,5}/s);
  61. return "Cannot define xs1Bridge device. Perl modul ${missingModul}is missing." if ( $missingModul );
  62. my $xs1check = 0;
  63. if(!defined $modules{xs1Bridge}) {
  64. my $p = Net::Ping->new("tcp", 2);
  65. if(!($p->ping("$arg[2]", 2))) {
  66. $xs1check = 1;
  67. }
  68. $p->close();
  69. return "Your IP is not reachable. Please Check!" if ($xs1check == 1);
  70. }
  71. # Parameter Define
  72. my $xs1_ip = $arg[2]; ## Zusatzparameter 1 bei Define - ggf. nur in Sub
  73. $hash->{xs1_ip} = $xs1_ip;
  74. $hash->{STATE} = "Initialized"; ## Der Status des Modules nach Initialisierung.
  75. $hash->{TIME} = time(); ## Zeitstempel, derzeit vom anlegen des Moduls
  76. $hash->{VERSION} = "1.26"; ## Version
  77. $hash->{BRIDGE} = 1;
  78. # Attribut gesetzt
  79. $attr{$name}{xs1_interval} = "60" if( not defined( $attr{$name}{xs1_interval} ) );
  80. $attr{$name}{room} = "xs1" if( not defined( $attr{$name}{room} ) );
  81. $attr{$name}{xs1_control} = "0" if( not defined( $attr{$name}{xs1_control} ) );
  82. $modules{xs1Bridge}{defptr}{BRIDGE} = $hash;
  83. InternalTimer(gettimeofday()+$attr{$name}{xs1_interval}, "xs1Bridge_GetUpDate", $hash); ## set Timer
  84. #Log3 $name, 3, "$typ: IODev defined with xs1_ip: $xs1_ip";
  85. if(!defined($defs{'FileLog_xs1Bridge'})) { ## Logfile existent check
  86. Log3 $name, 4, "$typ: FileLog_xs1Bridge ist NICHT definiert";
  87. fhem("define FileLog_xs1Bridge FileLog ./log/xs1Bridge-%Y-%m.log ".$arg[0]); ## Logfile define
  88. fhem("attr FileLog_xs1Bridge room xs1"); ## Logfile in xs1 room
  89. } else {
  90. Log3 $name, 4, "$typ: FileLog_xs1Bridge ist definiert";
  91. }
  92. return undef;
  93. }
  94. sub xs1Bridge_Attr(@) {
  95. my ($cmd,$name,$attrName,$attrValue) = @_;
  96. my $hash = $defs{$name};
  97. my $typ = $hash->{TYPE};
  98. my $debug = AttrVal($hash->{NAME},"debug",0);
  99. my $xs1_interval = 0;
  100. my @string_attrValue = split(",",$attrValue) if (defined $attrValue); ## for Check Blacklist
  101. my $length = scalar @string_attrValue; ## for Check Blacklist
  102. # $cmd - Vorgangsart - kann die Werte "del" (löschen) oder "set" (setzen) annehmen
  103. # $name - Gerätename
  104. # $attrName/$attrValue sind Attribut-Name und Attribut-Wert
  105. #### Handling bei set .. attribute
  106. if ($cmd eq "set") {
  107. RemoveInternalTimer($hash); ## Timer löschen
  108. Debug " $typ: Attr | Cmd:$cmd | RemoveInternalTimer" if($debug == 2);
  109. if ($attrName eq "xs1_interval" && $attrValue == 0) { ## Handling xs1_interval == 0
  110. RemoveInternalTimer($hash);
  111. readingsSingleUpdate($hash, "state", "deactive", 1);
  112. }elsif ($attrName eq "xs1_interval" && $attrValue >= 30) { ## Handling xs1_interval >= 30
  113. $xs1_ConnectionTry = 1;
  114. my $xs1_interval = $attrValue;
  115. InternalTimer(gettimeofday()+$xs1_interval, "xs1Bridge_GetUpDate", $hash);
  116. readingsSingleUpdate($hash, "state", "active", 1);
  117. ### Ansicht xs1_Device_function ###
  118. }elsif ($attrName eq "view_Device_function") {
  119. if ($attrValue eq "1") { ## Handling view_Device_function 1
  120. #Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue";
  121. }
  122. elsif ($attrValue eq "0") { ## Handling view_Device_function 0
  123. #Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue";
  124. }
  125. ### Ansicht xs1_Device_name ###
  126. }elsif ($attrName eq "view_Device_name") {
  127. if ($attrValue eq "1") { ## Handling view_Device_name 1
  128. #Log3 $name, 3, "$typ: Attribut view_Device_name $cmd to $attrValue";
  129. }
  130. elsif ($attrValue eq "0") { ## Handling view_Device_name 0
  131. #Log3 $name, 3, "$typ: Attribut view_Device_name $cmd to $attrValue";
  132. for my $i (0..64) {
  133. delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS});
  134. delete $hash->{READINGS}{"Sensor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS});
  135. }
  136. }
  137. ### Wertaenderung nur bei Difference ###
  138. }elsif ($attrName eq "update_only_difference") {
  139. if ($attrValue eq "1") { ## Handling update_only_difference 1
  140. #Log3 $name, 3, "$typ: Attribut update_only_difference $cmd to $attrValue";
  141. }
  142. elsif ($attrValue eq "0") { ## Handling update_only_difference 0
  143. #Log3 $name, 3, "$typ: Attribut update_only_difference $cmd to $attrValue";
  144. for my $i (0..64) {
  145. delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS});
  146. }
  147. }
  148. ### xs1 - steuern ###
  149. }elsif ($attrName eq "xs1_control") {
  150. if ($attrValue eq "1") { ## Handling xs1_control 1
  151. if(! $modules{xs1Dev}) { ## Check Modul vorhanden
  152. $attr{$name}{xs1_control} = "0";
  153. return "Module xs1Dev is non-existent or still under development. Please wait"
  154. }
  155. }
  156. ### Blacklist - Aktor / Sensor ###
  157. }elsif ($attrName eq "xs1_blackl_aktor") { ## Handling xs1_blackl_aktor
  158. for (my $x = 0; $x < $length ; $x++) {
  159. if ($string_attrValue[$x] =~ /^[1-9]{1}\d*/ && $string_attrValue[$x] <65) {
  160. ## RICHTIG ##
  161. } else {
  162. return "The comma separated value must only 1 to 64";
  163. }
  164. }
  165. Log3 $name, 4, "$typ: Attribut xs1_blackl_aktor $attrValue";
  166. }elsif ($attrName eq "xs1_blackl_sensor") { ## Handling xs1_blackl_sensor
  167. for (my $x = 0; $x < $length ; $x++) {
  168. if ($string_attrValue[$x] =~ /^[1-9]{1}\d*/ && $string_attrValue[$x] <65) {
  169. ## RICHTIG ##
  170. } else {
  171. return "The comma separated value must only 1 to 64";
  172. }
  173. }
  174. Log3 $name, 4, "$typ: Attribut xs1_blackl_sensor $attrValue";
  175. }
  176. }
  177. #### Handling bei del ... attribute
  178. if ($cmd eq "del") {
  179. if ($attrName eq "xs1_interval") { ## Handling deleteattr xs1_interval
  180. RemoveInternalTimer($hash);
  181. readingsSingleUpdate($hash, "state", "deactive", 1);
  182. Debug " $typ: Attr | Cmd:$cmd | $attrName" if($debug == 2);
  183. }
  184. elsif ($attrName eq "view_Device_function") { ## Handling deleteattr view_Device_function
  185. Log3 $name, 3, "$typ: Attribut view_Device_function delete";
  186. for my $i (0..64) {
  187. for my $i2 (1..4) {
  188. delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_function_".$i2} if($hash->{READINGS});
  189. }
  190. }
  191. }
  192. elsif ($attrName eq "view_Device_name") { ## Handling deleteattr view_Device_name
  193. Log3 $name, 3, "$typ: Attribut view_Device_name delete";
  194. for my $i (0..64) {
  195. delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS});
  196. delete $hash->{READINGS}{"Sensor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS});
  197. }
  198. }
  199. elsif ($attrName eq "update_only_difference") {
  200. Log3 $name, 3, "$typ: Attribut update_only_difference delete";
  201. }
  202. }
  203. #### Handling bei state active
  204. if ($hash->{STATE} eq "active") {
  205. RemoveInternalTimer($hash);
  206. InternalTimer(gettimeofday()+$xs1_interval, "xs1Bridge_GetUpDate", $hash);
  207. Debug " $typ: Attr | RemoveInternalTimer + InternalTimer" if($debug == 2);
  208. }
  209. return undef;
  210. }
  211. sub xs1Bridge_GetUpDate() {
  212. my ($hash) = @_;
  213. my $name = $hash->{NAME};
  214. my $typ = $hash->{TYPE};
  215. my $state = $hash->{STATE};
  216. my $xs1_ip = $hash->{xs1_ip};
  217. my $xs1_uptimeStart = $hash->{helper}{xs1_uptimeStart};
  218. my $xs1_uptimeOld = $hash->{helper}{xs1_uptimeOld};
  219. my $xs1_uptimeNew = $hash->{helper}{xs1_uptimeNew};
  220. my $def;
  221. #http://x.x.x.x/control?callback=cname&cmd=...
  222. #get_list_actuators - list all actuators i0
  223. #get_list_sensors - list all sensors i1
  224. #get_list_timers - list all timers i3
  225. #get_config_info - list all device info´s i2
  226. #get_protocol_info - list protocol info´s
  227. my $cmd = "/control?callback=cname&cmd=";
  228. my @cmdtyp = ("get_list_actuators","get_list_sensors","get_config_info","get_list_timers","get_list_actuators");
  229. my @arrayname = ("actuator","sensor","info","timer","function");
  230. my @readingsname = ("Aktor","Sensor","","Timer","");
  231. my $debug = AttrVal($hash->{NAME},"debug",0);
  232. my $xs1_interval = AttrVal($name, "xs1_interval", 60);
  233. my $viewDeviceName = AttrVal($hash->{NAME},"view_Device_name",0);
  234. my $viewDeviceFunction = AttrVal($hash->{NAME},"view_Device_function",0);
  235. my $update_only_difference = AttrVal($hash->{NAME},"update_only_difference",0);
  236. my $xs1_control = AttrVal($hash->{NAME},"xs1_control",0);
  237. my $xs1_blackl_aktor = AttrVal($hash->{NAME},"xs1_blackl_aktor",0);
  238. my $xs1_blackl_sensor = AttrVal($hash->{NAME},"xs1_blackl_sensor",0);
  239. #### xs1Bridge xs1_interval >= 10 -> aktiviert zum auslesen
  240. if ($xs1_interval >= 10 && $xs1_ConnectionTry <= 5) {
  241. RemoveInternalTimer($hash); ## Timer löschen
  242. InternalTimer(gettimeofday()+$xs1_interval, "xs1Bridge_GetUpDate", $hash);
  243. Debug " -------------- ERROR CHECK - START --------------" if($debug == 2 || $debug == 1);
  244. Debug " $typ: GetUpDate | RemoveInternalTimer + InternalTimer" if($debug == 2);
  245. #Log3 $name, 3, "$typ: xs1Bridge_GetUpDate | RemoveInternalTimer + InternalTimer";
  246. if ($state eq "Initialized") {
  247. readingsSingleUpdate($hash, "state", "active", 1);
  248. }
  249. my $xs1Dev_check = "ERROR";
  250. #if($modules{xs1Dev} && $modules{xs1Dev}{LOADED}) { ## Check Modul vorhanden + geladen
  251. if($modules{xs1Dev}) { ## Check Modul vorhanden
  252. $xs1Dev_check = "ok";
  253. Debug " $typ: GetUpDate | Modul xs1Dev_check = $xs1Dev_check" if($debug == 2);
  254. } else {
  255. Debug " $typ: GetUpDate ERROR | Modul xs1Dev not existent! Please check it to be available!" if($debug == 2);
  256. #Log3 $name, 3, "$typ: GetUpDate | xs1Dev_check = $xs1Dev_check";
  257. }
  258. #### JSON Abfrage - Schleife
  259. for my $i (0..3) {
  260. #### HTTP Requests #### Start ####
  261. my $connection;
  262. my $Http_err = "";
  263. my $Http_data = "";
  264. my $param = {
  265. url => "http://".$xs1_ip.$cmd.$cmdtyp[$i],
  266. timeout => 3,
  267. method => "GET", # Lesen von Inhalten
  268. };
  269. #HttpUtils_BlockingGet($param);
  270. ($Http_err, $Http_data) = HttpUtils_BlockingGet($param);
  271. #### HTTP Requests #### END ####
  272. my $adress = "http://".$xs1_ip.$cmd.$cmdtyp[$i];
  273. my $json;
  274. my $json_utf8;
  275. my $decoded;
  276. Debug " $typ: GetUpDate | Adresse: $adress | xs1_ConnectionTry=$xs1_ConnectionTry" if($debug == 1 && $Http_err eq "");
  277. Debug " $typ: GetUpDate | HTTP request: ".$Http_err."| xs1_ConnectionTry=$xs1_ConnectionTry" if($debug == 1 && $Http_err ne "");
  278. #### HTTP Requests, ERROR
  279. if ($Http_err ne "") {
  280. # ERROR Message
  281. # http://192.168.2.5/control?callback=cname&cmd=get_list_actuators: Can't connect(1) to http://192.168.2.5:80: IO::Socket::INET: connect: No route to host
  282. # http://192.168.2.5/control?callback=cname&cmd=get_config_info: empty answer received
  283. # http://192.168.2.5/control?callback=cname&cmd=get_config_info: Select timeout/error:
  284. #($Http_err) = $Http_err =~ /[:]\s.*/g;
  285. Log3 $name, 3, "$typ: GetUpDate | Try=$xs1_ConnectionTry loop=$i | Error: ".$Http_err;
  286. $xs1_ConnectionTry++;
  287. last; ## Abbruch Schleife
  288. }
  289. #### HTTP Requests, OK dann ARRAY Verarbeitung
  290. elsif ($Http_data ne "") {
  291. ($json) = $Http_data =~ /[^(]*[}]/g; ## cut cname( + ) am Ende von Ausgabe -> ARRAY Struktur als Antwort vom xs1
  292. $json_utf8 = eval {encode_utf8( $json )}; ## UTF-8 character Bearbeitung, da xs1 TempSensoren ERROR
  293. $decoded = eval {decode_json( $json_utf8 )};
  294. $xs1_ConnectionTry = 1;
  295. #### xs1 Aktoren / Sensoren als Readings
  296. if ($i <= 1 ) {
  297. my $xs1_data;
  298. my @array;
  299. if (defined $decoded->{$arrayname[$i]}) {
  300. @array = @{ $decoded->{$arrayname[$i]} };
  301. } else {
  302. Log3 $name, 3, "$typ: GetUpDate | ARRAY-ERROR xs1 -> no Data in loop $i";
  303. last;
  304. }
  305. my $i3 = 0; ## Counter für real Werte in xs1, da sonst Verschiebungen wenn User ID´s verschiebt, NOTWENDIG!
  306. foreach my $f ( @array ) {
  307. $i3++;
  308. $xs1_id = $i3;
  309. #### Test ob Aktoren / Sensoren auf xs1_blackl
  310. if ($f->{"type"} ne "disabled" && is_in_array($hash,$xs1_id,$i) == 0) {
  311. my $xs1Dev = "xs1Dev";
  312. #### Aktoren spezifisch
  313. my $xs1_function1 = "-";
  314. my $xs1_function2 = "-";
  315. my $xs1_function3 = "-";
  316. my $xs1_function4 = "-";
  317. if ($i == 0) {
  318. #### xs1 Aktoren nur update bei differenten Wert
  319. if ($update_only_difference == 1) {
  320. my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $i3), "unknown"); ## Readings Wert
  321. my $newState = sprintf("%.1f" , $f->{"value"}); ## ARRAY Wert xs1 aktuell
  322. Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $i3)." oldState=$oldState newState=$newState" if($debug == 2);
  323. if ($oldState ne $newState) {
  324. readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3) , $newState, 0);
  325. }
  326. }
  327. #### xs1 Aktoren / Funktion != disable
  328. my @array2 = @{ $decoded->{'actuator'}->[$i3-1]->{$arrayname[4]} };
  329. my $i2 = 0; ## Funktionscounter
  330. foreach my $f2 ( @array2 ) {
  331. $i2++;
  332. #### xs1 Option - Ansicht Funktionsname
  333. if ($viewDeviceFunction == 1) {
  334. my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $i3)."_".$arrayname[4]."_".$i2, "unknown"); ## Readings Wert
  335. my $newState = $f2->{'type'}; ## ARRAY Wert xs1 aktuell
  336. if ($oldState ne "unknown" && $newState eq "disabled") { ## FunktionReading del bei disable
  337. Debug " $typ: "."Aktor_".sprintf("%02d", $i3)."_function_".$i2." are disabled" if($debug == 2);
  338. delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i3)."_function_".$i2} if($hash->{READINGS});
  339. }
  340. if ($f2->{"type"} ne "disabled") { ## Funktion != function -> type disable
  341. if ($oldState ne $newState) {
  342. readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3)."_".$arrayname[4]."_".$i2 , $f2->{"type"} , 1);
  343. }
  344. }
  345. }
  346. #### Funktion != function -> type disable
  347. if ($f2->{"type"} ne "disabled") {
  348. if ($i2 == 1) {
  349. $xs1_function1 = $f2->{"type"};
  350. }elsif ($i2 == 2) {
  351. $xs1_function2 = $f2->{"type"};
  352. }elsif ($i2 == 3) {
  353. $xs1_function3 = $f2->{"type"};
  354. }elsif ($i2 == 4) {
  355. $xs1_function4 = $f2->{"type"};
  356. }
  357. }
  358. }
  359. }
  360. #### Value der Aktoren | Sensoren
  361. if ($i == 1 || $i == 0 && $update_only_difference == 0) { # Aktoren | Sensoren im intervall - Format 0.0 bzw. 37.0 wie aus xs1
  362. readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3) , sprintf("%.1f" , $f->{"value"}), 0);
  363. $xs1_data = $xs1Dev."#".$readingsname[$i]."#".sprintf("%02d", $i3)."#".$f->{"type"}."#".sprintf("%.1f" , $f->{"value"})."#"."$xs1_function1"."#"."$xs1_function2"."#"."$xs1_function3"."#"."$xs1_function4"."#".$f->{"name"};
  364. } elsif ($i == 0 && $update_only_difference == 1){ # Aktoren | nur bei DIFF - Format 0.0 bzw. 37.0 wie aus xs1
  365. $xs1_data = $xs1Dev."#".$readingsname[$i]."#".sprintf("%02d", $i3)."#".$f->{"type"}."#".sprintf("%.1f" , $f->{"value"})."#"."$xs1_function1"."#"."$xs1_function2"."#"."$xs1_function3"."#"."$xs1_function4"."#".$f->{"name"};
  366. }
  367. #### Ausgaben je Typ unterschiedlich !!!
  368. Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $i3)." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"}." | "."F1 $xs1_function1 | F2 $xs1_function2 | F3 $xs1_function3 | F4 $xs1_function4" if($debug == 2 && $i == 0);
  369. Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $i3)." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"} if($debug == 2 && $i != 0);
  370. ### Ansicht Namen der Aktoren | Sensoren als Readings
  371. if ($viewDeviceName == 1) {
  372. my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $i3)."_name", "unknown"); ## Readings Wert
  373. my $newState = $f->{"name"}; ## ARRAY Wert xs1 aktuell
  374. if ($oldState ne $newState) { ## Namen nur bei Änderung schreiben
  375. #Log3 $name, 3, "$typ: GetUpDate | newState=$newState ne oldState=$oldState";
  376. readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3)."_name" , $f->{"name"} , 1);
  377. }
  378. }
  379. ### Dispatch an xs1Device Modul
  380. if ($xs1Dev_check eq "ok" && $xs1_control == 1) {
  381. Debug " $typ: GetUpDate | Dispatch: $xs1_data" if($debug == 2);
  382. Dispatch($hash,$xs1_data,undef) if($xs1_data);
  383. }
  384. } else {
  385. #### ID bzw. Speicherplatz xs1 ist disabled | Reading are delete
  386. delete $hash->{READINGS}{$readingsname[$i]."_".sprintf("%02d", $i3)} if($hash->{READINGS});
  387. delete $hash->{READINGS}{$readingsname[$i]."_".sprintf("%02d", $i3)."_name"} if($hash->{READINGS});
  388. ### Erweiterung v1.20 ### Device | Logfile | SVG löschen wenn in xs1 disable - TEST
  389. my $delDevice = "xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3);
  390. if (defined($defs{"xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3)})) {
  391. #Log3 $name, 3, "$typ: GetUpDate | for delete $delDevice";
  392. fhem("delete ".$delDevice); ## delete Device
  393. }
  394. if (defined($defs{"SVG_xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3)})) {
  395. #Log3 $name, 3, "$typ: GetUpDate | for delete FileLog_$delDevice";
  396. fhem("delete SVG_".$delDevice); ## delete FileLog_Device
  397. }
  398. if (defined($defs{"FileLog_xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3)})) {
  399. #Log3 $name, 3, "$typ: GetUpDate | for delete FileLog_$delDevice";
  400. fhem("delete FileLog_".$delDevice); ## delete FileLog_Device
  401. }
  402. ### Erweiterung v1.20 ### Device | Logfile | SVG löschen wenn in xs1 disable - TEST ### ENDE ###
  403. if ($i == 0) {
  404. for my $count (1..4) {
  405. delete $hash->{READINGS}{$readingsname[$i]."_".sprintf("%02d", $i3)."_function_".$count} if($hash->{READINGS});
  406. }
  407. }
  408. }
  409. }
  410. }
  411. #### xs1 Info´s nur bei uptime Änderung als Readings
  412. elsif ($i == 2) {
  413. my $features;
  414. my $features_i=0;
  415. my @xs1_readings = ("xs1_start","xs1_devicename","xs1_bootloader","xs1_hardware","xs1_features","xs1_firmware","xs1_mac","xs1_dhcp");
  416. my @xs1_decoded = (FmtDateTime(time()-($decoded->{'info'}{'uptime'})) , $decoded->{'info'}{'devicename'} , $decoded->{'info'}{'bootloader'} , $decoded->{'info'}{'hardware'} , $features , $decoded->{'info'}{'firmware'} , $decoded->{'info'}{'mac'} , $decoded->{'info'}{'autoip'});
  417. my $oldState = ReadingsVal($name, $xs1_readings[0], "2000-01-01 03:33:33"); ## Readings Wert
  418. my @oldstate = split (/[-,:,\s\/]/, $oldState); ## Split $year, $month, $mday, $hour, $min, $sec
  419. $oldState = fhemTimeGm($oldstate[5], $oldstate[4], $oldstate[3], $oldstate[2], $oldstate[1]-1, $oldstate[0]-1900); ## Verarbeitung $sec, $min, $hour, $mday, $month-1, $year-1900
  420. my $newState = FmtDateTime(time()-($decoded->{'info'}{'uptime'})); ## ARRAY uptime Wert xs1 aktuell
  421. my @newState = split (/[-,:,\s\/]/, $newState); ## Split $year, $month, $mday, $hour, $min, $sec
  422. $newState = fhemTimeGm($newState[5], $newState[4], $newState[3], $newState[2], $newState[1]-1, $newState[0]-1900); ## Verarbeitung $sec, $min, $hour, $mday, $month-1, $year-1900
  423. #### Vergleich mit 5 Sekunden Tolleranz je Verarbeitungszeit Netzwerk | DLAN | CPU
  424. if (abs($oldState - $newState) > 5) {
  425. readingsBeginUpdate($hash);
  426. for my $i2 (0..7) {
  427. if ($i2 == 4) {
  428. while (defined $decoded->{'info'}{'features'}->[$features_i]) {
  429. $features.= $decoded->{'info'}{'features'}->[$features_i]." ";
  430. $features_i++;
  431. }
  432. $xs1_decoded[4] = $features; ## ARRAY Wert xs1_decoded wird definiert
  433. }
  434. if (defined $xs1_decoded[$i2]) {
  435. readingsBulkUpdate($hash, $xs1_readings[$i2] , $xs1_decoded[$i2]);
  436. Debug " $typ: ".$xs1_readings[$i2].": ".$xs1_decoded[$i2] if($debug == 2);
  437. } else {
  438. Log3 $name, 3, "$typ: GetUpDate | ARRAY-ERROR xs1 -> no Data in loop $i|$i2";
  439. last;
  440. }
  441. }
  442. readingsEndUpdate($hash, 1);
  443. }
  444. }
  445. #### xs1 Timers als Readings
  446. elsif ($i == 3) {
  447. my @array = @{ $decoded->{$arrayname[$i]} };
  448. foreach my $f ( @array ) {
  449. my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}), "unknown"); ## Readings Wert
  450. my $newState = FmtDateTime($f->{"next"}); ## ARRAY Wert xs1 aktuell
  451. if ($f->{"type"} ne "disabled") {
  452. if ($oldState ne $newState) { ## Update Reading nur bei Wertänderung
  453. readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , FmtDateTime($f->{"next"}), 1);
  454. }
  455. Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." | ".$f->{"name"}." | ".$f->{"type"}." | ". $f->{"next"} if($debug == 2);
  456. } elsif ($oldState ne "unknown") { ## deaktive Timer mit Wert werden als Reading entfernt
  457. Log3 $name, 3, "$typ: GetUpDate | ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." is deactive in xs1";
  458. delete $defs{$name}{READINGS}{$readingsname[$i]."_".sprintf("%02d", $f->{"id"})};
  459. }
  460. }
  461. }
  462. if ($i < 2) {
  463. Debug " --------------- ERROR CHECK - SUB --------------- " if($debug == 2);
  464. }
  465. ### Schleifen Ende ###
  466. }
  467. }
  468. Debug " ------------- ERROR CHECK - ALL END -------------\n " if($debug == 2 || $debug == 1);
  469. }
  470. if ($xs1_ConnectionTry == 6) { ## Abschaltung xs1 nach 5 Verbindungsversuchen
  471. $attr{$name}{xs1_interval} = "0";
  472. readingsSingleUpdate($hash, "state", "deactive", 1);
  473. RemoveInternalTimer($hash); ## Timer löschen
  474. Log3 $name, 3, "$typ: GetUpDate | connection ERROR -> xs1 set to disable! Device not reachable after 5 attempts";
  475. }
  476. }
  477. sub xs1Bridge_Write($) ## Zustellen von Daten via IOWrite() vom logischen zum physischen Modul
  478. {
  479. my ($hash, $Aktor_ID, $xs1_typ, $cmd, $cmd2) = @_;
  480. my $name = $hash->{NAME};
  481. my $typ = $hash->{TYPE};
  482. my $xs1_ip = $hash->{xs1_ip};
  483. my $debug = AttrVal($hash->{NAME},"debug",0);
  484. ## Anfrage (Client -> XS1): http://192.168.1.242/control?callback=cname&cmd=set_state_actuator&number=1&value=100
  485. ## Aktor Typen aus xs1: (notwendig zur Verarbeitung)
  486. ## -------------------------------------------------
  487. ## blind - Jalousie | dimmer - Dimmer | door - Tür | disabled - deaktivert
  488. ## switch - Schalter | shutter - Rolladen | sound - Ton | sun-blind - Markise
  489. ## temperature - Temperatur | timerswitch - Zeitschalter | window - Fenster
  490. ## Sensor Typen (Auswahl) aus xs1: (nur Info)
  491. ## ------------------------------------------
  492. ## alarmmat - Alarmmatte | disabled - deaktivert
  493. ## gas_butan - Gasmelder Butan | gas_peak - Gas Spitzenwert
  494. ## mail - Briefmelder | motion - Bewegung
  495. ## other - Andere | presence - Anwesenheit
  496. ## pwr_consump - Energiezähler | pwr_peak - Energie Spitzenwert
  497. ## soilmoisture - Bodenfeuchte | soiltemp - Bodentemperatur
  498. ## leafwetness - Blattfeuchte | remotecontrol - Fernbedienung
  499. ## windowopen - Fenstermelder ...
  500. $Aktor_ID = substr($Aktor_ID, 1,2);
  501. my $xs1cmd;
  502. #### xs1 Typ switch || shutter || timerswitch - Anpassung Sendebefehl
  503. if ($xs1_typ eq "switch" || $xs1_typ eq "shutter" || $xs1_typ eq "timerswitch") {
  504. $xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&$cmd2";
  505. } elsif ($xs1_typ eq "dimmer") {
  506. if ($cmd eq "off") {
  507. $cmd = 0;
  508. }
  509. $xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&$cmd2" if ($cmd2 =~ /[f][u][n][c][t][i][o][n][=]./);
  510. my $valuenew = substr($cmd2,3,length($cmd2)-3) if ($cmd2 !~ /[f][u][n][c][t][i][o][n][=]./);
  511. #Log3 $name, 3, "$typ: Write | Check cmd=$cmd cmd2=$cmd2 valuenew=$valuenew";
  512. $xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&value=$valuenew" if ($cmd2 !~ /[f][u][n][c][t][i][o][n][=]./);
  513. } else {
  514. #### keine Verarbeitung zum senden ####
  515. Log3 $name, 3, "$typ: Write | $xs1_typ not control xs1. Please inform me!";
  516. last;
  517. }
  518. ### HTTP Requests #### Start ####
  519. my $connection;
  520. my $Http_err = "";
  521. my $Http_data;
  522. my $param = {
  523. url => "$xs1cmd",
  524. timeout => 3,
  525. method => "GET", # Lesen von Inhalten
  526. };
  527. ($Http_err, $Http_data) = HttpUtils_BlockingGet($param);
  528. ### HTTP Requests #### END ####
  529. if ($Http_err ne "") {
  530. ($Http_err) = $Http_err =~ /[:]\s.*/g;
  531. Log3 $name, 3, "$typ: Write | no Control possible | Error".$Http_err;
  532. return undef;
  533. } elsif ($Http_data ne "") {
  534. Debug " $typ: Write | Send to xs1 -> $xs1cmd" if($debug == 1); ## Kontrolle Sendebefehl
  535. }
  536. }
  537. sub xs1Bridge_Undef($$)
  538. {
  539. my ( $hash, $name) = @_;
  540. my $typ = $hash->{TYPE};
  541. RemoveInternalTimer($hash);
  542. delete $modules{xs1Bridge}{defptr}{BRIDGE} if( defined($modules{xs1Bridge}{defptr}{BRIDGE}) );
  543. Log3 $name, 3, "$typ: deleting Device with Name $name";
  544. foreach my $d (sort keys %defs) {
  545. if(defined($defs{$d}) && defined($defs{$d}{IODev}) && $defs{$d}{IODev} == $hash) {
  546. Log3 $name, 3, "$typ: deleting IODev for $d";
  547. delete $defs{$d}{IODev};
  548. }
  549. }
  550. return undef;
  551. }
  552. ##########################
  553. # eigene Sub
  554. sub is_in_array($$$)
  555. {
  556. my ( $hash,$xs1_id,$i) = @_;
  557. my $name = $hash->{NAME};
  558. my $typ = $hash->{TYPE};
  559. my $xs1_blackl = AttrVal($hash->{NAME},"xs1_blackl_aktor",0) if ($i eq 0);
  560. $xs1_blackl = AttrVal($hash->{NAME},"xs1_blackl_sensor",0) if ($i eq 1);
  561. my @attr_array=split(/,/,$xs1_blackl);
  562. if ( grep( /^$xs1_id$/, @attr_array ) ) {
  563. #Log3 $name, 3, "$typ: is_in_array | id=$xs1_id auf xs1_blackl Aktoren" if ($i eq 0);
  564. #Log3 $name, 3, "$typ: is_in_array | id=$xs1_id auf xs1_blackl Sensoren" if ($i eq 1);
  565. return 1;
  566. } else {
  567. #Log3 $name, 3, "$typ: is_in_array | id=$xs1_id NICHT auf xs1_blackl Aktoren" if ($i eq 0);
  568. #Log3 $name, 3, "$typ: is_in_array | id=$xs1_id NICHT auf xs1_blackl Sensoren" if ($i eq 1);
  569. return 0;
  570. }
  571. }
  572. ##########################
  573. # Eval-Rückgabewert für erfolgreiches
  574. # Laden des Moduls
  575. 1;
  576. # Beginn der Commandref
  577. =pod
  578. =item summary Connection of the device xs1 from EZControl
  579. =item summary_DE Anbindung des Ger&auml;tes xs1 der Firma EZControl
  580. =begin html
  581. <a name="xs1Bridge"></a>
  582. <h3>xs1Bridge</h3>
  583. <ul>
  584. With this module you can read out the device xs1 from EZcontrol. There will be actors | Sensors | Timer | Information read from xs1 and written in readings. With each read only readings are created or updated, which are also defined and active in xs1. Actor | Sensor or timer definitions which are deactivated in xs1 are NOT read.
  585. <br><br>
  586. The module was developed based on the firmware version v4-Beta of the xs1. There may be errors due to different adjustments within the manufacturer's firmware.<br>
  587. Testet firmware: v4.0.0.5326 (Beta) @me | v3.0.0.4493 @ForumUser<br>
  588. <br><ul>
  589. <u>Currently implemented types of xs1 for processing: </u><br>
  590. <li>Aktor: dimmer, switch, shutter, timerswitch</li>
  591. <li>Sensor: barometer, counter, counterdiff, light, motion, other, rain, rain_1h, rain_24h, rainintensity, remotecontrol, uv_index, waterdetector, winddirection, windgust, windspeed, windvariance</li>
  592. </ul><br><br>
  593. <a name="xs1Bridge_define"></a>
  594. <b>Define</b><br>
  595. <ul>
  596. xs1 without password:&nbsp;&nbsp;<code>define &lt;NAME&gt; xs1Bridge &lt;IP&gt;</code><br>
  597. xs1 with password:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>define &lt;NAME&gt; xs1Bridge &lt;User&gt;:&lt;Passwort&gt;@&lt;IP&gt;</code>
  598. <br><br>
  599. The module can not create without the IP of the xs1. If the IP can not be reached during module definition, the Define process is aborted.
  600. <ul>
  601. <li><code>&lt;IP&gt;</code> is IP address in the local network</li>
  602. <li><code>&lt;User&gt;</code> is the administrator user admin (default)</li>
  603. <li><code>&lt;Password&gt;</code> is the assigned administrator password in xs1</li>
  604. </ul><br>
  605. examples:
  606. <ul>
  607. define EZcontrol_xs1 xs1Bridge 192.168.1.45<br>
  608. define EZcontrol_xs1 xs1Bridge admin:secret@192.168.1.45<br>
  609. </ul>
  610. </ul><br>
  611. <b>Set</b>
  612. <ul>N/A</ul><br>
  613. <b>Get</b><br>
  614. <ul>N/A</ul><br>
  615. <a name="xs1_attr"></a>
  616. <b>Attributes</b>
  617. <ul>
  618. <li>debug (0,1,2)<br>
  619. This brings the module into a very detailed debug output in the logfile. Program parts can be checked and errors checked.<br>
  620. (Default, debug 0)
  621. </li><br>
  622. <li>update_only_difference (0,1)<br>
  623. The actuators defined in xs1 are only updated when the value changes.<br>
  624. (Default, update_only_difference 0)</li><br>
  625. <li>view_Device_name (0,1)<br>
  626. The actor names defined in xs1 are read as Reading.<br>
  627. (Default, view_Device_name 0)<br>
  628. </li><br>
  629. <li>view_Device_function (0,1)<br>
  630. The actuator functions defined in xs1 are read out as Reading.<br>
  631. (Default, view_Device_function 0)<br>
  632. </li><br>
  633. <li>xs1_blackl_aktor<br>
  634. A comma-separated blacklist of actuators, which should not be created automatically as soon as xs1_control = 1(aktiv).<br>
  635. (Example: 2,40,3)<br>
  636. </li><br>
  637. <li>xs1_blackl_sensor<br>
  638. A comma-separated blacklist of sensors, which should not be created automatically as soon as xs1_control = 1(aktiv).<br>
  639. (Example: 3,37,55)<br>
  640. </li><br>
  641. <li>xs1_control (0,1)<br>
  642. Option to control the xs1. After activating this, the xs1Dev module creates each actuator and sensor in FHEM.<br>
  643. (Default, xs1_control 0)<br><br>
  644. <li>xs1_interval (0,30,60,180,360)<br>
  645. This is the interval in seconds at which readings are read from xs1<br>
  646. <i>For actuators, only different states are updated in the set interval.</i><br>
  647. <i>Sensors are always updated in intervals, regardless of the status.</i><br>
  648. (Default, xs1_interval 60)
  649. </li><br>
  650. </li><br><br>
  651. </ul>
  652. <b>explanation:</b>
  653. <ul>
  654. <li>various Readings:</li>
  655. <ul>
  656. <li>Aktor_(01-64)</li> defined actuator in the device<br>
  657. <li>Aktor_(01-64)_name</li> defined actor name in the device<br>
  658. <li>Aktor_(01-64)_function(1-4)</li> defined actuator function in the device<br>
  659. <li>Sensor_(01-64)</li> defined sensor in the device<br>
  660. <li>Sensor_(01-64)_name</li> defined sensor name in the device<br>
  661. <li>Timer_(01-128)</li> defined timer in the device<br>
  662. <li>xs1_bootloader</li> version of bootloader<br>
  663. <li>xs1_dhcp</li> DHCP on/off<br>
  664. <li>xs1_features</li> purchased feature when buying (A = send | B = receive | C = Skripte/Makros | D = Media Access)<br>
  665. <li>xs1_firmware</li> firmware number<br>
  666. <li>xs1_start</li> device start<br>
  667. </ul><br>
  668. <li>The message "<code>... Can't connect ...</code>" or "<code>ERROR: empty answer received</code>" in the system logfile says that there was no query for a short time.<br>
  669. (This can happen more often with DLAN.)<br><br></li>
  670. <li>If the device has not been connected after 5 connection attempts, the module will switch on < disable > !</li><br>
  671. <li>Create logfile automatically after define | scheme: <code>define FileLog_xs1Bridge FileLog ./log/xs1Bridge-%Y-%m.log &lt;name&gt;</code><br>
  672. The following values ​​are recorded in logfile: Timer | xs1-status information</li>
  673. </ul>
  674. </ul>
  675. =end html
  676. =begin html_DE
  677. <a name="xs1Bridge"></a>
  678. <h3>xs1Bridge</h3>
  679. <ul>
  680. Mit diesem Modul k&ouml;nnen Sie das Gerät xs1 der Firma <a href="http://www.ezcontrol.de/">EZcontrol</a> auslesen. Das Modul ruft die Daten des xs1 via der Kommunikationsschnittstelle ab. Mit einem HTTP GET Requests erh&auml;lt man die Antworten in Textform welche im Datenformat JSON (JavaScript Object Notation) ausgegeben werden.
  681. Es werden Aktoren | Sensoren | Timer | Informationen vom xs1 ausgelesen und in Readings geschrieben. Bei jedem Auslesen werden nur Readings angelegt bzw. aktualisiert, welche auch im xs1 definiert und aktiv sind. Aktor | Sensor bzw. Timer Definitionen welche deaktiviert sind im xs1, werden NICHT ausgelesen.
  682. <br><br>
  683. Das Modul wurde entwickelt basierend auf dem Firmwarestand v4-Beta des xs1. Es kann aufgrund von unterschiedlichen Anpassungen innerhalb der Firmware des Herstellers zu Fehlern kommen.<br>
  684. Getestete Firmware: v4.0.0.5326 (Beta) @me | v3.0.0.4493 @ForumUser<br>
  685. <br><ul>
  686. <u>Derzeit implementierte Typen des xs1 zur Verarbeitung: </u><br>
  687. <li>Aktor: dimmer, switch, shutter, timerswitch</li>
  688. <li>Sensor: barometer, counter, counterdiff, light, motion, other, rain, rain_1h, rain_24h, rainintensity, remotecontrol, uv_index, waterdetector, winddirection, windgust, windspeed, windvariance</li>
  689. </ul><br><br>
  690. <a name="xs1Bridge_define"></a>
  691. <b>Define</b><br>
  692. <ul>
  693. xs1 ohne Passwortabfrage:&nbsp;&nbsp;<code>define &lt;NAME&gt; xs1Bridge &lt;IP&gt;</code><br>
  694. xs1 mit Passwortabfrage:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>define &lt;NAME&gt; xs1Bridge &lt;User&gt;:&lt;Passwort&gt;@&lt;IP&gt;</code>
  695. <br><br>
  696. Ein anlegen des Modules ohne Angabe der IP vom xs1 ist nicht m&ouml;glich. Sollte die IP bei der Moduldefinierung nicht erreichbar sein, so bricht der Define Vorgang ab.
  697. <ul>
  698. <li><code>&lt;IP&gt;</code> ist IP-Adresse im lokalen Netzwerk</li>
  699. <li><code>&lt;User&gt;</code> ist der Administrator Benutzer admin (standard)</li>
  700. <li><code>&lt;Passwort&gt;</code> ist das vergebene Administrator Passwort im xs1.</li>
  701. </ul><br>
  702. Beispiele:
  703. <ul>
  704. define EZcontrol_xs1 xs1Bridge 192.168.1.45<br>
  705. define EZcontrol_xs1 xs1Bridge admin:geheim@192.168.1.45<br>
  706. </ul>
  707. </ul><br>
  708. <b>Set</b>
  709. <ul>N/A</ul><br>
  710. <b>Get</b><br>
  711. <ul>N/A</ul><br>
  712. <a name="xs1_attr"></a>
  713. <b>Attribute</b>
  714. <ul>
  715. <li>debug (0,1,2)<br>
  716. Dies bringt das Modul in eine sehr ausf&uuml;hrliche Debug-Ausgabe im Logfile. Somit lassen sich Programmteile kontrollieren und Fehler &uuml;berpr&uuml;fen.<br>
  717. (Default, debug 0)
  718. </li><br>
  719. <li>update_only_difference (0,1)<br>
  720. Die Aktoren welche im xs1 definiert wurden, werden nur bei Wert&auml;nderung aktualisiert.<br>
  721. (Default, update_only_difference 0)</li><br>
  722. <li>view_Device_name (0,1)<br>
  723. Die Aktor Namen welche im xs1 definiert wurden, werden als Reading ausgelesen.<br>
  724. (Default, view_Device_name 0)<br>
  725. </li><br>
  726. <li>view_Device_function (0,1)<br>
  727. Die Aktor Funktionen welche im xs1 definiert wurden, werden als Reading ausgelesen.<br>
  728. (Default, view_Device_function 0)<br>
  729. </li><br>
  730. <li>xs1_blackl_aktor<br>
  731. Eine kommagetrennte Blacklist der Aktoren, welche nicht automatisch angelegt werden sollen sobald xs1_control = 1(aktiv).<br>
  732. (Beispiel: 2,40,3)<br>
  733. </li><br>
  734. <li>xs1_blackl_sensor<br>
  735. Eine kommagetrennte Blacklist der Sensoren, welche nicht automatisch angelegt werden sollen sobald xs1_control = 1(aktiv).<br>
  736. (Beispiel: 3,37,55)<br>
  737. </li><br>
  738. <li>xs1_control (0,1)<br>
  739. Die Freigabe zur Steuerung des xs1. Nach Aktivierung dieser, wird durch das xs1Dev Modul jeder Aktor und Sensor in FHEM angelegt.<br>
  740. (Default, xs1_control 0)<br>
  741. </li><br>
  742. <li>xs1_interval (0,30,60,180,360)<br>
  743. Das ist der Intervall in Sekunden, in dem die Readings neu gelesen werden vom xs1.<br>
  744. <i>Bei Aktoren werden nur unterschiedliche Zust&auml;nde aktualisiert im eingestellten Intervall.</i><br>
  745. <i>Sensoren werden unabhängig vom Zustand immer im Intervall aktualisiert.</i><br>
  746. (Default, xs1_interval 60)
  747. </li><br><br>
  748. </ul>
  749. <b>Erl&auml;uterung:</b>
  750. <ul>
  751. <li>Auszug Readings:</li>
  752. <ul>
  753. <li>Aktor_(01-64)</li> definierter Aktor mit jeweiligem Zustand im Ger&auml;t<br>
  754. <li>Aktor_(01-64)_name</li> definierter Aktorname im Ger&auml;t<br>
  755. <li>Aktor_(01-64)_function(1-4)</li> definierte Aktorfunktion im Ger&auml;t<br>
  756. <li>Sensor_(01-64)</li> definierter Sensor im Ger&auml;t<br>
  757. <li>Sensor_(01-64)</li> definierter Sensorname im Ger&auml;t<br>
  758. <li>Timer_(01-128)</li> definierter Timer im Ger&auml;t<br>
  759. <li>xs1_bootloader</li> Firmwareversion des Bootloaders<br>
  760. <li>xs1_dhcp</li> DHCP an/aus<br>
  761. <li>xs1_features</li> erworbene Feature beim Kauf (A = SENDEN | B = EMPFANGEN | C = Skripte/Makros | D = Speicherkartenzugriff)<br>
  762. <li>xs1_firmware</li> Firmwareversion<br>
  763. <li>xs1_start</li> Ger&auml;testart<br>
  764. </ul><br>
  765. <li>Die Meldung "<code>Error: Can't connect ...</code>" oder "<code>ERROR: empty answer received</code>" im System-Logfile, besagt das kurzzeitig keine Abfrage erfolgen konnte.<br>
  766. (Das kann h&auml;ufiger bei DLAN vorkommen.)<br><br></li>
  767. <li>Sollte das Ger&auml;t nach 5 Verbindungsversuchen ebenfalls keine Verbindung erhalten haben, so schaltet das Modul auf < disable > !</li><br>
  768. <li>Logfile Erstellung erfolgt automatisch nach dem definieren. | Schema: <code>define FileLog_xs1Bridge FileLog ./log/xs1Bridge-%Y-%m.log &lt;Name&gt;</code><br>
  769. Folgende Werte werden im Logfile erfasst: Timer | xs1-Statusinformationen</li><br>
  770. <li>Sollte das Ger&auml;t nach 5 Verbindungsversuchen ebenfalls keine Verbindung erhalten haben, so schaltet das Modul auf < disable > !</li><br>
  771. </ul>
  772. </ul>
  773. =end html_DE
  774. =cut