Страница 2 из 3

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб апр 22, 2017 7:29 pm
Alex
Можно и MQTT, особенно если он уже есть в сети. Если нет, то «волочь» лишний контроллер (а в случае брокера уже не контроллер, а мини-компьютер) не всегда хочется (вернее, всегда не хочется). Идеология АМС — множество самодостаточных лёгких контроллеров с веб-интерфейсом. И я думаю, что проблемы с обменом данными между АМС можно решить.

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб апр 22, 2017 7:40 pm
ledmax
Честно говоря никогда не работал с MQTT. Вариант интересный, попозже почитаю. Сейчас хотелось бы решить задачу без сторонних устройств.
Есть две идеи:
1. Собрать нужные переменные в один запрос и отправлять его через какой то промежуток времени (руками написать) вариант не очень удобный для последующего изменения программы.
2. Сделать функцию, которая будет собирать все запросы в буфер (буферы) и потом в конце цыкла отправлять. По очереди или все сразу.

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб апр 22, 2017 8:12 pm
nick7zmail
ledmax писал(а):АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС Б посылает GET зарос на АМС А - насос включен?
АМС А отвечает АМС Б - насос включен
Как вариант можно логику немного поменять...
АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС А посылает GET отчет на АМС Б - насос включен

А периодические переменные передавать json строкой к примеру...или множественным get запросом (с несколькими параметрами)

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб апр 22, 2017 8:30 pm
ledmax
nick7zmail писал(а):
ledmax писал(а):АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС Б посылает GET зарос на АМС А - насос включен?
АМС А отвечает АМС Б - насос включен
Как вариант можно логику немного поменять...
АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС А посылает GET отчет на АМС Б - насос включен

А периодические переменные передавать json строкой к примеру...или множественным get запросом (с несколькими параметрами)
Идея норм, но есть пару нюансов)

1. Будет плохо работать с кнопками - например если вы в веб морде нажали вкл насос, но надо бы сразу получить ответ
2. Будет нагружать АМС А сбором не нужных данных
3. У меня все переменные в глобальном массиве и имеют имена - например OUT_CircuPumpON compressor_ON итд.. Эта переменная и есть выход контроллера и по его имени происходит парсинг запросов. Т.е. В контроллере А OUT_CircuPumpON и в контроллере Б OUT_CircuPumpON . Очень удобно. Если для каждой переменной присваивать ещё сокращение, то потом не разберёшься, что, куда..

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб апр 22, 2017 11:05 pm
nick7zmail
Дак ответ то вторая ардуина посылает сразу как только включит насос...так что первый нюанс отметается))
А на счет второго - собирать/отправлять только нужные данные)

Re: AMS <-> AMS Туды Сюды

Добавлено: Пн апр 24, 2017 8:50 pm
ledmax
Есть эксперты по strtok? :)

Собрал такого крокодила:

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

else if(StrContains(HTTP_req, "GET /GTX?")) { //вид запроса GET /GTX?OUT_CircuPumpON=0&MHC_T_boil2=35&
   // sendXmlAnswer(cl);
      Serial.println(HTTP_req);Serial.print("\n");
         int i = 1;
         strtok(HTTP_req, "?"); // убираем GET /GTX
         char* httpreq = strtok(NULL, "%");// выделяем строку от ? до %
         strtok(httpreq, "&"); //Первая пара
              while (httpreq != NULL){   //Крутим пока не закончатся пары
                parsecom(i, httpreq);
                httpreq = strtok(NULL, "&");
                i++;
                }
      }
 
В функции

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

 void parsecom(int number, char* data){
        Serial.print(number);
        Serial.print(" ");
        Serial.print(data);Serial.print("\n");

            
            char* Valuename = strtok(data, "="); 
            const char *lp_ptr = strtok(NULL, "=");
            int value = atoi(lp_ptr); 

         for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными
          if (!strcmp(Valuename, valuename_strs[i])) {
            values[i] = value;
            Serial.print( valuename_strs[i]);
            Serial.print(": ");
            Serial.print(values[i]);
            Serial.print("\n");
          }
        }  
      }
 
