2021-12-23 09:09:26 +03:00
# include "Utils/JsonUtils.h"
# include "Utils/SerialPrint.h"
# include "Utils/StringUtils.h"
# include "Class/IoTSensor.h"
# include "Class/IoTModule.h"
# include "DallasTemperature.h"
# include <OneWire.h>
2021-12-24 20:03:38 +03:00
# include <map>
2021-12-23 09:09:26 +03:00
extern std : : vector < IoTModule * > iotModules ; //v3dev: вектор ссылок базового класса IoTModule - интерфейсы для общения с о всеми поддерживаемыми системой модулями
2021-12-24 20:03:38 +03:00
//глобальные списки необходимы для хранения объектов о б активных линиях 1-wire используемых разными датчиками из модуля. Ключ - номер пина
std : : map < int , OneWire * > oneWireTemperatureArray ;
std : : map < int , DallasTemperature * > sensorsTemperatureArray ;
2021-12-23 09:09:26 +03:00
class IoTSensorDallas : public IoTSensor {
private :
//описание переменных экземпляра датчика - аналог глобальных переменных из Arduino
2021-12-24 20:03:38 +03:00
//для работы библиотеки с несколькими линиями необходимо обеспечить каждый экземпляр класса ссылками на объекты настроенные на эти линии
2021-12-23 09:09:26 +03:00
OneWire * oneWire ;
2021-12-24 20:03:38 +03:00
DallasTemperature * sensors ;
2021-12-23 09:09:26 +03:00
//описание параметров передаваемых из настроек датчика из веба
String _addr ;
unsigned int _pin ;
unsigned int _index ;
public :
//аналог setup() из Arduino
IoTSensorDallas ( String parameters ) {
2021-12-27 21:24:55 +03:00
//передаем часть базовых параметров в конструктор базового класса для обеспечения работы е г о методов
init ( jsonReadStr ( parameters , " key " ) , jsonReadStr ( parameters , " id " ) , jsonReadInt ( parameters , " int " ) ) ;
2021-12-23 09:09:26 +03:00
_pin = jsonReadInt ( parameters , " pin " ) ;
_index = jsonReadInt ( parameters , " index " ) ;
_addr = jsonReadStr ( parameters , " addr " ) ;
2021-12-24 20:03:38 +03:00
//учитываем, что библиотека может работать с несколькими линиями на разных пинах, поэтому инициируем библиотеку, если линия ранее не использовалась
if ( oneWireTemperatureArray . find ( _pin ) = = oneWireTemperatureArray . end ( ) ) {
oneWire = new OneWire ( ( uint8_t ) _pin ) ;
sensors = new DallasTemperature ( ) ;
sensors - > setOneWire ( oneWire ) ;
sensors - > begin ( ) ;
sensors - > setResolution ( 12 ) ;
oneWireTemperatureArray [ _pin ] = oneWire ;
sensorsTemperatureArray [ _pin ] = sensors ;
} else {
oneWire = oneWireTemperatureArray [ _pin ] ;
sensors = sensorsTemperatureArray [ _pin ] ;
}
2021-12-23 09:09:26 +03:00
}
~ IoTSensorDallas ( ) { }
//аналог loop() из Arduino но квотируемый по времени параметром interval
void doByInterval ( ) {
2021-12-24 20:03:38 +03:00
//запускаем опрос измерений у всех датчиков на линии
sensors - > requestTemperatures ( ) ;
2021-12-23 09:09:26 +03:00
2021-12-24 20:03:38 +03:00
//Определяем адрес. Если парамтер addr не установлен, то узнаем адрес по индексу
2021-12-23 09:09:26 +03:00
DeviceAddress deviceAddress ;
if ( _addr = = " " ) {
2021-12-24 20:03:38 +03:00
sensors - > getAddress ( deviceAddress , _index ) ;
2021-12-23 09:09:26 +03:00
} else {
string2hex ( _addr . c_str ( ) , deviceAddress ) ;
}
2021-12-24 20:03:38 +03:00
//получаем температуру по адресу
float value = sensors - > getTempC ( deviceAddress ) ;
2021-12-23 09:09:26 +03:00
char addrStr [ 20 ] = " " ;
2021-12-24 20:03:38 +03:00
hex2string ( deviceAddress , 8 , addrStr ) ;
2021-12-23 09:09:26 +03:00
regEvent ( ( String ) value , " addr: " + String ( addrStr ) ) ; //обязательный вызов для отправки результата работы
}
} ;
2021-12-23 13:02:06 +03:00
//технический класс для взаимодействия с ядром, меняются только названия
2021-12-23 09:09:26 +03:00
class IoTModuleDallasTemp : public IoTModule {
2021-12-23 13:02:06 +03:00
//обязательный метод для инициализации экземпляра датчика, вызывается при чтении конфигурации. Нужно учитывать, что некоторые датчики могут обеспечивать
//несколько измерений, для каждого будет отдельный вызов.
2021-12-23 09:09:26 +03:00
void * initInstance ( String parameters ) {
return new IoTSensorDallas ( parameters ) ;
} ;
2021-12-27 21:24:55 +03:00
//обязательный к заполнению метод, если модуль использует свои глобальные переменные. Необходимо сбросить и очистить используемую память.
void clear ( ) {
2021-12-27 22:05:23 +03:00
for ( auto it = sensorsTemperatureArray . cbegin ( ) , next_it = it ; it ! = sensorsTemperatureArray . cend ( ) ; it = next_it ) {
+ + next_it ;
DallasTemperature * tmpptr = it - > second ; //временно сохраняем указатель на сенсор, т.к. е г о преждевременное удаление оставит поломаную запись в векторе, к которой может обратиться ядро и вызвать исключение
sensorsTemperatureArray . erase ( it ) ;
delete tmpptr ; //а далее уже удаляем объект сенсора
2021-12-27 21:24:55 +03:00
}
2021-12-27 22:05:23 +03:00
for ( auto it = oneWireTemperatureArray . cbegin ( ) , next_it = it ; it ! = oneWireTemperatureArray . cend ( ) ; it = next_it ) {
+ + next_it ;
OneWire * tmpptr = it - > second ; //временно сохраняем указатель на сенсор, т.к. е г о преждевременное удаление оставит поломаную запись в векторе, к которой может обратиться ядро и вызвать исключение
oneWireTemperatureArray . erase ( it ) ;
delete tmpptr ; //а далее уже удаляем объект сенсора
2021-12-27 21:24:55 +03:00
}
}
2021-12-23 13:02:06 +03:00
//обязательный метод для отправки информации о модуле,
2021-12-23 09:09:26 +03:00
ModuleInfo getInfo ( ) {
ModuleInfo MI ;
2021-12-27 21:24:55 +03:00
MI . name = " dallas-temp " ;
MI . title = " Датчик температуры Ds18b20 " ;
MI . parameters = " { \" key \" : \" dallas-temp \" , \" id \" : \" tmp \" , \" addr \" : \" \" , \" int \" : \" 10 \" , \" pin \" : \" 18 \" , \" index \" : \" 0 \" } " ;
2021-12-23 09:09:26 +03:00
MI . type = " Sensor " ;
return MI ;
} ;
} ;
2021-12-23 13:02:06 +03:00
//точка входа в модуль для заполнения вектора, требуется только изменить имя и прописать в файле api.cpp
2021-12-23 09:09:26 +03:00
void getApiIoTSensorDallasTemp ( ) {
iotModules . push_back ( new IoTModuleDallasTemp ( ) ) ;
return ;
}