增加云台控制时间精准控制

增加云台控制时间精准控制
PtzNew
jxjajs 3 months ago committed by Matthew
parent a42bf5390c
commit 8381d6a0b9

@ -103,13 +103,17 @@ void PtzController::ExitAndWait()
void PtzController::PtzProc() void PtzController::PtzProc()
{ {
PTZ_STATE state = PTZS_POWER_OFF; PROC_PTZ_STATE state = PTZS_POWER_OFF;
SERIAL_CMD cmd; SERIAL_CMD cmd;
PTZ_STATE ptz_state;
bool hasCmd = false; bool hasCmd = false;
int i=0;
std::shared_ptr<PowerControl> powerCtrl; std::shared_ptr<PowerControl> powerCtrl;
time_t selfTestingStartTime = 0; time_t selfTestingStartTime = 0;
time_t selfTestingWaitTime = 0; time_t selfTestingWaitTime = 0;
time_t PTZ_preset_start_time=0;
time_t PTZ_preset_wait_time=0;
while(true) while(true)
{ {
@ -153,10 +157,28 @@ void PtzController::PtzProc()
time_t timeout = time(NULL) - selfTestingStartTime; time_t timeout = time(NULL) - selfTestingStartTime;
if (timeout >= selfTestingWaitTime) if (timeout >= selfTestingWaitTime)
{ {
XYLOG(XYLOG_SEVERITY_INFO, "超时(%d秒)未收到云台自检结束应答,状态改为空闲!", timeout);
state = PTZS_IDLE; state = PTZS_IDLE;
m_sem.release(); m_sem.release();
continue; continue;
} }
else
{
if(timeout >= CAMERA_SELF_TEST_TIME)
{
//XYLOG(XYLOG_SEVERITY_INFO, "开始查询云台自检状态timeout=%d秒", timeout);
if(0 == QueryPtzState(&ptz_state, QUERY_PTZ_STATE, cmd.serfile, cmd.baud, cmd.addr))
{
if(0 == ptz_state.ptz_status)
{
XYLOG(XYLOG_SEVERITY_INFO, "收到云台自检结束应答状态改为空闲timeout=%d秒", timeout);
state = PTZS_IDLE;
m_sem.release();
continue;
}
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
m_sem.release(); m_sem.release();
continue; continue;
@ -178,6 +200,7 @@ void PtzController::PtzProc()
selfTestingStartTime = time(NULL); selfTestingStartTime = time(NULL);
selfTestingWaitTime = cmd.photoParams->mPhotoInfo.selfTestingTime; selfTestingWaitTime = cmd.photoParams->mPhotoInfo.selfTestingTime;
state = PTZS_SELF_TESTING; state = PTZS_SELF_TESTING;
XYLOG(XYLOG_SEVERITY_INFO, "1、收到拍照指令摄像机从关机状态改为自检状态");
m_locker.lock(); m_locker.lock();
m_cmds.insert(m_cmds.begin(), cmd); m_cmds.insert(m_cmds.begin(), cmd);
@ -186,12 +209,33 @@ void PtzController::PtzProc()
continue; continue;
} }
} }
XYLOG(XYLOG_SEVERITY_INFO, "2、收到拍照指令state=%d", state);
state = PTZS_TAKING_PHOTO; state = PTZS_TAKING_PHOTO;
if (cmd.preset != 0 && cmd.preset != 0xFF) if (cmd.preset != 0 && cmd.preset != 0xFF)
{ {
CameraPhotoCmd(0, cmd.channel, MOVE_PRESETNO, 0, cmd.preset, cmd.serfile, cmd.baud, cmd.addr); 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));
XYLOG(XYLOG_SEVERITY_INFO, "摄像机拍照前开始调用预置点state=%d", state);
PTZ_preset_start_time = time(NULL);
PTZ_preset_wait_time = MOVE_PRESET_WAIT_TIME;
for(;;)
{
if(0 == QueryPtzState(&ptz_state, QUERY_PTZ_STATE, cmd.serfile, cmd.baud, cmd.addr))
{
if(0 == ptz_state.ptz_status)
{
XYLOG(XYLOG_SEVERITY_INFO, "摄像机拍照前调用预置点,收到移动结束应答!移动时长=%d秒 state=%d", time(NULL)-PTZ_preset_start_time, state);
break;
}
}
if(time(NULL) - PTZ_preset_start_time >= PTZ_preset_wait_time)
{
XYLOG(XYLOG_SEVERITY_INFO, "摄像机拍照前调用预置点,摄像机在%d秒内未收到调用预置点结束应答state=%d", PTZ_preset_wait_time, state);
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
} }
m_pPhoneDevice->TakePhotoWithNetCamera(cmd.photoParams->mPhotoInfo, cmd.photoParams->mPath, cmd.photoParams->mOsds, powerCtrl); m_pPhoneDevice->TakePhotoWithNetCamera(cmd.photoParams->mPhotoInfo, cmd.photoParams->mPath, cmd.photoParams->mOsds, powerCtrl);
state = PTZS_IDLE; state = PTZS_IDLE;
@ -203,22 +247,36 @@ void PtzController::PtzProc()
{ {
if (!powerCtrl) if (!powerCtrl)
{ {
powerCtrl = std::make_shared<PlzCameraPowerCtrl>(cmd.delayTime); powerCtrl = std::make_shared<PlzCameraPowerCtrl>(150);
selfTestingStartTime = time(NULL); selfTestingStartTime = time(NULL);
selfTestingWaitTime = cmd.ts; selfTestingWaitTime = 150;
state = PTZS_SELF_TESTING; state = PTZS_SELF_TESTING;
m_sem.release();
XYLOG(XYLOG_SEVERITY_INFO, "收到开机指令,摄像机从关机状态改为自检状态!设置的自检等待时间%d秒", selfTestingWaitTime);
} }
} }
else
{
XYLOG(XYLOG_SEVERITY_INFO, "收到开机指令摄像机处于state=%d", state);
}
break; break;
case CLOSE_TOTAL: case CLOSE_TOTAL:
if (state == PTZS_POWER_OFF) if (state == PTZS_POWER_OFF)
{ {
XYLOG(XYLOG_SEVERITY_INFO, "收到关机指令,摄像机本来就处于关机状态!");
// Do Nothing // Do Nothing
} }
else else
{ {
XYLOG(XYLOG_SEVERITY_INFO, "收到关机指令通知云台准备关机state=%d", state);
for(i=0; i<3; i++)
{
if(0 == QueryPtzState(&ptz_state, NOTIFY_PTZ_CLOSE, cmd.serfile, cmd.baud, cmd.addr))
break;
}
powerCtrl.reset(); powerCtrl.reset();
state = PTZS_POWER_OFF; state = PTZS_POWER_OFF;
XYLOG(XYLOG_SEVERITY_INFO, "关闭云台电源state=%d", state);
} }
break; break;
default: default:

@ -14,7 +14,7 @@
#include <SemaphoreEx.h> #include <SemaphoreEx.h>
#include <Client/Device.h> #include <Client/Device.h>
enum PTZ_STATE enum PROC_PTZ_STATE
{ {
PTZS_POWER_OFF = 0, PTZS_POWER_OFF = 0,
PTZS_IDLE = 1, PTZS_IDLE = 1,
@ -23,6 +23,9 @@ enum PTZ_STATE
PTZS_TAKING_PHOTO = 4, PTZS_TAKING_PHOTO = 4,
}; };
#define CAMERA_SELF_TEST_TIME 60 /* Camera self-test time (excluding PTZ self-test)*/
#define MOVE_PRESET_WAIT_TIME 20 /* Waiting for the maximum time for the PTZ to move to the preset position*/
class PtzPhotoParams class PtzPhotoParams
{ {
public: public:

@ -23,13 +23,14 @@
#include <sys/time.h> #include <sys/time.h>
#include <pthread.h> #include <pthread.h>
#include <AndroidHelper.h> #include "AndroidHelper.h"
#include "SensorsProtocol.h" #include "SensorsProtocol.h"
//#include "Eint.h" //#include "Eint.h"
#include <algorithm> #include <algorithm>
pthread_mutex_t serial_mutex = PTHREAD_MUTEX_INITIALIZER; // 定义一个互斥锁 pthread_mutex_t serial_mutex = PTHREAD_MUTEX_INITIALIZER; // 定义一个互斥锁
pthread_mutex_t camera_mutex = PTHREAD_MUTEX_INITIALIZER; // 定义一个互斥锁 pthread_mutex_t camera_mutex = PTHREAD_MUTEX_INITIALIZER; // 定义一个互斥锁
pthread_mutex_t bd_mutex = PTHREAD_MUTEX_INITIALIZER; // 定义一个互斥锁
SIO_PARAM_SERIAL_DEF serialport[MAX_SERIAL_PORT_NUM]; SIO_PARAM_SERIAL_DEF serialport[MAX_SERIAL_PORT_NUM];
@ -948,6 +949,7 @@ void Gm_FindAllSensorsCommand()
case PELCO_P_PROTOCOL: /* 摄像机协议*/ case PELCO_P_PROTOCOL: /* 摄像机协议*/
case SERIALCAMERA_PROTOCOL: /* 串口摄像机协议*/ case SERIALCAMERA_PROTOCOL: /* 串口摄像机协议*/
break; break;
default:
break; break;
} }
if (flag == -1) if (flag == -1)
@ -2439,13 +2441,23 @@ void MakeShxyProtocolPollCommand(int portno, uint8_t cmdidx)
unsigned char CalLpc(unsigned char *msg, int len) unsigned char CalLpc(unsigned char *msg, int len)
{ {
int i; int i;
u_char retval = 0; unsigned char retval = 0;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
retval += msg[i]; retval += msg[i];
return retval; return retval;
} }
unsigned char BDXorCheck(unsigned char *msg, int len)
{
int i;
unsigned char retval = 0;
for (i = 0; i < len; i++)
retval ^= msg[i];
return retval;
}
/*************************************************************** /***************************************************************
* * * *
***************************************************************/ ***************************************************************/
@ -3288,14 +3300,17 @@ void GM_CameraSerialComRecv(SIO_PARAM_SERIAL_DEF *pPortParam)
recvlen = read(pPortParam->fd, &recvbuf[i], sizeof(recvbuf)-i);/* 在串口读取字符串 */ recvlen = read(pPortParam->fd, &recvbuf[i], sizeof(recvbuf)-i);/* 在串口读取字符串 */
t1 = get_msec(); t1 = get_msec();
if(t1-t0 >= 350) if(t1-t0 >= 350)
break; {
i += recvlen;
break;
}
} }
recvlen = i; recvlen = i;
if (recvlen < 1) if (recvlen < 1)
return; return;
#if 1 #if 1
sprintf(buf, "收到Camera, %d字节数据:", recvlen); sprintf(buf, "收到BD, %d字节数据:", recvlen);
BytestreamLOG(0, buf, recvbuf, recvlen, 'I'); BytestreamLOG(0, buf, recvbuf, recvlen, 'I');
#endif #endif
@ -3489,6 +3504,465 @@ int QueryPtzState(PTZ_STATE *ptz_state, int cmdidx, const char *serfile, unsign
pthread_mutex_unlock(&camera_mutex); // 解锁 pthread_mutex_unlock(&camera_mutex); // 解锁
return flag; return flag;
} }
int Query_BDGNSS_Data(BD_GNSS_DATA *BD_data, int samptime, const char *serfile, unsigned int baud)
{
pthread_mutex_lock(&bd_mutex);
int flag = 0;
char szbuf[128], logbuf[128];
SIO_PARAM_SERIAL_DEF *cameraport=NULL;
if(NULL == BD_data)
return -1;
if(samptime < 5)
samptime = 5;
cameraport = (SIO_PARAM_SERIAL_DEF*)malloc(sizeof(SIO_PARAM_SERIAL_DEF));
cameraport->Retry = 0;
cameraport->RetryTime = 1000;
cameraport->WaitTime = 0;
cameraport->m_iRevStatus = 0;
cameraport->m_iRecvLen = 0;
cameraport->m_iNeedRevLength = 0;
cameraport->fd = -1;
memset(cameraport->m_au8RecvBuf, 0, RECVDATA_MAXLENTH); // 接收数据缓存区
ClearCameraCmdFormPollCmdBuf(cameraport);
flag = Gm_OpenCameraSerial(cameraport, serfile, baud);
#if 1
memset(szbuf, 0, sizeof(szbuf));
srdt.iLastGetPhotoNo = -1;
cameraport->SerialCmdidx = -1;
cameraport->FirstCmdTimeCnt = get_msec();
#endif
if(-1 == flag)
{
if(NULL != cameraport)
{
free(cameraport);
cameraport = NULL;
}
return -1;
}
if (0x00 == flag)
{
sprintf(szbuf, "北斗定位数据查询启动串口定时器!");
DebugLog(8, szbuf, 'I');
for (;;)
{
usleep(10);
//LOGW("polltime=%ldms", get_msec()-polltime);
//polltime = get_msec();
flag = GM_BdSerialTimer(cameraport);
if(get_msec() - cameraport->FirstCmdTimeCnt > samptime*1000)
{
DebugLog(8, "退出查询北斗定位数据流程!", 'V');
memmove((void*)BD_data, &cameraport->bd_data, sizeof(BD_GNSS_DATA));
break;
}
}
}
if(NULL != cameraport)
{
free(cameraport);
cameraport = NULL;
}
pthread_mutex_unlock(&bd_mutex); // 解锁
return flag;
}
int GM_BdSerialTimer(SIO_PARAM_SERIAL_DEF *pPortParam)
{
int flag = 0;
GM_BdSerialComRecv(pPortParam);
return flag;
}
void GM_BdSerialComRecv(SIO_PARAM_SERIAL_DEF *pPortParam)
{
int i, recvlen;
u_char recvbuf[RECVDATA_MAXLENTH];
char buf[RECVDATA_MAXLENTH+256];
int64_t t0, t1;
t0 = get_msec();
memset(recvbuf, 0, sizeof(recvbuf));
if (pPortParam->fd <= 0)
return;
i=0;
recvlen = 0;
memset(recvbuf, 0, sizeof(recvbuf));
for(;;)
{
i += recvlen;
recvlen = read(pPortParam->fd, &recvbuf[i], sizeof(recvbuf)-i);/* 在串口读取字符串 */
t1 = get_msec();
if(t1-t0 >= 350)
break;
}
recvlen = i;
if (recvlen < 1)
return;
#if 1
sprintf(buf, "收到BD, %d字节数据:%s", recvlen, recvbuf);
DebugLog(0, (char*)recvbuf, 'I');
#endif
BdRecvData(pPortParam, recvbuf, recvlen);
}
void BdRecvData(SIO_PARAM_SERIAL_DEF *pPortParam, u_char *buf, int len)
{
int i;
unsigned char bdxor=0, srcxor=0;
for (i = 0; i < len; i++)
{
switch (pPortParam->m_iRevStatus)
{
case 0: // 搜索起始符 '$'
pPortParam->m_iRecvLen = 0;
memset(pPortParam->m_au8RecvBuf, 0,sizeof(pPortParam->m_au8RecvBuf));
if ('$' == buf[i])
{
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
pPortParam->m_iRevStatus = 1; // 进入数据接收状态
}
break;
case 1: // 接收数据直到 '*'
if (pPortParam->m_iRecvLen >= RECVDATA_MAXLENTH)
{
// 缓冲区溢出,重置状态
pPortParam->m_iRevStatus = 0;
pPortParam->m_iRecvLen = 0;
break;
}
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
if (buf[i] == '*')
{
pPortParam->m_iRevStatus = 2; // 进入校验码接收状态
}
break;
case 2: // 接收校验码2字节十六进制和<CR><LF>
if (pPortParam->m_iRecvLen >= RECVDATA_MAXLENTH)
{
// 缓冲区溢出,重置状态
pPortParam->m_iRevStatus = 0;
pPortParam->m_iRecvLen = 0;
break;
}
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
// 检测到换行符0x0A检查前一个字符是否为回车符0x0D
if (buf[i] == 0x0A)
{
if (pPortParam->m_iRecvLen >= 5 &&
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen - 2] == 0x0D)
{
// 提取校验码(*后的两个字符)
char hex_str[3] = {
(char)pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen - 4],
(char)pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen - 3],
'\0'
};
srcxor = (uint8_t)strtol(hex_str, NULL, 16);
// 计算校验值(从$后的第一个字符到*前的字符)
uint8_t calc_xor = BDXorCheck(&pPortParam->m_au8RecvBuf[1],pPortParam->m_iRecvLen - 6);// 长度 = 总长度 - ($ + *HH + \r\n)
if (srcxor == calc_xor)
{
BD_NMEA0183_PortDataProcess(pPortParam);
pPortParam->RevCmdFlag = 1;
}
// 重置状态,准备接收下一帧
pPortParam->m_iRevStatus = 0;
pPortParam->m_iRecvLen = 0;
}
else
{
// 格式错误,丢弃数据
pPortParam->m_iRevStatus = 0;
pPortParam->m_iRecvLen = 0;
}
}
break;
case 255:// 错误接收数据
default:
if (buf[i] == '$')
{
pPortParam->m_iRevStatus = 1;
pPortParam->m_iRecvLen = 1;
pPortParam->m_au8RecvBuf[0] = buf[i];
}
else
{
pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
if (pPortParam->m_iRecvLen > 200)
{
pPortParam->m_iRecvLen = 0;
}
}
break;
}
}
}
/*
$BDRMC,023656.00,A,2240.61563,N,11359.86512,E,0.16,,140324,,,A,V*2C
$BDVTG,,,,,0.16,N,0.30,K,A*2F
$BDGGA,023656.00,2240.61563,N,11359.86512,E,1,23,0.7,96.53,M,-3.52,M,,*5B
$BDGSA,A,3,01,02,03,04,05,06,07,09,10,16,19,20,1.0,0.7,0.8,4*30
$BDGSV,6,1,23,01,45,125,38,02,46,235,40,03,61,189,46,04,32,112,37,1*7B
$BDGLL,2240.61563,N,11359.86512,E,023656.00,A,A*78
$BDZDA,023656.00,14,03,2024,00,00*71
$GPTXT,01,01,01,ANTENNA OPEN*25
GLLUTC
GSA使DOP
GSVSNR
RMC
VTG
ZDA:
TXT线
*/
void BD_NMEA0183_PortDataProcess(SIO_PARAM_SERIAL_DEF *curserial)
{
BD_NMEA0183_PROC_FUNC bd_nmea0183_call[] = {
{"$BDRMC",BD_get_BDRMC_data},/* 时间、日期、位置、速度*/
{"$BDVTG",NULL},/* 地面速度信息*/
{"$BDGGA",NULL},/* 时间、位置、定位类型*/
{"$BDGSA",NULL},/* 北斗接收机操作模式定位使用的卫星DOP 值 */
{"$BDGSV",NULL},/* 可见北斗卫星信息、仰角、方位角、信噪比SNR*/
{"$BDGLL",NULL},/* 经度、纬度、UTC 时间*/
{"$BDZDA",NULL},/* 时间、日期 */
{"$GPTXT",NULL},/* 用于天线状态检测*/
};/* irows*/
int i=0, irows;
char szbuf[512];
//char *cmd=NULL, *sourestr=NULL;
//RTUMSG rtumsg;
if(NULL == curserial)
return;
irows = sizeof(bd_nmea0183_call)/sizeof(BD_NMEA0183_PROC_FUNC);
memset(szbuf, 0, sizeof(szbuf));
//sprintf(szbuf, "rows = %d", irows);
DebugLog(0, (char*)curserial->m_au8RecvBuf, 'I');
#if 0
memset((void*)rtumsg.MsgData, 0, sizeof(rtumsg.MsgData));
memcpy((void*)rtumsg.MsgData, (void*)curserial->m_au8RecvBuf, curserial->m_iRecvLen);
rtumsg.MsgLen = curserial->m_iRecvLen;
/* 析出关键字符串*/
cmd = (char *)rtumsg.MsgData;
sourestr = strstr((char *)rtumsg.MsgData, ",");
*sourestr = 0;
sprintf(szbuf, "cmd_len = %d, cmd:%s", strlen(cmd), cmd);
DebugLog(0, szbuf, 'I');
#endif
for(i=0; i<irows; i++)
{
if(strstr((char *)curserial->m_au8RecvBuf, bd_nmea0183_call[i].cmd_name))
{
sprintf(szbuf, "cmd_name[%d]:%s", i, bd_nmea0183_call[i].cmd_name);
DebugLog(0, szbuf, 'I');
if(NULL != bd_nmea0183_call[i].recv_process)
bd_nmea0183_call[i].recv_process(curserial);
break;
}
}
if(i >= irows)
return;
}
int BD_get_BDRMC_data(SIO_PARAM_SERIAL_DEF *curserial)
{
const int UTC_TIME = 1;
const int STATUS = 2;
const int LAT = 3;
const int ULAT = 4;
const int LON = 5;
const int ULON = 6;
const int DATE = 9;
double dvalue;
int total_fields=0, ivalue;
char **result = NULL;
char buffer[128]; // 存储格式化时间的缓冲区
if(NULL == curserial)
return -1;
/*
1 $--RMC IDRMC --
2 UTCtime hhmmss.ss UTC
3 status V= A=
4 lat ddmm.mmmmm 2
5 uLat N-S-
6 lon dddmm.mmmmm 3
7 uLon E-W-西
8 spd
9 cog
10 date ddmmyy dd mm yy
11 mv
12 mvE E-W-西
13 mode [1]
14 navStatus V NMEA 4.1
15 CS 16 $*$*
16 <CR><LF> */
result = BD_NMEA0183_SplitString((char *)curserial->m_au8RecvBuf, &total_fields);
if(NULL == result)
return -1;
dvalue = ::atof(result[UTC_TIME]);
curserial->bd_data.UTC_time.tm_sec = (int)dvalue%100;
curserial->bd_data.UTC_time.tm_min = (int)dvalue/100%100;
curserial->bd_data.UTC_time.tm_hour = (int)dvalue/10000;
curserial->bd_data.ms_time = (dvalue - ((int)dvalue/1))*1000;
curserial->bd_data.status = result[STATUS][0];
dvalue = ::atof(result[LAT]);
curserial->bd_data.lat = ((int)dvalue/100)+(dvalue - ((int)dvalue/100*100))/60;
curserial->bd_data.uLat = result[ULAT][0];
dvalue = ::atof(result[LON]);
curserial->bd_data.lon = ((int)dvalue/100)+(dvalue - ((int)dvalue/100*100))/60;
curserial->bd_data.uLon = result[ULON][0];
ivalue = ::atoi(result[DATE]);
ALOGD("%d", ivalue);
curserial->bd_data.UTC_time.tm_mday = ivalue/10000;
ALOGD("D:%d", curserial->bd_data.UTC_time.tm_mday);
curserial->bd_data.UTC_time.tm_mon = ivalue/100%100-1;
ALOGD("M:%d", curserial->bd_data.UTC_time.tm_mon);
curserial->bd_data.UTC_time.tm_year = ivalue%100+100;
ALOGD("Y:%d", curserial->bd_data.UTC_time.tm_year);
::memset(buffer, 0, sizeof(buffer));
// 使用 strftime 格式化时间
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &curserial->bd_data.UTC_time);
DebugLog(0, (char*)buffer, 'I');
::sprintf(buffer, "ms:%d lat=%f ulat=%c", curserial->bd_data.ms_time, curserial->bd_data.lat, curserial->bd_data.uLat);
DebugLog(0, (char*)buffer, 'I');
::sprintf(buffer, "lon=%f ulon=%c, status=%c", curserial->bd_data.lon, curserial->bd_data.uLon, curserial->bd_data.status);
DebugLog(0, (char*)buffer, 'I');
// 释放内存
for (int i = 0; i < total_fields; ++i) free(result[i]);
free(result);
return 0;
}
char** BD_NMEA0183_SplitString(char *str, int *total_fields)
{
int max_fields, field_count = 0;
char **fields = NULL, **new_fields = NULL, **result = NULL;
char *copy = NULL, *p = NULL;
char szbuf[128];
if(NULL == str)
return NULL;
if(NULL == total_fields)
return NULL;
// 创建可修改的副本
copy = strdup(str);
memset(szbuf, 0, sizeof(szbuf));
if (!copy)
{
sprintf(szbuf, "内存分配失败\n");
DebugLog(0, szbuf, 'E');
return NULL;
}
// 初始字段数组大小
max_fields = MAX_FIELDS_NUM;
fields = (char**)malloc(max_fields * sizeof(char *));
if (!fields) {
free(copy);
sprintf(szbuf, "fields 内存分配失败\n");
DebugLog(0, szbuf, 'E');
return NULL;
}
field_count = 0;
fields[field_count] = copy; // 第一个字段起始
// 遍历字符串分割字段
for (p = copy; *p; ++p)
{
if (*p == ',')
{
*p = '\0'; // 结束当前字段
field_count++;
// 动态扩展数组
if (field_count >= max_fields) {
max_fields *= 2;
new_fields = (char**)realloc(fields, max_fields * sizeof(char *));
if (!new_fields) {
free(fields);
free(copy);
sprintf(szbuf, "new_fields 内存分配失败\n");
DebugLog(0, szbuf, 'E');
return NULL;
}
fields = new_fields;
}
fields[field_count] = p + 1; // 下一字段起始
}
}
*total_fields = field_count + 1; // 总字段数
// 复制字段到独立内存
result = (char **)malloc((*total_fields) * sizeof(char *));
if (!result)
{
free(fields);
free(copy);
sprintf(szbuf, "result 内存分配失败\n");
DebugLog(0, szbuf, 'E');
return NULL;
}
for (int i = 0; i < *total_fields; ++i) {
result[i] = strdup(fields[i]);
if (!result[i]) {
// 释放已分配内存
for (int j = 0; j < i; ++j) free(result[j]);
free(result);
free(fields);
free(copy);
sprintf(szbuf, "result 字段复制失败\n");
DebugLog(0, szbuf, 'E');
return NULL;
}
}
// 输出结果到日志
for (int i = 0; i < *total_fields; ++i)
{
sprintf(szbuf, "字段 %2d: %s\n", i + 1, result[i]);
DebugLog(0, szbuf, 'I');
}
// 释放内存
//for (int i = 0; i < total_fields; ++i) free(result[i]);
//free(result);
free(fields);
free(copy);
return result;
}
/* 串口启动接口函数 结束*/ /* 串口启动接口函数 结束*/
/* 数据和图片采集数据返回函数 开始*/ /* 数据和图片采集数据返回函数 开始*/

