majordomo-arduino не получается снять показания

Interkom
Offline
Зарегистрирован: 09.07.2014

Добрый день.

Скачал и установил majordomo-arduino.

Если открыть страницу http://192.168.3.177/getdev или http://192.168.3.177/ как написано в документации, то всё хорошо, страницы формируются и есть показания дачтиков и состояние пинов.

А вот если в php коде написать :

<?php
$data = file_get_contents('http://192.168.3.177/getdev');
echo $data;
?>
 
то никакого результата не выводится.
Подскажите плз, что я делаю не так ?
 
NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013

А доступ есть к этому ресурсу в PHP? Мне кажется что нет ...

Interkom
Offline
Зарегистрирован: 09.07.2014

А как проверить ?

если я ввожу в php :

<?php
$data = file_get_contents('http://http://www.example.com/');
echo $data;
?>
 
То всё получается.
 
JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012
<?php
$data = file_get_contents('getdev.php'); //ну или как там он называется
echo $data;
?>
Interkom
Offline
Зарегистрирован: 09.07.2014

IP адрес сервера на котором крутится LAMP с кодом PHP 192.168.3.5

а IP адрес Arduino 192.168.3.177

И как запрос 

$data = file_get_contents('getdev.php'); //ну или как там он называется
echo $data;
достучится до Arduino ?
 
vdk
Offline
Зарегистрирован: 14.04.2013

Я правильно понимаю, что с других внешних серверов все получается, а с http://192.168.3.177/  ну никак?

(и, кстати, непонятно, вы с компа голым php лезете, или из-под веб-сервера)

Interkom
Offline
Зарегистрирован: 09.07.2014

Да, с других серверов получается.

Сервер который лезет за данными. Ubuntu + LAMP.

 

vdk
Offline
Зарегистрирован: 14.04.2013

хорошо бы посмотреть, что выдаст wget http://192.168.3.177/getdev

(интересует его протокол работы)

Interkom
Offline
Зарегистрирован: 09.07.2014

Вот что выдал 

root@ubuntusrv:~# wget http://192.168.3.177/getdev
--2014-07-26 10:22:26--  http://192.168.3.177/getdev
Подключение к 192.168.3.177:80... соединились.
Запрос HTTP послан, ожидание ответа... 200 Заголовки отсутствуют, подразумевается HTTP/0.9
Длина: нет данных
Сохранение в каталог: ««getdev»».
 
    [ <=>                                   ] 28          --.-K/s   за 0s
 
2014-07-26 10:22:26 (445 KB/s) - «getdev» сохранено [28]
 
root@ubuntusrv:~#
 
Interkom
Offline
Зарегистрирован: 09.07.2014

а вот и файлы по запросам

wget http://192.168.3.177/getdev - getdev

ATI-0.00 HW-nan GND HUM-289 

и 

wget http://192.168.3.177 - index.html

<html><head><title>smartliving.ru controller 0.1</title></head><body>
IP:192.168.3.177<br>Location:Greenhouse<hr>Pin info:<br>A4 - Soil moisture sensor<br>D2 - DHT11<br>D3 - 1-wire (many DS18S20)<br>D4-output description<br>D5-output description<br>D6-output description<hr>Pin current state: P4=0;P5=0;P6=0;P7=0;P8=0;P9=0;<hr><a href='/getdev'>1-wire devices</a><hr>Commands:<br>HELP<br>ON<br>OFF<br>STATUS<br>CLICK<br>LCLICK<br><hr><br>Version info: 0.1. Compile date: 2012-09-18
 

 

vdk
Offline
Зарегистрирован: 14.04.2013

Попробуйте подкинуть php адрес http://192.168.3.177/getdev/index.html

Interkom
Offline
Зарегистрирован: 09.07.2014

Жаль, но не помогло.

 

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

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

Interkom
Offline
Зарегистрирован: 09.07.2014

Нет, я так не считаю.

Может кто то сталкивался уже с такой проблемой. Проект majordomo-arduino давольно известный.

В этом проекте как то считываются показания с датчиков на ардуине. Хотелось бы узнать каким методом ?

vdk
Offline
Зарегистрирован: 14.04.2013

Interkom пишет:

Жаль, но не помогло.

попробуйте еще http://192.168.3.177/getdev/

vdk
Offline
Зарегистрирован: 14.04.2013

Interkom пишет:

В этом проекте как то считываются показания с датчиков на ардуине. Хотелось бы узнать каким методом ?

Посмотреть код?

leshak
Offline
Зарегистрирован: 29.09.2011

Interkom пишет:

wget http://192.168.3.177 - index.html

Ну если этот запрос вам вернул "что-то вменяемое", то может его и пробовать на php воспроизвести? Я так понял это был http://192.168.3.177/index.html

Во вторых... что-то смущает что "

200 Заголовки отсутствуют"
Возможно мажордомо их не выдает (хотя странно... сомнительно что они столь грубую ошибку допустили...)
А file_get_contents() может как раз вести себя типа "если http 200 нема, то считать попытку неудачей".

Может файерволы какие-то у вас стоят...

Посмотрите что там, все-таки приходит от вашего мажордомо в заголовках.... в друг там что-то типа http 301 или http 401

PHP: $http_response_header - Manual

P.S. А вообще это тема ближе куда-то к php-шным форумам... там скорее можно найти решение проблем доступа из php к внешним ресурсам.

Interkom
Offline
Зарегистрирован: 09.07.2014
Через wget мне пока ещё сложновато. Я только пробую свои силы. Там нужно будет разбирать файл и вытаскивать значения и записывать их в mysql. Хотя и через file_get_contents делать придётся тоже самое.

Да, скорее всего arduino шлёт ответ в "неправильном" формате. Именно по этому file_get_contents не выдаёт никаких результатов.

Блин !!! Но всё таки как то люди вытаскивают значения из arduino !!!

Разбирать код http://smartliving.ru/ мне не под силу. Не хватит знаний !!!

Файерволыотключил. Не помогло.

 

 

 

leshak
Offline
Зарегистрирован: 29.09.2011

>Блин !!! Но всё таки как то люди вытаскивают значения из arduino !!!
Прекратите думать об этом как "вытаскивать значения из ардуино".
Вы общаетесь по протоколу http.
Следовательно у вас есть http сервер и http клиент (ваш php код).
Кто там выступает в роли http-сервера... - дело десятое.
Копать нужно в сторону разбирательств с http протоколом. Разобраться что такое заголовки (и для реквеста и для респонса), что такое статусы, как посмотреть "что ответил сервер" (вот я вам как раз и дал ссылочку)

Найти разницу между запросом который посылает браузер, и запросом который у вас получается с помощью file_get_content....
Может там мажордомо ожидает какого-нибудь банального "Accept: text/html" что бы знать в каком же виде вам ответ нужно дать...

Посмотрите, для начала какие заголовки в запросе посылают wget/браузер и ваш php.
Ну скажем вот это первое нагуглилось для проверки этого:http://headers.cloxy.net/request.php

