Конечно сразу после настройки Nodemcu для отправки на thingspeak.com захотелось сделать отправку к себе на сайт, что бы не было никаких ограничений.
Напишем не большой php скрипт для приема данных и записи их в файл. Это подойдет для хостингов без mysql к тому же я его пока так и не освоил.
В итоге на данный момент у меня получилась такая страничка. Нечто подобное должно получится и у вас.
Для отправки данных на сайт будем использовать вот такую функцию:
const char* host = "kno.su"; //адрес сайта
int value = 0; //переменная для счётчика попыток подключения(если не получилось подключится с первого раза)
void sendHttp (float temp){
++value;
const int httpPort = 80; //порт
int count = 0;
Serial.print("connecting to ");
Serial.println(host);
WiFiClient client;
while(!client.connect(host, httpPort)){
Serial.print("(");
Serial.print(count);
Serial.println(")Connect to server.");
delay(1000);
}
String url = "/sensor/sensor.php"; //путь к скрипту от корня
url += "?api=";
url += "DEY7kMFdpOCQTuAvsDbu"; //API код который должен совпадать с кодом в php скрипте иначе он данные не примет
url += "&field1="; // название ключа, его нужно будет указать в функциях построения графика и последнего значения, может быть любой ключ главное задать его здесь и указать в функциях.
url += String(temp); // Сама температура
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
Serial.println();
Serial.println("closing connection");
}
Code language: Arduino (arduino)
Ключей-значений может быть сколько угодно, их нужно будет добавить по аналогии в void sendHttp (float temp, float название_переменной_с_данными) и в текст url:
String url = "/sensor/sensor.php"; //путь к скрипту от корня
url += "?api=";
url += "DEY7kMFdpOCQTuAvsDbu"; //API код который должен совпадать с кодом в php скрипте иначе он данные не примет
url += "&field1="; // название ключа, его нужно будет указать в функциях построения графика и последнего значения, может быть любой ключ главное задать его здесь и указать в функциях.
url += String(temp); // Сама температура
url += "&название_ключа_для_новой_переменной=";
url += String(название_переменной_с_данныминной_с_даннымианнымиыми;
Code language: Arduino (arduino)
Саму функцию запускаем так:
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
//сначала опрашиваем ваши датчики в переменные temperature и humidity потом отправляем их значения в функцию, верхние две строчки для ясности, у вас должны будут быть вместо них опросы ваших датчиков возвращаемые в переменные которые в свою очередь передаем в функцию.
sendHttp(temperature, humidity);
Code language: Arduino (arduino)
Целиком скетч будет выглядеть примерно так:
#include <ESP8266WiFi.h>
const char* ssid = "KV3";
const char* password = "qweasdzxc12345678";
unsigned long timing_http; // Переменная для хранения точки отсчета
void setup() {
Serial.begin(115200);
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password); //works!
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
int value = 0;
void loop() {
int timer_http = 10 * 60 * 1000; //Таймер отправки (каждые 10 мин)
if (millis() - timing_http > timer_http){ // Если настало время(таймер из переменной timer), то отправляем данные
timing_http = millis();
Serial.println ("otpravka na kno.su");
float temperature = dht.readTemperature(); //у меня опрос dht 22 у вас может быть что угодно
float humidity = dht.readHumidity(); //у меня опрос dht 22 у вас может быть что угодно
float ppm = gasSensor.getPPM(); //у меня опрос mq135 у вас может быть что угодно
float rzero = gasSensor.getRZero(); //у меня опрос mq135 у вас может быть что угодно
//пинг смартфонов на предмет присутствия, эксперимент, нужна библиотека https://github.com/dancol90/ESP8266Ping
int ping1 = 0;
int ping2 = 0;
int ping3 = 0;
const IPAddress remote_ip_1(192, 168, 100, 201);
if(Ping.ping(remote_ip_1)) {ping1 = 1;} else{ping1 = 0;}
const IPAddress remote_ip_2(192, 168, 100, 202);
if(Ping.ping(remote_ip_2)) {ping2 = 1;} else{ping2 = 0;}
const IPAddress remote_ip_3(192, 168, 100, 203);
if(Ping.ping(remote_ip_3)) {ping3 = 1;} else{ping3 = 0;}
sendHttp(temperature, humidity, ppm, rzero, ping1, ping2, ping3); //Функция отправки, код функции ниже
}
}
//Функция отправки с 7 значениями
const char* host = "kno.su";
int value = 0;
void sendHttp (float temp, float humidity, float ppm, float rzero, int ping1, int ping2, int ping3){
++value;
const int httpPort = 80;
int count = 0;
Serial.print("connecting to ");
Serial.println(host);
// Use WiFiClient class to create TCP connections
WiFiClient client;
while(!client.connect(host, httpPort)){
Serial.print("(");
Serial.print(count);
Serial.println(")Connect to kno.su.");
delay(1000);
}
// We now create a URI for the request
String url = "/sensor/sensor.php";
url += "?api=";
url += "DEY7kMFdpOCQTuAvsDbu";
url += "&field1=";
url += String(temp);
url += "&field2=";
url += String(humidity);
url += "&field3=";
url += String(ppm);
url += "&field4=";
url += String(rzero);
url += "&ping1=";
url += String(ping1);
url += "&ping2=";
url += String(ping2);
url += "&ping3=";
url += String(ping3);
Serial.print("Requesting URL: ");
Serial.println(url);
// This will send the request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
Serial.println();
Serial.println("closing connection");
}
Code language: Arduino (arduino)
Вот скрипт приема и записи данных в файл с комментариями:
<?php
date_default_timezone_set("Europe/Minsk"); //часовой пояс
//Сравниваем ключ API с тем что прислан, если все сходится продолжаем:
if(isset($_GET['api']) && $_GET['api'] == "DEY7kMFdpOCQTuAvsDbu"){
unset($_GET['api']); //удаляем api т.к. он нужен был только для проверки подлинности
$sensors_data = $_GET; //Все данные из $_GET переносим в $sensor_data
$date_sensor = date("Y-m-d H:i"); // Дата, в таком формате что бы потом можно было использовать со js скриптом графика
$sensors_write ="date=$date_sensor::"; //Переменная с данными которые будут записаны в файл
$filename = "nodemcu.dat"; //имя файла
foreach($sensors_data as $key => $value){//цикл который запишет все ключи и их значения которые пришли
$sensors_write .= "$key=$value::";
}
$sensors_write .= "]||[\n";//разделитель между записями
$text = $sensors_write; //Итоговый текст для записи в файл
if(file_exists($filename)) //Проверка наличия файла
{
echo "<b>Файл есть</b><br>";
}
else{
echo "<b>Файл не найден</b></br>";
}
$fh = fopen($filename, 'a+'); //Переменная для открытия файла
fwrite($fh, $text) or die ("Ошибка записи файла"); // Запись файла
fclose($fh); // Закрытие файла
echo "Запись добавлена";
}
?>
Code language: PHP (php)
Дальше нужно эти данные считать и показать. Для этого напишем три функции: функцию чтения из файла в массив вида ключ = значение, функцию которая с этого массива берет один ключ и строит по нему график на основе dygraphs, и функцию которая будет выводит последнее поступившее значение по определенному ключу.
Функция чтения:
function sensor_read($filename){
$sensors_read = file_get_contents($filename);
$sensors_read = explode("]||[\n", $sensors_read);
foreach($sensors_read as $key => $value){
$sensors_temp = explode("::", $value);
$n = 0;
foreach($sensors_temp as $key_ => $value){
if($value != ""){
$sensors_data[$key][$key_] = explode("=", $value);
}}
}
foreach ($sensors_data as $key => $value){
//test_print($value);
//$sensors[$value[0]] = $value[1];
foreach($value as $key_ => $sensor){
//test_print($sensor);
$sensors[$key][$sensor[0]] = $sensor[1];
}
}
return $sensors;
}
Code language: PHP (php)
Функция построения графика:
function sensor_graph($sensor_id, $sensor_id_description, $sensors){
echo'
<div id="'.$sensor_id.'_graph" class="graph" style="width: 90%; height: 100px; margin: 5px auto;"></div><script type="text/javascript">
g = new Dygraph(
// containing div
document.getElementById("'.$sensor_id.'_graph"),
"Дата,'.$sensor_id_description.'\n" +
';
$sensor_count = 0;
foreach($sensors as $key => $value){
if(isset($value[$sensor_id]) && $value[$sensor_id] != ""){
$sensor_count++;
}
}
$count = 0;
foreach($sensors as $key => $value){
if(isset($value[$sensor_id]) && $value[$sensor_id] != ""){
$count++;
if($count < $sensor_count){
echo '"'.$value['date'].",".$value[$sensor_id].'\n'.'" +'."\n";
}
else{
echo '"'.$value['date'].",".$value[$sensor_id].'"'."\n".");\n";
}
}
}
echo '</script>';
}
Code language: PHP (php)
Для того что бы график работал нужно подключить библиотеку dygraph:
<script type="text/javascript"
src="dygraph.js"></script>
Code language: HTML, XML (xml)
Саму библиотеку можно скачать и ознакомится с ней на сайте dygraphs.com.
Функция вывода последнего значения:
function sensor_latest($sensor_id, $sensors){
foreach($sensors as $key => $value){
foreach($value as $key_ => $value_){
if(isset($value[$sensor_id]) && $value[$sensor_id] !=""){
$sensor_latest['sensor'] = $value[$sensor_id];
$sensor_latest['date'] = $value['date'];
}
}
}
return $sensor_latest;
}
Code language: PHP (php)
Последнее значение будет в виде массива, где ключ sensor — само значение, а ключ date — дата когда оно поступило.
В итоге файл с вызовом этих функций должен выглядеть примерно так:
<?php
include "functions.php";
echo '
<html>
<head>
<title>Датчики</title>
<meta charset="utf-8">
<meta name="robots" content="nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="style.css">
<script type="text/javascript" src="dygraph.js"></script>
</head>
<body>
';
$filename = "nodemcu.dat"; //имя файла
$sensors = sensor_read($filename); //массив с данными для функций
$field1_latest = sensor_latest("field1", $sensors);//последнее значение
echo "<h4>Температура ".$field1_latest['sensor']." °C</h4>"; //вывод последнего значения
sensor_graph("field1", "Температура", $sensors); //вывод графика
echo'</body> </html>';
?>
Code language: HTML, XML (xml)
field1 в данном случае это ключ с которым отправлялись данные. Ключ может быть любым, как его назвали такой и вставляете в функцию и их может быть сколько угодно.
З.Ы. Как ни странно но долетают данные иногда реже чем на thingspeak и от чего такие затупы так и не понял, возможно дело в хостинге.