FreeRTOS рдХреЗ рддрд╣рдд C рдореЗрдВ ESP8266 рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдереЛрдбрд╝рд╛ рд╕рд╛

рдПрдХ рдХреИрдк рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдЗрд╕рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдмрдЬрдЯ рдирд╣реАрдВ рдерд╛ред

ESP8266 рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ WIFI рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ ARDUINO рдХреЗ рд╕рд╛рде рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдФрд░ рдбреЗрдЯрд╛ рд╡рд┐рдирд┐рдордп рдкрд░ рдореЗрд░реА рдЯрд┐рдкреНрдкрдгреА рдХреЗ рд▓рд┐рдП рдЯрд╛рд░реНрд╕рди рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реЛрдХрд░ , рдореИрдВрдиреЗ FreeRTOS рдХреЗ рддрд╣рдд C рдореЗрдВ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ ESP8266 рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдХрдЯ рдХреЗ рддрд╣рдд рд╡рд┐рд╡рд░рдгред

рдЪрд░рдг реж - рдпрдВрддреНрд░

рдкрд╣рд▓реЗ рдЖрдкрдХреЛ ESP8266 рдХреЗ рд╕рд╛рде рдПрдХ рдбрд┐рд╡рд╛рдЗрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдпрд╣ рд╡рд╛рдВрдЫрдиреАрдп рд╣реИ рдХрд┐ рдпреВрдПрд╕рдмреА рдХреЛ UART рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЬрд╛рдП, рддрд╛рдХрд┐ рдЖрдкрдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рдмрдВрдж рди рдХрд░рдирд╛ рдкрдбрд╝реЗред рдореИрдВ NodeMCU рдореЗрдВ рдЕрдкрдиреЗ рдЕрдорд╛рдирд╡реАрдп рдкреНрд░рдпреЛрдЧреЛрдВ рдХрд╛ рдЦрд░реНрдЪ рдХрд░рддрд╛ рд╣реВрдВред

рддреЛ, рдЪрд░рдг 1 - рдЯреВрд▓рдХрд┐рди рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВ

рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рд▓рд┐рдирдХреНрд╕ рд╡рд┐рддрд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рдХрдВрдкреНрдпреВрдЯрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдореЗрд░реЗ рдкрд╛рд╕ OpenSUSE рд▓реАрдк рд╣реИ)ред рд╣рдо tyts рд▓рд┐рдВрдХ рдкрд░ github рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ, рд╡рд┐рдзрд╛рдирд╕рднрд╛ рдХреЗ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдкрдврд╝рддреЗ рд╣реИрдВ, рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рдХреНрд▓реЛрди рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╣реИрдВред рдореИрдВрдиреЗ / рдСрдкреНрдЯ / рдИрдПрд╕рдкреА рдореЗрдВ рдХреНрд▓реЛрди рдХрд┐рдпрд╛ рдФрд░ рдореЗрдХрдлрд╛рдЗрд▓ рдирд┐рдпрдореЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЪрд░ рд╕реЗрдЯ рдХрд░рдирд╛:

STANDALONE = n VENDOR_SDK = 2.1.0 

рдЗрд╕рдХреЗ рдмрд╛рдж, рдЖрдк PATH рдореЗрдВ рдЯреВрд▓рдХрд┐рди рдмрд╛рдпрдиреЗрд░рд┐рдЬрд╝ рдореЗрдВ рдкрде рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ ~ / .bashrc:

 export PATH=/opt/ESP/esp-open-sdk/xtensa-lx106-elf/bin:$PATH 

рдЪрд░рдг 2 - рдПрд╕рдбреАрдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ

рд╣рдо рдЧрд┐рдЯрдм ( рдЯрд┐рдХреНрдХ ) рдЬрд╛рддреЗ рд╣реИрдВ, рдирд┐рд░реНрджреЗрд╢ рдкрдврд╝рддреЗ рд╣реИрдВ, рдХреНрд▓реЛрди (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП / рдСрдкреНрдЯ / рдИрдПрд╕рдкреА рдореЗрдВ)ред рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ ESP8266_SDK_PATH рдХреЛ рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ рддрд░реАрдХреЗ рд╕реЗ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ~ / .bashrc рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ):

 export ESP8266_SDK_PATH=/opt/ESP/esp-open-rtos 

рдЪрд░рдг 3 - рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдмрдирд╛рдПрдВ

рд╣рдо рдПрд╕рдбреАрдХреЗ рдХреЗ рд╕рд╛рде рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЙрджрд╛рд╣рд░рдг рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЖрдк рдХреА рддрд░рд╣ рдХреЗ рдХрд┐рд╕реА рднреА рдЙрджрд╛рд╣рд░рдг рдХреЛ рдХреЙрдкреА рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдЕрдкрдиреЗ рдкрд╕рдВрджреАрджрд╛ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдорд╛рд╣реМрд▓ рдореЗрдВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдЖрдпрд╛рдд / рдЦреЛрд▓рддреЗ рд╣реИрдВ, рдорд╕реЛрдЪрд┐рд╕реНрдЯ рдПрдХ рдкрд╛рда рд╕рдВрдкрд╛рджрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдореИрдВ NetBeans рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ - рдЗрд╕рдореЗрдВ C / C ++ рдкреНрд░реЛрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╕рдорд░реНрдерди рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдореЗрдХрдлрд╛рдЗрд▓ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИрдВред рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдореЗрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрдХрдЯреНрдард╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕реЗ рдореЗрдХ рдлреНрд▓реИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлреНрд▓реИрд╢ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред Local.mk рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рдЖрдк рдЕрдкрдиреЗ рдбрд┐рд╡рд╛рдЗрд╕ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝реНрд▓реИрд╢ рдореЗрдореЛрд░реА рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХрд╛ рдЖрдХрд╛рд░ рдФрд░ рдореЛрдб) рдХреЛ рдЪрдордХрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЪрд░рдг 4 - рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рд╣рдо рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ, рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╣реИрдВ, GOST 34.602-89 рдХреЗ рдЕрдиреБрд╕рд╛рд░ рддрдХрдиреАрдХреА рд╡рд┐рд╢рд┐рд╖реНрдЯрддрд╛рдУрдВ рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдЖрдк рдХреЛрдб рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ :) рдореИрдВрдиреЗ рдПрд▓ рдИ рдбреА рдмреНрд▓рд┐рдВрдХ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдореЗрд░реЗ рдкрд╛рд╕ рдЙрдиреНрд╣реЗрдВ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рд╣реИрд▓реЛрд╡рд░реНрд▓реНрдб рдХреЗ рд░реВрдк рдореЗрдВ рдореИрдВ AM2302 рд╕реЗрдВрд╕рд░ рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝реВрдВрдЧрд╛ред DHT22) рдФрд░ рд╕рд░реНрд╡рд░ рдХреЛ MQTT рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреЗрдЬ рд░рд╣рд╛ рд╣реИред