А еще... на 80% уверен, что сам мажордомо имеет какое-нибудь API. И, с большой долей вероятности клиенты на PHP уже тоже существуют. Выпарсивать данные из html-ля предназначенные для человека (с дизайном и проч.) - это самое последнее что нужно пробовать. Если никаких других способов не предусмотрено. Но с большой долей вероятности этот мажордомо умеет отдавать данные в виде json или xml.
 

 

Interkom
Offline
Зарегистрирован: 09.07.2014

Спасибо. Буду ковырять в этом направлении.

О результатах отпишусь.

 

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

Interkom пишет:

Проект majordomo-arduino давольно известный.

ну так гуггл вам в руки. вы же видите что тут никто не сталкивался. и если прям НАСТОЛЬКО ИЗВЕСТНЫЙ, то загуглите примеры. 

Divest
Offline
Зарегистрирован: 04.05.2014

А я вот стакливался. Сейчас подскажу.

Смотрите. На странице имеем http://192.168.0.210/getdev следующие показания: 

28FF820410140093:26.00;28FFE90310140074:25.00;

Из кода я специально убрал следющие строки: 


server.print("T");
server.print(i);
server.print(":");

Мне показалось так будет проще. 

Собственно на WEB сервере пишем следующий PHP скрипт:




<?            
$dbhost = 'mysql_server_ip';
$dbuser = 'user';
$dbpass = 'password';
$dbname = 'db_name';
$connect = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db ($dbname, $connect);
$ch = curl_init();
curl_setopt_array($ch, array(
        CURLOPT_URL=>'http://ip_address/getdev',
        CURLOPT_RETURNTRANSFER=>true
));
$data = curl_exec($ch);
               
               
$dats = explode(';',$data);
foreach($dats as $dat){
        if(strpos($dat,':')===false)continue;
        $addrs = explode(':',$dat);
        echo $addrs[0].' - '.$addrs[1].PHP_EOL.'<br/>';
        $sql = "INSERT INTO sensor_readings (sensor_id, sensor_value) VALUES ('$addrs[0]', '$addrs[1]')";
        if(!mysql_query($sql)) {
                echo '<p><b>Data upload error!</b></p>';
        } else {
                echo '<p><b>OK</b></p>';
        }
}
?>

Собственно данный скрипт сам напишет значения с датчиков в БД не зависимо от их кол-ва. 

Убедитесь что на сервере стоит cURL. Проверить можно создав PHP файл на сервере: 


<?php
// Получаем массив с информацией о версии curl
$version = curl_version();

// Это битовые поля, которые можно использовать
// для проверки возможностей сборки curl
$bitfields = Array(
            'CURL_VERSION_IPV6',
            'CURL_VERSION_KERBEROS4',
            'CURL_VERSION_SSL',
            'CURL_VERSION_LIBZ'
            );


foreach($bitfields as $feature)
{
    echo $feature . ($version['features'] & constant($feature) ? ' есть' : ' нет');
    echo PHP_EOL;
}
?>

Собственно и все. Чтоб не плодить новые темы, хочется спросить по коду следующее. В каком случае идет обновление данных с датчиков? Или каким образом можно сделать, чтоб данные с датчиков обновлялись раз в минуту. 


/**
* Контроллер-исполнительное устройство (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.0.1
*
* исполнительные устройства (реле) подключены к Digital 3 - 9
*
* обращение по http://xx.xx.xx.xx/ выдаст справочную информацию по этому устройству (нужно для того, чтобы когда обращаешься
* по IP к устройству понять что это за контроллер и пр.)
*
* /state - состояние всех портов
* /command - выполнение команды
*         команды можно вызывать серией в 1 запросе. Например http://xx.xx.xx.xx/command?3=CLICK&4=CLICK&5=ON&6=OFF
*         только длинна строки запроса не должна привышать maxLength
* /getdev - получить список всех устройст на 1-wire
*         формат вывода: 
*                T<номер устройства на шине>:<HEX адрес устройства>:<текущая температура в градусах цельсия>;[...]
*                (пример T0:1060CF59010800E3:24.06;T1:109ABE59010800FE:24.56;)
*
**/

#include <Ethernet.h>
#include <SPI.h>
#include <Arduino.h>
#include "WebServer.h" // Webduino (https://github.com/sirleech/Webduino)
#include <OneWire.h>
#include <DallasTemperature.h>


byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x35 }; // MAC-адрес нашего устройства
byte ip[] = { 192, 168, 0, 210 };
byte subnet[] = { 255, 255, 255, 0 };
byte gateway[] = { 192, 168, 0, 1 };
byte dns_server[] = { 192, 168, 0, 1 };
// ip-адрес удалённого сервера
byte rserver[] = { 192, 168, 0, 78 };

// Настройки выходов
int startPin=3;
int endPin=9;

// Pin controller for connection data pin DS18S20
#define ONE_WIRE_BUS 2 // Digital 2 pin Arduino (куда подключен выход с шины датчиков DS18X20
#define TEMPERATURE_PRECISION 9

#define VERSION_STRING "0.1"
#define COMPILE_DATE_STRING "2012-09-18"

P(Page_info) = "<html><head><title>smartliving.ru controller " VERSION_STRING "</title></head><body>\n";
P(location_info) = "underground server room";
P(pin_info) = "D2 - 1-wire (many DS18S20)<br>D3-light undergroung";
P(version_info) = VERSION_STRING ". Compile date: " COMPILE_DATE_STRING;

String url = String(25);
int maxLength=25; // Максимальная длинна строки запроса

#define delayClick 1000 // задержка при обычном CLICK
#define delayLClick 3000 // задержка при длинном LCLICK
#define MAX_COMMAND_LEN             (10)
#define MAX_PARAMETER_LEN           (10)
#define COMMAND_TABLE_SIZE          (8)
#define PREFIX ""

WebServer webserver(PREFIX, 80);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Для поиска
DeviceAddress Termometers;
float tempC; 

#define NAMELEN 32
#define VALUELEN 32

char gCommandBuffer[MAX_COMMAND_LEN + 1];
char gParamBuffer[MAX_PARAMETER_LEN + 1];
long gParamValue;

typedef struct {
  char const    *name;
  void          (*function)(WebServer &server);
} command_t;

command_t const gCommandTable[COMMAND_TABLE_SIZE] = {
//  {"LED",     commandsLed, },
  {"HELP",     commandsHelp, }, // Выводит список комманд (вызов http://xx.xx.xx.xx/command?8=HELP )
  {"ON",     commandsOn, }, // Устанавливает "1" на заданном цифровом порту (вызов http://xx.xx.xx.xx/command?8=ON )
  {"OFF",     commandsOff, }, // Устанавливает "0" на заданном цифровом порту (вызов http://xx.xx.xx.xx/command?8=OFF )
  {"STATUS",     commandsStatus, }, // Получить состояние цифрового порта (1 или 0) (вызов http://xx.xx.xx.xx/command?8=STATUS ),
                                    // если вместо номера порта передать ALL (вызов http://xx.xx.xx.xx/command?ALL=STATUS ), то получим состояние всех портов (Пример вывода P3=0;P4=0;P5=0;P6=0;P7=0;P8=1;P9=1;)
  {"CLICK",     commandsClick, }, // Кратковременная "1" на порту 1сек (время настраивается) (вызов http://xx.xx.xx.xx/command?8=CLICK )
  {"LCLICK",     commandsLClick, }, // Кратковременная "1" на порту 3сек (время настраивается) (вызов http://xx.xx.xx.xx/command?8=LCLICK )
  {NULL,      NULL }
};

