var MC31:MSGCallBack_V31=nil;
//注册回调,程序开始的时候
mc31:=MCallback;//MCAllBack在后面
NET_DVR_SetDVRMessageCallBack_V31(MC31, nil);
//登录
function LoginCam4(ip,user,pass:Ansistring;Port:Integer):integer;
var
LoginInfo: NET_DVR_USER_LOGIN_INFO;
DInfo:NET_DVR_DEVICEINFO_V40;
begin
FillChar(LoginInfo, SizeOf(LoginInfo), 0);
FillChar(DInfo, SizeOf(DInfo), 0);
move(IP[1],LoginInfo.sDeviceAddress[0],length(ip));
move(user[1],LoginInfo.sUserName[0],length(user));
move(pass[1],LoginInfo.sPassword[0],length(pass));
LoginInfo.wPort:=Port;
LoginInfo.cbLoginResult:=nil;
LoginInfo.bUseAsynLogin:=false;
LoginInfo.byLoginMode:=0;
LoginInfo.byHttps:=0;
LoginInfo.pUser:=nil;
LoginInfo.byVerifyMode:=0;
LoginInfo.byUseTransport:=1;
Result := NET_DVR_Login_V40(@LoginInfo,@DInfo);
end;
//预览
function bView(view:TObject;Channel:Byte;ID:Integer):integer;
var
pUser: Pointer;
lpPreviewInfo:NET_DVR_PREVIEWINFO;// NET_DVR_CLIENTINFO;
begin
FillChar(lpPreviewInfo, SizeOf(lpPreviewInfo), 0);
lpPreviewInfo.hPlayWnd := View.Handle; // 预览窗口
lpPreviewInfo.lChannel := Channel; // 预览的设备通道
lpPreviewInfo.dwStreamType := 1; // 码流类型
lpPreviewInfo.dwLinkMode := 0; // 连接方式
lpPreviewInfo.bBlocked := 0; // 阻塞取流
lpPreviewInfo.dwDisplayBufNum := 1; // 播放库播放缓冲区最大缓冲帧数
lpPreviewInfo.byProtoType := 0;
lpPreviewInfo.byPreviewMode := 0;
Result:=NET_DVR_RealPlay_V40(ID, @lpPreviewInfo, nil, pUser);
end;
//布防
function Alarm(ID:integer):integer; //布防
var
AlarmParam: NET_DVR_SETUPALARM_PARAM;
begin
FillChar(AlarmParam, SizeOf(AlarmParam), 0);
AlarmParam.dwsize := SizeOf(AlarmParam);
AlarmParam.byLevel := 1;
AlarmParam.byAlarmInfoType := 1;
AlarmParam.byFaceAlarmDetection := 1;
Result:= NET_DVR_SetupAlarmChan_V41(ID, @AlarmParam);
end;
//
function MCallback(lCommand: long; pAlarmer: LPNET_DVR_ALARMER;
pAlarmInfo: PAnsiChar; dwBufLen: DWORD; pUser: PVOID):bool; StdCall;//回调函数
begin
case lCommand of
COMM_ITS_PLATE_RESULT:
begin
//......
end;
COMM_VEHICLE_RECOG_RESULT:
begin
end;
else
begin
exit
end;
end;
end;
function enc(S: string): string; //字符串转为GB2312的Http字符。 ascii值
function IsChineseChar(C: Char): Boolean;
begin
Result := (C >= #$4E00) and (C <= #$9FA5); // 中文字符的Unicode范围
end;
var I: Integer;
begin
I := Length(S);
Result:='';
for i := 1 to length(s) do
begin
if not IsChineseChar(s[i]) then
Result:=Result+s[i]
else
Result:=Result+'&#x'+inttohex(ord(s[i]),2)+';';
//之前没有做过网站类的,不知道Delphi有没有相关的函数,自己写了个。
end;
end;
//.................................
const LedXML =
'<?xml version="1.0"?>'+
'<LEDConfigurationList xmlns="http://www.isapi.org/ver20/XMLSchem' +
'a" version="2.0">' +
'<LEDConfiguration>' +
'<information>[info]</information>' +
'<displayMode>immediate</displayMode>' +
'<speedType>fast</speedType>' +
'<showTime>1</showTime>' +
'<showPlate>true</showPlate> ' +
' <fontSize>16</fontSize>' +
'<fontColor>[color]</fontColor>' +
'</LEDConfiguration>' +
'<LEDConfiguration>' +
'<information>[info2]</information>' +
'<displayMode>immediate</displayMode>' +
'<speedType>fast</speedType>' +
'<showTime>1</showTime>' +
'<showPlate>true</showPlate>' +
' <fontSize>16</fontSize>' +
'<fontColor>[color2]</fontColor>' +
'</LEDConfiguration>' +
'</LEDConfigurationList>';
putLedCMD='PUT /ISAPI/Parking/channels/1/LEDConfigurationDz';
//通过put 发送到LED屏。
function XML(ID:integer;Url: AnsiString; Param: AnsiString ):Byte;
//这里的Param(LEDXML,然后对内容替换),
//直接传送中文会有可能乱码,要用上面的enc转码,比如[info]显示内容。
//url : putLedCMD
var
pInputXml: NET_DVR_XML_CONFIG_INPUT;
nInSize: Integer;
strRequestUrl: AnsiString;
dwRequestUrlLen: Cardinal;
strInputParam: AnsiString;
pOutputXml: NET_DVR_XML_CONFIG_OUTPUT;
iLastErr: Cardinal;
XMSize: Cardinal;
managedArray:tbytes;
begin
Result:=0;
FillChar(pInputXml, SizeOf(pInputXml), 0);
nInSize := SizeOf(pInputXml);
pInputXml.dwSize := nInSize; // 设置大小
strRequestUrl := Url; // 设置url
dwRequestUrlLen := Length(strRequestUrl); // url长度
pInputXml.lpRequestUrl := PAnsiChar(strRequestUrl);
pInputXml.dwRequestUrlLen := dwRequestUrlLen; // 设置长度
strInputParam := Param; // 设置参数
pInputXml.lpInBuffer := PAnsiChar(strInputParam);
pInputXml.dwInBufferSize := Length(strInputParam); // 设置缓冲区大小
FillChar(pOutputXml, SizeOf(pOutputXml), 0);
pOutputXml.dwSize := SizeOf(pOutputXml); // 结构体大小
pOutputXml.lpOutBuffer := AllocMem( 3 * 1024 * 1024); // 输出参数缓冲区
pOutputXml.dwOutBufferSize := 3 * 1024 * 1024; // 输出参数缓冲区大小
pOutputXml.lpStatusBuffer := AllocMem( 4096 * 4); // 返回的状态参数
pOutputXml.dwStatusSize := 4096 * 4; // 状态缓冲区大小(内存大小)
// 透传
try
if not NET_DVR_STDXMLConfig(ID, @pInputXml, @pOutputXml) then
begin
Result := NET_DVR_GetLastError(); // 失败
EXIT;
end;
except
Result:=-1;
exit;
end;
end;
//发送语音
function Speek(s: string;ID:integer): boolean;//这里参数也要enc
var
CondSize:DWORD;
VChannel:Cardinal;
VInfo:TBytes;
InSize,OutSize:integer;
Vocfg:NET_DVR_VOICEBROADCAST_CFG;
stdCfg:NET_DVR_STD_CONFIG;
begin
if trim(s)='' then
exit;
VChannel:=1;
CondSize:=SizeOf(VChannel);
stdCfg.byDataType:=0;
stdcfg.lpCondBuffer:=@VChannel;
stdcfg.dwCondSize:=condsize;
FillChar(vocfg, SizeOf(vocfg), 0);
insize:=sizeof(vocfg);
stdcfg.lpOutBuffer:=nil;
stdcfg.dwOutSize:=insize;
stdcfg.lpStatusBuffer:=nil;
stdcfg.dwStatusSize:=0;
vocfg.dwSize:=InSize;
Vinfo:=TEncoding.Default.GetBytes(s);
move(vinfo[0],vocfg.sInfo[0],length(vinfo));
vocfg.byBroadcastNum:=1;
vocfg.byIntervalTime:=2;
GetMem(stdcfg.lpInBuffer,InSize);
stdcfg.dwInSize:=InSize;
move(vocfg,stdcfg.lpInBuffer^,sizeof(vocfg));
Result:=NET_DVR_SetSTDConfig(ID,NET_DVR_SET_VOICEBROADCAST_CFG,@stdcfg);
end;
使用HCNetSDK.pas 做海康抓拍一体机开发的时候,过程中遇到很多问题,网上找过很多,java\C#\Python,原厂Demo,开发文档,发过很多遍,包括网上发的Delphi样例,依然有很多问题,比如登录的时候,C# ,JAVA,Python都用的V40,而网上Delphi的基本都是V30,我在做的时候,尝试用V40,从C#翻译过来,结果怎么做都出问题,用V30就很方便成功了,后来试出来,用FillChar给参数先分配空间,再sizeof获取大小,后面也就正常了。还有就是发LED文本,用SDK中的NET_DVR_SetSTDConfig,只能发一行(可以用#13换行),不能换颜色,后来翻到过一篇JAVA的用Put ISAPI的,翻看开发文档中,却没有这一些内容,找了真机试了才发现。这样可以发多行,不同颜色,不同速度。
另外,在回调函数中对Form中控件操作,经常会出现读取0x0000000错误,后来发现,cxgrid,刷新过快就会这样,后面换了个表格。
回调中读写数据库,尽量使用单独连接。
--------------------------------------------------
SDK版本: CH-HCNetSDKV6.1.9.48_build20230410_win32
用的是@bluestorm提供的HCNetSDK.pas