Arsip untuk Juli, 2017


Ngrok skema : sumber gambar ngrok.com

Ngrok skema : sumber gambar ngrok.com

Assalamu’alaikum Wr. Wb.
Oke saya lanjutkan. remind lagi ini adalah seri berantai dari posting berikut ya

  1. https://tarecha.wordpress.com/2015/10/26/project-raspberry-pi/
  2. https://tarecha.wordpress.com/2017/06/05/project-weather-logger-part-1/
  3. https://tarecha.wordpress.com/2017/06/26/project-weather-logger-part-2-tambahan-sensor-tekanan-udara/
  4. https://tarecha.wordpress.com/2017/07/01/project-weather-logger-part-3-komunikasi-udp/
  5. https://tarecha.wordpress.com/2017/07/15/project-weather-logger-part-4-simpan-di-server-mysql/
  6. https://tarecha.wordpress.com/2017/07/24/project-weather-logger-part-5-view-data-dan-export/
  7. https://tarecha.wordpress.com/2017/07/25/project-weather-logger-part-6-plot-graphic/

 

web servernya bisa langsung diakses di sini ya http://weatherlogger.ap.ngrok.io/

oke kita lanjutkan part 7 yaitu http tunelling.  ingat gambar berikut ? ada garis yang akses langsung ke raspberry nya. ada gmbar tunelling ke raspberry pi akses port 80 melalui browser. tentu ini kalau raspinya ada internetnya. karena dirumah gk ada internet kabel. saya pakai thetering hp. jadi tunneling ini akan bekerja kalau saya aktifkan theteringnya. kalau mau aktif terus ya langganan internet. tapi mahal he he. karena itu next chapter akan melakukan sync data dari raspberry pi ke web hosting yang datanya otomatis tersyncronize saat raspi tersambung internet. user bisa lihat 24jam/7hari ke slave server itu.

 

Big Picture System

Big Picture System

1. Ngrok.com http tunneling

Tujuannya adalah seperti gambar diatas. karena raspi menggunakan IP LOCAL sehingga gk bisa diakses melalui internet maka diperlukan http tunelling agar bisa diakses langsung ke raspi secara real time. kita buat http tunelling pakai ngrok.com. intinya kita menembus firewall .dan mempublis port 80 kita ke public

Ngrok skema : sumber gambar ngrok.com

Ngrok skema : sumber gambar ngrok.com

buka https://ngrok.com/ buat akun dan silahkan login.

Download sesuai sistem yang digunakan. saya menggunakan raspberry pi jadi download yang linux ARM ya. ekstrak dan taruh di desktop raspberry pi

rubah permissionnya jadi 777 dengan klik kanan dan permission any one

rubah properties ngrok

rubah properties ngrok

2. buat file di desktop ngrokstart.sh

dan pastikan 777 juga

permission ngrokstart.sh

permission ngrokstart.sh

isinya sbb

ngrok start

ngrok start

argumennya yang lengkap bisa di baca di dokumentasinya. http 80 berart yang di exspose port 80 -subdomain saya pakai weatherlogger sebagai nama -region ap (asia pasific / mengarah ke server singapore yang dekat) -auttoken kode token diperoleh dari sini

auth token

auth token

lalu klik 2x ngrokstart.sh akan jalan seperti ini

tunnel yang jalan

tunnel yang jalan

dan web saya bisa diakses langsung deh di http://weatherlogger.ap.ngrok.io

hasil expose

hasil expose

dan bisa dilihat bahwa alamatnya udah jadi weatherlogger.ap.ngrok.io , kecepatannya tergantung kecepatan koneksi hp nya. dan hanya nyala kalau theteringnya nyala

 

3. edit base_url

ada yang perlu diedit sedikit agar link nya mengarah ke nama server yang benar ketika diakses localhost , same LAN, ataupun expose http tunelling. kalau tidak nanti link nya mengarah ke localhost pc client

edit config ci

edit config ci

edit sebagai berikut


$root = "http://".$_SERVER['HTTP_HOST'];
$root .= str_replace(basename($_SERVER['SCRIPT_NAME']),"",$_SERVER['SCRIPT_NAME']);
$config['base_url'] = "$root";

sehingga ketika diakses base url nya bisa ganti otomatis

akses localhost raspi

akses localhost raspi linknya jadi localhost

 

akses same LAN pakai laptop

akses same LAN pakai laptop linknya jadi alamat IP 192.168.3.199

 

hasil expose linknya

hasil expose link jadi weahterlogger.ap.ngrok.io

hasil expose link jadi weahterlogger.ap.ngrok.io

 

sekian dulu.

next chapter

8. sync data

 

Wassalamu’alaikum Wr. Wb.

Iklan

Grafik Last 24 Hours

Grafik Last 24 Hours

Big Picture System

Big Picture System

Assalamu’alaikum Wr. Wb.
Oke saya lanjutkan. remind lagi ini adalah seri berantai dari posting berikut ya

  1. https://tarecha.wordpress.com/2015/10/26/project-raspberry-pi/
  2. https://tarecha.wordpress.com/2017/06/05/project-weather-logger-part-1/
  3. https://tarecha.wordpress.com/2017/06/26/project-weather-logger-part-2-tambahan-sensor-tekanan-udara/
  4. https://tarecha.wordpress.com/2017/07/01/project-weather-logger-part-3-komunikasi-udp/
  5. https://tarecha.wordpress.com/2017/07/15/project-weather-logger-part-4-simpan-di-server-mysql/
  6. https://tarecha.wordpress.com/2017/07/24/project-weather-logger-part-5-view-data-dan-export/

oke selanjutnya ke tahap plot grafik, sebuah data dengan X waktu akan mudah dibaca dengan grafik garis. disini tujuannya melihat hubungan suhu, kelembapan, dan tekanan dalam waktu yang sama. dari pengamatan saya Suhu berbanding terbalik dengan kelembapan dan kelembapan berbanding lurus dengan tekanan.

1.  Memilih plugin untuk ploting grafik

disini ada beberapa pertimbangan yaitu render grafik di server lalu dikirim ke browser client dalam bentuk gambar atau kirim data ke client dan di render di client. opsi pertama plugin akan membuat gambar di server dan ini cukup berat jika dilakukan pada server raspberry pi, sehingga saya pilih opsi ke dua. client side plotting. jadi server mengirim data dan di render menggunakan javascrip di browser client. pilihan saya jatuh pada https://canvasjs.com/ karena mudah dan interaktif. bisa multi y axis dimana untuk yang presure karena rangengya beda jauh antara kelembapan dan suhu maka saya gunakan axis y secondari yang sebelah kanan. sedangkan axis y utama digunakan suhu dan kelembapan karena rangenya dekat. selain itu canvasjs bisa plot jadi satu dan bisa muncul data dengan x (waktu) yang sama seperti berikut. selain itu bisa di hidden legend nya. misal pengen lihat suhu saja tinggal klik saja legennya, bisa zoom, pan, dan save sebagai jpg.

tool tip pop up

tool tip pop up

save plot grafik jpg

save plot grafik jpg

ok silahkan download canvasjs tersebut dan jadikan 1 ya. kita mulai programnya