/**********************************************************************************************************************
 *
 * Function:    cliProcessCommand
 *
 * Description: Look up the command in the command table. If the
 *              command is found, call the command's function. If the
 *              command is not found, output an error message.
 *
 * Notes:       
 *
 * Returns:     None.
 *
 **********************************************************************/
void cliProcessCommand(WebServer &server)
{
  int bCommandFound = false;
  int idx;

  gParamValue = strtol(gParamBuffer, NULL, 0);  // Convert the parameter to an integer value. If the parameter is empty, gParamValue becomes 0.
  for (idx = 0; gCommandTable[idx].name != NULL; idx++) {  // Search for the command in the command table until it is found or the end of the table is reached. If the command is found, break out of the loop.
    if (strcmp(gCommandTable[idx].name, gCommandBuffer) == 0) {
      bCommandFound = true;
      break;
    }
  }

  if (bCommandFound == true) {  // Если команда найдена (в массиве команд), то выполняем ее. Если нет - игнорируем
    (*gCommandTable[idx].function)(server);
  }
  else { // Command not found
    server.print("ERROR: Command not found");
  }
}


/**********************************************************************************************************************/
/* Обработчики команд */

void commandsOn(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,HIGH);
  } else ErrorMessage(server);
}

void commandsOff(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,LOW);
  } else ErrorMessage(server);
}

void commandsClick(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,HIGH);     
     delay(delayClick);
     digitalWrite(gParamValue,LOW);
  } else ErrorMessage(server);
}

void commandsLClick(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,HIGH);     
     delay(delayLClick);
     digitalWrite(gParamValue,LOW);
  } else ErrorMessage(server);
}

void commandsStatus(WebServer &server) {
   if  (strcmp(gParamBuffer,  "ALL") == 0) { // выдать состояние всех пинов
          for(int i=startPin;i<=endPin;i++) {
            int st=digitalRead(i);
            char my_st[5];
            itoa(st,my_st,10);
            server.print("P");
            server.print(i);
            server.print("=");
            server.print(my_st);
            server.print(";");
          }
   } else { // выдать состояние только 1 пина
          if (gParamValue>=startPin && gParamValue<=endPin) {
            server.print("P");
            server.print(gParamValue);
            server.print("=");
            server.print(digitalRead(gParamValue));
          } else ErrorMessage(server);
    }
}

void commandsHelp(WebServer &server) {
  int idx;
  for (idx = 0; gCommandTable[idx].name != NULL; idx++) {
    server.print(gCommandTable[idx].name);
    server.print("<br>");
  }
}

/**********************************************************************************************************************/

void ErrorMessage(WebServer &server) {
    server.print("ERROR: This Pin is not configured for I/O");
}

/**********************************************************************************************************************
* Разбор запроса
**/
void parsedRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  int  name_len;
  char value[VALUELEN];
  int value_len;

  server.httpSuccess();  // this line sends the standard "we're all OK" headers back to the browser

  /* if we're handling a GET or POST, we can output our data here.
     For a HEAD request, we just stop after outputting headers. */
  if (type == WebServer::HEAD)
    return;

  if (strlen(url_tail))
    {
    while (strlen(url_tail)) // Разбор URI на составные части (выборка параметров)
      {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc == URLPARAM_EOS) {
  //      server.printP(Params_end);
      }
       else // Получили параметр (name) и его значение (value)
        {
        // Выполняем команды
        strcpy (gCommandBuffer, value); // параметры (значение)
        strcpy (gParamBuffer, name); // команда
        cliProcessCommand(server);
        }
      }
    }
/*    
  if (type == WebServer::POST)
  {
    server.printP(Post_params_begin);
    while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
    {
      server.print(name);
      server.printP(Parsed_item_separator);
      server.print(value);
      server.printP(Tail_end);
    }
  }
*/

}

void get1wireDevices(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  //TODO получить все устройства на шине и выдать на страницу
   int numberOfDevices = sensors.getDeviceCount();
   sensors.begin();
   for(int i=0;i<numberOfDevices; i++) {
      if(sensors.getAddress(Termometers, i))
      {
        //  server.print("T");
        //  server.print(i);
        // server.print(":");
          for (uint8_t i = 0; i < 8; i++) {
            if (Termometers[i] < 16) server.print("0");
              server.print(Termometers[i], HEX);
          }
          float tempC = sensors.getTempC(Termometers);
          server.print(":");
          server.print(tempC);
          server.print(";");
      } else {
            // not found
            server.print("NOT FOUND");
      }
    }
}


void stateRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  strcpy (gParamBuffer, "ALL");
  commandsStatus(server);
}

/**********************************************************************************************************************
* Генерация и вывод информации об устройстве
**/
void infoRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  server.printP(Page_info);
  server.print("IP:");
  server.print(Ethernet.localIP());
  server.print("<br>Location:");
  server.printP(location_info);
  server.print("<hr>Pin info:<br>");
  server.printP(pin_info);
  server.print("<hr>Pin current state: ");
  strcpy (gParamBuffer, "ALL");
  commandsStatus(server);
  server.print("<hr><a href='/getdev'>1-wire devices</a>");
  server.print("<hr>Commands:<br>");
  commandsHelp(server);
  server.print("<hr><br>Version info: ");
  server.printP(version_info);
  
}

/**********************************************************************************************************************
* Поиск устройств (датчиков температуры на шине 1-wire)
**/
void searchDevices() {
   Serial.print("Start search on 1-wire");
   int numberOfDevices = sensors.getDeviceCount();
   sensors.begin();
   
   for(int i=0;i<numberOfDevices; i++) {
      if(sensors.getAddress(Termometers, i))
      {
          Serial.print("Found device ");
	  Serial.print(i, DEC);
          Serial.print(" with address: ");
          for (uint8_t i = 0; i < 8; i++) {
            if (Termometers[i] < 16) Serial.print("0");
              Serial.print(Termometers[i], HEX);
          }

          Serial.print("Resolution actually set to: ");
	  Serial.print(sensors.getResolution(Termometers), DEC); 
          Serial.println();
          float tempC = sensors.getTempC(Termometers);
          Serial.print(tempC);
          Serial.println("C");
      
      } else {
            // not found
      }
    }
}


/**********************************************************************************************************************/
void setup() {
  // Для дебага будем выводить отладочные сообщения в консоль
  //TODO Убрать вывод в консоль "за дабаг" (т.е. вывод только если скимпилированно с поддержкой дебага)
 Serial.begin(9600);
 Serial.println("Start");
  
  Ethernet.begin(mac, ip, dns_server, gateway, subnet); // Инициализируем Ethernet Shield

  webserver.setDefaultCommand(&infoRequest); // дефолтная страница вывода (информация о контроллере)
  webserver.addCommand("command", &parsedRequest); // команды
  webserver.addCommand("state", &stateRequest); // выдать состояния всех устройств
  webserver.addCommand("getdev", &get1wireDevices); // получить список устройств на 1-wire
  webserver.begin();
  
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  
  // Настройка портов на вывод
  for (int thisPin = startPin; thisPin <=endPin; thisPin++)  {
    pinMode(thisPin, OUTPUT);      
  }
  // Настройки 1-wire 
  sensors.begin(); // Инициализация шины 1-wire (для датчиков температуры)
  sensors.requestTemperatures(); // Перед каждым получением температуры надо ее запросить
  searchDevices();
  
}