рдЕрддрд┐рд░рд┐рдХреНрдд рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП MQTT рдпрд╛ DHT, рдЙрдиреНрд╣реЗрдВ рдореЗрдХрдлрд╛рдЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

 PROGRAM=fffmeteo EXTRA_COMPONENTS = extras/paho_mqtt_c extras/dht include $(ESP8266_SDK_PATH)/common.mk 

main.h
 #ifndef MAIN_H #define MAIN_H #include <stdio.h> #include <stdint.h> #include <limits.h> #include <FreeRTOS.h> #include <task.h> #include <queue.h> #include <semphr.h> #define DEBUG #ifdef DEBUG #define debug(args...) printf("--- "); printf(args) #define SNTP_DEBUG_ENABLED true #else #define debug(args...) #define SNTP_DEBUG_ENABLED false #endif #define WIFI_SSID "kosmonaFFFt" #define WIFI_PASS "mysupermegapassword" #define MQTT_HOST "m11.cloudmqtt.com" #define MQTT_PORT 16464 #define MQTT_USER "kosmonaFFFt" #define MQTT_PASS "mysupermegapassword" #define MQTT_TOPIC "/meteo" #define NTP_SERVER "pool.ntp.org" #define UART0_BAUD 9600 #define STACK_SIZE 512 #define INIT_TASK_PRIORITY (configTIMER_TASK_PRIORITY + 1) #define MEASUREMENT_TASK_PRIORITY (INIT_TASK_PRIORITY + 1) #define SENDING_DATA_TASK_PRIORITY (MEASUREMENT_TASK_PRIORITY + 1) #define MEASUREMENTS_PERIOD_S 59 #define MAX_MEASUREMENTS_COUNT 16 #define SEND_PERIOD_S 120 #define RUN_SNTP_SYNC_PERIOD 5 #define MS(x) (x / portTICK_PERIOD_MS) #define AM2302_PIN 5 #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif #endif /* MAIN_H */ 