1. Header.php file header ini untuk menampung script sehingga di masing grafik cukup menginclude kan. disini saya memasukkan yang dibutuhan untuk plot grafik dan datetime picker untuk select berdasarkan waktu meski library yang saya gunakan untuk jquery versi 3 tidak kompatibel dengan date time pickernya. jadi gak ada gambar tangannya ketika kasi filter tapi masih fungsi. daripada bila versinya diturunkan plot grafiknya yang jadi gk bisa

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
		
		<title>Graphic Weather Logger</title>
		
		<!-- stylesheets -->
		<link href="/assets/bootstrap.min.css" rel="stylesheet">
		<link href="/assets/font-awesome/css/font-awesome.min.css" rel="stylesheet">
		<link href="/assets/style.css" rel="stylesheet">
		
		<link href="/assets/jquery.simple-dtpicker.css" rel="stylesheet" type="text/css" />
		
		<!-- scripts -->
		<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fjs%2Fjquery-3.1.0.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />	
		<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fjs%2Fbootstrap.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
		<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fjs%2Fcanvasjs.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
		<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fassets%2Fjs%2Fjquery.simple-dtpicker.js%22%20type%3D%22text%2Fjavascript%22%20%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
		
	
	

	</head>

2. grafik.php
disini saya select all data berdasarkan node defaultnya yaitu N1, misal node nya ada banyak tinggal kasi argumen grafik.php?node=N2 . dari awal saya rancang untuk multi node ya.

<?php 
include "header.php"; 
include "config.php"; 
if(isset($_GET['node']))
{ 
$idnode = $_GET['node']; 
$query = "select unix_timestamp(waktu)*1000 as x,dhttemp,dhthum,bmptemp,bmppress from masterdata where idnode='$idnode' order by waktu asc"; 
} 
else 
{ 
        $idnode = "N1"; 
        //untuk multi data dari beberapa node kita ambil default node nya N1 
        $query = "select unix_timestamp(waktu)*1000 as x,dhttemp,dhthum,bmptemp,bmppress from masterdata where idnode='$idnode' order by waktu asc"; } $data = mysqli_query($conn, $query); $dataPointsdhttemp = array(); $dataPointsdhthum = array(); $dataPointsbmptemp = array(); $dataPointsbmppress = array(); while ($row = mysqli_fetch_array($data, MYSQL_ASSOC)) { array_push($dataPointsdhttemp,array('x'=>$row['x'],'y'=>$row['dhttemp']));
	array_push($dataPointsdhthum, array('x'=>$row['x'],'y'=>$row['dhthum']));
	array_push($dataPointsbmptemp, array('x'=>$row['x'],'y'=>$row['bmptemp']));
	array_push($dataPointsbmppress, array('x'=>$row['x'],'y'=>$row['bmppress']));
}

//ambil tanggal start date dan end date
$firstupdateU = reset($dataPointsdhttemp)['x']/1000;
$lastupdateU =end($dataPointsdhttemp)['x']/1000;
$firstupdate = date("d F Y H:i:s",$firstupdateU);
$lastupdate = date("d F Y H:i:s",$lastupdateU);

//bikin strip garis pembagi per pukul 00:00
$firstupdatetengahmalam = date("d F Y  H:i:s",$firstupdateU);
$begin = (new DateTime( $firstupdatetengahmalam ))->setTime(0,0);
$end = new DateTime( $lastupdate );
$begin = $begin->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);

?>


<body style="padding-top: 3px;">



<div id="chartContainer"></div>






<div>

</div>





</body>


<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%24(function%20()%20%7B%0A%20%20%20%20var%20chart%20%3D%20new%20CanvasJS.Chart(%22chartContainer%22%2C%20%7B%0A%20%20%20%20%20%20%20%20theme%3A%20%22theme%22%2C%0A%20%20%20%20%20%20%20%20zoomEnabled%3A%20true%2C%0A%09%09exportEnabled%3A%20true%2C%0A%20%20%20%20%20%20%20%20animationEnabled%3A%20true%2C%0A%09%09axisY%3A%20%0A%09%09%7B%0A%09%09%09title%3A%20%22Suhu%20C%20dan%20Kelembapan%20%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontFamily%3A%20%22arial%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontSize%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20includeZero%3A%20false%2C%0A%09%09%09suffix%3A%20%22%20C%20%2F%20%25%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09axisY2%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3A%20%22Pressure%20pa%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontFamily%3A%20%22arial%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontSize%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20includeZero%3A%20false%2C%0A%09%09%09lineColor%3A%20%22%2386b402%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20suffix%3A%20%22%20pa%22%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20title%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3A%20%22Graphic%20Weather%20Logger%20of%20%3C%3Fphp%20echo%20%24idnode%3B%3F%3E%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09subtitles%3A%5B%0A%09%09%7B%0A%09%09%09text%3A%20%22by%20Mochamad%20Agung%20Tarecha%22%0A%09%09%0A%09%09%09%0A%09%09%7D%2C%0A%09%09%7B%0A%09%09%09%0A%09%09%09text%3A%20%22%3C%3Fphp%20echo%20%22Time%20range%20from%20%22.%24firstupdate%20.%22%20to%20%22.%20%24lastupdate%3B%3F%3E%22%0A%09%09%09%0A%09%09%7D%0A%09%09%5D%2C%0A%09%09%0A%09%09axisX%3A%0A%09%09%7B%20%20%20stripLines%3A%20%5B%0A%09%09%3C%3Fphp%20foreach(%24daterange%20as%20%24date)%20%7B%20echo%20%22%7B%22%3B%20echo%20%22value%3A%20%22.(string)%24date-%3Eformat(%22U%22).'000%2C'%3B%09%09%09%0A%09%09%09%09echo%20%22showOnTop%3A%20false%22%3B%20%20%20%20%20%20%20%20%20%20%20%0A%09%09%09%09echo%20%22%7D%2C%22%3B%0A%09%09%09%7D%0A%09%09%3F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%09%09%09valueFormatString%3A%20%22DD%20MMM%20YYYY%20HH%3Amm%22%0A%09%09%7D%2C%0A%09%09toolTip%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20shared%3A%20true%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20data%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%0A%09%09%09showInLegend%3A%20true%2C%09%09%0A%09%09%09name%3A%20%22Suhu%20C%20DHT%22%2C%09%09%09%09%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsdhttemp%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%0A%09%09%09showInLegend%3A%20true%2C%0A%09%09%09name%3A%20%22Humidity%20%25%20DHT%22%2C%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsdhthum%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%09%09%09%0A%09%09%09showInLegend%3A%20true%2C%09%09%09%0A%09%09%09name%3A%20%22Suhu%20C%20BMP%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsbmptemp%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20axisYType%3A%20%22secondary%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%09%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3A%20%22Pressure%20pa%22%2C%0A%09%09%09showInLegend%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsbmppress%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%0A%09%09%0A%20%20%20%20%20%20%20%20%5D%2C%0A%09%09legend%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cursor%3A%20%22pointer%22%2C%0A%09%09%09%09horizontalAlign%3A%20%22center%22%2C%0A%09%09%09%09verticalAlign%3A%20%22bottom%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20itemclick%3A%20function%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20(e.dataSeries.visible)%20%3D%3D%3D%20%22undefined%22%20%7C%7C%20e.dataSeries.visible)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.dataSeries.visible%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.dataSeries.visible%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20chart.render()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D)%3B%0A%20%20%20%20chart.render()%3B%0A%7D)%3B%0A%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
</html>

