98_cloneDummy.pm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. # $Id: 98_cloneDummy.pm 13015 2017-01-08 20:26:33Z betateilchen $
  2. ################################################################################
  3. # 98_cloneDummy
  4. # Von Joachim Herold
  5. # FHEM Modul um aus Events von FHEM2FHEM clone-Devices zu erstellen
  6. # cloneDummy ist "readonly"
  7. # Grundlage ist 98_dummy.pm von Rudolf Koenig
  8. # von betateilchen gab es viel Hilfe (eigentlich wars betateilchen)
  9. # mit Erweiterungenen von gandy
  10. #
  11. # Anleitung:
  12. # Um cloneDummy zu nutzen, einfach einen cloneDummy anlegen
  13. #
  14. # Eintrag in der fhem.cfg:
  15. # define <name> cloneDummy <quellDevice> [reading]
  16. # attr <name> cloneIgnore <reading1,reading2,...,readingX>
  17. # attr <name> addStateEvent 1 (0 ist Vorgabe)
  18. #
  19. ################################################################################
  20. #
  21. # 2017-01-08 (betateilchen)
  22. # changed: do not use NOTIFYDEFV
  23. # fixed: set $rval in _state instead of $reading
  24. # added: new attribute deleteBeforeUpdate
  25. #
  26. ################################################################################
  27. package main;
  28. use strict;
  29. use warnings;
  30. ################################################################################
  31. # Initialisierung des Moduls
  32. ################################################################################
  33. sub cloneDummy_Initialize($) {
  34. my ($hash) = @_;
  35. $hash->{DefFn} = "cloneDummy_Define";
  36. $hash->{NotifyFn} = "cloneDummy_Notify";
  37. $hash->{AttrList} = "cloneIgnore "
  38. ."addStateEvent:0,1 "
  39. ."deleteBeforeUpdate:0,1 "
  40. .$readingFnAttributes;
  41. }
  42. ################################################################################
  43. # Definition des Moduls
  44. ################################################################################
  45. sub cloneDummy_Define($$) {
  46. my ($hash, $def) = @_;
  47. my @a = split("[ \t][ \t]*", $def);
  48. return "Wrong syntax: use define <name> cloneDummy <sourceDevice> [reading]"
  49. if((int(@a) < 3 || int(@a) > 4)) ;
  50. return "Error: cloneDummy and sourceDevice must not have the same name!"
  51. if($a[0] eq $a[2]);
  52. my $hn = $hash->{NAME};
  53. # do some cleanup in case of "modify DEF"
  54. delete $hash->{READINGS};
  55. delete $hash->{NDEV} if (defined($hash->{NDEV}));
  56. delete $hash->{NSTATE} if (defined($hash->{NSTATE}));
  57. $hash->{NDEV} = $a[2];
  58. $hash->{NSTATE} = $a[3] if(defined($a[3]));
  59. $attr{$hn}{stateFormat} = "_state" if(defined($a[3]));
  60. readingsSingleUpdate($hash,'state','defined',1);
  61. Log3($hash,4,"cloneDummy: $a[0] defined for source $a[2]");
  62. return undef;
  63. }
  64. ################################################################################
  65. # auslesen der Daten aus der globalen Schleife und aufbereiten der Daten
  66. ################################################################################
  67. sub cloneDummy_Notify($$) {
  68. my ($hash, $dev) = @_;
  69. my $dn = $dev->{NAME}; # Devicename
  70. my $hn = $hash->{NAME}; # Quellname
  71. my $hs = "";
  72. return if ($dn ne $hash->{NDEV}); # nothing to do!
  73. my $events = deviceEvents($dev, AttrVal($hn, "addStateEvent", 0)); # Quellevents
  74. my $max = int(@{$events}); # Anzahl Quellevents
  75. if(defined($hash->{NSTATE})) {
  76. $hs = $hash->{NSTATE};
  77. }
  78. delete $hash->{READINGS} if(AttrVal($hn,'deleteBeforeUpdate',0));
  79. readingsBeginUpdate($hash);
  80. readingsBulkUpdate($hash,'state', 'active');
  81. for(my $i=0;$i<$max;$i++){
  82. my $reading = $events->[$i]; # Quellevents vereinzeln
  83. $reading = "" if(!defined($reading));
  84. Log3($hash,4, "cloneDummy: $hash D: $dn R: $reading");
  85. my ($rname,$rval) = split(/ /,$reading,2); # zerlegen in Name und Wert
  86. $rname = substr($rname,0,length($rname)-1);
  87. my %check = map { $_ => 1 } split(/,/,AttrVal($hn,'cloneIgnore','')); # Vorbereitung cloneIgnore
  88. my ($isdup, undef) = CheckDuplicate("", "$hn: $reading", undef); # Vorbereitung Duplikate entfernen
  89. if ($isdup) { # Duplikate filtern
  90. Log3 $hash, 4, "cloneDummy: drop duplicate <$dn> <$hn> <$reading> ***";
  91. } else {
  92. Log3 $hash, 4, "cloneDummy: publish unique <$dn> <$hn> <$reading>";
  93. if (($hs ne "") && ($rname eq $hs) ){ # Reading in _state einsetzen
  94. readingsBulkUpdate($hash,"_state", $rval);
  95. }
  96. unless (exists ($check{$rname})) { # zu ignorierende Reading filtern
  97. readingsBulkUpdate($hash, $rname, $rval);
  98. }
  99. }
  100. }
  101. readingsEndUpdate($hash, 1);
  102. return;
  103. }
  104. 1;
  105. =pod
  106. =item helper
  107. =item summary clone a device and its readings
  108. =item summary_DE klont ein device und seine readings
  109. =begin html
  110. <a name="cloneDummy"></a>
  111. <h3>cloneDummy</h3>
  112. <ul>This module provides a cloneDummy which will receive readings from any other device sending data
  113. to fhem.<br>
  114. E.g. may be used in an FHEM2FHEM environment. Duplicate source events which may occur within the
  115. time given by the global attribute <a href="#dupTimeout">dupTimeout</a>, will be suppressed in order
  116. to avoid overhead. The value of this attribute is to be changed with great care, as it affects other
  117. parts of FHEM, too.<br>
  118. the order of precedence for STATE is following:
  119. <ul><li>if there is no parameter preset then state of cloneDummy (initialized,active)</li>
  120. <li>if addStateEvent is set then the "state" of cloned Device is set
  121. (no "state" from cloneDummy)</li>
  122. <li>if the optional reading is set in define, then value of the optional reading.
  123. (this will overstrike the previous two lines)</li>
  124. <li>if stateFormat set ass attr, it will dominate all previous lines</li>
  125. </ul>
  126. <br><a name="cloneDummydefine"></a>
  127. <b>Define</b>
  128. <ul><code>define &lt;cloneDevice&gt; cloneDummy &lt;sourceDevice&gt; [reading]</code><br>
  129. <br>Example:<br>
  130. <br>
  131. <ul><code>define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000</code>
  132. </ul>
  133. <br>Optional parameter [reading] will be written to STATE if provided.<br>
  134. <br>Example:<br>
  135. <br>
  136. <ul><code>define clone_OWX_26_09FF26010000 cloneDummy OWX_26_09FF26010000 temperature</code>
  137. </ul>
  138. <br>
  139. </ul>
  140. <a name="cloneDummyset"></a>
  141. <b>Set</b>
  142. <ul>N/A
  143. </ul>
  144. <br>
  145. <a name="cloneDummyget"></a>
  146. <b>Get</b>
  147. <ul>N/A
  148. </ul>
  149. <br>
  150. <a name="cloneDummyattr"></a>
  151. <b>Attributes</b>
  152. <ul><li>addStateEvent
  153. <br>When paremeter in Modul is set to 1 the originalstate of the original Device will be STATE
  154. (Momentarily not possible in Connection with FHEM2FHEM)</li>
  155. <br>
  156. <li>cloneIgnore
  157. <br>- comma separated list of readingnames that will NOT be generated.<br>
  158. Useful to prevent truncated readingnames coming from state events.</li>
  159. <br>
  160. <li>deleteBeforeUpdate<br>
  161. If set to 1, all readings will be deleted befor update.</li>
  162. <br>
  163. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  164. </ul>
  165. <br>
  166. <b>Important: You MUST use different names for cloneDevice and sourceDevice!</b><br>
  167. </ul>
  168. =end html
  169. =begin html_DE
  170. <a name="cloneDummy"></a>
  171. <h3>cloneDummy</h3>
  172. <ul>Definiert einen Klon eines lokalen Devices oder von FHEM2FHEM im Logmodus uebergebenen Devices
  173. und uebernimmt dessen Readings. Sinnvoll um entfernte FHEM-Installationen lesend einzubinden,
  174. zum Testen oder Programmieren. Dabei werden die von FHEM2FHEM in Form von Events weitergereichten
  175. entfernten Device-Readings in eigene Readings übernommen. Identische Events, die innerhalb der
  176. durch das globale Attribut <a href="#dupTimeout">dupTimeout</a> vorgegebenen Zeit auftreten, werden
  177. zusammengefasst, um überflüssige Events zu verhindern. Dieses Attribut ist mit bedacht zu ändern,
  178. da sich seine Auswirkungen auch auf andere Bereiche von FHEM erstreckt.<br>
  179. Die Rangfolge für den STATE ist:
  180. <ul><li>wenn keine Vorgabe gemacht wurde, dann die Meldung von cloneDummy (initialized, active)</li>
  181. <li>wenn addStateEvent gesetzt ist, dann der "state" vom geklonten Device (dann kein "state" mehr
  182. vom cloneDummy)</li>
  183. <li>wenn das optionale reading im define gesetzt ist, dann der Wert davon (überstimmt die beiden
  184. vorherigen Zeilen)</li>
  185. <li>wenn stateFormat als attr gesetzt ist, toppt das alles</li>
  186. </ul>
  187. <br>
  188. <a name="cloneDummydefine"></a>
  189. <b>Define</b>
  190. <ul><code>define &lt;name&gt; cloneDummy &lt;Quelldevice&gt; [reading]</code><br>
  191. <br>
  192. Aktiviert den cloneDummy, der dann an das Device &lt;Quelldevice&gt; gebunden ist.
  193. Mit dem optionalen Parameter reading wird bestimmt, welches reading im STATE angezeigt wird,
  194. stateFormat ist auch weiterhin möglich.<br>
  195. <br>
  196. <ul>Beispiel:<br>
  197. <br>
  198. Der cloneDummy wird lesend an den Sensor OWX_26_09FF26010000 gebunden und zeigt im
  199. State temperature an.<br>
  200. <br>
  201. <ul><code>define Feuchte cloneDummy OWX_26_09FF26010000 temperature</code><br>
  202. </ul>
  203. </ul>
  204. </ul>
  205. <br>
  206. <a name="cloneDummyset"></a>
  207. <b>Set</b>
  208. <ul>N/A
  209. </ul>
  210. <br>
  211. <a name="cloneDummyget"></a>
  212. <b>Get</b>
  213. <ul>N/A
  214. </ul>
  215. <br>
  216. <a name="cloneDummyattr"></a>
  217. <b>Attributes</b>
  218. <ul>
  219. <li>addStateEvent<br>
  220. 0 ist Vorgabe im Modul, bei 1 wird der Originalstate des original Devices als STATE verwendet
  221. (geht z.Z. nicht in Verbindung mit FHEM2FHEM)</li>
  222. <br>
  223. <li>clonIgnore<br>
  224. Eine durch Kommata getrennte Liste der readings, die cloneDummy nicht in eigene readings
  225. umwandelt</li>
  226. <br>
  227. <li>deleteBeforeUpdate<br>
  228. Ist dieses Attribut auf 1 gesetzt, werden alle readings zuerst gelöscht, bevor neue Readings geschrieben werden.</li>
  229. <br> <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  230. </ul>
  231. <br>
  232. <b>Wichtig: Es müssen unterschiedliche Namen für &lt;name&gt; und &lt;Quelldevice&gt; verwendet
  233. werden!</b><br/>
  234. <br>
  235. </ul>
  236. =end html_DE
  237. =cut