Скетч Arduino + W5100 обсуждаем, пишем, тестируем

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

Модератор: immortal

Devil_Blood
Сообщения: 6
Зарегистрирован: Пн фев 04, 2019 10:35 pm
Благодарил (а): 1 раз
Поблагодарили: 0

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение Devil_Blood » Пт апр 19, 2019 1:08 am

woow писал(а):
Вт фев 19, 2019 3:01 pm
вот застрял. Почему публикуется с разу по четыре состояния каждой пуликации:
led1 on
led1 on
led1 on
led1 on
led2 on
led2 on
led2 on
led2 on
........
а потом когда уже команды приходят о изменении состояния уже меняются только по одной
led1 off
led1 on
led1 on
led1 on
led2 off
led2 on
led2 on
led2 on
................
У меня такой проблемы нет. после запуска скетча определилось 4 позиции, дублирующих нет. статусы так же нормально определяются при нажатии на кнопку. но вот с самого сервера посылая команды, ардуинка не реагирует. или тут не реализовано управление с сервера? только статусы? или я что-то не так делаю :(

p.s
Спасибо за скетч! :D
Alexiy2
Сообщения: 104
Зарегистрирован: Вт май 12, 2015 9:59 pm
Благодарил (а): 16 раз
Поблагодарили: 13 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение Alexiy2 » Ср окт 02, 2019 2:26 pm

Господа!!! Помогите пожалуйста!
Не могу разобраться каким образом отправить статус реле на Алису!
Взял скетч с данной темы в редакции m-malva (первый пост на 27 странице):

Код: Выделить всё

/**
* Контроллер-исполнительное устройство (к проекту http://smartliving.ru/)
* Platform: Arduino UNO R3 + EthernetShield W5100
* IDE: Arduino 1.0.1
*
* исполнительные устройства (реле) подключены к Digital 3 - 9
* управляющие кнопки  14 - 18 
* обращение по 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 <math.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xE4, 0xDE, 0x33 }; // MAC-адрес нашего устройства
byte ip[] = { 192, 168, 0, 24 };
byte subnet[] = { 255, 255, 255, 0 };
byte gateway[] = { 192, 168, 0, 1 };
byte dns_server[] = { 192, 168, 0, 1 };
// ip-адрес удалённого сервера
byte server[] = { 192, 168, 0, 2 }; //Адрес сервера MAJORDOMO
char buf[80];
char ipbuff[16];

EthernetClient rclient;
// Функция отправки HTTP-запроса на сервер
void sendHTTPRequest() {
  Serial.println(buf); 
  if (rclient.connect(server, 80)) { 
   rclient.print(buf);
   rclient.println(" HTTP/1.0");
   Serial.println("Send http get request");
   Serial.println(buf);
   rclient.print("Host: ");
   sprintf(ipbuff, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
   rclient.println(ipbuff); // ip адрес нашего контроллера в текстовом виде
   rclient.print("Content-Type: text/html\n");
   rclient.println("Connection: close\n");
   delay(1000);
   rclient.stop();
  } else {
   Serial.println("FAILED");     
  }
}

void sendAPin(int a) {
   int DPin = a-11;
if (digitalRead(a)==LOW){//если кнопка нажата и перемення flag равна 0 , то ... 
    digitalWrite(DPin,!digitalRead(DPin)); //Инвертируем выход
    Serial.print("Button: ");
    Serial.print(a);
    Serial.print(" Pin: ");
    Serial.print(DPin);
    Serial.print(" = ");    
    Serial.println(digitalRead(DPin));
//  sprintf(buf, "GET /objects/?object=sensor222%i&op=m&m=st&status=%i", DPin, digitalRead(DPin));//Готовим запрос на сервер
    sprintf(buf, "GET /objects/?op=set&object=sensor222%i&p=status&v=%i", DPin, digitalRead(DPin));//Готовим запрос на сервер
    sendHTTPRequest();

}    
}


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

// Настройки входов
int startAPin=14;
int endAPin=18;


// 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.2"
#define COMPILE_DATE_STRING "2015-11-14"

P(Page_info) = "<html><head><title>" COMPILE_DATE_STRING" " VERSION_STRING "</title></head><body>\n";
P(location_info) = "NA";
P(pin_info) = "D2 - 1-wire";
P(version_info) = VERSION_STRING " " 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("Command not found");
  }
}


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

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

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

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

void commandsLClick(WebServer &server) {
  if (gParamValue>=startPin && gParamValue<=endPin) {
     digitalWrite(gParamValue,LOW);     
     delay(delayLClick);
     digitalWrite(gParamValue,HIGH);
  } 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("This Pin is not 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();
   sensors.requestTemperatures();
   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>State: ");
  strcpy (gParamBuffer, "ALL");
  commandsStatus(server);
  server.print("<br><a href='/getdev'>getdev</a>");
  server.print("<hr>Commands:<br>");
  commandsHelp(server);
  server.print("<hr>Version: ");
  server.printP(version_info);
  
}


/**********************************************************************************************************************
* Поиск устройств (датчиков температуры на шине 1-wire)
**/
void searchDevices() {
   Serial.println("Search on 1-wire");
   int numberOfDevices = sensors.getDeviceCount();
   sensors.begin();
   
   for(int i=0;i<numberOfDevices; i++) {
      if(sensors.getAddress(Termometers, i))
      {
          Serial.print("Device ");
            Serial.print(i, DEC);
          Serial.print(" 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(" 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
//  sprintf(buf, "GET /objects/?script=controller_widget&dev=%u.%u.%u.%u&code=start",ip[0], ip[1], ip[2], ip[3]);//Готовим запрос на сервер
//  sendHTTPRequest();  

  webserver.setDefaultCommand(&infoRequest); // дефолтная страница вывода (информация о контроллере)
  webserver.addCommand("command", &parsedRequest); // команды
  webserver.addCommand("state", &stateRequest); // выдать состояния всех устройств
  webserver.addCommand("getdev", &get1wireDevices); // получить список устройств на 1-wire
  webserver.begin();
  
  Serial.print("IP ");
  Serial.println(Ethernet.localIP());
  
    // Настройка портов
  for (int thisAPin = startAPin; thisAPin <=endAPin; thisAPin++)  {
    pinMode(thisAPin, INPUT);      
  }
    // Настройка портов
  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;

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

/* Работа с выключателями
*/
          for(int i=startAPin;i<=endAPin;i++) {
 
            int st=digitalRead(i);
            char my_st[5];
            itoa(st,my_st,10);
             if (st==1)
             {
                sendAPin(i);
             }
          }

  webserver.processConnection(buff, &len);  // process incoming connections one at a time forever
}
залил на Ардуино, все работает (спасибо автору за него), но на сервер статус реле не приходит.
уже не единожды прочитал данный форум, все что касается подключения ардуино, заглянул в азбуку, но все без результатно.
Через браузер отправил запрос вида: 192.168.0.2/objects/?object=sensor2223&op=m&m=st&status=1, но заветного ОК не получил.
Прочитал азбуку и нашел HTTP-ссылки:
https://kb.mjdm.ru/http-ssilki-dlya-raboti-s-majordomo/
/objects/?op=set&object=<OBJECT>&p=<PROPERTY>&v=<VALUE>
попробовал ввести в баузере запрос вида: http://192.168.0.2/objects/?op=set&obje ... status&v=1 и...
... получил долгожданную надпись ОК. Заглянул в свойство обекта sensor2223, там стояла заветная единица. Подправил запрос в скетче на:
sprintf(buf, "GET /objects/?op=set&object=sensor222%i&p=status&v=%i", DPin, digitalRead(DPin));
но ардуино ни как не хочет передавать статус Алисе.
Что может быть??? Уже не первый месяц мучаю данную проблему, но мне ее ни как не побороть...
ВЫРУЧАЙТЕ друзья! У кого какие мысли могут быть???
P.S. Алиса живет на Ubuntu server 16.04
Аватара пользователя
nick7zmail
Сообщения: 7573
Зарегистрирован: Пн окт 28, 2013 8:14 am
Откуда: Екатеринбург
Благодарил (а): 121 раз
Поблагодарили: 2010 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение nick7zmail » Ср окт 02, 2019 2:38 pm

Код: Выделить всё

* обращение по http://xx.xx.xx.xx/ выдаст справочную информацию по этому устройству (нужно для того, чтобы когда обращаешься
* по IP к устройству понять что это за контроллер и пр.)
*
* /state - состояние всех портов
Написано же - надо обратиться к контроллеру по IP адресу, на путь /state. Обратиться можно к примеру скриптом из МД, расшифровать ответ, раскидать по свойствам.

Второй вариант - закидывать самим контроллером статус, что вы и пытаетесь сделать.
sprintf(buf, "GET /objects/?op=set&object=sensor222%i&p=status&v=%i", DPin, digitalRead(DPin));
только кладёт в буфер buf строку с нужными значениями...вам после этого нужно выполнить get запрос. В экзамплах есть примеры....или в инете где нить гляньте https://cxem.net/arduino/arduino176.php
Raspberry Pi3+Broadlink+esp8266 (blynk)+AMS
Если вам помогло какое-либо сообщение - не забывайте пользоваться кнопкой "СПАСИБО".
:arrow: Услуги в профиле коннект
>>>>>Мой новый канал на ютутбе, подписывайтесь!<<<<<
Alexiy2
Сообщения: 104
Зарегистрирован: Вт май 12, 2015 9:59 pm
Благодарил (а): 16 раз
Поблагодарили: 13 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение Alexiy2 » Ср окт 02, 2019 6:35 pm

nick7zmail писал(а):
Ср окт 02, 2019 2:38 pm

Код: Выделить всё

* 
Второй вариант - закидывать самим контроллером статус, что вы и пытаетесь сделать.
sprintf(buf, "GET /objects/?op=set&object=sensor222%i&p=status&v=%i", DPin, digitalRead(DPin));
только кладёт в буфер buf строку с нужными значениями...вам после этого нужно выполнить get запрос.

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

P.S. Все же в логах присутствует запись от контроллера: 192.168.0.24 - - [02/Oct/2019:19:22:32 +0300] "GET /objects/?op=set&object=sensor2223&p=status&v=1 HTTP/1.0" 400 0 "-" "-"
Но как видно присутствует ошибка 400.
400 Bad Request
Запрос не может быть исполнен ввиду синтаксической ошибки.
Когда этот код может использоваться? Когда пользователь запрашивает информацию, но делает это, пренебрегая правилами протокола передачи гипертекста. Запрос не следует повторять без изменения синтаксиса.
Как бороться в данной ситуации??? Обычный браузер же отрабатывает данный GET запрос
Alexiy2
Сообщения: 104
Зарегистрирован: Вт май 12, 2015 9:59 pm
Благодарил (а): 16 раз
Поблагодарили: 13 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение Alexiy2 » Чт окт 03, 2019 6:51 pm

Не уж то ни кто подсказать не может? У многих же система на ардуинках собрана...
Аватара пользователя
woow
Сообщения: 821
Зарегистрирован: Пн июл 04, 2016 8:46 am
Откуда: Mazeikiai
Благодарил (а): 125 раз
Поблагодарили: 46 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение woow » Чт окт 03, 2019 7:05 pm

Alexiy2 писал(а):
Чт окт 03, 2019 6:51 pm
Не уж то ни кто подсказать не может? У многих же система на ардуинках собрана...
Да ну . От куда такие выводы? И если и Arduino есть почему обезательно и этот скетч ?
Raspberry Pi 3B+
Alexiy2
Сообщения: 104
Зарегистрирован: Вт май 12, 2015 9:59 pm
Благодарил (а): 16 раз
Поблагодарили: 13 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение Alexiy2 » Чт окт 03, 2019 7:53 pm

Мои личные умозаключения. Судя по страницам форума (А их не мало) и количеству человеков писавших туда.
Проблема то в том, что система не хочет принимать get запросы от ардуино. Я многие скетчи перепробовал, что сами должны возвращать данные на сервер. Один из них в теме про ардуину и кучи датчиков температурных.
Все отправляют, но в логе apache у всех ответов от ардуино стоит 400 ошибка. Не могу ее побороть. Мозги уже закипают... :oops:
Аватара пользователя
nick7zmail
Сообщения: 7573
Зарегистрирован: Пн окт 28, 2013 8:14 am
Откуда: Екатеринбург
Благодарил (а): 121 раз
Поблагодарили: 2010 раз

Re: Скетч Arduino + W5100 обсуждаем, пишем, тестируем

Сообщение nick7zmail » Пт окт 04, 2019 6:38 am

Я обычно таким гемором не занимался если честно (Только в самом начале, когда на ардуино писать начинал. Всё работало. Давно таким способом не пользуюсь.). Сейчас если надо с ардуины на сервер передать - пользуюсь mqtt. Когда можно не на прямую - то проще сервисами типа blynk.
Raspberry Pi3+Broadlink+esp8266 (blynk)+AMS
Если вам помогло какое-либо сообщение - не забывайте пользоваться кнопкой "СПАСИБО".
:arrow: Услуги в профиле коннект
>>>>>Мой новый канал на ютутбе, подписывайтесь!<<<<<
Ответить