#include "device_io_service.hpp" #include "iflytopcpp/core/components/string_util.hpp" #include "iflytopcpp/core/components/time_util.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() { modbusMaster = shared_ptr(new ModbusMaster()); bool suc = modbusMaster->initializeTtyChannel("/dev/ttyUSB0", 115200); if (!suc) { logger->error("modbusMaster initializeTtyChannel fail"); } thread.reset(new Thread("input_device_state_monitor", [this]() { inputStateMonitorLoop(); })); idcard_read_thread.reset(new Thread("idcard_read", [this]() { ThisThread thisThread; while (!thisThread.getExitFlag()) { try { bool state; string info; idcardread(state, info); if (state) { logger->info("idcard read info:{}", info); onidcard(info); } } catch (zexception& e) { static tp_steady lastlogticket; if (tu_steady().elapsedTimeS(lastlogticket) > 5) { logger->error("idcard read fail:{}", e.what()); lastlogticket = tu_steady().now(); } } thisThread.sleepForMs(100); } })); } void DeviceIOService::relayControl(relay_device_type_t type, bool value) { /** * @brief * 0(16Byte) | 继电器0 ->继电器15 掩码 * 1(16Byte) | 继电器16->继电器31 掩码 * 2(16Byte) | 继电器0 ->继电器15 继电器状态 * 3(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, 0, 4, reg, kovertime)); } DeviceIOService::RelayDeviceState DeviceIOService::relayStateGet() { /** * @brief * 0(16Byte) | 继电器0 ->继电器15 掩码 * 1(16Byte) | 继电器16->继电器31 掩码 * 2(16Byte) | 继电器0 ->继电器15 继电器状态 * 3(16Byte) | 继电器16->继电器31 继电器状态 */ DeviceIOService::RelayDeviceState state = {}; Modbus03Rx modbus03rx; EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 2, 2, modbus03rx, kovertime)); uint32_t regstate = uint32_t(modbus03rx.getReg(2)) | uint32_t(modbus03rx.getReg(3) << 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); } #if 0 /*********************************************************************************************************************** * ==================================================路由器电源控制=================================================== * ***********************************************************************************************************************/ bool DeviceIOService::routerGetPowerState() { return relayStateGet(0); } void DeviceIOService::routerSetPowerState(bool routepower) { logger->debug("routerSetPowerState {}", routepower); relayControl(0, true); } /*********************************************************************************************************************** * ==================================================触控屏供电控制=================================================== * ***********************************************************************************************************************/ bool DeviceIOService::touchScreenGetPowerState() { return relayStateGet(1); } void DeviceIOService::touchScreenSetPowerState(bool touchpower) { logger->debug("touchScreenSetPowerState {}", touchpower); relayControl(1, touchpower); } /*********************************************************************************************************************** * ==================================================USB充电器供电=================================================== * ***********************************************************************************************************************/ bool DeviceIOService::usbChargerGetPowerState() { return relayStateGet(2); } void DeviceIOService::usbChargerSetPowerState(bool usbpower) { logger->debug("usbChargerSetPowerState {}", usbpower); relayControl(2, usbpower); } /*********************************************************************************************************************** * ==================================================摄像头供电=================================================== * ***********************************************************************************************************************/ bool DeviceIOService::cameraGetPowerState() { return relayStateGet(3); } void DeviceIOService::cameraSetPowerState(bool camerapower) { logger->debug("cameraSetPowerState {}", camerapower); relayControl(3, camerapower); } /*********************************************************************************************************************** * ==================================================照明控制=================================================== * ***********************************************************************************************************************/ bool DeviceIOService::lightGetPowerState() { return relayStateGet(4); } void DeviceIOService::lightSetPowerState(bool lightpower) { logger->debug("lightSetPowerState {}", lightpower); relayControl(4, lightpower); } #endif DeviceIOService::InputDeviceState DeviceIOService::getinputState() { DeviceIOService::InputDeviceState inputDeviceState; Modbus03Rx modbus03rx; EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 4, 2, modbus03rx, kovertime)); uint32_t regstate = uint32_t(modbus03rx.getReg(4)) | uint32_t(modbus03rx.getReg(5) << 16); inputDeviceState.state = regstate; return inputDeviceState; } void DeviceIOService::inputStateMonitorLoop() { ThisThread thisThread; while (!thisThread.getExitFlag()) { try { uint32_t regstate = getinputState().state; for (size_t i = 0; i < 32; i++) { bool state = (regstate & (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); } } } catch (const std::exception& e) { /** * @brief 如果出现异常,则每隔5秒打印一次日志 */ static tp_steady lastlogticket; if (tu_steady().elapsedTimeS(lastlogticket) > 5) { logger->error("inputStateMonitorLoop fail, {}", e.what()); lastlogticket = tu_steady().now(); } } thisThread.sleepForMs(50); } } uint32_t DeviceIOService::getInterTemperature() { return getReg(16); } DeviceIOService::env_sensor_state_t DeviceIOService::getEnvSensorState() { Modbus03Rx modbus03rx; env_sensor_state_t env_sensor_state = {0}; EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, 48, 11, modbus03rx, kovertime)); /** 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 */ 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); 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; } 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::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 = StringUtil().bytesToString(modbus03rx.getRegBegin(), datalen); } state = true; logger->debug("idcardread, state={},info={}", state, info); return; }