Arduino+php+MySQL = дурдом

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

День добрый, уважаемые!

У меня снова глупый вопрос. Гугл с Яндексом уже откровенно меня посылают, поэтому обращаюсь к вам :)

Имеется: Arduino UNO / NANO (китайские аналоги), DHT11 (или любой другой датчик), ethernet-модуль, удалённый web-сервер с Apache + php 5.3 + MySQL.

Требуется: данные с датчика записывать в БД на удалённом сервере.

Проблема: как передать данные от Ардуинки в базу с помощью GET или POST запроса?

Собственно, с php и mysql я знаком и кое-что там понимаю, а вот с ардуино... Выводить данные на страницу в своей же сети и включать/выключать светодиоды на ней плюс получать данные от датчиков у меня получилось (как здесь). Перепробовал разные примеры отправки данных - ничего не получается.

Нафига это всё надо: собрал я себе дома небольшую метеостанцию. Очень хочется с неё данные видеть на своём сайте, а не только дома. Плюс сюда потом хочу ещё всякого добавить, но без вывода на сайт это всё бесполезно будет :(

Помогите, пожалуйста! Хотя бы, ткните носом в пример работающий, где бы подробно было всё расписано, а не как во многих местах: "тут всё просто, это пропустим" :(

twsdwf
Offline
Зарегистрирован: 25.03.2015

Вам в описание протокола http надо бы.

В простейшем варианте будет GET-запрос в формате:

GET /logger.php?temp=value&param1=val1&param2=val2 HTTP/1.1

Host: sitename.ru

Connection: close

Эти три строки запихиваем в строку-буфер, который запихиваем потом при общении в ethernet модуль на отправку(сам не работал с такими модулями, но по работе сайтов много делаю). Переносы строк через \r\n и в конце должен быть двойной перенос строки. Строчку с параметрами склеиваем через тот же sprintf() но следим за размером буфера, лучше брать с запасом.с числами проблем не будет, со строками - надо перекодировать пробелы в %20 и избегать спецсимволов <>&?= на вебсервере в logger.php все переменные попадут в $_GET, получаем их оттуда. sitename.ru --доменное имя вашего сайта.

предполагаю, что по http://sitename.ru/logger.php скриптик сохранения данных доступен через браузер.

Как-то так.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Посмотрите стандартный пример "web-client".

На сервере должен быть php-скрипт, который обслудивает запросы от ардуино.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Уточню ещё разок: я ЗНАЮ, как формируется GET запрос. Благо уже не один сайт сделал, где приходилось его формировать :) А вот чего я НЕ ЗНАЮ, так это как в скетче этот запрос передавать удалённому серверу.

На сервере у меня лежит файлик test.php, который принимает GET-запрос и распихивает данные из него по базе.

Мне бы кусочек скетча, отвечающий за это...

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Я попробовал два примера webClient'а. Один от библиотеки Ethernet, второй от EtherCard. Первый не компилится, выдавая кучу ошибок. Второй выводит инфу в монитор порта, проверяя доступность указанного сайта. И всё.

На сервере всё есть: и скриптик, и база. Нет скетча, передающего данные на сервер :(

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

первый - для w5100

с ENC28J60 я не люблю работать - он кастрированный. Для него у меня нет готового кода.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Эх, попробую подробнее описать.

Есть скетч небольшой погодной станции, который отлично работает на имеющихся у меня UNO и NANO:

#include <stdio.h>
#include <DS1302.h>

namespace {

// Set the appropriate digital I/O pin connections. These are the pin
// assignments for the Arduino as well for as the DS1302 chip. See the DS1302
// datasheet:
//
//   http://datasheets.maximintegrated.com/en/ds/DS1302.pdf

//DS1302 pins
const int kCePin   = 10;  // Chip Enable (RST)
const int kIoPin   = 9;  // Input/Output (DA)
const int kSclkPin = 8;  // Serial Clock (CLK)

//LCD pins
//RST - 6
//CE - 7
//DC - 5
//Din - 4
//Clk - 3


// Create a DS1302 object.
DS1302 rtc(kCePin, kIoPin, kSclkPin);

String dayAsString(const Time::Day day) {
  switch (day) {
    case Time::kSunday: return "Вс";
    case Time::kMonday: return "Пн";
    case Time::kTuesday: return "Вт";
    case Time::kWednesday: return "Ср";
    case Time::kThursday: return "Чт";
    case Time::kFriday: return "Пт";
    case Time::kSaturday: return "Сб";
  }
  return "(unknown day)";
}
}  // namespace

#include <PCD8544.h>
static PCD8544 lcd;

#include "DHT.h"

#define DHTPIN 13
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

float tempOut;
int tOut;
int tempOutPin = 7; // пин подключения LM35DZ

void setup() {
  Serial.begin(9600);
  dht.begin();
  lcd.begin(84, 48);
  //раскомментить, чтобы задать время!

//  rtc.writeProtect(false);
//  rtc.halt(false);
    // Sunday, September 22, 2013 at 01:38:50.
//  Time t(2015, 3, 18, 20, 54, 50, Time::kWednesday);

    // Set the time and date on the chip.
//  rtc.time(t);
  lcd.setCursor(0,0);
  lcd.print("Подождите,");
  lcd.setCursor(0,1);
  lcd.print("включаюсь!");
}

void loop() {
      // Get the current time and date from the chip.
  Time t = rtc.time();

  // Name the day of the week.
  const String day = dayAsString(t.day);

  // Format the time and date and insert into the temporary buffer.
  char buf[50];
  snprintf(buf, sizeof(buf), "%s %02d.%02d.%04d %02d:%02d:%02d      ",
           day.c_str(),
           t.date, t.mon, t.yr,
           t.hr, t.min, t.sec);
  if (fmod(t.min,10) == 0 && t.sec == 0) {
   lcd.clear(); 
  }
  if (fmod(t.sec,10) == 0) {
    int h = dht.readHumidity();
    int t = dht.readTemperature();
    tempOut = analogRead(tempOutPin);
    tempOut = tempOut * 0.48828125;
    tOut = (int) tempOut;
    if (isnan(t) || isnan(h)) {
      Serial.println("Failed to read from DHT");
      lcd.setCursor(0, 0);
      lcd.print("Failed to read from DHT");
    } else {
      lcd.setCursor(0, 0);
      lcd.print("Темп-ра Дом/Ул");
      lcd.setCursor(0, 1);
      if (t < 10) {
        lcd.print(t);
        lcd.print(" ");
      } else {
         lcd.print(t); 
        }
      lcd.setCursor(12, 1);
      lcd.print(" / ");
      if (tempOut < 10) {
        lcd.print(tOut);
        lcd.print(" ");
      } else {
         lcd.print(tOut);
        }
      lcd.print(" *C");
      lcd.setCursor(0, 2);
      lcd.print("Влажность ");
      lcd.setCursor(0, 3);
      lcd.print(h);
      lcd.setCursor(12, 3);
      lcd.print("%");
      lcd.setCursor(24, 3);
        if (h < 40) {
          lcd.print("- сухо\t");
        } else if (h > 60) {
          lcd.print("- мокро\t");
        } else {
          lcd.print("- норма\t"); 
        }
/*    Serial.print("Humidity: "); 
    Serial.print(h);
    Serial.print(" %\t");
    Serial.print("Temperature: "); 
    Serial.print(t);
    Serial.println(" *C");
    Serial.print("TEMPRATURE = ");
  Serial.print(tempOut);
  Serial.print("*C");
  Serial.println();
*/
    }
  }
  // Print the formatted string to serial so we can see the time.
  Serial.println(buf);
  lcd.setCursor(0, 4);
  lcd.print(buf);
}

На сервере лежит файлик test.php, отвечающий за приём данных и запихивание их в базу:

<?php
//адрес хоста
$dbhost = 'localhost';
//Имя пользовтаеля
$dbuser = 'user"';
//пароль для подключения к Mysql
$dbpass = 'pass';
//имя базы данных
$dbname = 'arduino';
// сохраняем IP на всякий случай
$client_ip = $_SERVER['REMOTE_ADDR'];
// получение значения переменной температура
$temp = $_GET["t"];
// получение значения влажность
$hum = $_GET["h"];

//устанавливаем подключение к MySQL
$connect = mysql_connect($dbhost, $dbuser, $dbpass);
// проверяем состояние подключения
if(! $connect )
{
  die('Could not connect: ' . mysql_error());
}
// Выбираем базу данных
mysql_select_db ($dbname, $connect);

//Отправляем данные в таблицу
$sql = "INSERT INTO sensor_data SET date_time = NOW(), sensor_temp = '$temp', sensor_humidity = '$hum', client_ip = '$client_ip'";

// проверяем состояние отправки
if(!mysql_query($sql))
{echo '<p><b>Data upload error!</b></p>';}
else
{echo '<p><b>OK</b></p>';}
// закрываем соединение с базой
mysql_close($connect);
?>

При вводе на сайте строки вида http://mysite.ru/test.php?t=23&h=35 в базу пишется id записи, дата и время записи, температура (23) и влажность (35).

Вопрос: что надо добавить в скетч, чтобы ардуинка могла передавать данные на удалённый сервак? :)

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Это я уже понял. Но w5100 нет под рукой, а ждать месяц, пока оно приедет, как-то не хочется.

RomAndry
RomAndry аватар
Offline
Зарегистрирован: 20.02.2014

да такой же, как и стандартный вывод, после коннекта

if(yourEth.connect(ADDR, PORT)) {
  yourEth.print("POST /log.php HTTP/1.1");
  и т.д. заголовки, согласно правил HTTP не забывая о переводах и концах строк.
  можно использовать println где надо.
  и в конце 
  yourEth.print("foo=23&bar=44");
}

ну и смотрите апачевский (или своего сервера лог)

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

RomAndry пишет:

да такой же, как и стандартный вывод, после коннекта

Блин. Спасибо, конечно, за ответ. Но я же не зря спрашивал подробного кусочка кода запроса :) "Стандартный", "можно использовать" - для меня это равносильно фразам: "заливаем фундамент, потом быстренько строим дом и вот тут в центре комнаты вешаем красивую люстру". А как залить фундамент? Как построить дом?! :)

