98_pilight.pm 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. ##############################################
  2. package main;
  3. use strict;
  4. use warnings;
  5. use IO::Socket::INET;
  6. use Switch;
  7. sub
  8. pilight_Initialize($)
  9. {
  10. my ($hash) = @_;
  11. $hash->{SetFn} = "pilight_Set";
  12. $hash->{DefFn} = "pilight_Define";
  13. $hash->{AttrList} = "protocol housecode number systemcode unitcode id remote_ip remote_port useOldVersion rawCodeOn rawCodeOff follow-on-for-timer";
  14. }
  15. # housecode == id und number == unitcode
  16. ###################################
  17. sub
  18. pilight_Set($@)
  19. {
  20. my ($hash, @a) = @_;
  21. my $rc = undef;
  22. return "no set value specified" if(int(@a) < 2);
  23. return "on off" if($a[1] eq "?");
  24. my $command = $a[1];
  25. my $c_timer= "";
  26. if(defined($a[2])) { $c_timer=$a[2]; }
  27. Log 3, "pilight command: $command";
  28. if($command eq "on")
  29. {
  30. $rc = commit($hash, 1);
  31. }
  32. elsif($command eq "on-for-timer")
  33. {
  34. InternalTimer(gettimeofday()+$c_timer, "pilight_on_timeout",$hash, 0);
  35. # on-for-timer is now a on.
  36. $rc = commit($hash, 1);
  37. }
  38. # elsif
  39. else
  40. {
  41. $rc = commit($hash, 0);
  42. }
  43. if ($rc) {
  44. $hash->{CHANGED}[0] = $command;
  45. $hash->{STATE} = $command;
  46. $hash->{READINGS}{state}{TIME} = TimeNow();
  47. $hash->{READINGS}{state}{VAL} = $command;
  48. };
  49. return undef;
  50. }
  51. ###################################
  52. sub
  53. pilight_on_timeout($)
  54. {
  55. my ($hash) = @_;
  56. my @a;
  57. $a[0]=$hash->{NAME};
  58. $a[1]="off";
  59. pilight_Set($hash,@a);
  60. return undef;
  61. }
  62. sub
  63. pilight_Define($$)
  64. {
  65. my ($hash, $def) = @_;
  66. my @a = split("[ \t][ \t]*", $def);
  67. my $u = "wrong syntax: define <name> <protocol>";
  68. return $u if(int(@a) < 2);
  69. $hash->{protocol} = $a[2];
  70. #for backward compartibility
  71. $hash->{housecode} = (int(@a) > 2) ? $a[3] : '';
  72. $hash->{unitcode} = (int(@a) > 2) ? $a[4] : '';
  73. return undef;
  74. }
  75. sub commit
  76. {
  77. my ($hash, $on) = @_;
  78. my $name = $hash->{NAME};
  79. my $protocol = $hash->{protocol};
  80. my $rawCodeOn = AttrVal($name, "rawCodeOn", $hash->{rawCodeOn});
  81. my $rawCodeOff = AttrVal($name, "rawCodeOff", $hash->{rawCodeOff});
  82. my $housecode = AttrVal($name, "id", AttrVal($name, "housecode", $hash->{housecode}));
  83. my $unit = AttrVal($name, "unitcode", $hash->{unitcode});
  84. my $systemcode = AttrVal($name, "systemcode", '0');
  85. my $param = $on ? "on" : "off";
  86. my $remote_ip = AttrVal($name, "remote_ip", '127.0.0.1');
  87. my $remote_port = AttrVal($name, "remote_port", '5000');
  88. my $useOldVersion = AttrVal($name, "useOldVersion", undef);
  89. my ($socket,$client_socket);
  90. # flush after every write
  91. $| = 1;
  92. $socket = new IO::Socket::INET (
  93. PeerHost => $remote_ip,
  94. PeerPort => $remote_port,
  95. Proto => 'tcp',
  96. );
  97. if (!$socket) {
  98. Log 3, "pilight: ERROR. Can't open socket to pilight-daemon: $! See: https://github.com/andreas-fey/fhem-pilight/issues/3\n";
  99. return undef
  100. };
  101. my $data = $useOldVersion ? '{ "message": "client sender" }' : '{ "action": "identify" }';
  102. $socket->send($data);
  103. $socket->recv($data,1024);
  104. $data =~ s/\n/ /g;
  105. if ( $data !~ /accept client/ && $data !~ /success/) # "accept client" < v6,
  106. {
  107. Log 3, "pilight: ERROR. No handshake with pilight-daemon. Received: >>>$data<<<\n";
  108. return undef
  109. };
  110. my $code = "{\"protocol\":[ \"$protocol\" ],";
  111. if( $protocol eq 'raw')
  112. {
  113. switch( $param ) {
  114. case 'on' { $code = $code . "\"code\":\"$rawCodeOn\""} # on
  115. case 'off' { $code = $code . "\"code\":\"$rawCodeOff\""} #off
  116. }
  117. }
  118. else
  119. {
  120. switch( $protocol ) {
  121. case 'kaku_switch' { $code = $code . "\"id\":$housecode, \"unit\":$unit,\"$param\":1"}
  122. case 'quigg_switch' { $code = $code . "\"id\":$housecode, \"unit\":$unit,\"$param\":1"}
  123. case 'quigg_gt7000' { $code = $code . "\"id\":$housecode, \"unit\":$unit,\"$param\":1"}
  124. case 'quigg_gt1000' { $code = $code . "\"id\":$housecode, \"unit\":$unit,\"$param\":1"}
  125. case 'elro' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  126. case 'elro_he' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  127. case 'elro_hc' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  128. case 'silvercrest' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  129. case 'pollin' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  130. case 'brennenstuhl' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  131. case 'mumbi' { $code = $code . "\"systemcode\":$systemcode, \"unitcode\":$unit,\"$param\":1"}
  132. case 'impuls' { $code = $code . "\"systemcode\":$systemcode, \"programcode\":$unit,\"$param\":1"}
  133. case 'rsl366' { $code = $code . "\"systemcode\":$systemcode, \"programcode\":$unit,\"$param\":1"}
  134. case 'intertechno_old' { $code = $code . "\"id\":$systemcode, \"unit\":$unit,\"$param\":1"}
  135. case 'clarus_switch' { $code = $code . "\"id\":\"$systemcode\", \"unit\":$unit,\"$param\":1"}
  136. case 'rev1_switch' { $code = $code . "\"id\":\"$systemcode\", \"unit\":$unit,\"$param\":1"}
  137. case 'rev2_switch' { $code = $code . "\"id\":\"$systemcode\", \"unit\":$unit,\"$param\":1"}
  138. case 'rev3_switch' { $code = $code . "\"id\":\"$systemcode\", \"unit\":$unit,\"$param\":1"}
  139. }
  140. }
  141. $code = $code . '}';
  142. $data = $useOldVersion ? "{ \"message\": \"send\", \"code\": $code}" : "{ \"action\": \"send\", \"code\": $code}";
  143. Log 3, "pilight data: $data";
  144. $socket->send($data);
  145. $socket->close();
  146. return 1;
  147. }
  148. 1;
  149. =pod
  150. =begin html
  151. <a name="pilight"></a>
  152. <h3>pilight</h3>
  153. <ul>
  154. <a name="pilight_define"></a>
  155. <h4>Define</h4>
  156. <ul>
  157. <code>define &lt;name&gt; pilight &lt;protocol&gt;</code>
  158. <br/>
  159. <br/>
  160. Defines a module for setting pilight compartible switches on or off. See <a href="http://www.sweetpi.de/blog/258/funksteckdosen-mit-dem-raspberry-pi-und-pilight-schalten">Sweetpi</a>.<br><br>
  161. Supported protocols: kaku_switch, quigg_*, elro_he, elro_hc, silvercrest, pollin, brennenstuhl, mumbi, impuls, rsl366, rev1_switch, rev2_switch, clarus_switch, raw, and intertechno_old. If you need more, just write an issue!<br/><br/>
  162. Example:
  163. <ul>
  164. <code>define Weihnachtsbaum pilight kaku_switch</code><br>
  165. <code>attr Weihnachtsbaum housecode 12323578</code><br>
  166. <code>attr Weihnachtsbaum unitcode 0</code><br>
  167. </ul>
  168. <br/>
  169. If your pilight server does not run on localhost, please set both the attributes <b>remote_ip</b> and <b>remote_port</b>. If you are running pilight >3.0, then please <b>define the port used by pilight</b> settings: http://www.pilight.org/getting-started/settings/; fhem-plight uses 5000 by default.
  170. <br/>
  171. <b>This version is written for pilight 6.0. If you run a prior version, please set the following attribute:</b>
  172. <code> attr Weihnachtsbaum useOldVersion 1</code>
  173. </ul>
  174. <a name="pilight_Attr"></a>
  175. <h4>Attributes</h4>
  176. <ul>
  177. <li><a name="protocol"><code>attr &lt;name&gt; protocol &lt;string&gt;</code></a>
  178. <br />Protocol used in pilight, e.g. "kaku_switch"</li>
  179. <li><a name="housecode"><code>attr &lt;name&gt; housecode &lt;string&gt;</code></a>
  180. <br />Housecode used in pilight (for protocol kaku*, clarus_switch, rev1_switch, rev2_switch, rev3_switch, quigg_switch, quigg_gt1000, quigg_gt7000)</li>
  181. <li><a name="systemcode"><code>attr &lt;name&gt; systemcode &lt;string&gt;</code></a>
  182. <br />Systemcode of your switch (for protocol elso, elro_he, elro_hc, silvercrest, impuls, rsl366, pollin, mumbi, brennenstuhl, intertechno_old)</li>
  183. <li><a name="unitcode"><code>attr &lt;name&gt; unitcode &lt;string&gt;</code></a>
  184. <br />Unit code/device code used in pilight (all protocols)</li>
  185. <li><a name="rawCodeOn/rawCodeOff"><code>attr &lt;name&gt; rawCode &lt;string&gt;</code></a>
  186. <br />Raw code to send on/off-command with protocol "raw"</li>
  187. <li><a name="remote_ip"><code>attr &lt;name&gt; remote_ip &lt;string&gt;</code></a>
  188. <br />Remote IP of you pilight server (127.0.0.1 is default)</li>
  189. <li><a name="remote_port"><code>attr &lt;name&gt; remote_port &lt;string&gt;</code></a>
  190. <br />Remote port of you pilight server (5000 is default)</li>
  191. <li><a name="rawCodeOn"><code>attr &lt;name&gt; rawCodeOn &lt;string&gt;</code></a>
  192. <br />Raw command to send to switch device ON (only used with protocol 'raw')</li>
  193. <li><a name="rawCodeOff"><code>attr &lt;name&gt; rawCodeOff &lt;string&gt;</code></a>
  194. <br />Raw command to send to switch device OFF (only used with protocol 'raw')</li>
  195. </ul>
  196. </ul>
  197. =end html
  198. =cut