hasilnya sebagai berikut

Grafik all time

Grafik all time

 

3. grafikwaktu.php

sama saja bedanya kita bisa milih node yang mana dan range waktu tertentu. script utamanya sama tinggal ada inputan formnya

<?php 
include "header.php"; 
include "config.php"; 
$startdate = ""; 
$enddate = ""; 
$idnode = "N1"; 
//defalut value 
if(isset($_POST['startdate'])&&isset($_POST['enddate'])&&isset($_POST['idnode'])) 
{       $startdate = $_POST['startdate']; 
        $enddate = $_POST['enddate']; 
        $idnode = $_POST['idnode']; 
        if(($startdate!="")&&($enddate!=""))
         { 
        $query = "select unix_timestamp(waktu)*1000 as x,dhttemp,dhthum,bmptemp,bmppress from masterdata where idnode='$idnode' and waktu between '$startdate' and '$enddate' order by waktu asc"; 
       } else {
          $query = "select unix_timestamp(waktu)*1000 as x,dhttemp,dhthum,bmptemp,bmppress from masterdata where idnode='$idnode' order by waktu asc"; }
 } else { $query = "select unix_timestamp(waktu)*1000 as x,dhttemp,dhthum,bmptemp,bmppress from masterdata where idnode='$idnode' order by waktu asc"; }
 $data = mysqli_query($conn, $query); $dataPointsdhttemp = array(); $dataPointsdhthum = array(); $dataPointsbmptemp = array(); $dataPointsbmppress = array();
 while ($row = mysqli_fetch_array($data, MYSQL_ASSOC)) { array_push($dataPointsdhttemp,array('x'=>$row['x'],'y'=>$row['dhttemp']));
	array_push($dataPointsdhthum, array('x'=>$row['x'],'y'=>$row['dhthum']));
	array_push($dataPointsbmptemp, array('x'=>$row['x'],'y'=>$row['bmptemp']));
	array_push($dataPointsbmppress, array('x'=>$row['x'],'y'=>$row['bmppress']));
}

//ambil tanggal start date dan end date
$firstupdateU = reset($dataPointsdhttemp)['x']/1000;
$lastupdateU =end($dataPointsdhttemp)['x']/1000;
$firstupdate = date("d F Y H:i:s",$firstupdateU);
$lastupdate = date("d F Y H:i:s",$lastupdateU);

//bikin strip garis pembagi per pukul 00:00
$firstupdatetengahmalam = date("d F Y  H:i:s",$firstupdateU);
$begin = (new DateTime( $firstupdatetengahmalam ))->setTime(0,0);
$end = new DateTime( $lastupdate );
$begin = $begin->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);

?>

<body style="padding-top: 3px;">


<form action="grafikwaktu.php" method="post">


<div align="center">
    
	Node ID : 
	<select name="idnode">
<option value="N1" <?php if ($idnode=='N1') echo "selected"?>>N1</option>
<option value="N2" <?php if ($idnode=='N2') echo "selected"?>>N2</option>
<option value="N3" <?php if ($idnode=='N3') echo "selected"?>>N3</option>
<option value="N4" <?php if ($idnode=='N4') echo "selected"?>>N4</option>
<option value="N5" <?php if ($idnode=='N5') echo "selected"?>>N5</option>
<option value="N6" <?php if ($idnode=='N6') echo "selected"?>>N6</option>
<option value="N7" <?php if ($idnode=='N7') echo "selected"?>>N7</option>
	</select>
	
	
	Range time  : 
	<input type="text" name="startdate" id="startdate" value="<?php echo $startdate;?>"> - 
	<input type="text" name="enddate" id="enddate" value="<?php echo $enddate;?>">
	<input type="submit" name="submit" value="Filter">
	<button type="button" onclick="ClearFields();">Clear Filter</button>
	
	
</div>



</form>





<div id="chartContainer"></div>


</body>

	<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%09%09%24(function()%7B%0A%09%09%09%24('%23startdate').appendDtpicker(%0A%09%09%09%7B%0A%09%09%09%09%09%22autodateOnStart%22%3A%20false%0A%09%09%09%7D)%3B%0A%09%09%7D)%3B%0A%09%09%24(function()%7B%0A%09%09%09%24('%23enddate').appendDtpicker(%0A%09%09%09%7B%0A%09%09%09%09%22autodateOnStart%22%3A%20false%0A%09%09%09%7D)%3B%0A%09%09%7D)%3B%0A%09%09%0A%09%09function%20ClearFields()%20%0A%09%09%7B%0A%0A%09%09%09document.getElementById(%22startdate%22).value%20%3D%20%22%22%3B%0A%09%09%09document.getElementById(%22enddate%22).value%20%3D%20%22%22%3B%0A%09%09%7D%0A%09%09%0A%09%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%0A%0A%24(function%20()%20%7B%0A%20%20%20%20var%20chart%20%3D%20new%20CanvasJS.Chart(%22chartContainer%22%2C%20%7B%0A%20%20%20%20%20%20%20%20theme%3A%20%22theme%22%2C%0A%20%20%20%20%20%20%20%20zoomEnabled%3A%20true%2C%0A%09%09exportEnabled%3A%20true%2C%0A%20%20%20%20%20%20%20%20animationEnabled%3A%20true%2C%0A%09%09axisY%3A%20%0A%09%09%7B%0A%09%09%09title%3A%20%22Suhu%20C%20dan%20Kelembapan%20%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontFamily%3A%20%22arial%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontSize%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20includeZero%3A%20false%2C%0A%09%09%09suffix%3A%20%22%20C%20%2F%20%25%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09axisY2%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3A%20%22Pressure%20pa%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontFamily%3A%20%22arial%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontSize%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20includeZero%3A%20false%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20suffix%3A%20%22%20pa%22%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20title%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3A%20%22Graphic%20Weather%20Logger%20of%20%3C%3Fphp%20echo%20%24idnode%3B%3F%3E%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09subtitles%3A%5B%0A%09%09%7B%0A%09%09%09text%3A%20%22by%20Mochamad%20Agung%20Tarecha%22%0A%09%09%0A%09%09%09%0A%09%09%7D%2C%0A%09%09%7B%0A%09%09%09%0A%09%09%09text%3A%20%22%3C%3Fphp%20echo%20%22Time%20range%20from%20%22.%24firstupdate%20.%22%20to%20%22.%20%24lastupdate%3B%3F%3E%22%0A%09%09%09%0A%09%09%7D%0A%09%09%5D%2C%0A%09%09%0A%09%09axisX%3A%0A%09%09%7B%20%20%20stripLines%3A%20%5B%0A%09%09%3C%3Fphp%20foreach(%24daterange%20as%20%24date)%20%7B%20echo%20%22%7B%22%3B%20echo%20%22value%3A%20%22.(string)%24date-%3Eformat(%22U%22).'000%2C'%3B%09%09%09%0A%09%09%09%09echo%20%22showOnTop%3A%20false%22%3B%20%20%20%20%20%20%20%20%20%20%20%0A%09%09%09%09echo%20%22%7D%2C%22%3B%0A%09%09%09%7D%0A%09%09%3F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%09%09%09valueFormatString%3A%20%22DD%20MMM%20YYYY%20HH%3Amm%22%0A%09%09%7D%2C%0A%09%09toolTip%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20shared%3A%20true%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20data%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%0A%09%09%09showInLegend%3A%20true%2C%09%09%0A%09%09%09name%3A%20%22Suhu%20C%20DHT%22%2C%09%09%09%09%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsdhttemp%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%0A%09%09%09showInLegend%3A%20true%2C%0A%09%09%09name%3A%20%22Humidity%20%25%20DHT%22%2C%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsdhthum%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%09%09%09%0A%09%09%09showInLegend%3A%20true%2C%09%09%09%0A%09%09%09name%3A%20%22Suhu%20C%20BMP%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsbmptemp%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20axisYType%3A%20%22secondary%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%09%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3A%20%22Pressure%20pa%22%2C%0A%09%09%09showInLegend%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsbmppress%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%0A%09%09%0A%20%20%20%20%20%20%20%20%5D%2C%0A%09%09legend%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cursor%3A%20%22pointer%22%2C%0A%09%09%09%09horizontalAlign%3A%20%22center%22%2C%0A%09%09%09%09verticalAlign%3A%20%22bottom%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20itemclick%3A%20function%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20(e.dataSeries.visible)%20%3D%3D%3D%20%22undefined%22%20%7C%7C%20e.dataSeries.visible)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.dataSeries.visible%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.dataSeries.visible%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20chart.render()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D)%3B%0A%20%20%20%20chart.render()%3B%0A%7D)%3B%0A%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
