openhab_arduino_mqtt Ардуино перестает реагировать на команды и слать топики

vovankin
Offline
Зарегистрирован: 11.10.2014

Добрый день.
Сам я не программист(прошу отнестись с пониманием)
Из разных источников собрал код под свои нужды.
Управление через OpenHab Ардуиной по протоколу MQTT.
Управление/получение информации от ардуино идет какое то время нормально(например сутки).
Потом ардуино перестает реагировать на команды и отправлять температуру.
Предполагаю, что переполняется память. Но точно не знаю.
Уважаемые программисты подскажите, что в коде поправить что бы работало стабильно.

// Arduino_w5100_mqtt_10 rele_6Temp_2Konc_DHT11


#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#define ONE_WIRE_BUS 2 // пин для датчиков температуры
#define rel1_pin 19
#define rel2_pin 16
#define rel3_pin 4
#define rel4_pin 5
#define rel5_pin 6
#define rel6_pin 7
#define rel7_pin 8
#define rel8_pin 9
#define rel9_pin 18
#define rel10_pin 17
#define DHTPIN 3 
#define DHTTYPE DHT11   // DHT 11

const int konc1_pin = 14; 
const int konc2_pin = 15; 

int val1 = 0;
int val2 = 0;
char REL1;
char REL2;
char REL3;
char REL4;
char REL5;
char REL6;
char REL7;
char REL8;
char REL9;
char REL10;
char tmp1[10];
char tmp2[10];
char tmp3[10];
char tmp4[10];
char tmp5[10];
char tmp6[10];
char tUstav1;
char StrtUstav11[3];
unsigned long loopTime;
unsigned long currentTime;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = { 0x28, 0x1C, 0xC1, 0x5D, 0x06, 0x00, 0x00, 0x43 };
DeviceAddress Thermometer2 = { 0x28, 0xFF, 0xE7, 0x2C, 0xA6, 0x15, 0x01, 0xCB };
DeviceAddress Thermometer3 = { 0x28, 0xFF, 0xE7, 0x2C, 0xA6, 0x15, 0x01, 0xCB };
DeviceAddress Thermometer4 = { 0x28, 0xFF, 0xE7, 0x2C, 0xA6, 0x15, 0x01, 0xCB };
DeviceAddress Thermometer5 = { 0x28, 0xFF, 0xE7, 0x2C, 0xA6, 0x15, 0x01, 0xCB };
DeviceAddress Thermometer6 = { 0x28, 0xFF, 0xE7, 0x2C, 0xA6, 0x15, 0x01, 0xCB };
IPAddress ip(192, 168, 1, 22);
IPAddress server(192, 168, 1, 25);
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };


DHT dht(DHTPIN, DHTTYPE);
void callback(char* topic, byte* payload, unsigned int length) {
// Выделяем необходимое кол-во памяти для копии payload
  byte* p = (byte*)malloc(length);
// Копирование payload в новый буфер
  memcpy(p, payload, length);
// то что было ранее
payload[length] = '\0';
//free(p); \\это не понятно куда поставить
Serial.print(topic);
Serial.print(" ");
String strTopic = String(topic);
String strPayload = String((char*)payload);
Serial.println(strPayload);

if (strTopic == "test/device/arduino01/rel1") {
if (strPayload == "ON"){REL1 = 1;}
else if (strPayload == "OFF"){REL1 = 0;}
}
else if (strTopic == "test/device/arduino01/rel2") {
if (strPayload == "ON") {REL2 = 1;}
else if (strPayload == "OFF") {REL2 = 0;}
}
else if (strTopic == "test/device/arduino01/rel3") {
if (strPayload == "ON") {REL3 = 1;}
else if (strPayload == "OFF") {REL3 = 0;}
}
else if (strTopic == "test/device/arduino01/rel3") {
if (strPayload == "ON") {REL3 = 1;}
else if (strPayload == "OFF") {REL3 = 0;}
}
else if (strTopic == "test/device/arduino01/rel4") {
if (strPayload == "ON") {REL4 = 1;}
else if (strPayload == "OFF") {REL4 = 0;}
}
else if (strTopic == "test/device/arduino01/rel5") {
if (strPayload == "ON") {REL5 = 1;}
else if (strPayload == "OFF") {REL5 = 0;}
}
else if (strTopic == "test/device/arduino01/rel6") {
if (strPayload == "ON") {REL6 = 1;} 
else if (strPayload == "OFF") {REL6 = 0;}
}
else if (strTopic == "test/device/arduino01/rel7") {
if (strPayload == "ON") {REL7 = 1;}
else if (strPayload == "OFF") {REL7 = 0;}
}
else if (strTopic == "test/device/arduino01/rel8") {
if (strPayload == "ON") {REL8 = 1;}
else if (strPayload == "OFF") {REL8 = 0;}
}
else if (strTopic == "test/device/arduino01/rel9") {
if (strPayload == "ON") {REL9 = 1;}
else if (strPayload == "OFF") {REL9 = 0;}
}
else if (strTopic == "test/device/arduino01/rel10") {
if (strPayload == "ON") {REL10 = 1;}
else if (strPayload == "OFF") {REL10 = 0;}
}
else if (strTopic == "test/device/arduino01/kotel1/get") {
char tUstav11;
tUstav11 = atoi((char*)payload);
if (tUstav11 != tUstav1 ) {
tUstav1 = tUstav11;
}
}
// Освобождаем память (куда поставить это не понятно, возможно надо выше условий)
free(p);
}

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
void reconnect() {
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("arduinoClient")) {
Serial.println("connected");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(3000);
}
}
}

void setup() {
Serial.begin(9600);

pinMode(rel1_pin, OUTPUT);
digitalWrite(rel1_pin, HIGH);
pinMode(rel2_pin, OUTPUT);
digitalWrite(rel2_pin, HIGH);
pinMode(rel3_pin, OUTPUT);
digitalWrite(rel3_pin, HIGH);
pinMode(rel4_pin, OUTPUT);
digitalWrite(rel4_pin, HIGH);
pinMode(rel5_pin, OUTPUT);
digitalWrite(rel5_pin, HIGH);
pinMode(rel6_pin, OUTPUT);
digitalWrite(rel6_pin, HIGH);
pinMode(rel7_pin, OUTPUT);
digitalWrite(rel7_pin, HIGH);
pinMode(rel8_pin, OUTPUT);
digitalWrite(rel8_pin, HIGH);
pinMode(rel9_pin, OUTPUT);
digitalWrite(rel9_pin, HIGH);
pinMode(rel10_pin, OUTPUT);
digitalWrite(rel10_pin, HIGH);

pinMode(konc1_pin, INPUT);
pinMode(konc2_pin, INPUT);

dht.begin();
sensors.begin();
sensors.setResolution(Thermometer1, 10);
sensors.setResolution(Thermometer2, 10);
sensors.setResolution(Thermometer3, 10);
sensors.setResolution(Thermometer4, 10);
sensors.setResolution(Thermometer5, 10);
sensors.setResolution(Thermometer6, 10);

currentTime = millis();
loopTime = currentTime;
Ethernet.begin(mac, ip);
if (client.connect("arduinoClient")) {
Serial.println("online");

client.publish("test/device/arduino01/rel1", "OFF");
client.publish("test/device/arduino01/rel2", "OFF");
client.publish("test/device/arduino01/rel3", "OFF");
client.publish("test/device/arduino01/rel4", "OFF");
client.publish("test/device/arduino01/rel5", "OFF");
client.publish("test/device/arduino01/rel6", "OFF");
client.publish("test/device/arduino01/rel7", "OFF");
client.publish("test/device/arduino01/rel8", "OFF");
client.publish("test/device/arduino01/rel9", "OFF");
client.publish("test/device/arduino01/rel10", "OFF");

client.publish("test/device/arduino01/kotel1/get", "37");
client.subscribe("test/device/arduino01/#");
}
}

