Отправка запроса от веб-сервера ардуино

sbm
Offline
Зарегистрирован: 06.05.2020

Здравствуйте.

Подскажите, как отправить данные с веб-сервера ардуино?

Ардуино подключен к интернету с помощью ENC28J60

В библиотеке EtherCard за это отвечает tcpReply(), скетч выглядит так:

   session = ether.tcpSend();
      const char* reply = ether.tcpReply(session);
 
   if (reply != 0) {
     //res = 0;
     String data(reply);
     Serial.println(F(" >>>REPLY recieved...."));
     Serial.println(reply);
    }

php-код, обрабатывающий нажатие кнопки:

include('../connect.php');
 
$query = 'SELECT * FROM `data` where `id`=3 ORDER by time DESC';  // берем текущее состояние кнопки
$result = mysqli_query($link, $query);
$row = mysqli_fetch_array($result);
$S2=!$row['data'];                                                                              // меняем на противоположное
$query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES ("3", "'.$S2.'", "'.date('Y-m-d H:i:s').'", "")';
$result = mysqli_query($link, $query);
 
echo "v1=".$S2;                                                                                 // выводим значение кнопки для ардуино

после нажатия кнопки, ардуино видит ответ сервера, в мониторе пишется >>>REPLY recieved...., но сам reply пустой

Подскажите, что не так делаю, может не так запрос с сервера отправляю, или reply надо как-то по-другому обрабатывать?

b707
Онлайн
Зарегистрирован: 26.05.2017

зачем нужна 6 строчка? память некуда девать?

sbm
Offline
Зарегистрирован: 06.05.2020

b707 пишет:
зачем нужна 6 строчка? память некуда девать?

я пробовал и Serial.println(reply); и Serial.println(data); все равно пустой результат, просто забыл удалить из этого текста

b707
Онлайн
Зарегистрирован: 26.05.2017

проверьте. что отвечает сервер. может там ответ пустой. Подключитесь к серверу не через ардуино, а с компа

sbm
Offline
Зарегистрирован: 06.05.2020

b707 пишет:
проверьте. что отвечает сервер. может там ответ пустой. Подключитесь к серверу не через ардуино, а с компа

я могу зайти на сервер с компа, но как увидеть, что он отвечает?

b707
Онлайн
Зарегистрирован: 26.05.2017

sbm пишет:

как увидеть, что он отвечает?

в браузере

sbm
Offline
Зарегистрирован: 06.05.2020

b707 пишет:
в браузере

в браузере я вижу только головной файл сайта index.php из него вызывается файл led.php обработчик кнопки и он должен послать запрос ардуино:

index.php:

<html>
<head>
<title>HOME</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <script src="//code.jquery.com/jquery-1.11.0.min.js"></script>

    <link rel="stylesheet" type="text/css" href="style.css">
    <script>
      function show()
        {
             $.ajax({
                url: "transfer/ledstate.php",
                cache: false,
                success: function(html){
                    $("#content-3").html(html);
                }
             });

        }

        $(document).ready(function(){
            show();
            setInterval('show()',5000);
        });

      function AjaxFormRequest(result_id,led,url) {
      jQuery.ajax({
      url:     url,
      type:     "GET",
      dataType: "html",
      data: jQuery("#"+led).serialize(),
         });
        show();
    }
  </script>

</head>
<body>
          <div class="rr">
          <p class="r1">Состояние&nbsp;&nbsp;<a href="transfer/graf.php?id=3"><img src="../images/graf.png" style="vertical-align: middle" alt="Смотреть график"></a></p>
          <div class="r2"style="font-size:35px" >
            <form  id="led" action="" method="post"  >
              <div class="r3" id="content-3" onclick="AjaxFormRequest('messegeResult', 'led', 'transfer/led.php')" ></div>
            </form>
          </div>
          </div>

   </body>
</html>

led.php:

<?php
include('../connect.php');

$query = 'SELECT * FROM `data` where `id`=3 ORDER by time DESC';
//echo $query.'<br>';
$result = mysqli_query($link, $query);
$row = mysqli_fetch_array($result);
$S2=!$row['data'];
$query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES ("3", "'.$S2.'", "'.date('Y-m-d H:i:s').'", "")';
//echo $query.'<br>';
$result = mysqli_query($link, $query);
echo "v1=".$S2;
?>

последняя строка предполагается отправляет значение v1=1 или 0, но похоже это не так)

sadman41
Онлайн
Зарегистрирован: 19.10.2016

arduino к какому файлу обращается?

b707
Онлайн
Зарегистрирован: 26.05.2017

sadman41 пишет:

arduino к какому файлу обращается?

хороший вопрос :) к какому-то add_data.php

вот скетч автора. выложенный на Амперке