@ -27,6 +27,7 @@
#define IOT_PARAM_WRITE 0xAE #define IOT_PARAM_WRITE 0xAE
#define IOT_PARAM_READ 0xAF #define IOT_PARAM_READ 0xAF
#define MAX_FIELDS_NUM 20 /* BD_NMEA0183单组字符串数据内含数据最大数量*/
#define MAX_SERIAL_DEV_NUM 25 /* 最大接串口传感器数量*/ #define MAX_SERIAL_DEV_NUM 25 /* 最大接串口传感器数量*/
#define MAX_SERIAL_PORT_NUM 5 #define MAX_SERIAL_PORT_NUM 5
#define MAX_DEV_VALUE_NUM 12 /* 一台装置最大的采样值数量*/ #define MAX_DEV_VALUE_NUM 12 /* 一台装置最大的采样值数量*/
@ -39,6 +40,7 @@
#define PELCO_D_PROTOCOL 6 /* 摄像机Pelco_D协议序号*/ #define PELCO_D_PROTOCOL 6 /* 摄像机Pelco_D协议序号*/
#define SERIALCAMERA_PROTOCOL 8 /* 串口摄像机协议序号*/ #define SERIALCAMERA_PROTOCOL 8 /* 串口摄像机协议序号*/
#define MUTIWEATHER_PROTOCOL 9 /*多合一气象*/ #define MUTIWEATHER_PROTOCOL 9 /*多合一气象*/
#define NMEA0183_PROTOCOL 10 /* 单一北斗NMEA0183标准协议*/
#define RESERVE2_PROTOCOL 17 /* 备用2协议序号*/ #define RESERVE2_PROTOCOL 17 /* 备用2协议序号*/
#define RESERVE4_PROTOCOL 19 /* 备用4协议序号*/ #define RESERVE4_PROTOCOL 19 /* 备用4协议序号*/
#define RESERVE5_PROTOCOL 20 /* 备用5协议序号*/ #define RESERVE5_PROTOCOL 20 /* 备用5协议序号*/
@ -127,7 +129,6 @@
#define NOTIFY_PTZ_CLOSE 10021 // 通知云台关闭 #define NOTIFY_PTZ_CLOSE 10021 // 通知云台关闭
#define QUERY_PTZ_STATE 10022 // 查询云台状态 #define QUERY_PTZ_STATE 10022 // 查询云台状态
#define CLOSE_TOTAL 10040 /* 关闭总电源*/ #define CLOSE_TOTAL 10040 /* 关闭总电源*/
#define SPEED_DOME_CAMERA 0 /* 球机摄像机*/ #define SPEED_DOME_CAMERA 0 /* 球机摄像机*/
#define SERIAL_CAMERA 2 /* 串口摄像机a*/ #define SERIAL_CAMERA 2 /* 串口摄像机a*/
@ -227,6 +228,38 @@ typedef struct
float x_coordinate; /* 云台所处位置水平方向坐标*/ float x_coordinate; /* 云台所处位置水平方向坐标*/
float y_coordinate; /* 云台所处位置垂直方向坐标*/ float y_coordinate; /* 云台所处位置垂直方向坐标*/
} PTZ_STATE; } PTZ_STATE;
/*
$--RMC IDRMC --
2 UTCtime hhmmss.ss UTC
3 status
V=
A=
4 lat ddmm.mmmmm 2
5 uLat N-S-
6 lon dddmm.mmmm
m
3
7 uLon E-W-西
8 spd
9 cog
10 date ddmmyy dd mm yy
11 mv
12 mvE E-W-西
13 mode [1]
14 navStatus V
NMEA 4.1
15 CS 16 $*$**/
// 北斗卫星数据
typedef struct
{
struct tm UTC_time; /* UTC时间*/
int ms_time; /* 毫秒*/
double lat; /* 纬度,原值(前 2 字符表示度,后面的字符表示分)转换后为° */
char uLat; /* 纬度方向N-北S-南*/
double lon; /* 经度,原值(前 3 字符表示度,后面的字符表示分)转换后为°*/
char uLon; /* 经度'E'-东,'W'-西*/
char status; /* 'A'=数据有效 其他字符表示数据无效*/
} BD_GNSS_DATA;
typedef struct typedef struct
{ {
@ -249,18 +282,27 @@ typedef struct
uint16_t ForceWaitCnt; /* 强制等待计数*/ uint16_t ForceWaitCnt; /* 强制等待计数*/
uint8_t ReSendCmdFlag; /* 重发命令标志 */ uint8_t ReSendCmdFlag; /* 重发命令标志 */
uint8_t SendCmdFlag; /* 命令发送标志 */ uint8_t SendCmdFlag; /* 命令发送标志 */
uint8_t RevCmdFlag; /* 命令正常接收标志*/ uint8_t RevCmdFlag; /* 命令正常接收标志*/
//********************************************************** //**********************************************************
int64_t lsendtime; /* 命令发送绝对时间计时(毫秒)*/ int64_t lsendtime; /* 命令发送绝对时间计时(毫秒)*/
int cameraaddr; /* 摄像机地址*/ int cameraaddr; /* 摄像机地址*/
int SerialCmdidx; /* 正在使用的串口发送命令的命令序号(-1:表示没有命令发送) int SerialCmdidx; /* 正在使用的串口发送命令的命令序号(-1:表示没有命令发送)
使*/ 使*/
PHOTO_DEF image; /* 临时存储图片数据*/ PHOTO_DEF image; /* 临时存储图片数据*/
int64_t FirstCmdTimeCnt; /* 串口读取数据起始时间*/ int64_t FirstCmdTimeCnt; /* 串口读取数据起始时间*/
PTZ_STATE ptz_state; PTZ_STATE ptz_state;
int sendptzstatecmd; int sendptzstatecmd; // 查询命令次数控制
BD_GNSS_DATA bd_data;
} SIO_PARAM_SERIAL_DEF; } SIO_PARAM_SERIAL_DEF;
typedef const struct
{
//char *account; // 命令说明
char *cmd_name; // 命令名称
int (*recv_process)(SIO_PARAM_SERIAL_DEF *); /* urc数据处理*/
}BD_NMEA0183_PROC_FUNC;
//串口相关装置所有参数集中定义 //串口相关装置所有参数集中定义
typedef struct typedef struct
{ {
@ -489,6 +531,23 @@ int GM_IsCloseCamera(SIO_PARAM_SERIAL_DEF *pPortParam);
int GM_CameraSerialTimer(SIO_PARAM_SERIAL_DEF *pPortParam); int GM_CameraSerialTimer(SIO_PARAM_SERIAL_DEF *pPortParam);
int QueryPtzState(PTZ_STATE *ptz_state, int cmdidx, const char *serfile, unsigned int baud, int addr); int QueryPtzState(PTZ_STATE *ptz_state, int cmdidx, const char *serfile, unsigned int baud, int addr);
int Query_BDGNSS_Data(BD_GNSS_DATA *BD_data, int samptime, const char *serfile, unsigned int baud);
int GM_BdSerialTimer(SIO_PARAM_SERIAL_DEF *pPortParam);
void GM_BdSerialComRecv(SIO_PARAM_SERIAL_DEF *pPortParam);
void BdRecvData(SIO_PARAM_SERIAL_DEF *pPortParam, u_char *buf, int len);
unsigned char BDXorCheck(unsigned char *msg, int len);
void BD_NMEA0183_PortDataProcess(SIO_PARAM_SERIAL_DEF *curserial);
char** BD_NMEA0183_SplitString(char *str, int *total_fields);
int BD_get_BDRMC_data(SIO_PARAM_SERIAL_DEF *curserial);
#endif // __SENSOR_PROTOCOL_H__ #endif // __SENSOR_PROTOCOL_H__

Loading…
Cancel
Save