"yourEth.print" - это в смысле ether.print? Так в примере к библиотеке EtherCard, с которой у меня хоть что-то получается, нигде нет ничего похожего, кроме

ether.printIp("My SET IP: ", ether.myip); // Выводим в Serial монитор статический IP адрес.

Если не трудно, можете написать или дать ссылку на подробный пример, где бы был именно кусок кода, формирующий и передающий запрос серверу? Без "стандартный" и "и т.д.". Как для полного дауна, который пытается постичь дзен, но без конкретного примера нифига не может сделать.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Эх. То ли я дурак, то ли лыжи не едут. Перепробовал кучу примеров - не получается ничего с GET-запросом :(

RomAndry
RomAndry аватар
Offline
Зарегистрирован: 20.02.2014

давайте попробуем разобрать Ваш скетч (часть кода или метод отвечающий за отправку)
я недавно делал прием отправку данных (эмуляция dDNS), но правда на W5100, но думаю примерно аналогично должно быть и для модуля.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Мой скетч и файлик на сервере приведены чуть выше. Мне бы просто получить строчку кода, которая будет отправлять GET запрос на удалённый сервер вида sitename.ru/test.php?t=XX&h=YY. Переджелать его под передачу других данных я уже сам смогу, наверное :)

Только данные должны отправляться автоматически, например, раз в 5 минут. Без необходимости обновления страницы каждый раз для этого.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Первая ссылка в поисковике... именно под ваш адаптер ну а переписать ссылку с народмона на свой сервак думаю не сложно.