#include <EtherCard.h>                // Подключаем библиотеку для взаимодействия ENC28J60
#include <OneWire.h>                  // Подключаем библиотеку для взаимодействия с устройствами, работающими на шине и по протоколу 1-Wire
#include <DallasTemperature.h>        // Подключаем библиотеку с функциями для работы с DS18B20 (запросы, считывание и преобразование возвращаемых данных)

#define ONE_WIRE_BUS 2                // Указываем пин подключения data-вывода датчика температуры
#define term_power 4                  // Указываем пин подключения питания датчика температуры

OneWire oneWire(ONE_WIRE_BUS);        // Сообщаем библиотеке об устройстве, работающем по протоколу 1-Wire
DallasTemperature sensors(&oneWire);  // Связываем функции библиотеки DallasTemperature с нашим 1-Wire устройством (DS18B20)

#define HTTP_HEADER_OFFSET 0
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
const char website[] PROGMEM = "www.moysite";
const char* reply;

byte Ethernet::buffer[700];
static uint32_t timer = 0;
static byte session;
Stash stash;
float t[2], tmp[]={77.1, 77,11};
char param[20];
/*
static void response_callback (byte status, word off, word len) {
  Serial.print((const char*) Ethernet::buffer + off + HTTP_HEADER_OFFSET);
}
*/
void setup () {
  Serial.begin(57600);
  sensors.begin();                // Запускаем библиотеку измерения температуры
  pinMode(term_power, OUTPUT);    // Определяем пин подключения питания датчика температуры

  if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)         // проверка ENC28J60 модуля и соединения
    Serial.println(F("Failed to access Ethernet controller"));
  if (!ether.dhcpSetup())
    Serial.println(F("DHCP failed"));

  if (!ether.dhcpSetup())
  {
    Serial.println("Failed to get configuration from DHCP");
    while(1);
  }
  else
    Serial.println("DHCP configuration done");

  if (!ether.dnsLookup(website))
  {
    Serial.println("DNS failed");
    while(1);
  }
  else
    Serial.println("DNS resolution done");

  ether.printIp("SRV IP:\t", ether.hisip);       // конец проверки ENC28J60 модуля и соединения
}

void temperature()                              // Измеряем температуру
{
  digitalWrite(term_power, HIGH);                // Включаем питание датчика температуры
  delay(100);                                    // Задержка перед первым измерением
  sensors.requestTemperatures();                 // Запрос на измерение температуры (1-й ошибочный)
  delay(500);                                    // Задержка перед повторным измерением
  sensors.requestTemperatures();                 // Запрос на измерение температуры (повторный)
  t[0] = float(sensors.getTempCByIndex(0));   // Получаем значение температуры
  t[1] = float(sensors.getTempCByIndex(1));
  digitalWrite(term_power, LOW);                 // Отключаем питание датчика температуры
//  delay(4400);                                   // Задержка, чтобы датчик не нагревался от частых измерений
//  return();                                     // Возвращаем значение температуры в место вызова функции
}

void loop() {
ether.packetLoop(ether.packetReceive());

if (millis() > timer)
{
   timer = millis() + 5000;                     // проверка таймера 1 раз в 5 секунд
 
   byte sd = stash.create();
   if(tmp[0]!=77.11)
    {
     tmp[0]=t[0];
     tmp[1]=t[1];
    };
   temperature();
   //param="";
   if(t[0]!=tmp[0])                                 // Записываем значение датчика 1, если оно изменилось
    {
     stash.print("t1=");
     stash.print(t[0],1);                           // Выводим текущее значение температуры датчика, округленное до десятых
     Serial.println(t[0],1);
    };
   if(t[1]!=tmp[1])                                 // Записываем значение датчика 2, если оно изменилось
    {
     if(t[0]!=tmp[0]) stash.print("&");
     stash.print("t2=");
     stash.print(t[1],1);                           // Выводим текущее значение температуры датчика, округленное до десятых
     Serial.println(t[1],1);
    };
   if((t[0]!=tmp[0])||(t[1]!=tmp[1]))               // Отправляем данные на сервер, если значение датчиков 1 или 2 изменилось
    {
     stash.save();
     Stash::prepare(PSTR("POST http://sbm78.cf/add_data.php HTTP/1.0" "\r\n"    // отправка запроса на сервер
                         "Host: www.sbm78.cf \r\n"
                         "Content-Length: $D" "\r\n"
                         "Content-Type: application/x-www-form-urlencoded \r\n"
                         "\r\n"
                         "$H"),
          stash.size(), sd);
     session = ether.tcpSend();
    };
 
   const char* reply = ether.tcpReply(session);

   if (reply != 0) {
     //res = 0;
     String data(reply);
     Serial.println(F(" >>>REPLY recieved...."));
     Serial.println(reply);
     Serial.println(data);
     Serial.println(data.length());
   }
}
}

 

b707
Онлайн
Зарегистрирован: 26.05.2017