/**********************************************************************************************************************/
void loop() {
 //searchDevices();
 //delay(60000);
 char buff[64];
 int len = 64;
 webserver.processConnection(buff, &len);  // process incoming connections one at a time forever
 }
Interkom
Offline
Зарегистрирован: 09.07.2014


Огромное спасибо за поддержку.
Завтра буду разбираться.
Я тоже немного модифицировал вывод по запросу http://192.168.3.177/getdev
Выглядит он так
T0-23.75 ATI-36.00 HW-31.00 GND HUM-46

Где T0 - Температура датчиков на шине 1-wire

ATI и HW - температура и влажность на датчике DHT11

GND HUM - влажность почвы

Ардуино установленно в теплице, и управляет автоматическим поливом.

Вод код вывода !!!

void get1wireDevices(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
   //TODO получить все устройства на шине и выдать на страницу
   int numberOfDevices = sensors.getDeviceCount();
   sensors.begin();
   for(int i=0;i<numberOfDevices; i++) {
      if(sensors.getAddress(Termometers, i))
      {
//          server.print("HTTP/1.1 200 OK");            // Denis wr
//          server.println("Content-Type: text/html");  // Denis wr
//          server.println("<!DOCTYPE HTML>");          // Denis wr
//          server.println("<html>");                   // Denis wr
          
          
          server.print("T");
          server.print(i);
//          server.print(":");                                  //Denis comment
          for (uint8_t i = 0; i < 8; i++) {
            if (Termometers[i] < 16); //server.print("0");      //Denis comment ???
//              server.print(Termometers[i], HEX);              //Denis comment
          }
          float tempC = sensors.getTempC(Termometers);
          server.print("-");
          server.print(tempC);
          server.print(" ");
          
//          server.println("<br />");                   // Denis wr
//          server.println("</html>");                  // Denis wr
//          server.println("HTTP/1.1 200 OK");          // Denis wr
//          client.println("HTTP/1.1 200 OK");          // Denis wr
 
 
// denis
// Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
//  float h = Dht.readHumidity();
  // Read temperature as Celsius
//  float t = Dht.readTemperature();
  // Read temperature as Fahrenheit
//server.print(h);
//server.print(t);
          
          
      } else {
            // not found
            server.print("NOT FOUND");
      }
    }
float h = Dht.readHumidity();
// Read temperature as Celsius
float t = Dht.readTemperature();
// Read temperature as Fahrenheit
// Печатаем температуру воздуха внутри теплицы DHT11
server.print("ATI");
server.print("-");
server.print(t);
server.print(" ");
// Печатаем влажность воздуха внутри теплицы
server.print("HW");
server.print("-");
server.print(h);
server.print(" ");
//server.print(<br>);
 
val = analogRead(4);
//server.print("Влажность почвы");
server.print("GND HUM");
server.print("-");
server.print(val);
//server.print(" ");
 
// server.print(h);
// server.print(t);
}
Divest
Offline
Зарегистрирован: 04.05.2014

Собственно вам можно просто сделать вот так: T0:23.75;ATI:36.00;HW:31.00;GND HUM:46;

И все значения упадут в таблицу. Выложите пожалуйста весь код. 

Interkom
Offline
Зарегистрирован: 09.07.2014

вот мой код.

/**
*https://github.com/sochkasov/majordomo-arduino/blob/master/ArduinoControllerWebServer/ArduinoControllerWebServer.ino
* Контроллер-исполнительное устройство (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.0.1
*
* исполнительные устройства (реле) подключены к Digital 3 - 9
*
* обращение по http://xx.xx.xx.xx/ выдаст справочную информацию по этому устройству (нужно для того, чтобы когда обращаешься
* по IP к устройству понять что это за контроллер и пр.)
*
* /state - состояние всех портов
* /command - выполнение команды
*         команды можно вызывать серией в 1 запросе. Например http://xx.xx.xx.xx/command?3=CLICK&4=CLICK&5=ON&6=OFF
*         только длинна строки запроса не должна привышать maxLength
* /getdev - получить список всех устройст на 1-wire
*         формат вывода: 
*                T<номер устройства на шине>:<HEX адрес устройства>:<текущая температура в градусах цельсия>;[...]
*                (пример T0:1060CF59010800E3:24.06;T1:109ABE59010800FE:24.56;)
*
**/

#include <Ethernet.h>
#include <SPI.h>
#include <Arduino.h>
#include "WebServer.h" // Webduino (https://github.com/sirleech/Webduino)
#include <OneWire.h>
#include <DallasTemperature.h>
#include "Dht.h" //Denis

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x35 }; // MAC-адрес нашего устройства
byte ip[] = { 192, 168, 3, 177 };
byte subnet[] = { 255, 255, 255, 0 };
byte gateway[] = { 192, 168, 3, 1 };
byte dns_server[] = { 192, 168, 3, 1 };
// ip-адрес удалённого сервера
byte rserver[] = { 192, 168, 3, 5 };

// Настройки выходов
int startPin=4;
int endPin=9;
int val = 0;

// Pin controller for connection data pin DS18S20
#define ONE_WIRE_BUS 3 // Digital 2 pin Arduino (куда подключен выход с шины датчиков DS18X20
#define TEMPERATURE_PRECISION 9
#define DHTPIN 2 //Denis
#define DHTTYPE DHT11 //Denis
DHT Dht(DHTPIN, DHTTYPE);

#define VERSION_STRING "0.1"
#define COMPILE_DATE_STRING "2012-09-18"

P(Page_info) = "<html><head><title>smartliving.ru controller " VERSION_STRING "</title></head><body>\n";
P(location_info) = "Greenhouse";
P(pin_info) = "A4 - Soil moisture sensor<br>D2 - DHT11<br>D3 - 1-wire (many DS18S20)<br>D4-output description<br>D5-output description<br>D6-output description";
P(version_info) = VERSION_STRING ". Compile date: " COMPILE_DATE_STRING;

String url = String(25);
int maxLength=125; // Максимальная длинна строки запроса

#define delayClick 1000 // задержка при обычном CLICK
#define delayLClick 3000 // задержка при длинном LCLICK
#define MAX_COMMAND_LEN             (10)
#define MAX_PARAMETER_LEN           (10)
#define COMMAND_TABLE_SIZE          (8)
#define PREFIX ""

WebServer webserver(PREFIX, 80);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Для поиска
DeviceAddress Termometers;
float tempC; 

#define NAMELEN 32
#define VALUELEN 32

char gCommandBuffer[MAX_COMMAND_LEN + 1];
char gParamBuffer[MAX_PARAMETER_LEN + 1];
long gParamValue;

