Quellcode durchsuchen

优化海康相机的拍照逻辑, 改用线程回调拍摄照片, 避免卡死在海康SDK拍照函数(SDK问题, 极少出现)的调用上, 从而导致RTU一直处于拍照中的工作状态, 无法掉电

niujiuru vor 1 Monat
Ursprung
Commit
5ff76e2f93

+ 1 - 1
Makefile

@@ -7,7 +7,7 @@ DEFINS = -D_GNU_SOURCE
 
 GO := go
 GO_BUILD := $(GO) build
-GO_FLAGS := -ldflags "-s -w -X hnyfkj.com.cn/rtu/bxs-sy/baseapp.Version=1.0.0.3 -X hnyfkj.com.cn/rtu/bxs-sy/baseapp.BuildTime=$(shell date +%Y-%m-%dT%H:%M:%S)"
+GO_FLAGS := -ldflags "-s -w -X hnyfkj.com.cn/rtu/bxs-sy/baseapp.Version=1.0.0.4 -X hnyfkj.com.cn/rtu/bxs-sy/baseapp.BuildTime=$(shell date +%Y-%m-%dT%H:%M:%S)"
 
 target ?= x86_64
 ifeq ($(target),armv7hf)

+ 1 - 1
docs/便携色板监测设备与平台端交互协议.md

@@ -287,7 +287,7 @@ e) "Device Unique Identifier", 简称为"DUI", 相关的具体说明和编码规
 "rtu_bxs_seyou_1.0.0.1.tar.gz"升级包内容格式:
 
 - 升级程序文件: rtu_bxs_seyou.out
-- 升级版本文件: version.txt, 内容: 1.0.0.3, 格式: x.x.x.x
+- 升级版本文件: version.txt, 格式: x.x.x.x
 - 升级程序校检: rtu_bxs_seyou.md5, 内容: 5d41402abc4b2a76b9719d911017c592, 说明: 为防止改值被篡改, 可以
   简单的加入一层AES-128的加密安全处理, 密码固定到程序中, 密钥: "YFKJ@seyou123456", 长16字节。
 

+ 85 - 36
mvs_takephoto/takephoto.c

@@ -6,6 +6,52 @@ static const char MODULE_NAME[] = "TakePhoto";
 // 保存照片
 static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const char *imgFile);
 
+// 拍照回调
+typedef struct
+{
+  HANDLE      hCam;
+  EImgType    saveImgType;
+  const char *saveImgFilename;
+  HANDLE      hESig; // 任务结束的通知
+  int         rCode; // 任务结束返回值
+} PthotoProcCtx;
+
+static int PhotoProc(unsigned long wParam, unsigned long lParam) // 线程回调函数,执行一次拍照任务
+{
+  PthotoProcCtx *ctx = (PthotoProcCtx *)wParam; MV_FRAME_OUT frame = { 0 };
+
+  // 1, 触发一次拍照
+  int ret = MV_CC_SetCommandValue(ctx->hCam, "TriggerSoftware");
+
+  // 2, 等待获取图像
+  if(MV_OK == ret)
+  {
+    memset(&frame, 0, sizeof(MV_FRAME_OUT));
+    ret = MV_CC_GetImageBuffer(ctx->hCam, &frame, 1000);
+  }
+
+  // 3, 导出图像文件
+  if(MV_OK == ret)
+  {
+    sw_log_debug("[%s] +++GetOneFrame+++, Width[%d], Height[%d], FrameNum[%d], FrameLen[%d], PixelType[0x%08X]", MODULE_NAME, \
+                  frame.stFrameInfo.nWidth, frame.stFrameInfo.nHeight, frame.stFrameInfo.nFrameNum, frame.stFrameInfo.nFrameLen, \
+                  (unsigned int)frame.stFrameInfo.enPixelType);
+    ret = SavePhoto(ctx->hCam, &frame, ctx->saveImgType, ctx->saveImgFilename);
+    MV_CC_FreeImageBuffer(ctx->hCam, &frame);
+  }
+
+  // 4, 控制线程退出
+  switch(ret)
+  {
+  case MV_E_NODATA: // 无数据时, 线程继续运行
+    ret = 1; break;
+  default: // 成功或发生其他错误,线程结束运行
+    ctx->rCode = ret; sw_signal_give(ctx->hESig); ret = -1; break;
+  }
+
+  return ret;
+}
+
 // 单次执行相机拍照, 并保存到文件, 成功返回: 0值, 失败返回:非0值
 // "imgType"         - 获取图像类型
 // "saveImgFilename" - 保存的文件名
@@ -17,9 +63,8 @@ static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const
 int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMark *pImgMark)
 {
   int fd; char runDir[MAX_PATH_CHARS] = { 0 }, lockFile[MAX_PATH_CHARS+32] = { 0 };
-  int ret, waitTimeTick/* 计时单位: 秒 */; SImgMark imgMark = { 0 }; HANDLE hCam = NULL;
-  MV_FRAME_OUT frame; MV_CC_DEVICE_INFO_LIST devList = { 0 }; MV_CC_DEVICE_INFO *pDevInfo;
-  unsigned long startTime, now; // 计算"waitTimeTick"时使用
+  int ret; SImgMark imgMark = { 0 }; HANDLE hCam = NULL; PthotoProcCtx ctx = { 0 };
+  MV_CC_DEVICE_INFO_LIST devList = { 0 }; MV_CC_DEVICE_INFO *pDevInfo = NULL;
 
   // 1, 占用锁定, 避免同时间拍照
   xGetSelfRunningInfo(runDir, NULL);
@@ -90,33 +135,38 @@ int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMa
     goto end_p;
   }
 