sbm - выложите еще код файла add_data.php

sbm
Offline
Зарегистрирован: 06.05.2020

Вот весь скетч:

#include <EtherCard.h>                // Подключаем библиотеку для взаимодействия ENC28J60
#include <OneWire.h>                  // Подключаем библиотеку для взаимодействия с устройствами, работающими на шине и по протоколу 1-Wire
#include <DallasTemperature.h>        // Подключаем библиотеку с функциями для работы с DS18B20 (запросы, считывание и преобразование возвращаемых данных)

#define ONE_WIRE_BUS 2                // Указываем пин подключения data-вывода датчика температуры
#define term_power 4                  // Указываем пин подключения питания датчика температуры

OneWire oneWire(ONE_WIRE_BUS);        // Сообщаем библиотеке об устройстве, работающем по протоколу 1-Wire
DallasTemperature sensors(&oneWire);  // Связываем функции библиотеки DallasTemperature с нашим 1-Wire устройством (DS18B20)

#define HTTP_HEADER_OFFSET 0
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
const char website[] PROGMEM = "www.my.site";
const char* reply;

byte Ethernet::buffer[900];
static uint32_t timer = 0;
static byte session;
Stash stash;
float t[2], tmp[]={77.1, 77,11};
char param[20];
/*
static void response_callback (byte status, word off, word len) {
  Serial.print((const char*) Ethernet::buffer + off + HTTP_HEADER_OFFSET);
} 
*/
void setup () {
  Serial.begin(57600);
  sensors.begin();                // Запускаем библиотеку измерения температуры
  pinMode(term_power, OUTPUT);    // Определяем пин подключения питания датчика температуры
  
  if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)         // проверка ENC28J60 модуля и соединения
    Serial.println(F("Failed to access Ethernet controller"));
  if (!ether.dhcpSetup())
    Serial.println(F("DHCP failed"));

  if (!ether.dhcpSetup())
  {
    Serial.println("Failed to get configuration from DHCP");
    while(1);
  }
  else
    Serial.println("DHCP configuration done");

  if (!ether.dnsLookup(website))
  {
    Serial.println("DNS failed");
    while(1);
  }
  else 
    Serial.println("DNS resolution done"); 

  ether.printIp("SRV IP:\t", ether.hisip);       // конец проверки ENC28J60 модуля и соединения
}

void temperature()                              // Измеряем температуру 
 {
  digitalWrite(term_power, HIGH);                // Включаем питание датчика температуры
  delay(100);                                    // Задержка перед первым измерением 
  sensors.requestTemperatures();                 // Запрос на измерение температуры (1-й ошибочный)
  delay(500);                                    // Задержка перед повторным измерением
  sensors.requestTemperatures();                 // Запрос на измерение температуры (повторный)
  t[0] = float(sensors.getTempCByIndex(0));   // Получаем значение температуры
  t[1] = float(sensors.getTempCByIndex(1));
  digitalWrite(term_power, LOW);                 // Отключаем питание датчика температуры
//  delay(4400);                                   // Задержка, чтобы датчик не нагревался от частых измерений
//  return();                                     // Возвращаем значение температуры в место вызова функции
 }

// called when the client request is complete
static void my_callback (byte status, word off, word len) {
  Serial.println(">>>");
  Ethernet::buffer[off+500] = 0;
  Serial.print((const char*) Ethernet::buffer + off);
  Serial.println("...");
}

void loop() {
 ether.packetLoop(ether.packetReceive());

 if (millis() > timer) 
 {
   timer = millis() + 5000;                     // проверка таймера 1 раз в 5 секунд 
   
   byte sd = stash.create();
   if(tmp[0]!=77.11)
    {
     tmp[0]=t[0];
     tmp[1]=t[1];
    }; 
   temperature();
   //param="";
   if(t[0]!=tmp[0])                                 // Записываем значение датчика 1, если оно изменилось
    {
     stash.print("t1=");
     stash.print(t[0],1);                           // Выводим текущее значение температуры датчика, округленное до десятых
     Serial.println(t[0],1);
    }; 
   if(t[1]!=tmp[1])                                 // Записываем значение датчика 2, если оно изменилось
    {
     if(t[0]!=tmp[0]) stash.print("&");
     stash.print("t2=");
     stash.print(t[1],1);                           // Выводим текущее значение температуры датчика, округленное до десятых
     Serial.println(t[1],1);
    }; 
   if((t[0]!=tmp[0])||(t[1]!=tmp[1]))               // Отправляем данные на сервер, если значение датчиков 1 или 2 изменилось
    {
     stash.save();
     Stash::prepare(PSTR("POST http://my.site/add_data.php HTTP/1.0" "\r\n"    // отправка запроса на сервер
                         "Host: www.my.site \r\n"
                         "Content-Length: $D" "\r\n"
                         "Content-Type: application/x-www-form-urlencoded \r\n"
                         "\r\n"
                         "$H"),
          stash.size(), sd);
     session = ether.tcpSend();
    };
   
   const char* reply = ether.tcpReply(session);

   if (reply != 0) {
     //res = 0;
     String data(reply);
     Serial.println(F(" >>>REPLY recieved...."));
     Serial.println(reply);
     Serial.println(data);
     Serial.println(data.length());
   }
 }
}