http://imarh.ru/content/%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-arduino-pro-mini-enc28j60-dht11-ds18b20-%D0%BA-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%83-narodmonru

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Ну или идём на гитхаб и смотрим примеры использования библиотеки под ENC28J60, там всё есть.

https://github.com/jcw/ethercard/blob/master/examples/webClient/webClient.ino

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Penni пишет:

Ну или идём на гитхаб и смотрим примеры использования библиотеки под ENC28J60, там всё есть.

https://github.com/jcw/ethercard/blob/master/examples/webClient/webClient.ino

Видел я этот пример. Пробовал. Ткните, пожалуйста, пальцем в строчку, где там формируется GET-запрос к удалённому сайту. Я что-то не разглядел этого.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Спасибо, буду изучать. У меня такой ссылки не было. Видимо, мы по-разному запросы поисковые формировали.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Penni пишет:

Первая ссылка в поисковике... именно под ваш адаптер ну а переписать ссылку с народмона на свой сервак думаю не сложно.

http://imarh.ru/content/%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-arduino-pro-mini-enc28j60-dht11-ds18b20-%D0%BA-%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%83-narodmonru

Попробовал этот пример. Не получается всё равно ничего :( Вроде всё переделал, но в сериал-мониторе только выводится 5 строчек

Start!
My IP: 192.168.2.222
GW IP: 192.168.2.1
DNS IP: 93.204.136.6
Server: 93.81.252.64

и дальше тишина.

Мой скетч:

#include <OneWire.h>
#include <DallasTemperature.h>
#include <EtherCard.h>

#define ONE_WIRE_BUS 2                             // Data wire is plugged into digital pin 3 on the Arduino
#define NumberOfDevices 1                          // Set maximum number of devices in order to dimension

#define REQUEST_RATE 300000 // milliseconds

static byte mac[] = { 0x99, 0x98, 0x97, 0x96, 0x95, 0x94 }; //В этой строке задайте свой MAC адрес
static byte hisip[] = { 93,81,252,64,80 };
static byte myip[] = { 192,168,2,222 };
static byte gwip[] = { 192,168,2,1 };

OneWire oneWire(ONE_WIRE_BUS);                     // Setup a oneWire instance to communicate with any OneWire devices

DallasTemperature sensors(&oneWire);               // Pass our oneWire reference to Dallas Temperature.

byte allAddress [NumberOfDevices][1];              // Device Addresses are 8-element byte arrays.
                                                   // we need one for each of our DS18B20 sensors.

byte totalDevices;                                 // Declare variable to store number of One Wire devices
                                                   // that are actually discovered.
float tempC = 0;

byte discoverOneWireDevices() {
  byte j=0;                                        // search for one wire devices and
                                                   // copy to device address arrays.
  while ((j < NumberOfDevices) && (oneWire.search(allAddress[j]))) {        
    j++;
  }
   return j;                 // return total number of devices found.
}
String macstring;
String DSstring[NumberOfDevices];
byte Ethernet::buffer[700];
static long timer;
Stash stash;  

void setup() {
  Serial.begin(57600);
  Serial.println("Start!");
  delay(1000);

  if (ether.begin(sizeof Ethernet::buffer, mac, SS) == 0)
    Serial.println( "Failed to access Ethernet controller");
    ether.staticSetup(myip);
    ether.setGwIp(gwip);
  //overwrite DNS with google's if there are problems with DNS setup
  static byte dnsip[] = {93,204,136,6};
  ether.copyIp(ether.dnsip, dnsip);
  
  ether.printIp("My IP: ", ether.myip);
  ether.printIp("GW IP: ", ether.gwip);
  ether.printIp("DNS IP: ", ether.dnsip);

  ether.copyIp(ether.hisip, hisip);
  ether.printIp("Server: ", ether.hisip);

  while (ether.clientWaitingGw())
    ether.packetLoop(ether.packetReceive());
  Serial.println("Gateway found");

  macstring="";
  for(int k=0;k<sizeof(mac)/sizeof(byte);k++)
  {
        char msg[3];
        sprintf(msg,"%02X",mac[k]);
        //if (macstring!="#") macstring+="-";
        macstring+=msg;
  }

  sensors.begin();
  totalDevices = discoverOneWireDevices();
  for (byte i=0; i < totalDevices; i++)
  {
    DSstring[i]="";
    for(int k=7;k>=0;k--)
    {
          char msg[3];
          sprintf(msg,"%02X",allAddress[i][k]);
          DSstring[i]+=msg;
    };
   
    sensors.setResolution(allAddress[i], 10);      // and set the a to d conversion resolution of each.
  }
 
  timer = - REQUEST_RATE; // start timing out right away
}

void loop() {
 
  ether.packetLoop(ether.packetReceive());
 
  if (millis() > timer + REQUEST_RATE)
  {
    timer = millis();

    byte sd = stash.create();
    stash.print("ID=");
    stash.print(macstring);

    Serial.println("\n\n\nPosting...\n");
    
    sensors.requestTemperatures();                // Initiate  temperature request to all devices
    String result;
    char msg[50];
    result=macstring+"\n";
    String temp;
    for (byte i=0; i < totalDevices; i++) {
      tempC = sensors.getTempC(allAddress[i]);           // read the device at addr.
      if (tempC != -127.00)
      {
        //dtostrf(tempC,10,2,msg);
        stash.print("&");
        stash.print(DSstring[i]);
        stash.print("=");
        stash.print(tempC);
      }
    }
  
    stash.save();

    // generate the header with payload - note that the stash size is used,
    // and that a "stash descriptor" is passed in as argument using "$H"
    Stash::prepare(PSTR("GET http://test.alninyo.ru/test.php?t=$D HTTP/1.0" "\r\n"
                        "Host: test.alninyo.ru.ru" "\r\n"
                        "Content-Length: $D" "\r\n"
                        "\r\n"
                        "$H"),tempC,
                  stash.size(), sd);

    // send the packet - this also releases all stash buffers once done
    ether.tcpSend();

    Serial.println("Done");
  }
}

 

zhenious
Offline
Зарегистрирован: 03.07.2014

Чтобы выполнять внешние запросы вам нужен веб-клиент на ардуино http://arduino.cc/en/Tutorial/WebClient

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

zhenious пишет:

Чтобы выполнять внешние запросы вам нужен веб-клиент на ардуино http://arduino.cc/en/Tutorial/WebClient

В том-то и дело, что мне не нужно выполнять внешние запросы на Ардуино! Мне надо, чтобы Ардуинка отправляла на удалённый сервер показания датчиков, и чтобы эти показания заносились в базу. Всё!

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Al_Ninyo пишет:

zhenious пишет:

Чтобы выполнять внешние запросы вам нужен веб-клиент на ардуино http://arduino.cc/en/Tutorial/WebClient

В том-то и дело, что мне не нужно выполнять внешние запросы на Ардуино! Мне надо, чтобы Ардуинка отправляла на удалённый сервер показания датчиков, и чтобы эти показания заносились в базу. Всё!

Вы ошибаетесь. Вам нужен именно веб-клиент который будет отправлять GET-запрос на ваш сервер.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Gippopotam пишет:

Вы ошибаетесь. Вам нужен именно веб-клиент который будет отправлять GET-запрос на ваш сервер.

Ок. Я ошибаюсь. Я запускал этот пример с клиентом и получил облом, т.к. он под модуль W5100, а у меня не он (о чём я уже не раз тут писал!). Я запускал другой пример, в котором, тыкая ссылки на странице, можно зажигать светодиоды, подключённые к ардуинке и смотреть, на этой же странице, показания датчиков. Но, хоть убейте, я не понимаю, как заставить Ардуинку эти данные передать в виде GET запроса моему серваку, который уже заждался их! Именно поэтому я здесь пишу, в надежде на помощь. Но, видимо, нифига не получится у меня. Всем проще сказать "вон пример, учись" и пофиг, что в примере нет ничего по моему вопросу, чем тупо поделиться нужными строчками кода...

Простите, накипело :(

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Al_Ninyo, вы извините, что даю вам не сильно конкретные советы, просто я исходил из предположения (судя по первому посту), что вы что-то умеете.

Модуль w5100, у меня практически всегда в работе, а ENC28J60 я вспоминаю, как страшный сон. Чтобы дать вам конкретный совет, мне нужно (1) откопать у себя в ящике этот модуль, (2) заставить его работать, (3) написать скетч и выложить его здесь. Если бы не пункт (2) - я бы вам уже давно помог.

Вот посмотрите у Осипова - он этот модуль любит...

https://www.youtube.com/watch?v=PPB2Xvubt4s

https://www.youtube.com/watch?v=e9qeCrK85Fs

https://www.youtube.com/watch?v=Dg78YB3i1Vc

 

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Уважаемый Gippopotam!

Я в первом посте примерно написал, что умею :) Видео эти видел, светодиодами по этим примерам со страницы локальной управлял. Пробовал сделать GET-запрос, в том числе, вот так:

bfill.emit_p(PSTR("GET mysite.ru/test.php?t="),temp,PSTR("&h="),vlajnost,PSTR(" HTTP/1.0"));

Нифига не получилось. К сожалению, мои познания о программировании Ардуино ещё очень слабые. Я уже кое-что могу сделать, переработав имеющиеся примеры, но, если не вижу конкретного примера, то "додумать" мне пока сложновато.

Про "w5100 vs ENC28J60" я уже понял. К сожалению, пока нормального модуля под рукой нет и когда будет - неизвестно. Придётся ждать прихода wi-fi модулей и пробовать то же самое с ними сделать, видимо :(

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014
Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Gippopotam пишет:

Приятно быть уважаемым!

:)

Вот за эти ссылки - огромное спасибо! В конце странице по второй ссылке нашёл чудесный линк: http://www.tweaking4all.com/hardware/arduino/arduino-ethernet-data-push/. Пока не пробовал сильно разбираться, но, вроде бы, похоже на нужное! Как опробую - отпишусь. Спасибо!

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Так. Всем привет. У меня новый дурдом :)

