// // Created by Matthew on 2023/12/27. // #include #include #include #include #include #include #include #include #include #include "GPIOControl.h" #include #ifdef _DEBUG #include #endif #define IOT_PARAM_WRITE 0xAE #define IOT_PARAM_READ 0xAF std::mutex GpioControl::m_locker; CSemaphore GpioControl::m_semaphore; std::vector GpioControl::m_items; std::thread GpioControl::m_thread; bool GpioControl::m_exitSignal = false; bool GpioControl::m_cameraPowerStatus = false; size_t GpioControl::turnOnImpl(const IOT_PARAM& param) { size_t oldRef = 0; size_t references = 1; std::vector::iterator it; int res = 0; int fd = -1; time_t now = time(NULL); // check res??? for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == param.cmd) { oldRef = it->references; it->references++; // it->closeTime = 0; references = it->references; if(it->openTime == 0) it->openTime = now; SetCamerastatus(it->cmd, true); break; } } if (it == m_items.end()) { oldRef = 0; ITEM item = {param.cmd, references, 0, 0, now}; m_items.push_back(item); SetCamerastatus(param.cmd, true); } if (oldRef == 0) { fd = open(GPIO_NODE_MP, O_RDONLY); if( fd > 0 ) { res = ioctl(fd, IOT_PARAM_WRITE, ¶m); close(fd); #ifdef OUTPUT_DBG_INFO XYLOG(XYLOG_SEVERITY_INFO, "setInt cmd=%d,value=%d,result=%d",param.cmd, param.value, param.result); #endif } #ifdef _DEBUG ALOGI("PWR TurnOn cmd=%d,result=%d ref=%u\r\n",param.cmd, param.result, (uint32_t)references); #endif std::this_thread::sleep_for(std::chrono::milliseconds(100)); } return references; } void GpioControl::setInt(int cmd, int value) { IOT_PARAM param = { cmd, value, 0 }; // param.cmd = cmd; // param.value = value; int fd = open(GPIO_NODE_MP, O_RDONLY); if (fd > 0) { int res = ioctl(fd, IOT_PARAM_WRITE, ¶m); close(fd); #ifdef OUTPUT_DBG_INFO int realVal = getInt(param.cmd); XYLOG(XYLOG_SEVERITY_INFO, "setInt cmd=%d,value=%d,result=%d RealVal=%d",param.cmd, param.value, param.result, realVal); #endif } } int GpioControl::getInt(int cmd) { int fd = open(GPIO_NODE_MP, O_RDONLY); // LOGE("get_int fd=%d,cmd=%d\r\n",fd, cmd); if( fd > 0 ) { IOT_PARAM param; param.cmd = cmd; ioctl(fd, IOT_PARAM_READ, ¶m); #ifdef _DEBUG ALOGI("getInt cmd=%d,value=%d,result=%d",param.cmd, param.value, param.result); #endif close(fd); return param.value; } return -1; } void GpioControl::setLong(int cmd, long value) { int fd = open(GPIO_NODE_MP, O_RDONLY); IOT_PARAM param; param.cmd = cmd; param.value2 = value; // LOGE("set_long fd=%d,cmd=%d,value2=%ld\r\n",fd, param.cmd, param.value2); if( fd > 0 ) { ioctl(fd, IOT_PARAM_WRITE, ¶m); // LOGE("set_long22 cmd=%d,value2=%ld,result=%d\r\n",param.cmd, param.value2, param.result); close(fd); } } long GpioControl::getLong(int cmd) { int fd = open(GPIO_NODE_MP, O_RDONLY); // LOGE("get_long fd=%d,cmd=%d\r\n",fd, cmd); if( fd > 0 ) { IOT_PARAM param; param.cmd = cmd; ioctl(fd, IOT_PARAM_READ, ¶m); // LOGE("get_long22 cmd=%d,value2=%ld,result=%d\r\n",param.cmd, param.value2, param.result); close(fd); return param.value2; } return -1; } void GpioControl::setString(int cmd, const std::string& value) { IOT_PARAM param; int fd = open(GPIO_NODE_MP, O_RDONLY); int len = MAX_STRING_LEN < value.size() ? MAX_STRING_LEN : value.size(); param.cmd = cmd; memset(param.str, 0, MAX_STRING_LEN); memcpy(param.str, value.c_str(), len); // LOGE("set_string fd=%d,cmd=%d,str=%s\r\n",fd, param.cmd, param.str); if( fd > 0 ) { ioctl(fd, IOT_PARAM_WRITE, ¶m); // LOGE("set_string22 cmd=%d,str=%s,result=%d\r\n",param.cmd, param.str, param.result); close(fd); } return; } std::string GpioControl::getString(int cmd) { int fd = open(GPIO_NODE_MP, O_RDONLY); // LOGE("get_string fd=%d,cmd=%d\r\n",fd, cmd); if( fd > 0 ) { IOT_PARAM param; param.cmd = cmd; ioctl(fd, IOT_PARAM_READ, ¶m); // LOGE("get_string22 cmd=%d,str=%s,result=%d\r\n",param.cmd, param.str, param.result); close(fd); return std::string(param.str); } return ""; } /////////////////////////// Power Control ///////////////////////////////// size_t GpioControl::TurnOn(int cmd) { IOT_PARAM param = { cmd, 1, 0 }; // param.cmd = cmd; // param.value = value; m_locker.lock(); size_t ref = turnOnImpl(param); m_locker.unlock(); return ref; } size_t GpioControl::TurnOn(const std::vector& cmds) { IOT_PARAM param = { 0, 1, 0 }; // param.cmd = cmd; // param.value = value; std::vector::const_iterator it; m_locker.lock(); for (it = cmds.cbegin(); it != cmds.cend(); ++it) { if (*it == 0) { continue; } param.cmd = *it; turnOnImpl(param); } m_locker.unlock(); return 0; } size_t GpioControl::TurnOffImmediately(int cmd) { time_t ts = time(NULL); size_t ref = 0; std::vector::iterator it; m_locker.lock(); for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == cmd) { ref = it->references; it->closeCmds++; it->closeTime = ts; break; } } m_locker.unlock(); m_semaphore.release(); #ifdef _DEBUG ALOGI("PWR TurnOffNow cmd=%d ref=%u", cmd, (uint32_t)ref); #endif return 0; } size_t GpioControl::TurnOff(int cmd, uint32_t delayedCloseTime/* = 0*/) { time_t ts = 0; if (delayedCloseTime > 0) { ts = time(NULL) + delayedCloseTime; } size_t ref = 0; std::vector::iterator it; m_locker.lock(); for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == cmd) { ref = it->references; it->closeCmds++; if (ts > it->closeTime) { it->closeTime = ts; } break; } } m_locker.unlock(); m_semaphore.release(); #ifdef _DEBUG ALOGI("PWR TurnOff cmd=%d ref=%u", cmd, (uint32_t)ref); #endif return 0; } size_t GpioControl::TurnOff(const std::vector& cmds, uint32_t delayedCloseTime/* = 0*/) { time_t ts = 0; if (delayedCloseTime > 0) { ts = time(NULL) + delayedCloseTime; } std::vector::iterator it; std::vector::const_reverse_iterator itCmd; m_locker.lock(); // turnOnImpl(param); for (itCmd = cmds.crbegin(); itCmd != cmds.crend(); ++itCmd) { for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == *itCmd) { it->closeCmds++; if (ts > it->closeTime) { it->closeTime = ts; } break; } } } m_locker.unlock(); m_semaphore.release(); return 0; } size_t GpioControl::TurnOff(const std::vector >& cmds) { time_t ts = time(NULL); time_t ts2; std::vector::iterator it; std::vector >::const_iterator itCmd; m_locker.lock(); for (itCmd = cmds.cbegin(); itCmd != cmds.end(); ++itCmd) { for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == itCmd->first) { it->closeCmds++; if (itCmd->second != 0) { ts2 = itCmd->second + ts; if (ts2 > it->closeTime) { it->closeTime = ts2; } } break; } } } m_locker.unlock(); m_semaphore.release(); return 0; } bool GpioControl::SetCamerastatus(int cmd, bool status) { #ifdef USING_N938 if(cmd == CMD_SET_PIC1_POWER) m_cameraPowerStatus = status; #endif #ifdef USING_PLZ if(cmd == CMD_SET_PTZ_PWR_ENABLE) { m_cameraPowerStatus = status; } #endif return true; } bool GpioControl::GetCamerastatus() { return m_cameraPowerStatus; } bool GpioControl::GetSelftestStatus(time_t wait_time) { int cmd = 0; #ifdef USING_N938 cmd = CMD_SET_PIC1_POWER; #endif #ifdef USING_PLZ cmd = CMD_SET_PTZ_PWR_ENABLE; #endif time_t now = time(NULL); std::vector::iterator it; for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == cmd && it->openTime!=0 && (now - it->openTime >= wait_time)) { return true;//自检完成 } } return false; } time_t GpioControl::GetSelfTestRemain(time_t wait_time) { int cmd = 0; #ifdef USING_N938 cmd = CMD_SET_PIC1_POWER; #endif #ifdef USING_PLZ cmd = CMD_SET_PTZ_PWR_ENABLE; #endif time_t now = time(NULL); std::vector::iterator it; for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->cmd == cmd && it->openTime!=0 && (now - it->openTime <= wait_time)) { time_t remaintime =wait_time - (now - it->openTime); return remaintime;//自检完成 } } return 0; } void GpioControl::PowerControlThreadProc() { time_t ts = 0; std::vector::iterator it; std::vector items; time_t minDelayTime = 0; time_t delayTime = 0; int fd = -1; int res = -1; m_cameraPowerStatus = 0; while(1) { // Check if there is close cmd ts = time(NULL); minDelayTime = std::numeric_limits::max(); m_locker.lock(); for (it = m_items.begin(); it != m_items.end(); ++it) { if (it->references == 0 && it->closeCmds == 0 && it->closeTime == 0) { #ifdef _DEBUG ALOGI("PWR THREAD cmd=%d ref=%u closeCmds=%u", it->cmd, (uint32_t)it->references, (uint32_t)it->closeCmds); #endif continue; } if (it->closeCmds > 0) { if (it->references <= it->closeCmds) { it->references = 0; } else { it->references -= it->closeCmds; if(it->references < 0) it->references = 0; } it->closeCmds = 0; } if (it->references == 0) { // Should turn off the power if ((it->closeTime == 0) || (it->closeTime <= ts)) { // close it directly setInt(it->cmd, 0); it->closeTime = 0; it->openTime = 0; #ifdef _DEBUG ALOGI("PWR THREAD DO TurnOff cmd=%d", it->cmd); #endif SetCamerastatus(it->cmd, false); } else { // Check Time delayTime = ts - it->closeTime; if (delayTime < minDelayTime) { minDelayTime = delayTime; } } } #ifdef _DEBUG ALOGI("PWR THREAD cmd=%d ref=%u closeCmds=%u", it->cmd, (uint32_t)it->references, (uint32_t)it->closeCmds); #endif } m_locker.unlock(); if (minDelayTime < std::numeric_limits::max()) { m_semaphore.try_acquire_for(std::chrono::seconds(1)); } else { m_semaphore.acquire(); } if (m_exitSignal) { break; } } } bool GpioControl::Startup() { // if (m_thread.) m_exitSignal = false; m_thread = std::thread(PowerControlThreadProc); #ifdef _DEBUG pthread_t nativeHandle = m_thread.native_handle(); pthread_setname_np(nativeHandle, "gpioclose"); #endif return true; } void GpioControl::Stop() { // Notify m_exitSignal = true; m_semaphore.release(); m_thread.detach(); }