ардуино передает данные в файл add_date.php - это у меня отлично получается.

Не получается при нажатии кнопки на сервере (на сайте), передать значение в ардуино

обрабатывает нажатие кнопки led.php и он должен возвращать значение 1 или 0

<?php
include('../connect.php');

$query = 'SELECT * FROM `data` where `id`=3 ORDER by time DESC';
//echo $query.'<br>';
$result = mysqli_query($link, $query);
$row = mysqli_fetch_array($result);
$S2=!$row['data'];
$query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES ("3", "'.$S2.'", "'.date('Y-m-d H:i:s').'", "")';
//echo $query.'<br>';
$result = mysqli_query($link, $query);
echo "v1=".$S2;
?>

в скетче я пытаюсь это сделать в строчках с 119 по 128

b707
Онлайн
Зарегистрирован: 26.05.2017

sbm пишет:

в скетче я пытаюсь это сделать в строчках с 119 по 128

ЛОЛ :)

В строчках с 119 по 128 - это ответ на запрос к add_data.php

С нажатием кнопки на сервере это НЕ СВЯЗАНО НИКАК.

b707
Онлайн
Зарегистрирован: 26.05.2017

Цитата:
Не получается при нажатии кнопки на сервере (на сайте), передать значение в ардуино

И не получится. Вы, похоже, кардинально не понимаете как это все работает. При нажатии кнопки в форме на сайте на ардуину НИЧЕГО НЕ ПЕРЕДАЕТСЯ. Ардуина может что-то получить только в том случае. если сама послала запрос. И посылать этот запрос нужно именно тому скрипту на сервере, который вам вернет состояние кнопки.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sbm, чтоб данные ушли в arduino, вам сначала при нажатии кнопки необходимо исправить данные в бд, т е поставить какой то флаг, а при запросе get с МК смотреть на этот флаг и в зависимости от него слать данные.

sbm
Offline
Зарегистрирован: 06.05.2020

b707 пишет:
Цитата:
Не получается при нажатии кнопки на сервере (на сайте), передать значение в ардуино
И не получится. Вы, похоже, кардинально не понимаете как это все работает. При нажатии кнопки в форме на сайте на ардуину НИЧЕГО НЕ ПЕРЕДАЕТСЯ. Ардуина может что-то получить только в том случае. если сама послала запрос. И посылать этот запрос нужно именно тому скрипту на сервере, который вам вернет состояние кнопки.

отлично, уже немного понял свою ошибку, я действительно плохо понимаю этот процесс

у меня передача данных датчиков и нажатие кнопки - разные процессы, хотя получается их можно объединить в один.

в моем случае, надо послать запрос в led.php и получить от него ответ

b707
Онлайн
Зарегистрирован: 26.05.2017

sbm пишет:

в моем случае, надо послать запрос в led.php и получить от него ответ

да, как-то так

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ему нужно просо создать этот файл add data и в нем отдавать значение кнопки из базы в дуню. Если я верно понял вопрос. Причём просто текстом, по виду 

echo $row[‘data’];

 

sbm
Offline
Зарегистрирован: 06.05.2020

в исходной версии сайта данные температуры и состояние кнопки обрабатывались разными скриптами соответственно в файлах add_data.php, который по запросу ардуино добавляет данные в базу, и led.php, который вызывается только сайтом.

Теперь я понял, что нужно переделать в скетче и сайте, будем пробовать, спасибо 

sbm
Offline
Зарегистрирован: 06.05.2020

я исправил скетч, теперь и датчики и кнопку обрабатывает один файл add_data.php

скетч:

#include <EtherCard.h>                // Подключаем библиотеку для взаимодействия ENC28J60
#include <OneWire.h>                  // Подключаем библиотеку для взаимодействия с устройствами, работающими на шине и по протоколу 1-Wire
#include <DallasTemperature.h>        // Подключаем библиотеку с функциями для работы с DS18B20 (запросы, считывание и преобразование возвращаемых данных)

#define ONE_WIRE_BUS 2                // Указываем пин подключения data-вывода датчика температуры
#define term_power 4                  // Указываем пин подключения питания датчика температуры

OneWire oneWire(ONE_WIRE_BUS);        // Сообщаем библиотеке об устройстве, работающем по протоколу 1-Wire
DallasTemperature sensors(&oneWire);  // Связываем функции библиотеки DallasTemperature с нашим 1-Wire устройством (DS18B20)

