14_SD_RSL.pm 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. ###########################################
  2. # SIGNALduini RSL Modul. Modified version of FHEMduino Modul by Wzut
  3. #
  4. # $Id: 14_SD_RSL.pm 15451 2017-11-18 21:45:20Z Sidey $
  5. # Supports following devices:
  6. # - Conrad RSL
  7. #####################################
  8. package main;
  9. use strict;
  10. use warnings;
  11. my %sets = ( "on:noArg" => "", "off:noArg" => "");
  12. my @RSLCodes;
  13. # Tastenpaar [1 - 3] , Schiebeschalter/Kanal [I - IV] , an-aus [1 - 0]
  14. $RSLCodes[0][0][0] = 62; # ? / ? off
  15. $RSLCodes[0][0][1] = 54; # ? / ? on
  16. $RSLCodes[1][1][0] = 1; # 1 / I off
  17. $RSLCodes[1][1][1] = 14; # 1 / I on
  18. $RSLCodes[1][2][0] = 46; # 2 / I off
  19. $RSLCodes[1][2][1] = 38; # 2 / I on
  20. $RSLCodes[1][3][0] = 30; # 3 / I off
  21. $RSLCodes[1][3][1] = 22; # 3 / I on
  22. $RSLCodes[1][4][0] = 53; # 4 / I off - nicht auf 12 Kanal FB
  23. $RSLCodes[1][4][1] = 57; # 4 / I on - nicht auf 12 Kanal FB
  24. $RSLCodes[2][1][0] = 13; # 1 / II off
  25. $RSLCodes[2][1][1] = 5; # 1 / II on
  26. $RSLCodes[2][2][0] = 37; # 2 / II off
  27. $RSLCodes[2][2][1] = 41; # 2 / II on
  28. $RSLCodes[2][3][0] = 21; # 3 / II off
  29. $RSLCodes[2][3][1] = 25; # 3 / II on
  30. $RSLCodes[2][4][0] = 56; # 4 / II off - nicht auf 12 Kanal FB
  31. $RSLCodes[2][4][1] = 48; # 4 / II on - nicht auf 12 Kanal FB
  32. $RSLCodes[3][1][0] = 4; # 1 / III off
  33. $RSLCodes[3][1][1] = 8; # 1 / III on
  34. $RSLCodes[3][2][0] = 40; # 2 / III off
  35. $RSLCodes[3][2][1] = 32; # 2 / III on
  36. $RSLCodes[3][3][0] = 24; # 3 / III off
  37. $RSLCodes[3][3][1] = 16; # 3 / III on
  38. $RSLCodes[3][4][0] = 50; # 4 / III off - nicht auf 12 Kanal FB
  39. $RSLCodes[3][4][1] = 60; # 4 / III on - nicht auf 12 Kanal FB
  40. $RSLCodes[4][1][0] = 10; # 1 / IV off
  41. $RSLCodes[4][1][1] = 2; # 1 / IV on
  42. $RSLCodes[4][2][0] = 34; # 2 / IV off
  43. $RSLCodes[4][2][1] = 44; # 2 / IV on
  44. $RSLCodes[4][3][0] = 18; # 3 / IV off
  45. $RSLCodes[4][3][1] = 28; # 3 / IV on
  46. $RSLCodes[4][4][0] = 35; # 4 / IV off - nicht auf 12 Kanal FB
  47. $RSLCodes[4][4][1] = 19; # 4 / IV on - nicht auf 12 Kanal FB
  48. sub SD_RSL_Initialize($)
  49. {
  50. my ($hash) = @_;
  51. $hash->{Match} = "^P1#[A-Fa-f0-9]+";
  52. $hash->{SetFn} = "SD_RSL_Set";
  53. $hash->{DefFn} = "SD_RSL_Define";
  54. $hash->{UndefFn} = "SD_RSL_Undef";
  55. $hash->{AttrFn} = "SD_RSL_Attr";
  56. $hash->{ParseFn} = "SD_RSL_Parse";
  57. $hash->{AttrList} = "IODev RSLrepetition ignore:0,1 ".$readingFnAttributes;
  58. $hash->{AutoCreate}=
  59. { "RSL.*" => { GPLOT => "", FILTER => "%NAME", autocreateThreshold => "2:30"} };
  60. }
  61. #####################################
  62. sub SD_RSL_Define($$)
  63. {
  64. my ($hash, $def) = @_;
  65. my @a = split("[ \t][ \t]*", $def);
  66. return "wrong syntax: define <name> SD_RSL <code (00000-FFFFFF)_channel (1-4)_button (1-4)>" if(int(@a) != 3);
  67. my $name = $a[0];
  68. my ($device,$channel,$button) = split("_",$a[2]);
  69. return "wrong syntax: use channel 1 - 4" if(($channel > 4)); # || ($channel < 1 ));
  70. return "wrong syntax: use button 1 - 4" if(($button > 4)); # || ($button < 1));
  71. return "wrong syntax: use code 000000 - FFFFFF" if (length($device) != 6);
  72. return "wrong Device Code $device , please use 000000 - FFFFFF" if ((hex($device) < 0) || (hex($device) > 16777215));
  73. my $code = uc($a[2]);
  74. $hash->{DEF} = $code;
  75. $modules{SD_RSL}{defptr}{$code} = $hash;
  76. $modules{SD_RSL}{defptr}{$code}{$name} = $hash;
  77. # code auf 32Bit umrechnen int 16777216 = 0x1000000
  78. #$hash->{OnCode} = ($RSLCodes[$channel][$button][1]*16777216) + hex($device);
  79. #$hash->{OffCode} = ($RSLCodes[$channel][$button][0]*16777216) + hex($device);
  80. $hash->{OnCode} = "10" . sprintf('%06b', ($RSLCodes[$channel][$button][1])) . sprintf('%24b',hex($device));
  81. $hash->{OffCode} = "10" . sprintf('%06b', ($RSLCodes[$channel][$button][0])) . sprintf('%24b',hex($device));
  82. AssignIoPort($hash);
  83. return undef;
  84. }
  85. ##########################################################
  86. sub SD_RSL_Set($@)
  87. {
  88. my ($hash, @a) = @_;
  89. my $name = $hash->{NAME};
  90. my $cmd = $a[1];
  91. my $c;
  92. my $message;
  93. return join(" ", sort keys %sets) if((@a < 2) || ($cmd eq "?"));
  94. $c = $hash->{OnCode} if ($cmd eq "on") ;
  95. $c = $hash->{OffCode} if ($cmd eq "off");
  96. return "Unknown argument $cmd, choose on or off" if(!$c);
  97. my $io = $hash->{IODev};
  98. ## Send Message to IODev using IOWrite
  99. $message = 'P1#' . $c . '#R' . AttrVal($name, "RSLrepetition", 6);
  100. Log3 $name, 4, $io->{NAME} . " RSL_SET_sendCommand: $name -> message: $message";
  101. IOWrite($hash, 'sendMsg', $message);
  102. #my $ret = IOWrite($hash, 'sendMsg', $c."_".AttrVal($name, "RSLrepetition", 6));
  103. #Log3 $hash, 5, "$name Set return : $ret";
  104. #if (($cmd eq "on") && ($hash->{STATE} eq "off")){$cmd = "stop";}
  105. #if (($cmd eq "off") && ($hash->{STATE} eq "on")) {$cmd = "stop";}
  106. #$hash->{CHANGED}[0] = $cmd;
  107. #$hash->{STATE} = $cmd;
  108. readingsSingleUpdate($hash,"state",$cmd,1);
  109. return undef;
  110. }
  111. ###################################################################
  112. sub RSL_getButtonCode($$)
  113. {
  114. my ($hash,$msg) = @_;
  115. my $DeviceCode = "undef";
  116. my $receivedButtonCode = "undef";
  117. my $receivedActionCode = "undef";
  118. my $parsedButtonCode = "undef";
  119. my $action = "undef";
  120. my $button = -1;
  121. my $channel = -1;
  122. ## Groupcode
  123. $DeviceCode = substr($msg,2,6);
  124. $receivedButtonCode = substr($msg,0,2);
  125. Log3 $hash, 5, "SD_RSL Message Devicecode: $DeviceCode Buttoncode: $receivedButtonCode";
  126. if ((hex($receivedButtonCode) & 0xc0) != 0x80) {
  127. Log3 $hash, 4, "SD_RSL Message Error: received Buttoncode $receivedButtonCode begins not with bin 10";
  128. return "";
  129. }
  130. $parsedButtonCode = hex($receivedButtonCode) & 63; # nur 6 Bit bitte
  131. Log3 $hash, 4, "SD_RSL Message parsed Devicecode: $DeviceCode Buttoncode: $parsedButtonCode";
  132. for (my $i=0; $i<5; $i++)
  133. {
  134. for (my $j=0; $j<5; $j++)
  135. {
  136. next if ($i == 0 && $j != 0);
  137. next if ($i != 0 && $j == 0);
  138. if ($RSLCodes[$i][$j][0] == $parsedButtonCode)
  139. {$action ="off"; $button = $j; $channel = $i;}
  140. if ($RSLCodes[$i][$j][1] == $parsedButtonCode)
  141. {$action ="on"; $button = $j; $channel = $i;}
  142. }
  143. }
  144. if (($button >-1) && ($channel > -1))
  145. {
  146. Log3 $hash, 4, "RSL button return/result: ID: $DeviceCode $receivedButtonCode DEVICE: $DeviceCode $channel $button ACTION: $action";
  147. return $DeviceCode."_".$channel."_".$button." ".$action;
  148. }
  149. return "";
  150. }
  151. ########################################################
  152. sub SD_RSL_Parse($$)
  153. {
  154. my ($hash,$msg) = @_;
  155. my $name = $hash->{NAME};
  156. my (undef ,$rawData) = split("#",$msg);
  157. Log3 $hash, 4, "$name RSL_Parse Message: $rawData";
  158. my $result = RSL_getButtonCode($hash,$rawData);
  159. if ($result ne "")
  160. {
  161. my ($deviceCode,$action) = split m/ /, $result, 2;
  162. Log3 $hash, 4, "$name Parse: Device: $deviceCode Action: $action";
  163. my $def = $modules{SD_RSL}{defptr}{$hash->{NAME} . "." . $deviceCode};
  164. $def = $modules{SD_RSL}{defptr}{$deviceCode} if(!$def);
  165. if(!$def)
  166. {
  167. Log3 $hash, 3, "UNDEFINED Remotebutton send to define: $deviceCode";
  168. return "UNDEFINED RSL_$deviceCode SD_RSL $deviceCode";
  169. }
  170. $hash = $def;
  171. my $name = $hash->{NAME};
  172. return "" if(IsIgnored($name));
  173. if(!$action)
  174. {
  175. Log3 $name, 5, "$name SD_RSL_Parse: can't decode $msg";
  176. return "";
  177. }
  178. Log3 $name, 5, "$name SD_RSL_Parse actioncode: $action";
  179. #if (($action eq "on") && ($hash->{STATE} eq "off")){$action = "stop";}
  180. #if (($action eq "off") && ($hash->{STATE} eq "on")) {$action = "stop";}
  181. #$hash->{CHANGED}[0] = $action;
  182. #$hash->{STATE} = $action;
  183. readingsSingleUpdate($hash,"state",$action,1);
  184. return $name;
  185. }
  186. return "";
  187. }
  188. ########################################################
  189. sub SD_RSL_Undef($$)
  190. {
  191. my ($hash, $name) = @_;
  192. delete($modules{SIGNALduino_RSL}{defptr}{$hash->{DEF}}) if($hash && $hash->{DEF});
  193. return undef;
  194. }
  195. sub SD_RSL_Attr(@)
  196. {
  197. my @a = @_;
  198. # Make possible to use the same code for different logical devices when they
  199. # are received through different physical devices.
  200. return if($a[0] ne "set" || $a[2] ne "IODev");
  201. my $hash = $defs{$a[1]};
  202. my $iohash = $defs{$a[3]};
  203. my $cde = $hash->{DEF};
  204. delete($modules{SIGNALduino_FA20RF}{defptr}{$cde});
  205. $modules{SIGNALduino_FA20RF}{defptr}{$iohash->{NAME} . "." . $cde} = $hash;
  206. return undef;
  207. }
  208. 1;
  209. =pod
  210. =item summary devices communicating using the Conrad RSL protocol
  211. =item summary_DE Anbindung von Conrad RSL Ger&auml;ten
  212. =begin html
  213. <a name="SD_RSL"></a>
  214. <h3>RSL</h3>
  215. The SD_RSL module decrypts and sends Conrad RSL messages sent by the SIGNALduino.<br>
  216. <br>
  217. <a name="SD_RSL_Define"></a>
  218. <b>Define</b>
  219. <ul>
  220. <p><code>define &lt;name&gt; SD_RSL &lt;code&gt;_&lt;channel&gt;_&lt;button&gt;</code>
  221. <br>
  222. <br>
  223. <code>&lt;name&gt;</code> is any name assigned to the device.
  224. For a better overview it is recommended to use a name in the form &quot;RSL_B1A800_1_2&quot;
  225. <br /><br />
  226. <code>&lt;code&gt;</code> The code is 00000-FFFFFF
  227. <br /><br />
  228. <code>&lt;channel&gt;</code> The channel is 1-4
  229. <br /><br />
  230. <code>&lt;button&gt;</code> The button is 1-4
  231. <br /><br />
  232. </ul>
  233. <a name="SD_RSL_Set"></a>
  234. <b>Set</b>
  235. <ul>
  236. <code>set &lt;name&gt; &lt;value&gt;</code>
  237. <br /><br />
  238. <code>&lt;value&gt;</code> can be one of the following values:<br>
  239. <pre>
  240. off
  241. on
  242. </pre>
  243. </ul>
  244. <a name="SD_RSL_Get"></a>
  245. <b>Get</b>
  246. <ul>
  247. N/A
  248. </ul>
  249. <a name="SD_RSL_Attr"></a>
  250. <b>Attribute</b>
  251. <ul>
  252. <li><a href="#IODev">IODev</a></li>
  253. <li><a href="#do_not_notify">do_not_notify</a></li>
  254. <li><a href="#eventMap">eventMap</a></li>
  255. <li><a href="#ignore">ignore</a></li>
  256. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  257. <li>RSLrepetition<br>
  258. Set the repeats for sending signal.
  259. </li>
  260. </ul>
  261. =end html
  262. =cut