</html>



hasilnya sebagai berikut
ini yang kata saya krusornya gk muncul gambar tangan, tapi masih bisa digunakan

grafik seleksi waktu

grafik seleksi waktu

 

4. grafiklast24hour.php

sama seperti yang pertama bedanya langsung select 24 jam terakhir mulai pukul 00 tengah malam

<?php include "header.php"; include "config.php"; if(isset($_GET['node'])) { $idnode = $_GET['node']; $query = "select unix_timestamp(waktu)*1000 as x,dhttemp,dhthum,bmptemp,bmppress,waktu from masterdata where idnode='$idnode' and waktu >= curdate() order by waktu asc";
	
}
else
{
	$idnode = "N1";
	//untuk multi data dari beberapa node kita ambil default node nya N1
	$query = "select unix_timestamp(waktu)*1000  as x,dhttemp,dhthum,bmptemp,bmppress,waktu from masterdata where idnode='$idnode' and waktu >= curdate() order by waktu asc";
}


$data = mysqli_query($conn, $query);
$dataPointsdhttemp = array();
$dataPointsdhthum = array();
$dataPointsbmptemp = array();
$dataPointsbmppress = array();



while ($row = mysqli_fetch_array($data, MYSQL_ASSOC)) 
{
	array_push($dataPointsdhttemp,array('x'=>$row['x'],'y'=>$row['dhttemp']));
	array_push($dataPointsdhthum, array('x'=>$row['x'],'y'=>$row['dhthum']));
	array_push($dataPointsbmptemp, array('x'=>$row['x'],'y'=>$row['bmptemp']));
	array_push($dataPointsbmppress, array('x'=>$row['x'],'y'=>$row['bmppress']));
}

//ambil tanggal start date dan end date
$firstupdateU = reset($dataPointsdhttemp)['x']/1000;
$lastupdateU =end($dataPointsdhttemp)['x']/1000;
$firstupdate = date("d F Y H:i:s",$firstupdateU);
$lastupdate = date("d F Y H:i:s",$lastupdateU);

//bikin strip garis pembagi per pukul 00:00
$firstupdatetengahmalam = date("d F Y  H:i:s",$firstupdateU);
$begin = (new DateTime( $firstupdatetengahmalam ))->setTime(0,0);
$end = new DateTime( $lastupdate );
$begin = $begin->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);

?>

<body style="padding-top: 3px;">


<div id="chartContainer"></div>


<div>

</div>



</body>


<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%24(function%20()%20%7B%0A%20%20%20%20var%20chart%20%3D%20new%20CanvasJS.Chart(%22chartContainer%22%2C%20%7B%0A%20%20%20%20%20%20%20%20theme%3A%20%22theme%22%2C%0A%20%20%20%20%20%20%20%20zoomEnabled%3A%20true%2C%0A%09%09exportEnabled%3A%20true%2C%0A%20%20%20%20%20%20%20%20animationEnabled%3A%20true%2C%0A%09%09axisY%3A%20%0A%09%09%7B%0A%09%09%09title%3A%20%22Suhu%20C%20dan%20Kelembapan%20%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontFamily%3A%20%22arial%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontSize%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20includeZero%3A%20false%2C%0A%09%09%09suffix%3A%20%22%20C%20%2F%20%25%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09axisY2%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3A%20%22Pressure%20pa%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontFamily%3A%20%22arial%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20titleFontSize%3A%2012%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20includeZero%3A%20false%2C%0A%09%09%09lineColor%3A%20%22%2386b402%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20suffix%3A%20%22%20pa%22%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20title%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3A%20%22Graphic%20Weather%20Logger%20of%20%3C%3Fphp%20echo%20%24idnode%3B%3F%3E%22%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09subtitles%3A%5B%0A%09%09%7B%0A%09%09%09text%3A%20%22by%20Mochamad%20Agung%20Tarecha%22%0A%09%09%0A%09%09%09%0A%09%09%7D%2C%0A%09%09%7B%0A%09%09%09%0A%09%09%09text%3A%20%22%3C%3Fphp%20echo%20%22Time%20range%20from%20%22.%24firstupdate%20.%22%20to%20%22.%20%24lastupdate%3B%3F%3E%22%0A%09%09%09%0A%09%09%7D%0A%09%09%5D%2C%0A%09%09%0A%09%09axisX%3A%0A%09%09%7B%20%20%20stripLines%3A%20%5B%0A%09%09%3C%3Fphp%20foreach(%24daterange%20as%20%24date)%20%7B%20echo%20%22%7B%22%3B%20echo%20%22value%3A%20%22.(string)%24date-%3Eformat(%22U%22).'000%2C'%3B%09%09%09%0A%09%09%09%09echo%20%22showOnTop%3A%20false%22%3B%20%20%20%20%20%20%20%20%20%20%20%0A%09%09%09%09echo%20%22%7D%2C%22%3B%0A%09%09%09%7D%0A%09%09%3F%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%09%09%09valueFormatString%3A%20%22DD%20MMM%20YYYY%20HH%3Amm%22%0A%09%09%7D%2C%0A%09%09toolTip%3A%20%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20shared%3A%20true%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20data%3A%20%5B%0A%20%20%20%20%20%20%20%20%7B%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%0A%09%09%09showInLegend%3A%20true%2C%09%09%0A%09%09%09name%3A%20%22Suhu%20C%20DHT%22%2C%09%09%09%09%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsdhttemp%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%0A%09%09%09showInLegend%3A%20true%2C%0A%09%09%09name%3A%20%22Humidity%20%25%20DHT%22%2C%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsdhthum%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%09%09%09%0A%09%09%09showInLegend%3A%20true%2C%09%09%09%0A%09%09%09name%3A%20%22Suhu%20C%20BMP%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsbmptemp%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%2C%0A%09%09%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20type%3A%20%22line%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20axisYType%3A%20%22secondary%22%2C%0A%09%09%09xValueType%3A%20%22dateTime%22%2C%0A%09%09%09xValueFormatString%3A%22DD%20MMM%20YYYY%20HH%3Amm%3Ass%22%2C%09%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3A%20%22Pressure%20pa%22%2C%0A%09%09%09showInLegend%3A%20true%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dataPoints%3A%20%3C%3Fphp%20echo%20json_encode(%24dataPointsbmppress%2C%20JSON_NUMERIC_CHECK)%3B%20%3F%3E%0A%20%20%20%20%20%20%20%20%7D%0A%09%09%0A%20%20%20%20%20%20%20%20%5D%2C%0A%09%09legend%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cursor%3A%20%22pointer%22%2C%0A%09%09%09%09horizontalAlign%3A%20%22center%22%2C%0A%09%09%09%09verticalAlign%3A%20%22bottom%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20itemclick%3A%20function%20(e)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(typeof%20(e.dataSeries.visible)%20%3D%3D%3D%20%22undefined%22%20%7C%7C%20e.dataSeries.visible)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.dataSeries.visible%20%3D%20false%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20e.dataSeries.visible%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20chart.render()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D)%3B%0A%20%20%20%20chart.render()%3B%0A%7D)%3B%0A%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
</html>