main.c
 #include "main.h" #include "sntp.h" #include <esp/uart.h> #include <espressif/esp_common.h> #include <paho_mqtt_c/MQTTESP8266.h> #include <paho_mqtt_c/MQTTClient.h> #include <dht/dht.h> //-----------------------------------------------------------------------------+ // Measurements task section. | //-----------------------------------------------------------------------------+ struct measurement_results { time_t timestamp; int am2302_humidity; int am2302_temperature; }; static QueueHandle_t measurements_queue; void measurement_task(void *arg) { int16_t humidity; int16_t temperature; struct measurement_results measurements; while (true) { debug("MEASUREMENTS: Start measurements...\n"); measurements.timestamp = time(NULL); bool success = dht_read_data(DHT_TYPE_DHT22, AM2302_PIN, &humidity, &temperature); if (success && temperature >= -500 && temperature <= 1500 && humidity >= 0 && humidity <= 1000) { measurements.am2302_humidity = humidity; measurements.am2302_temperature = temperature; } else { debug("MEASUREMENT: Error! Cannot read data from AM2302!!!\n"); measurements.am2302_humidity = INT_MIN; measurements.am2302_temperature = INT_MIN; } debug("MEASUREMENTS: Measurements finished...\n"); xQueueSendToBack(measurements_queue, &measurements, MS(250)); vTaskDelay(MS(MEASUREMENTS_PERIOD_S * 1000)); } vTaskDelete(NULL); } //-----------------------------------------------------------------------------+ // Sending data task section. | //-----------------------------------------------------------------------------+ static uint8_t mqtt_buf[512]; static uint8_t mqtt_readbuf[128]; void sending_data_task(void *arg) { mqtt_network_t network; mqtt_network_new(&network); mqtt_client_t client = mqtt_client_default; mqtt_packet_connect_data_t data = mqtt_packet_connect_data_initializer; uint8_t sntp_sync_counter = 0; while (true) { debug("MQTT: ConnectNetwork...\n"); int err = mqtt_network_connect(&network, MQTT_HOST, MQTT_PORT); if (err) { debug("MQTT: Error!!! ConnectNetwork ERROR!\n"); vTaskDelay(MS(5 * 1000)); continue; } else { debug("MQTT: ConnectNetwork success...\n"); } // TODO: add check for errors!!! // TODO: replace magic constants!!! mqtt_client_new(&client, &network, 5000, mqtt_buf, 100, mqtt_readbuf, 100); data.willFlag = 0; data.MQTTVersion = 3; data.clientID.cstring = "fff"; data.username.cstring = MQTT_USER; data.password.cstring = MQTT_PASS; data.keepAliveInterval = 10; data.cleansession = 0; err = mqtt_connect(&client, &data); if (err) { debug("MQTT: Error!!! MQTTConnect ERROR!\n"); vTaskDelay(MS(5 * 1000)); continue; } else { debug("MQTT: MQTTConnect success...\n"); } struct measurement_results msg; while (xQueueReceive(measurements_queue, &msg, 0) == pdTRUE) { if (msg.am2302_humidity == INT_MIN || msg.am2302_temperature == INT_MIN) { debug("MQTT: Got invalid message, no publishing!!!\n"); continue; } debug("MQTT: Got message to publish...\n"); debug(" timestamp: %ld\n", msg.timestamp); debug(" am2302_humidity: %.1f\n", msg.am2302_humidity / 10.0); debug(" am2302_temperature: %.1f\n", msg.am2302_temperature / 10.0); msg.timestamp = htonl(msg.timestamp); msg.am2302_humidity = htonl(msg.am2302_humidity); msg.am2302_temperature = htonl(msg.am2302_temperature); mqtt_message_t message; message.payload = &msg; message.payloadlen = sizeof (msg); message.dup = 0; message.qos = MQTT_QOS1; message.retained = 0; err = mqtt_publish(&client, MQTT_TOPIC, &message); if (err) { debug("MQTT: Error!!! Error while publishing message!\n"); } else { debug("MQTT: Successfully publish message...\n"); } } mqtt_disconnect(&client); mqtt_network_disconnect(&network); ++sntp_sync_counter; if (sntp_sync_counter == RUN_SNTP_SYNC_PERIOD) { sntp_sync(NTP_SERVER, NULL, arg); sntp_sync_counter = 0; } vTaskDelay(MS(SEND_PERIOD_S * 1000)); } vTaskDelete(NULL); } //-----------------------------------------------------------------------------+ // Init task section. | //-----------------------------------------------------------------------------+ /** * This semaphore is taken during sntp sync and released after it finished. */ static SemaphoreHandle_t init_task_sem; /** * Set time and free init task semaphore. * @param error unused * @param arg unused */ void init_sntp_callback(int8_t error, void* arg) { time_t ts = time(NULL); debug("TIME: %s", ctime(&ts)); xSemaphoreGive(init_task_sem); } /** * Connection parameters. */ static struct sdk_station_config STATION_CONFIG = { .ssid = WIFI_SSID, .password = WIFI_PASS, }; void init_task(void* arg) { debug("INIT: setting pins...\n"); gpio_set_pullup(AM2302_PIN, false, false); debug("INIT: Set station parameters...\n"); sdk_wifi_station_set_auto_connect(false); sdk_wifi_station_set_config(&STATION_CONFIG); debug("Station parameters has been set.\n"); debug("INIT: Connecting to AP...\n"); sdk_wifi_station_connect(); while (sdk_wifi_station_get_connect_status() != STATION_GOT_IP) { vTaskDelay(MS(1000)); } debug("INIT: Connection to AP has been estabilished...\n"); debug("INIT: Start SNTP synchronization...\n"); init_task_sem = xSemaphoreCreateMutex(); if (!init_task_sem) { debug("INIT: Cannot create init task semaphore!!!"); return; } xSemaphoreTake(init_task_sem, 0); sntp_init(); sntp_sync(NTP_SERVER, init_sntp_callback, arg); BaseType_t result = pdFALSE; while (true) { debug("INIT: Trying to take init task semaphore...\n"); result = xSemaphoreTake(init_task_sem, MS(5 * 1000)); if (result == pdTRUE) { debug("INIT: Init task semaphore is taken...\n"); break; } } measurements_queue = xQueueCreate(MAX_MEASUREMENTS_COUNT, sizeof (struct measurement_results)); if (!measurements_queue) { debug("INIT: ERROR!!! Cannot create queue for measurements!\n"); goto fail; } result = xTaskCreate(measurement_task, "measurement_task", STACK_SIZE, NULL, MEASUREMENT_TASK_PRIORITY, NULL); if (result == pdFAIL) { debug("INIT: Measurement task creation failed!!!\n"); goto fail; } debug("INIT: Measurement task created...\n"); result = xTaskCreate(sending_data_task, "send_data_task", STACK_SIZE, NULL, SENDING_DATA_TASK_PRIORITY, NULL); if (result == pdFAIL) { debug("INIT: Send task creation failed!!!\n"); goto fail; } debug("INIT: Send data task created...\n"); fail: vSemaphoreDelete(init_task_sem); vTaskDelete(NULL); } //-----------------------------------------------------------------------------+ // Application entry point. | //-----------------------------------------------------------------------------+ void user_init(void) { debug("USER_INIT: SDK version: %s\n", sdk_system_get_sdk_version()); debug("USER_INIT: sizeof (int): %d\n", sizeof (int)); debug("USER_INIT: sizeof (float): %d\n", sizeof (float)); debug("USER_INIT: sizeof (time_t): %d\n", sizeof (time_t)); uart_set_baud(0, UART0_BAUD); BaseType_t result = xTaskCreate(init_task, (const char * const) "init_task", STACK_SIZE, NULL, INIT_TASK_PRIORITY, NULL); if (!result) { debug("USER_INIT: Cannot create init task!!!"); return; } } 


