Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Generowanie wykresu
KR2615
post 8.07.2022, 15:53:07
Post #1





Grupa: Zarejestrowani
Postów: 311
Pomógł: 13
Dołączył: 7.05.2007

Ostrzeżenie: (0%)
-----


Hej. Mam stację meteorologiczną z trzema czujnikami, która co minutę dokonuje odczytu, przesyła to do skryptu .php który zapisuje wszystko w bazie MySQL. Później generuję z tego wykres z pomocą Chart.js (po 4 słupki na godzinę, każdy ze średnią z 15 minut)

Kod PHP wygląda tak:
  1. function Temperaturechart($days) {
  2. if($days == 1) {
  3. // Hour average
  4. $startH = date("H",time());
  5. $tday = date("Y-m-d",time());
  6. $yday = date("Y-m-d",time()-$days*86400);
  7. $tdayshort = date("d-m",time());
  8. $ydayshort = date("d-m",time()-$days*86400);
  9. }
  10. $sensors = array('IN','OUT','Akwa');
  11. foreach($sensors as $sensor) {
  12. $data = '';
  13. $lastvalue = 0;
  14. //Yesterday from current H to midnight
  15. for($YH = $startH; $YH < 24; $YH++) {
  16. $m = 0;
  17. while($m < 60) {
  18. $mn = $m+15;
  19. if($mn == 60) {
  20. if($YH == 23) {
  21. $q="SELECT AVG(value) AS value, COUNT(id) AS number FROM `temperatures` WHERE sensor='$sensor' AND `date` BETWEEN '$yday $YH:$m' AND '$tday 00:00'";
  22. if($sensor == 'IN') { $labels .= "\"$ydayshort $YH:$m\","; }
  23. if($temp['value'] == 0) {
  24. $value = $lastvalue;
  25. } else {
  26. $lastvalue = $temp['value'];
  27. $value = $temp['value'];
  28. }
  29. $data .= "\"$value\",";
  30. } else {
  31. //Next hour, minute 00
  32. $NH = $YH+1;
  33. $q="SELECT AVG(value) AS value, COUNT(id) AS number FROM `temperatures` WHERE sensor='$sensor' AND `date` BETWEEN '$yday $YH:$m' AND '$yday $NH:00'";
  34. if($sensor == 'IN') { $labels .= "\"$ydayshort $YH:$m\","; }
  35. if($temp['value'] == 0) {
  36. $value = $lastvalue;
  37. } else {
  38. $lastvalue = $temp['value'];
  39. $value = $temp['value'];
  40. }
  41. $data .= "\"$value\",";
  42. }
  43. } else {
  44. $q="SELECT AVG(value) AS value, COUNT(id) AS number FROM `temperatures` WHERE sensor='$sensor' AND `date` BETWEEN '$yday $YH:$m' AND '$yday $YH:$mn'";
  45. if($sensor == 'IN') { $labels .= "\"$ydayshort $YH:$m\","; }
  46. if($temp['value'] == 0) {
  47. $value = $lastvalue;
  48. } else {
  49. $lastvalue = $temp['value'];
  50. $value = $temp['value'];
  51. }
  52. $data .= "\"$value\",";
  53. }
  54. $m=$mn;
  55. }
  56. }
  57. // Today from 0 to current hour
  58. for($TH = 0; $TH < $startH; $TH++) {
  59. $m = 0;
  60. while($m < 60) {
  61. $mn = $m+15;
  62. if($mn == 60) {
  63. if($TH == 23) {
  64. $q="SELECT AVG(value) AS value, COUNT(id) AS number FROM `temperatures` WHERE sensor='$sensor' AND `date` BETWEEN '$tday $YH:$m' AND '$tday 23:59';";
  65. if($sensor == 'IN') { $labels .= "\"$tdayshort $TH:$m\","; }
  66. if($temp['value'] == 0) {
  67. $value = $lastvalue;
  68. } else {
  69. $lastvalue = $temp['value'];
  70. $value = $temp['value'];
  71. }
  72. $dataAkwa .= "\"$value\",";
  73. } else {
  74. //Next hour, minute 00
  75. $NH = $TH+1;
  76. $q="SELECT AVG(value) AS value, COUNT(id) AS number FROM `temperatures` WHERE sensor='$sensor' AND `date` BETWEEN '$tday $TH:$m' AND '$tday $NH:00';";
  77. if($sensor == 'IN') { $labels .= "\"$tdayshort $TH:$m\","; }
  78. if($temp['value'] == 0) {
  79. $value = $lastvalue;
  80. } else {
  81. $lastvalue = $temp['value'];
  82. $value = $temp['value'];
  83. }
  84. $data .= "\"$value\",";
  85. }
  86. } else {
  87. $q="SELECT AVG(value) AS value, COUNT(id) AS number FROM `temperatures` WHERE sensor='$sensor' AND `date` BETWEEN '$tday $TH:$m' AND '$tday $TH:$mn';";
  88. if($sensor == 'IN') { $labels .= "\"$tdayshort $TH:$m\","; }
  89. if($temp['value'] == 0) {
  90. $value = $lastvalue;
  91. } else {
  92. $lastvalue = $temp['value'];
  93. $value = $temp['value'];
  94. }
  95. $data .= "\"$value\",";
  96. }
  97. $m=$mn;
  98. }
  99. }
  100. ${"data$sensor"} = $data;
  101. }
  102. echo '<div class="card mb-3">
  103. <div class="card-body">
  104. <canvas id="Temperaturechart"></canvas>
  105. </div>
  106. </div>
  107.  
  108. <script>
  109. var ctxL = document.getElementById("Temperaturechart").getContext(\'2d\');
  110. var myLineChart = new Chart(ctxL, {
  111. type: \'line\',
  112. data: {
  113. labels: ['.$labels.'],
  114. datasets: [{
  115. label: "OUT",
  116. data: ['.$dataOUT.'],
  117. backgroundColor: [
  118. \'rgba(0,0,0, .2)\',
  119. ],
  120. borderColor: [
  121. \'#aaaaaa\',
  122. ],
  123. borderWidth: 2
  124. },{
  125. label: "IN",
  126. data: ['.$dataIN.'],
  127. backgroundColor: [
  128. \'rgba(154, 207, 75, .2)\',
  129. ],
  130. borderColor: [
  131. \'#9acf4b\',
  132. ],
  133. borderWidth: 2
  134. },{
  135. label: "Akwa",
  136. data: ['.$dataAkwa.'],
  137. backgroundColor: [
  138. \'rgba(66, 170, 243, .2)\',
  139. ],
  140. borderColor: [
  141. \'#42aaf3\',
  142. ],
  143. borderWidth: 2
  144. },
  145. ]
  146. },
  147. options: {
  148. responsive: true
  149. }
  150.  
  151. });
  152. </script>';
  153. }


Kod HTML wygląda tak:
https://pastebin.com/VQPFZPKF

Nie do końca podoba mi się to rozwiązanie. Raz ze względu na obciążenie - prawie 300 kwerend dla trzech czujników. Dwa że kod jest bardzo skomplikowany a to tylko wykres dla jednego dnia. Boje się pomyśleć nad tygodniem, miesiącem a może rokiem.

Czy istnieje coś innego, gotowiec, który generuje dane dla Chart.js który by mi w tym pomógł?

Lub może w ogóle zrezygnować z MySQLa i oprzeć to na czymś innym?


--------------------
Go to the top of the page
+Quote Post
trueblue
post 8.07.2022, 15:55:32
Post #2





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


A dlaczego aż 300 kwerend?
Skoro generujesz dane z jakichś interwałów czasowych określonych w PHP, to możesz równie dobrze generować wyniki w SQL z większego zakresu czasowego i grupować według określonych przedziałów.


--------------------
Go to the top of the page
+Quote Post
KR2615
post 8.07.2022, 17:16:37
Post #3





Grupa: Zarejestrowani
Postów: 311
Pomógł: 13
Dołączył: 7.05.2007

Ostrzeżenie: (0%)
-----


W sensie pobierać z SQLa w całości i grupować po stronie skryptu PHP?

Jakiś przykładowy kod na to?


--------------------
Go to the top of the page
+Quote Post
trueblue
post 9.07.2022, 08:39:46
Post #4





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


Grupować po stronie SQL.


--------------------
Go to the top of the page
+Quote Post
KR2615
post 9.07.2022, 09:38:22
Post #5





Grupa: Zarejestrowani
Postów: 311
Pomógł: 13
Dołączył: 7.05.2007

Ostrzeżenie: (0%)
-----


A jak grpować pole typu DATETIME przedziałami po 15 minut? Czy musiałbym przemodelować bazę danych i dorzucić kolejne pole oznaczające np. kolejny kwadrans doby?


--------------------
Go to the top of the page
+Quote Post
trueblue
post 9.07.2022, 09:51:14
Post #6





Grupa: Zarejestrowani
Postów: 6 761
Pomógł: 1822
Dołączył: 11.03.2014

Ostrzeżenie: (0%)
-----


  1. SELECT DATA, FROM_UNIXTIME(CEIL(UNIX_TIMESTAMP(DATA)/(15*60))*15*60) FROM tabela

W zależności do którego kwadransu (bliższego/dalszego) ma wpadać czas możesz użyć CEIL lub FLOOR.


--------------------
Go to the top of the page
+Quote Post
KR2615
post 9.07.2022, 10:33:42
Post #7





Grupa: Zarejestrowani
Postów: 311
Pomógł: 13
Dołączył: 7.05.2007

Ostrzeżenie: (0%)
-----


Dzięki, takie zapytanie rozwiązuje mój problem:

  1. SELECT AVG(value) AS temp, FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(date)/(15*60))*15*60) AS period FROM temperatures GROUP BY period;


Klikam pomógł


--------------------
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 27.04.2024 - 19:27