grafik last 24 hour

grafik last 24 hour

 

oke sekiat dahulu chapter berikut.

next chapter

7. Ngrok http tunneling

8. Sync data dengan server slave.

9. saya belum punya ide soal ini

 

terima kasih semoga bermanfaat.

Wassalamu’alaikum Wr. Wb.


 

Assalamu’alaikum Wr. Wb.

Oke saya lanjutkan. remind lagi ini adalah seri berantai dari posting berikut ya

  1. https://tarecha.wordpress.com/2015/10/26/project-raspberry-pi/
  2. https://tarecha.wordpress.com/2017/06/05/project-weather-logger-part-1/
  3. https://tarecha.wordpress.com/2017/06/26/project-weather-logger-part-2-tambahan-sensor-tekanan-udara/
  4. https://tarecha.wordpress.com/2017/07/01/project-weather-logger-part-3-komunikasi-udp/
  5. https://tarecha.wordpress.com/2017/07/15/project-weather-logger-part-4-simpan-di-server-mysql/

well sebentar lagi akan semakin rumit,

setelah kita simpan di server lalu bagaimana kah cara melihat datanya ? mengekspornya ke csv kalau perlu. oke ini akan agak rumit,

kita akan gunakan Code Igniter dan Grocery CRUD untuk melihat dalam bentuk tabel, next chapter kita akan gunakan grafik. kira-kira seperti ini hasilnya

View Data Tabel dan Export

View Data Tabel dan Export

1. Download Code Igniner 3 di link berikut https://codeigniter.com/download   Jangan yang versi 4 karena belum stabil

2. Download Grocery CRUD di link berikut https://www.grocerycrud.com/

Fungsi dari grocery crud adalah kita bisa generate CRUD (Create Read Update Delete) dan View dari sebuah tabel tanpa hardcoding. tinggal panggil fungsi2 nya nanti jadi code generator. cukup mudah sih. sesunggunya bisa pakai fungsi CRUD ke data namun saya matikan karena pengen datanya pure dari node sensor.

oke ekstrak Code Igniter ke folder /var/www/html kalau pakai raspi, karena saya pakai windows untuk tutorialnya maka agak beda ya.

lalu ekstrak grocery crud ke root folder yang sama. grocery punya struktur tabel yang sama. tinggal copy paste dan overwrite saja.

exstrak CI

exstrak CI

3. setting database

cari file di folder \appication\config\database.php

untuk key itu tambahan dari saya ya. baca posting sebelumnya.

Setting Database

Setting Database

4. Buat controller application\controllers\Masterdata.php


<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Masterdata extends CI_Controller { public function __construct() { parent::__construct(); $this->load->database();
		$this->load->helper('url');

		$this->load->library('grocery_CRUD');
	}

	//ini untuk panggil viewnya
	public function _example_output($output = null)
	{
		$this->load->view('masterdata.php',(array)$output);
	}

	public function offices()
	{
		$output = $this->grocery_crud->render();

		$this->_example_output($output);
	}

	public function index()
	
	{
		
		$this->_example_output((object)array('output' => '' , 'js_files' => array() , 'css_files' => array()));
		
	}
	
	public function datamanagement()
	{
		$crud = new grocery_CRUD();
 
 
		$crud->set_table('masterdata');
		$crud->set_subject('Master Data Log');
		$crud->columns('iddata','waktu','idnode','dhthum','dhttemp','bmptemp','bmppress','sync1','sync2');
		$crud->display_as('iddata','ID Data');
		$crud->display_as('idnode','Node Name');
		$crud->display_as('waktu','Waktu');
		$crud->display_as('dhthum','Humidity DHT Sensor (%)');
		$crud->display_as('dhttemp','Temperatur DHT Sensor (oC)');
		$crud->display_as('bmptemp','Temperatur BMP Sensor(oC)');
		$crud->display_as('bmppress','Presure BMP Sensor (pa)');
		$crud->display_as('sync1','Sync Slave Server 1');
		$crud->display_as('sync2','Sync Slave Server 2');
		$crud->callback_column('sync1',array($this,'statusSync'));
		$crud->callback_column('sync2',array($this,'statusSync'));
		$crud->order_by('waktu','desc');
		//karena untuk display data saja makan add, edit, delete dihilangkan
		//data pure dari sensor
		$crud->unset_add();
		$crud->unset_edit();
		$crud->unset_delete();
		
		
		
		
		$output = $crud->render();
 
		$this->_example_output($output); 
	}
	
	public function statusSync($value, $row)
	{
		
		if ($value == 1)
			return "<img src=".site_url('../image/check.png')." height='15' width='15' > Done</img> ";
		else
			return "<img src=".site_url('../image/notcheck.png')." height='15' width='15' > Not Yet</img> ";
		
	}

	

}


5. Buat View application\views\masterdata.php

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php foreach($css_files as $file): ?>
	<link type="text/css" rel="stylesheet" href="<?php echo $file; ?>" />
<?php endforeach; ?>
<?php foreach($js_files as $file): ?>
	<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%3C%3Fphp%20echo%20%24file%3B%20%3F%3E%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="&lt;script&gt;" title="&lt;script&gt;" />
<?php endforeach; ?>
</head>
<body>
	<center> 
<H2>Halaman Management Data</H2>

		 
<H3>Weather Logger by Mochamad Agung Tarecha</H3>

</center>
	
	
	 <a href='<?php echo site_url('masterdata/DataManagement')?>'>Log Data Management</a> |
	  
	 <a href='<?php echo site_url('../grafik.php')?>' target="_blank">Grafik All</a> | 
         <a href='<?php echo site_url('../grafikwaktu.php')?>' target="_blank">Grafik Filter Waktu</a> | 
	 <a href='<?php echo site_url('../grafiklast24hour.php')?>' target="_blank">Grafik last 24 Hour</a> 
    
<div>
		
		<?php echo $output; ?>
    </div>

</body>
</html>

6. Setting default controller ke controller masterdata

Default controller master data

Default controller master data

7. akses root folder menggunakan browser lalu klik log data management akan muncul tabel. untuk export tinggal klik export saja

Akses data

Akses data

 

oke sekian dahulu. next selanjutnya adalah tampilan grafik

Wassalamu’alaik


