16_STACKABLE_CC.pm 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. ##############################################
  2. # $Id: 16_STACKABLE_CC.pm 12973 2017-01-06 10:01:25Z rudolfkoenig $
  3. package main;
  4. use strict;
  5. use warnings;
  6. #####################################
  7. sub
  8. STACKABLE_CC_Initialize($)
  9. {
  10. my ($hash) = @_;
  11. LoadModule("CUL");
  12. $hash->{Match} = "^\\*";
  13. $hash->{DefFn} = "STACKABLE_CC_Define";
  14. $hash->{UndefFn} = "STACKABLE_CC_Undef";
  15. $hash->{ParseFn} = "STACKABLE_CC_Parse";
  16. $hash->{NotifyFn} = "STACKABLE_CC_Notify";
  17. $hash->{AttrFn} = "CUL_Attr";
  18. $hash->{AttrList} = "IODev ignore:0,1 ".$modules{CUL}{AttrList};
  19. $hash->{WriteFn} = "STACKABLE_CC_Write";
  20. $hash->{GetFn} = "CUL_Get";
  21. $hash->{SetFn} = "CUL_Set";
  22. $hash->{AddPrefix} = "STACKABLE_CC_AddPrefix";
  23. $hash->{DelPrefix} = "STACKABLE_CC_DelPrefix";
  24. $hash->{noRawInform} = 1; # Our message was already sent as raw.
  25. $hash->{noAutocreatedFilelog} = 1;
  26. $hash->{IOOpenFn} = "STACKABLE_IOOpenFn";
  27. $hash->{IOReadFn} = "STACKABLE_IOReadFn";
  28. $hash->{IOWriteFn} = "STACKABLE_IOWriteFn";
  29. }
  30. #####################################
  31. sub
  32. STACKABLE_CC_Define($$)
  33. {
  34. my ($hash, $def) = @_;
  35. my @a = split("[ \t][ \t]*", $def);
  36. $hash->{TCM} = pop @a if(int(@a) == 4 && $a[3] eq "TCM");
  37. return "wrong syntax: define <name> STACKABLE_CC [CUL|SCC] [TCM]"
  38. if(int(@a) != 3);
  39. my $io = $defs{$a[2]};
  40. return "$a[2] is not a CUL/STACKABLE_CC"
  41. if(!$io || $io->{TYPE} !~ m/^(CUL|TSCUL|STACKABLE_CC|TSSTACKED)$/);
  42. return "$io->{NAME} has alread a stacked device: $io->{STACKED}"
  43. if($io->{STACKED});
  44. $io->{STACKED} = $hash->{NAME};
  45. $hash->{IODev} = $io;
  46. delete($io->{".clientArray"}); # Force a recompute
  47. if(!$hash->{TCM}) {
  48. $hash->{initString} = $io->{initString};
  49. $hash->{CMDS} = "";
  50. $hash->{Clients} = $io->{Clients};
  51. $hash->{MatchList} = $io->{MatchList};
  52. CUL_DoInit($hash);
  53. }
  54. $hash->{StackLevel} = $io->{StackLevel} ? $io->{StackLevel}+1 : 1;
  55. $hash->{STATE} = "Defined";
  56. notifyRegexpChanged($hash, $a[2]);
  57. return undef;
  58. }
  59. sub
  60. STACKABLE_CC_DoNotify($)
  61. {
  62. my ($ntfy) = @_;
  63. DoTrigger($ntfy->{NAME}, $ntfy->{TriggerText});
  64. delete $ntfy->{TriggerText};
  65. }
  66. sub
  67. STACKABLE_CC_Notify($$)
  68. {
  69. my ($ntfy, $dev) = @_;
  70. my $events = deviceEvents($dev, 0);
  71. for(my $i = 0; $i < @{$events}; $i++) {
  72. if($events->[$i] eq "DISCONNECTED") {
  73. $ntfy->{STATE} = "disconnected";
  74. setReadingsVal($ntfy, "state", "disconnected", TimeNow());
  75. $ntfy->{TriggerText} = $events->[$i];
  76. InternalTimer(gettimeofday()+0.1, "STACKABLE_CC_DoNotify", $ntfy, 0);
  77. } elsif($events->[$i] eq "CONNECTED") {
  78. CUL_DoInit($ntfy);
  79. $ntfy->{TriggerText} = $events->[$i];
  80. InternalTimer(gettimeofday()+0.001, "STACKABLE_CC_DoNotify", $ntfy, 0);
  81. }
  82. }
  83. }
  84. #####################################
  85. sub
  86. STACKABLE_CC_Write($$)
  87. {
  88. my ($hash,$fn,$msg) = @_;
  89. ($fn, $msg) = CUL_WriteTranslate($hash, $fn, $msg);
  90. return if(!defined($fn));
  91. IOWrite($hash, "", ($hash->{TCM} ? "%":"*")."$fn$msg"); # No more translations
  92. }
  93. #####################################
  94. sub
  95. STACKABLE_CC_Parse($$)
  96. {
  97. my ($iohash,$msg) = @_;
  98. $msg =~ s/^.//; # Cut off prefix *
  99. my $name = $iohash->{STACKED} ? $iohash->{STACKED} : "";
  100. my $id = $iohash->{StackLevel} ? $iohash->{StackLevel}+1 : 1;
  101. return "UNDEFINED STACKABLE_CC_$id STACKABLE_CC $iohash->{NAME}"
  102. if(!$name);
  103. return "" if(IsIgnored($name));
  104. my $sh = $defs{$name};
  105. if($sh && $sh->{TCM}) {
  106. my $th = $sh->{TCMHash};
  107. if($th) {
  108. delete $th->{IOReadFn};
  109. $th->{IODevRxBuffer} = pack("H*", $msg);
  110. CallFn($th->{NAME}, "ReadFn", $th);
  111. $th->{IOReadFn} = "STACKABLE_IOReadFn";
  112. } else {
  113. Log 1, "$name: no TCM device assigned";
  114. }
  115. } else {
  116. CUL_Parse($defs{$name}, $iohash, $name, $msg);
  117. }
  118. return "";
  119. }
  120. sub
  121. STACKABLE_CC_DelPrefix($$)
  122. {
  123. my ($hash, $msg) = @_;
  124. $msg =~ s/^[^A-Z0-9]//i;
  125. return $msg;
  126. }
  127. sub
  128. STACKABLE_CC_AddPrefix($$)
  129. {
  130. my ($hash, $msg) = @_;
  131. return "*$msg";
  132. }
  133. sub
  134. STACKABLE_CC_Undef($$)
  135. {
  136. my ($hash, $arg) = @_;
  137. CUL_SimpleWrite($hash, "X00");
  138. delete $hash->{IODev}{STACKED};
  139. return undef;
  140. }
  141. sub
  142. STACKABLE_IOOpenFn($)
  143. {
  144. my ($hash) = @_;
  145. $hash->{FD} = $hash->{IODev}{IODev}{FD}; # Lets fool the TCM
  146. $hash->{IODev}{TCMHash} = $hash;
  147. $hash->{IOReadFn} = "STACKABLE_IOReadFn";
  148. return 1;
  149. }
  150. sub
  151. STACKABLE_IOReadFn($)
  152. {
  153. my ($hash) = @_;
  154. my $me = $hash->{IODev};
  155. my $buf = "";
  156. while($buf !~ m/\n/) {
  157. $buf .= DevIo_SimpleRead($me->{IODev}); # may block
  158. }
  159. $buf =~ s/[\r\n]//g;
  160. $buf = STACKABLE_CC_DelPrefix($me, $buf);
  161. return pack("H*",$buf);
  162. }
  163. sub
  164. STACKABLE_IOWriteFn($$)
  165. {
  166. my ($hash, $msg) = @_;
  167. return IOWrite($hash, "", unpack("H*",$msg));
  168. }
  169. 1;
  170. =pod
  171. =item summary Busware Stackable CC (SCC) base module
  172. =item summary_DE Busware Stackabble CC (SCC) basis Modul
  173. =begin html
  174. <a name="STACKABLE_CC"></a>
  175. <h3>STACKABLE_CC</h3>
  176. <ul>
  177. This module handles the stackable CC1101 devices for the Raspberry PI from
  178. busware.de. You can attach a lot of CUL-Type devices to a single RPi this way.
  179. The first device is defined as a CUL, the rest of them as STACKABLE_CC.
  180. <br><br>
  181. <a name="STACKABLE_CCdefine"></a>
  182. <b>Define</b>
  183. <ul>
  184. <code>define &lt;name&gt; STACKABLE_CC &lt;Base-Device-Name&gt;</code> <br>
  185. <br>
  186. &lt;Base-Device-Name&gt; is the name of the device, which this device is
  187. attached on, the first one has to be defined as a CUL device<br>
  188. Example:
  189. <ul><code>
  190. define SCC0 CUL /dev/ttyAMA0@38400<br>
  191. attr SCC0 rfmode SlowRF<br>
  192. define SCC1 STACKABLE_CC SCC0<br>
  193. attr SCC1 rfmode HomeMatic<br>
  194. define SCC2 STACKABLE_CC SCC1<br>
  195. attr SCC2 rfmode Max<br>
  196. </code></ul>
  197. <b>Important:</b>
  198. <ul>
  199. <li>The rfmode has to be specified explicitely (valid for the STACKABLE_CC
  200. types only, not for the first, which is defined as a CUL).</li>
  201. <li>In case of SlowRF, the FHTID has to be specified explicitely with the
  202. command "set SCCX raw T01HHHH". Again, this is valid for the STACKABLE_CC
  203. types only.</li>
  204. <li>If you rename the base CUL or a STACKABLE_CC, which is a base for
  205. another one, the define of the next one has to be adjusted, and FHEM has to be
  206. restarted.</li>
  207. </ul>
  208. </ul>
  209. <a name="STACKABLE_CCset"></a>
  210. <b>Set</b> <ul>Same as for the <a href="#CULset">CUL</a>.</ul><br>
  211. <a name="STACKABLE_CCget"></a>
  212. <b>Get</b> <ul>Same as for the <a href="#CULget">CUL</a>.</ul><br>
  213. <a name="STACKABLE_CCattr"></a>
  214. <b>Attributes</b>
  215. <ul>
  216. <li><a href="#IODev">IODev</a></li><br>
  217. <li><a href="#ignore">ignore</a></li><br>
  218. The rest of the attributes is the same as for the <a href="#CULattr">CUL</a>.
  219. </ul>
  220. </ul>
  221. =end html
  222. =begin html_DE
  223. <a name="STACKABLE_CC"></a>
  224. <h3>STACKABLE_CC</h3>
  225. <ul>
  226. Mit Hilfe dieses Moduls kann man die "Stackable CC" Ger&auml;te von busware.de in
  227. FHEM integrieren. Diese Ger&auml;te erm&ouml;glichen eine Menge von CULs an einem RPi
  228. anzuschliessen.
  229. Das erste Ger&auml;t wird als CUL definiert, alle nachfolgenden als STACKABLE_CC.
  230. <br><br>
  231. <a name="STACKABLE_CCdefine"></a>
  232. <b>Define</b>
  233. <ul>
  234. <code>define &lt;name&gt; STACKABLE_CC &lt;Base-Device-Name&gt;</code> <br>
  235. <br>
  236. &lt;Base-Device-Name&gt; ist der Name des Ger&auml;tes, der als Basis f&uuml;r das
  237. aktuelle Ger&auml;t dient.<br>
  238. Beispiel:
  239. <ul><code>
  240. define SCC0 CUL /dev/ttyAMA0@38400<br>
  241. attr SCC0 rfmode SlowRF<br>
  242. define SCC1 STACKABLE_CC SCC0<br>
  243. attr SCC1 rfmode HomeMatic<br>
  244. define SCC2 STACKABLE_CC SCC1<br>
  245. attr SCC2 rfmode Max<br>
  246. </code></ul>
  247. <b>Wichtig:</b>
  248. <ul>
  249. <li>Das rfmode Attribut muss explizit spezifiziert werden. Das gilt nur
  250. f&uuml;r die STACKABLE_CC Definitionen, und nicht f&uuml;r die erste, die
  251. als CUL definiert wurde.</li>
  252. <li>Falls SlowRF spezifiziert wurde, dann muss das FHTID explizit gesetzt
  253. werden, mit folgendem Kommando: "set SCCX raw T01HHHH". Auch das ist nur
  254. f&uuml;r die STACKABLE_CC n&ouml;tig.</li>
  255. <li>Falls ein Ger&auml;t umbenannt wird, was als Basis f&uuml;r ein STACKABLE_CC
  256. dient, dann muss es auch in der Definition des abh&auml;ngigen Ger&auml;tes
  257. umbenannt werden, und FHEM muss neugestartet werden.</li>
  258. </ul>
  259. </ul>
  260. <a name="STACKABLE_CCset"></a>
  261. <b>Set</b> <ul>Die gleichen wie f&uuml;r das <a href="#CULset">CUL</a>.</ul><br>
  262. <a name="STACKABLE_CCget"></a>
  263. <b>Get</b> <ul>Die gleichen wie f&uuml;r das <a href="#CULget">CUL</a>.</ul><br>
  264. <a name="STACKABLE_CCattr"></a>
  265. <b>Attributes</b>
  266. <ul>
  267. <li><a href="#IODev">IODev</a></li><br>
  268. <li><a href="#ignore">ignore</a></li><br>
  269. Die anderen Attribute sind die gleichen wie f&uuml;r das <a href="#CULattr">CUL</a>.
  270. </ul>
  271. </ul>
  272. =end html_DE
  273. =cut