Power monitor для встраиваемых систем (Linux)
// синглтон для записи логов
static logger& loggerInstance = logger::Instance();
I2cPoll::I2cPoll() {
// создаем класс БД
db = new DbConnection();
if(db->isConnecting()) {
loggerInstance.appendToLog("I2cPoll: db-connected-OK\r\n");
} else {
loggerInstance.appendToLog("I2cPoll: db opening -ERROR\r\n");
}
// структура позволят опрашивать больше одного устройства
// указываем с которого начинать опрос
this->currentDeviceType = startDeviceType;
}
// функция опроса
void I2cPoll::pollExect() {
uint8_t *p_data = NULL;
uint16_t word = 0;
bool res = false;
char cmd_command[128] = {0};
S_insertData device_data;
int device_addr = 0;
// формируем запрос
switch(currentDeviceType) {
case dev_i2c_ina260: {
// извлекаем из БД id устройства
device_addr = db->getDeviceAddrFromName(
i2c_Dev_typeName.ina260.name_text.c_str()
);
// если извлекли правильно
if(device_addr != 0) {
// интересует 3 параметра - ток, напряжение и мощность
for(int i=0; i<3; i++) {
switch(i) {
// curent
case 0:
sprintf(cmd_command, "i2cget -y 0 0x%X 0x01 w\r\n", device_addr);
// отправляем в консоль
res = readWord(cmd_command, &word);
if(res) { // проверяем ответ
p_data = (uint8_t*)&word;
float raw_data;
fprintf(stdout, "Raw u16 %x\r\n", word);
// преобразование по описанию из даташита
raw_data = (0xFF & p_data[1]) | ((0xFF & (p_data[0])) << 8);
device_data.parameter.power_monitor.currnetFlowing =
raw_data * 1.25 / 1000;
fprintf(stdout, "Current %4.2f\r\n",
device_data.parameter.power_monitor.currnetFlowing
);
}
break;
// voltage
case 1:
sprintf(cmd_command, "i2cget -y 0 0x%X 0x02 w", device_addr);
// отправляем в консоль
res = readWord(cmd_command, &word);
if(res) { // проверяем ответ
p_data = (uint8_t*)&word;
float raw_data;
fprintf(stdout, "Raw u16 %x\r\n", word);
// преобразование по описанию из даташита
raw_data = (0xFF & p_data[1]) | ((0xFF & (p_data[0])) << 8);
device_data.parameter.power_monitor.voltage =
raw_data * 1.25 / 1000;
fprintf(stdout, "Volage %4.2f\r\n",
device_data.parameter.power_monitor.voltage
);
}
break;
case 2:
// power
sprintf(cmd_command, "i2cget -y 0 0x%X 0x03 w\r\n", device_addr);
// отправляем в консоль
res = readWord(cmd_command, &word);
if(res) { // проверяем ответ
p_data = (uint8_t*)&word;
float raw_data;
fprintf(stdout, "Raw u16 %x\r\n", word);
// преобразование по описанию из даташита
raw_data = (0xFF & p_data[1]) | ((0xFF & (p_data[0])) << 8);
device_data.parameter.power_monitor.currentPower =
raw_data * 1.25;
fprintf(stdout, "Power %4.2f\r\n",
device_data.parameter.power_monitor.currentPower
);
}
break;
}
}
// если все опросили, отправляем данные в БД
if(res) {
db->insertData(device_data);
}
}
}
break;
default : // если что-то не так, начинаем с первого устройства
currentDeviceType = startDeviceType;
break;
}
// после конца цикла, начинаем с первого устройства
if(currentDeviceType >= (E_I2c_device)endTypeDeviceType) {
currentDeviceType = startDeviceType;
fprintf(stdout, "I2c parce -endDev\r\n");
} else { // иначе опрашиваем следующий
currentDeviceType++;
fprintf(stdout, "I2c parce -nextDev\r\n");
}
}
// формируем запрос на шину i2c
// парсим данные в ответе
bool I2cPoll::readWord(char *cmd_command, uint16_t *p_word) {
int res = false;
int word = 0;
FILE *stream;
// отправляем в консоль
stream = popen(cmd_command, "r");
fprintf(stdout, "cmd_command - %s\r\n", cmd_command);
std::string data;
if (stream) {
char reply_buff[128] = {0};
while (!feof(stream))
if(fgets(reply_buff, sizeof(reply_buff), stream) != NULL) {
data.append(reply_buff);
}
pclose(stream);
}
// проверяем ответ
fprintf(stdout, "shell result :\r\n%s\r\n", data.c_str());
if(data.length() != 0) {
char *p_start = strstr((char*)data.c_str(), "0x");
if(p_start != NULL) {
res = sscanf(p_start, "%x", &word);
if(res) {
*p_word = (uint16_t)word;
}
fprintf(stdout, "getWord %x\r\n", *p_word);
}
}
return res;
}
I2cPoll::~I2cPoll() {
// TODO Auto-generated destructor stub
}