Первый код разбивает запрос на пары и по парам посылает в функцию, где уже разбивается на переменные и значения, затем идёт присвоение переменным значений.

из плюсов - нету разницы какой длины запрос (сколько переменных) и очень быстро работает.
из минусов - не работает :D

В общем если из функции убрать
char* Valuename = strtok(data, "=");
const char *lp_ptr = strtok(NULL, "=");
int value = atoi(lp_ptr);

То всё прекрасно - в сериал летят 1 OUT_CircuPumpON=0 , MHC_T_boil2=35 итд... но если добавляем код разбора переменной, то разбирается только первая пара и потом программа выходит из while . Такое чувство, что strtok в функции как то модифицирует строку в основном цикле или сдвигает указатель.. Не могу разобраться. Кто нибудь силён в этих тонкостях?

Re: AMS <-> AMS Туды Сюды

Добавлено: Вт апр 25, 2017 10:15 pm
ledmax
Решил проблему, но не без помощи :)

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

else if(StrContains(HTTP_req, "GET /GTX?")) { //вид запроса GET /GTX?OUT_CircuPumpON=0&MHC_T_boil2=35 HTTP/1.1
 
  char * pairPotinter = strtok(HTTP_req, "?");
   for (pairPotinter = strtok(NULL, "="); pairPotinter; pairPotinter = strtok(NULL, "=")) {
    const char * valuePointer = strtok(NULL, "&");
    int value = atoi(valuePointer); //перводим const char * valuePointer в int value
    
        for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными
          if (!strcmp(pairPotinter, valuename_strs[i])) {
            values[i] = value;
            Serial.print( valuename_strs[i]);
            Serial.print(": ");
            Serial.print(values[i]);
            Serial.print("\n");
          }
       }
   }
} 

Re: AMS <-> AMS Туды Сюды

Добавлено: Вс май 07, 2017 8:07 am
ledmax
Выкладываю рабочее решение, вариант может не идеальный, но работает стабильно. Вопрос-ответ происходит в течении одной сессии. Если есть переложения по улучшению, то пожалуйста...

Формирование запроса и приём ответа (АМС А)

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

//sendreq
const boolean set = 1;
const boolean req = 0;

#define ANSW_BUF_SIZE 128
char HTTP_answ[ANSW_BUF_SIZE] = {0};

// target net settings
byte MHC_IP[] = {192, 168, 2, 105};  //MainHeatController в подвале дома
int MHC_PORT = 80;

WiFiClient tclient;