Пришли на днях ESP8266-01. Подключил к ардуинке, GET-запрос на удалённый сервер передал - работает, из запроса данные в базу записались. НО! Как теперь в это запрос вставить данные от датчиков? Бьюсь уже 2 часа и ничего не получается.

Есть кусок кода, в котором формируется нужный запрос:

wifi.Send("GET httр://test.mysite.ru/test.php?t=22&h=33 HTTP/1.0\r\n\r\n");

В таком виде на удалённый сервак в базу заносятся данные: температура = 22, влажность = 33.

Чуть раньше есть получение данных с DHT11:

int h = dht.readHumidity();
int t = dht.readTemperature();

Как мне теперь данные от датчика (которые t и h) воткнуть в GET-запрос вместо "22" и "33" соответственно? Помогите идиоту, пожалуйста :( Я очень мало в программировании понимаю, но очень хочется научиться!

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Всё же я не безнадёжен :) Решена проблема вот таким кодом:

String getRequest = "GET httр://test.mysite.ru/test.php?t=";
    getRequest+= t;
    getRequest+= "&h=";
    getRequest+= h;
    getRequest+= " HTTP/1.0\r\n\r\n";

Сам запрос потом отправляется так:

wifi.Send(getRequest);

Всем спасибо, все свободны :)

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Хм. Теперь новая проблема. 1-2 раза коннект к удалённому серверу проходит нормально и данные в базу заносятся, а потом начинается веселье в виде:

AT+CIPCLOSE
AT+CIPMUX=0
AT+CIPSTART="TCP","xx.xx.xx.xx",80
connection failed
disconnecting.

 

Иногда проскакивает, что коннект вроде как произошёл, но данные в базу не заносятся. Нажму reset на Ардуинке - в базу снова попадает 1-2 значения и опять постоянные ошибки. На серваке в логах никаких ошибок нет. Подскажите, куда копать-то?

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

Сам запрос потом отправляется так:

wifi.Send(getRequest);

ого как эзернет модуль подрос до wi-fi. это где к нему такие драйвера скачать?

 

Al_Ninyo пишет:

Всем спасибо, все свободны :)

дык мы всегда свободны

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Puhlyaviy пишет:

ого как эзернет модуль подрос до wi-fi. это где к нему такие драйвера скачать?

Я же написал, что пришли wi-fi-модули и с ними теперь мучаюсь.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

 Я же написал, что пришли wi-fi-модули и с ними теперь мучаюсь.

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

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

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Простите, намёк понял :) Использую адскую смесь из стандартного примера webclientRepeating библиотеки ESP8266 со стандартным же примером получения данных от DHT11.

/*
ESP8266 library

When you use with UNO board, uncomment the follow line in uartWIFI.h.
#define UNO

When you use with MEGA board, uncomment the follow line in uartWIFI.h.
#define MEGA

Connection:
When you use it with UNO board, the connection should be like these:
ESP8266_TX->D0
ESP8266_RX->D1
ESP8266_CH_PD->3.3V
ESP8266_VCC->3.3V
ESP8266_GND->GND

FTDI_RX->D3			//The baud rate of software serial can't be higher that 19200, so we use software serial as a debug port
FTDI_TX->D2

When you use it with MEGA board, the connection should be like these:
ESP8266_TX->RX1(D19)
ESP8266_RX->TX1(D18)
ESP8266_CH_PD->3.3V
ESP8266_VCC->3.3V
ESP8266_GND->GND

When you want to output the debug information, please use DebugSerial. For example,

DebugSerial.println("hello");


Note:	The size of message from ESP8266 is too big for arduino sometimes, so the library can't receive the whole buffer because  
the size of the hardware serial buffer which is defined in HardwareSerial.h is too small.

Open the file from \arduino\hardware\arduino\avr\cores\arduino\HardwareSerial.h.
See the follow line in the HardwareSerial.h file.

#define SERIAL_BUFFER_SIZE 64

The default size of the buffer is 64. Change it into a bigger number, like 256 or more.

*/