void loop() {
if (REL1 == 0) digitalWrite(rel1_pin, HIGH);
else if (REL1 == 1) digitalWrite(rel1_pin, LOW);

if (REL2 == 0) digitalWrite(rel2_pin, HIGH);
else if (REL2 == 1) digitalWrite(rel2_pin, LOW);

if (REL3 == 0) digitalWrite(rel3_pin, HIGH);
else if (REL3 == 1) digitalWrite(rel3_pin, LOW);

if (REL4 == 0) digitalWrite(rel4_pin, HIGH);
else if (REL4 == 1) digitalWrite(rel4_pin, LOW);

if (REL5 == 0) digitalWrite(rel5_pin, HIGH);
else if (REL5 == 1) digitalWrite(rel5_pin, LOW);

if (REL6 == 0) digitalWrite(rel6_pin, HIGH);
else if (REL6 == 1) digitalWrite(rel6_pin, LOW);

if (REL7 == 0) digitalWrite(rel7_pin, HIGH);
else if (REL7 == 1) digitalWrite(rel7_pin, LOW);

if (REL8 == 0) digitalWrite(rel8_pin, HIGH);
else if (REL8 == 1) digitalWrite(rel8_pin, LOW);

if (REL9 == 0) digitalWrite(rel9_pin, HIGH);
else if (REL9 == 1) digitalWrite(rel9_pin, LOW);

if (REL10 == 0) digitalWrite(rel10_pin, HIGH);
else if (REL10 == 1) digitalWrite(rel10_pin, LOW);

/*  
val1 = digitalRead(konc1_pin); // считываем значение с концевика1
if (val1 == HIGH) {
client.publish("test/device/arduino01/konc1", "ON");
}
else if (val1 == LOW) {
client.publish("test/device/arduino01/konc1", "OFF");
}
val2 = digitalRead(konc2_pin); // считываем значение с концевика2
if (val2 == HIGH) {
client.publish("test/device/arduino01/konc2", "ON");
}
else if (val2 == LOW) {
client.publish("test/device/arduino01/konc2", "OFF");
}
if ((sensors.getTempC(Thermometer2)) < tUstav1 && REL2==0) {
REL2 = 1;
client.publish("test/device/arduino01/rel2", "ON");
Serial.println("REL2 - ON");
}
else if ((sensors.getTempC(Thermometer2)) >= tUstav1 && REL2==1) {
REL2=0;
client.publish("test/device/arduino01/rel2", "OFF");
Serial.println("REL2 - OFF");
}
*/ 
client.loop();
currentTime = millis();
sensors.requestTemperatures();
if(currentTime >= (loopTime + 15000)){
if (!client.connected()) {
reconnect();
}

float temperature1 = sensors.getTempC(Thermometer1);
float temperature2 = sensors.getTempC(Thermometer2);
dtostrf(temperature1, -2, 1, tmp1);
client.publish("test/device/arduino01/temp1",tmp1);
dtostrf(temperature2, -2, 1, tmp2);
client.publish("test/device/arduino01/temp2",tmp2);
dtostrf(tUstav1, -2, 0, StrtUstav11);
client.publish("test/device/arduino01/kotel1/get", StrtUstav11);
   /////////////////////////////
   //dht
   //delay(2000);
    float humidity = dht.readHumidity(); // humidity
    float tempC = dht.readTemperature(); // temperature [C]
   char tmpBuffer[20];
     // check if any reads failed and exit early (to try again).
   /* if (isnan(humidity) || isnan(tempC))
    {
      Serial.println("error reading sensor data");
      return;
    }
    else
    {*/
      //Serial.print("[sensor data] temperature[C]: ");
      Serial.print(tempC);
      Serial.print(", humidity: ");
      Serial.println(humidity);
client.publish("test/device/arduino01/sensor/temp", dtostrf(tempC, 6, 2, tmpBuffer)); // переменая с плав запятой, символов всего, после запятой, переменная char
client.publish("test/device/arduino01/sensor/hum", dtostrf(humidity, 6, 2, tmpBuffer));
   // }
loopTime = currentTime;
}
}

 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Что сразу бросилось в глаза:

1. Для чего выделяется память в строке №65, если она после этого нигде и никак не используется?

2. В строке №69 есть риск "распашки памяти". Если Вам передали массив, длиной length то в нём нет элемента с номером length - Вы вылезли за массив. Хорошо если там "ничего важного", а если там что-то нужное, вы портите это своим нулём.

3. В строке №312 заявка на проблемы с переполнением счётчика millis

4. В строках №№319 и 321 написана какая-то странность - полный размер результата - 2 символа, при этом 1 знак после десятичной точки. Не возбраняется, конечно, но выглядит странно.

5. Непонятно, для чего размер буфера в строке №330 такой большой, когда используется только 7 символов (строки №№ 343 и 344)

6. Строки №№ 41-44 определяют переменные, которые нигде потом не используются.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Вот этот кусок - ну зачем такие лишние извращения-то?

void callback(char* topic, byte* payload, unsigned int length) {
// Выделяем необходимое кол-во памяти для копии payload
  byte* p = (byte*)malloc(length);
// Копирование payload в новый буфер
  memcpy(p, payload, length);
// то что было ранее
payload[length] = '\0';
//free(p); \\это не понятно куда поставить
Serial.print(topic);
Serial.print(" ");
String strTopic = String(topic);
String strPayload = String((char*)payload);
Serial.println(strPayload);

if (strTopic == "test/device/arduino01/rel1") {
if (strPayload == "ON"){REL1 = 1;}
else if (strPayload == "OFF"){REL1 = 0;}
}
else if (strTopic == "test/device/arduino01/rel2") {
if (strPayload == "ON") {REL2 = 1;}
else if (strPayload == "OFF") {REL2 = 0;}
}
else if (strTopic == "test/device/arduino01/rel3") {
if (strPayload == "ON") {REL3 = 1;}
else if (strPayload == "OFF") {REL3 = 0;}
}
else if (strTopic == "test/device/arduino01/rel3") {
if (strPayload == "ON") {REL3 = 1;}
else if (strPayload == "OFF") {REL3 = 0;}
}
else if (strTopic == "test/device/arduino01/rel4") {
if (strPayload == "ON") {REL4 = 1;}
else if (strPayload == "OFF") {REL4 = 0;}
}
else if (strTopic == "test/device/arduino01/rel5") {
if (strPayload == "ON") {REL5 = 1;}
else if (strPayload == "OFF") {REL5 = 0;}
}
else if (strTopic == "test/device/arduino01/rel6") {
if (strPayload == "ON") {REL6 = 1;} 
else if (strPayload == "OFF") {REL6 = 0;}
}
else if (strTopic == "test/device/arduino01/rel7") {
if (strPayload == "ON") {REL7 = 1;}
else if (strPayload == "OFF") {REL7 = 0;}
}
else if (strTopic == "test/device/arduino01/rel8") {
if (strPayload == "ON") {REL8 = 1;}
else if (strPayload == "OFF") {REL8 = 0;}
}
else if (strTopic == "test/device/arduino01/rel9") {
if (strPayload == "ON") {REL9 = 1;}
else if (strPayload == "OFF") {REL9 = 0;}
}
else if (strTopic == "test/device/arduino01/rel10") {
if (strPayload == "ON") {REL10 = 1;}
else if (strPayload == "OFF") {REL10 = 0;}
}
else if (strTopic == "test/device/arduino01/kotel1/get") {
char tUstav11;
tUstav11 = atoi((char*)payload);
if (tUstav11 != tUstav1 ) {
tUstav1 = tUstav11;
}
}
// Освобождаем память (куда поставить это не понятно, возможно надо выше условий)
free(p);
}