Assalamu’alaikum Wr. Wb.

Oke saya lanjutkan.  remind lagi ini adalah seri berantai dari posting berikut ya

  1. https://tarecha.wordpress.com/2015/10/26/project-raspberry-pi/
  2. https://tarecha.wordpress.com/2017/06/05/project-weather-logger-part-1/
  3. https://tarecha.wordpress.com/2017/06/26/project-weather-logger-part-2-tambahan-sensor-tekanan-udara/
  4. https://tarecha.wordpress.com/2017/07/01/project-weather-logger-part-3-komunikasi-udp/

Ok semakin kesini semakin sulit dan rumit, sampai saya sendiri bingung bagaimana menuliskannya agar mudah dipahami. saya akan bikin sekma gambar big picture nya ya. biar jelas “maksudnya apa”.

Big Picture System

Big Picture System

Flow Sync Data
Flow syc data

oh ya seperti yang saya infokan sebelumnya ada tambahan komponen. sebenarnya arus nya cukup. hanya saja saya curiga dht nya gk stabil jadi saya kasi regulator tambahan 3.3v. lagi pula ams117 nya itu sisa raspi yang dulu.

pin vu ini 5v dari usb kita sambungkan ke regulagor. ada kapasitor elco dan keramik agar dayanya stabil

schematic

schematic

 

Bagaimana save di server mysql ?

saya menggunakan file php untuk savenya , pyhon melempar data ke file insertdata.php lalu php yang save datanya. mengapa demikian ? coba anda cari web hosting yang port MySQL 3306 nya dibuka, apalagi saya berencana di hosting gratisan. tentu yang dibuka port 80 nya saja untuk akses web nya. jadi kira2 sekemanya seperti ini

skema insert data

diagram simpan data

diagram simpan data

kira2 seperti ini

 

dan nantinya kita memonitor melalui grafik hubungan suhu, humiditym dan pressure di waktu yang sama, nanti ya

grafik gabung semua

grafik gabung semua

 

oke kita mulai langkah2 nya. mungkin ini akan overlap ya karena beberapa menggunakan coding untuk next capter.

Pre oh ya karena saya pakai Raspberry pi maka perlu install phpmyadmin, mysql, dan apache disini http://lastbug.net/blog/2016/01/23/install-apache-php-and-mysql-and-phpmyadmin-on-raspberry-pi/

atau mudahnya jalankan perintah ini arti -y adalah langsung install gk perlu ketik Yes waktu konfirmasi install
 
sudo apt-get update
sudo apt-get upgrade
sudo apt-get -y install apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-mysql mysql-server mysql-client phpmyadmin
 
  1. Membuat database
    Buat user dan database masterlogger dan tabel masterdata. yang perlu dicatat iddata auto_increment dan primary key di master logger untuk generate id datanya dimana nilai auto increment ini nanti diambil untuk di save pada file csv ( comma sparated value ). sedangkan nanti di database slave iddata tidak perlu jadi primary key dan autoincrement karena nilai id nanti diambil dari master logger sehingga sama persis dan bisa saja di slave database menampung iddata yang sama karena slave logger bisa menampung lebih dari 1 node raspberry pi. panjang lah ceritanya. agak bingung ya ?

    struktur tabel masterdata

    struktur tabel masterdata

  2. File PHP untuk insert data
    oke pastikan anda sudah familiah dengan xampp ya. kita langsung saja bikin filenya
    pertama adalah config.php file ini menyimpan settingan  database
isi dari config.php
</pre>
<?php
//define ini untuk mengakali code ignitner yang gk bisa akses ke filenya langsung karena ambil settingan dari sana
define('BASEPATH', "/");
define('ENVIRONMENT', "production");

//include $_SERVER['DOCUMENT_ROOT']."/application/config/database.php";
include "/application/config/database.php";
$key = $db['default']['key'];

//===============================================================================
error_reporting(E_ERROR | E_PARSE);
$conn =mysqli_connect($db['default']['hostname'],$db['default']['username'],$db['default']['password']);

if (!$conn)
{

die('i#Server tidak konek#Periksa link');
}

$selected_database = mysqli_select_db($conn, $db['default']['database']);
if (!$selected_database)
{
die('i#Database tidak ditemukan#Periksa database');
}

?>
<pre>

lalu berikut file insertdata.php
variabel $k adalah key semacam password yang dicocokkan setiap posting data dari program python. isinya saya simpan di database .php milik code igniter

</pre>
<?php
include "config.php";

if(isset($_POST['k']))
{
if( $_POST['k'] ==$key)
//jika variabel k sama dengan key makan proses input.
//ini untuk autentikasi meski sebenarnya metode ini sangat mudah dibobol pakai wireshark untuk lihat datanya
{
$iddata =$_POST['iddata']; //master server (lokal raspberry pipakai autoincrement jadi gak perlu sebenarnya , hanya buat slave servernya saja
$idnode =$_POST['idnode'];
$dhthum =$_POST['dhthum'];
$dhttemp =$_POST['dhttemp'];
$bmptemp =$_POST['bmptemp'];
$bmppress =$_POST['bmppress'];
$waktu =$_POST['waktu'];
$sync1 =$_POST['sync1'];
$sync2 =$_POST['sync2'];

if ($iddata=="auto")
{
$valuecoloumn = 'idnode,dhthum,dhttemp,bmptemp,bmppress,waktu,sync1,sync2';
$valuedata = '"'.$idnode.'","'.$dhthum.'","'.$dhttemp.'","'.$bmptemp.'","'.$bmppress.'","'.$waktu.'","'.$sync1.'","'.$sync2.'"';
}
else
{
$valuecoloumn = 'iddata,dhthum,dhttemp,bmptemp,bmppress,waktu,sync1,sync2';
$valuedata = '"'.$iddata.'","'.$idnode.'","'.$dhthum.'","'.$dhttemp.'","'.$bmptemp.'","'.$bmppress.'","'.$waktu.'","'.$sync1.'","'.$sync2.'"';
}

$sql="insert into masterdata($valuecoloumn) values($valuedata);";
//echo $sql;
$hasil = mysqli_query($conn,$sql);
//echo $hasil;

if (!$hasil)
{
echo "i#Gagal Insert#".$sql;
}
else
{
//melempar nilai last id untuk di save csv. karena ini jalan di server lokal maka kemungkinan diskoneknya kecil
//belum coba ke slave server yang tidak ada auto incrementnya
echo 'i#Berhasil Insert#'.mysqli_insert_id($conn).'#'.$valuedata;
}

}
else
{
echo "i#Key Salah#Periksa Key";
}
}
else
{
echo "i#Tidak post#Periksa Post";
}
?>

akses insert data.php

akses insert data.php

karena ini bukan di raspberry pi maka saya tambahkan child folder html  di xampp windows.

3. insertdata python

berikut edit coding pythonnya


import socket
import sys
import datetime
import time
import urllib2
import urllib

UDP_IP = "192.168.3.192"
UDP_PORT = 80
MESSAGE = "d"
urlserver = "http://localhost/html/insertdata.php"
key = "098dfsiuohjsdf98709sdf8709"
namafilecsv = "rawdata5.csv"

print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(10) #dalam 10 detik setelah kirim tunggu data, kalau lewat bypass
data ={}
errordatasensor ='belum pernah NAN'
i=0
lastdhthum = -99999
lastdhttemp = -99999
lastbmptemp = -99999
lastbmppress = -99999
d={}
d[0] = 'N1,32,324,23,23'
while True:

try :
print '-------------------------------------------------------------------------------------'
#Set the whole string
# sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

# receive data from client (data, addr)
#d = sock.recvfrom(1024)
#pemisahan data dengan karakter "," nanti buat save di mysql

reply = d[0].split(",")


curmin = datetime.datetime.now().time().minute
cursec = datetime.datetime.now().time().second
#curhour = datetime.datetime.now().time().hour
curtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print 'Nodesensor reply : ' + str(reply) +' at '+curtime

#kadang dht22 gagal baca dan menghasilkan nan (not a number)
#jadi kalau gagal gunakan data dari pembacaan sebelumnya
#untuk amannya kalau data bukan angka maka gunakan data sebelumnya
#termasuk data dari sensor bmp280

if (i==3):
reply[1] = 'nan'
reply[2] = 'nan'
reply[3] = 'nan'
reply[4] = 'nan'


i+=1

if reply[1].replace('.','').isdigit():#dihilangkan koma dan titik lalu dicek apakah nomor saja
lastdhthum=reply[1]
#ini adalah kondisi normal dimana data dibaca benar.
else:
reply[1]=lastdhthum
print 'Ada data NaN di dhthum gunakan last data '+str(lastdhthum)
errordatasensor = 'pernah NAN dhthum di waktu '+curtime

if reply[2].replace('.','').isdigit():
lastdhttemp=reply[2]
#ini adalah kondisi normal dimana data dibaca benar.

else:
reply[2]=lastdhttemp
print 'Ada data NaN di dhttemp gunakan last data '+str(lastdhttemp)
errordatasensor = 'pernah NAN dhttemp di waktu '+curtime

if reply[3].replace('.','').isdigit():
lastbmptemp=reply[3]
#ini adalah kondisi normal dimana data dibaca benar.
else:
reply[3]=lastbmptemp
print 'Ada data NaN di bmptemp gunakan last data '+str(lastbmptemp)
errordatasensor = 'pernah NAN bmptemp di waktu '+curtime

if reply[4].replace('.','').isdigit():
lastbmppress=reply[4]
#ini adalah kondisi normal dimana data dibaca benar.
else:
reply[4]=lastbmppress
print 'Ada data NaN di bmppress gunakan last data '+str(lastbmppress)
errordatasensor = 'pernah NAN bmppress di waktu '+curtime

#cek isi apakah data terakhir benar
#print 'lastdhthum '+lastdhthum
#print 'lastdhttemp '+lastdhttemp
#print 'lastbmptemp '+lastbmptemp
#print 'lastbmppress '+lastbmppress
print errordatasensor


#tiap 10 menit simpan di file csv, karena dalam 10 menit lama
#untuk mencegah save berulang di menit ke 10 dilihat detiknya
#selama kurang dari 5 maka di save karena ada sleep 5 detiknya

#if (curmin % 10 ==0)and (cursec < 6) :
if 1:
#simpan menggunakan php

data['k']= key
data['iddata'] = 'auto'
data['idnode'] = reply[0]
data['dhthum'] = reply[1]
data['dhttemp'] = reply[2]
data['bmptemp'] = reply[3]
data['bmppress'] = reply[4]
data['waktu'] = curtime
data['sync1'] = 'false'
data['sync2'] = 'false'
dataformaturl = urllib.urlencode(data)

requesttoserver = urllib2.urlopen(urlserver,dataformaturl)
infosavephp = requesttoserver.read().split("#")
#print infosavephp
#print '=========================================================================='
if(infosavephp[0]=='i')and(infosavephp[1]=='Berhasil Insert'):
print 'Informasi Save ke Server : ID '+infosavephp[2]+' '+infosavephp[3]

if(infosavephp[0]=='i')and(infosavephp[1]!='Berhasil Insert'):#selain berhasil
print 'Gagal Insert Server : '+infosavephp[2]
#karena gagal insert maka isi infosavephp[2] adalah sql nya untuk di cek
#karena tetap pakai dimana infosavephp[2] harusnya berisi id auto increment maka diganti
#untuk di save csv
infosavephp[2] = 'No ID'

with open(namafilecsv,'a') as file:
file.writelines(infosavephp[2]+','+curtime+','+d[0]+'\n')
#urutan csv nya iddataterakhir disave, waktu, data d (isi sensor)
print 'data disimpan di csv ' +infosavephp[2]+' '+curtime+' '+str(reply)
# print '=========================================================================='

&nbsp;

except urllib2.HTTPError:
print 'Tidak konek server'
except urllib2.URLError:
print 'URL Salah'

except socket.error:
print 'Tidak konek node'
#tidak pernah exit karena kalau tidak konek dilewati dan ngulang
#5 detik kemudian
#sys.exit()
except Exception as e:
print 'Error Message '+ str(e)
print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)
print "General Error Unexpected error:", sys.exc_info()[0]
time.sleep(5)

kalau diekseskusi seperi ini . saat habis insert akan mengembalikan nilai auto increment. yang nanti nya id tersebut akan disave di csv sebagai kolom iddata jadi data nya sama persis kalau dicek berdasarkan iddatanya oh ya ini karena tidak di rumah maka untuk nilai sensornya saya kasi nilai tetap

data csv

data csv

oke deh. done.
next dilanjut ya
wassalamu’alaikum


Grafik Suhu dan Kelembapan

Grafik Suhu dan Kelembapan

Grafik Tekanan Udara

Grafik Tekanan Udara

Assalamu’alaikum Wr. Wb.

Oke saya lanjutkan.  remind lagi ini adalah seri berantai dari posting berikut ya

  1. https://tarecha.wordpress.com/2015/10/26/project-raspberry-pi/
  2. https://tarecha.wordpress.com/2017/06/05/project-weather-logger-part-1/
  3. https://tarecha.wordpress.com/2017/06/26/project-weather-logger-part-2-tambahan-sensor-tekanan-udara/

 

Sebenarnya masih mau saya edit lagi skema rangkaiannya. tapi nanti saja. saya posting dulu. oh ya ini saya tambahkan resistor 10K untuk sensor DHT sebagai pull up resistor dan 4,7K di sensor BMP 280 sebagai pull up resistor. setelah baca-baca ternyata komunikasi I2C itu memang memerlukan pull up resistor. sebelumnya sih normal-normal saja bacanya cman kadang error. terutama di sensor DHT yang pembacaan suhu dan kelembapannya 1 dan 2 point saja. ini kejadikan ketika sumber powernya dari cas hp. kalau laptop jarang sekali ada masalah. saya yakin ini karena gk kuat catu dayanya atau gk stabil . nanti saja saya perbaiki. dan juga mau saya tambahkan buzzer sebagai penanda kalau error baca. next posting saja.

