MySensors API обрабатывает большую часть сообщений в фоновом режиме без особого вмешательства, необходимого от скетча программиста. Давайте начнем с небольшого примера датчика.
Сенсорные Узлы
Для того, чтобы создать программу Arduino (также известный как эскиз), который сообщает данные датчика по воздуху вам нужно только написать несколько строк кода. В следующем примере мы предположим, что у Вас есть RF24 радио, прикрепленную к Arduino и вы хотите послать определенный статус двери:
#define MY_RADIO_NRF24
#include <MySensors.h>
#include <SPI.h>
#define OPEN 1
#define CLOSE 0
MyMessage msg(NODE_ID, V_TRIPPED);
uint8_t value = OPEN;
void presentation()
{
present(NODE_ID, S_DOOR);
}
void loop()
{
value = value == OPEN ? CLOSE : OPEN;
send(msg.set(value));
sleep(10000);
}
ОК! Итак, что здесь происходит?
Инициализация
Библиотека MySensors автоматически запускается и представляет узел.
Если это первый раз, когда запускается узел он будет получать уникальный идентификатор узла от контроллера.
После того, как идентификатор получен от контроллера он будет сохранен в статической памяти EEPROM в Arduino. Идентификатор автоматически считывается из EEPROM каждый раз, когда узел перезагрузжается или отключается питание узла.
Инициализация также определяет кратчайший путь к сетевому шлюзу.
В этом примере #define MY_RADIO_NRF24 определяет, какой тип радио используется.
Презентация
Ваш датчик должен сначала представить себя контролеру. Представление необходимо чтобы контроллер подготовился к данным датчика, которые в конечном итоге придут. Это делается путем вызова present(child-sensor,id, sensor-type)
sensor-type Список поддерживаемых типов датчиков постоянно растет. Подробные объяснения типов поддерживаемых датчиков представлены в таблице.
Все present() должны быть помещены в функцию presentation(). Контроллер может позже повторно запросить эту информацию от узла.
typedef enum {
S_DOOR, S_MOTION, S_SMOKE, S_LIGHT, S_DIMMER, S_COVER, S_TEMP, ...
} sensor;
child-sensor-id Каждый узел радио может передавать данные до 254 различных датчиков. Вы можете выбирать любой ID датчика. Нельзя использовать идентификатор 255, поскольку он используется для системных целей, как отправка в уровне заряда батареи и другую информацию специфичную информацию.
Передача информации
Для передачи данных вы должны создать MyMessage контейнер для хранения информации. Создание контейнера выглядит следующим образом:
MyMessage msg(child-sensor-id, variable-type);
В методе loop() в приведенном выше примере мы делаем фактическую отправку вызовом send(msg.set(payload)). Это когда данные датчика передается в контроллер (или в другого место назначения).
child-sensor-id Здесь вы определяете датчик, который отправляет данные. В этом примере у нас есть только один датчик, таким образом мы выбираем 0.
variable-type При передаче данных в контроллер необходимо указать, какой тип данных вы сообщаете. Мы называем это variable-type. Часто тип датчика и тип переменной почти то же самое, но есть несколько датчиков, которые сообщают более чем один тип переменной. Например, измеритель мощности может сообщить как потребление за период, так и текущую мощность. Список типов переменных постоянно растет. Вы можете ознакомиться с таблицей типов переменных для более подробной информации.
typedef enum {
V_TEMP, V_HUM, V_LIGHT, V_DIMMER, V_PRESSURE, V_FORECAST, V_RAIN, ...
} variableType;
Вы всегда найдете самый последний список поддерживаемых датчиков и типов переменных в MyMessage.h на GitHub:
GitHub | MyMessage.h
Приведенный выше пример был простым, потому что передает только OPEN / CLOSE значений каждые 10 секунд. Тем не менее, это должно помочь вам понять, как написать скетч сенсорного узла. Есть много более продвинутых примеров здесь на MySensors если вы любите программирование типа копировать-вставить ;).
Создание Репитера (повторителя, ретранслятора)
Если вы живете в клетке Фарадея или огромном особняке вам может понадобиться несколько ретрансляторов-узлов, чтобы покрыть всю площадь. Для этого есть встроенный функционал ретранслятора.
Для того, чтобы превратить узел в ретранслятор, вы должны помнить несколько вещей:
- Включить режим ретранслятора путем добавления следующей строки в начало скетча:
#define MY_REPEATER_FEATURE
- Узел все время должен слушать эфир (быть не спящим!). Это означает, что ретранслятор не может работать с питанием от батареи (т.к. большой расход батареи).
Конфигурация
Конфигурация эскиза является очень важным шагом при создании узла MySensors. Она включает / отключает функции ядра во время компиляции, это также может быть сделано непосредственно в скетче источника с помощью #define-переменных.
Файл конфигурации MyConfig.h содержит много значений по умолчанию для конфигурирования. Они хорошо описаны, и вы можете посмотреть на него в этом файле.
Одно из наиболее часто используемых значений это MY_DEBUG, которое включает / отключает сообщения отладки. Можно настроить такие вещи, как тип радиомодуля, частота, канал, Led индикацию, опций подписи и т.д.
Не забудьте это настроить перед подключением библиотеки MySensors.h.
Вот все доступных опций. Примечание: Эта таблица будет обновляться в ближайшее время
| Name | Default Value | Comment |
| MY_NODE_ID | AUTO | ID ноды выдается автоматически, если статический адрес не указан в скетче (1-254). |
| MY_PARENT_NODE_ID | ID ноды родителя для данного узла. | |
| MY_PARENT_NODE_IS_STATIC | ID родителя постоянный | |
| MY_RADIO_NRF24 | Disabled | Добавьте в скетч если используете NRF24L01+ |
| MY_RADIO_RFM69 | Disabled | Добавьте в скетч если используете RFM69 |
| MY_RS485 | Disabled | Добавьте в скетч если используете serial |
| MY_REPEATER_FEATURE | Disabled | Включение функции репитера (повторителя, ретранслятора)(пересылаются сообщения других нод). Включать, если есть удаленные ноды на большом расстоянии от гейта. |
| MY_GATEWAY_SERIAL | ||
| MY_GATEWAY_W5100 | ||
| MY_GATEWAY_ENC28J60 | ||
| MY_GATEWAY_ESP8266 | ||
| MY_DEBUG | Disabled | Чтобы видеть сообщения в порту ноды добавить MY_DEBUG в скетче, но при включении увеличится размер скетча. |
| MY_SPECIAL_DEBUG | Disabled | Добавьте MY_SPECIAL_DEBUG в программу для активации I_DEBUG сообщений, если MY_DEBUG отключен. I_DEBUG запрашивает: R: routing info (only repeaters): received msg XXYY (as stream), where XX is the node and YY the routing node, V: CPU voltage //Напряжение на процессоре,F: CPU frequency // Частоту процессора (камня), M: free memory //Свободное место, E: clear MySensors EEPROM area and reboot (i.e. «factory» reset) //Очищает EEPROM и перезагружает ноду |
| MY_DEBUG_VERBOSE | Disabled | В консоль выводит подробные сообщения в части подписи сообщений |
| MY_DEBUG_VERBOSE_RF24 | Disabled | При включении выводит подробные сообщения касающиеся RF24 driver. DEBUG Должен быть включен. |
| MY_DEBUG_VERBOSE_SIGNING | Disabled | MY_DEBUG_VERBOSE_SIGNING в консоль выводит подробные сообщения в части подписи сообщений |
| MY_DISABLED_SERIAL | Disabled | Включить если необходимо использовать TX(1), RX(0) как обычные пины I/O pin |
| MY_WITH_LEDS_BLINKING_INVERSE | ||
| MY_DEFAULT_LED_BLINK_PERIOD | ||
| MY_DEFAULT_RX_LED_PIN | ||
| MY_DEFAULT_TX_LED_PIN | ||
| MY_DEFAULT_ERR_LED_PIN | ||
| MY_INCLUSION_MODE_FEATURE | ||
| MY_INCLUSION_BUTTON_FEATURE | ||
| MY_INCLUSION_MODE_BUTTON_PIN | ||
| MY_INCLUSION_MODE_DURATION | ||
| MY_INCLUSION_BUTTON_EXTERNAL_PULLUP | ||
| MY_SIGNING_ATSHA204 | ||
| MY_SIGNING_SOFT | ||
| MY_VERIFICATION_TIMEOUT_MS | ||
| MY_SIGNING_NODE_WHITELISTING | ||
| MY_SIGNING_ATSHA204_PIN | ||
| MY_SIGNING_SOFT_RANDOMSEED_PIN | ||
| MY_SIGNING_REQUEST_SIGNATURES | ||
| MY_RF24_ENABLE_ENCRYPTION | ||
| MY_RF24_SPI_MAX_SPEED | ||
| MY_RF24_CE_PIN | ||
| MY_RF24_CS_PIN | ||
| MY_RF24_PA_LEVEL | RF24_PA_MAX | Варианты усиления: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH or RF24_PA_MAX. MAX По умолчанию используется максимальная мощность NRF24l01 |
| MY_RF24_CHANNEL | 76 | |
| MY_RF24_DATARATE | 256Kbps | |
| MY_RF24_BASE_RADIO_ID | ||
| MY_SOFTSPI | ||
| MY_SOFT_SPI_SCK_PIN | ||
| MY_SOFT_SPI_MISO_PIN | ||
| MY_SOFT_SPI_MOSI_PIN | ||
| MY_REGISTRATION_FEATURE | Enabled | Если функция включена, нода сначала регистрируется на гейте, а уже потом передает данные с сенсоров |
| MY_REGISTRATION_RETRIES | 3 | Количество попыток регистрации если гейт или контроллер не отвечают |
| MY_REGISTRATION_DEFAULT | true | Регистрация по умолчанию, если нода не получила ответ о регистрации от гейта |
| MY_REGISTRATION_CONTROLLER | Disabled | Если включено, то запрос на регистрацию должен быть обработан контроллером |
| MY_OTA_FIRMWARE_FEATURE | Disabled | Добавьте MY_OTA_FIRMWARE_FEATURE для обновления по воздуху. Данная функция требует наличия внешней памяти и загрузчика DualOptiBoot .Вы можете обновиться по воздуху и без внешней памяти, но это требует наличие MYSBootloader и отключить MY_OTA_FIRMWARE_FEATURE Подробнее https://www.mysensors.org/about/ota https://www.mysensors.org/about/ota |
| MY_OTA_FLASH_SS | 8 | Указать пин для внешней памяти |
| MY_OTA_FLASH_JDECID | 0x1F65 | Память jdecid. |
| MY_RFM69_FREQUENCY | RFM69_868MHZ | Для других частот измените это определение в эскизе на предпочтительное значение в RFM69_433MHZ, RFM69_868MHZ или RFM69_915MHZ |
| MY_IS_RFM69HW | Disabled | По умолчанию это определение комментируется в библиотеке. Если вы хотите использовать версию RFM69H (C) W, просто добавьте это определение в свой эскиз |
| MY_RFM69_NETWORKID | 100 | Вы можете изменить его, добавив это определение в свой эскиз и настройте его на свое предпочтительное значение. Пример: #define MY_RFM69_NETWORKID 101 |
| MY_RF69_IRQ_PIN | 2 | Если вам нужно изменить его, добавьте это определение в свой эскиз и установите его на свой предпочтительный вывод. Примечание для 328p uC (mini pro, nano, moteino и т. Д.), Mysensors обрабатывает только контакты D2 / D3. Последнее примечание: на данный момент вам также необходимо установить MY_RF69_IRQ_NUM. Смотри ниже |
| MY_RF69_IRQ_NUM | 0 | (будет удален в следующем выпуске). Нужно, если вы хотите изменить контакт IRQ, к которому подключено ваше радио. Итак, если ваше радио подключено к D3 / INT1, установите #define MY_RF69_IRQ_PIN 3, затем #define MY_RF69_IRQ_NUM 1 |
| MY_RF69_SPI_CS | 10 | Вы можете изменить его, добавив это определение в свой эскиз и установите его на свой предпочтительный вывод значения |
| MY_RFM69_ENABLE_ENCRYPTION | Disabled | Добавьте это определение в свой эскиз, если вы хотите включить шифрование |
| MY_RAM_ROUTING_TABLE_FEATURE | Enabled | Если этот параметр включен, то таблица маршрутизации хранится в оперативной памяти (если позволяет память) и сохраняются в регулярные промежутки времени. Примечание: AVR имеет ограниченную память, использовать с осторожностью |
| MY_ROUTING_TABLE_SAVE_INTERVAL_MS | 10 min (600000ms) | Интервал обновления таблицы маршрутизации |
| MY_CORE_ONLY | Disabled | Добавить в скетч MY_CORE_ONLY если желаете использовать функции без загрузки всей платформы |
| MY_BAUD_RATE | 115200 | Устанавливаем скорость порта для отладочных сообщений и для СериалГейта |
| MY_CORE_COMPATIBILITY_CHECK | Enabled | Если этот параметр включен, библиотека проверяет совместимость при регистрации узла. Несовместимые библиотеки не могут отправить данные датчика. |
| MY_TRANSPORT_SANITY_CHECK | Disabled | Если функция включена нода проверяет передачу с регулярным интервалом для обнаружения проблем, при сбое пытается снова инициализировать. Включена для всех нод-репитеров. |
| MY_TRANSPORT_SANITY_CHECK_INTERVAL | 60000 | Величина интервала проверки передачи в мс. |
| MY_TRANSPORT_DISCOVERY_INTERVAL_MS | 10 min (600000ms) | Этот параметр проверки сети только для гейта |
| MY_TRANSPORT_UPLINK_CHECK_DISABLED | Disabled | Если установлено, то проверка поднятия линии связи GW отключается во время инициализации транспорта. |
| MY_TRANSPORT_MAX_TX_FAILURES | 10 | Максимально количествонеудачных инициализаций |
| MY_SLEEP_TRANSPORT_RECONNECT_TIMEOUT_MS | 10000 | Таймаут для повторной передачи если нода спит. |
| MY_SMART_SLEEP_WAIT_DURATION_MS | 500 | Период ожидания (в мс) перед сном при использовании SmartSleep-функций. Этот период должен быть достаточно большим для контроллера, чтобы иметь возможность посылать буферизованные сообщения. |
| MY_MQTT_SUBSCRIBE_TOPIC_PREFIX | ||
| MY_MQTT_PUBLISH_TOPIC_PREFIX | ||
| MY_MQTT_CLIENT_ID | ||
| MY_GATEWAY_MQTT_CLIENT | ||
| MY_NODE_LOCK_FEATURE | ||
| MY_NODE_UNLOCK_PIN | ||
| MY_NODE_LOCK_COUNTER_MAX | ||
| MY_ESP8266_SSID | ||
| MY_ESP8266_PASSWORD | ||
| MY_ESP8266_HOSTNAME | ||
| MY_PORT | ||
| MY_IP_ADDRESS | ||
| MY_USE_UDP | ||
| MY_IP_RENEWAL_INTERVAL | ||
| MY_MAC_ADDRESS | ||
| MY_CONTROLLER_IP_ADDRESS | ||
| MY_IP_GATEWAY_ADDRESS | ||
| MY_IP_SUBNET_ADDRESS | ||
| MY_GATEWAY_MAX_CLIENTS | 1 | Максимальное количество клиентов (режим сервера) |
| MY_GATEWAY_MAX_SEND_LENGTH | 120 | Максимальный размер буфера для отправки сообщений. |
| MY_GATEWAY_MAX_RECEIVE_LENGTH | 100 | Максимальный размер буфера сообщений приходящих от контроллера |
| MY_W5100_SPI_EN | ||
| MY_RS485_BAUD_RATE | ||
| MY_RS485_MAX_MESSAGE_LENGTH | ||
| MY_RS485_DE_PIN | ||
| MY_DISABLE_REMOTE_RESET | Disabled | Отключение удаленной перезагрузки ноды |
| MY_SMART_SLEEP_WAIT_DURATION | ||
| MY_SPIFLASH_SST25TYPE | ||
Запуск библиотеки
Библиотека запускается автоматически и перехватывает себя до вашего основного цикла.
Получение идентификатора узла
При включении режима автоматического ID (по умолчанию), датчик автоматически получает уникальный идентификатор узла. Идентификатор может быть получен с помощью вызова этого метода.
uint8_t getNodeId ();
Презентация
Датчики должны представить себя, прежде чем они начнут передавать данные контроллеру. Делайте эти вызовы в функции presentation()
void present(uint8_t childSensorId, uint8_t sensorType, const char *description, bool ack);
childSensorId — Уникальный идентификатор для датчика, подключенного к данному Arduino. Диапазон 0-254.
sensorType — тип датчика .
Description— Необязательное текстовое описание подключенного датчика.
ack — Установите true, если хотите чтобы конечный узел подтвердил получение сообщения. По умолчанию отключено.
Вы также можете отправить какую-то дополнительную мета-информацию для данного датчика узла.
void sendSketchInfo(const char *name, const char *version, bool ack);
name — строка, содержащая краткое имя эскиза или NULL. Не более 25 символов.
version — строка, содержащая краткий эскиз версии или NULL, если не применимо.
ack — Установите true, если хотите чтобы конечный узел подтвердил получение сообщения. По умолчанию отключено.
Отправка данных
Можно отправлять данные в контроллер или другой узел, используя метод Send (msg).
bool send(MyMessage &msg, bool ack);
msg — Сообщение, которое вы хотите отправить. См MyMessage для уточнения.
ack — Установите true, если хотите чтобы конечный узел подтвердил получение сообщения. По умолчанию отключено.
Если ваш узел работает от батареи, и вы реализовали измерения уровня батареи вы можете отправить уровень заряда батареи контроллеру.
void sendBatteryLevel(uint8_t level, bool ack);
level — Уровень заряда батареи между 0-100 (%) — уровень
ack — Установите true, если хотите чтобы конечный узел подтвердил получение сообщения. По умолчанию отключено.
Отправка сообщения на контроллер (узел жив!).
void sendHeartbeat();
Узлы, ожидающие входящие данные, такие, как исполнительные механизм (реле, и т.д) или ноды в режиме ретранслятора, должны использовать receive() — это функция для обработки входящих сообщений. Узлы должны быть не спящие иначе входящие данные будут утеряны.
void receive(const MyMessage &message)
message — Входящие данные сообщения
Запрос данных
Запрашивает какого-либо значение от шлюза или другого узла в сети. Если вы отправляете этот запрос на какой-либо узел, то должны самостоятельно обрабатывать ответное сообщение в функции receive() узла назначения. Добавление данной функции обязательно для обработки ответа на запрос.
void request(uint8_t childSensorId, uint8_t variableType, uint8_t destination);
childSensorId — Уникальный идентификатор сенсора для различных датчиков, подключенных к узлу. 0-254.
variableType — тип переменной .
destination — Id другого узла для запроса данных из сети. По умолчанию шлюз.
Запрос времени от контроллера
Запрашивает время от контроллера. Ответ будет получен в функцию receiveTime() в вашем эскизе.
void requestTime(); void receiveTime(unsigned long ts);
ts — Время в секундах, начиная с 1970 года с поправкой на часовой пояс с помощью контроллера.
Конфигурация контроллера
Ваш датчик отвечает за данные в правильных единицах измерения. Контроллер может дать вам «подсказку», о единицах измерения.
ControllerConfig GetConfig ();
ControlleConfig содержит только isMetric , который имеет следующие параметры:
истина (= метрическая) — Цельсию, метр, см, г, км / ч, м / с и т.п ..
ложь (= имперская) — Fahrenheit, ноги, галлон, миль / ч и т.д. …
Сохранение состояния
Вы можете сохранить значение (в локальном EEPROM), хорошо для исполнительных механизмов для запоминания состояния. У вас есть 256 байт. Обратите внимание, что существует ограничение на количество операций записи EEPROM может обрабатывать (~ 100 000 циклов).
void saveState(uint8_t pos, uint8_t value);
pos — (0-255)
value — значение для сохранения в позиции
Получение состояния (из локальной EEPROM).
uint8 loadState(uint8_t pos);
pos — Положение для извлечения из EEPROM (0-255)
Ожидание
Ожидание с использованием команды Arduino delay() не является хорошей идеей. Она останавливает всю обработку MySensors и ее следует избегать. Вместо этого вы должны использовать функцию wait(), которая вызывает process() во время ожидания. Обратите внимание, что она не обесточит Arduino или радио во время ожидания. Используйте функцию сна, если хотите сохранить батарею.
void wait(unsigned long ms);
ms — количество миллисекунд ожидания (в то же время обработка входящих данных)
Ожидание для конкретного сообщения (или максимальное время в миллисекундах).
bool wait(unsigned long ms, uint8_t cmd, uint8_t msgtype);
ms — количество миллисекунд ожидания (в то же время обработка входящих данных)
cmd — тип команды ожидания
msgtype — Тип сообщения для ожидания
Сон
Для экономии заряда батареи крайне важно, чтобы узел спал. Узел может проснуться от прерываний или с помощью таймера.
Каждая функция сна имеет «умный» вариант, который посылает heartbeat(узел жив) и обрабатывать входящие сообщения перед сном. Это полезно для отправки команд или прошивки FOTA для спящих узлов. Контроллер должен поддерживать буферизацию сообщений и отправлять их, когда узел просыпается.
Функции сна по таймеру.
void sleep(unsigned long ms); void smartSleep(unsigned long ms);
ms — Количество миллисекунд спать.
Функции сна по внешнему прерыванию или по таймеру
Смотрите: http://arduino.cc/en/Reference/attachInterrupt . Подробную информацию о режимах назначения ног прерывания. На Nano / Pro Mini: 0 = Pin2, 1 = PIN3
int8_t sleep(int interrupt, int mode, unsigned long ms=0); int8_t smartSleep(int interrupt, int mode, unsigned long ms=0);
interrupt — прерывание, которое должно вызвать пробуждение.
mode — RISING, FALLING, CHANGE (РАСТЕТ, ПАДАЕТ, ИЗМЕНЯЕТСЯ)
ms — Количество миллисекунд спать (или 0, чтобы спать постоянно).
Возвращает номер прерывания, если пробуждение было вызвано прерыванием, MY_SLEEP_NOT_POSSIBLE если сон не был возможен и отрицательное число если таймер разбудил его.
int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0); int8_t smartSleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0);
interrupt1 — Первое прерывание, которое должно вызвать пробуждение.
mode1 — режим для первого прерывания RISING, FALLING, CHANGE (РАСТЕТ, ПАДАЕТ, ИЗМЕНЯЕТСЯ)
interrupt2 — второе прерывание, которое должно вызвать пробуждение.
mode2 — режим для второго прерывания RISING, FALLING, CHANGE (РАСТЕТ, ПАДАЕТ, ИЗМЕНЯЕТСЯ)
ms — Количество миллисекунд спать (или 0, чтобы спать постоянно).
Возвращает номер прерывания, если пробуждение было вызвано прерыванием, MY_SLEEP_NOT_POSSIBLE если сон не был возможен и отрицательное число если по таймеру.
Подписание сообщений
Для включения подписанных сообщений, есть отличный гид здесь.
Конструктор сообщений
Создайте экземпляр MyMessage. Этот класс содержит данные сообщения и некоторые помощники для установки полезной нагрузки.
MyMessage (uint8_t childSensorId, uint8_t variableType);
childSensorId — Id датчика . 0-254.
variableType — тип переменной .
Управление сообщениями
Вы можете управлять исходящими и входящими сообщениями со следующими функциями.
// Setters for building message "on the fly" MyMessage& setType(uint8_t type); MyMessage& setSensor(uint8_t sensor); MyMessage& setDestination(uint8_t destination); // Setters for payload MyMessage& set(void* payload, uint8_t length); MyMessage& set(const char* value); MyMessage& set(uint8_t value); MyMessage& set(float value, uint8_t decimals); MyMessage& set(unsigned long value); MyMessage& set(long value); MyMessage& set(unsigned int value); MyMessage& set(int value); // Getter for ack-flag. Returns true if this is an ack message. bool isAck() const; // Getters for picking up payload on incoming messages char* getStream(char *buffer) const; char* getString(char *buffer) const; const char* getString() const; void* getCustom() const; uint8_t getByte() const; bool getBool() const; float getFloat() const; long getLong() const; unsigned long getULong() const; int getInt() const; unsigned int getUInt() const;
Автор перевода anton_kulibin