typedef struct {
  char const    *name;
  void          (*function)(WebServer &server);
} command_t;

command_t const gCommandTable[COMMAND_TABLE_SIZE] = {
//  {"LED",     commandsLed, },
  {"HELP",     commandsHelp, }, // Выводит список комманд (вызов http://xx.xx.xx.xx/command?8=HELP )
  {"ON",     commandsOn, }, // Устанавливает "1" на заданном цифровом порту (вызов http://xx.xx.xx.xx/command?8=ON )
  {"OFF",     commandsOff, }, // Устанавливает "0" на заданном цифровом порту (вызов http://xx.xx.xx.xx/command?8=OFF )
  {"STATUS",     commandsStatus, }, // Получить состояние цифрового порта (1 или 0) (вызов http://xx.xx.xx.xx/command?8=STATUS ),
                                    // если вместо номера порта передать ALL (вызов http://xx.xx.xx.xx/command?ALL=STATUS ), то получим состояние всех портов (Пример вывода P3=0;P4=0;P5=0;P6=0;P7=0;P8=1;P9=1;)
  {"CLICK",     commandsClick, }, // Кратковременная "1" на порту 1сек (время настраивается) (вызов http://xx.xx.xx.xx/command?8=CLICK )
  {"LCLICK",     commandsLClick, }, // Кратковременная "1" на порту 3сек (время настраивается) (вызов http://xx.xx.xx.xx/command?8=LCLICK )
  {NULL,      NULL }
};

/**********************************************************************************************************************
 *
 * Function:    cliProcessCommand
 *
 * Description: Look up the command in the command table. If the
 *              command is found, call the command's function. If the
 *              command is not found, output an error message.
 *
 * Notes:       
 *
 * Returns:     None.
 *
 **********************************************************************/
void cliProcessCommand(WebServer &server)
{
  int bCommandFound = false;
  int idx;

  gParamValue = strtol(gParamBuffer, NULL, 0);  // Convert the parameter to an integer value. If the parameter is empty, gParamValue becomes 0.
  for (idx = 0; gCommandTable[idx].name != NULL; idx++) {  // Search for the command in the command table until it is found or the end of the table is reached. If the command is found, break out of the loop.
    if (strcmp(gCommandTable[idx].name, gCommandBuffer) == 0) {
      bCommandFound = true;
      break;
    }
  }

  if (bCommandFound == true) {  // Если команда найдена (в массиве команд), то выполняем ее. Если нет - игнорируем
    (*gCommandTable[idx].function)(server);
  }
  else { // Command not found
    server.print("ERROR: Command not found");
  }
}


/**********************************************************************************************************************/
/* Обработчики команд */

void commandsOn(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,HIGH);
  } else ErrorMessage(server);
}

void commandsOff(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,LOW);
  } else ErrorMessage(server);
}

void commandsClick(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,HIGH);     
     delay(delayClick);
     digitalWrite(gParamValue,LOW);
  } else ErrorMessage(server);
}

void commandsLClick(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,HIGH);     
     delay(delayLClick);
     digitalWrite(gParamValue,LOW);
  } else ErrorMessage(server);
}

void commandsStatus(WebServer &server) {
   if  (strcmp(gParamBuffer,  "ALL") == 0) { // выдать состояние всех пинов
          for(int i=startPin;i<=endPin;i++) {
            int st=digitalRead(i);
            char my_st[5];
            itoa(st,my_st,10);
            server.print("P");
            server.print(i);
            server.print("=");
            server.print(my_st);
            server.print(";");
          }
   } else { // выдать состояние только 1 пина
          if (gParamValue>=startPin && gParamValue<=endPin) {
            server.print("P");
            server.print(gParamValue);
            server.print("=");
            server.print(digitalRead(gParamValue));
          } else ErrorMessage(server);
    }
}

void commandsHelp(WebServer &server) {
  int idx;
  for (idx = 0; gCommandTable[idx].name != NULL; idx++) {
    server.print(gCommandTable[idx].name);
    server.print("<br>");
  }
}

/**********************************************************************************************************************/

void ErrorMessage(WebServer &server) {
    server.print("ERROR: This Pin is not configured for I/O");
}

/**********************************************************************************************************************
* Разбор запроса
**/
void parsedRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  URLPARAM_RESULT rc;
  char name[NAMELEN];
  int  name_len;
  char value[VALUELEN];
  int value_len;

  server.httpSuccess();  // this line sends the standard "we're all OK" headers back to the browser

  /* if we're handling a GET or POST, we can output our data here.
     For a HEAD request, we just stop after outputting headers. */
  if (type == WebServer::HEAD)
    return;

  if (strlen(url_tail))
    {
    while (strlen(url_tail)) // Разбор URI на составные части (выборка параметров)
      {
      rc = server.nextURLparam(&url_tail, name, NAMELEN, value, VALUELEN);
      if (rc == URLPARAM_EOS) {
  //      server.printP(Params_end);
      }
       else // Получили параметр (name) и его значение (value)
        {
        // Выполняем команды
        strcpy (gCommandBuffer, value); // параметры (значение)
        strcpy (gParamBuffer, name); // команда
        cliProcessCommand(server);
        }
      }
    }
/*    
  if (type == WebServer::POST)
  {
    server.printP(Post_params_begin);
    while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
    {
      server.print(name);
      server.printP(Parsed_item_separator);
      server.print(value);
      server.printP(Tail_end);
    }
  }
*/

}

void get1wireDevices(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
   //TODO получить все устройства на шине и выдать на страницу
   int numberOfDevices = sensors.getDeviceCount();
   sensors.begin();
   for(int i=0;i<numberOfDevices; i++) {
      if(sensors.getAddress(Termometers, i))
      {
//          server.print("HTTP/1.1 200 OK");            // Denis wr
//          server.println("Content-Type: text/html");  // Denis wr
//          server.println("<!DOCTYPE HTML>");          // Denis wr
//          server.println("<html>");                   // Denis wr
          
          
          server.print("T");
          server.print(i);
//          server.print(":");                                  //Denis comment
          for (uint8_t i = 0; i < 8; i++) {
            if (Termometers[i] < 16); //server.print("0");      //Denis comment ???
//              server.print(Termometers[i], HEX);              //Denis comment
          }
          float tempC = sensors.getTempC(Termometers);
          server.print("-");
          server.print(tempC);
          server.print(" ");
          
//          server.println("<br />");                   // Denis wr
//          server.println("</html>");                  // Denis wr
//          server.println("HTTP/1.1 200 OK");          // Denis wr
//          client.println("HTTP/1.1 200 OK");          // Denis wr


// denis
// Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
//  float h = Dht.readHumidity();
  // Read temperature as Celsius
//  float t = Dht.readTemperature();
  // Read temperature as Fahrenheit
//server.print(h);
//server.print(t);
          
          
      } else {
            // not found
            server.print("NOT FOUND");
      }
    }
float h = Dht.readHumidity();
// Read temperature as Celsius
float t = Dht.readTemperature();
// Read temperature as Fahrenheit
// Печатаем температуру воздуха внутри теплицы DHT11
server.print("ATI");
server.print("-");
server.print(t);
server.print(" ");
// Печатаем влажность воздуха внутри теплицы
server.print("HW");
server.print("-");
server.print(h);
server.print(" ");
//server.print(<br>);

val = analogRead(4);
//server.print("Влажность почвы");
server.print("GND HUM");
server.print("-");
server.print(val);
server.print(" ");

// server.print(h);
// server.print(t);
    
    
    
    
    
}


void stateRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  strcpy (gParamBuffer, "ALL");
  commandsStatus(server);
}

/**********************************************************************************************************************
* Генерация и вывод информации об устройстве
**/
void infoRequest(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
{
  server.printP(Page_info);
  server.print("IP:");
  server.print(Ethernet.localIP());
  server.print("<br>Location:");
  server.printP(location_info);
  server.print("<hr>Pin info:<br>");
  server.printP(pin_info);
  server.print("<hr>Pin current state: ");
  strcpy (gParamBuffer, "ALL");
  commandsStatus(server);
  server.print("<hr><a href='/getdev'>1-wire devices</a>");
  server.print("<hr>Commands:<br>");
  commandsHelp(server);
  server.print("<hr><br>Version info: ");
  server.printP(version_info);
  
}

/**********************************************************************************************************************
* Поиск устройств (датчиков температуры на шине 1-wire)
**/
void searchDevices() {
   Serial.print("Start search on 1-wire");
   int numberOfDevices = sensors.getDeviceCount();
   sensors.begin();
   
   for(int i=0;i<numberOfDevices; i++) {
      if(sensors.getAddress(Termometers, i))
      {
          Serial.print("Found device ");
 Serial.print(i, DEC);
          Serial.print(" with address: ");
          for (uint8_t i = 0; i < 8; i++) {
            if (Termometers[i] < 16) Serial.print("0");
              Serial.print(Termometers[i], HEX);
          }

          Serial.print("Resolution actually set to: ");
 Serial.print(sensors.getResolution(Termometers), DEC); 
          Serial.println();
          float tempC = sensors.getTempC(Termometers);
          Serial.print(tempC);
          Serial.println("C");
      
      } else {
            // not found
      }
    }
}


/**********************************************************************************************************************/
void setup() {
  // Для дебага будем выводить отладочные сообщения в консоль
  //TODO Убрать вывод в консоль "за дабаг" (т.е. вывод только если скимпилированно с поддержкой дебага)
  Dht.begin();
  Serial.begin(9600);
  Serial.println("Start");
  
  Ethernet.begin(mac, ip, dns_server, gateway, subnet); // Инициализируем Ethernet Shield

  webserver.setDefaultCommand(&infoRequest); // дефолтная страница вывода (информация о контроллере)
  webserver.addCommand("command", &parsedRequest); // команды
  webserver.addCommand("state", &stateRequest); // выдать состояния всех устройств
  webserver.addCommand("getdev", &get1wireDevices); // получить список устройств на 1-wire
  webserver.begin();
  
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  
  // Настройка портов на вывод
  for (int thisPin = startPin; thisPin <=endPin; thisPin++)  {
    pinMode(thisPin, OUTPUT);      
  }
  // Настройки 1-wire 
  sensors.begin(); // Инициализация шины 1-wire (для датчиков температуры)
  sensors.requestTemperatures(); // Перед каждым получением температуры надо ее запросить
  
  searchDevices();
  
}

/**********************************************************************************************************************/
void loop() {
  char buff[64];
  int len = 64;
  webserver.processConnection(buff, &len);  // process incoming connections one at a time forever
  }

 

 

Interkom
Offline
Зарегистрирован: 09.07.2014

Данные с датчиков думаю обновлять как раз через опрос, который по расписанию будет запускаться раз в 10 минут.

Для моих задач это достаточно.

Что касаемо curl

php страница с кодом 

<?php
// Получаем массив с информацией о версии curl
$version = curl_version();
 
// Это битовые поля, которые можно использовать
// для проверки возможностей сборки curl
$bitfields = Array(
            'CURL_VERSION_IPV6',
            'CURL_VERSION_KERBEROS4',
            'CURL_VERSION_SSL',
            'CURL_VERSION_LIBZ'
            );
 
 
foreach($bitfields as $feature)
{
    echo $feature . ($version['features'] & constant($feature) ? ' есть' : ' нет');
    echo PHP_EOL;
}
?>
 
выдала вот что
CURL_VERSION_IPV6 есть CURL_VERSION_KERBEROS4 нет CURL_VERSION_SSL есть CURL_VERSION_LIBZ есть
 
Залил Ваш код в Arduino, создал php страницу
<?           
/*
$dbhost = 'mysql_server_ip';
$dbuser = 'user';
$dbpass = 'password';
$dbname = 'db_name';
$connect = mysql_connect($dbhost, $dbuser, $dbpass);
mysql_select_db ($dbname, $connect);
*/
 
$ch = curl_init();
curl_setopt_array($ch, array(
        CURLOPT_URL=>'<a href="/getdev">http://192.168.3.201/getdev</a>',
        CURLOPT_RETURNTRANSFER=>true
));
$data = curl_exec($ch);
$dats = explode(';',$data);
foreach($dats as $dat){
        if(strpos($dat,':')===false)continue;
        $addrs = explode(':',$dat);
        echo $addrs[0].' - '.$addrs[1].PHP_EOL.'<br/>';
 
/*        $sql = "INSERT INTO sensor_readings (sensor_id, sensor_value) VALUES ('$addrs[0]', '$addrs[1]')";
        if(!mysql_query($sql))
{
                echo '<p><b>Data upload error!</b></p>';
        }
else
{
                echo '<p><b>OK</b></p>';
        }
*/
}
?>
 
в ответ как всегда ничего,
я думал строка 
echo $addrs[0].' - '.$addrs[1].PHP_EOL.'<br/>';
хоть что то выведет !!!
 
 
leshak
Offline
Зарегистрирован: 29.09.2011

Скажите, а вы никогда не замечали разницы между кодом который выкладываете вы и кодом который выкладывают другие?
 

Interkom
Offline
Зарегистрирован: 09.07.2014

да, замечал, но при попытке выложить код в нормальном формате, форум выдаёт ошибку.

Инструкцию http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii прочитал.

Но всё равно не получается.

Сорри.

Interkom
Offline
Зарегистрирован: 09.07.2014

подправил страницу с выводом curl

вот что теперь выдаёт

CURL_VERSION_IPV6 есть CURL_VERSION_KERBEROS4 нет CURL_VERSION_SSL есть CURL_VERSION_LIBZ есть

 

Divest
Offline
Зарегистрирован: 04.05.2014

Собственно CURL_VERSION_KERBEROS4 не нужен. Сейчас посмотрю чтоб просто отоброжало. 

За отображение кода, прошу понять и простить )) 

Не забудь, что тебе нужно сделать Датчик:Значение;Датчик1:Значение;

<?             
$ch = curl_init();
curl_setopt_array($ch, array(
        CURLOPT_URL=>'http://*******',
        CURLOPT_PORT=>6050,
        CURLOPT_RETURNTRANSFER=>true
));
$data = curl_exec($ch);
if(!$data){
        die('Error['.curl_errno($ch).']: '.curl_error($ch));
}
               
