Ethernet и mysql

Casper17
Offline
Зарегистрирован: 21.06.2013

Подскажите пожалуйста как правильно работать с Ethernet Shild-ом. Отправить get запрос на выполнение скрипта который заносит данные в БД mysql у меня получилось. А вот считать данные у меня не получается(( 

#include <SPI.h>
#include <Ethernet.h>


byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

char server[] = {192, 168, 1, 44};   

IPAddress ip(192,168,1,67);


EthernetClient client;
int val;
String currentLine = "";

void setup() {
 
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  
}

void loop()
{
  if (Serial.available()) {         
    val = Serial.read();            
    if (val == '1') {               
      
      
      Serial.println("connecting to server...");
  if (client.connect(server, 80)) {
    Serial.println("making HTTP request...");
  // Создаем GET HTTP-запрос 
    client.println("GET /get2.php HTTP/1.1");
    client.println("HOST: 192.168.1.44");
    client.println();
    
    if (client.connected()) {
    if (client.available()) {
      // считываем полученные байты:
      char inChar = client.read();
 Serial.println(inChar);
      // добавляем полученные байты в конец строки:
      currentLine += inChar;
      Serial.println(currentLine);
    }
    client.stop();
  }
  
  }
      
    }

  }
  
}

И вот сам get.php который делает выборку из БД. Если в браузере делать запрос то выводится запись. а в ардуинке полная тишина..

<?php
//адрес хоста
$dbhost = 'localhost';
//Имя пользовтаеля
$dbuser = 'Casper';
//пароль для подключения к Mysql
$dbpass = '123456';
//имя базы данных
$dbname = 'test';




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


$sql = mysql_query("SELECT temp FROM banya");
$myrow = mysql_fetch_array($sql);
echo ( $myrow['temp']."\n");



?>

 

CityCat
CityCat аватар
Offline
Зарегистрирован: 13.06.2013

Casper17, пока не смотрел код, но навскидку в ардуине вы обращаетесь к файлу get2.php, а приводите код из get.php - там (на сервере) точно есть файл get2.php?

Плюс, проверьте IP-адреса на соответствие.

P.S. В коде ничего криминального не нашел. Разве что вместо  if (client.available()) я бы написал while (client.available())

Casper17
Offline
Зарегистрирован: 21.06.2013

Да get2.php, тут опечатался. Хорошо попробую.

CityCat
CityCat аватар
Offline
Зарегистрирован: 13.06.2013

Ну и еще - обычно между отправкой запроса и чтением ответа необходим делей, чтоб сервер успел ответить, иначе ардуина не успеет услышать ответ и "побежит" дальше. Как раз 37-я строчка пустая для него :)
Я ставлю 10-50 миллис.

Casper17
Offline
Зарегистрирован: 21.06.2013

Спасибо большое помогло!

Casper17
Offline
Зарегистрирован: 21.06.2013

А можно как то отсеять HTML код и вытащить только переменную.

Отсеять получилось, но вот мне кажется что не рационально немножко так.. Или от этого не уйти?

CityCat
CityCat аватар
Offline
Зарегистрирован: 13.06.2013

Ну по мне самый простой способ - принимать строку и потом искать первое вхождение "\r\n\r\n" и "резать".

У меня так:

in = in.substring(in.indexOf("\r\n\r\n") + 4);

Хотя, может и неоптимально.

Casper17
Offline
Зарегистрирован: 21.06.2013

А можешь расписать как работают эти функции? Почитал немного о них, но как точно они работают немного не понял.. Я вот так пока реализовал

while (client.available())              // Если пришли данные от сервера, читаем и отображаем их в Serial-порту
        {
          char c = client.read();
          currentLine += c;
          
          Serial.print(c);
          
          if (c == '\n') {
            currentLine = "";
            
                }

Для моих задач работае хорошо и в переменной currentLine остается только число которое передавал, в скрипте можно указать перед числом несколько раз "\n\n" к примеру.. Просто для развития и знаний хочется узнать как у вас работает))

