diff --git a/.vscode/settings.json b/.vscode/settings.json index 41fc6ca..ff43457 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,22 +1,21 @@ { "files.associations": { - "vector": "cpp", - "*.def": "cpp", - "valarray": "cpp", + "__locale": "cpp", "array": "cpp", "atomic": "cpp", + "hash_map": "cpp", + "bit": "cpp", "*.tcc": "cpp", "bitset": "cpp", "cctype": "cpp", - "cfenv": "cpp", + "charconv": "cpp", "chrono": "cpp", - "cinttypes": "cpp", "clocale": "cpp", "cmath": "cpp", "codecvt": "cpp", - "complex": "cpp", + "compare": "cpp", + "concepts": "cpp", "condition_variable": "cpp", - "csetjmp": "cpp", "csignal": "cpp", "cstdarg": "cpp", "cstddef": "cpp", @@ -25,21 +24,20 @@ "cstdlib": "cpp", "cstring": "cpp", "ctime": "cpp", - "cuchar": "cpp", "cwchar": "cpp", "cwctype": "cpp", "deque": "cpp", "forward_list": "cpp", "list": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", "unordered_map": "cpp", - "unordered_set": "cpp", + "vector": "cpp", "exception": "cpp", "algorithm": "cpp", - "any": "cpp", - "filesystem": "cpp", "functional": "cpp", "iterator": "cpp", - "map": "cpp", "memory": "cpp", "memory_resource": "cpp", "numeric": "cpp", @@ -47,15 +45,11 @@ "random": "cpp", "ratio": "cpp", "regex": "cpp", - "set": "cpp", - "string": "cpp", "string_view": "cpp", "system_error": "cpp", "tuple": "cpp", "type_traits": "cpp", "utility": "cpp", - "rope": "cpp", - "slist": "cpp", "fstream": "cpp", "future": "cpp", "initializer_list": "cpp", @@ -66,41 +60,22 @@ "limits": "cpp", "mutex": "cpp", "new": "cpp", + "numbers": "cpp", "ostream": "cpp", - "scoped_allocator": "cpp", + "semaphore": "cpp", "shared_mutex": "cpp", + "span": "cpp", "sstream": "cpp", "stdexcept": "cpp", + "stop_token": "cpp", "streambuf": "cpp", "thread": "cpp", + "cfenv": "cpp", + "cinttypes": "cpp", "typeindex": "cpp", "typeinfo": "cpp", - "barrier": "cpp", - "bit": "cpp", - "charconv": "cpp", - "compare": "cpp", - "concepts": "cpp", - "coroutine": "cpp", - "source_location": "cpp", - "latch": "cpp", - "numbers": "cpp", - "ranges": "cpp", - "semaphore": "cpp", - "span": "cpp", - "stop_token": "cpp", - "syncstream": "cpp", + "valarray": "cpp", "variant": "cpp", - "__nullptr": "cpp", - "__config": "cpp", - "__functional_base": "cpp", - "__functional_base_03": "cpp", - "__hash_table": "cpp", - "__tree": "cpp", - "__tuple": "cpp", - "hash_map": "cpp", - "__bit_reference": "cpp", - "*.ipp": "cpp", - "__functional_03": "cpp", - "__node_handle": "cpp" + "__nullptr": "cpp" } } \ No newline at end of file diff --git a/dep/iflytopcpp b/dep/iflytopcpp index 2d2ac28..574b15a 160000 --- a/dep/iflytopcpp +++ b/dep/iflytopcpp @@ -1 +1 @@ -Subproject commit 2d2ac28f73d5a14aba4501831c1c52468b726a10 +Subproject commit 574b15ad972bcaae593cfc434f9f60e6d6a13ca8 diff --git a/sh/envsetup.sh b/sh/envsetup.sh index 21aa547..efe117b 100755 --- a/sh/envsetup.sh +++ b/sh/envsetup.sh @@ -25,7 +25,7 @@ else #如果定义了 COMPILE_TOOLS_DOWN_URL # 下载编译工具 cd ${PROJECT_PATH}/build - # wget -p ${COMPILE_TOOLS_DOWN_URL} + wget -c ${COMPILE_TOOLS_DOWN_URL} # 解压编译工具 cd ${PROJECT_PATH}/build diff --git a/src/service/device_io_service.cpp b/src/service/device_io_service.cpp index 0156eae..f414c89 100644 --- a/src/service/device_io_service.cpp +++ b/src/service/device_io_service.cpp @@ -1,4 +1,281 @@ #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(uint16_t off, bool value) { + /** + * @brief + * 0(16Byte) | 继电器0 ->继电器15 掩码 + * 1(16Byte) | 继电器16->继电器31 掩码 + * 2(16Byte) | 继电器0 ->继电器15 继电器状态 + * 3(16Byte) | 继电器16->继电器31 继电器状态 + */ + 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)); +} +bool DeviceIOService::relayStateGet(uint16_t off) { + /** + * @brief + * 0(16Byte) | 继电器0 ->继电器15 掩码 + * 1(16Byte) | 继电器16->继电器31 掩码 + * 2(16Byte) | 继电器0 ->继电器15 继电器状态 + * 3(16Byte) | 继电器16->继电器31 继电器状态 + */ + 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); + return (regstate & (1 << off)) != 0; +} + +uint16_t DeviceIOService::getReg(int index) { + Modbus03Rx modbus03rx; + EXEC_MODBUS(modbusMaster->modbus03(ksubboarddeviceid, index, 1, modbus03rx, kovertime)); + return modbus03rx.getReg(index); +} + +/*********************************************************************************************************************** + * ==================================================路由器电源控制=================================================== * + ***********************************************************************************************************************/ +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); +} + +uint32_t DeviceIOService::getinputState() { + 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); + return regstate; +} + +void DeviceIOService::inputStateMonitorLoop() { + ThisThread thisThread; + while (!thisThread.getExitFlag()) { + uint32_t regstate = 0; + try { + regstate = getinputState(); + 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; +} +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; +} diff --git a/src/service/device_io_service.hpp b/src/service/device_io_service.hpp index 5361c17..ff45eb7 100644 --- a/src/service/device_io_service.hpp +++ b/src/service/device_io_service.hpp @@ -17,8 +17,10 @@ #include "iflytopcpp/core/spdlogfactory/logger.hpp" // #include "configs/config.hpp" +#include "iflytopcpp/core/basic/nod/nod.hpp" +#include "iflytopcpp/core/components/modbus/modbus.hpp" +#include "iflytopcpp/core/thread/thread.hpp" #include "zservice_container/zservice_container.hpp" - /** * @brief * @@ -29,17 +31,142 @@ * 依赖服务: * 作用: * + * 编写参考:http://192.168.1.3:3000/project_intelligent_light_pole/subboard */ namespace iflytop { using namespace std; using namespace core; +using namespace nod; class DeviceIOService : public enable_shared_from_this { ENABLE_LOGGER(DeviceIOService); + shared_ptr modbusMaster; + uint32_t keystate; + + unique_ptr thread; + unique_ptr idcard_read_thread; + + public: + // + /** + * @brief + * 0(16Byte) | 继电器0 ->继电器15 掩码 + * 1(16Byte) | 继电器16->继电器31 掩码 + * 2(16Byte) | 继电器0 ->继电器15 继电器状态 + * 3(16Byte) | 继电器16->继电器31 继电器状态 + */ + void relayControl(uint16_t off, bool value); + bool relayStateGet(uint16_t off); + uint16_t getReg(int index); + + public: + typedef enum { + kEmergency, // 紧急按钮 + kWaterImmersionSensor, // 水浸传感器 + kHumanProximitySensor, // 人体接近传感器 + } input_device_type_t; + + string input_device_type2str(input_device_type_t type) { + switch (type) { + case kEmergency: + return "kEmergency"; + case kWaterImmersionSensor: + return "kWaterImmersionSensor"; + case kHumanProximitySensor: + return "kHumanProximitySensor"; + default: + return "unknow"; + } + } + public: DeviceIOService(){}; + void initialize(); + /********************************************************************************************************************* + * =====================================================路由器====================================================== * + *********************************************************************************************************************/ + bool routerGetPowerState(); + void routerSetPowerState(bool routepower); + /********************************************************************************************************************* + * ===================================================触控屏供电==================================================== * + *********************************************************************************************************************/ + bool touchScreenGetPowerState(); + void touchScreenSetPowerState(bool screenpower); + /********************************************************************************************************************* + * ==================================================USB充电器供电================================================== * + *********************************************************************************************************************/ + bool usbChargerGetPowerState(); + void usbChargerSetPowerState(bool usbpower); + /********************************************************************************************************************* + * ===================================================摄像头供电==================================================== * + *********************************************************************************************************************/ + bool cameraGetPowerState(); + void cameraSetPowerState(bool camerapower); + /********************************************************************************************************************* + * ===================================================照明灯控制==================================================== * + *********************************************************************************************************************/ + bool lightGetPowerState(); + void lightSetPowerState(bool lightpower); + + /********************************************************************************************************************* + * =================================================监听IO输入状态================================================== * + *********************************************************************************************************************/ + nod::signal onInputStateChange; + uint32_t getinputState(); + + /********************************************************************************************************************* + * ===================================================温度传感器==================================================== * + *********************************************************************************************************************/ + uint32_t getInterTemperature(); + + /********************************************************************************************************************* + * ===================================================环境传感器==================================================== * + *********************************************************************************************************************/ + /** + 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 + */ + + typedef struct { + uint16_t wind_speed; + uint16_t wind_direction; + uint16_t temperature; + uint16_t humidity; + uint16_t noise; + uint16_t pm2_5; + uint16_t pm10; + uint16_t co2; + uint16_t atmospheric_pressure; + uint16_t tvoc; + uint16_t hcho; + } env_sensor_state_t; + + env_sensor_state_t getEnvSensorState(); + + /********************************************************************************************************************* + * ==================================================散热风扇控制=================================================== * + *********************************************************************************************************************/ + void fanGetState(int id, float& power, uint16_t& error); + void fanSetState(int id, float power); + + /********************************************************************************************************************* + * ====================================================刷卡控制===================================================== * + *********************************************************************************************************************/ + + nod::signal onidcard; + void idcardread(bool& state, string& info); - void initialize(){}; + private: + void inputStateMonitorLoop(); }; } // namespace iflytop \ No newline at end of file