You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
266 lines
9.7 KiB
266 lines
9.7 KiB
#include "device_io_service.hpp"
|
|
|
|
#include "iflytopcpp/core/components/stringutils.hpp"
|
|
#include "iflytopcpp/core/components/timeutils.hpp"
|
|
#include "iflytopcpp/core/zexception/zexception.hpp"
|
|
using namespace iflytop;
|
|
using namespace core;
|
|
using namespace std;
|
|
|
|
const static int ksubboarddeviceid = 0x01;
|
|
const int kovertime = 33;
|
|
|
|
#define EXEC_MODBUS(exptr) \
|
|
int ret = exptr; \
|
|
if (ret != 0) { \
|
|
throw zexception( \
|
|
fmt::format("[{}:{}] do {} fail, ret={},{}", __FUNCTION__, __LINE__, #exptr, ret, modbusStatusToStr(ret))); \
|
|
}
|
|
|
|
void DeviceIOService::initialize(string uartpath, int baudrate) {
|
|
modbusMaster = shared_ptr<ModbusMaster>(new ModbusMaster());
|
|
bool suc = modbusMaster->initializeTtyChannel(uartpath.c_str(), baudrate);
|
|
if (!suc) {
|
|
logger->error("modbusMaster initializeTtyChannel fail");
|
|
}
|
|
#if 0
|
|
|
|
thread.reset(new Thread("input_device_state_monitor", [this]() { inputStateMonitorLoop(); }));
|
|
idcard_read_thread.reset(new Thread("idcard_read", [this]() {idcardreadLoop();}));
|
|
#endif
|
|
}
|
|
void DeviceIOService::relayControl(uint32_t type, bool value) {
|
|
/**
|
|
* @brief
|
|
* 8(16Byte) | 继电器0 ->继电器15 掩码
|
|
* 9(16Byte) | 继电器16->继电器31 掩码
|
|
* 10(16Byte) | 继电器0 ->继电器15 继电器状态
|
|
* 11(16Byte) | 继电器16->继电器31 继电器状态
|
|
*/
|
|
uint32_t off = (uint32_t)type;
|
|
uint32_t mask = 1 << off;
|
|
uint32_t status = value ? mask : 0;
|
|
|
|
uint16_t reg[4];
|
|
MODBUS_SET_REG(reg[0], uint16_t(mask));
|
|
MODBUS_SET_REG(reg[1], uint16_t(mask >> 16));
|
|
MODBUS_SET_REG(reg[2], uint16_t(status));
|
|
MODBUS_SET_REG(reg[3], uint16_t(status >> 16));
|
|
|
|
EXEC_MODBUS(modbusMaster->modbus10(ksubboarddeviceid, 8, 4, reg, kovertime));
|
|
}
|
|
DeviceIOService::RelayDeviceState DeviceIOService::relayStateGet() {
|
|
/**
|
|
* @brief
|
|
* 8(16Byte) | 继电器0 ->继电器15 掩码
|
|
* 9(16Byte) | 继电器16->继电器31 掩码
|
|
* 10(16Byte) | 继电器0 ->继电器15 继电器状态
|
|
* 11(16Byte) | 继电器16->继电器31 继电器状态
|
|
*/
|
|
DeviceIOService::RelayDeviceState state = {};
|
|
Modbus03Rx modbus03rx;
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 10, 2, modbus03rx, kovertime));
|
|
uint32_t regstate = uint32_t(modbus03rx.getReg(10)) | uint32_t(modbus03rx.getReg(11) << 16);
|
|
state.state = regstate;
|
|
return state;
|
|
}
|
|
|
|
uint16_t DeviceIOService::getReg(int index) {
|
|
Modbus03Rx modbus03rx;
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, index, 1, modbus03rx, kovertime));
|
|
return modbus03rx.getReg(index);
|
|
}
|
|
DeviceIOService::InputDeviceState DeviceIOService::getinputState() {
|
|
#if 0
|
|
寄存器:
|
|
Addr | 功能
|
|
------------|-------------------------------
|
|
12(16Byte) | 所有限位输入状态
|
|
#endif
|
|
DeviceIOService::InputDeviceState inputDeviceState;
|
|
Modbus03Rx modbus03rx;
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 12, 1, modbus03rx, kovertime));
|
|
uint32_t regstate = uint32_t(modbus03rx.getReg(12)) | 0;
|
|
inputDeviceState.state = regstate;
|
|
return inputDeviceState;
|
|
}
|
|
uint32_t DeviceIOService::getInterTemperature() { return getReg(16); }
|
|
DeviceIOService::env_sensor_state_t DeviceIOService::getEnvSensorState() {
|
|
Modbus03Rx modbus03rx;
|
|
env_sensor_state_t env_sensor_state = {0};
|
|
/**
|
|
48(16Byte) | 风速
|
|
49(16Byte) | 风向
|
|
50(16Byte) | temperature 实际湿度值=temperature/10 ℃
|
|
51(16Byte) | humidity 实际湿度值=humidity/10 (0->100%)
|
|
52(16Byte) | 噪声
|
|
53(16Byte) | pm2.5 ug/m³
|
|
54(16Byte) | pm10 ug/m³
|
|
55(16Byte) | co2 PPM
|
|
56(16Byte) | 大气压力 PPM
|
|
57(16Byte) | tvoc ppm
|
|
58(16Byte) | hcho mg/m3
|
|
59(16Byte) | light_intensity H
|
|
60(16Byte) | light_intensity L
|
|
*/
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 48, 13, modbus03rx, kovertime));
|
|
env_sensor_state.wind_speed = modbus03rx.getReg(48);
|
|
env_sensor_state.wind_direction = modbus03rx.getReg(49);
|
|
env_sensor_state.temperature = modbus03rx.getReg(50);
|
|
env_sensor_state.humidity = modbus03rx.getReg(51);
|
|
env_sensor_state.noise = modbus03rx.getReg(52);
|
|
env_sensor_state.pm2_5 = modbus03rx.getReg(53);
|
|
env_sensor_state.pm10 = modbus03rx.getReg(54);
|
|
env_sensor_state.co2 = modbus03rx.getReg(55);
|
|
env_sensor_state.atmospheric_pressure = modbus03rx.getReg(56);
|
|
env_sensor_state.tvoc = modbus03rx.getReg(57);
|
|
env_sensor_state.hcho = modbus03rx.getReg(58);
|
|
env_sensor_state.light_intensity = uint32_t(modbus03rx.getReg(59)) << 16 | uint32_t(modbus03rx.getReg(60));
|
|
|
|
logger->debug(
|
|
"getEnvSensorState, "
|
|
"wind_speed={},wind_direction={},temperature={},humidity={},noise={},pm2_5={},pm10={},co2={},atmospheric_"
|
|
"pressure={},tvoc={},hcho={}",
|
|
env_sensor_state.wind_speed, env_sensor_state.wind_direction, env_sensor_state.temperature,
|
|
env_sensor_state.humidity, env_sensor_state.noise, env_sensor_state.pm2_5, env_sensor_state.pm10,
|
|
env_sensor_state.co2, env_sensor_state.atmospheric_pressure, env_sensor_state.tvoc, env_sensor_state.hcho);
|
|
return env_sensor_state;
|
|
}
|
|
|
|
void DeviceIOService::fanGetState(int id, float& power, uint16_t& error) {
|
|
int startindex = 0;
|
|
if (id == 0) {
|
|
startindex = 128;
|
|
} else if (id == 1) {
|
|
startindex = 136;
|
|
} else {
|
|
power = 0;
|
|
error = 0;
|
|
logger->error("fanGetState fail, id={},id is illegal", id);
|
|
}
|
|
|
|
Modbus03Rx modbus03rx;
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, startindex, 2, modbus03rx, kovertime));
|
|
power = modbus03rx.getReg(startindex);
|
|
error = modbus03rx.getReg(startindex + 1);
|
|
logger->debug("fanGetState, id={},power={},error={}", id, power, error);
|
|
return;
|
|
}
|
|
|
|
void DeviceIOService::fanSetState(int id, float power) {
|
|
logger->debug("fanSetState, id={},power={}", id, power);
|
|
int startindex = 0;
|
|
if (id == 0) {
|
|
startindex = 128;
|
|
} else if (id == 1) {
|
|
startindex = 136;
|
|
} else {
|
|
logger->error("fanGetState fail, id={},id is illegal", id);
|
|
return;
|
|
}
|
|
|
|
uint16_t reg[1];
|
|
MODBUS_SET_REG(reg[0], uint16_t(power));
|
|
EXEC_MODBUS(modbusMaster->modbus10(ksubboarddeviceid, startindex, 1, reg, kovertime));
|
|
return;
|
|
}
|
|
|
|
void DeviceIOService::idcardread(bool& state, string& info) {
|
|
/**
|
|
* 64->127 | 读卡器透传,03时读取消息,10写消息
|
|
* 64(16Byte) | 是否有新卡信息
|
|
* 65(16Byte) | 卡的内容
|
|
* 65(16Byte) |
|
|
* ..(16Byte) |
|
|
* 127(16Byte) |
|
|
*/
|
|
state = false;
|
|
info = "";
|
|
int datalen = 0;
|
|
{
|
|
Modbus03Rx modbus03rx;
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 64, 1, modbus03rx, kovertime));
|
|
datalen = modbus03rx.getReg(64);
|
|
}
|
|
if (datalen == 0) {
|
|
logger->debug("idcardread, state={},info={}", state, info);
|
|
return;
|
|
}
|
|
|
|
int readreg = datalen / 2 + datalen % 2 != 0 ? 1 : 0;
|
|
|
|
{
|
|
Modbus03Rx modbus03rx;
|
|
EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 65, readreg, modbus03rx, kovertime));
|
|
info = StringUtils().bytesToString(modbus03rx.getRegBegin(), datalen);
|
|
}
|
|
state = true;
|
|
logger->debug("idcardread, state={},info={}", state, info);
|
|
return;
|
|
}
|
|
/*************************************************************************************
|
|
* *
|
|
* 非MODBUS直接调用接口 *
|
|
* *
|
|
*************************************************************************************/
|
|
float DeviceIOService::fanGetState(int id) {
|
|
float power = 0;
|
|
uint16_t error = 0;
|
|
fanGetState(id, power, error);
|
|
if (error != 0) {
|
|
return -1;
|
|
}
|
|
return power;
|
|
}
|
|
|
|
void DeviceIOService::inputStateMonitorLoop() {
|
|
ThisThread thisThread;
|
|
int loopperiod = 50;
|
|
while (!thisThread.getExitFlag()) {
|
|
try {
|
|
uint32_t newkeystate = getinputState().state;
|
|
for (size_t i = 0; i < 32; i++) {
|
|
bool state = (newkeystate & (1 << i)) != 0;
|
|
bool oldstate = (keystate & (1 << i)) != 0;
|
|
if (state != oldstate) {
|
|
logger->info("on {} state change, state={}", input_device_type2str(input_device_type_t(i)), state);
|
|
onInputStateChange((input_device_type_t)i, state);
|
|
}
|
|
}
|
|
keystate = newkeystate;
|
|
loopperiod = 50;
|
|
} catch (const std::exception& e) {
|
|
/**
|
|
* @brief 如果出现异常,那么就延时10秒,然后再次尝试
|
|
*/
|
|
logger->error("[:{}] catch exception, {}", __LINE__, e.what());
|
|
loopperiod = 10000;
|
|
} catch (...) {
|
|
logger->error("[:{}] catch exception, unknown error", __LINE__);
|
|
loopperiod = 10000;
|
|
}
|
|
thisThread.sleepForMs(loopperiod);
|
|
}
|
|
}
|
|
|
|
void DeviceIOService::idcardreadLoop() {
|
|
ThisThread thisThread;
|
|
int loopperiod = 50;
|
|
while (!thisThread.getExitFlag()) {
|
|
try {
|
|
bool state;
|
|
string info;
|
|
|
|
idcardread(state, info);
|
|
if (state) {
|
|
logger->info("idcard read info:{}", info);
|
|
onidcard(info);
|
|
}
|
|
loopperiod = 50;
|
|
} catch (zexception& e) {
|
|
logger->error("idcard read fail:{}", e.what());
|
|
loopperiod = 10000;
|
|
}
|
|
thisThread.sleepForMs(loopperiod);
|
|
}
|
|
}
|