CityCat
CityCat аватар
Offline
Зарегистрирован: 13.06.2013

Что именно непонятно?

Substring - Извлекает подстроку из данного экземпляра. Подстрока начинается с указанной позиции знака и имеет указанную длину. 

indexOf - Возвращает индекс с отсчетом от нуля первого вхождения значения указанной строки в данном экземпляре.

То есть, индексофом ищу первое (и оно единсвенное будет, если в возвращаемой строке не будет два раза возврата строки подряд) вхождение во всю полученную строку символов "\r\n\r\n" (где \r - символ возврата каретки, а \n - перевода строки - проще говоря, в строке ищу два "энтера"), запоминаю позицию начала этой комбинации и, поскольку эта "комбинация" состоит из 4-х символов, прибавляю 4 - это будет позиция начала строки с обрезанным всем (и этими четырьмя символами тоже) и извлекаю подстроку сабстрингом (нужную сроку).

Andrei83
Offline
Зарегистрирован: 25.03.2014

Casper17,  можешь показать как отправить get запрос на выполнение скрипта который заносит данные в БД mysql , а точнее сам php скрипт? Сформировать GET запрос получилось, а вот передать его для чтения в php - не получается, скрипт нисего не читает

Casper17
Offline
Зарегистрирован: 21.06.2013
<?php
//адрес хоста
$dbhost = 'localhost';
//Имя пользовтаеля
$dbuser = 'Casper';
//пароль для подключения к Mysql
$dbpass = '123456';
//имя базы данных
$dbname = 'test';

// получение значения переменной температура
$temp = $_GET["t"];

//устанавливаем подключение к MySQL
$connect = mysql_connect($dbhost, $dbuser, $dbpass);
// проверяем состояние подключения
if(! $connect )
{
  die('Could not connect: ' . mysql_error());
}
// Выбираем базу данных
mysql_select_db ($dbname, $connect);
$times=date("H:i:s");
//Отправляем данные в таблицу
$sql = "INSERT INTO banya (time_update, time, temp) VALUES (NOW(), '$times', '$temp')";

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

Вот мой скрипт для занесение в БД температуры. Значение температуры находится в переменной t которую мы отправляем get запросом

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

Хмм, наверно я недогоняю... 

Что осуществляет вызов скрипта в интерпретаторе ?

Casper17
Offline
Зарегистрирован: 21.06.2013
 // Создаем GET HTTP-запрос
   client.println("GET /get2.php?t=50 HTTP/1.1");
   client.println("HOST: 192.168.1.44");
   client.println();

Вот этим мы отправляем данные в скрипт, тем самым мы его вызываем и он запускается и принимает переменные которые ему отправили.

GET /examples/test.html?параметры HTTP/1.1
Andrei83
Offline
Зарегистрирован: 25.03.2014

Casper17,  спасибо за скрипт, все получилось и работает.

Тапарь пытаюсь прикрутить к БД вывод данных на графики, как здесь    http://duvarov.dyndns.org/ 

VGorokhov
Offline
Зарегистрирован: 11.12.2013

Casper17 пишет:

А можно как то отсеять HTML код и вытащить только переменную.

Отсеять получилось, но вот мне кажется что не рационально немножко так.. Или от этого не уйти?

просмотрел ваш код, смог разобраться до уровня вывода информации на сом порт, самостоятельно отсеять значение из запроса так и смог. Не могли бы вы, выложить обновленный скечь, с фунциями выбора из текста значения полученного из MySQL. Заранее балагодарю за помощь.

std
Offline
Зарегистрирован: 05.01.2012

Вообще-то можно лазить прямо в базу, в обход PHP. Читайте описание команд SQL. Здесь, например.

sva1509
Offline
Зарегистрирован: 07.12.2012

Доброго времени суток !

Простите за мой французкий, но в коде у Вас полная белиберда !

Попробуем разобраться:

void loop()
{
    if (Serial.available()) {        
        val = Serial.read();           
        if (val == '1') {              
           Serial.println("connecting to server...");
           if (client.connect(server, 80)) {
              Serial.println("making HTTP request...");
              // Создаем GET HTTP-запрос
              client.println("GET /get2.php HTTP/1.1");
              client.println("HOST: 192.168.1.44");
              client.println();
              if (client.connected()) {
                 if (client.available()) {
                    // считываем полученные байты:
                    char inChar = client.read();
                    Serial.println(inChar);
                    // добавляем полученные байты в конец строки:
                    currentLine += inChar;
                    Serial.println(currentLine);
                 }
                 client.stop();
              }
           }
        }
    }
}

И так теперь видно, что Вы послали запрос, получили один символ, вывели его в сериал и остановили клиента. В следующий проход цикла loop ситуация повториться. Пауза которую вы добавили "по совету друзей" проблемму Вам не решила - просто за время ожидания в память приехал весь ответ сервера, но если связь будет хуже то проблемма проявится.

Попробуем изменить немного код:

void loop()
{
    if (Serial.available()) {        
        val = Serial.read();           
        if (val == '1') {              
           Serial.println("connecting to server...");
           if (client.connect(server, 80)) {
              Serial.println("making HTTP request...");
              // Создаем GET HTTP-запрос
              client.println("GET /get2.php HTTP/1.1");
              client.println("HOST: 192.168.1.44");
              client.println();
              while (client.connected()) {
                    if (client.available()) {
                       // считываем полученные байты:
                       char inChar = client.read();
                       //Serial.println(inChar);
                       // добавляем полученные байты в конец строки:
                       currentLine += inChar;
                    }
              }
              Serial.println(currentLine);  
              client.stop();
           }
        }
    }
}

Мне кажеться так будет правильней. 

В этом случае наш цыкл while собирает все доступные символы до закрытия соединения сервером.

После чего выводит полученный контент и завершает работу клиента.

По поводу парсинга - добавьте в php код какуюто метку по которой Вы будете опознавать ваши данные, капримеру <MyData:99> где 99 это ваши данные. Таким образом найти их будет значительно легче.

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

std пишет:

Вообще-то можно лазить прямо в базу, в обход PHP. Читайте описание команд SQL. Здесь, например.

Напрямую в базу с ардуино???? Это как? Нет я могу конечно представить себе с внутреннего клиента авторизироваться на сервере итд., но какой в этом смысл? И как быть с внешними?

std
Offline
Зарегистрирован: 05.01.2012

По-идее трафа меньше и соответственно парсить проще. Этож сетевой сервер, такой же как HTTP. Только в случае PHP, т. о. HTTP сервера принято посылать в порт 80, а в случае SQL сервера на 1433.

Но если извне нужен доступ, то таки да, нужон HTTP сервак с PHP.

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

std пишет:

По-идее трафа меньше и соответственно парсить проще. Этож сетевой сервер, такой же как HTTP. Только в случае PHP, т. о. HTTP сервера принято посылать в порт 80, а в случае SQL сервера на 1433.

Но если извне нужен доступ, то таки да, нужон HTTP сервак с PHP.

Любительский сервер с SQL? Кхм. Я бы все-таки поставил на 3306 ;)

Трафика будет больше, или Вы пердлагаете доступ к БД с нулевым логин/пароль?

ПХП ни при чем. Коннектиться можно хоть на асме, вопрос безопасности. Все что может коннектиться не к локалхосту - бяка.

sle
Offline
Зарегистрирован: 28.12.2013
Люди добрые,  ПОМОГИТЕ!!!

Не работает нижеприведённая конструкция в части if (client.available()), т.е. часть кода внутри этого условия не выполняется, соответственно условие ложно.  

Serial.println("client connected"); - вот это в сериал монитор пишется.
Сам get запрос   client.println(buf); на сервер прилетает и более того, если его в браузер руками ввести, то видно ответ сервера в виде: "2430", что собственно мне и надо считать и записать в переменную.
 
Ума не приложу в чём проблема.
 
