- 蘇標(biāo)是江蘇省交通廳2018年發(fā)布的道路運(yùn)輸車輛主動(dòng)安全智能防控系統(tǒng)的平臺(tái)技術(shù)規(guī)范颂砸,是繼部標(biāo)1078流媒體后這兩年最火熱的規(guī)范早直,今年深圳展會(huì)幾乎所有參展商都以主動(dòng)安全報(bào)警作為亮點(diǎn)靶橱。
- 蘇標(biāo)的主動(dòng)安全實(shí)現(xiàn)是通過(guò)終端視頻算法分析阶淘,主動(dòng)判斷出司機(jī)駕駛行為是否違反駕駛行為規(guī)范利耍,并觸發(fā)報(bào)警望抽,如前向碰撞報(bào)警肺蔚、車道偏離報(bào)警煌妈、車距過(guò)近報(bào)警、疲勞駕駛報(bào)警宣羊、分神駕駛報(bào)警璧诵、接打電話報(bào)警、抽煙報(bào)警仇冯、駕駛員異常報(bào)警之宿、胎壓異常報(bào)警等。在發(fā)生報(bào)警的時(shí)候苛坚,可以上傳違章證據(jù)到服務(wù)器平臺(tái)比被,如視頻,圖片和記錄儀數(shù)據(jù)等炕婶。
- 蘇標(biāo)的報(bào)警是通過(guò)擴(kuò)展部標(biāo)JT808協(xié)議0x0200位置上報(bào)的附加數(shù)據(jù)上報(bào)的姐赡,平臺(tái)判斷附件數(shù)量大于0,則下發(fā)蘇標(biāo)0x9208附件上傳指令讓終端把證據(jù)文件發(fā)到附件服務(wù)器柠掂。
-
附件上傳的協(xié)議使用了2種:(1) 0x1210報(bào)警附件信息消息项滑、0x1211文件信息上傳、0x1212文件上傳完成消息采用部標(biāo)JT808協(xié)議涯贞。(2) 文件數(shù)據(jù)上傳采用蘇標(biāo)自定義的格式枪狂。
- 因?yàn)椴繕?biāo)上傳的文件有3處:808多媒體文件、1078錄像上傳FTP宋渔、蘇標(biāo)附件州疾,我們將這3塊整合在一起,程序起名為file-server皇拣,既能處理FTP錄像文件又能處理蘇標(biāo)附件严蓖,還提供了http文件訪問(wèn)接口給前端。JT808協(xié)議解析可以直接復(fù)用JT808網(wǎng)關(guān)程序的氧急,已經(jīng)兼容了JT808-2019國(guó)標(biāo)協(xié)議颗胡。
public class Jt808Message extends BaseMessage {
/**
* 消息ID
*/
private int msgId;
/**
* 終端手機(jī)號(hào)
*/
private String phoneNumber;
/**
* 終端手機(jī)號(hào)數(shù)組
*/
private byte[] phoneNumberArr;
/**
* 協(xié)議版本號(hào)
*/
private int protocolVersion;
/**
* 消息流水號(hào)
*/
private int msgFlowId;
/**
* 是否分包
*/
private boolean multiPacket;
/**
* 版本標(biāo)識(shí)
*/
private int versionFlag;
/**
* 加密方式,0:不加密吩坝,1:RSA加密
*/
private int encryptType;
/**
* 消息總包數(shù)
*/
private int packetTotalCount;
/**
* 包序號(hào)
*/
private int packetOrder;
}
- 我們?cè)诘讓幼隽艘粋€(gè)消息服務(wù)處理的provider毒姨,每條指令的處理服務(wù)在程序啟動(dòng)時(shí)自動(dòng)注冊(cè)到provider。當(dāng)每條消息解析成vo傳遞到netty的handler時(shí)钉寝,會(huì)根據(jù)消息ID從provider找到對(duì)應(yīng)的處理服務(wù)弧呐。市面上開(kāi)源的或者賣的源碼闸迷,基本上都用if/else去判斷消息ID處理,造成處理類非常龐大俘枫,而且很難維護(hù)腥沽。
@Slf4j
@Sharable
public class Jt808BusinessHandler extends SimpleChannelInboundHandler<Jt808Message> {
private MessageServiceProvider messageServiceProvider;
public static final Jt808BusinessHandler INSTANCE = new Jt808BusinessHandler();
private Jt808BusinessHandler() {
messageServiceProvider = SpringBeanService.getBean(MessageServiceProvider.class);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Jt808Message msg) throws Exception {
//獲取對(duì)應(yīng)的消息處理器
int messageId = msg.getMsgId();
BaseMessageService messageService = messageServiceProvider.getMessageService(messageId);
ByteBuf msgBodyBuf = Unpooled.wrappedBuffer(msg.getMsgBodyArr());
try {
Object result = messageService.process(ctx, msg, msgBodyBuf);
log.info("收到{}({}),終端手機(jī)號(hào):{},消息流水號(hào):{},內(nèi)容:{}", messageService.getDesc(), CommonUtil.formatMessageId(messageId), msg.getPhoneNumber(), msg.getMsgFlowId(), result);
} catch (Exception e) {
Jt808PacketUtil.reply8001(ctx, msg, Jt808ReplyResultEnum.MSG_ERROR);
printExceptionLog(msg, messageService, e);
} finally {
ReferenceCountUtil.release(msgBodyBuf);
}
}
}
-
文件路徑入庫(kù)的時(shí)候,我們把路徑用base64編碼保存崩哩,前端查詢時(shí)根據(jù)base64的路徑請(qǐng)求巡球,后臺(tái)把base64路徑解碼后直接獲取到多媒體文件數(shù)據(jù)返回前端言沐,這樣就省去了查詢數(shù)據(jù)庫(kù)的步驟邓嘹。
@Api(tags = {"文件管理"})
@RestController
@RequestMapping({"/api/v1/files/"})
public class FileController {
@Autowired
private ResourceLoader resourceLoader;
@ApiOperation("顯示文件")
@GetMapping("/display")
public ResponseEntity<Resource> show(@ApiParam("路徑") @RequestParam String path) {
try {
byte[] pathArr = Base64.getDecoder().decode(path);
String filePath = new String(pathArr, "UTF8");
log.info("顯示文件,路徑:{}", filePath);
return ResponseEntity.ok(resourceLoader.getResource("file:" + filePath));
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
-
由于file-server做了跨域處理,所以前端直接調(diào)用接口沒(méi)有問(wèn)題险胰,也可以使用nginx做反向代理汹押,前端頁(yè)面和接口都用同一個(gè)端口,前后端分離一般都用這種方案實(shí)現(xiàn)起便。