AMS <-> AMS Туды Сюды
Модератор: Alex
-
- Сообщения: 2357
- Зарегистрирован: Пт апр 20, 2012 12:53 pm
- Благодарил (а): 42 раза
- Поблагодарили: 262 раза
Re: AMS <-> AMS Туды Сюды
Можно и MQTT, особенно если он уже есть в сети. Если нет, то «волочь» лишний контроллер (а в случае брокера уже не контроллер, а мини-компьютер) не всегда хочется (вернее, всегда не хочется). Идеология АМС — множество самодостаточных лёгких контроллеров с веб-интерфейсом. И я думаю, что проблемы с обменом данными между АМС можно решить.
-
- Сообщения: 88
- Зарегистрирован: Сб окт 24, 2015 9:56 pm
- Благодарил (а): 11 раз
- Поблагодарили: 8 раз
Re: AMS <-> AMS Туды Сюды
Честно говоря никогда не работал с MQTT. Вариант интересный, попозже почитаю. Сейчас хотелось бы решить задачу без сторонних устройств.
Есть две идеи:
1. Собрать нужные переменные в один запрос и отправлять его через какой то промежуток времени (руками написать) вариант не очень удобный для последующего изменения программы.
2. Сделать функцию, которая будет собирать все запросы в буфер (буферы) и потом в конце цыкла отправлять. По очереди или все сразу.
Есть две идеи:
1. Собрать нужные переменные в один запрос и отправлять его через какой то промежуток времени (руками написать) вариант не очень удобный для последующего изменения программы.
2. Сделать функцию, которая будет собирать все запросы в буфер (буферы) и потом в конце цыкла отправлять. По очереди или все сразу.
- nick7zmail
- Сообщения: 7573
- Зарегистрирован: Пн окт 28, 2013 8:14 am
- Откуда: Екатеринбург
- Благодарил (а): 121 раз
- Поблагодарили: 2010 раз
Re: AMS <-> AMS Туды Сюды
Как вариант можно логику немного поменять...ledmax писал(а):АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС Б посылает GET зарос на АМС А - насос включен?
АМС А отвечает АМС Б - насос включен
АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС А посылает GET отчет на АМС Б - насос включен
А периодические переменные передавать json строкой к примеру...или множественным get запросом (с несколькими параметрами)
- За это сообщение автора nick7zmail поблагодарил:
- ledmax (Сб апр 22, 2017 8:16 pm)
- Рейтинг: 1.16%
Raspberry Pi3+Broadlink+esp8266 (blynk)+AMS
Если вам помогло какое-либо сообщение - не забывайте пользоваться кнопкой "СПАСИБО".
Услуги в профиле коннект
>>>>>Мой новый канал на ютутбе, подписывайтесь!<<<<<
Если вам помогло какое-либо сообщение - не забывайте пользоваться кнопкой "СПАСИБО".
Услуги в профиле коннект
>>>>>Мой новый канал на ютутбе, подписывайтесь!<<<<<
-
- Сообщения: 88
- Зарегистрирован: Сб окт 24, 2015 9:56 pm
- Благодарил (а): 11 раз
- Поблагодарили: 8 раз
Re: AMS <-> AMS Туды Сюды
Идея норм, но есть пару нюансов)nick7zmail писал(а):Как вариант можно логику немного поменять...ledmax писал(а):АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС Б посылает GET зарос на АМС А - насос включен?
АМС А отвечает АМС Б - насос включен
АМС Б посылает GET зарос на АМС А - включить насос
АМС А включает насос
АМС А посылает GET отчет на АМС Б - насос включен
А периодические переменные передавать json строкой к примеру...или множественным get запросом (с несколькими параметрами)
1. Будет плохо работать с кнопками - например если вы в веб морде нажали вкл насос, но надо бы сразу получить ответ
2. Будет нагружать АМС А сбором не нужных данных
3. У меня все переменные в глобальном массиве и имеют имена - например OUT_CircuPumpON compressor_ON итд.. Эта переменная и есть выход контроллера и по его имени происходит парсинг запросов. Т.е. В контроллере А OUT_CircuPumpON и в контроллере Б OUT_CircuPumpON . Очень удобно. Если для каждой переменной присваивать ещё сокращение, то потом не разберёшься, что, куда..
- nick7zmail
- Сообщения: 7573
- Зарегистрирован: Пн окт 28, 2013 8:14 am
- Откуда: Екатеринбург
- Благодарил (а): 121 раз
- Поблагодарили: 2010 раз
Re: AMS <-> AMS Туды Сюды
Дак ответ то вторая ардуина посылает сразу как только включит насос...так что первый нюанс отметается))
А на счет второго - собирать/отправлять только нужные данные)
А на счет второго - собирать/отправлять только нужные данные)
Raspberry Pi3+Broadlink+esp8266 (blynk)+AMS
Если вам помогло какое-либо сообщение - не забывайте пользоваться кнопкой "СПАСИБО".
Услуги в профиле коннект
>>>>>Мой новый канал на ютутбе, подписывайтесь!<<<<<
Если вам помогло какое-либо сообщение - не забывайте пользоваться кнопкой "СПАСИБО".
Услуги в профиле коннект
>>>>>Мой новый канал на ютутбе, подписывайтесь!<<<<<
-
- Сообщения: 88
- Зарегистрирован: Сб окт 24, 2015 9:56 pm
- Благодарил (а): 11 раз
- Поблагодарили: 8 раз
Re: AMS <-> AMS Туды Сюды
Есть эксперты по strtok?
Собрал такого крокодила:
В функции
Первый код разбивает запрос на пары и по парам посылает в функцию, где уже разбивается на переменные и значения, затем идёт присвоение переменным значений.
из плюсов - нету разницы какой длины запрос (сколько переменных) и очень быстро работает.
из минусов - не работает
В общем если из функции убрать
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 в функции как то модифицирует строку в основном цикле или сдвигает указатель.. Не могу разобраться. Кто нибудь силён в этих тонкостях?
Собрал такого крокодила:
Код: Выделить всё
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");
}
}
}
из плюсов - нету разницы какой длины запрос (сколько переменных) и очень быстро работает.
из минусов - не работает
В общем если из функции убрать
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 в функции как то модифицирует строку в основном цикле или сдвигает указатель.. Не могу разобраться. Кто нибудь силён в этих тонкостях?
-
- Сообщения: 88
- Зарегистрирован: Сб окт 24, 2015 9:56 pm
- Благодарил (а): 11 раз
- Поблагодарили: 8 раз
Re: AMS <-> AMS Туды Сюды
Решил проблему, но не без помощи
Код: Выделить всё
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");
}
}
}
}
-
- Сообщения: 88
- Зарегистрирован: Сб окт 24, 2015 9:56 pm
- Благодарил (а): 11 раз
- Поблагодарили: 8 раз
Re: AMS <-> AMS Туды Сюды
Выкладываю рабочее решение, вариант может не идеальный, но работает стабильно. Вопрос-ответ происходит в течении одной сессии. Если есть переложения по улучшению, то пожалуйста...
Формирование запроса и приём ответа (АМС А)
Вызов функции - установка
Вызов функции - запрос
Приём запроса и отправка ответа (АМС Б)
Формирование запроса и приём ответа (АМС А)
Код: Выделить всё
//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");
}
-
- Сообщения: 791
- Зарегистрирован: Пт янв 22, 2016 10:08 am
- Благодарил (а): 6 раз
- Поблагодарили: 63 раза