Для небольшого проекта я обзавёлся Arduino Ethernet и начал писать для него программки. Проект подразумевает подключение десятков или даже несколько сотен идентичных устройств к IP сети и периодического сброса информации на Web сервер.
Проект рассчитан на долговременное использования. Устройства могут устанавливаться в труднодоступных местах или в вандалозащищённых корпусах. За время работы системы я хочу иметь возможность заменять или добавлять новые устройства в систему не используя программатор.
Учитывая всё это я решил озадачиться вопросом передачи конфигурации из центрального источника (сервера) во время начала работы платы, а не на записывая конфигурацию в EEPROM или Flash.
Протокол BOOTP/DHCP, который определён в RFC 951, 1531 и 2131 и рассчитан как раз на то, что бы производить первоначальную конфигурацию сетевых устройств. Одной из возможностей протокола является определение собственных типов переменных и их обработку на стороне клиента. Этой возможностью я как раз и хочу воспользоваться.
Реализация в библиотеке Arduino Ethernet протокола DHCP весьма ограничена и не подразумевает расширения. С помощью DHCP возможно (в версии 1.0.3) установить только IP адрес, маску сети, DNS сервер и маршрут по-умолчанию.
Я модифицировал соответствующий код в библиотеке и теперь стало возможно реализовывать вот такой способ настройки:
// Определяем функцию-обработчик для неизвестных опций
void dhcpOptionParser(const uint8_t optionType, EthernetUDP *dhcpUdpSocket) {
uint8_t opt_len = dhcpUdpSocket->read();
if (optionType == 15) { // domain name
// читаем нужную нам опцию при помощи dhcpUdpSocket->read()
} else {
while (opt_len--) {
dhcpUdpSocket->read();
}
}
}
// Определяем функцию-генератор дополнительных опций запроса
void dhcpOptionProvider(const uint8_t messageType, EthernetUDP *dhcpUdpSocket) {
uint8_t buffer[] = {
dhcpClassIdentifier,
0x08,
'M','S','F','T',' ','5','.','0'
};
dhcpUdpSocket->write(buffer, 10);
}
//...
// Инициализируем библиотеку Ethernet с нужными ссылками
void setup() {
// ...
Ethernet.begin(mac, (DhcpOptionParser *) &dhcpOptionParser, (DhcpOptionProvider *) &dhcpOptionProvider);
// ...
}
Таким образом для того, что бы получить параметры с сервера и настроить своё приложение необходимо реализовать функцию dhcpOptionParser
и в ней прочитать данные, которые поступили от DHCP сервера.
Этот метод можно реализовать на любом DHCP сервере, в котором можно определять дополнительные опции. Например, для ISC-DHCP это будет выглядеть следующим образом (определяем новую опцию xTargetWebServerAddress с номером 128):
option xTargetWebServerAddress code 128 = ip-address;
option xTargetWebServerAddress www.habrahabr.ru;
Эти параметры нужно добавить в dhcpd.conf
.
Как бонус я сделал возможность отправлять дополнительные опции как часть запроса. В примере Arduino пошлёт опцию Vendor Class Identifier (номер 60) со значением «MSFT 5.0».
Изменения ждут интеграции в основной код Arduino на GitHub. Пока что можно воспользоваться моей веткой.
Автор: valexeev