Ethernet выключатель нагрузки в локальной сети
- Войдите на сайт для отправки комментариев
Чт, 27/12/2018 - 14:12
Надоело слать SMS для удаленного включения домашнего сервера, собрал на Arduino Pro Mini и W5500 выключатель с простенькой авторизацией по паролю.
#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet2.h>
#include <EEPROM.h>
#define eeprom_pos_device_mode 241 // 26 - device is on
byte deviceMode; // 1 is on
#define eeprom_pos_last_relay 245 // 49 - relay 2
byte lastRelay;
#define WORK_LEVEL_RELAY 0 // 1 if HIGH level ON relay, else 0
#define relay1_pin 4 // pin relay 1
#define relay2_pin 5 // pin relay 2
#if (WORK_LEVEL_RELAY == 0)
#define RELAY1ON digitalWrite(relay1_pin,LOW)
#define RELAY2ON digitalWrite(relay2_pin,LOW)
#define RELAY1OFF digitalWrite(relay1_pin,HIGH)
#define RELAY2OFF digitalWrite(relay2_pin,HIGH)
#else
#define RELAY1ON digitalWrite(relay1_pin,HIGH)
#define RELAY2ON digitalWrite(relay2_pin,HIGH)
#define RELAY1OFF digitalWrite(relay1_pin,LOW)
#define RELAY2OFF digitalWrite(relay2_pin,LOW)
#endif
unsigned long currentMillis; // main timer
byte mac[] = {0xD4, 0xA8, 0xB7, 0x6F, 0x5E, 0x4D};
EthernetServer server(80);
#define maxSizeResponse 64
char resp_buf[maxSizeResponse]; // response buf from modem
byte pos_buf = 0; // current pos response buf
#define period_wait_pass 30000UL
unsigned long timer_wait_pass;
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
mcusr_mirror = MCUSR;
MCUSR = 0;
wdt_disable();
}
void setup() {
MCUSR = 0;
wdt_disable();
// put your setup code here, to run once:
pinMode(relay1_pin, OUTPUT); pinMode(relay2_pin, OUTPUT);
if (EEPROM.read(eeprom_pos_device_mode) == 26) deviceON(); else deviceOFF();
if (Ethernet.begin(mac)) server.begin();
wdt_enable(WDTO_4S);
}
void loop() {
// put your main code here, to run repeatedly:
wdt_reset();
//delay(5000); // test WDT
currentMillis = millis();
// -----
EthernetClient client = server.available();
if (client) processServer(client);
}
void processServer(EthernetClient ec) {
// an http request ends with a blank line
boolean requestRoot = false;
boolean passwordOK = false;
boolean havePost = false;
boolean currentLineIsBlank = true;
clearRespBuf();
while (ec.connected()) {
if (ec.available()) {
char c = ec.read();
if ((pos_buf < (maxSizeResponse - 1)) && (c)) {
resp_buf[pos_buf] = c; ++pos_buf;
}
if (((strPos(resp_buf, "GET / HTTP")) >= 0) || ((strPos(resp_buf, "GET /? HTTP")) >= 0)) requestRoot = true;
if (((strPos(resp_buf, "POST / HTTP")) >= 0) || ((strPos(resp_buf, "POST /? HTTP")) >= 0)) havePost = true;
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
if (havePost) {
clearRespBuf();
// find password
while (ec.available()) {
char c = ec.read();
if ((pos_buf < (maxSizeResponse - 1)) && (c)) {
resp_buf[pos_buf] = c; ++pos_buf;
}
if (strPos(resp_buf, "password=1234") >= 0) {
passwordOK = true; break;
}
}
}
if ((requestRoot) && ((currentMillis - timer_wait_pass) >= period_wait_pass)) {
// show form
ec.println("HTTP/1.1 200 OK");
ec.println("Content-Type: text/html");
ec.println("Connection: close"); // the connection will be closed after completion of the response
ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("<br />");
// show enter pass page
ec.print("Device is ");
if (deviceMode) ec.println("ON"); else ec.println("OFF");
ec.println("<br />");
ec.println("<p></p>");
ec.println("<form action=\"?\" method=\"post\">");
ec.println("<div>");
ec.println("<label for=\"password\">Pass: <input type=\"password\" name=\"password\" id=\"password\"></label>");
ec.println("</div>");
ec.println("<p></p>");
ec.println("<div>");
ec.println("<input type=\"submit\" value=\"Enter\">");
ec.println("</div>");
ec.println("</form>");
ec.println("</html>");
timer_wait_pass = currentMillis;
break;
} else if (havePost) {
// go to null page
ec.println("HTTP/1.1 302 Found");
ec.println("Location: /"); // the connection will be closed after completion of the response
ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("</html>");
timer_wait_pass = currentMillis;
break;
} else {
// show null page
ec.println("HTTP/1.1 200 OK");
ec.println("Content-Type: text/html");
ec.println("Connection: close"); // the connection will be closed after completion of the response
ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("</html>");
break;
}
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
ec.stop();
if (passwordOK) {
if (deviceMode) {
deviceOFF();
} else {
deviceON();
}
}
}
char* LastPos(char *str1, char *str2) { // find substring in string
int L1 = strlen(str1);
int L2 = strlen(str2);
for (int i = L1 - L2; i >= 0; i--)
{
int j = 0;
for (; j < L2; j++)
if ((str1[i + j] != str2[j]))
break;
if (j == L2)
return str1 + i;
}
return 0;
}
int strPos(char *str11, char *str22) { // find position in string(1) substring(2)
char*p = LastPos(str11, str22);
int n = p - str11;
return n;
}
void clearRespBuf() {
memset(resp_buf, 0, maxSizeResponse);
pos_buf = 0;
}
void deviceON() {
EEPROM.write(eeprom_pos_device_mode, 26);
deviceMode = 1;
if (EEPROM.read(eeprom_pos_last_relay) == 49) {
RELAY1ON; delay(50); RELAY2ON;
} else {
RELAY2ON; delay(50); RELAY1ON;
}
}
void deviceOFF() {
EEPROM.write(eeprom_pos_device_mode, 0);
deviceMode = 0;
if (EEPROM.read(eeprom_pos_last_relay) == 49) {
RELAY1OFF; delay(50); RELAY2OFF;
EEPROM.write(eeprom_pos_last_relay, 0);
} else {
RELAY2OFF; delay(50); RELAY1OFF;
EEPROM.write(eeprom_pos_last_relay, 49);
}
}
Поскольку большую часть времени железка простаивает, добавил к ней несколько дополнительных функций: раз в сутки берет время с NTP сервера, каждый час по MQTT получает с удаленной железки (ESP8266) в деревне температуру и показывает списком последние 10 значений. Включение/отключение нагрузки идет по случайно выбранному паролю из трех (или больше - в скетче вводится).
#include <avr/wdt.h>
#include <SPI.h>
#include <Ethernet2.h>
#include <EEPROM.h>
struct tempItem {
char dateTime[18];
char currTemp[6];
};
#define max_count_temp_item 10
byte countTemp;
byte posTemp;
tempItem massTemp[max_count_temp_item + 1];
char mqtt_server[] = "m20.cloudmqtt.com"; // Имя сервера MQTT
int mqtt_port = 19791; // Порт для подключения к серверу MQTT
char mqtt_user[] = "*******"; // Логи от сервер
char mqtt_pass[] = "********"; // Пароль от сервера
char mqtt_id[] = "catsrv01";
char mqtt_device[] = "Chmd01";
char mqtt_topic_temp[] = "/temp";
char mqtt_topic_gettemp[] = "/gettemp";
EthernetClient clientMqtt;
#define period_mqtt_request 3600000UL
unsigned long timer_mqtt_request = 0;
#define period_wait_mqtt 8000UL
unsigned long timer_wait_mqtt;
#define eeprom_pos_device_mode 241 // 26 - device is on
byte deviceMode; // 1 is on
#define eeprom_pos_last_relay 245 // 49 - relay 2
byte lastRelay;
#define WORK_LEVEL_RELAY 0 // 1 if HIGH level ON relay, else 0
#define relay1_pin 4 // pin relay 1
#define relay2_pin 5 // pin relay 2
#if (WORK_LEVEL_RELAY == 0)
#define RELAY1ON digitalWrite(relay1_pin,LOW)
#define RELAY2ON digitalWrite(relay2_pin,LOW)
#define RELAY1OFF digitalWrite(relay1_pin,HIGH)
#define RELAY2OFF digitalWrite(relay2_pin,HIGH)
#else
#define RELAY1ON digitalWrite(relay1_pin,HIGH)
#define RELAY2ON digitalWrite(relay2_pin,HIGH)
#define RELAY1OFF digitalWrite(relay1_pin,LOW)
#define RELAY2OFF digitalWrite(relay2_pin,LOW)
#endif
byte workMode = 0;
// 0 - send ntp packet
// 1 - wait response ntp
// default - http web server
#define period_ntp_wait 1000UL
unsigned long timer_ntp_wait;
#define localPort 123 // local port to listen for UDP packets
char timeServer[] = "213.141.154.170"; // time.nist.gov NTP server
#define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message
char packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
byte posBuffer;
EthernetUDP Udp;
byte nDay, nMonth, nHour, nMin; word nYear;
unsigned long start_ntp_time;
unsigned long timer_day_ntp_time;
unsigned long timer_min_ntp_time;
byte daysY[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
unsigned long currentMillis; // main timer
byte mac[] = {0xD4, 0xA8, 0xB7, 0x6F, 0x5E, 0x4D};
EthernetServer server(80);
#define countPass 3
char* switchPassword[] = {"789", "456", "123"};
byte passID;
#define maxSizeResponse 64
char resp_buf[maxSizeResponse]; // response buf from modem
byte pos_buf = 0; // current pos response buf
#define period_wait_pass 30000UL
unsigned long timer_wait_pass = 0;
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
__attribute__((naked)) \
__attribute__((used)) \
__attribute__((section(".init3")));
void get_mcusr(void)
{
mcusr_mirror = MCUSR;
MCUSR = 0;
wdt_disable();
}
void setup() {
MCUSR = 0;
wdt_disable();
// put your setup code here, to run once:
randomSeed(analogRead(A7));
passID = random(countPass);
pinMode(relay1_pin, OUTPUT); pinMode(relay2_pin, OUTPUT);
if (EEPROM.read(eeprom_pos_device_mode) == 26) deviceON(); else deviceOFF();
if (Ethernet.begin(mac)) server.begin();
countTemp = 0; posTemp = 0;
wdt_enable(WDTO_4S);
}
void loop() {
// put your main code here, to run repeatedly:
wdt_reset();
//delay(5000); // test WDT
currentMillis = millis();
switch (workMode) {
case 0: {
Udp.begin(localPort);
sendNTPpacket(timeServer);
++workMode;
timer_ntp_wait = currentMillis;
break;
}
case 1: {
if ((currentMillis - timer_ntp_wait) >= period_ntp_wait) {
if (Udp.parsePacket()) {
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
convertNTPtime();
start_ntp_time = currentMillis;
timer_day_ntp_time = currentMillis;
timer_min_ntp_time = currentMillis;
Ethernet.maintain();
} else {
nDay = 1; nMonth = 1; nYear = 1900; nHour = 0; nMin = 0;
}
memset(packetBuffer, 0, NTP_PACKET_SIZE); posBuffer = 0;
workMode = 10;
}
break;
}
case 2: {
clientMqtt.stop();
if (clientMqtt.connect(mqtt_server, mqtt_port)) {
sendConnectPacket();
sendSubscribeTemp();
sendPubGetTemp();
memset(packetBuffer, 0, NTP_PACKET_SIZE); posBuffer = 0;
timer_wait_mqtt = currentMillis;
++workMode; // wait response mqtt
} else {
clientMqtt.stop();
timer_mqtt_request = currentMillis;
workMode = 10;
}
break;
}
case 3: {
if ((currentMillis - timer_wait_mqtt) < period_wait_mqtt) {
// wait/find data from server
while (clientMqtt.available()) {
char c = clientMqtt.read();
if ((posBuffer < (NTP_PACKET_SIZE - 1)) && (c)) {
packetBuffer[posBuffer] = c; ++posBuffer;
}
}
} else {
sendDisConnectPacket();
clientMqtt.stop();
timer_mqtt_request = currentMillis;
parseMqtt();
workMode = 10;
}
break;
}
default: {
EthernetClient client = server.available();
if (client) processServer(client);
// update current time
if ((currentMillis - timer_day_ntp_time) >= 86400000UL) { // 1 day
workMode = 0; // update date time from NTP server
} else if ((currentMillis - timer_min_ntp_time) >= 60000UL) { // 1 min
timer_min_ntp_time = currentMillis;
updateCurrentTime();
}
// mqtt actions
if ((currentMillis - timer_mqtt_request) >= period_mqtt_request) {
workMode = 2; // connect mqtt server
}
// end
}
}
}
void processServer(EthernetClient ec) {
// an http request ends with a blank line
boolean requestRoot = false;
boolean requestSw = false;
boolean passwordOK = false;
boolean havePost = false;
boolean currentLineIsBlank = true;
char findPass[24]; findPass[0] = 0;
strcat(findPass, "password="); strcat(findPass, switchPassword[passID]);
clearRespBuf();
while (ec.connected()) {
if (ec.available()) {
char c = ec.read();
if ((pos_buf < (maxSizeResponse - 1)) && (c)) {
resp_buf[pos_buf] = c; ++pos_buf;
}
if (((strPos(resp_buf, "GET /switch")) >= 0) || ((strPos(resp_buf, "GET /SWITCH")) >= 0)) requestSw = true;
if (((strPos(resp_buf, "GET / HTTP")) >= 0) || ((strPos(resp_buf, "GET /? HTTP")) >= 0)) requestRoot = true;
if (((strPos(resp_buf, "POST / HTTP")) >= 0) || ((strPos(resp_buf, "POST /? HTTP")) >= 0) || ((strPos(resp_buf, "POST /switch")) >= 0) || ((strPos(resp_buf, "POST /SWITCH")) >= 0)) havePost = true;
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
if (havePost) {
clearRespBuf();
// find password
while (ec.available()) {
char c = ec.read();
if ((pos_buf < (maxSizeResponse - 1)) && (c)) {
resp_buf[pos_buf] = c; ++pos_buf;
}
if (strPos(resp_buf, findPass) >= 0) {
passwordOK = true; break;
}
}
}
if ((requestSw) && ((currentMillis - timer_wait_pass) >= period_wait_pass)) {
passID = random(countPass);
// show form
ec.println("HTTP/1.1 200 OK");
ec.println("Content-Type: text/html");
ec.println("Connection: close"); // the connection will be closed after completion of the response
ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("<br />");
// show enter pass page
ec.print("Device is ");
if (deviceMode) ec.println("ON"); else ec.println("OFF");
ec.print("id ");
ec.println((passID + 1), DEC);
ec.println("<br />");
ec.println("<p></p>");
ec.println("<form action=\"?\" method=\"post\">");
ec.println("<div>");
ec.println("<label for=\"password\">Pass: <input type=\"password\" name=\"password\" id=\"password\"></label>");
ec.println("</div>");
ec.println("<p></p>");
ec.println("<div>");
ec.println("<input type=\"submit\" value=\"Enter\">");
ec.println("</div>");
ec.println("</form>");
ec.println("</html>");
timer_wait_pass = currentMillis;
break;
} else if (havePost) {
// go to null page
ec.println("HTTP/1.1 302 Found");
ec.println("Location: /switch/"); // the connection will be closed after completion of the response
/*ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("</html>");*/
timer_wait_pass = currentMillis;
break;
} else if (requestRoot) {
// show chart mqtt page
ec.println("HTTP/1.1 200 OK");
ec.println("Content-Type: text/html");
ec.println("Connection: close"); // the connection will be closed after completion of the response
ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print(nDay, DEC); ec.print('.'); ec.print(nMonth, DEC); ec.print('.'); ec.print(nYear, DEC);
ec.print(' '); ec.print(nHour, DEC); ec.print(':'); ec.println(nMin, DEC);
ec.println("<br />");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("<br />");
byte idxMass;
if (countTemp < max_count_temp_item) idxMass = 0; else idxMass = posTemp;
for (byte i = 0; i < countTemp; ++i) {
ec.println(massTemp[idxMass].dateTime);
ec.println(" - ");
ec.println(massTemp[idxMass].currTemp);
ec.println("<br />");
if ((++idxMass) > max_count_temp_item) idxMass = 0;
}
ec.println("<br />");
ec.println("</html>");
break;
} else {
// show null page
ec.println("HTTP/1.1 200 OK");
ec.println("Content-Type: text/html");
ec.println("Connection: close"); // the connection will be closed after completion of the response
ec.println();
ec.println("<!DOCTYPE HTML>");
ec.println("<html>");
ec.print("Uptime = ");
unsigned long upm = currentMillis / 60000UL;
ec.print(upm, DEC);
ec.println(" min.");
ec.println("</html>");
break;
}
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
ec.stop();
if (passwordOK) {
if (deviceMode) {
deviceOFF();
} else {
deviceON();
}
}
}
char* LastPos(char *str1, char *str2) { // find substring in string
int L1 = strlen(str1);
int L2 = strlen(str2);
for (int i = L1 - L2; i >= 0; i--)
{
int j = 0;
for (; j < L2; j++)
if ((str1[i + j] != str2[j]))
break;
if (j == L2)
return str1 + i;
}
return 0;
}
int strPos(char *str11, char *str22) { // find position in string(1) substring(2)
char*p = LastPos(str11, str22);
int n = p - str11;
return n;
}
void clearRespBuf() {
memset(resp_buf, 0, maxSizeResponse);
pos_buf = 0;
}
void deviceON() {
EEPROM.write(eeprom_pos_device_mode, 26);
deviceMode = 1;
if (EEPROM.read(eeprom_pos_last_relay) == 49) {
RELAY1ON; delay(50); RELAY2ON;
} else {
RELAY2ON; delay(50); RELAY1ON;
}
}
void deviceOFF() {
EEPROM.write(eeprom_pos_device_mode, 0);
deviceMode = 0;
if (EEPROM.read(eeprom_pos_last_relay) == 49) {
RELAY1OFF; delay(50); RELAY2OFF;
EEPROM.write(eeprom_pos_last_relay, 0);
} else {
RELAY2OFF; delay(50); RELAY1OFF;
EEPROM.write(eeprom_pos_last_relay, 49);
}
}
// send an NTP request to the time server at the given address
void sendNTPpacket(const char * address) {
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); // NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}
void convertNTPtime() {
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
// now convert NTP time into everyday time:
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const unsigned long seventyYears = 2208988800UL;
// subtract seventy years:
unsigned long epoch = secsSince1900 - seventyYears;
nHour = ((epoch % 86400L) / 3600) + 3 ; // print the MSK hour (86400 equals secs per day)
nMin = (epoch % 3600) / 60; // print the minute (3600 equals secs per minute)
// wait ten seconds before asking for the time again
unsigned long daysSince1970 = epoch / 86400L;
unsigned long fourYearsSince1970 = daysSince1970 / 1461; // 1461 days by 4 years
unsigned long ldayYearsSince1970 = daysSince1970 % 1461; // 1461 days by 4 years
unsigned long fostYearsSince1970 = ldayYearsSince1970 / 365; // 1461 days by 4 years
unsigned long fdayYearsSince1970 = ldayYearsSince1970 % 365; // 1461 days by 4 years
nYear = fourYearsSince1970 * 4 + fostYearsSince1970 + 1970;
word msum = 0; nMonth = 1; word psum = 0;
for (byte i = 0; i < 12; ++i) {
psum = msum;
if (i == 1) {
// feb
if (nYear % 4) msum += daysY[i]; else msum += 29;
} else {
msum += daysY[i];
}
if (msum > fdayYearsSince1970) {
nMonth = i + 1;
nDay = fdayYearsSince1970 - psum + 1;
break;
}
}
}
void updateCurrentTime() {
if ((++nMin) > 59) {
nMin = 0;
if ((++nHour) > 23) {
nHour = 0;
byte pdays = daysY[nMonth - 1];
if ((nMonth == 2) && ((nYear % 4) == 0)) pdays = 29;
if ((++nDay) > pdays) {
nDay = 0;
if ((++nMonth) > 12) {
nMonth = 1;
++nYear;
}
}
}
}
}
void sendConnectPacket() {
byte sizeDevice = strlen(mqtt_id); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass);
// fixed header
sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000
sendByteToMQTTclient((byte)(16 + sizeDevice + sizeUser + sizePass)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)0x04); // Length LSB (4)
sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name
sendByteToMQTTclient((byte)0x04); // Protocol Level byte
sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable
sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0)
sendByteToMQTTclient((byte)0x0A); // Keep Alive LSB (10) - 10 sec
// payload
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_id[i]));
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user
for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i]));
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass
for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i]));
}
void sendDisConnectPacket() {
// fixed header
sendByteToMQTTclient((byte)0xE0); // MQTT Control Packet type 1110 connect, reserved 0000
sendByteToMQTTclient((byte)0x00); // Remaining Length
}
void sendByteToMQTTclient(byte inByte) {
clientMqtt.write((byte)(inByte));
}
void sendSubscribeTemp() {
byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_temp);
// fixed header
sendByteToMQTTclient((byte)0x82); // MQTT Control Packet type (8) 0100, reserved 0010
sendByteToMQTTclient((byte)(5 + sizeDevice + sizeTopic)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
sendByteToMQTTclient((byte)(0x0A)); // Packet Identifier LSB (10)
// payload
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i]));
sendByteToMQTTclient((byte)0x00); // Requested QoS(1)
}
void sendPubGetTemp() {
char textTemp[] = "5";
byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_gettemp); byte sizeData = strlen(textTemp);
// fixed header
sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags
sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload.
// Variable header
sendByteToMQTTclient((byte)0x00); // Length MSB (0)
sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4)
for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i]));
for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_gettemp[i]));
sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0)
sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10)
// payload
for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i]));
}
void parseMqtt() {
char findStr[NTP_PACKET_SIZE / 2]; findStr[0] = 0;
strcpy(findStr, mqtt_device); strcat(findStr, mqtt_topic_temp);
int pp = strPos(packetBuffer, findStr);
byte posS = 0;
packetBuffer[posS] = 0;
if (pp >= 0) {
pp += strlen(findStr);
for (byte i = 0; i < 7; ++i) {
byte c = packetBuffer[pp + i];
if (((c >= '0') && (c <= '9')) || (c == '.')) {
packetBuffer[posS] = c; ++posS;
}
}
packetBuffer[posS] = 0;
}
if ((strlen(packetBuffer) > 0) && (strlen(packetBuffer) <= 4)) {
char tempStr[6];
// save temp to mass
itoa(nDay, tempStr, 10); strcpy(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, ".");
itoa(nMonth, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, ".");
itoa(nYear, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, " ");
itoa(nHour, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, ":");
itoa(nMin, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr);
strcpy(massTemp[posTemp].currTemp, packetBuffer);
if ((++posTemp) >= max_count_temp_item) posTemp = 0;
if (countTemp < max_count_temp_item) ++countTemp;
}
}