#define SSID       "HOME"
#define PASSWORD   "xxxxxxxxx"

//#define server      "xx.xx.xx.xx"    //test.mysite1.ru
#define server      "yy.yy.yy.yy"    //test.mysite2.ru

#include "uartWIFI.h"
#include <SoftwareSerial.h>
WIFI wifi;

#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11   // DHT 11
DHT dht(DHTPIN, DHTTYPE);

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000;  // delay between updates, in milliseconds

void setup()
{
  Serial.begin(9600);
  dht.begin();
  wifi.begin();
  bool b = wifi.Initialize(STA, SSID, PASSWORD);
  if(!b)
  {
    Serial.println("Init error");
    
  }
  delay(8000);  
  String ipstring  = wifi.showIP();

  Serial.println(ipstring);
  
  pinMode(13,OUTPUT);
}
void loop()
{
  int h = dht.readHumidity();
  int t = dht.readTemperature();
  
 // String getRequest = "GET http://test.mysite1.ru/test.php?t=";
  String getRequest = "GET http://tes.tmysite2.ru/test.php?t=";
    getRequest+= t;
    getRequest+= "&h=";
    getRequest+= h;
    getRequest+= "&c=anna";
    getRequest+= " HTTP/1.0\r\n\r\n";
       
  char message[320];
   // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if((millis() - lastConnectionTime > postingInterval)) {
//    httpRequest();
    
    // if there's a successful connection:
  if (wifi.ipConfig(TCP,server, 80)) {
    Serial.println("connecting...");
        
    // send the HTTP PUT request:
    
    //wifi.Send("GET / HTTP/1.0\r\n\r\n");
    wifi.Send(getRequest);
    Serial.println(getRequest);
    // note the time that the connection was made:
    lastConnectionTime = millis();
  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    wifi.closeMux();
  }
    
  } 
  
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if(wifi.ReceiveMessage(message)) 
  {
      Serial.println(message);   
  }

  delay(10);
}

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