sntp.h
 #ifndef SNTP_H #define SNTP_H #include <time.h> #include <stdint.h> #ifdef __cplusplus extern "C" { #endif #define SNTP_ERR_OK 0 #define SNTP_ERR_CONTEXT -1 #define SNTP_ERR_DNS -2 #define SNTP_ERR_UDP_PCB_ALLOC -3 #define SNTP_ERR_PBUF_ALLOC -4 #define SNTP_ERR_SEND -5 #define SNTP_ERR_RECV_ADDR_PORT -6; #define SNTP_ERR_RECV_SIZE -7 #define SNTP_ERR_RECV_MODE -8 #define SNTP_ERR_RECV_STRATUM -9 typedef void (*sntp_sync_callback)(int8_t error, void *arg); void sntp_init(); void sntp_sync(char *server, sntp_sync_callback callback, void *callback_arg); time_t sntp_get_rtc_time(int32_t *us); void sntp_update_rtc(time_t t, uint32_t us); #ifdef __cplusplus } #endif #endif /* SNTP_H */ 


sntp.c
 #include "main.h" #include "sntp.h" #include <time.h> #include <string.h> #include <lwip/ip_addr.h> #include <lwip/err.h> #include <lwip/dns.h> #include <lwip/udp.h> #include <esp/rtc_regs.h> #include <espressif/esp_common.h> #define TIMER_COUNT RTC.COUNTER /** * Daylight settings. * Base calculated with value obtained from NTP server (64 bits). */ #define SNTP_BASE (*((uint64_t*) RTC.SCRATCH)) /** * Timer value when base was obtained. */ #define SNTP_TIME_REF (RTC.SCRATCH[2]) /** * Calibration value. */ #define SNTP_CALIBRATION (RTC.SCRATCH[3]) /** * SNTP modes. */ #define SNTP_MODE_CLIENT 0x03 #define SNTP_MODE_SERVER 0x04 #define SNTP_MODE_BROADCAST 0x05 /** * Kiss-of-death code. */ #define SNTP_STRATUM_KOD 0x00 #define SNTP_OFFSET_LI_VN_MODE 0 #define SNTP_OFFSET_STRATUM 1 #define SNTP_OFFSET_RECEIVE_TIME 32 #define DIFF_SEC_1900_1970 (2208988800UL) struct sntp_message { uint8_t li_vn_mode; uint8_t stratum; uint8_t poll; uint8_t precision; uint32_t root_delay; uint32_t root_dispersion; uint32_t reference_identifier; uint32_t reference_timestamp[2]; uint32_t originate_timestamp[2]; uint32_t receive_timestamp[2]; uint32_t transmit_timestamp[2]; } __attribute__ ((packed)); struct sntp_sync_context { ip_addr_t ip_address; sntp_sync_callback callback; void* callback_arg; }; void sntp_init() { SNTP_BASE = 0; SNTP_CALIBRATION = 1; SNTP_TIME_REF = TIMER_COUNT; } void on_dns_found(const char* name, ip_addr_t* ipaddr, void* arg); void on_udp_recv(void* arg, struct udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port); void sntp_sync(char* server, sntp_sync_callback callback, void* callback_arg) { int result = ERR_OK; debug("SNTP: Start SNTP synchronization, allocating memory for context...\n"); struct sntp_sync_context* context = malloc(sizeof (struct sntp_sync_context)); if (!context) { debug("SNTP: Error!!! Cannot allocate memory for context!\n"); result = SNTP_ERR_CONTEXT; goto fail; } context->callback = callback; context->callback_arg = callback_arg; debug("SNTP: Context successfully allocated...\n"); debug("SNTP: Start DNS lookup...\n"); err_t err = dns_gethostbyname(server, &(context->ip_address), on_dns_found, context); if (!(err == ERR_OK || err == ERR_INPROGRESS)) { debug("SNTP: Error!!! DNS lookup error!\n"); result = SNTP_ERR_DNS; goto fail; } return; fail: if (context) { free(context); } if (callback) { callback(result, callback_arg); } } // //============================================================================================================================================================== // void on_dns_found(const char* name, ip_addr_t* ipaddr, void* arg) { debug("SNTP: Start DNS lookup successfully finished...\n"); int result = ERR_OK; struct sntp_sync_context* context = arg; sntp_sync_callback callback = context->callback; void* callback_arg = context->callback_arg; debug("SNTP: Creating upd_pcb...\n"); struct udp_pcb* sntp_pcb = udp_new(); if (!sntp_pcb) { debug("SNTP: Error!!! Cannot allocate udp_pcb!\n"); result = SNTP_ERR_UDP_PCB_ALLOC; goto fail; } debug("SNTP: Successfully created upd_pcb...\n"); debug("SNTP: Allocating pbuf...\n"); struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, sizeof (struct sntp_message), PBUF_RAM); if (!p) { debug("SNTP: Error!!! DNS lookup error!\n"); result = SNTP_ERR_PBUF_ALLOC; goto fail; } struct sntp_message* message = p->payload; memset(message, 0, sizeof (struct sntp_message)); message->li_vn_mode = 0b00100011; // li = 00, vn = 4, mode = 3 debug("SNTP: Pbuf allocated successfully...\n"); debug("SNTP: Sending data to server...\n"); udp_recv(sntp_pcb, on_udp_recv, context); err_t err = udp_sendto(sntp_pcb, p, ipaddr, 123); pbuf_free(p); if (err != ERR_OK) { debug("SNTP: Error!!! data sending error!\n"); result = SNTP_ERR_SEND; goto fail; } debug("SNTP: Data sent...\n"); return; fail: if (context) { free(context); } if (sntp_pcb) { udp_remove(sntp_pcb); } if (callback) { callback(result, callback_arg); } } void on_udp_recv(void* arg, struct udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port) { debug("SNTP: Response has successfully received...\n"); int result = ERR_OK; struct sntp_sync_context* context = arg; sntp_sync_callback callback = context->callback; void* callback_arg = context->callback_arg; debug("SNTP: Checking response size...\n"); if (p->tot_len < sizeof (struct sntp_message)) { debug("SNTP: Error!!! Invalid response size!\n"); result = SNTP_ERR_RECV_SIZE; goto fail; } debug("SNTP: Response size is OK...\n"); debug("SNTP: Checking mode...\n"); u8_t mode = 0x0; pbuf_copy_partial(p, &mode, sizeof (mode), SNTP_OFFSET_LI_VN_MODE); mode &= 0b00000111; if (mode != SNTP_MODE_SERVER && mode != SNTP_MODE_BROADCAST) { debug("SNTP: Error!!! Invalid mode!\n"); result = SNTP_ERR_RECV_MODE; goto fail; } debug("SNTP: Mode is OK...\n"); debug("SNTP: Checking stratum...\n"); u8_t stratum = 0x0; pbuf_copy_partial(p, &stratum, sizeof (stratum), SNTP_OFFSET_STRATUM); if (stratum == SNTP_STRATUM_KOD) { debug("SNTP: Error!!! Kiss of death!\n"); result = SNTP_ERR_RECV_STRATUM; goto fail; } debug("SNTP: Stratum is OK...\n"); debug("SNTP: Updating system timer...\n"); uint32_t receive_time[2]; pbuf_copy_partial(p, &receive_time, 2 * sizeof (uint32_t), SNTP_OFFSET_RECEIVE_TIME); time_t t = ntohl(receive_time[0]) - DIFF_SEC_1900_1970; uint32_t us = ntohl(receive_time[1]) / 4295; sntp_update_rtc(t, us); debug("SNTP: System timer updated...\n"); fail: if (context) { free(context); } if (pcb) { udp_remove(pcb); } if (callback) { callback(result, callback_arg); } } /** * Check if a timer wrap has occurred. Compensate sntp_base reference * if affirmative. * TODO: think about multitasking and race conditions. */ inline void sntp_check_timer_wrap(uint32_t current_value) { if (current_value < SNTP_TIME_REF) { // Timer wrap has occurred, compensate by subtracting 2^32 to ref. SNTP_BASE -= 1LLU << 32; } } /** * Return secs. If us is not a null pointer, fill it with usecs */ time_t sntp_get_rtc_time(int32_t *us) { time_t secs; uint32_t tim; uint64_t base; tim = TIMER_COUNT; // Check for timer wrap. sntp_check_timer_wrap(tim); base = SNTP_BASE + tim - SNTP_TIME_REF; secs = base * SNTP_CALIBRATION / (1000000U << 12); if (us) { *us = base * SNTP_CALIBRATION % (1000000U << 12); } return secs; } /** * Update RTC timer. Called by SNTP module each time it receives an update. */ void sntp_update_rtc(time_t t, uint32_t us) { // Apply daylight and timezone correction // DEBUG: Compute and print drift int64_t sntp_current = SNTP_BASE + TIMER_COUNT - SNTP_TIME_REF; int64_t sntp_correct = (((uint64_t) us + (uint64_t) t * 1000000U) << 12) / SNTP_CALIBRATION; debug("RTC Adjust: drift = %ld ticks, cal = %d\n", (time_t) (sntp_correct - sntp_current), SNTP_CALIBRATION); SNTP_TIME_REF = TIMER_COUNT; SNTP_CALIBRATION = sdk_system_rtc_clock_cali_proc(); SNTP_BASE = (((uint64_t) us + (uint64_t) t * 1000000U) << 12) / SNTP_CALIBRATION; } /** * Syscall implementation. doesn't seem to use tzp. */ int _gettimeofday_r(struct _reent* r, struct timeval* tp, void* tzp) { // Syscall defined by xtensa newlib defines tzp as void* // So it looks like it is not used. Also check tp is not NULL if (tzp || !tp) { return EINVAL; } tp->tv_sec = sntp_get_rtc_time((int32_t*) & tp->tv_usec); return 0; } рдореМрдд рдХрд╛ \ N!"); #include "main.h" #include "sntp.h" #include <time.h> #include <string.h> #include <lwip/ip_addr.h> #include <lwip/err.h> #include <lwip/dns.h> #include <lwip/udp.h> #include <esp/rtc_regs.h> #include <espressif/esp_common.h> #define TIMER_COUNT RTC.COUNTER /** * Daylight settings. * Base calculated with value obtained from NTP server (64 bits). */ #define SNTP_BASE (*((uint64_t*) RTC.SCRATCH)) /** * Timer value when base was obtained. */ #define SNTP_TIME_REF (RTC.SCRATCH[2]) /** * Calibration value. */ #define SNTP_CALIBRATION (RTC.SCRATCH[3]) /** * SNTP modes. */ #define SNTP_MODE_CLIENT 0x03 #define SNTP_MODE_SERVER 0x04 #define SNTP_MODE_BROADCAST 0x05 /** * Kiss-of-death code. */ #define SNTP_STRATUM_KOD 0x00 #define SNTP_OFFSET_LI_VN_MODE 0 #define SNTP_OFFSET_STRATUM 1 #define SNTP_OFFSET_RECEIVE_TIME 32 #define DIFF_SEC_1900_1970 (2208988800UL) struct sntp_message { uint8_t li_vn_mode; uint8_t stratum; uint8_t poll; uint8_t precision; uint32_t root_delay; uint32_t root_dispersion; uint32_t reference_identifier; uint32_t reference_timestamp[2]; uint32_t originate_timestamp[2]; uint32_t receive_timestamp[2]; uint32_t transmit_timestamp[2]; } __attribute__ ((packed)); struct sntp_sync_context { ip_addr_t ip_address; sntp_sync_callback callback; void* callback_arg; }; void sntp_init() { SNTP_BASE = 0; SNTP_CALIBRATION = 1; SNTP_TIME_REF = TIMER_COUNT; } void on_dns_found(const char* name, ip_addr_t* ipaddr, void* arg); void on_udp_recv(void* arg, struct udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port); void sntp_sync(char* server, sntp_sync_callback callback, void* callback_arg) { int result = ERR_OK; debug("SNTP: Start SNTP synchronization, allocating memory for context...\n"); struct sntp_sync_context* context = malloc(sizeof (struct sntp_sync_context)); if (!context) { debug("SNTP: Error!!! Cannot allocate memory for context!\n"); result = SNTP_ERR_CONTEXT; goto fail; } context->callback = callback; context->callback_arg = callback_arg; debug("SNTP: Context successfully allocated...\n"); debug("SNTP: Start DNS lookup...\n"); err_t err = dns_gethostbyname(server, &(context->ip_address), on_dns_found, context); if (!(err == ERR_OK || err == ERR_INPROGRESS)) { debug("SNTP: Error!!! DNS lookup error!\n"); result = SNTP_ERR_DNS; goto fail; } return; fail: if (context) { free(context); } if (callback) { callback(result, callback_arg); } } // //============================================================================================================================================================== // void on_dns_found(const char* name, ip_addr_t* ipaddr, void* arg) { debug("SNTP: Start DNS lookup successfully finished...\n"); int result = ERR_OK; struct sntp_sync_context* context = arg; sntp_sync_callback callback = context->callback; void* callback_arg = context->callback_arg; debug("SNTP: Creating upd_pcb...\n"); struct udp_pcb* sntp_pcb = udp_new(); if (!sntp_pcb) { debug("SNTP: Error!!! Cannot allocate udp_pcb!\n"); result = SNTP_ERR_UDP_PCB_ALLOC; goto fail; } debug("SNTP: Successfully created upd_pcb...\n"); debug("SNTP: Allocating pbuf...\n"); struct pbuf* p = pbuf_alloc(PBUF_TRANSPORT, sizeof (struct sntp_message), PBUF_RAM); if (!p) { debug("SNTP: Error!!! DNS lookup error!\n"); result = SNTP_ERR_PBUF_ALLOC; goto fail; } struct sntp_message* message = p->payload; memset(message, 0, sizeof (struct sntp_message)); message->li_vn_mode = 0b00100011; // li = 00, vn = 4, mode = 3 debug("SNTP: Pbuf allocated successfully...\n"); debug("SNTP: Sending data to server...\n"); udp_recv(sntp_pcb, on_udp_recv, context); err_t err = udp_sendto(sntp_pcb, p, ipaddr, 123); pbuf_free(p); if (err != ERR_OK) { debug("SNTP: Error!!! data sending error!\n"); result = SNTP_ERR_SEND; goto fail; } debug("SNTP: Data sent...\n"); return; fail: if (context) { free(context); } if (sntp_pcb) { udp_remove(sntp_pcb); } if (callback) { callback(result, callback_arg); } } void on_udp_recv(void* arg, struct udp_pcb* pcb, struct pbuf* p, ip_addr_t* addr, u16_t port) { debug("SNTP: Response has successfully received...\n"); int result = ERR_OK; struct sntp_sync_context* context = arg; sntp_sync_callback callback = context->callback; void* callback_arg = context->callback_arg; debug("SNTP: Checking response size...\n"); if (p->tot_len < sizeof (struct sntp_message)) { debug("SNTP: Error!!! Invalid response size!\n"); result = SNTP_ERR_RECV_SIZE; goto fail; } debug("SNTP: Response size is OK...\n"); debug("SNTP: Checking mode...\n"); u8_t mode = 0x0; pbuf_copy_partial(p, &mode, sizeof (mode), SNTP_OFFSET_LI_VN_MODE); mode &= 0b00000111; if (mode != SNTP_MODE_SERVER && mode != SNTP_MODE_BROADCAST) { debug("SNTP: Error!!! Invalid mode!\n"); result = SNTP_ERR_RECV_MODE; goto fail; } debug("SNTP: Mode is OK...\n"); debug("SNTP: Checking stratum...\n"); u8_t stratum = 0x0; pbuf_copy_partial(p, &stratum, sizeof (stratum), SNTP_OFFSET_STRATUM); if (stratum == SNTP_STRATUM_KOD) { debug("SNTP: Error!!! Kiss of death!\n"); result = SNTP_ERR_RECV_STRATUM; goto fail; } debug("SNTP: Stratum is OK...\n"); debug("SNTP: Updating system timer...\n"); uint32_t receive_time[2]; pbuf_copy_partial(p, &receive_time, 2 * sizeof (uint32_t), SNTP_OFFSET_RECEIVE_TIME); time_t t = ntohl(receive_time[0]) - DIFF_SEC_1900_1970; uint32_t us = ntohl(receive_time[1]) / 4295; sntp_update_rtc(t, us); debug("SNTP: System timer updated...\n"); fail: if (context) { free(context); } if (pcb) { udp_remove(pcb); } if (callback) { callback(result, callback_arg); } } /** * Check if a timer wrap has occurred. Compensate sntp_base reference * if affirmative. * TODO: think about multitasking and race conditions. */ inline void sntp_check_timer_wrap(uint32_t current_value) { if (current_value < SNTP_TIME_REF) { // Timer wrap has occurred, compensate by subtracting 2^32 to ref. SNTP_BASE -= 1LLU << 32; } } /** * Return secs. If us is not a null pointer, fill it with usecs */ time_t sntp_get_rtc_time(int32_t *us) { time_t secs; uint32_t tim; uint64_t base; tim = TIMER_COUNT; // Check for timer wrap. sntp_check_timer_wrap(tim); base = SNTP_BASE + tim - SNTP_TIME_REF; secs = base * SNTP_CALIBRATION / (1000000U << 12); if (us) { *us = base * SNTP_CALIBRATION % (1000000U << 12); } return secs; } /** * Update RTC timer. Called by SNTP module each time it receives an update. */ void sntp_update_rtc(time_t t, uint32_t us) { // Apply daylight and timezone correction // DEBUG: Compute and print drift int64_t sntp_current = SNTP_BASE + TIMER_COUNT - SNTP_TIME_REF; int64_t sntp_correct = (((uint64_t) us + (uint64_t) t * 1000000U) << 12) / SNTP_CALIBRATION; debug("RTC Adjust: drift = %ld ticks, cal = %d\n", (time_t) (sntp_correct - sntp_current), SNTP_CALIBRATION); SNTP_TIME_REF = TIMER_COUNT; SNTP_CALIBRATION = sdk_system_rtc_clock_cali_proc(); SNTP_BASE = (((uint64_t) us + (uint64_t) t * 1000000U) << 12) / SNTP_CALIBRATION; } /** * Syscall implementation. doesn't seem to use tzp. */ int _gettimeofday_r(struct _reent* r, struct timeval* tp, void* tzp) { // Syscall defined by xtensa newlib defines tzp as void* // So it looks like it is not used. Also check tp is not NULL if (tzp || !tp) { return EINVAL; } tp->tv_sec = sntp_get_rtc_time((int32_t*) & tp->tv_usec); return 0; } 


