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

Тема в разделе "Arduino & Shields", создана пользователем SBM78, 6 май 2020.

Метки:
  1. SBM78

    SBM78 Нуб

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

    Подскажите, как отправить данные с веб-сервера ардуино?
    Ардуино подключен к интернету с помощью ENC28J60

    В библиотеке EtherCard за это отвечает tcpReply(), скетч выглядит так:
    Код (C++):
       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-код, обрабатывающий нажатие кнопки:
    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 надо как-то по-другому обрабатывать?
     
  2. b707

    b707 Гуру

    зачем вы превращаете reply в строку data. если потом ею не пользуетесь? Попробуйте выводить на печать data. может и получится.
    если нет - сначала проверьте. посылает ли сервер ответ. Тот PHP код. который вы цитируете - абсолютно не имеет отношения к ответу сервера.
     
    NikitOS нравится это.
  3. SBM78

    SBM78 Нуб

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

    я и чувствую...а как отправить ответ сервера ардуино?
    и непонятно почему тогда срабатывает reply!=0?
     
  4. NikitOS

    NikitOS Король шутов Администратор

    Не выглядит он так. Это кусок. Давайте весь.
    В каком месте там обработка кнопки? Я вижу только запросы к БД.
     
    b707 нравится это.
  5. SBM78

    SBM78 Нуб

    весь скетч:
    Код (C++):
    #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());
       }
    }
    }
    сам приведенный файл led.php является обработчиком кнопки из index.php
    HTML:
                <form  id="led" action="" method="post"  >
                  <div class="r3" id="content-3" onclick="AjaxFormRequest('messegeResult', 'led', 'transfer/led.php')" ></div>
                </form>
     
    при нажатии на кнопку вызывается led.php, там идет проверка состояния кнопки, меняется на противоположное, записывается обратно в базу и должно в конце послать запрос ардуино echo"v1=".$S2; но видать это неверно
     
  6. b707

    b707 Гуру

    echo"v1=".$S2; - это не запрос, это всего лишь печать строчки типа "v1=ON"
    Самого запроса, так же как управления кнопкой - в этом коде нет
     
    NikitOS нравится это.
  7. SBM78

    SBM78 Нуб

    файл index.php:
    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
    led.php:
    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;
    ?>
    как тогда отправить запрос ардуино?
     
  8. b707

    b707 Гуру

    чем дальше, тем меньше понимаю.
    Кнопку-то вы где нажимаете? На ардуино?

    Поправка. кнопку нашел.
    Но понятнее не стало.
     
    Последнее редактирование: 6 май 2020
  9. SBM78

    SBM78 Нуб

    нет, на сервере (на сайте) - файл index.php
    и при нажатии кнопки на сервере, ардуино должно что-то включить, получив запрос с сервера
    т.е. отправить данные на сервер (сайт) у меня получается, а обратно с сайта в ардиуно ответ получить нет
     
  10. b707

    b707 Гуру

    сорри, дальше вряд ли помогу. Могу только повторить совет подключится к серверу обычным браузером и убедится. что он хоть что-то возвращает
     
    NikitOS нравится это.
  11. SBM78

    SBM78 Нуб

    Ну подскажите, пожалуйста, а принимаю я ответ сервера правильно?

    Код (C++):
    const char* reply = ether.tcpReply(session);

       if (reply != 0) {
         Serial.println(F(" >>>REPLY recieved...."));
         Serial.println(reply);
       }
    при том, что сервер возвращает данные, указанный код должен их выводить в сериал порт?
     
  12. b707

    b707 Гуру

    вам на ардуино.ру правильный вопрос задали. Вы из ардуины посылаете запрос совсем к другому файлу - не к index.php и не к led.php. а какому-то add_data.php. . Вот именно этот файл и надо изуячать в первую очередь
     
    NikitOS нравится это.
  13. SBM78

    SBM78 Нуб

    да, я там объяснил, что add_data.php принимает данные с датчиков, это у меня хорошо получается, по этому вопросов нет.
    но когда я на сайте нажимаю кнопку, которая обрабатывается led.php, на сайте состояние кнопки меняется, но как послать ответ ардуино и как его принять, я не знаю и прошу в этом помощи
     
  14. b707

    b707 Гуру

    никак

    Ардуине нельзя послать никаких данных, для этого сервером должна быть ардуина, а не ПК.
    Единственный вариант - это хранить состояние кнопки на сервере в виде какой-то строчки и периодически запрашивать его с ардуино.
    Для этого нужно написать отдельный скрипт на сервере. который отдавал бы состояние кнопки. а в коде на ардуино сформировать к этому скрипту полноценный запрос по типу того. что у вас обращается к add_data.php - и вот от этого-то нового запроса и получать ответ.

    а сейчас вы в коде делаете ерунду - посылаете запрос к одному скрипту, а ждете ответ совсем от другого, так не заработает
     
  15. SBM78

    SBM78 Нуб

    да, отлично, я кажется понял свою ошибку, буду пробовать ее исправить, спасибо
     
  16. SBM78

    SBM78 Нуб

    я исправил скетч, теперь и датчики и кнопку обрабатывает один файл add_data.php
    скетч:
    Код (C++):
    #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 <a href="http://my.site/add_data.php" title="http://my.site/add_data.php" rel="nofollow">http://my.site/add_data.php</a> HTTP/1.0" "\r\n"    // отправка запроса на сервер
                             "Host: <a href="http://www.my.site" title="www.my.site" rel="nofollow">www.my.site</a> \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:
    <?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