首页 > Python基础教程 >
-
C#教程之华夏出入口车牌识别摄像机
出入口车牌识别摄像机
HTTP POST功能模式说明
2018年5月
目 录
一、 Http架构方案处理流程... 2
二、 相机端参数配置页面... 3
三、 模式说明... 4
(一) 模式1.. 4
1. WebService地址... 4
2. 接口... 4
3. message的创建方式及事例代码... 4
(二) 模式2.. 8
1. 数据内容... 8
2. 方案说明:... 9
3. http post 断网续传功能... 9
4. 上传车牌全景图片和特写图片数据内容... 12
5. 服务器端图片数据解析... 13
6. 服务端应答... 14
1) 入口应答数据... 14
2) 出口应答数据... 14
3) 主服务响应心跳应答数据... 15
四、 注意事项... 16
一、 Http架构方案处理流程
二、 相机端参数配置页面
图1 相机配置页面
三、 模式说明
(一) 模式1
摄像头对进出场车辆数量更新,使用WebService方式调用
- WebService地址
WebService地址是可以在摄像头端配置的,配置的地址样例格式为:
http://182.92.112.149:8089/WebService.asmx
- 接口
bool UpdateParkingCountByCamera(string message)
string是消息字符串,内容见下一节
bool是返回值true成功,false失败
- message的创建方式及事例代码
private string CreateCameraMessage()
{
// 创建byte的数组
// 1字节的在场车辆数量增加还是减少,4字节的车型字符串长度,N字节的车型字符串,
// 4字节的车牌颜色字符串长度,N字节的车牌颜色字符串,4字节的车牌号字符串长度,N字节的车牌号字符串
// 8字节的date毫秒,4字节的摄像头IP字符串长度,N字节的摄像头IP字符串,4字节的停车场ID
bool isAdd = true; // true表示有车进场,在场车辆数量增加,false表示有车出场,在场车辆数量减少
string carType = "小型车";
string plateColor = "蓝色";
string plate = "京A99999";
long ms = DateTime.Now.Millisecond;
string ip = "192.168.0.1";
int parkingId = 1;
byte[] ret = new byte[1 + 4 + Encoding.UTF8.GetBytes(carType).Length + 4 + Encoding.UTF8.GetBytes(plateColor).Length +
4 + Encoding.UTF8.GetBytes(plate).Length + 8 + 4 + Encoding.UTF8.GetBytes(ip).Length + 4];
int offset = 0;
Array.Copy(BitConverter.GetBytes(isAdd), 0, ret, offset, 4);
offset += 1;
Array.Copy(BitConverter.GetBytes(Encoding.UTF8.GetBytes(carType).Length), 0, ret, offset, 4);
offset += 4;
Array.Copy(Encoding.UTF8.GetBytes(carType), 0, ret, offset,Encoding.UTF8.GetBytes(carType).Length);
offset += Encoding.UTF8.GetBytes(carType).Length;
Array.Copy(BitConverter.GetBytes(Encoding.UTF8.GetBytes(plateColor).Length), 0, ret, offset, 4);
offset += 4;
Array.Copy(Encoding.UTF8.GetBytes(plateColor), 0, ret, offset,Encoding.UTF8.GetBytes(plateColor).Length);
offset += Encoding.UTF8.GetBytes(plateColor).Length;
Array.Copy(BitConverter.GetBytes(Encoding.UTF8.GetBytes(plate).Length), 0, ret, offset, 4);
offset += 4;
Array.Copy(Encoding.UTF8.GetBytes(plate), 0, ret, offset, Encoding.UTF8.GetBytes(plate).Length);
offset += Encoding.UTF8.GetBytes(plate).Length;
Array.Copy(BitConverter.GetBytes(ms), 0, ret, offset, 4);
offset += 8;
Array.Copy(BitConverter.GetBytes(Encoding.UTF8.GetBytes(ip).Length), 0, ‘。第三方可微分11111asdqweqwrewqfdkpewokfret, offset, 4);
offset += 4;
Array.Copy(Encoding.UTF8.GetBytes(ip), 0, ret, offset, Encoding.UTF8.GetBytes(ip).Length);
offset += Encoding.UTF8.GetBytes(ip).Length;
Array.Copy(BitConverter.GetBytes(parkingId), 0, ret, offset, 4);
offset += 4;
return Convert.ToBase64String(ret);
其中该摄像头是进场摄像头还是出场摄像头,可在摄像头管理页面配置
该摄像头隶属于哪个停车场,也可在摄像头管理页面配置,一个int可以满足。
(二) 模式2
- 数据内容
1)车牌数据包
POST /htc/app/v1/c/camera_parking HTTP ----- 上传路径
Host: 119.254.103.73 ----- 服务器地址/ 端口
Content-Type: application/x-www-form-urlencoded ----- 数据类型
Content-Length: 61 ----- 数据长度 (取决于真实数据长度决定)
type=%s&car_plate=京ABC123&color=蓝色 ----数据包类型 (车牌数据包和心跳包)
&start_time=1234567890&park_id=5& camera_id=%s ----车牌数据(包含数据包类型、日期、车牌颜色、车牌号码、相机ID---MAC地址、停车场ID)
2)心跳数据包
POST /htc/app/v1/c/camera_parking HTTP ----- 上传路径同上
Host: 119.254.103.73 ----- 服务器地址/ 端口同上
Content-Type: application/x-www-form-urlencoded ----- 数据类型
Content-Length: 25 ----- 数据长度 (取决于真实数据长度决定)
type=HeartBeat&interval=%d ------心跳周期(可配置)
- 方案说明:
路径:实际发送路径就是界面配置的路径。
发送内容:
1) 车牌数据内容: 数据类型&车牌号&车牌颜色&时间&停车场ID&相机ID,以及抓拍图片
2) 心跳数据包内容: HeartBeat&心跳周期(心跳周期可设置为5~30秒,超过边界5或30时取其边界值,心跳周期默认值为10秒)。
注意: 数据类型type可取值为online/offline/HeartBeat(心跳数据包部分), online: 表示此次发送的数据包为实时车牌信息数据包。
offline: 表示此次发送的数据包是从SD卡中存储的原来心跳检测http post 的服务器离线或post上传服务器时失败时所存储的车牌信息数据包。
HeartBeat:表示此次发送的数据包为心跳数据包。
算法识别到结果后,入口相机根据http服务端反馈信息判断是否打开道闸,以及在LED屏显示相关内容
出口相机则根据http服务器返回的消息进行打开道闸和LED屏金额显示。
- http post 断网续传功能
网页控件(相机参数-http post参数)界面中有一个断网续传功能开关和一个心跳周期设置选项见第3页图1 相机配置页面。httppost断网续传功能默认不开启。心跳默认是10秒。
相机通过添加对接收http post上传数据的主服务器(以下简称主服务器,为了和备用服务器区分)心跳检测来判断主服务器是否在线。例如心跳周期设定为5秒,相机就会每隔5秒向主服务器发一次心跳,主服务器接收到心跳数据后,通过判断心跳发来的数据给相机发送不同的响应,相机接收主服务器发来响应,进行判断主服务器是否在线。如果相机超时时间内没有接收到服务器发送的响应或接收到错误的响应,相机就会判定主服务器离线,然后继续判定其它条件(是否启用正确的备用服务器,详见如下表1、表2)决定是否存车牌等储信息片到SD中。当心跳检测主服务器正常时,SD卡中有带有httpost的NC图片相机就会以post形式续传到主服务器上。
1)http post断网存储部分:
心跳检测主服务器正常时: 车牌识别成功后,会先post 上传到主服务器再上传备用服务器(开启备用服务器),如果向主服务器和备用服务器(开启备用服务器)都post最大上传次后数仍没有接收正确的响应或未接收到响应,就会存储实时车牌图片信息到SD卡中,图片名如下(图2)中带httppost字段和NC字段的全景图和车牌特写图(带有closeup字段);如果向主服务器或备用服务器(开启备用服务器)上传中有一次post成功就停止post继续执行并且不会存储图片。(post上传到主服务器和备用服务器之间没有前后影响,上传数据到主服务器成功后,如果开启备用服务器,仍会继续向备用服务器上传数据)
如果心跳检测到主服务离线,post上传会跳过向主服务器的上传,如果未开启比用服务器就会直接存储图片到SD卡中;如果开启了备用服务器,会向备用服务器上传(最大次数3次),如果成功,不会存储图片,失败就存储图片到SD卡中。
图2 httppost 断网续传存储的文件名
图注:图中带有httppost 字段的文件名表示是由httppost所存储到SD卡中的文件,同时带有httppost字段的和NC字段的文件名是post失败或主服务器离线时存储到SD卡中的图片的文件名。
例如:设置最大上次次数3次,开启断网续传功能,设置心跳周期5秒
(1) 开启备用服务器,相机存储车牌等信息到SD卡中的条件如下(表1)
表1:
心跳检测主服务器是否在线 |
上传主服务器是否有一次post成功(最多post3次) |
上传备用服务器是否有一次post成功(最多post3次) |
是否存储图片到SD卡中 |
在线 |
有 |
有 |
不存储 |
在线 |
有 |
没有 |
不存储 |
在线 |
没有 |
有 |
不存储 |
在线 |
没有 |
没有 |
存储 |
离线 |
|
有 |
不存储 |
离线 |
|
没有 |
存储 |
(2)如果未开启备用服务器,相机存储车牌等信息到SD卡中的条件如下(表2)
表2:
心跳检测主服务器是否在线 |
上传主服务器是否有一次post成功(最多post3次) |
是否存储图片到SD卡中 |
在线 |
有 |
不存储 |
在线 |
没有 |
存储 |
离线 |
|
存储 |
2)http post续传部分:
心跳检查post 的主服务器是否在线,在线的话,会把SD中的带有_httppost_字段并且带有NC字段的图片以post形式续传到主服务器(只续传主服务器,备用服务器不续传,此次续传服务器不用给相机发送相应的响应数据),续传成功,会将图片名字的NC字段去掉以剩下字段重新命名如下图3。如果post续传到主服务器失败会保留图片的文件名等待下次续传直至续传成功。
图3 http post断网续传续传后文件名
相机对对SD卡中的http post断网存储图片的处理如下(表3)
表3:
心跳检测主服务器是否在线 |
续传主服务器是否有一次post成功(最多post3次) |
对SD卡中的http post断网存储图片的处理 |
在线 |
有 |
文件名中去掉NC字段并且重新命名 |
在线 |
没有 |
保留文件直至续传成功 |
离线 |
|
保留文件等待续传 |
- 上传车牌全景图片和特写图片数据内容
发送请求:
1)实时http post上传
POST /htc/app/v1/c/camera_parking HTTP/1.1
Host: 115.28.209.249:4088
Content-Type: application/x-www-form-urlencoded
Content-Length: 55240
type=online&car_plate=京N06GB8&color=蓝色&start_time=1436509947&park_id=5&camera_id=0001aa00000d&picture=全景图数据BASE64编码&closeup_pic=车牌特写图数据BASE64编码
2)SD卡存储的图片续传
POST /htc/app/v1/c/camera_parking HTTP/1.1
Host: 115.28.209.249:4088
Content-Type: application/x-www-form-urlencoded
Content-Length: 55241
type=offline&car_plate=京N06GB8&color=蓝色&start_time=1436509947&park_id=5&camera_id=0001aa00000d&picture=全景图数据BASE64编码&closeup_pic=车牌特写图数据BASE64编码
- 服务器端图片数据解析
$data= base64_decode(str_replace(" ", "+", $picture));
file_put_contents("./imgs/". iconv('UTF-8', 'GB2312', $car_plate) . "." ."jpg", $data);
- 服务端应答
1) 入口应答数据
识别车牌数据上传服务器,服务端返回应答数据在LED屏中显示,并根据返回状态判断是否抬杆(只针对实时post数据到主服务器;相机对于备用服务器发过来的响应数据只用来判定通信成功与否不会进行其它的动作处理)
{"status":200, "speed":1, "postfix":"欢迎光临","verified":true/false}
status:200 http通信状态,200代表应答返回正常
speed:1 显示屏播放速度为1 (不同品牌LED屏速度存在差异)
postfix:欢迎光临 LED屏播放内容
verified:true/false 是否抬杆,true:抬杆 false: 不抬杆
入口开闸模式:
- 识别成功开闸:只有识别为有牌车辆才会控制闸机开启,车辆放行
- 全部开闸: 识别有牌车和无牌车均开启栏杆放行
- 反馈开闸: 根据http服务端返回状态来判断是否抬杆 (true:抬杆 false: 不抬杆)
2) 出口应答数据
识别车牌数据上传服务器,服务端返回应答数据,相机通过服务端所返回的消息判断是否打开道闸,并在LED屏显示金额 (只针对实时post数据到主服务器;相机对于备用服务器发过来的响应数据只用来判定通信成功与否不会进行其它的动作处理)
{"status":200, "totol_fee":0.000000,"is_paid":true, "display":"hello,123456"}
status:200 http通信状态,200代表应答返回正常
totol_fee:0.000000 收费金额 (费率由服务端进行计算)
display:"hello,123456"} LED屏显示内容 (内容可自定义)
is_paid: true/false 是否抬杆,true:抬杆 false: 不抬杆
3) 主服务响应心跳应答数据
主服务器接收到相机发送的心跳包,进行判定响应相机请求,给出应答数据,应答数据在wireshark里的抓包应该是标准的http消息,如下图
内容如下:
{"status": 200,"PostServer":"OK"}
status:200 http通信状态,200代表应答返回正常
PostSetver:OK 用于相机判定主服务器正常
4) 车牌数据与心跳数据通用应答数据
当服务器工作在公网,设备工作在私网时,因为存在私网穿透的问题,服务器很难直接向设备发起通信。如果服务器需要主动向设备下发黑白名单、透传串口数据、执行开闸等动作时,可以利用定时上报的心跳包网络连接,将这些主动下发的命令通过心跳包应答来发送给设备。
这种方案的好处是可以简单的解决私网穿透的问题,坏处是主动下发的命令需要被动的定时发送,会有一定的延时,延时最长可达到心跳包的周期间隔。
此外对于正常的车牌推送消息,服务器也可以通过推送消息的应答来下发上述的各种命令。在车牌推送消息应答中增加命令下发,可以减小被动下发命令的延时。
a) 黑白名单下发
- i. 添加黑白名单
添加黑白名单的应答消息为json格式,例如:
{"PostServer":"OK", "whitelist_opt_data" : [{"Action" : "add",
"PlateNumber" : "粤B12345", "Type" : "W",
"Start" : "2000/01/01 00:00:00", "End" : "2020/12/31 23:59:59"}]}
其中PostServer字段为必填字段,其值必须为OK;
whitelist_opt_data字段为必填字段,其值为一个数组,数组中的每一项为一条待添加的黑白名单,黑白名单信息包括:
Action为必填字段,其值为黑白名单操作类型,对于添加黑白名单,必须为add;
PlateNumber为必填字段,其值为车牌号码;
Type为黑白名单类型,当值为W时表示白名单,当值为B时表示黑名单;
Start为黑白名单生效的开始时间;
End为黑白名单生效的结束时间。
- ii. 编辑黑白名单
编辑黑白名单的应答消息为json格式,例如:
{"PostServer":"OK", "whitelist_opt_data" : [{"Action" : "update",
"PlateNumber" : "粤B12345", "Type" : "W",
"Start" : "2000/01/01 00:00:00", "End" : "2020/12/31 23:59:59"}]}
其中PostServer字段为必填字段,其值必须为OK;
whitelist_opt_data字段为必填字段,其值为一个数组,数组中的每一项为一条待编辑的黑白名单,黑白名单信息包括:
Action为必填字段,其值为黑白名单操作类型,对于编辑黑白名单,必须为update;
PlateNumber为必填字段,其值为车牌号码;
Type为黑白名单类型,当值为W时表示白名单,当值为B时表示黑名单;
Start为黑白名单生效的开始时间;
End为黑白名单生效的结束时间。
- iii. 删除黑白名单
删除黑白名单的应答消息为json格式,例如:
{"PostServer":"OK", "whitelist_opt_data" : [{"Action" : "delete",
"PlateNumber" : "粤B12345"
}]}
其中PostServer字段为必填字段,其值必须为OK;
whitelist_opt_data字段为必填字段,其值为一个数组,数组中的每一项为一条待删除的黑白名单,黑白名单信息包括:
Action为必填字段,其值为黑白名单操作类型,对于删除黑白名单,必须为delete;
PlateNumber为必填字段,其值为车牌号码。
- iv. 删除所有黑白名单
删除所有黑白名单的应答消息为json格式,例如:
{"PostServer":"OK", "whitelist_opt_data" : [{"Action" : "deleteAll",
"PlateNumber" : ""
}]}
其中PostServer字段为必填字段,其值必须为OK;
whitelist_opt_data字段为必填字段,其值为一个数组,对于删除所有黑白名单的操作,只需要向数组中添加一条空白车牌号的黑白名单信息即可;
Action为必填字段,其值为黑白名单操作类型,对于删除所有黑白名单,必须为deleteAll;
PlateNumber为必填字段,对于删除所有黑白名单的操作,车牌号码可以随意填写。
- v. 查询黑白名单信息
查询黑白名单的应答消息为json格式,例如:
{"PostServer":"OK", "whitelist_opt_data" : [{"Action" : "query",
"PlateNumber" : "粤B12345"
}]}
其中PostServer字段为必填字段,其值必须为OK;
whitelist_opt_data字段为必填字段,其值为一个数组,数组中的每一项为一条待查询的黑白名单,黑白名单信息包括:
Action为必填字段,其值为黑白名单操作类型,对于查询黑白名单,必须为query;
PlateNumber为必填字段,其值为车牌号码。
b) 485/232串口数据透传
485/232串口数据透传的应答消息为json格式,例如:
{"ext" : {"name" : "test", "type" : 0, "device" : "RS485", "data" : " MDAwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGY="}}
其中name字段目前没有使用,可以随意填写;
type字段必须为0;
device字段支持RS485和RS232,分别表示485和232串口设备;
data字段为要透传的数据,base64编码格式。
c) 开闸(第一路开关量输出闭合)
开闸(开关量输出闭合)的应答消息为json格式,例如:
{"ext" : {"name" : "test", "type" : 0, "device" : "IO1", "data" : "ON"}}
其中name字段目前没有使用,可以随意填写;
type字段必须为0;
device字段目前只支持IO1,即第一路开关量输出;
data字段为ON时,表示开关量闭合。
四、 注意事项
1、 在对接时,如果网页上勾选了断网续传,则服务器必须在收到相机的心跳包后,响应心跳应答数据才行,否则相机会认为服务器掉线,不再推送车牌图片数据。