Т.к. жду БП с Китая, то устройство еще в разработке, если будут дополнения/исправления - выложу.
Исправленный скетч (несколько ошибок было) и готовая железка
#include <avr/wdt.h> #include <SPI.h> #include <Ethernet2.h> #include <EEPROM.h> #define max_count_temp_item 14 struct tempItem { char dateTime[18]; char currTemp[6]; }; byte countTemp, posTemp; tempItem massTemp[max_count_temp_item]; char mqtt_server[] = "m20.cloudmqtt.com"; // Имя сервера MQTT int mqtt_port = 19791; // Порт для подключения к серверу MQTT char mqtt_user[] = "******"; // Логин от сервер char mqtt_pass[] = "*******"; // Пароль от сервера char mqtt_id[] = "catsrv01"; // имя непосдерственно данной железки не должно ни с чем совпадать char mqtt_device[] = "Chmd01"; // логическое имя - фактически первое слово в топике char mqtt_topic_temp[] = "/temp"; char mqtt_topic_gettemp[] = "/gettemp"; #define period_mqtt_request 3600000UL #define period_wait_mqtt 6000UL EthernetClient clientMqtt; unsigned long timer_mqtt_request = 0; unsigned long timer_wait_mqtt; #define eeprom_pos_device_mode 146 // 26 - device is on #define eeprom_pos_last_relay 71 // 49 - relay 2 byte lastRelay, deviceMode; // 1 is on #define WORK_LEVEL_RELAY 0 // 1 if HIGH level ON relay, else 0 #define relay1_pin 4 // pin relay 1 #define relay2_pin 5 // pin relay 2 #if (WORK_LEVEL_RELAY == 0) #define RELAY1ON digitalWrite(relay1_pin,LOW) #define RELAY2ON digitalWrite(relay2_pin,LOW) #define RELAY1OFF digitalWrite(relay1_pin,HIGH) #define RELAY2OFF digitalWrite(relay2_pin,HIGH) #else #define RELAY1ON digitalWrite(relay1_pin,HIGH) #define RELAY2ON digitalWrite(relay2_pin,HIGH) #define RELAY1OFF digitalWrite(relay1_pin,LOW) #define RELAY2OFF digitalWrite(relay2_pin,LOW) #endif byte workMode = 0; // 0 - send ntp packet // 1 - wait response ntp // 2 - send mqtt request // 3 - wait mqtt response // default - http web server unsigned long currentMillis; // main timer #define period_ntp_wait 1000UL unsigned long timer_ntp_wait; #define localPort 123 // local port to listen for UDP packets char timeServer[] = "213.141.154.170"; // time.nist.gov NTP server #define NTP_PACKET_SIZE 48 // NTP time stamp is in the first 48 bytes of the message byte posBuffer; char packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets EthernetUDP Udp; byte nDay, nMonth, nHour, nMin; word nYear; unsigned long timer_day_ntp_time; unsigned long timer_min_ntp_time; byte daysY[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; byte mac[] = {0xD4, 0xA8, 0xB7, 0x6F, 0x5E, 0x4D}; EthernetServer server(80); #define countPass 3 char* switchPassword[] = {"789", "456", "123"}; byte passID; #define maxSizeResponse 64 char resp_buf[maxSizeResponse]; byte pos_buf = 0; #define period_wait_pass 30000UL unsigned long timer_wait_pass = 0; uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); void get_mcusr(void) \ __attribute__((naked)) \ __attribute__((used)) \ __attribute__((section(".init3"))); void get_mcusr(void) { mcusr_mirror = MCUSR; MCUSR = 0; wdt_disable(); } void setup() { MCUSR = 0; wdt_disable(); // put your setup code here, to run once: randomSeed(analogRead(A7)); passID = random(countPass); pinMode(relay1_pin, OUTPUT); pinMode(relay2_pin, OUTPUT); if (EEPROM.read(eeprom_pos_device_mode) == 26) deviceON(); else deviceOFF(); if (Ethernet.begin(mac)) server.begin(); countTemp = 0; posTemp = 0; wdt_enable(WDTO_4S); } void loop() { // put your main code here, to run repeatedly: wdt_reset(); currentMillis = millis(); //delay(5000); // test WDT switch (workMode) { case 0: { Udp.begin(localPort); sendNTPpacket(timeServer); ++workMode; timer_ntp_wait = currentMillis; break; } case 1: { if ((currentMillis - timer_ntp_wait) >= period_ntp_wait) { if (Udp.parsePacket()) { Udp.read(packetBuffer, NTP_PACKET_SIZE); convertNTPtime(); timer_day_ntp_time = currentMillis; timer_min_ntp_time = currentMillis; Ethernet.maintain(); } else { nDay = 1; nMonth = 1; nYear = 1900; nHour = 0; nMin = 0; } memset(packetBuffer, 0, NTP_PACKET_SIZE); posBuffer = 0; workMode = 10; } break; } case 2: { clientMqtt.stop(); if (clientMqtt.connect(mqtt_server, mqtt_port)) { sendConnectPacket(); sendSubscribeTemp(); sendPubGetTemp(); memset(packetBuffer, 0, NTP_PACKET_SIZE); posBuffer = 0; timer_wait_mqtt = currentMillis; ++workMode; // wait response mqtt } else { clientMqtt.stop(); timer_mqtt_request = currentMillis; workMode = 10; } break; } case 3: { if ((currentMillis - timer_wait_mqtt) < period_wait_mqtt) { // wait/find data from server while (clientMqtt.available()) { char c = clientMqtt.read(); if ((posBuffer < (NTP_PACKET_SIZE - 1)) && (c)) { packetBuffer[posBuffer] = c; ++posBuffer; } } } else { sendDisConnectPacket(); clientMqtt.stop(); timer_mqtt_request = currentMillis; parseMqtt(); workMode = 10; } break; } default: { EthernetClient client = server.available(); if (client) processServer(client); if ((currentMillis - timer_day_ntp_time) >= 86400000UL) { // 1 day // update current time workMode = 0; // update date time from NTP server } else if ((currentMillis - timer_min_ntp_time) >= 60000UL) { // 1 min // correct time timer_min_ntp_time = currentMillis; updateCurrentTime(); } if ((currentMillis - timer_mqtt_request) >= period_mqtt_request) { // mqtt actions workMode = 2; // connect mqtt server } // end other action } } } void processServer(EthernetClient ec) { boolean requestRoot = false; boolean requestSw = false; boolean passwordOK = false; boolean havePost = false; boolean currentLineIsBlank = true; char findPass[24]; findPass[0] = 0; strcat(findPass, "password="); strcat(findPass, switchPassword[passID]); clearRespBuf(); while (ec.connected()) { if (ec.available()) { char c = ec.read(); if ((pos_buf < (maxSizeResponse - 1)) && (c)) { resp_buf[pos_buf] = c; ++pos_buf; } if (((strPos(resp_buf, "GET /switch")) >= 0) || ((strPos(resp_buf, "GET /SWITCH")) >= 0)) requestSw = true; if (((strPos(resp_buf, "GET / HTTP")) >= 0) || ((strPos(resp_buf, "GET /? HTTP")) >= 0)) requestRoot = true; if (((strPos(resp_buf, "POST / HTTP")) >= 0) || ((strPos(resp_buf, "POST /? HTTP")) >= 0) || ((strPos(resp_buf, "POST /switch")) >= 0) || ((strPos(resp_buf, "POST /SWITCH")) >= 0)) havePost = true; if (c == '\n' && currentLineIsBlank) { if (havePost) { clearRespBuf(); while (ec.available()) { char c = ec.read(); if ((pos_buf < (maxSizeResponse - 1)) && (c)) { resp_buf[pos_buf] = c; ++pos_buf; } if (strPos(resp_buf, findPass) >= 0) { passwordOK = true; break; } } } if ((requestSw) && ((currentMillis - timer_wait_pass) >= period_wait_pass)) { passID = random(countPass); ec.println("HTTP/1.1 200 OK"); ec.println("Content-Type: text/html"); ec.println("Connection: close"); ec.println(); ec.println("<!DOCTYPE HTML>"); ec.println("<html>"); ec.print("Uptime = "); unsigned long upm = currentMillis / 60000UL; ec.print(upm, DEC); ec.println(" min."); ec.println("<br />"); ec.print("Device is "); if (deviceMode) ec.println("ON"); else ec.println("OFF"); ec.print("id "); ec.println((passID + 1), DEC); ec.println("<br />"); ec.println("<p></p>"); ec.println("<form action=\"?\" method=\"post\">"); ec.println("<div>"); ec.println("<label for=\"password\">Pass: <input type=\"password\" name=\"password\" id=\"password\"></label>"); ec.println("</div>"); ec.println("<p></p>"); ec.println("<div>"); ec.println("<input type=\"submit\" value=\"Enter\">"); ec.println("</div>"); ec.println("</form>"); ec.println("</html>"); timer_wait_pass = currentMillis; break; } else if (havePost) { ec.println("HTTP/1.1 302 Found"); ec.println("Location: /switch/"); timer_wait_pass = currentMillis; break; } else if (requestRoot) { ec.println("HTTP/1.1 200 OK"); ec.println("Content-Type: text/html"); ec.println("Connection: close"); ec.println(); ec.println("<!DOCTYPE HTML>"); ec.println("<html>"); ec.print(nDay, DEC); ec.print('.'); ec.print(nMonth, DEC); ec.print('.'); ec.print(nYear, DEC); ec.print(' '); ec.print(nHour, DEC); ec.print(':'); ec.println(nMin, DEC); ec.println("<br />"); ec.print("Uptime = "); unsigned long upm = currentMillis / 60000UL; ec.print(upm, DEC); ec.println(" min."); ec.println("<br />"); byte idxMass; if (countTemp < max_count_temp_item) idxMass = 0; else idxMass = posTemp; for (byte i = 0; i < countTemp; ++i) { ec.println(massTemp[idxMass].dateTime); ec.println(" - "); ec.println(massTemp[idxMass].currTemp); ec.println("<br />"); if ((++idxMass) >= max_count_temp_item) idxMass = 0; } ec.println("<br />"); ec.println("</html>"); break; } else { ec.println("HTTP/1.1 200 OK"); ec.println("Content-Type: text/html"); ec.println("Connection: close"); ec.println(); ec.println("<!DOCTYPE HTML>"); ec.println("<html>"); ec.print("Uptime = "); unsigned long upm = currentMillis / 60000UL; ec.print(upm, DEC); ec.println(" min."); ec.println("</html>"); break; } } if (c == '\n') currentLineIsBlank = true; else if (c != '\r') currentLineIsBlank = false; } } delay(1); ec.stop(); if (passwordOK) { if (deviceMode) deviceOFF(); else deviceON(); } } char* LastPos(char *str1, char *str2) { // find substring in string int L1 = strlen(str1); int L2 = strlen(str2); for (int i = L1 - L2; i >= 0; i--) { int j = 0; for (; j < L2; j++) if ((str1[i + j] != str2[j])) break; if (j == L2) return str1 + i; } return 0; } int strPos(char *str11, char *str22) { // find position in string(1) substring(2) char*p = LastPos(str11, str22); int n = p - str11; return n; } void clearRespBuf() { memset(resp_buf, 0, maxSizeResponse); pos_buf = 0; } void deviceON() { EEPROM.write(eeprom_pos_device_mode, 26); deviceMode = 1; if (EEPROM.read(eeprom_pos_last_relay) == 49) { RELAY1ON; delay(100); RELAY2ON; } else { RELAY2ON; delay(100); RELAY1ON; } } void deviceOFF() { EEPROM.write(eeprom_pos_device_mode, 0); deviceMode = 0; if (EEPROM.read(eeprom_pos_last_relay) == 49) { RELAY1OFF; delay(100); RELAY2OFF; EEPROM.write(eeprom_pos_last_relay, 0); } else { RELAY2OFF; delay(100); RELAY1OFF; EEPROM.write(eeprom_pos_last_relay, 49); } } void sendNTPpacket(const char * address) { memset(packetBuffer, 0, NTP_PACKET_SIZE); packetBuffer[0] = 0b11100011; packetBuffer[1] = 0; packetBuffer[2] = 6; packetBuffer[3] = 0xEC; packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; Udp.beginPacket(address, 123); Udp.write(packetBuffer, NTP_PACKET_SIZE); Udp.endPacket(); } void convertNTPtime() { unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); unsigned long secsSince1900 = highWord << 16 | lowWord; const unsigned long seventyYears = 2208988800UL; unsigned long epoch = secsSince1900 - seventyYears; nHour = ((epoch % 86400L) / 3600) + 3 ; nMin = (epoch % 3600) / 60; unsigned long daysSince1970 = epoch / 86400L; unsigned long fourYearsSince1970 = daysSince1970 / 1461; unsigned long ldayYearsSince1970 = daysSince1970 % 1461; unsigned long fostYearsSince1970 = ldayYearsSince1970 / 365; unsigned long fdayYearsSince1970 = ldayYearsSince1970 % 365; nYear = fourYearsSince1970 * 4 + fostYearsSince1970 + 1970; word msum = 0; nMonth = 1; word psum; for (byte i = 0; i < 12; ++i) { psum = msum; if (i == 1) { if (nYear % 4) msum += daysY[i]; else msum += 29; } else { msum += daysY[i]; } if (msum > fdayYearsSince1970) { nMonth = i + 1; nDay = fdayYearsSince1970 - psum + 1; break; } } } void updateCurrentTime() { if ((++nMin) > 59) { nMin = 0; if ((++nHour) > 23) { nHour = 0; byte pdays = daysY[nMonth - 1]; if ((nMonth == 2) && ((nYear % 4) == 0)) pdays = 29; if ((++nDay) > pdays) { nDay = 1; if ((++nMonth) > 12) { nMonth = 1; ++nYear; } } } } } void sendConnectPacket() { byte sizeDevice = strlen(mqtt_id); byte sizeUser = strlen(mqtt_user); byte sizePass = strlen(mqtt_pass); // fixed header sendByteToMQTTclient((byte)0x10); // MQTT Control Packet type 0001 connect, reserved 0000 sendByteToMQTTclient((byte)(16 + sizeDevice + sizeUser + sizePass)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)0x04); // Length LSB (4) sendByteToMQTTclient((byte)'M'); sendByteToMQTTclient((byte)'Q'); sendByteToMQTTclient((byte)'T'); sendByteToMQTTclient((byte)'T'); // protocol name sendByteToMQTTclient((byte)0x04); // Protocol Level byte sendByteToMQTTclient((byte)0xC0); // Connect Flag bits, login and pass enable sendByteToMQTTclient((byte)0x00); // Keep Alive MSB (0) sendByteToMQTTclient((byte)0x0A); // Keep Alive LSB (10) - 10 sec // payload sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizeDevice); // Length LSB (4) - device for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_id[i])); sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizeUser); // Length LSB (4) - user for (byte i = 0; i < sizeUser; ++i) sendByteToMQTTclient((byte)(mqtt_user[i])); sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)sizePass); // Length LSB (4) - pass for (byte i = 0; i < sizePass; ++i) sendByteToMQTTclient((byte)(mqtt_pass[i])); } void sendDisConnectPacket() { // fixed header sendByteToMQTTclient((byte)0xE0); // MQTT Control Packet type 1110 connect, reserved 0000 sendByteToMQTTclient((byte)0x00); // Remaining Length } void sendByteToMQTTclient(byte inByte) { clientMqtt.write((byte)(inByte)); } void sendSubscribeTemp() { byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_temp); // fixed header sendByteToMQTTclient((byte)0x82); // MQTT Control Packet type (8) 0100, reserved 0010 sendByteToMQTTclient((byte)(5 + sizeDevice + sizeTopic)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0) sendByteToMQTTclient((byte)(0x0A)); // Packet Identifier LSB (10) // payload sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4) for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_temp[i])); sendByteToMQTTclient((byte)0x00); // Requested QoS(1) } void sendPubGetTemp() { char textTemp[] = "5"; byte sizeDevice = strlen(mqtt_device); byte sizeTopic = strlen(mqtt_topic_gettemp); byte sizeData = strlen(textTemp); // fixed header sendByteToMQTTclient((byte)0x30); // MQTT Control Packet type 0011, DUP QoS Retain 0000 flags sendByteToMQTTclient((byte)(4 + sizeDevice + sizeTopic + sizeData)); // Remaining Length is the length of the variable header (10 bytes) plus the length of the Payload. // Variable header sendByteToMQTTclient((byte)0x00); // Length MSB (0) sendByteToMQTTclient((byte)(sizeDevice + sizeTopic)); // Length LSB (4) for (byte i = 0; i < sizeDevice; ++i) sendByteToMQTTclient((byte)(mqtt_device[i])); for (byte i = 0; i < sizeTopic; ++i) sendByteToMQTTclient((byte)(mqtt_topic_gettemp[i])); sendByteToMQTTclient((byte)0x00); // Packet Identifier MSB (0) sendByteToMQTTclient((byte)0x00); // Packet Identifier LSB (10) // payload for (byte i = 0; i < sizeData; ++i) sendByteToMQTTclient((byte)(textTemp[i])); } void parseMqtt() { char findStr[NTP_PACKET_SIZE / 2]; findStr[0] = 0; strcpy(findStr, mqtt_device); strcat(findStr, mqtt_topic_temp); int pp = strPos(packetBuffer, findStr); byte posS = 0; packetBuffer[posS] = 0; if (pp >= 0) { pp += strlen(findStr); for (byte i = 0; i < 7; ++i) { byte c = packetBuffer[pp + i]; if (((c >= '0') && (c <= '9')) || (c == '.')) { packetBuffer[posS] = c; ++posS; } } packetBuffer[posS] = 0; } if ((strlen(packetBuffer) > 0) && (strlen(packetBuffer) <= 4)) { char tempStr[6]; itoa(nDay, tempStr, 10); strcpy(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, "."); itoa(nMonth, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, "."); itoa(nYear, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, " "); itoa(nHour, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcat(massTemp[posTemp].dateTime, ":"); itoa(nMin, tempStr, 10); strcat(massTemp[posTemp].dateTime, tempStr); strcpy(massTemp[posTemp].currTemp, packetBuffer); if ((++posTemp) >= max_count_temp_item) posTemp = 0; if (countTemp < max_count_temp_item) ++countTemp; } }Каков DHCP lease time в сети?
Каков DHCP lease time в сети?
Дома 8 часов, на работе где сейчас железка тестируется - сутки. Я все равно на роутере адрес для железки резервирую.
PS Что то все таки с библиотекой ethernet не то...непредсказуемо по wdt МК перезагружается при общении с mqtt сервером, бывает каждый час, а максимальный uptime который видел 6 часов.
Аренда адреса DHCP обновляется в mantain(), а он в коде вызывается раз в сутки. Если адрес не в резерве, то вероятны веселые глюки.
А то, что перезагружается - вполне логичным оказаться может быть. Если, положим, ресолв FDQN затянулся, потом при коннекте MQTT-хост проверяет PTR-запись для клиентского IP... Все 4 секунды уйдут легко. Я бы для теста сначала на локального брокера завёл клиента, а потом уже делал выводы насчет библиотек.
Хм...спасибо, буду экспериментировать
Upd: временно поставил wdt 8 секунд, помогло.
Буду или логику менять или ковырять библиотеку на предмет добавления wdt_reset
Спасибо.
Либы ковырять - сизифов труд. Я бы на данном этапе делал бы отдельно ресолв (возможно с некоторой периодичностью) и потом в процедуру MQTT уже готовый IP сдавал.
Либы ковырять - сизифов труд. Я бы на данном этапе делал бы отдельно ресолв (возможно с некоторой периодичностью) и потом в процедуру MQTT уже готовый IP сдавал.
Да, похожая мысль есть, но не факт что через минуту при коннекте / отправке адрес уже не поменяется (
Буду думать....логику менять....
Спасибо.
А чего ему меняться? Если у них там на dns балансир стоит и по кругу выдает адреса из пула, то это не говорит о том, что по старому ip стопроцентно никто не откликнется. Да и, в крайнем случае, никто не мешает сделать ресолв, потом вачдог заресетить и сразу законнектиться к mqtt с готовым ip. Логика та же, либу ковырять не требуется, вачдог сбрасывается.
В крайнем случае вообще можно оставить все как есть), сейчас аптайм 3000 минут, более 2х суток, для данной железки более чем достаточно.
Но из спортивного интереса именно хочется добавить в библиотеку wdt_reset.
Так что буду в свободное время ковырять библиотеку.