#define HTTP_HEADER_OFFSET 0
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
const char website[] PROGMEM = "www.my.site";
const char* reply;

byte Ethernet::buffer[900];
static uint32_t timer = 0;
static byte session;
Stash stash;
float t[2], tmp[]={77.1, 77,11};
char param[20];
/*
static void response_callback (byte status, word off, word len) {
  Serial.print((const char*) Ethernet::buffer + off + HTTP_HEADER_OFFSET);
} 
*/
void setup () {
  Serial.begin(57600);
  sensors.begin();                // Запускаем библиотеку измерения температуры
  pinMode(term_power, OUTPUT);    // Определяем пин подключения питания датчика температуры
  
  if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)         // проверка ENC28J60 модуля и соединения
    Serial.println(F("Failed to access Ethernet controller"));
  if (!ether.dhcpSetup())
    Serial.println(F("DHCP failed"));

  if (!ether.dhcpSetup())
  {
    Serial.println("Failed to get configuration from DHCP");
    while(1);
  }
  else
    Serial.println("DHCP configuration done");

  if (!ether.dnsLookup(website))
  {
    Serial.println("DNS failed");
    while(1);
  }
  else 
    Serial.println("DNS resolution done"); 

  ether.printIp("SRV IP:\t", ether.hisip);       // конец проверки ENC28J60 модуля и соединения
}

void temperature()                              // Измеряем температуру 
 {
  digitalWrite(term_power, HIGH);                // Включаем питание датчика температуры
  delay(100);                                    // Задержка перед первым измерением 
  sensors.requestTemperatures();                 // Запрос на измерение температуры (1-й ошибочный)
  delay(500);                                    // Задержка перед повторным измерением
  sensors.requestTemperatures();                 // Запрос на измерение температуры (повторный)
  t[0] = float(sensors.getTempCByIndex(0));   // Получаем значение температуры
  t[1] = float(sensors.getTempCByIndex(1));
  digitalWrite(term_power, LOW);                 // Отключаем питание датчика температуры
 }

void loop() {
 ether.packetLoop(ether.packetReceive());

 if (millis() > timer) 
 {
   timer = millis() + 5000;                     // проверка таймера 1 раз в 5 секунд 
   
   byte sd = stash.create();
   temperature();
     stash.print("t1=");
     stash.print(t[0],1);                           // Выводим текущее значение температуры датчика, округленное до десятых
     Serial.println(t[0],1);
     stash.print("&t2=");
     stash.print(t[1],1);                           // Выводим текущее значение температуры датчика, округленное до десятых
     Serial.println(t[1],1);
     stash.save();
     Stash::prepare(PSTR("POST http://my.site/add_data.php HTTP/1.0" "\r\n"    // отправка запроса на сервер
                         "Host: www.my.site \r\n"
                         "Content-Length: $D" "\r\n"
                         "Content-Type: application/x-www-form-urlencoded \r\n"
                         "\r\n"
                         "$H"),
          stash.size(), sd);
     session = ether.tcpSend();
   
   const char* reply = ether.tcpReply(session);

   if (reply != 0) 
    {
     Serial.println(F(" >>>REPLY recieved...."));
     Serial.println(reply);
    }
 }
}

add_data.php:

<?php
include('connect.php');

$query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES (1, '.$_POST['t1'].', "'.date("Y-m-d H-i-s").'", ""), (2, '.$_POST['t2'].', "'.date("Y-m-d H-i-s").'", "")';
$result = mysqli_query($link, $query); // записали данные по температуре

if(@$_POST['led']==11)                            // проверка, что есть запрос на изменение состояния кнопки с сайта
  {
    $query = 'SELECT * FROM `data` where `id`=3 ORDER by time DESC';
    $result = mysqli_query($link, $query);
    $row = mysqli_fetch_array($result);
    $S2=!$row['data'];
    $query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES ("3", "'.$S2.'", "'.date('Y-m-d H:i:s').'", "")';
    $result = mysqli_query($link, $query);
    echo "v1=".$S2;
  }
?>