вот вы мне реально скажите, у вас что там каждые 10 секунд температура меняется?  просто прям колбасит от минус 270 до плюс 5000?

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Puhlyaviy пишет:

вот вы мне реально скажите, у вас что там каждые 10 секунд температура меняется?  просто прям колбасит от минус 270 до плюс 5000?

Вы предлагаете в процессе отладки ждать 30 минут отсылки новых значений? Конечно же, если это всё заработает, я буду отсылать данные раз в 30 минут/час :)

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

Вы предлагаете в процессе отладки ждать 30 минут отсылки новых значений? Конечно же, если это всё заработает, я буду отсылать данные раз в 30 минут/час :)

а не посещала мысль что если температура не изменилась больше чем на полградуса, то вообще нет смысла что то куда то посылать?

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Поверьте, если оно начнёт нормально отсылать данные на сервак и записывать их в базу, я начну усиленно думать, как это оптимизировать. В том числе, подумаю о не отсылании данных при остутствии измененийв полградуса. Честно. Но сейчас мне надо это заставить работать! Т.е., мне надо видеть, что данные отправляются на сервер и пишутся в базу. Всё остальное - позже.

Когда вы пишете код, вы тоже сразу пишете с реальными таймерами и условиям? Даже когда данные у вас раз в сутки отправляются? И реально ждёте сутки, чтобы увидеть "облом" и потом начинаете копать код? :)

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

Поверьте, если оно начнёт нормально отсылать данные на сервак и записывать их в базу, я начну усиленно думать, как это оптимизировать. В том числе, подумаю о не отсылании данных при остутствии измененийв полградуса. Честно. Но сейчас мне надо это заставить работать! Т.е., мне надо видеть, что данные отправляются на сервер и пишутся в базу. Всё остальное - позже.

Когда вы пишете код, вы тоже сразу пишете с реальными таймерами и условиям? Даже когда данные у вас раз в сутки отправляются? И реально ждёте сутки, чтобы увидеть "облом" и потом начинаете копать код? :)

гыыыы спасибо поржал... давайте подумаем ( это значит нужно напрячь то место на котором шапку носите)

ардуина конектится и честно отсылает какое то количество посылок.. а потом сервер перестает ей отвечать... причем тут ардуино?

maksim
Offline
Зарегистрирован: 12.02.2012

Попробуйте конект закрывать после ответа сервера

  if(wifi.ReceiveMessage(message))
  {
      Serial.println(message);
      wifi.closeMux();  
  }

 

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Puhlyaviy пишет:

гыыыы спасибо поржал... давайте подумаем ( это значит нужно напрячь то место на котором шапку носите)

ардуина конектится и честно отсылает какое то количество посылок.. а потом сервер перестает ей отвечать... причем тут ардуино?

А я не ношу шапку :)

Есть 2 сервака: один стоит под столом у моего московского друга и на нём крутится Апач+МуСКЛ+ПХП, кучка сайтов и ещё дофига всего; второй - РуЦентровский с ещё одним моим сайтом (хостинг nic.ru). С разными настройками, но ведут себя почти одинаково. Точнее, ник.ру вообще себя по-свински ведёт :( Не заносит ардуинка данные в базу там, хотя при правильном обращении к скрипту на сервере (через браузер) данные в базу исправно заходят и ардуинка в мониторе порта пишет периодически, что коннект прошёл успешно.

Попробую поставить отсылку раз в 20 секунд, что ли. И снова попробую на сервак друга посылать данные. Там хоть через раз, но заносилось в базу.

А не может оказаться проблемы в ESP8266? А то как-то не всегда с первого раза в монитор порта данные начинают идти. Иногда несколько раз надо нажать на ардуинке Reset, прежде чем дело сдвинется дальше команды AT+RST.

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

А я не ношу шапку :)