$dats = explode(';',$data);
foreach($dats as $dat){
   if(strpos($dat,':')===false)continue;
   $addrs = explode(':',$dat);
   echo $addrs[0].' - '.$addrs[1].PHP_EOL.'<br/>';
   //$addrs[0] - адрес датчика
   //$addrs[1] - значение
   //mysql... тут записываем в базу
}

 

Interkom
Offline
Зарегистрирован: 09.07.2014

Что бы разобраться с этой проблемой я сделал проще.

Я загрузил Ваш код в свою тестовыю Arduino MEGA 2560 R3.

Браузер по запросу http://192.168.3.201/getdev

выдаёт показания 2871C4DC04000001:27.62;

А вот PHP пока не хочет.

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

Для начала мне нужно их получить !!! И хотябы распечатать на странице :-).

Я не совсем понимаю как работает curl.

IP адрес у меня http://192.168.3.201/

Что я должен вставить в строку :

CURLOPT_URL=>'<a href="">http://*******</a>',

При попытке вставить CURLOPT_URL=>'<a href="">http://192.168.3.201/getdev</a>',

ничего не выводится.

leshak
Offline
Зарегистрирован: 29.09.2011

Вообщем-то странно. Если вы "для просмотра" используете скетч из #29 , что-то увидеть вы просто обязаны.
Или данные, или сообщение об ошибке.

Если, перед
 

foreach($dats as $dat){

Воткнуть что-то типа:
 

echo 'Received Data<br/>'

То хоть эту надпись видно?

А если в браузере, там где вы php-дергаете, сделать View Source, там тоже пусто?

А еще смущает  CURLOPT_PORT=>6050
Если мы браузером дергаем ардуину, не указывая никаких портов, то.... по логике номер порта должен быть дефолтным. то есть - 80-тым.

Но... даже если мы ошиблись, то все равно должны что-то увидеть от 
die('Error['.curl_errno($ch).']: '.curl_error($ch));

Или он не на страницу плюет ошибку, а куда-то в лог?  Просто я с php 10-ть лет назад последний раз общался... не помню :)
Если "куда-то в лог", то искать где же эти логи...
Или заменить die на echo... и все-таки увидеть эту ошибку.
Можно даже специально что-нибудь в адресе напутать. Что-бы убедится что хотя-бы диагностинка работает верно. Невозможно "работать с тишиной".
Ни тебе ошибок, ни отвеченный хедеров я вам в #16 зачем ссылочку давал?  Показать как я умею ссылки втавлять? ;)
 

Interkom
Offline
Зарегистрирован: 09.07.2014

Всем ОГРОМНОЕ СПАСИБО !!!

Разобрался.

Код из #29 оказался для меня очень сложным. Поэтому немного погуглив и спросив товарищей получилось вот что :

при запросе http://192.168.3.177/getdev

получаем T0-23.75 ATI-42.00 HW-29.00 GND HUM-503

конечно формат не правильный, но пока так. Потом эти данные я буду записывать в разные SQL таблицы.

php код который у меня заработал.

<?php
// инициализация сеанса
$ch = curl_init();
 
// установка URL и других необходимых параметров
 
curl_setopt($ch, CURLOPT_URL, "http://192.168.3.177/getdev");
 
//результат выдаем не в браузер а в строку
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
// загрузка страницы и выдача в строку
$data = curl_exec($ch);
 
// разбиваем строку пробелом и передаем в массив
$pieces = explode(" ", $data);
//выводим переменные массива
$t0= substr($pieces[0],-5,5); // температура земли
echo $t0 . '<br>';
 
$t1= substr($pieces[1],-5,5); // температура воздуха
echo $t1 . '<br>';
 
$hw= substr($pieces[2],-5,5); // влажность воздуха
echo $hw . '<br>';
 
$gh= substr($pieces[4],-3,3); // влажность почвы
echo $gh . '<br>';
 
// Формат вывода Arduino
// T0-23.75 ATI-43.00 HW-29.00 GND HUM-508 
 
 
// завершение сеанса и освобождение ресурсов
curl_close($ch);
?>
Divest
Offline
Зарегистрирован: 04.05.2014

CURLOPT_URL=>'http://192.168.3.201/getdev', Без а href

Curl port можете убрать, это просто у меня так. 

Плюс попробуйте так, это просто отображение, без записи: 

<?             
$ch = curl_init();
curl_setopt_array($ch, array(
        CURLOPT_URL=>'http://192.168.3.201/getdev', //ИЗМЕНИТЬ
        CURLOPT_RETURNTRANSFER=>true
));
$data = curl_exec($ch);
               
               
$dats = explode(';',$data);
foreach($dats as $dat){
   if(strpos($dat,':')===false)continue;
   $addrs = explode(':',$dat);
   echo $addrs[0].' - '.$addrs[1].PHP_EOL.'<br/>';
   //$addrs[0] - адрес датчика
   //$addrs[1] - значение
   //mysql... тут записываем в базу
}

 

Посмотрите PHPINFO, там что пишет про библиотеку CURL, у меня вот так вот:

Пожалуй спрячу в код

curl

cURL support	enabled
cURL Information	7.37.0
Age	3
Features
AsynchDNS	Yes
CharConv	No
Debug	No
GSS-Negotiate	Yes
IDN	Yes
IPv6	Yes
krb4	No
Largefile	Yes
libz	Yes
NTLM	Yes
NTLMWB	Yes
SPNEGO	No
SSL	Yes
SSPI	No
TLS-SRP	Yes
Protocols	dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp
Host	x86_64-pc-linux-gnu
SSL Version	OpenSSL/1.0.1i
ZLib Version	1.2.8
libSSH Version	libssh2/1.4.3

 

Divest
Offline
Зарегистрирован: 04.05.2014

Собственно у меня остался вопрос по данному коду. В какой именно момент происходит повторный опрос с датчиков. Т.к. данные у меня не обновляются. 

Interkom
Offline
Зарегистрирован: 09.07.2014

Пока не разбирался, но думаю как то так :

в гугле набрал "запуск php страницы по расписанию"

Понравилась эта статья.

http://php.ru/forum/viewtopic.php?t=21166

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

Ещё раз ОГРОМНОЕ Вам спасибо за помощь !!!

 

Divest
Offline
Зарегистрирован: 04.05.2014

Не совсем меня правильно поняли. 

Меня интересует в коде от Сергея Очкасова, в какой момент происходит обновление данных. 

Просто у меня температура статична, если не нажать Reset на устройстве (ардуине). Собственно мне не понятно след. строка:

void loop() {
 //searchDevices();
 //delay(60000);
 char buff[64];
 int len = 64;
 webserver.processConnection(buff, &len);  // process incoming connections one at a time forever
 }

Вот что это значит. Или как можно сделать опрос датчиков раз в минуту.

С этим еще проще, если у вас nix сервер, то просто в /etc/crontab добавляем 

0-59 * * * * root /usr/bin/curl http://server_ip/script.php

И будем опрашивать датчики каждую минуту. По крону можно много где почитать. Если стоит Денвер, то можно через планировщик, или тот-же crontab для win