if (client.connect(rserver, 80)) 
              {
                int temp1 = ((val_dht_temp[i]) - (int)(val_dht_temp[i])) * 100; // выделяем дробную часть
                sprintf(buf, "GET /objects/?object=dht%i&op=m&m=tempChanged&t=%0d.%d HTTP/1.1", (int)(i+1), (int)(val_dht_temp[i]), abs(temp1));
                client.println(buf);
                client.println("HOST: 192.168.0.10");
                client.println();
                Serial.println(buf);
                while (client.connected()) {
                Serial.println("client connected");
                    if (client.available()) {
                                              //delay(100);
                                             // считываем полученные байты:
                                             char inChar = client.read();
                                             Serial.println(inChar);
                                             }
                                          client.stop();
                                          Serial.println("Disconnect to server");
                                          }
               //set_temp[i]=currentLine;
               //Serial.println("Set new needed temp=Temp in server=");
               //Serial.println(set_temp[i]);
               }

Может в этом: собствено лог апача: 
192.168.0.101 - - [04/Dec/2016:16:33:05 +0400] "GET /objects/?object=dht1&op=m&m=tempChanged&t=24.89 HTTP/1.1" 400 506 "-" "-"

c http/1.0 ошибки 400 нет
192.168.0.101 - - [04/Dec/2016:16:53:42 +0400] "GET /objects/?object=dht1&op=m&m=tempChanged&t=24.70 HTTP/1.0" 200 228 "-" "-"

yuryivanov
Offline
Зарегистрирован: 10.06.2018

Casper17 пишет:

Отправить get запрос на выполнение скрипта который заносит данные в БД mysql у меня получилось.

Подскажите пожалуйста, а каким образом вы подключили устройство работающее по Ethernet к базе.
 

У меня есть лифтовой блок и он работает через Ethernet я хочу чтобы данные, поступающие с этого блока, добавлялись в базу MySQL.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

yuryivanov, общие принципы таковы:

1. На компе, где поднята MySQL база, поднимаешь веб-сервер (Apache, nginx и т.д.) и прикручиваешь к нему PHP.

2. Пишешь страничку на PHP, в которой реализовываешь подключение и запись в базу данных MySQL.

3. С устройства по Ethernet переходишь на эту веб-страничку, написанную на PHP, и передаешь параметры.

 

Осталось узнать, что и в каком виде передаёт ваш лифтовой блок по Ethernet. Позволяет ли он вообще себя перепрограммировать. Может он работает только с каким-то спецсофтом и ничего менять нельзя.

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно к inetd привязать небольшой perl-скрипт, к примеру. Это будет полегковесней. А я бы так и вовсе одиночного демона на перловке подвесил, чтобы он порт слушал. 

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

Нужно определить кто мастер и на каком наречии/протоколе болтает. 

yuryivanov
Offline
Зарегистрирован: 10.06.2018

Jeka_M пишет:

1. На компе, где поднята MySQL база, поднимаешь веб-сервер (Apache, nginx и т.д.) и прикручиваешь к нему PHP.

2. Пишешь страничку на PHP, в которой реализовываешь подключение и запись в базу данных MySQL.

3. С устройства по Ethernet переходишь на эту веб-страничку, написанную на PHP, и передаешь параметры.

Всё сделал и подключил. Не понимаю только как можно осуществить переход с устройства.

Jeka_M пишет:

Осталось узнать, что и в каком виде передаёт ваш лифтовой блок по Ethernet. Позволяет ли он вообще себя перепрограммировать. Может он работает только с каким-то спецсофтом и ничего менять нельзя.

Глупый вопрос может быть, но как это можно выяснить? Для блока, действительно имеется специальная программа, MPultPro. Неужели действительно нельзя никаким образом сделать подключение к веб-сервису?

sadman41
Offline
Зарегистрирован: 19.10.2016

Нереальную задачу для этого форума ставите. У вас устройство с собственным протоколом. Знания о том, как ардуина пишет SQL через PHP в данном случае бесполезны чуть менее, чем полностью.