void sendHttpComand(byte ip[], int port, boolean act, char object1[],int value1, char object2[],int value2, char object3[], int value3, WiFiClient tclient) { //Отправка команды или  запроса
  String s = "";
  
    tclient.connect(ip, port); 
    delay(500);
    if(tclient.connected()){
      
                          #ifdef SENDREQU_DEBUG
    timeStamp();
    Serial.print("Host ");
    printIp(ip);
    Serial.print(" ");
                          #endif
    if(act){                      
    s += "GET /ValSet?";
    s += object1;
    s += "=";
    s += value1;
    if(object2 != "empty"){
    s += "&";
    s += object2;
    s += "=";
    s += value2;
    if(object3 != "empty"){
    s += "&";
    s += object3;
    s += "=";
    s += value3;
    }
    }
    s += '\n';
    }
    else{
      s += "GET /ValReq?";
      s += object1;
      s += "&";
      if(object2 != "empty"){
      
      s += object2;
      s += "&";
      if(object3 != "empty"){
      
      s += object3;
      s += "&";
      }
      }
      s += '\n';
    }
    tclient.println(s); 
        

                          #ifdef SENDREQU_DEBUG
    Serial.println(s);
                          #endif
    //формируем ответ                      
    int answIndex = 0;
     while (tclient.connected()) {
      if (tclient.available()) {
        char c = tclient.read(); 
         if (answIndex < ANSW_BUF_SIZE - 1) {
          HTTP_answ[answIndex] = c;
          answIndex++;
         }
       }
     }
    delay(100);
                         #ifdef SENDREQU_DEBUG
     Serial.println(HTTP_answ);
                          #endif
    
     tclient.stop();//получили ответ - отключаем клиента
        
//разбираем ответ и назначаем переменные
    char * pairPotinter = strtok(HTTP_answ, "&");
    Serial.println(pairPotinter);
    for (pairPotinter = strtok(NULL, "="); pairPotinter; pairPotinter = strtok(NULL, "=")) {
    const char * valuePointer = strtok(NULL, "&");
    int value = atoi(valuePointer); //перводим const char * valuePointer в int value
    
        for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными
          if (!strcmp(pairPotinter, valuename_strs[i])) {
            values[i] = value;
            Serial.print("\n");
            Serial.print( valuename_strs[i]);
            Serial.print(": ");
            Serial.print(values[i]);
            Serial.print("\n");
          }
       }
   }
  
  StrClear(HTTP_answ, ANSW_BUF_SIZE); //чистим буфер приёма
      
  } else {     //если не получучилось подключится к клиенту
      timeStamp();
      Serial.print("Host ");
      printIp(ip);
      Serial.print(" not connected (");
      Serial.println(")");
    }


} 
Вызов функции - установка

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

 sendHttpComand(MHC_IP, MHC_PORT, set,  "OUT_CircuPumpON",1,"empty",0 ,"empty",0, tclient); 
Вызов функции - запрос

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

sendHttpComand(MHC_IP, MHC_PORT, req ,"MHC_T_boil2",0 ,"empty",0 ,"empty",0, tclient); 
Приём запроса и отправка ответа (АМС Б)

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

if (StrContains(HTTP_req, "GET /ValSet?")) {
  String s = "";
       s += "response";
    //   s += "?";
 char * pairPotinter = strtok(HTTP_req, "?");
   for (pairPotinter = strtok(NULL, "="); pairPotinter; pairPotinter = strtok(NULL, "=")) {
    const char * valuePointer = strtok(NULL, "&");
    int value = atoi(valuePointer); //перводим const char * valuePointer в int value
    
        for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными
          if (!strcmp(pairPotinter, valuename_strs[i])) {
            values[i] = value;

            s += "&";
            s += valuename_strs[i];
            s += "=";
            s += values[i];

            Serial.print( valuename_strs[i]);
            Serial.print(": ");
            Serial.print(values[i]);
            Serial.print("\n");
          }
       }
   }

   s += '\n';
   sclient.println(s);
   Serial.println(s);
   Serial.print("\n");
}



    else if(StrContains(HTTP_req, "GET /ValReq?")){


       String s = "";
       s += "response";

 char * pairPotinter = strtok(HTTP_req, "?");
   for (pairPotinter = strtok(NULL, "&"); pairPotinter; pairPotinter = strtok(NULL, "&")) {
    for (byte i = 0; i < MAX_VAR; i++) {//сравниваем Valuename c нашими переменными
          if (!strcmp(pairPotinter, valuename_strs[i])) {

            s += "&";
            s += valuename_strs[i];
            s += "=";
            s += values[i];
            

            Serial.print( valuename_strs[i]);
            Serial.print(": ");
            Serial.print(values[i]);
            Serial.print("\n");
          }
       }
   }

   s += '\n';
   sclient.println(s);
   Serial.println(s);
   Serial.print("\n");
} 

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб авг 19, 2017 1:55 pm
alexsis_76
а почему бы http запрос не заменить на tcp?

Re: AMS <-> AMS Туды Сюды

Добавлено: Сб авг 19, 2017 3:12 pm
ledmax
??!