leshak
Offline
Зарегистрирован: 29.09.2011

Это значит, что в loop() ардуина ждет приходящие запросы и их обрабатывает.
Дальше нужно смотреть, что происходит в processConnection
При обработке каждого запроса она перечитывает датчик или нет (скорее всего - на каждый).

Следовательно что-бы получать актуальную инфу, вам нужно, как минмум регулярно слать запросы к самой ардуине.
Либо F5 в браузере нажимая, либо каким-то планироващиком запуская свой скрипт. Либо... вообще отказаться от PHP. Сделать html страничку, в ней написать маленький скриптик на javascript.... с помощью setInterval, вызывать jQuery.get() | jQuery API Documentation

Парсить полученные данные, и с помощью того jQuery выводить их на эту страничку. В резульатет - открили этот Html-льчик  и смотрите на нем актуальные данные (актуальность зависит от того какой интервал задали в setInteval).

P.S. весь javascript путь, это "само-собой" если вы хотите именно "смотреть данные". если нужно в базу ложить... то изначальный php+cron довольно оптимальный вариант.

Interkom
Offline
Зарегистрирован: 09.07.2014

Я так понимаю, что опрос датчиков происходить только по команде

http://192.168.3.201/getdev

Я не разбирался в коде (опыта не хватит :-) ). Только добавил в код несколько других датчиков и дописал вывод их результатов.

 

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

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

извиняюсь если это обсуждение уже было выше - из-за простыней кода читать трудно :)

Interkom
Offline
Зарегистрирован: 09.07.2014

Я не знаю какие задачи решает Arduino у "Divest", но у меня задача такая :

Собрать данные с датчиков, записать их в БД (для статистики и анализа)

Управлять Arduino через браузер, внутри локалки и из "внешнего мира".

Так что мне подойдёт только arduino-server.

Ещё раз прошу прощения за "простыни кода".

leshak
Offline
Зарегистрирован: 29.09.2011

Interkom пишет:

Ещё раз прошу прощения за "простыни кода".

Поробуйте другой браузер. Посмотрите не включенна ли у вас какая-нибудь "баннеро-резалка" которая скрипты коцает....
По крайней мере в chrome, если не обвешивать его 100 и одним плагином - все нормально.
А то часто попадаются "любители Оперы" (или еще какой "экзотики"), который "самый лучший браузер", только проблемы вылазять то тут, то там.... и все равно "он самый лучший".

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

Interkom пишет:

Я не знаю какие задачи решает Arduino у "Divest", но у меня задача такая :

Собрать данные с датчиков, записать их в БД (для статистики и анализа)

Управлять Arduino через браузер, внутри локалки и из "внешнего мира".

Так что мне подойдёт только arduino-server.

Блин, а я не знал что так нельзя делать :( Пойду сниму свои Ардуины.

leshak
Offline
Зарегистрирован: 29.09.2011

JollyBiber пишет:

Так что мне подойдёт только arduino-server.

Блин, а я не знал что так нельзя делать :( Пойду сниму свои Ардуины.

[/quote]

Перевод: раз у вас крутится php, то можно php сделать "сервером". Что-бы "ардуина его дергала" посылая ему свежие данные с какой-то периодичноситью. А он их принимал и ложил в базу.

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

Если быть точным: даже когда Вы что-то посылаете на сервер, то Вы можете получать ответ от него.

Interkom
Offline
Зарегистрирован: 09.07.2014

Да, конечно я так изначально и хотел, но что то не пошло. А пошло пока так :

События происходящие на ардуино (например нажатие кнопки) у меня так уже реализованно.

А вот как снимать показания с датчиков с некой переодичностью и отсылать их на server (Ubuntu + LAMP), я как и "Divest" не знаю. Он задавал именно этот вопрос в этой теме. #34 и #36.

 На данный момент так :

События происходящие на ардуино отправляются на Server и заносятся в БД.

С Servera приходят комманды на arduino (php код)

$handle = @fopen("http://192.168.3.177/command?4=ON", "r");

Сбора показаний с датчиков по запросу от Servera (вся эта тема)

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

leshak
Offline
Зарегистрирован: 29.09.2011

Interkom пишет:

А вот как снимать показания с датчиков с некой переодичностью 

А потому что начинать нужно не с "космических кораблей", а с кнопок и светодиодов.
Смотреть базовые примеры, про мигание светодиодом. С delay() и без.
Когда это будет "элементарно", то вместо "включить/выключить светодиод" подставляете "опросить датчик". И все.

И делаете это все не сразу с кучей "неизвестных", php, сервера, шилды, а обычным Serial.println отправляете на комп, переодически, состояние датчиков. По Serial.
Когда так заработает, тогда уже думаете как же это по http отправить, вместо Serial.  (тем более, судя по "кнопки так и работают" - это вы уже умеете). Если не умеете - смотрите примеры где Arduino выступает http клиентом.

Interkom
Offline
Зарегистрирован: 09.07.2014

Конечно, на примерах я кое чему научился.

Буду дальше читать и изучать. Спасибо за подсказки и помощь.

 

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

на Уно уходит около 0,5 на чтение датчика ДХТ22, и пару секунд на соединение с сервером. Таким образом дуня шлет показания каждые 3 секунды (это если больше ничего нет в цикле). Периодичность посылки можно ограничить таймером. Сервер в любом (нормальном) случае пришлет ответ, но Вам ничего не мешает добавить свой текст к ответу и отловить на Ардуине.

Divest
Offline
Зарегистрирован: 04.05.2014

К месту это будет сказано, или нет. Но при выборе структуры при построении концепции системы опроса датчиков и управления конечными устройствами, мне показалось такой способ намного лучше. Да, я реализовывал конечные устройства с посылкой данных на сервер, и это даже проще, чем их опрашивать (хотя особой разницы нет). Скорее у меня отсутсвует опыт программирования микроконтроллеров для решения всех моих желаний. И я собственно пошел по более простому пути для меня. Для меня это более удобно\привычно. В целом, микроконтреллер должен выполнять все алгоритмы сам, без участия компьютера, а компьютер необходим лишь для визуального контроля и ручного управления. Собственно перекладывать функцию опроса датчиков на сам датчик, не особо практично. При условии, что в квартире будет 10-20 датчиков, и уже вшитых в стены, на сколько практично будет их перепрограммировать на новые адреса сервера? Или после изменения свойств в таблице баз данных, не проще переписать скрипт на сервере, чем каждый отдельный датчик. Нужна универсальность и масштабируемость, но если эти данные писать в железку, то ничего этого не будет.

И да, в большой степени, lamp/apache сервер, это визуализация, упрощение ввода/вывода данных. 

leshak
Offline
Зарегистрирован: 29.09.2011

JollyBiber пишет:

 Сервер в любом (нормальном) случае пришлет ответ, но Вам ничего не мешает добавить свой текст к ответу и отловить на Ардуине.

Нафига? Если цель - положить показания датчика в базу? Зачем еще что-то отвечать, городить парсинг ответа на ардуине и т.п.?  Послали данные - и все. Ну максимум проверили что http 200 вернулся (если нет - зажгли какую-то красную аварийную лампочку). И то... уже "по желанию".