需求:订阅成功后,当有新的数据时,下级平台可以向上级平台发送通知消息推送数据。
目录
一、通知接口
1.接口文档
2.入参对象
(1)通知对象
通过通知消息,可推送采集设备、卡口信息、人脸信息、机动车信息等数据。
(2)设备对象
设备ID(20位数字):1-6位行政区划码;11-13位119
(3)卡口对象
卡口ID规则同设备ID
(4)人脸对象
详见协议GA/T 1400.3-A.9 人脸对象,此处仅列举必选字段。R为必选/O为可选。
设备编码必填,否则无法挂到对应设备下。
(5)机动车对象
详见协议GA/T 1400.3-A.10 机动车对象,此处仅列举必选字段。R为必选/O为可选。
卡口编号为必填,否则无法挂到对应卡口下。
坐标值没有可以填0。
(6)子图像对象
Data:图片base64码。
Type:图像类型。如果类型不对会导致图片无法解析。
3.请求头示例
User-Identify:20位数字平台编码(本平台)
4.请求方法体示例
(1)通知消息对象
@Data
public class SubscribeNotificationRequestObject {
private SubscribeNotificationListObject SubscribeNotificationListObject;
@Data
public static class SubscribeNotificationListObject {
private List<SubscribeNotification> SubscribeNotificationObject;
}
@Data
public static class SubscribeNotification {
private String NotificationID; // 通知消息id 33位
private String SubscribeID;
private String Title;
private String TriggerTime;
private String InfoIDs;
private Integer ExecuteOperation; // 更新项目:1添加;2修改;3删除
// 设备数据 集合
private DeviceRequestObject.APEListObject DeviceList;
// 卡口目录 集合
private TollgateRequestObject.TollgateListObject TollgateObjectList;
// 人脸数据 集合
private FaceRequestObject.FaceListObject FaceObjectList;
// 机动车数据 集合
private MotorVehicleRequestObject.MotorVehicleListObject MotorVehicleObjectList;
}
}
========================================================================================
Json格式:
{
"SubscribeNotificationListObject": {
"SubscribeNotificationObject": [{
"NotificationID": "xxxx",
"InfoIDs": "xxxx",
"Title": "xx数据通知",
"SubscribeID": "xxxx",
"TriggerTime": "20230412145514",
"ExecuteOperation":1,
"DeviceList":{},
"FaceObjectList":{},
"MotorVehicleObjectList":{},
"TollgateObjectList":{}
}]
}
}
(2)设备对象
@Data
public class DeviceRequestObject {
private APEListObject APEList;
@Data
public static class APEListObject {
private List<ApeObject> APEObject;
}
@Data
public static class ApeObject {
private String ApeID; // 设备ID
private String Name;
private String Model;
private String IPAddr;
private String IPV6Addr;
private String Port;
private String Longitude;
private String Latitude;
private String PlaceCode;
private String Place;
private String OrgCode;
private String MonitorDirection;
private String MonitorAreaDesc;
private String IsOnline;
private String OwnerApsID;
private String UserId;
private String Password;
private String FunctionType;
}
}
========================================================================================
Json格式:
"DeviceList":
{
"APEObject": [{
"IPAddr": "xx.xx.xx.xx",
"Port": "xx",
"FunctionType": "x",
"PlaceCode": "行政区划码",
"Latitude": "xx.xxxx",
"Longitude": "xx.xxxx",
"Name": " 设备名称",
"IsOnline": "1",
"Model": "xxxx",
"ApeID": "xxxx"
}]
}
(3)卡口对象
@Data
public class TollgateRequestObject {
private TollgateListObject TollgateListObject;
@Data
public static class TollgateListObject {
private List<Tollgate> TollgateObject;
}
@Data
public static class Tollgate {
private String TollgateID;
private String Name;
private String Longitude;
private String Latitude;
private String PlaceCode;
private String Place;
private String Status;
private String TollgateCat;
private String TollgateUsage;
private String LaneNum;
private String OrgCode;
private String OrgIndex;
}
}
========================================================================================
Json格式:
"TollgateObjectList":
{
"TollgateObject": [{
"Status": "x",
"PlaceCode": "行政区划码",
"TollgateCat": "xx",
"Latitude": "xxx.xx",
"Longitude": "xx.xx",
"Name": "卡口名称",
"TollgateID": "xxx",
"TollgateUsage": "xx"
}]
}
(4)人脸对象
@Data
public class FaceRequestObject {
private FaceListObject FaceListObject;
@Data
public static class FaceListObject {
private List<Face> FaceObject;
}
@Data
public static class Face {
private String FaceID; // 48位
private Integer InfoKind;
private String SourceID; // faceId的前41位,与子图像对象中底图类型的ImageID相等
private String DeviceID;
private Integer LeftTopX;
private Integer LeftTopY;
private Integer RightBtmX;
private Integer RightBtmY;
private Integer IsDriver;
private Integer IsForeigner;
private Integer IsSuspectedTerrorist;
private Integer IsCriminalInvolved;
private Integer IsDetainees;
private Integer IsVictim;
private Integer IsSuspiciousPerson;
private SubImageList SubImageList;
}
@Data
public static class SubImageList {
private List<SubImageInfo> SubImageInfoObject;
}
}
========================================================================================
Json格式:
"FaceObjectList":
{
"FaceObject": [{
"FaceID": "xxxx",
"DeviceID": "xxxx",
"SourceID": "xxxx",
"IsVictim": 0,
"SubImageList": {
"SubImageInfoObject": [{
"DeviceID": "xxxx",
"EventSort": 2,
"FileFormat": "Jpeg",
"Type": "14", // 底图
"ImageID": "xxxx",
"ShotTime": "20220412145208",
"Height": 1440,
"Width": 2560
}, {
"DeviceID": "xxx",
"EventSort": 2,
"FileFormat": "Jpeg",
"Type": "11", // 人脸图
"ImageID": "xxx",
"ShotTime": "20220412145208",
"Height": 512,
"Width": 512
}]
},
"IsSuspectedTerrorist": 0,
"IsForeigner": 0,
"InfoKind": 0,
"IsCriminalInvolved": 0,
"IsDetainees": 0,
"IsSuspiciousPerson": 0
}]
}
(4)机动车对象
@Data
public class MotorVehicleRequestObject {
private MotorVehicleListObject MotorVehicleListObject;
@Data
public static class MotorVehicleListObject {
private List<MotorVehicle> MotorVehicleObject;
}
@Data
public static class MotorVehicle {
private String MotorVehicleID; // 48位
private Integer InfoKind;
private String SourceID; // motorVehicleID的前41位
private String TollgateID;
private String DeviceID;
private String StorageUrl1;
private Integer LeftTopX;
private Integer LeftTopY;
private Integer RightBtmX;
private Integer RightBtmY;
private String HasPlate;
private String PlateClass;
private String PlateColor;
private String PlateNo;
private String VehicleColor;
private SubImageList SubImageList;
}
@Data
public static class SubImageList {
private List<SubImageInfo> SubImageInfoObject;
}
}
========================================================================================
Json格式:
"MotorVehicleObjectList":
{
"MotorVehicleObject": [{
"MotorVehicleID": "xxxxx",
"DeviceID": "xxxxx",
"SourceID": "xxxxxx",
"StorageUrl1": "https://图片路径.jpg",
"SubImageList": {
"SubImageInfoObject": [{
"DeviceID": "xxxx",
"EventSort": 1,
"FileFormat": "xx",
"Type": "01", // 车辆大图
"StoragePath": "https://车辆大图路径.jpg",
"ImageID": "xxxxxx",
"ShotTime": "20210412151437",
"Height": 1440,
"Width": 2560
}]
},
"PlateClass": "xx",
"InfoKind": 0,
"HasPlate": true,
"VehicleColor": "x",
"PlateColor": "x",
"PlateNo": "xxxxx"
}]
}
(6)子图像对象
@Data
public class SubImageInfo {
private String ImageID;
private Integer EventSort;
private String DeviceID;
private String StoragePath;
private String ImageType;
private String FileFormat;
private String ShotTime; // 拍摄时间
private Integer Width;
private Integer Height;
private String Data; // 图片base64码
private String Type;
}
二、通知消息代码示例
public class Gat1400NotificationDemo {
public void notification() {
try {
/** 根据保存的订阅详情,获得
*(1)订阅ID
*(2)订阅类型
*(3)发送通知消息地址(或写死)
*(4)图像类型
*/
String SubscribeID = "SubscribeID";
String SubscribeType = "SubscribeType";
String receiveAddr = "receiveAddr";
String ResultImageDeclare = "ResultImageDeclare";
// 构造通知消息
SubscribeNotificationRequestObject subscribeNotificationRequestObject = new SubscribeNotificationRequestObject();
SubscribeNotificationRequestObject.SubscribeNotificationListObject subscribeNotificationListObject = new SubscribeNotificationRequestObject.SubscribeNotificationListObject();
subscribeNotificationRequestObject.setSubscribeNotificationListObject(subscribeNotificationListObject);
List<SubscribeNotificationRequestObject.SubscribeNotification> subscribeNotificationList = new ArrayList();
// 公安机关机构代码 + 子类型编码(04-订阅通知)+ 时间编码(YYYYMMDDhhmmss) + 流水序号(00001)
String time = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
String NotificationIDStr = "xx0000000000" + "04" + time; // 需要补上5位流水号
int count = 1;
SubscribeNotificationRequestObject.SubscribeNotification subscribeNotification = new SubscribeNotificationRequestObject.SubscribeNotification();
subscribeNotification.setSubscribeID(SubscribeID);
subscribeNotification.setNotificationID(NotificationIDStr + String.format("%05d",count));
subscribeNotification.setTriggerTime(time);
subscribeNotification.setInfoIDs("MotorVehicleObjectList");
subscribeNotification.setTitle(SubscribeTitle); // 订阅标识
// 数据查询条件:时间区间、地区等
SearchParam param = new SearchParam();
switch (SubscribeType) {
case "13": // 机动车数据
MotorVehicleRequestObject vehicleRequestObject = new MotorVehicleRequestObject();
MotorVehicleRequestObject.MotorVehicleListObject vehicleListObject = new MotorVehicleRequestObject.MotorVehicleListObject();
vehicleRequestObject.setMotorVehicleListObject(vehicleListObject);
List<MotorVehicleRequestObject.MotorVehicle> vehicleList = new ArrayList<>();
// 填充车辆方法 vehicleList
makeVehicleList(vehicleList, param);
vehicleListObject.setMotorVehicleObject(vehicleList);
subscribeNotification.setMotorVehicleObjectList(vehicleListObject);
break;
case "12": // 人脸数据
FaceRequestObject faceRequestObject = new FaceRequestObject();
FaceRequestObject.FaceListObject faceListObject = new FaceRequestObject.FaceListObject();
faceRequestObject.setFaceListObject(faceListObject);
List<FaceRequestObject.Face> faceList = new ArrayList<>();
// 填充人脸数据方法
makeFaceList(faceList, param);
faceListObject.setFaceObject(faceList);
subscribeNotification.setFaceObjectList(faceListObject);
break;
case "3": // 采集设备
DeviceRequestObject deviceRequestObject = new DeviceRequestObject();
DeviceRequestObject.APEListObject apeList = new DeviceRequestObject.APEListObject();
deviceRequestObject.setAPEList(apeList);
List<DeviceRequestObject.ApeObject> apeObjectList = new ArrayList<>();
// 填充采集设备方法
makeDeviceList(apeObjectList, param);
apeList.setAPEObject(apeObjectList);
subscribeNotification.setDeviceList(apeList);
break;
case "7": // 卡口
TollgateRequestObject tollgateRequestObject = new TollgateRequestObject();
TollgateRequestObject.TollgateListObject tollgateListObject = new TollgateRequestObject.TollgateListObject();
tollgateRequestObject.setTollgateListObject(tollgateListObject);
List<TollgateRequestObject.Tollgate> tollgateList = new ArrayList<>();
// 填充卡口方法
makeDeviceList(tollgateList, param);
tollgateListObject.setTollgateObject(tollgateList);
subscribeNotification.setTollgateObjectList(tollgateListObject);
break;
default:
break;
}
subscribeNotificationList.add(subscribeNotification);
subscribeNotificationListObject.setSubscribeNotificationObject(subscribeNotificationList);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/json;charset=utf-8"));
headers.set("User-Identify", "本级平台编码");
HttpEntity<String> httpEntity = new HttpEntity<>(JSONUtil.toJsonStr(subscribeNotificationRequestObject), headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(receiveAddr, HttpMethod.POST, httpEntity, String.class);
} catch (Exception e) {
log.error("异常:", e);
}
}
}
/**
* 根据查询条件,查询对应的车辆信息,再构造成通知数据对象加入列表中。
*/
private void makeVehicleList(List<MotorVehicleRequestObject.MotorVehicle> vehicleList, SearchParam param) {
// 根据param查询车辆数据..
MotorVehicleRequestObject.MotorVehicle motorVehicle = new MotorVehicleRequestObject.MotorVehicle();
motorVehicle.setMotorVehicleID("xxxx");
...
// 子图片对象信息
MotorVehicleRequestObject.SubImageList subImageList = new MotorVehicleRequestObject.SubImageList();
SubImageInfo subImageInfo = new SubImageInfo();
subImageInfo.setData("base64码");
subImageInfo.setShotTime("拍摄时间");
...
List<SubImageInfo> subImageInfoList = new ArrayList<>();
subImageInfoList.add(subImageInfo);
subImageList.setSubImageInfoObject(subImageInfoList);
motorVehicle.setSubImageList(subImageList);
...
vehicleList.add(motorVehicle);
}
请求结果示例
{
"ResponseStatusListObject": {
"ResponseStatusObject": [{
"RequestURL": "/VIID/SubscribeNotifications",
"StatusCode": 0,
"StatusString": "操作成功",
"Id": "通知id",
"LocalTime": "20220412161015"
}]
}
}
三、RestTemplate请求配置
需要限制请求响应时长不超过5秒,数据应该少量多次推送。
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
HttpClient httpclient = HttpClientBuilder.create().build();
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient);
httpRequestFactory.setConnectTimeout(5000);
httpRequestFactory.setConnectionRequestTimeout(5000);
httpRequestFactory.setReadTimeout(5000);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
if (response.getRawStatusCode() != 401) {
super.handleError(response);
}
}
});
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("UTF-8")));
return restTemplate;
}
}