-  waitTimeTick = 0; xgettickcount(&startTime);
-  do
-  {
-    ret = MV_CC_SetCommandValue(hCam, "TriggerSoftware"); // 触发一次拍照
-    if(MV_OK == ret)
-    {
-      memset(&frame, 0, sizeof(MV_FRAME_OUT));
-      ret = MV_CC_GetImageBuffer(hCam, &frame, 1000);
-    }
-    else sw_thrd_delay(1000);
-    if(MV_OK == ret)
-    {
-      ret = SavePhoto(hCam, &frame, imgType, saveImgFilename);
-      MV_CC_FreeImageBuffer(hCam, &frame);
-    }
-    if(MV_OK == ret) break; // 拍照成功
-    else if(MV_E_NODATA == ret)
-    { // 无拍照数据时
-      xgettickcount(&now);  // 当前时间
-      waitTimeTick = ((now-startTime)/1000);
-    }
-    else
-    {
-      sw_log_error("[%s] 相机SDK取图异常, errCode=0x%x!!", MODULE_NAME, ret);
-      goto end_p;
-    }
-  } while(timeout < 0 ? true : (waitTimeTick < timeout));
+  ctx.hCam = hCam;
+  ctx.saveImgType = imgType;
+  ctx.saveImgFilename = saveImgFilename;
+  ctx.hESig = sw_signal_create();
+  if(!ctx.hESig)
+  {
+    ret = -5;
+    sw_log_error("[%s] SIG信号量创建失败!!", MODULE_NAME);
+    goto end_p;
+  }
+  ctx.rCode = MV_OK;
+
+  HANDLE hThrd = sw_thrd_create("PhotoProc", THREAD_DEFAULT_PRIORITY, THREAD_DEFAULT_STACK_SIZE, PhotoProc, (unsigned long)&ctx, 0);
+  if(!hThrd)
+  {
+    ret = -6;
+    sw_signal_destroy(ctx.hESig);
+    sw_log_error("[%s] 拍照线程-创建失败!!", MODULE_NAME);
+    goto end_p;
+  }
+  sw_thrd_resume(hThrd);
+
+  ret = sw_signal_wait(ctx.hESig, timeout*1000); // 阻塞等待拍照任务结束或超时
+  if(0 == ret) ret = ctx.rCode;
+  else
+  {
+    ret = -7;
+    sw_log_error("[%s] 拍照过程-等待超时!!", MODULE_NAME);
+  }
+
+  sw_thrd_destroy(hThrd, WAITTHRD_SAFEEXIT_TIMEOUT);
+  sw_signal_destroy(ctx.hESig);
 
   // 5, 成功拍照, 输出相机的信息
   if(MV_OK == ret)
@@ -126,7 +176,6 @@ int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMa
     imgMark.imgExposureTime = fv.fCurValue;
     if(pImgMark) memcpy(pImgMark, &imgMark, sizeof(SImgMark));
   }
-  else if(timeout >= 0 && waitTimeTick >= timeout) ret = -5; // 拍照超时
 
   // 6, 任务结束, 释放相关的资源
 end_p:
@@ -151,7 +200,7 @@ static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const
   MV_SAVE_IMAGE_PARAM_EX3 saveParams = { 0 }; MVCC_INTVALUE_EX iv;
   char *filename1 = (char *)imgFile, *filename2 = NULL; int ret; char ext[5];
 
-  if(!hCam || !pFrame || !filename1 || strlen(filename1) <= 0) return -6;
+  if(!hCam || !pFrame || !filename1 || strlen(filename1) <= 0) return -8;
 
   switch(imgType)
   {
@@ -163,7 +212,7 @@ static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const
     imgType = MV_Image_Jpeg;
     strcpy(ext, ".jpg");
     break;
-   default: return -7;
+   default: return -9;
   }
 
   ret = MV_CC_GetIntValueEx(hCam, "PayloadSize", &iv);
@@ -182,7 +231,7 @@ static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const
   if(imgType == IMG_TYPE_JPG) saveParams.nBufferSize  = (unsigned int)(iv.nCurValue * 1);
   else saveParams.nBufferSize  = (unsigned int)(iv.nCurValue * 4);
   saveParams.pImageBuffer = (unsigned char *)sw_heap_malloc(saveParams.nBufferSize);
-  if(!saveParams.pImageBuffer) return -8;
+  if(!saveParams.pImageBuffer) return -10;
 
   ret = MV_CC_SaveImageEx3(hCam, &saveParams);
   if(MV_OK != ret) goto end_p;
@@ -191,7 +240,7 @@ static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const
   {
     filename2 = (char *)sw_heap_malloc(strlen(filename1) +sizeof(ext));
     if(filename2) sprintf(filename2, "%s%s", filename1, ext);
-    else { ret = -9; goto end_p; }
+    else { ret = -11; goto end_p; }
     ret = sw_file_update(filename2, "wb", (const char *)saveParams.pImageBuffer, saveParams.nImageLen);
     sw_heap_free(filename2);
   }
@@ -201,7 +250,7 @@ static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const
   }
 
   if(ret == saveParams.nImageLen) ret = MV_OK;
-  else ret = -10;
+  else ret = -12;
 
 end_p:
   sw_heap_free(saveParams.pImageBuffer);

+ 1 - 1
package/armv7hf.sh

@@ -4,7 +4,7 @@
 set -e
 set -o pipefail
 
-ver_num="1.0.0.3"
+ver_num="1.0.0.4"
 cur_dir="$(pwd)"
 pre_dir="$(dirname "$cur_dir")"
 pkg_dir="${cur_dir}/rtu_bxs_seyou"

BIN
package/rtu_bxs_seyou_1.0.0.3.tar.gz