diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 2e3483a3..c4e2ad8a 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -385,6 +385,7 @@ add_library( # Sets the name of the library. GPIOControl.cpp MicroPhoto.cpp PhoneDevice.cpp + PtzController.cpp # PhoneDevice2.cpp Camera.cpp Camera2Reader.cpp diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp index a8775892..b324f660 100644 --- a/app/src/main/cpp/PhoneDevice.cpp +++ b/app/src/main/cpp/PhoneDevice.cpp @@ -565,6 +565,9 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service, const std::string& appPa GpioControl::setCam3V3Enable(true); GpioControl::setSpiPower(true); #endif + + m_ptzController = new PtzController(this); + m_ptzController->Startup(); } CPhoneDevice::~CPhoneDevice() @@ -2247,6 +2250,8 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector< } else if (mPhotoInfo.mediaType == 0 && (mPhotoInfo.cameraType == CAM_TYPE_PLZ)) { + m_ptzController->AddPhotoCommand(mPhotoInfo, mPath, mOsds); +#if 0 uint64_t wid_serial = RequestWakelock(0); CPhoneDevice* pThis = this; IDevice::PHOTO_INFO localPhotoInfo = mPhotoInfo; @@ -2281,6 +2286,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector< }); t.detach(); +#endif } else if ((mPhotoInfo.mediaType == XY_MEDIA_TYPE_STREAM || mPhotoInfo.mediaType == XY_MEDIA_TYPE_STREAM_OFF) && (mPhotoInfo.cameraType == CAM_TYPE_NET || mPhotoInfo.cameraType == CAM_TYPE_PLZ)) { @@ -4347,6 +4353,9 @@ void CPhoneDevice::ConvertDngToPng(const std::string& dngPath, const std::string void CPhoneDevice::CameraCtrl(unsigned short waitTime, unsigned short delayTime, unsigned char channel, int cmdidx, unsigned char preset, const char *serfile, unsigned int baud, int addr) { + + m_ptzController->AddCommand(channel, cmdidx, 0, preset, serfile, baud, addr); +#if 0 if(GpioControl::GetSelftestStatus(waitTime) && GpioControl::GetCamerastatus()) { CPhoneDevice *pThis = this; string serfileStr(serfile); @@ -4363,6 +4372,7 @@ void CPhoneDevice::CameraCtrl(unsigned short waitTime, unsigned short delayTime, }); ctrlThread.detach(); } +#endif } int CPhoneDevice::GetSerialPhoto(int devno, D_IMAGE_DEF *photo) diff --git a/app/src/main/cpp/PhoneDevice.h b/app/src/main/cpp/PhoneDevice.h index fd6206e6..b00ee3dd 100644 --- a/app/src/main/cpp/PhoneDevice.h +++ b/app/src/main/cpp/PhoneDevice.h @@ -31,6 +31,8 @@ #include #include "SensorsProtocol.h" +#include "PtzController.h" + #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "error", __VA_ARGS__)) #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "debug", __VA_ARGS__)) @@ -168,6 +170,8 @@ class CPhoneDevice : public IDevice { public: + friend PtzController; + struct NETWORK { std::string iface; @@ -437,6 +441,8 @@ protected: std::map m_streamings; + PtzController* m_ptzController; + }; diff --git a/app/src/main/cpp/PtzController.cpp b/app/src/main/cpp/PtzController.cpp new file mode 100644 index 00000000..a284f064 --- /dev/null +++ b/app/src/main/cpp/PtzController.cpp @@ -0,0 +1,234 @@ +// +// Created by Matthew on 2025/3/5. +// + +#include "PtzController.h" +#include "SensorsProtocol.h" +#include "GPIOControl.h" +#include "PhoneDevice.h" +#include + +PtzController::PtzController(CPhoneDevice* pPhoneDevice) : m_pPhoneDevice(pPhoneDevice) +{ + m_exit = false; +} + +void PtzController::Startup() +{ + m_thread = std::thread(PtzThreadProc, this); +} + +void PtzController::PtzThreadProc(PtzController* pThis) +{ + pThis->PtzProc(); +} + +void PtzController::AddCommand(uint8_t channel, int cmdidx, uint8_t bImageSize, uint8_t preset, const char *serfile, uint32_t baud, int addr) +{ + SERIAL_CMD cmd = { 0 }; + cmd.channel = channel; + cmd.channel = preset; + cmd.cmdidx = cmdidx; + cmd.bImageSize = bImageSize; + strcpy(cmd.serfile, serfile); + cmd.baud = baud; + cmd.addr = addr; + + m_locker.lock(); + m_cmds.push_back(cmd); + m_locker.unlock(); + + m_sem.release(); +} + +void PtzController::AddPhotoCommand(IDevice::PHOTO_INFO& photoInfo, const std::string& path, const std::vector& osds) +{ + IDevice::SerialsPhotoParam param = { "", 0, 0 }; + m_pPhoneDevice->GetPhotoSerialsParamCb(param); + + SERIAL_CMD cmdPreset = { 0 }; + time_t ts = time(NULL); + // if (photoInfo.preset != 0 && photoInfo.preset != 0xFF) + { + cmdPreset.ts = photoInfo.selfTestingTime; + cmdPreset.delayTime = photoInfo.closeDelayTime; + cmdPreset.channel = photoInfo.channel; + cmdPreset.channel = photoInfo.preset; + cmdPreset.cmdidx = OPEN_TOTAL; + strcpy(cmdPreset.serfile, param.serfile); + cmdPreset.baud = param.baud; + cmdPreset.addr = param.addr; + } + SERIAL_CMD cmd = { 0 }; + cmd.ts = ts; + cmd.delayTime = photoInfo.closeDelayTime; + cmd.channel = photoInfo.channel; + cmd.preset = photoInfo.preset; + cmd.cmdidx = Take_Photo; + cmd.bImageSize = photoInfo.resolution; + + strcpy(cmd.serfile, param.serfile); + cmd.baud = param.baud; + cmd.addr = param.addr; + + PtzPhotoParams* ppp = new PtzPhotoParams(photoInfo, path, osds); + cmd.photoParams.reset(ppp); + // cmd.delayTime; + // uint8_t bImageSize; + // char serfile[128]; + // uint32_t baud; + // int addr; + m_locker.lock(); + if (cmdPreset.cmdidx != 0) + { + m_cmds.push_back(cmdPreset); + } + m_cmds.push_back(cmd); + m_locker.unlock(); + + m_sem.release(); + m_sem.release(); +} + +void PtzController::ExitAndWait() +{ + m_exit = true; + m_sem.release(); + + if (m_thread.joinable()) + { + m_thread.join(); + } +} + +void PtzController::PtzProc() +{ + PTZ_STATE state = PTZS_POWER_OFF; + SERIAL_CMD cmd; + bool hasCmd = false; + + std::shared_ptr powerCtrl; + time_t selfTestingStartTime = 0; + time_t selfTestingWaitTime = 0; + + while(true) + { + m_sem.acquire(); + + if (m_exit) + { + break; + } + + hasCmd = false; + + m_locker.lock(); + for (auto it = m_cmds.begin(); it != m_cmds.end(); ++it) + { + if (state == PTZS_SELF_TESTING) + { + // find first non-taking-photo cmd + if (it->cmdidx != Take_Photo) + { + cmd = *it; + m_cmds.erase(it); + hasCmd = true; + break; + } + } + else + { + cmd = *it; + m_cmds.erase(it); + hasCmd = true; + break; + } + } + m_locker.unlock(); + + if (!hasCmd) + { + if (state == PTZS_SELF_TESTING) + { + time_t timeout = time(NULL) - selfTestingStartTime; + if (timeout >= selfTestingWaitTime) + { + state = PTZS_IDLE; + m_sem.release(); + continue; + } + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + m_sem.release(); + continue; + } + + powerCtrl.reset(); + continue; + } + + switch (cmd.cmdidx) + { + case Take_Photo: + { + if (state == PTZS_POWER_OFF) + { + if (!powerCtrl) + { + powerCtrl = std::make_shared(cmd.photoParams->mPhotoInfo.closeDelayTime); + selfTestingStartTime = time(NULL); + selfTestingWaitTime = cmd.photoParams->mPhotoInfo.selfTestingTime; + state = PTZS_SELF_TESTING; + + m_locker.lock(); + m_cmds.insert(m_cmds.begin(), cmd); + m_locker.unlock(); + m_sem.release(); + continue; + } + } + + state = PTZS_TAKING_PHOTO; + if (cmd.preset != 0 && cmd.preset != 0xFF) + { + CameraPhotoCmd(0, cmd.channel, MOVE_PRESETNO, 0, cmd.preset, cmd.serfile, cmd.baud, cmd.addr); + std::this_thread::sleep_for(std::chrono::milliseconds(10 * 1000)); + } + m_pPhoneDevice->TakePhotoWithNetCamera(cmd.photoParams->mPhotoInfo, cmd.photoParams->mPath, cmd.photoParams->mOsds, powerCtrl); + state = PTZS_IDLE; + } + + break; + case OPEN_TOTAL: + if (state == PTZS_POWER_OFF) + { + if (!powerCtrl) + { + powerCtrl = std::make_shared(cmd.delayTime); + selfTestingStartTime = time(NULL); + selfTestingWaitTime = cmd.ts; + state = PTZS_SELF_TESTING; + } + } + break; + case CLOSE_TOTAL: + if (state == PTZS_POWER_OFF) + { + // Do Nothing + } + else + { + powerCtrl.reset(); + state = PTZS_POWER_OFF; + } + break; + default: + { + CameraPhotoCmd(cmd.ts, cmd.channel, cmd.cmdidx, 0, cmd.preset, cmd.serfile, cmd.baud, cmd.addr); + + } + break; + } + } + + +} \ No newline at end of file diff --git a/app/src/main/cpp/PtzController.h b/app/src/main/cpp/PtzController.h new file mode 100644 index 00000000..b19541f1 --- /dev/null +++ b/app/src/main/cpp/PtzController.h @@ -0,0 +1,93 @@ +// +// Created by Matthew on 2025/3/5. +// + +#ifndef MICROPHOTO_PTZCONTROLLER_H +#define MICROPHOTO_PTZCONTROLLER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +enum PTZ_STATE +{ + PTZS_POWER_OFF = 0, + PTZS_IDLE = 1, + PTZS_SELF_TESTING = 2, + PTZS_MOVING = 3, + PTZS_TAKING_PHOTO = 4, +}; + +class PtzPhotoParams +{ +public: + PtzPhotoParams(const IDevice::PHOTO_INFO& photoInfo, const std::string& path, const std::vector& osds) : + mPhotoInfo(photoInfo), mPath(path), mOsds(osds) + { + } + + ~PtzPhotoParams() + { + } + + IDevice::PHOTO_INFO mPhotoInfo; + std::string mPath; + std::vector mOsds; +}; + +struct SERIAL_CMD +{ + uint8_t channel; + uint8_t preset; + time_t ts; + int cmdidx; + uint32_t delayTime; + uint8_t bImageSize; + char serfile[128]; + uint32_t baud; + int addr; + std::shared_ptr photoParams; +}; + + +class CPhoneDevice; +class PtzController +{ +public: + PtzController(CPhoneDevice* pPhoneDevice); + + void Startup(); + // (); + void AddCommand(uint8_t channel, int cmdidx, uint8_t bImageSize, uint8_t preset, const char *serfile, uint32_t baud, int addr); + void AddPhotoCommand(IDevice::PHOTO_INFO& photoInfo, const std::string& path, const std::vector& osds); + + void ExitAndWait(); + +protected: + static void PtzThreadProc(PtzController* pThis); + + void PtzProc(); + + +protected: + + +protected: + std::mutex m_locker; + std::vector m_cmds; + + CSemaphore m_sem; + bool m_exit; + + std::thread m_thread; + + CPhoneDevice* m_pPhoneDevice; +}; + + +#endif //MICROPHOTO_PTZCONTROLLER_H diff --git a/app/src/main/cpp/SensorsProtocol.h b/app/src/main/cpp/SensorsProtocol.h index 42e388fa..2924209c 100644 --- a/app/src/main/cpp/SensorsProtocol.h +++ b/app/src/main/cpp/SensorsProtocol.h @@ -126,6 +126,8 @@ #define OPEN_MODULE_POWER 10020 /* 打开机芯电源(1 有效)*/ #define NOTIFY_PTZ_CLOSE 10021 // 通知云台关闭 #define QUERY_PTZ_STATE 10022 // 查询云台状态 +#define CLOSE_TOTAL 10040 /* 关闭总电源*/ + #define SPEED_DOME_CAMERA 0 /* 球机摄像机*/ #define SERIAL_CAMERA 2 /* 串口摄像机a*/