32_speedtest.pm 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. # $Id: 32_speedtest.pm 12056 2016-08-22 19:30:31Z justme1968 $
  2. package main;
  3. use strict;
  4. use warnings;
  5. use Blocking;
  6. sub
  7. speedtest_Initialize($)
  8. {
  9. my ($hash) = @_;
  10. $hash->{DefFn} = "speedtest_Define";
  11. $hash->{UndefFn} = "speedtest_Undefine";
  12. $hash->{SetFn} = "speedtest_Set";
  13. $hash->{AttrList} = "checks-till-disable ".
  14. "disable:0,1 ".
  15. "path ".
  16. $readingFnAttributes;
  17. }
  18. #####################################
  19. sub
  20. speedtest_Define($$)
  21. {
  22. my ($hash, $def) = @_;
  23. my @a = split("[ \t][ \t]*", $def);
  24. return "Usage: define <name> speedtest [interval [server]]" if(@a < 2);
  25. my $name = $a[0];
  26. my $interval = 60*60;
  27. $interval = $a[2] if(int(@a)>=3);
  28. $interval = 30*60 if( $interval < 30*60 );
  29. my $server = $a[3] if(int(@a)>=4);
  30. delete( $hash->{SERVER} );
  31. $hash->{NAME} = $name;
  32. $hash->{STATE} = "Initialized";
  33. $hash->{INTERVAL} = $interval;
  34. $hash->{SERVER} = $server if( defined( $server ) );
  35. RemoveInternalTimer($hash);
  36. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "speedtest_GetUpdate", $hash, 0);
  37. return undef;
  38. }
  39. sub
  40. speedtest_Undefine($$)
  41. {
  42. my ($hash, $arg) = @_;
  43. RemoveInternalTimer($hash);
  44. BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
  45. return undef;
  46. }
  47. sub
  48. speedtest_Set($$@)
  49. {
  50. my ($hash, $name, $cmd) = @_;
  51. if($cmd eq 'statusRequest') {
  52. $hash->{LOCAL} = 1;
  53. speedtest_GetUpdate($hash);
  54. $hash->{LOCAL} = 0;
  55. return undef;
  56. }
  57. my $list = "statusRequest:noArg";
  58. return "Unknown argument $cmd, choose one of $list";
  59. }
  60. sub
  61. speedtest_GetUpdate($)
  62. {
  63. my ($hash) = @_;
  64. my $name = $hash->{NAME};
  65. if(!$hash->{LOCAL}) {
  66. RemoveInternalTimer($hash);
  67. InternalTimer(gettimeofday()+$hash->{INTERVAL}, "speedtest_GetUpdate", $hash, 0);
  68. }
  69. my $server ="";
  70. $server = $hash->{SERVER} if( defined($hash->{SERVER}) );
  71. if( !$hash->{LOCAL} ) {
  72. return undef if( AttrVal($name, "disable", 0 ) == 1 );
  73. my $checks = AttrVal($name, "checks-till-disable", undef );
  74. if( defined($checks) )
  75. {
  76. $checks -= 1;
  77. $attr{$name}{"checks-till-disable"} = max(0,$checks);
  78. $attr{$name}{"disable"} = 1 if( $checks <= 0 );
  79. }
  80. }
  81. readingsSingleUpdate($hash,"state", "running", 1);
  82. $hash->{helper}{RUNNING_PID} = BlockingCall("speedtest_DoSpeedtest", $name."|".$server, "speedtest_SpeedtestDone", 300, "speedtest_SpeedtestAborted", $hash) unless(exists($hash->{helper}{RUNNING_PID}));
  83. }
  84. sub
  85. speedtest_DoSpeedtest($)
  86. {
  87. my ($string) = @_;
  88. my ($name, $server) = split("\\|", $string);
  89. my $cmd = AttrVal($name, "path", "/usr/local/speedtest-cli" );
  90. $cmd .= "/speedtest-cli --simple";
  91. $cmd .= " --server $server" if( $server );
  92. Log3 $name, 5, "starting speedtest";
  93. my $speedstr = qx($cmd);
  94. Log3 $name, 5, "speedtest done";
  95. my @speedarr = split(/\n/, $speedstr);
  96. for( my $i = 0; $i < 3; ++$i )
  97. {
  98. $speedarr[$i] = $1 if( $speedarr[$i] && $speedarr[$i] =~ m/^\w+: (.*)/i );
  99. }
  100. return "$name|$speedarr[0]|$speedarr[1]|$speedarr[2]";
  101. }
  102. sub
  103. speedtest_SpeedtestDone($)
  104. {
  105. my ($string) = @_;
  106. return unless(defined($string));
  107. my @a = split("\\|",$string);
  108. my $hash = $defs{$a[0]};
  109. delete($hash->{helper}{RUNNING_PID});
  110. return if($hash->{helper}{DISABLED});
  111. Log3 $hash, 5, "speedtest_SpeedtestDone: $string";
  112. if( $a[1] eq "Invalid server ID" ) {
  113. readingsSingleUpdate($hash,"state", "failed", 1);
  114. return;
  115. }
  116. $a[1] =~ s/\s.*// if( defined($a[1]) );
  117. $a[2] =~ s/\s.*// if( defined($a[2]) );
  118. $a[3] =~ s/\s.*// if( defined($a[3]) );
  119. readingsBeginUpdate($hash);
  120. readingsBulkUpdate($hash,"ping",$a[1]);
  121. readingsBulkUpdate($hash,"download",$a[2]);
  122. readingsBulkUpdate($hash,"upload",$a[3]);
  123. readingsBulkUpdate($hash,"state",defined($a[3])?"ok":"failed");
  124. readingsEndUpdate($hash,1);
  125. }
  126. sub
  127. speedtest_SpeedtestAborted($)
  128. {
  129. my ($hash) = @_;
  130. delete($hash->{helper}{RUNNING_PID});
  131. }
  132. 1;
  133. =pod
  134. =item device
  135. =item summary internet speedtest data
  136. =item summary_DE Internet Speedtest &uuml;berwachung
  137. =begin html
  138. <a name="speedtest"></a>
  139. <h3>speedtest</h3>
  140. <ul>
  141. Provides internet speed data via <a href="https://github.com/sivel/speedtest-cli">speedtest-cli</a>.<br><br>
  142. Notes:
  143. <ul>
  144. <li>speedtest-cli hast to be installed on the FHEM host.</li>
  145. </ul>
  146. <a name="speedtest_Define"></a>
  147. <b>Define</b>
  148. <ul>
  149. <code>define &lt;name&gt; speedtest [&lt;interval&gt; [&lt;server&gt;]]</code><br>
  150. <br>
  151. Defines a speedtest device.<br><br>
  152. The data is updated every &lt;interval&gt; seconds. The default is 3600 and the minimum is 1800.<br><br>
  153. &lt;server&gt; gives the speedtest sever id. the list of all servers is available with <PRE>speedtest-cli --list</PRE>.
  154. Examples:
  155. <ul>
  156. <code>define speedtest speedtest</code><br>
  157. <code>define speedtest speedtest 3600 2760</code><br>
  158. </ul>
  159. </ul><br>
  160. <a name="speedtest_Readings"></a>
  161. <b>Readings</b>
  162. <ul>
  163. <li>ping</li>
  164. <li>download</li>
  165. <li>upload</li>
  166. </ul><br>
  167. <a name="speedtest_Set"></a>
  168. <b>Set</b>
  169. <ul>
  170. <li>statusRequest<br>
  171. manualy start a test. this works even if the device is set to disable.</li>
  172. </ul>
  173. <a name="speedtest_Attr"></a>
  174. <b>Attributes</b>
  175. <ul>
  176. <li>path<br>
  177. The path to the speedtest binary.</li>
  178. <li>checks-till-disable<br>
  179. how often the speedtest should be run before it is automaticaly set to disabled. the value will be decreased by 1 for every run.</li>
  180. <li>disable<br>
  181. set to 1 to disable the test.</li>
  182. </ul>
  183. </ul>
  184. =end html
  185. =cut