видимо в этом и проблема...

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

Я честно говоря подозреваю что ESP8266 настолько кривая что работает через раз и только в четверг. Но большинство народа которые ей пользуются закрывают на это глаза и тихонько об этом молчат :)

я бы попробовал отсылать раз в 2-3 минуты. вполне достаточно что бы посмотреть.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

maksim пишет:

Попробуйте конект закрывать после ответа сервера

  if(wifi.ReceiveMessage(message))
  {
      Serial.println(message);
      wifi.closeMux();  
  }

 

Попробовал. 1 раз данные в базу попали и тишина. Причём, после рестарта ардуинки всё та же тишина, хотя коннект вроде проходит.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

То, что я - идиот, мною и не скрывается никогда особо, если что :)

А на тему "медленная и кривая"... Что-то мне не везёт :( Купил ethernet-модуль, он УГ оказался. Почитал хвалебные статьи про ESP8266, а оно тоже вон как оказывается. Что же делать-то теперь? У меня их теперь 4 штуки есть и надо как-то использовать.

Попробую раз в 3 минуты отсылать. С 30-ю секундами пока разницы никакой.

Спасибо за ваше терпение!

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

 Почитал хвалебные статьи про ESP8266, а оно тоже вон как оказывается. Что же делать-то теперь? У меня их теперь 4 штуки есть и надо как-то использовать.

Меркетинг он такой маркетинг... 4 штуки=20 баксов... прибей их к стенке если что или подари пионерам в школу, они будут рады.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Puhlyaviy пишет:

Меркетинг он такой маркетинг... 4 штуки=20 баксов... прибей их к стенке если что или подари пионерам в школу, они будут рады.

Для учителя, коим я являюсь, 20 баксов не лишние. Меня жена рядом с этими модулями прибьёт к стенке, благо работает чуть ли не в соседнем кабинете :)

А "пионЭры" пока и так рады, потому что я с ними начал с ардуинкой разбираться немного :)

Т.е. ничего не получится с моей затеей, что ли? Сейчас поставил отправку раз в 2 минуты. Первый коннект через эти самые 2 минуты - failed. Следующий, вроде как, прошёл, но в базе пусто :(

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

Puhlyaviy пишет:

Меркетинг он такой маркетинг... 4 штуки=20 баксов... прибей их к стенке если что или подари пионерам в школу, они будут рады.

Для учителя, коим я являюсь, 20 баксов не лишние. Меня жена рядом с этими модулями прибьёт к стенке, благо работает чуть ли не в соседнем кабинете :)

А "пионЭры" пока и так рады, потому что я с ними начал с ардуинкой разбираться немного :)

Т.е. ничего не получится с моей затеей, что ли? Сейчас поставил отправку раз в 2 минуты. Первый коннект через эти самые 2 минуты - failed. Следующий, вроде как, прошёл, но в базе пусто :(

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

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Эх... Оставлю на ночь ардуинку работать. Утром посмотрим, чего наработает. Ещё раз спасибо за терпение.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

Грррррр. Чувствую себя идиотом полным :( Загрузил скетч не в Arduino IDE 1.6.3, а в версии 1.0.6 - всё работает, блин! Данные в базу раз в 2 минуты пишутся, коннект проходит, сообщений в мониторе порта стало как-то больше... Ну вот как так-то?! :(

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Al_Ninyo пишет:

 Ну вот как так-то?! :(

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

inspiritus
Offline
Зарегистрирован: 17.12.2012

На арде клиент, на сервере пхп скрипт запускается кроном, обращается к ардовскому клиенту, получает пакет, парсит и рассовывает по мисклу. Далее по вкусу.

Al_Ninyo
Offline
Зарегистрирован: 09.11.2014

inspiritus пишет:

На арде клиент, на сервере пхп скрипт запускается кроном, обращается к ардовскому клиенту, получает пакет, парсит и рассовывает по мисклу. Далее по вкусу.

Да, спасибо, вы очень помогли. Именно то, что я очень просил - конкретные куски кода для меня-идиота.

Если что, у меня уже вроде получилось то, что я хотел и гораздо проще (для меня), чем парсить пакеты. Чуть позже до ума доведу и поделюсь.