Если достаточно:

void callback(char* topic, byte* payload, unsigned int length) 
{
	const char* strPayload = (const char*) payload;
	
	if(length < 2) // payload слишком маленький
	{
		return;
	}

	if (!strcmp(topic,"test/device/arduino01/rel1")) 
	{
		REL1 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel2")) 
	{
		REL2 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel3")) 
	{
		REL3 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel4")) 
	{
		REL4 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel5")) 
	{
		REL5 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel6")) 
	{
		REL6 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel7")) 
	{
		REL7 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel8")) 
	{
		REL8 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel9")) 
	{
		REL9 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/rel10")) 
	{
		REL10 = !!strncmp(strPayload,"OF",2);
	}
	else if (!strcmp(topic,"test/device/arduino01/kotel1/get")) 
	{
		char tUstav11;
		tUstav11 = atoi(strPayload);
		if (tUstav11 != tUstav1 ) 
		{
			tUstav1 = tUstav11;
		}
	}

}

И это ещё не вся оптимизация, там по сравнению подстрок можно выкинуть "test/device/arduino01" и проверять на окончание имени топика только, по сути.

Плюс - можно загнать строки в PROGMEM макросом F(), и юзать strcmp_P - будет экономия оперативы ;) Короче, там есть, куда работать.

З.Ы. Единственное "но" - надо бы payload сравнивать не strcmp, а strncmp, а то там нетути завершающего '\0', наверняка. Так что выше - только идея по начальной оптимизации, не более ;)

З.З.Ы. Поправил на strncmp. И да - строка 48, где идёт вызов atoi - также небезопасна по распашке памяти, потому что идёт до завершающего '\0'. Но тоже - правится легко. По итогу же - не надо постоянных плясок с аллокацией памяти ;)

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

А вообще, навскидку - все эти привязки реле к топику можно сделать тыщей способов, сократив код callback до нескольких строк, буквально. Как бешеный вариант навскидку (далеко не самый оптимальный):

typedef struct
{
	const char* topic;
	char* pin;
	
} binding;

binding bindings[] = 
{
	{
		"/rel1",
		&REL1
	},
	
	{
		"/rel2",
		&REL2
	},
	...
};

void callback(char* topic, byte* payload, unsigned int length) 
{
	const char* strPayload = (const char*) payload;
	size_t topicLen = strlen(topic);
	
	if(length < 2) // payload слишком маленький
	{
		return;
	}
	
	for(size_t i=0;i<sizeof(bindings)/sizeof(bindings[0]);i++)
	{
		if(!memmem(topic, topicLen, bindings[i].topic, strlen(bindings[i].topic)))
		{
			*(bindings[i].pin) = !!strncmp(strPayload,"OF",2);
		}
	}
	
}

Можно также избавиться от digitalWrite в loop, и писать в пин прямо в callback:

typedef struct
{
	const char* topic;
	uint8_t pin;
	
} binding;

binding bindings[] = 
{
	{
		"/rel1",
		10 // пин номер 10 у нас привязан к топику rel1
	},
	
	{
		"/rel2",
		11 // пин номер 11 у нас привязан к топику rel2

	},
	...
};

void callback(char* topic, byte* payload, unsigned int length) 
{
	const char* strPayload = (const char*) payload;
	size_t topicLen = strlen(topic);
	
	if(length < 2) // payload слишком маленький
	{
		return;
	}
	
	for(size_t i=0;i<sizeof(bindings)/sizeof(bindings[0]);i++)
	{
		if(!memmem(topic, topicLen, bindings[i].topic, strlen(bindings[i].topic)))
		{
			digitalWrite(bindings[i].pin, !!strncmp(strPayload,"OF",2));
		}
	}
	
}

 

vovankin
Offline
Зарегистрирован: 11.10.2014
Спасибо, что не остались в стороне и уделили немного времени на коментарии.
Изменения с учетом рекомендаций Евгения:
 
1. Для чего выделяется память в строке №65, если она после этого нигде и никак не используется?
Были эксперименты по выделении очистке памяти. Удалил эти строки. Поменял на кусок кода, который предложил DIYMan
2. В строке №69 есть риск "распашки памяти". Если Вам передали массив, длиной length то в нём нет элемента с номером length - Вы вылезли за массив. Хорошо если там "ничего важного", а если там что-то нужное, вы портите это своим нулём.
Удалил эти строки. Поменял на кусок кода, который предложил DIYMan
3. В строке №312 заявка на проблемы с переполнением счётчика millis
Строка 268. Поменял куссок кода. Теперь счетчик идет на уменьшение. Изменил его расположение.
4. В строках №№319 и 321 написана какая-то странность - полный размер результата - 2 символа, при этом 1 знак после десятичной точки. Не возбраняется, конечно, но выглядит странно.
Строки 277 и 279. Поменял некоректные параметры.
5. Непонятно, для чего размер буфера в строке №330 такой большой, когда используется только 7 символов (строки №№ 343 и 344)
Строка 286. Буфер уменьшил до 6. Возможно уменьшить и до 3х. В стоках 299 и 300 поменял параметры.
6. Строки №№ 41-44 определяют переменные, которые нигде потом не используются.
Строки 41-44 убрал лишние переменные. Они пока не нужны.
 
Изменения с учетом рекомендаций DIYMan:
 
Поменял понятные для меня извращения на замысловатый код DIYMan в Callback (не знаю только правильно ли я его туда запихнул)
Убрал вызов atoi.
 
P.s.:Убрал лишний не используемый код.
 
Посмотрите пожайлуста своим мудрым взглядом. Есть ли сейчас замечания? Что можно еще поменять для оптимизации кода.
 
P.s.s: По хоже надо вшить код который будет выводить количество загружаемой памяти что бы понять от этого ли происходит зависание.
Или происходит какой то другой сбой в програме.
// Arduino_w5100_mqtt_10 rele_2Temp_DHT11
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DHT.h>
#define ONE_WIRE_BUS 2 // пин для датчиков температуры
#define rel1_pin 19
#define rel2_pin 16
#define rel3_pin 4
#define rel4_pin 5
#define rel5_pin 6
#define rel6_pin 7
#define rel7_pin 8
#define rel8_pin 9
#define rel9_pin 18
#define rel10_pin 17
#define DHTPIN 3 
#define DHTTYPE DHT11   // DHT 11

char REL1;
char REL2;
char REL3;
char REL4;
char REL5;
char REL6;
char REL7;
char REL8;
char REL9;
char REL10;
char tmp1[10];
char tmp2[10];

unsigned long timing; // Переменная для хранения точки отсчета

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress Thermometer1 = { 0x28, 0x1C, 0xC1, 0x5D, 0x06, 0x00, 0x00, 0x43 };
DeviceAddress Thermometer2 = { 0x28, 0xFF, 0xE7, 0x2C, 0xA6, 0x15, 0x01, 0xCB };

IPAddress ip(192, 168, 1, 22);
IPAddress server(192, 168, 1, 25);
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
DHT dht(DHTPIN, DHTTYPE);
typedef struct
{
const char* topic;
uint8_t pin;
} binding;
binding bindings[] =
{
{
"/rel1",
19 // пин номер 19 у нас привязан к топику rel1
},
{
"/rel2",
16 // пин номер 16 у нас привязан к топику rel2
},
{
"/rel3",
4
},
{
"/rel4",
5
},
{
"/rel5",
6
},
{
"/rel6",
7
},
{
"/rel7",
8
},
{
"/rel8",
9
},
{
"/rel9",
18
},
{
"/rel10",
17
},
};

void callback(char* topic, byte* payload, unsigned int length) 
{
const char* strPayload = (const char*) payload;
size_t topicLen = strlen(topic);
if(length < 2) // payload слишком маленький
{
return;
}
for(size_t i=0;i<sizeof(bindings)/sizeof(bindings[0]);i++)
{
if(!memmem(topic, topicLen, bindings[i].topic, strlen(bindings[i].topic)))
{
digitalWrite(bindings[i].pin, !!strncmp(strPayload,"OF",2));
}
}
}

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

void reconnect() {
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// Attempt to connect

if (client.connect("arduinoClient")) {
Serial.println("connected");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(3000);
}
}
}

void setup() {
Serial.begin(9600);
pinMode(rel1_pin, OUTPUT);
digitalWrite(rel1_pin, HIGH);
pinMode(rel2_pin, OUTPUT);
digitalWrite(rel2_pin, HIGH);
pinMode(rel3_pin, OUTPUT);
digitalWrite(rel3_pin, HIGH);
pinMode(rel4_pin, OUTPUT);
digitalWrite(rel4_pin, HIGH);
pinMode(rel5_pin, OUTPUT);
digitalWrite(rel5_pin, HIGH);
pinMode(rel6_pin, OUTPUT);
digitalWrite(rel6_pin, HIGH);
pinMode(rel7_pin, OUTPUT);
digitalWrite(rel7_pin, HIGH);
pinMode(rel8_pin, OUTPUT);
digitalWrite(rel8_pin, HIGH);
pinMode(rel9_pin, OUTPUT);
digitalWrite(rel9_pin, HIGH);
pinMode(rel10_pin, OUTPUT);
digitalWrite(rel10_pin, HIGH);

dht.begin();
sensors.begin();

sensors.setResolution(Thermometer1, 10);
sensors.setResolution(Thermometer2, 10);


Ethernet.begin(mac, ip);
if (client.connect("arduinoClient")) {
Serial.println("online");
client.publish("test/device/arduino01/rel1", "OFF");
client.publish("test/device/arduino01/rel2", "OFF");
client.publish("test/device/arduino01/rel3", "OFF");
client.publish("test/device/arduino01/rel4", "OFF");
client.publish("test/device/arduino01/rel5", "OFF");
client.publish("test/device/arduino01/rel6", "OFF");
client.publish("test/device/arduino01/rel7", "OFF");
client.publish("test/device/arduino01/rel8", "OFF");
client.publish("test/device/arduino01/rel9", "OFF");
client.publish("test/device/arduino01/rel10", "OFF");
client.subscribe("test/device/arduino01/#");
}
}

void loop() {
client.loop();

sensors.requestTemperatures();
float temperature1 = sensors.getTempC(Thermometer1);
float temperature2 = sensors.getTempC(Thermometer2);
dtostrf(temperature1, 3, 0, tmp1);
client.publish("test/device/arduino01/temp1",tmp1);
dtostrf(temperature2, 3, 0, tmp2);
client.publish("test/device/arduino01/temp2",tmp2);

// ----------------dht
float humidity = dht.readHumidity(); // humidity
float tempC = dht.readTemperature(); // temperature [C]

char tmpBuffer[6];
// check if any reads failed and exit early (to try again).
 if (isnan(humidity) || isnan(tempC))
{
Serial.println("error reading sensor data");
return;
}
else
{
Serial.print(tempC);
Serial.print(", humidity: ");
Serial.println(humidity);
client.publish("test/device/arduino01/sensor/temp", dtostrf(tempC, 3, 0, tmpBuffer)); // переменая с плав запятой, символов всего, после запятой, переменная char
client.publish("test/device/arduino01/sensor/hum", dtostrf(humidity, 3, 0, tmpBuffer));
 }

if (millis() - timing > 10000){
  timing = millis(); 
if (!client.connected()) {
reconnect();
 }

}
}

 

 

Komandir
Offline
Зарегистрирован: 18.08.2018

-