美猴王说车,从真假美猴王谈起-让套牌车
美猴王说车,从真假美猴王谈起-让套牌车RFID给真正杜绝套牌车带来了希望,我们只需要在汽车上牌时,同时也给汽车贴上RFID,那么这事就好办了。好了,回到套牌车(克隆车),传统方法在识别度、识别成本上就决定了,无法杜绝套牌车(原因是识别度低(纯靠经验)、识别成本高(纯靠人力))。假的美猴王简直是克隆的,和孙悟空一模一样。一开始菩提祖师、如来佛祖、观音菩萨、就连最亲近的师父、师兄弟都分辨不出来,最后师父使出紧箍咒的绝招才辨别出来。打假在现实世界中的需求也非常旺盛,诸如我们看到的一些商品的防伪码验证、水印验证、钞票的一些特征验证等等。但是大多数的防伪手段是很容易模仿的,包括电话,网站的防伪验证。钞票也一样,再难也有人会去搞。
标签
PostgreSQL rfid 物联网 IoT 套牌车 克隆车 Wavelet 图像相似度 传输加密 伪装
背景
西游记想必大家小时候都看过吧,其中有一集“真假美猴王”还记得吗?
假的美猴王简直是克隆的,和孙悟空一模一样。一开始菩提祖师、如来佛祖、观音菩萨、就连最亲近的师父、师兄弟都分辨不出来,最后师父使出紧箍咒的绝招才辨别出来。
打假在现实世界中的需求也非常旺盛,诸如我们看到的一些商品的防伪码验证、水印验证、钞票的一些特征验证等等。
但是大多数的防伪手段是很容易模仿的,包括电话,网站的防伪验证。钞票也一样,再难也有人会去搞。
好了,回到套牌车(克隆车),传统方法在识别度、识别成本上就决定了,无法杜绝套牌车(原因是识别度低(纯靠经验)、识别成本高(纯靠人力))。
RFID给真正杜绝套牌车带来了希望,我们只需要在汽车上牌时,同时也给汽车贴上RFID,那么这事就好办了。
但是前路并不是一帆风顺的,我们来分析一下还有什么难点。
难题一、车牌与RFID的配对泥潭
首先我们要搞清楚车牌与RFID的识别手段。
车牌的识别手段,拍摄,识别车牌,海康威视是一个典型的供应商代表。
RFID的识别手段,磁场识别,当RFID终端进入识别磁场时,就会被识别。
由于识别手段的差异,决定了不能同时识别同一辆车。
比如同一个路口多辆车并排通过,一张照片中可能涉及多辆车,同时RFID识别也一样,可能一次识别到多辆车,导致RFID与车牌无法在识别时一一挂钩。
如何解决被识别的车牌与RFID的多对多的配对问题呢?
一般来说道路下面都埋设了路感,当汽车经过时,触发拍摄和RFID的识别,并且触发时,可以产生一个唯一的ID,然后拍摄与RFID都带上这个ID,这样RFID与照片就能关联起来了。
但是这可能还是无法解决一对一的关联问题,由于一次可以识别多个设备,所以可能还是多对多的。
难题一解法、多对多的问题解决
1. 数组类型
由于一次或一个短暂的时间窗口内,可能拍摄到多个车牌,或者识别到多个RFID,所以我们在设计结构时,可以使用两个数组分别来存储车牌与RFID。
2. 流式计算
识别套牌车只是公共服务的其中之一,我还写过一些文章,比如抓捕人贩,识别遮挡车牌,公安刑侦等都可能会调用到RFID与车牌的数据。
《金融风控、公安刑侦、社会关系、人脉分析等需求分析与数据库实现 - PostgreSQL图数据库场景应用》
《一场IT民工 与 人贩子 之间的战争 - 只要人人都献出一点爱》
流式计算是必不可少的,不能等数据都汇总了之后再进行处理,那样延迟会很大,办事效率就低了。
3. 流式计算时间窗口
前面讲了,由于识别手段的差别,一辆车的RFID与车牌可能不是同一时刻被识别到的,比如前后有可能会差几秒。
所以在进行配对时,我们需要用到前后几秒的数据进行配对。
4. 流式计算地域窗口
除了时间维度,我们还有另一个维度,即位置维度,比如RFID的识别可能不是与拍摄系统共同建设的,不如说RFID的识别在A路段,而拍摄在附近几百米的某个信号灯附近。
那么时间可能不是差几秒,可能差分钟以上,此时,需要的是地域维度的配对手段,比如说圈定出一个区域,在该区域内的摄像头与RFID识别设备,识别到的车牌与RFID进行配对。
这里需要用到的是GIS技术,如何根据区域快速的赛选记录(GIS索引)。
PostgreSQL可以很好的支撑。
参考PostGIS。
《如何建立GIS测试环境 - 将openstreetmap的样本数据导入PostgreSQL PostGIS库》
《PostgreSQL 百亿地理位置数据 近邻查询性能》
流计算细节
配对的问题解决掉之后,就需要用到流式计算,及时的
定义transform udf
输入(车牌数组,RFID数组)
处理逻辑,根据车牌找出RFID,RFID与RFID数组进行匹配,如果不能匹配,告警。
例子、未做任何优化,仅展示功能(依赖PostGIS地理位置插件)
采集流 create stream tbl_chepai ( sid timestamp -- 序列或时间的epoch值 入库时减去offset值,形成时差 -- loc geometry -- 位置 loc point -- 测试时使用point代替经纬度 chepai text[] ); create stream tbl_rfid ( sid timestamp -- 序列或时间的epoch值 -- loc geometry -- 位置 loc point -- 测试时使用point代替经纬度 rfid text[] ); 字典库 车牌 RFID对应表 create table chepai_rfid( chepai text unique rfid text unique ); 被套牌车库 create table tbl_taopaiche(sid timestamp chepai text loc point); 流视图 1. RFID 流视图,保留30分钟的值 CREATE CONTINUOUS VIEW rfid_cv WITH (ttl = '30 min' ttl_column = 'sid') AS SELECT sid loc rfid FROM tbl_rfid; 2. 车牌 事件机制 create or replace function tg1() returns trigger as $$ declare v_rfid text := null; cv_rfid text[] := null; v_loc point := null; v_chepai text := null; cv_chepai text[] := NEW.chepai; begin for v_chepai in select chepai from (select chepai from unnest(NEW.chepai) as t(chepai)) t where not exists (select 1 from chepai_rfid where chepai_rfid.chepai=t.chepai) loop raise notice '% 是套牌车' v_chepai; -- 告警,这里可以写成异步通知,发现假车牌,或未登记RFID的车牌 -- 本例使用插入审计代替异步调用 insert into tbl_taopaiche(sid chepai loc) values (now() v_chepai NEW.loc); cv_chepai := array_remove(cv_chepai v_chepai); end loop; raise notice '%' cv_chepai; for v_rfid v_chepai in select rfid chepai from chepai_rfid where chepai = any(cv_chepai) loop raise notice '% %' v_rfid v_chepai; if v_loc is null then select loc into v_loc from rfid_cv order by loc <-> NEW.loc limit 1; raise notice '%' v_loc; end if; if cv_rfid is null then select array_agg(t.unnest) into cv_rfid from (select unnest(t1.rfid) from rfid_cv t1 where t1.loc::text=v_loc::text and t1.sid between NEW.sid-interval '1 min' and NEW.sid interval '1 min') t; if cv_rfid is null then -- 该时间段内RFID没有上报信息,可能是RFID故障,也可能是套牌车造成 raise notice '% 是套牌车' NEW.chepai; -- 告警,异步通知,可能发现套牌车 -- 本例使用插入审计代替异步调用 insert into tbl_taopaiche(sid chepai loc) values (now() v_chepai NEW.loc); continue; end if; raise notice '%' cv_rfid; end if; if (not cv_rfid && array[v_rfid]) then raise notice '% 是套牌车' NEW.chepai; -- 告警,异步通知,可能发现套牌车 -- 本例使用插入审计代替异步调用 insert into tbl_taopaiche(sid chepai loc) values (now() v_chepai NEW.loc); end if; end loop; RETURN NEW; end; $$ language plpgsql strict; CREATE CONTINUOUS TRANSFORM ct AS SELECT sid::timestamp loc::point chepai::text[] FROM tbl_chepai THEN EXECUTE PROCEDURE tg1();
数据测试
insert into chepai_rfid values('浙A00001' '123'); insert into chepai_rfid values('浙A00002' '234'); insert into tbl_rfid (sid loc rfid) values (now() '(1 2)' array['123']); insert into tbl_chepai (sid loc chepai) values (now()-interval '30 s' '(1 2)' array['浙A00002' '浙A00001']); 车牌 '浙A00002' 可能被套牌
关于流计算的其他案例和部署方法,请参考
《流计算风云再起 - PostgreSQL携PipelineDB力挺IoT》
数据风险与安全解法
1. 在识别RFID时,需要确保无线传输的数据不被窃取,比如使用加密的手段进行通信
2. 数据采集后,传输给后台(比如数据库)的过程中也需要加密
3. 由于RFID与车牌绑定,所以RFID的数据安全非常的重要,一旦RFID值被泄露,就有可能被不法分子拿去伪造携带一样信息的RFID。从而继续制造克隆车。 数据库的安全(SQL注入、密码复杂度等。。。)也是需要注意的。
关于数据库的安全,可以参考如下
《DBA专供 冈本003系列 - 数据库安全第一 过个好年》
小结
随着物联网的发展,数据正发生爆炸式的增长,流式的数据处理也会成为将来的热门需求。
pipelineDB的优势
这是个拼爹的年代,pipelinedb有个很牛逼的爸爸PostgreSQL,出身伯克利大学,有扎实的理论基础,历经了43年的进化,在功能、性能、扩展能力、理论基础等方面无需质疑一直处于领先的位置。
搞流式计算,计算是灵魂,算法和支持的功能排在很重要的位置。
PostgreSQL的强大之处在于统计维度极其丰富,数据类型也极其丰富。
build-in 数据类型参考
https://www.postgresql.org/docs/9.6/static/datatype.html
build-in 聚合,窗口,数学函数请参考
https://www.postgresql.org/docs/9.6/static/functions.html
同时还支持扩展,常见的例如
MADLib
PostGIS
路径规划
wavelet
基因
化学
还有好多好多(为什么这么多?原因是PostgreSQL的BSD-Like许可,致使了PG的生态圈真的很大很大,深入各行各业)。
你能想到的和想不到的几乎都可以在pipelinedb 中进行流式处理,大大提高开发效率。