oke yang pertama adalah

  1. Coding komunikasi UDP pada NodeMCU, sebelumnya saya coba pakai TCP tapi kadang2 ribet gk konek. berikut codingnya. intinya antara update data sensor saya gak pakai delay karena nanti kalau request datang ter delay nanti tidak konek. mau pakai blink without delay pakai millis() seperti di posting berikut https://tarecha.wordpress.com/2014/01/26/touchless-rotary-encoder/ s   malah error serialnya berhenti. tapi komunikasi UDP nya masih jalan. kemungkinan karena millis() dipakai oleh library sensor, tapi saya coba blink without delay yang pakai millis() saja tetep hang. jadi saya putuskan waktu tunggunya pakai perulangan if (delayKirimDataSensor > 100000) seterusnya.
    #include "DHT.h"
    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BMP280.h>
    #include <ESP8266WiFi.h>
    #include <WiFiUdp.h>
    
    Adafruit_BMP280 bmp; // I2C
    DHT dht;
    WiFiUDP Udp;
    byte localUdpPort = 80;  // local port to listen on
    char incomingPacket[255];  // buffer for incoming packets
    char  replyPacket[255];
    
    
    
    //untuk server
    const char* ssid = "tarecha";
    const char* password = "12345678a";
    const String aHostname = "N1";
    String dataSensor;
    String infoNode;
    unsigned long delayKirimDataSensor = 0;
    
    void setup()
    {
    
      Serial.begin(9600);
      dht.setup(D0); // untuk sensor DHT 22
      Wire.begin(D2, D1); //Sensor BMP
      WiFi.begin(ssid, password);
      if (!bmp.begin()) {
        Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
        while (1);
      }
      //bagian setup wifi
      Serial.printf("Connecting to %s ", ssid);
      WiFi.mode(WIFI_STA);
      WiFi.hostname(aHostname);
      while (WiFi.status() != WL_CONNECTED)
      {
        delay(500);
        Serial.print(".");
    
      }
      Serial.println(" connected");
      Udp.begin(localUdpPort);
      infoNode = (String)"Restart reason : " + ESP.getResetReason().c_str() + "\n MAC : " + WiFi.macAddress().c_str() + "\n Hostname : " + WiFi.hostname().c_str() + "\n Signal Stringth : " + WiFi.RSSI() +
                 "\n Local IP : " + WiFi.localIP().toString().c_str() + "\n Port : " + localUdpPort + "\n CPU Freq : " + String(ESP.getCpuFreqMHz()) + " MHz\n Sketch Size : " + ESP.getSketchSize()
                 + "\n Free Space Sketch Size : " + ESP.getFreeSketchSpace();
    
    
    
      Serial.println(infoNode);
    
    
    
    }
    
    void loop()
    {
    
      if (delayKirimDataSensor > 100000)
      {
        UpdateSensor();
        Serial.println(dataSensor);
        delayKirimDataSensor = 0;
      }
      delayKirimDataSensor++;
      requestHandler();
    
    }
    
    void UpdateSensor()
    {
      delay(dht.getMinimumSamplingPeriod());
      float dhtHum = dht.getHumidity();
      float dhtTemp = dht.getTemperature();
      while (dhtHum < 3 && dhtTemp < 3)
      {
        Serial.println("Akan restart karena dht 22 error");
        delay(10000);    
        ESP.restart();
      }
      dataSensor = (String)aHostname + "," + dhtHum + "," + dhtTemp + "," + bmp.readTemperature() + "," + bmp.readPressure() + "," + bmp.readAltitude(1013.25);
    }
    
    void requestHandler()
    {
      int packetSize = Udp.parsePacket();
     
      if (packetSize)
      {
        // receive incoming UDP packets
        Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
        int len = Udp.read(incomingPacket, 255);
        if (len > 0)
        {
           incomingPacket[len] = 0;
        }
        Serial.printf("UDP packet contents: %s\n", incomingPacket);
        if (incomingPacket[0] == 'd') //get info
        {
          dataSensor.toCharArray(replyPacket, 255);
        }
        else if (incomingPacket[0] == 'i') //get data sensor
        {
          infoNode.toCharArray(replyPacket, 255);
        }
        else
        {
          String lain = "masuk else";
          lain.toCharArray(replyPacket, 255);
        }
    
        Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
        Udp.write(replyPacket);
        Udp.endPacket();
        Serial.printf("isi reply packet %s\n", replyPacket);
    
      }
    
    
    }
    
    
    

untuk mencobanya bisa pakai packet sender bisa didownload di link ini https://packetsender.com/download

dalam percobaan ini saya kirimkan data “d” untuk data, “i” untuk info, dan “a” sebagai percobaan masuk else nya. begitu data dikirim maka nodemcu akan menerima data lalu dipilah masuk mana kemudian kirim balasan sesuai yang diinginkan . yang “d” saya kirim balasan dengan pemisah “,” agar bisa langsung save .csv (comma separated value) sehingga gk perlu rubah-rubah lagi.

Percobaan kirim data UDP

Percobaan kirim data UDP

2. Coding Python 2.7

Untuk menerima data dan menyimpannya saya menggunakan python 2.7, alasannya saya berencana pakai raspberry untuk simpan data di mysql jadi nanti gk perlu coding ulang. python ini sangat simpel sekali. berikut codingnya . simpan dalam client.py lalu jalankan. beberapa komentar berisi penjelasan “mengapa” .  ketika save pakai mode ‘a’ yang artinya append, nambahkan file yang ada.

import socket
import sys
import datetime
import time
 
UDP_IP = "192.168.3.192"
UDP_PORT = 80
MESSAGE = "d"

print "UDP target IP:", UDP_IP
print "UDP target port:", UDP_PORT
print "message:", MESSAGE
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.settimeout(10) #dalam 10 detik setelah kirim tunggu data, kalau lewat bypass

while True:
         
        try :
                #Set the whole string
                sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))
                 
                # receive data from client (data, addr)
                d = sock.recvfrom(1024)
                #pemisahan data dengan karakter "," nanti buat save di mysql
                reply = d[0].split(",")
                addr = str(d[1][0])
                
                curmin = datetime.datetime.now().time().minute
                cursec = datetime.datetime.now().time().second
                curhour = datetime.datetime.now().time().hour
                curtime = str(curhour)+':'+str(curmin)+':'+str(cursec)

                #tiap 10 menit simpan di file csv, karena dalam 10 menit lama
                #untuk mencegah save berulang di menit ke 10 dilihat detiknya
                #selama kurang dari 6 maka di save karena ada sleep 5 detiknya
                
                if (curmin % 10 ==0)and (cursec < 6)  :
                        with open('data2.csv','a') as file:
                                file.writelines(d[0]+','+curtime+'\n')
                        print 'data disimpan' + str(reply) +' '+ curtime
                              
                #print 'Server node : ' + reply[0]
                print 'Server reply : ' + str(reply) +' '+curtime
        
             
        except socket.error:
                print 'Tidak konek node'
                #tidak pernah exit karena kalau tidak konek dilewati dan ngulang
                #5 detik kemudian
                #sys.exit()  
        time.sleep(5)

python running

python running

hasil save csv

hasil save csv

dan kita bisa mengolahnya jadi gini

Grafik Tekanan Udara

Grafik Tekanan Udara

Grafik Suhu dan Kelembapan

Grafik Suhu dan Kelembapan

 

 

 

 

 

 

 

 

 

 

Oke done sekian dlu.

next posting akan ada tambahan save ke mysql sekalian grafik php nya kalau ada. dan juga perbaikan jalur powe 3.3 v nya dan 5 v nya mau saya cek apakah tegangannya terlalu tinggi atau terlalu rendah kalau pakai cas hp sehingga mengakibatkan error pembacaan sensor DHT.

terima kasih.

Wassalamu’alaikum Wr. Wb.