на стороне сайта, работает хорошо: температура выводится и кнопка переключается, но в ардуино данные все равно не возвращаются( reply в 95 строке всегда 0

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Зачем начинаете незнакомое дело с монстрячих конструкций? Сделайте простой php, который получает число, умножает на два и возвращает результат. Когда это заработает - будете уже свои SQL-и накручивать.

sbm
Offline
Зарегистрирован: 06.05.2020

sadman41 пишет:
Зачем начинаете незнакомое дело с монстрячих конструкций? Сделайте простой php, который получает число, умножает на два и возвращает результат. Когда это заработает - будете уже свои SQL-и накручивать.

резонно, add_date.php:

<?php
    if(@$_POST['t1']) $t1=$_POST['t1']+10;
    if(@$_POST['t2']) $t2=$_POST['t2']+20;

    echo "?t1=".$_POST['t1']."&t2=".$_POST['t2']
?>

проще некуда, передаю t1=10, t2=15, 

должен получить "?t1=20&t2=35", но почему-то возвращает в ардуино пустую строку

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Думаю ваш post запрос некорректно на сервер доходит, посмотрите в логах Web сервера ошибки. Я обычно начинал с get запросов, их полностью заставлял корректно работать, причём сначала с браузера, потом уже на post переходил.

sbm
Offline
Зарегистрирован: 06.05.2020

Мне тоже кажется, что echo "t1=20" это не POST запрос, а просто вывод на экран t1=20, но тогда можете привести пример как нужно делать get или пост запросы. 

Теорию я знаю, get запрос - это index.php?t1=10&t2=15, post запрос, через форму

Но как мне тут написать add_data.php, как Вы говорили умножение на 2 и вернуть это значение? 

Начало понятно:

$t1=$_GET['t1']*2;
$t2=$_GET['t2']*3;

а как вернуть эти значения get запросом?

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Так выше же все написано. Или я не понял задачу.
1. Нажимаете кнопку и значение в бд меняется и устанавливается флаг что необходимо отправить данные в ардуино
2. При любом get / post запросе смотрим в бд флаг, если он есть - возвращаем echo то что нам необходимо и сбрасываем флаг.

Вы в логах проверили - запрос доходит корректно?
Пример есть, если найду ближе к обеду скину

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Я больше скажу - возьмите оригинальную UIPEthernet - там в экзамплах, вроде как идёт, Webclient. Оно точно работает. На нем и прогоните свой простой алгоритм. EtherCard - своеобразная библиотека, редко тут всплывает.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

вот пример PHP откопал, если в параметре GET запроса пришло on то в обратку шлет текст " SetRelayOFF ~", скетч находит эту строку в ответной HTML страничке и выключает реле, ну и наоборот сотвественно.

<?php include_once $_SERVER['DOCUMENT_ROOT'] . '/includes/helpers.inc.php'; ?>
<!DOCTYPE html>
<html>

<?php 

function tempToFloat($arg)
{
	if ($arg >= 2000)
	{
		$res = ($arg-2000);
		$res = ($res / 10);
		$res = (0-$res);
	} else
	{
		$res = ($arg / 10);
	}
	return $res;
}

if ((isset($_GET['id']))  and (isset($_GET['rs'])) and (isset($_GET['t0'])))
{
	try
	{
		if (isset($_GET['t2'])) 
		{
			$sql = 'INSERT INTO `thermometers` (`i_id`, `c_strelay`, `f_t1`, `f_t2`, `f_t3`) VALUES (:p1, :p2, :p3, :p4, :p5)';
		} else if (isset($_GET['t1']))
		{
			$sql = 'INSERT INTO `thermometers` (`i_id`, `c_strelay`, `f_t1`, `f_t2`) VALUES (:p1, :p2, :p3, :p4)';
		} else 
		{
			$sql = 'INSERT INTO `thermometers` (`i_id`, `c_strelay`, `f_t1`) VALUES (:p1, :p2, :p3)';
		}
		$s = $pdo->prepare($sql);
		$s->bindValue(':p1', $_GET['id']);
		$s->bindValue(':p2', $_GET['rs']);
		$s->bindValue(':p3', tempToFloat($_GET['t0']));
		if (isset($_GET['t1']))
		{
			$s->bindValue(':p4', tempToFloat($_GET['t1']));
		}
		if (isset($_GET['t2']))
		{
			$s->bindValue(':p5', tempToFloat($_GET['t2']));
		}
		$s->execute();
	}
	catch (PDOException $e)
	{
		$error = 'Error ' . $e->getMessage();
		include $_SERVER['DOCUMENT_ROOT'] . '/includes/error.html.php';
		exit();
	}
	//echo " Save OK ~";
	if ($_GET['rs']=='on') 
	{
		echo " SetRelayOFF ~";
	} else 
	{
		echo " SetRelayON ~";
	}
}
?>

<p></p>

</html>

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

POST и GET запросы адресованы серверу и обрабатываются им (сервером). Он приняв эти запросы "раскладывает их по глобальным переменным" (к примеру, POST: https://www.php.net/manual/ru/reserved.variables.post.php )

Дуня в этой связке предстает КЛИЕНТОМ, а клиент может получать только "ВЫВОД" (обычно в html или чистый текст).

Если дуня будет слать GET запрос (POST используется для  большого объема данных), к примеру такого вида:

http://my.site/add_data.php?mode=dunya&data=32

То получающий на сервере скрипт (add_data.php) должен его обработать и выдать ответ:

<?php
include('connect.php');

if ($_GET['mode'] && trim($_GET['mode']) == "dunya") { // Если данные пришли с дуни, то заносим их и возвращаем ОК
   $query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES (1, '.$_GET['data'].', "'.date("Y-m-d H-i-s").'", "");
   $result = mysqli_query($link, $query); // записали данные по температуре
   if ($result) {
      echo "OK";   // если все занесли
   } else {
      echo "ERROR"; // если внести данные не получилось
   }
} else { // иначе делаете что там Вам нужно по кнопке с сайта или как там у Вас?
// пусть останется Ваш текст (не вдавался в подробности о чем он:
    $query = 'SELECT * FROM `data` where `id`=3 ORDER by time DESC';
    $result = mysqli_query($link, $query);
    $row = mysqli_fetch_array($result);
    $S2=!$row['data'];
    $query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES ("3", "'.$S2.'", "'.date('Y-m-d H:i:s').'", "")';
    $result = mysqli_query($link, $query);
    echo "v1=".$S2;
}
?>

Дуня получит ответ или "ОК" или "ERROR" и вы увидите его в выводе. То же самое и для получения данных из БД по GET (POST) запросу.

Что-то усложнили банальную задачу...

ЗЫ: Писал все быстро, могут быть и ошибки в коде.

sbm
Offline
Зарегистрирован: 06.05.2020

BOOM пишет:
Дуня получит ответ или "ОК" или "ERROR" и вы увидите его в выводе. То же самое и для получения данных из БД по GET (POST) запросу. Что-то усложнили банальную задачу...

Спасибо, то что Вы написали с 1 по 12 строку у меня получается.

Задача передать данные с сайта ардуине, если на сайте нажали кнопку. Я может не сказал отдельно, весь сайт находится на удаленном хостинге, не в ардуине.

Еще раз: ардиуно собирает данные с датчиков и выключателей и передает их в бд сайта на хостинге. Там они отображаются и если на сайте происходит нажатие кнопки, то это нужно как-то передать обратно ардуине, чтобы оно включило выключатель.

Размещать весь сайт в ардуине не хочу по некоторым соображениям и т.к. не хватит памяти.

sadman41
Онлайн
Зарегистрирован: 19.10.2016

Это надо коннект постоянный с хостингом держать. Что-то тут было такое про вебсокеты Или через MQTT заворачивать.

sbm
Offline
Зарегистрирован: 06.05.2020

andycat пишет:
вот пример PHP откопал, если в параметре GET запроса пришло on то в обратку шлет текст " SetRelayOFF ~", скетч находит эту строку в ответной HTML страничке и выключает реле, ну и наоборот сотвественно.

а есть пример скетча, который ловит этот ответ, было бы здорово

sbm
Offline
Зарегистрирован: 06.05.2020

sadman41 пишет:
Это надо коннект постоянный с хостингом держать. Что-то тут было такое про вебсокеты Или через MQTT заворачивать.

то, что я хочу сделать было реализовано на шилде w5100 без MQTT в этой статье, моя задача сделать тоже самое, только на ENC68J60

sadman41
Онлайн
Зарегистрирован: 19.10.2016

И что там написано в статье?

Во второй раз советую - возьмите UIPEthernet. У нее синтаксис такой же, как у визнетовской библиотеки

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sbm, вы читали то что выше написано? Поняли? Мне кажется нет :(
Sadman41 прав, если нужна мгновенная реакция, то http не ваш вариант.
Если секунда, две задержки допустимо то берете алгоритм выше.
Нажимая на кнопку - записываете флаг в бд и в ответе php (пример выше) читаете значение из бд и выдаёте в МК.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

sbm пишет:

andycat пишет:
вот пример PHP откопал, если в параметре GET запроса пришло on то в обратку шлет текст " SetRelayOFF ~", скетч находит эту строку в ответной HTML страничке и выключает реле, ну и наоборот сотвественно.

а есть пример скетча, который ловит этот ответ, было бы здорово


Почитайте в конце концов html ответ в Википедии, тупо поиск подстроки.

sbm
Offline
Зарегистрирован: 06.05.2020

sadman41 пишет:
И что там написано в статье?

там данные датчиков отправляют отдельно и скрипт на php add_data их обрабатывает, а проверка нажатие кнопки отдельно в файле led.php:

    if (client.connect(server, 80)) 
{

    client.print( "GET /add_data.php?");
    client.print("temperature=");
    client.print( sensors.getTempCByIndex(0) );
    client.println( " HTTP/1.1");
    client.print( "Host: " );
    client.println(server);
    client.println( "Connection: close" );
    client.println();
    client.println();
   
    delay(200);
    
      while (client.available())
 {
      char c = client.read();
        if ( c=='1') buff=1;
        if ( c=='0') buff=0;
      } 
      client.stop();
      client.flush();
      delay(100); 
  }
  else 
  {
   client.stop();
   delay(1000);
   client.connect(server, 80);
  }

  if ( buff==1) digitalWrite (led1, HIGH);
  else digitalWrite(led1, LOW);

led.php:

<?php
		$S2 =  $_POST['status'];
	    $myFile2 = "../txt/out-1.txt";
		$fh2 = fopen($myFile2, 'w') or die("can't open file");
		fwrite($fh2, $S2);
		fclose($fh2);
        echo $S2;
?>

sadman41 пишет:
Во второй раз советую - возьмите UIPEthernet. У нее синтаксис такой же, как у визнетовской библиотеки

Спасибо, я изучаю примеры, которые Вы рекомендовали, чувствую будут вопросы)

sbm
Offline
Зарегистрирован: 06.05.2020

andycat пишет:
sbm, вы читали то что выше написано? Поняли? Мне кажется нет :( Sadman41 прав, если нужна мгновенная реакция, то http не ваш вариант. Если секунда, две задержки допустимо то берете алгоритм выше. Нажимая на кнопку - записываете флаг в бд и в ответе php (пример выше) читаете значение из бд и выдаёте в МК.

пару секунд задержки совсем не критично

тогда получается, что если при нажатии кнопки на сайте вызывается по post-запросу следующий скрипт

<?php
    if(@$_POST['t1']) $t1=$_POST['t1']+10;
    if(@$_POST['t2']) $t2=$_POST['t2']+20;
    echo "?t1=".$_POST['t1']."&t2=".$_POST['t2']
?>

ардуино следующим скетчем должно увидеть в ответ в reply "?t1=20&t2=35", так?

   stash.print("t1=10&t2=15");
     stash.save();
     Stash::prepare(PSTR("POST http://my.site/add_data.php HTTP/1.0" "\r\n"    // отправка запроса на сервер
                         "Host: www.my.site.cf \r\n"
                         "Content-Length: $D" "\r\n"
                         "Content-Type: application/x-www-form-urlencoded \r\n"
                         "\r\n"
                         "$H"),
          stash.size(), sd);
     session = ether.tcpSend();
    const char* reply = ether.tcpReply(session);

   if (reply != 0) {
     Serial.println("Got a response!");
     Serial.println(reply);
  }

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Ну нет :(
По нажатию кнопки записывается флаг в бд.
А МК ардуино каждую например секунду шлет get или post запрос, в ответ на который php шлёт в обратку МК нужные данные с зависимости от данных в бд.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Совершенно верно!

Добавьте в бд отдельную таблицу (если с файлами морочиться не хотите) и проверяйте статус.

Это даже в одной файле скрипта можно реализовать, если так сильно это хочется:

<?php
include('connect.php');

if ($_GET['mode'] && trim($_GET['mode']) == "putdunya") { // Если данные пришли с дуни и режим "занести в базу", то заносим их и возвращаем ОК или ERROR если ошибка
    $query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES (1, '.$_GET['data'].', "'.date("Y-m-d H-i-s").'", "");
    $result = mysqli_query($link, $query); // записали данные по температуре
    if ($result) {
       echo "OK";   // если все занесли
    } else {
       echo "ERROR"; // если внести данные не получилось
    }
} 
if ($_GET['mode'] && trim($_GET['mode']) == "getdunya") { // Если данные пришли с дуни и режим "получить данные в дуню", то проверяем были ли изменены данных с сайта
  
  // и если были, то отправляем их дуне в виде строки:
  echo $reply;
  // если изменений небыло, то шлем флаг "ничегонеделать"
  echo "nojob"; // этот флаг в дуне является маркером ничего не делать
  // и ОБЯЗАТЕЛЬНО сбрасываем флаг
} 

if ($_GET['mode'] && trim($_GET['mode']) == "putsite") { // если работаем с сайтом напрямую, то делаете что там Вам нужно по кнопке с сайта или как там у Вас?
// пусть останется Ваш текст (не вдавался в подробности о чем он:
 // ============== >
}?>

Соответственно сами GET-запросы поправить не забудьте. И слать такие запросы на удаленный web-хостинг чаще 1 раз в 10 секунд я бы не стал - сказываются задержки сети и задержки обработки самим web-хостингом.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

BOOM пишет:

<?php

   $query = 'INSERT INTO `data` (`id`, `data`, `time`, `prim`) VALUES (1, '.$_GET['data'].', "'.date("Y-m-d H-i-s").'", "");

У вас дыра в запросе, подверженная SQL injection. Данные, полученные с небезопасной стороны, надо хотя бы обернуть в mysql_escape_string ;)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Это не у меня, как Вы выразились, "дыра", а у ТС, я использовал его кусок кода для "наглядности".

Я бы все сделал через API.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

ТС, не пугайся уязвимостей, всегда можно VPN-построить и только по VPN данные отдавать, тогда и авторизации не нужно будет использовать (правда не на всех shared, но сейчас VPS не дороже стоит под такие задачи). Чего у тебя там получается то?