рдПрд╕рдПрдирдЯреАрдкреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕рдордп рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреЛрдб рдХреА рдЙрдкрд▓рдмреНрдзрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЧреАрддрд╛рддреНрдордХ рд╡рд┐рд╖рдпрд╛рдВрддрд░: рдПрд╕рдбреАрдХреЗ рд╕реЗ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдРрд╕рд╛ рдПрдХ рдореЙрдбреНрдпреВрд▓ рд╣реИ, рд▓реЗрдХрд┐рди рдХрд┐рд╕реА рдХрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдпрд╣ рдкрд╕рдВрдж рдирд╣реАрдВ рдЖрдпрд╛ (рдпрд╣ рдмрд╣реБрдд рд╕рдордп рдкрд╣рд▓реЗ рдерд╛, рдореБрдЭреЗ рдпрд╣ рдпрд╛рдж рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕ рдХреЛрдб рдХреА рдирдХрд▓ рдХреА рдФрд░ рдЦреБрдж рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд┐рдпрд╛ред

рд╕рдм рдХреБрдЫ рдмрд╕ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ: рдЬрдм рдирд┐рдпрдВрддреНрд░рдХ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрд░рдВрднреАрдХрд░рдг рдХрд╛рд░реНрдп рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдЬреЛ рдкрд╣реБрдВрдЪ рдмрд┐рдВрджреБ рд╕реЗ рдЬреБрдбрд╝рддрд╛ рд╣реИ, рдПрд╕рдПрдирдЯреАрдкреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдордп рдХреЛ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝ рдХрд░рддрд╛ рд╣реИ, рдЖрд░реНрджреНрд░рддрд╛ рдХреЗ рд╕рд╛рде рддрд╛рдкрдорд╛рди рдХреЛ рдорд╛рдкрдиреЗ рдФрд░ рд╕рд░реНрд╡рд░ рдкрд░ рдбреЗрдЯрд╛ рднреЗрдЬрдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдпрд╣ рдЦреБрдж рдХреЛ рдорд╛рд░рддрд╛ рд╣реИред рдорд╛рдк рдХрд╛рд░реНрдп рдкреНрд░рддреНрдпреЗрдХ 59 рд╕реЗрдХрдВрдб рдореЗрдВ рдПрдХ рдмрд╛рд░ рд╕реЗрдВрд╕рд░ рдХреЛ рдкреНрд░рджреВрд╖рд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рдПрдХ рдХрддрд╛рд░ рдореЗрдВ рд░рдЦрддрд╛ рд╣реИ, рднреЗрдЬрдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд╣рд░ 2 рдорд┐рдирдЯ рдореЗрдВ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рдХрддрд╛рд░ рд╕реЗ рдбреЗрдЯрд╛ рдкрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ MQTT рд╕рд░реНрд╡рд░ рдХреЛ рднреЗрдЬрддрд╛ рд╣реИред

рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк C ++ рдореЗрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдЪрд░рдг 5 - рдирд┐рд╖реНрдХрд░реНрд╖, рдЙрд╕рдХреЗ рдмрд┐рдирд╛ рдХрд╣рд╛рдБ

рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рд╕рд░рд▓ рддрд░реАрдХреЗ рд╕реЗ, рд╕реА рднрд╛рд╖рд╛ рдФрд░ рд╣рд╛рдереЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╡рдХреНрд░рддрд╛ рдХреЗ рдПрдХ рдЫреЛрдЯреЗ рддреНрд░рд┐рдЬреНрдпрд╛ рдХреЗ рд╕рд╛рде, рдЖрдк ESP8266 рдирд┐рдпрдВрддреНрд░рдХ рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╕реНрдХреНрд░рд┐рдкреНрдЯрд┐рдВрдЧ рд╕рдорд╛рдзрд╛рдиреЛрдВ рдкрд░ рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдореБрдЦреНрдп рд▓рд╛рдн (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрд▓рдпреВрдП рдпрд╛ рдорд╛рдЗрдХреНрд░реЛрдкрд╛рдпрдереЙрди) рдлрд░реНрдорд╡реЗрдпрд░ рдХреА рд╕рдВрд░рдЪрдирд╛ рдФрд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдкрд░ рдкреВрд░реНрдг рдирд┐рдпрдВрддреНрд░рдг рд╣реИ, рдФрд░ рд╕реАрдорд┐рдд рдирд┐рдпрдВрддреНрд░рдХ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЗ рд╕рд╛рде рдЕрдзрд┐рдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд░рдЯрдирд╛ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИред рдПрд╕реНрдкреНрд░реЗрд╕рд┐рдл рд╕реЗ рдЖрд░рдЯреАрдУрдПрд╕ рдПрд╕рдбреАрдХреЗ рдпрд╛ рдПрдирдУрдПрдирдУрдПрд╕ рдПрд╕рдбреАрдХреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рд╡рд┐рдХрд▓реНрдк рднреА рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдкрд╣рд▓реЗ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд╛рде рдирд╣реАрдВ рдмрдврд╝рд╛, рдФрд░ рдореИрдВрдиреЗ рджреВрд╕рд░реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдирд╣реАрдВ рдХреАред рдЕрдЧрд░ рдХрд┐рд╕реА рдХреЛ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реЛрдЧреА, рд╕рд╛рде рд╣реА рдЬрдм рдореИрдВ рдЗрд╕реЗ рдЦреБрдж рд╕рдордЭреВрдВрдЧрд╛, рддреЛ рдореИрдВ рдУрдЯреАрдП (рд╣рд╡рд╛ рд╕реЗ рдлрд░реНрдорд╡реЗрдпрд░ рдЕрджреНрдпрддрди) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рд▓рд┐рдЦ рд╕рдХрддрд╛ рд╣реВрдВред

рдЗрд╕ рдХреЛрдб рдХреЗ рдХреБрдЫ рдкрд░рд┐рдгрд╛рдо:

MQTT рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛


UART рдореЗрдВ рдбреАрдмрдЧ рдирд┐рдпрдВрддреНрд░рдХ рдирд┐рдХрд╛рд╕
 SDK version: 0.9.9 --- USER_INIT: sizeof (int): 4 --- USER_INIT: sizeof (float): 4 --- USER_INIT: sizeof (time_t): 4 mode : sta(18:fe:34:d2:c5:a7) add if0 --- INIT: setting pins... --- INIT: Set station parameters... --- Station parameters has been set. --- INIT: Connecting to AP... scandone add 0 aid 2 cnt connected with kosmonaFFFt, channel 1 dhcp client start... ip:192.168.1.21,mask:255.255.255.0,gw:192.168.1.1 --- INIT: Connection to AP has been estabilished... --- INIT: Start SNTP synchronization... --- SNTP: Start SNTP synchronization, allocating memory for context... --- SNTP: Context successfully allocated... --- SNTP: Start DNS lookup... --- INIT: Trying to take init task semaphore... --- SNTP: Start DNS lookup successfully finished... --- SNTP: Creating upd_pcb... --- SNTP: Successfully created upd_pcb... --- SNTP: Allocating pbuf... --- SNTP: Pbuf allocated successfully... --- SNTP: Sending data to server... --- SNTP: Data sent... --- SNTP: Response has successfully received... --- SNTP: Checking response size... --- SNTP: Response size is OK... --- SNTP: Checking mode... --- SNTP: Mode is OK... --- SNTP: Checking stratum... --- SNTP: Stratum is OK... --- SNTP: Updating system timer... --- RTC Adjust: drift = 1220897578 ticks, cal = 1 --- SNTP: System timer updated... --- TIME: Thu Sep 21 19:20:36 2017 --- INIT: Init task semaphore is taken... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- INIT: Measurement task created... --- MQTT: ConnectNetwork... --- INIT: Send data task created... --- MQTT: ConnectNetwork success... --- MQTT: MQTTConnect success... --- MQTT: Got message to publish... --- timestamp: 1506021636 --- am2302_humidity: 55.8 --- am2302_temperature: 23.4 --- MQTT: Successfully publish message... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- MQTT: ConnectNetwork... --- MQTT: ConnectNetwork success... --- MQTT: MQTTConnect success... --- MQTT: Got message to publish... --- timestamp: 1506021694 --- am2302_humidity: 55.2 --- am2302_temperature: 23.8 --- MQTT: Successfully publish message... --- MQTT: Got message to publish... --- timestamp: 1506021751 --- am2302_humidity: 56.5 --- am2302_temperature: 24.4 --- MQTT: Successfully publish message... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- MQTT: ConnectNetwork... --- MQTT: ConnectNetwork success... --- MQTT: MQTTConnect success... --- MQTT: Got message to publish... --- timestamp: 1506021807 --- am2302_humidity: 53.0 --- am2302_temperature: 24.7 --- MQTT: Successfully publish message... --- MQTT: Got message to publish... --- timestamp: 1506021863 --- am2302_humidity: 52.3 --- am2302_temperature: 24.8 --- MQTT: Successfully publish message... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- MEASUREMENTS: Start measurements... --- MEASUREMENTS: Measurements finished... --- MQTT: ConnectNetwork... --- MQTT: ConnectNetwork success... --- MQTT: MQTTConnect success... --- MQTT: Got message to publish... --- timestamp: 1506021919 --- am2302_humidity: 52.0 --- am2302_temperature: 24.9 --- MQTT: Successfully publish message... --- MQTT: Got message to publish... --- timestamp: 1506021975 --- am2302_humidity: 53.3 --- am2302_temperature: 25.2 --- MQTT: Successfully publish message... 


рдкреАрдПрд╕ рдореИрдВ рдкреАрд╕реА рдкрд░ рдпреВрдПрдЖрд░рдЯреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдорд┐рдирд┐рдХреЙрдо (рдХрдВрд╕реЛрд▓) рдпрд╛ рдХрдЯрдХреЙрдо (рдЬреАрдпреВрдЖрдИ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ ред

рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ:

Source: https://habr.com/ru/post/hi406813/


All Articles