本系統(tǒng)為iot物聯(lián)網(wǎng)的插件版,功能和文檔與獨(dú)立應(yīng)用版有些地方不一致,以本文檔內(nèi)容為準(zhǔn)
本系統(tǒng)是基于webman開發(fā)的一套物聯(lián)網(wǎng)平臺,可以實(shí)現(xiàn)物聯(lián)網(wǎng)設(shè)備的聯(lián)網(wǎng)上線、數(shù)據(jù)采集、命令下發(fā)、被動回復(fù)、實(shí)時通訊等功能,支持TCP協(xié)議、Websocket協(xié)議(ws和wss)和MQTT協(xié)議,本系統(tǒng)提供的是TCP協(xié)議透傳,用戶需根據(jù)實(shí)際情況將設(shè)備協(xié)議轉(zhuǎn)為TCP協(xié)議后接入本系統(tǒng),一般可使用DTU設(shè)備或IO設(shè)備,這些設(shè)備可以將硬件的各種協(xié)議統(tǒng)一轉(zhuǎn)為TCP協(xié)議,如電表、儀表、傳感器、地磅、IO設(shè)備、開關(guān)量、模擬量、掃碼槍、語音播報、身份證讀卡器、各類燈具、門禁開關(guān)等都支持,真正實(shí)現(xiàn)萬物互聯(lián)。
1、安裝數(shù)據(jù)庫組件:(參考webman文檔)
composer require -W illuminate/database
2、安裝redis組件:(需安裝redis擴(kuò)展,參考webman文檔)
composer require -W illuminate/redis illuminate/events
3、安裝gateway-worker插件(安裝完成后,需將config/plugin/gateway-worker/app.php中的enable改為false)
composer require webman/gateway-worker
4、安裝http客戶端插件
composer require -W workerman/http-client
5、安裝redis隊列
composer require webman/redis-queue
6、安裝workerman/mqtt
composer require workerman/mqtt ^1.7
以上步驟完成之后,再去webman-admin的插件管理里面安裝本插件,如果已經(jīng)安裝過本插件,那么直接進(jìn)行下述升級步驟。
注意:php版本要求7.X
插件安裝完成之后,進(jìn)行以下升級步驟,升級文檔和所需文件在“/app/plugin/iotplug/升級步驟和相關(guān)文件”目錄下。
升級步驟:
升級前注意備份
1、將plugin\iotplug\升級步驟和相關(guān)文件\redis-queue目錄下的3個文件復(fù)制到app\queue\redis目錄下。
2、新建wa_device_logs表:
CREATE TABLE `wa_device_logs` (
`id` bigint(20) NOT NULL COMMENT 'id',
`device_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '設(shè)備id',
`type` int(11) NOT NULL DEFAULT '0' COMMENT '設(shè)備類型',
`topic` varchar(255) DEFAULT NULL COMMENT '主題',
`vtype` int(11) NOT NULL DEFAULT '0' COMMENT '0:ASCII類型1:HEX類型',
`val` longtext NOT NULL COMMENT '值',
`year` varchar(10) NOT NULL COMMENT '年',
`month` varchar(10) NOT NULL COMMENT '月',
`day` varchar(10) NOT NULL COMMENT '日',
`date` date NOT NULL COMMENT '日期',
`addtime` datetime NOT NULL COMMENT '時間',
`del` int(11) NOT NULL DEFAULT '0' COMMENT '0未刪除1已刪除',
`del_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '刪除人id',
`del_time` datetime DEFAULT NULL COMMENT '刪除時間'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='設(shè)備數(shù)據(jù)日志表';
--
-- 表的索引 `wa_device_logs`
--
ALTER TABLE `wa_device_logs`
ADD PRIMARY KEY (`id`),
ADD KEY `member_id_device_id_del` (`device_id`,`del`),
ADD KEY `idx_device_time` (`device_id`,`year`,`month`,`day`,`del`);
3、新建wa_webhook_logs表:
CREATE TABLE `wa_webhook_logs` (
`id` bigint(20) NOT NULL COMMENT 'id',
`device_id` bigint(20) NOT NULL COMMENT '設(shè)備id',
`url` text NOT NULL COMMENT 'url',
`param` text NOT NULL COMMENT '設(shè)備數(shù)據(jù)',
`status` int(11) NOT NULL COMMENT '0執(zhí)行成功,1執(zhí)行失敗',
`msg` text COMMENT '執(zhí)行結(jié)果',
`exception` text COMMENT '異常結(jié)果',
`year` varchar(20) NOT NULL COMMENT '年份',
`month` varchar(20) NOT NULL COMMENT '月份',
`day` varchar(20) NOT NULL COMMENT '日期',
`date` date NOT NULL COMMENT '日期',
`addtime` datetime NOT NULL COMMENT '時間',
`del` int(11) NOT NULL COMMENT '0未刪除1已刪除',
`del_id` bigint(20) NOT NULL COMMENT '刪除人id',
`del_time` datetime DEFAULT NULL COMMENT '刪除時間'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='設(shè)備webhook日志';
--
-- 表的索引 `wa_webhook_logs`
--
ALTER TABLE `wa_webhook_logs`
ADD PRIMARY KEY (`id`),
ADD KEY `member_id_device_id_del` (`device_id`,`del`),
ADD KEY `idx_device_year_month_day` (`device_id`,`year`,`month`,`day`,`del`);
4、wa_iot表增加字段,已經(jīng)存在就不需要執(zhí)行了
ALTER?TABLE?`wa_iot`?ADD?`log`?INT(1)?NOT?NULL?DEFAULT?'1'?COMMENT?'是否啟用設(shè)備數(shù)據(jù)日志0不啟用1啟用 '?AFTER?`directive`;
5、MQTT協(xié)議,如果用不到mqtt可以忽略。
(1)安裝emqx1.0,建議用寶塔進(jìn)行安裝。
(2)登錄emqx網(wǎng)頁管理后臺,左側(cè)菜單里找到訪問控制-客戶端認(rèn)證,創(chuàng)建mysql認(rèn)證方式,填寫mysql權(quán)限信息,密碼加密方式:plain,加鹽方式:disable
SQL代碼:
(3)左側(cè)菜單里:集成-webhook,創(chuàng)建webhook回調(diào),觸發(fā)器:所有消息和事件,請求方法:post,
URL:http://XXXX/api/mqtt(本URL可以隨意更改,但是必須是不需要登錄就可以被訪問的,安全校驗(yàn)請自行設(shè)計)
(4)在http://XXXX/api/mqtt里的代碼如下(文件路徑:plugin\iotplug\升級步驟和相關(guān)文件\ApiController.php):
<?php
namespace app\controller;
class ApiController
{
public function mqtt()
{
//安全校驗(yàn)請自行設(shè)計
//獲取請求參數(shù)
$param = [];
if (!empty(request())) {
$param = request()->all();
$body = request()->rawBody();
if (!empty($body)) {
$body = jsonDecode($body, true);
if (!empty($body)) {
$param = array_merge($param, $body);
}
}
}
//success,normal
//not_authorized bad_username_or_password
if (isset($param['reason_code']) && in_array($param['reason_code'], ['not_authorized', 'bad_username_or_password'])) {
return $param['reason_code'];
}
//發(fā)送mqtt消息
$param['index'] = genreId('mqtt');
\Webman\RedisQueue\Redis::send('iots_redis_queue_mqtt_api', $param);
}
}
6、重啟項目 php start.php restart -d 完成升級
1、數(shù)據(jù)采集:支持利用TCP協(xié)議從設(shè)備實(shí)時采集數(shù)據(jù),數(shù)據(jù)可以直接存入redis里,支持string類型和list類型,支持?jǐn)?shù)據(jù)過濾,支持?jǐn)?shù)據(jù)轉(zhuǎn)發(fā)給指定url。
2、命令下發(fā):支持服務(wù)端秒級給設(shè)備下發(fā)指令,支持以隊列的方式下發(fā)。
3、被動回復(fù):根據(jù)設(shè)備發(fā)送的特定指令,針對性的回復(fù)命令。
4、實(shí)時通訊:可以跟設(shè)備實(shí)時進(jìn)行通訊,方便驗(yàn)證命令和調(diào)試設(shè)備。
5、數(shù)據(jù)轉(zhuǎn)發(fā):可以實(shí)現(xiàn)兩個或多個設(shè)備之間的相互轉(zhuǎn)發(fā),如:想讓設(shè)備采集的數(shù)據(jù)直接發(fā)送到網(wǎng)頁websocket,用轉(zhuǎn)發(fā)即可簡單實(shí)現(xiàn)。
1、下載代碼部署到服務(wù)器上
2、修改配置參數(shù):文件路徑:plugin/iotplug/config/iot.php,其中ip:為所在服務(wù)器的公網(wǎng)IP,tcp_port:TCP協(xié)議監(jiān)聽端口,ws_port:WebSocket協(xié)議監(jiān)聽端口(ws),wss_port:WebSocket協(xié)議監(jiān)聽端口(wss),ssl_cert:SSL證書(.crt),ssl_key:SSL證書密鑰(.key),super_code:超級權(quán)限注冊包(注意修改),默認(rèn)所有的設(shè)備收到的消息都會轉(zhuǎn)發(fā)消息到這個注冊包.
(1)設(shè)置的端口要注意開啟放行,如果是用的寶塔,在安全欄目添加,如果是阿里云ECS,注意在ECS控制臺里添加安全組放行。
(2)wss_port是https的websocket端口,如果需要使用,請配置ssl證書,阿里云騰訊云都可以申請免費(fèi)的證書。注意:如果是鏈接wss的話,websocket不能用ip地址,需要用域名,跟證書保持一致。如WebSocket("wss://iot.xxx.com:6363"),其中iot.xxx.com的證書要跟配置的wss.key和wss.crt一致
3、如果需要mqtt,那么需要安裝mqtt服務(wù)端。百度安裝emqx軟件的步驟或者寶塔面板-軟件管理-搜索emqx安裝。安裝完成后進(jìn)入emqx的后臺管理系統(tǒng),默認(rèn)的路徑是http://xx.xx.xx.xx:18083 首次登錄需要設(shè)置賬號密碼。登錄進(jìn)去之后找到客戶端認(rèn)證設(shè)置菜單。
3.1配置客戶端認(rèn)證:
SELECT password FROM wa_iot where username = ${username} and code = ${clientid} and del = 0 LIMIT 1
具體配置頁面如下圖,注意密碼加密方式為:plain,加鹽:disable
3.2配置webhook:http://xx.xx.xx.xx:6767/api/mqtt 勾選所有消息與事件
注意不要啟動客戶端授權(quán)。
3.3配置客戶端
SELECT action, permission, topic FROM wa_iot where username = ${username} and code = ${clientid} and del = 0
1、自定義注冊包:
(1)必填。自定義注冊包是設(shè)備與服務(wù)端建立連接的唯一憑證,設(shè)備在連接服務(wù)端時,必須使用自定義注冊包,否則服務(wù)端會拒絕連接。
(2)自定義注冊包可以是任意字符串,但是不能包含英文逗號,否則會導(dǎo)致解析錯誤。
(3)注冊包是設(shè)備的唯一ID且不能跟其他設(shè)備重復(fù),相當(dāng)于設(shè)備的身份證,用于向服務(wù)端驗(yàn)證身份。一般是在使用DTU的時候配置在DTU里,第一次連接服務(wù)端的時候,DTU會發(fā)送自定義注冊包進(jìn)行身份注冊。服務(wù)端驗(yàn)證通過后建立連接。
(4)自定義注冊包只需在第一次連接服務(wù)端時發(fā)送,后續(xù)連接服務(wù)端時,不需要再發(fā)送。
2、自定義回復(fù)包:非必填,自定義回復(fù)包是設(shè)備在第一次注冊成功時,服務(wù)端回復(fù)給設(shè)備的數(shù)據(jù),如果不填寫,那么服務(wù)端不回復(fù)。
3、名稱:必填,設(shè)備名稱。
4、協(xié)議類型:
(1)TCP透傳:創(chuàng)建一個TCP客戶端,設(shè)備發(fā)送的數(shù)據(jù)會直接轉(zhuǎn)發(fā)給服務(wù)端,服務(wù)端發(fā)送的數(shù)據(jù)會直接轉(zhuǎn)發(fā)給設(shè)備。用戶可以通過DTU設(shè)備,將設(shè)備的數(shù)據(jù)轉(zhuǎn)發(fā)給服務(wù)端,服務(wù)端再轉(zhuǎn)發(fā)給設(shè)備,這樣就實(shí)現(xiàn)了設(shè)備與服務(wù)端的通訊。
(2)WebSocket:創(chuàng)建一個websocket客戶端。
(3)Mqtt:創(chuàng)建一個Mqtt設(shè)備
5、登錄類型:
(1)單點(diǎn)登錄:該自定義注冊包只允許一個設(shè)備登錄,當(dāng)多個設(shè)備使用同一個注冊包登錄時,會將已登錄設(shè)備踢下去。通常設(shè)備與服務(wù)端建立的TCP協(xié)議都使用單點(diǎn)登錄。
(2)多點(diǎn)登錄,該自定義注冊包只允許多個設(shè)備同時登錄,通常websocket協(xié)議都是多點(diǎn)登錄。
6、數(shù)據(jù)字段:
(1)此字段為配置redis字段,設(shè)備返回的數(shù)據(jù)會存入到這個redis字段里,支持string類型和list類型,如果是list類型,那么設(shè)備返回的數(shù)據(jù)會存入到list的頭部,如果是string類型,那么設(shè)備返回的數(shù)據(jù)會覆蓋之前的數(shù)據(jù)。如果想設(shè)置list類型,那么請在字段前面加上:list,如:list:valList。如果不設(shè)置,默認(rèn)為string類型,如:val,即表示字段為val的string類型數(shù)據(jù)。
(2)ASCII:設(shè)備返回的數(shù)據(jù)以ASCII格式存入redis,HEX:以16進(jìn)制格式存入redis
(3)請注意:即使不設(shè)置redis字段,這里的數(shù)據(jù)類型也要設(shè)置,系統(tǒng)是根據(jù)這個字段進(jìn)行數(shù)據(jù)轉(zhuǎn)化,如一般的設(shè)備都是HEX,系統(tǒng)默認(rèn)
7、數(shù)據(jù)轉(zhuǎn)發(fā):
(1)此字段為配置轉(zhuǎn)發(fā)設(shè)備的注冊包,多個注冊包用英文逗號分隔。
上圖含義:路燈M9NRilOsYETL2接收到的數(shù)據(jù)會同步轉(zhuǎn)發(fā)到vW5FqKGW6G28,B2PeiPfwejdu兩個設(shè)備里。
(2)轉(zhuǎn)發(fā)的數(shù)據(jù)會進(jìn)行簡單的打包,以json字符串進(jìn)行轉(zhuǎn)發(fā)。格式為:
{"k":"M9NRilOsYETL2","v":"values","t":"xxxx-xx-xx xx:xx:xx"}
解釋:k:數(shù)據(jù)來源的注冊包,v:轉(zhuǎn)發(fā)的數(shù)據(jù),t:轉(zhuǎn)發(fā)時間.
8、Http-Client:
(1)此字段為配置數(shù)據(jù)轉(zhuǎn)發(fā)的url,多個url用英文逗號分隔。
上圖含義:自來水供水tK8i2JvLJGrf3接收到的數(shù)據(jù)會同步轉(zhuǎn)發(fā)到http://xxx.com,http://yyy.com 這兩個域名,
(2)轉(zhuǎn)發(fā)會以post請求進(jìn)行轉(zhuǎn)發(fā),有以下參數(shù):vtype:數(shù)據(jù)類型:0表示ASCII,1表示HEX16進(jìn)制,msg:轉(zhuǎn)發(fā)的數(shù)據(jù),from:轉(zhuǎn)發(fā)來源注冊包
9、數(shù)據(jù)過濾
(1)如果啟用的話,系統(tǒng)會對設(shè)備發(fā)來的數(shù)據(jù)進(jìn)行簡單的過濾,不符合過濾條件的數(shù)據(jù)會被丟棄。
(2)字節(jié)長度:會根據(jù)數(shù)據(jù)的字節(jié)長度進(jìn)行過濾。
(3)前N位字符:會根據(jù)數(shù)據(jù)的前N位字符進(jìn)行過濾。
(4)忽略心跳包:會根據(jù)特定字符串進(jìn)行過濾。
1、設(shè)備默認(rèn)不啟用定時下發(fā),如果啟用的話,需要設(shè)備重新連接后生效。
2、系統(tǒng)默認(rèn)支持頻率:1秒1次、1秒2次、30秒1次、1分鐘1次、3秒1次、10秒1次。
3、自定義內(nèi)容:ASCII類型,HEX類型。物聯(lián)網(wǎng)設(shè)備一般以HEX16進(jìn)制類型下發(fā)。
4、支持填寫多個指令,用英文逗號,分隔。若設(shè)置多個指令,則會按照設(shè)置的頻率,按照指令從前到后依次發(fā)送。
如上圖所示,代表第一個30秒的時候,發(fā)送010300010001D5CA,第二個30秒發(fā)送010300040001C5CB,第三個30秒發(fā)送010300010001D5CA,依次類推。這樣設(shè)計的目的是有些設(shè)備會限制請求幀的頻率,頻率太高或一次性發(fā)多條,設(shè)備就不會回復(fù)。
1、系統(tǒng)支持設(shè)置兩套命令回復(fù)。
2、觸發(fā)指令:設(shè)備回復(fù)的指令如果與觸發(fā)指令匹配即觸發(fā),服務(wù)端會進(jìn)行回復(fù)。
3、回復(fù)指令:當(dāng)觸發(fā)被動回復(fù)后服務(wù)端回復(fù)的指令。
4、ASCII類型,HEX類型(16進(jìn)制)
設(shè)備發(fā)送的數(shù)據(jù)都會在這個數(shù)據(jù)流上顯示。系統(tǒng)設(shè)置了一個超級權(quán)限注冊包,即config/plugin/webman/gateway-worker/app.php文件中的super_code字段,所有的iot設(shè)備發(fā)送的數(shù)據(jù),都會默認(rèn)給這個超級權(quán)限轉(zhuǎn)發(fā),即實(shí)現(xiàn)了數(shù)據(jù)流的實(shí)時數(shù)據(jù)監(jiān)控,super_code也可以通過數(shù)據(jù)流下發(fā)指令給設(shè)備,即實(shí)現(xiàn)與設(shè)備的實(shí)時通訊。
1、每一個設(shè)備在連接服務(wù)端成功之后,都會默認(rèn)創(chuàng)建一個定時器,這個定時器是按照1秒1次進(jìn)行下發(fā)指令,該定時器使用隊列進(jìn)行依次下發(fā),隊列為HFiots-注冊包名-Default-Crontab,如果注冊包名為xxxx,即:HFiots-xxxx-Default-Crontab。
2、隊列的數(shù)據(jù)格式為:
$data = json_encode(['vtype' => 1, 'val' => 'xxxxxx'], JSON_UNESCAPED_UNICODE);
vtype:數(shù)據(jù)類型 0ASCII,1HEX16進(jìn)制
val:下發(fā)指令
3、使用方法:
Redis::rpush('HFiots-xxxx-Default-Crontab', $data);
4、服務(wù)端會按照下面代碼的順序1秒鐘給設(shè)備下發(fā)一次指令
Redis::lindex('HFiots-xxxx-Default-Crontab', 0)
1、系統(tǒng)默認(rèn)要求設(shè)備每隔30秒發(fā)送一次心跳包,如果設(shè)備超過55秒沒有發(fā)送心跳包,系統(tǒng)會自動斷開設(shè)備連接。
2、如果想關(guān)閉心跳包,可以在config/plugin/webman/gateway-worker/process.php文件中的對應(yīng)協(xié)議的pingNotResponseLimit字段設(shè)置為0,即關(guān)閉心跳包。
1、websocket端可以主動給其他客戶端發(fā)送消息,代碼如下:
var obj = {
to: th.deviceCode, //目標(biāo)客戶端自定義注冊包
type: 1, //0:ASCII,1:HEX
eol: 0, //0:指令末尾不加換行,1:指令末尾加換行(有些設(shè)備的協(xié)議需要換行來區(qū)分)
val: '010600020001e9ca' //指令內(nèi)容
};
ws.send(JSON.stringify(obj));
2、php端也可以主動給其他客戶端發(fā)送消息,代碼如下:
$my = [
'from' => 'fromCode', //發(fā)送方的自定義注冊包
'to' => 'toCode', //接收方的自定義注冊包
'type' => '1', //0:ASCII,1:HEX,2:GB2312
'eol' => '0', //不加換行
'val' => $code //發(fā)送的內(nèi)容
];
fwrite($client, json_encode($my, JSON_UNESCAPED_UNICODE) . "\n");
1、語音播報設(shè)備:https://www.bilibili.com/video/BV13h411V7FK
2、掃碼槍:https://www.bilibili.com/video/BV1f24y1L7fd/
3、紙幣識別器:https://www.bilibili.com/video/BV1Vs4y1U7Et/
4、電子秤:https://www.bilibili.com/video/BV1xo4y1H7Ro/
安裝workermann/mqtt
composer require workerman/mqtt ^1.7
1、wa_iot表添加索引 ALTER TABLE `wa_iot` ADD INDEX( `type`, `del`);
2、將mqtt客戶端部分改為workerman/mqtt重寫,不再使用emqx的webhook(請登錄emqx后臺關(guān)閉webhook)。
涉及到客戶端在線狀態(tài)、訂閱、發(fā)布、記錄上報數(shù)據(jù)、轉(zhuǎn)發(fā)ws設(shè)備、Http-Client轉(zhuǎn)發(fā)。
3、config/plugin/webman/gateway-worker/app.php增加配置項
'mqtt_client_port' => 5103, // MQTT客戶端所在進(jìn)程的監(jiān)聽端口,用于管理mqtt設(shè)備的訂閱、發(fā)布和銷毀
'mqtt_client_username' => 'admin', // MQTT客戶端的管理員用戶名,需跟emqx的配置保持一致:訪問控制-客戶端認(rèn)證
'mqtt_client_password' => '123456', // MQTT客戶端的管理員密碼,需跟emqx的配置保持一致:訪問控制-客戶端認(rèn)證
'mqtt_client_id' => 'HiWADmy42NB4', //MQTT客戶端的管理員client_id(不能跟其他client_id重復(fù)),需跟emqx的配置保持一致:訪問控制-客戶端認(rèn)證
'mqtt_client_api_url' => 'http://127.0.0.1:18083/', //MQTT客戶端的管理員api_url,帶/結(jié)尾.EMQX的api端口默認(rèn)18083,
如果修改了端口,需要修改這里.如果不是本機(jī),需要修改為實(shí)際的公網(wǎng)ip地址
'mqtt_client_api_key' => 'c7ad44cbad762a5d', //MQTT客戶端的管理員api_key,在emqx中創(chuàng)建:系統(tǒng)設(shè)置-API密鑰
'mqtt_client_api_secret' => 'j7SGdQpKIO3sUnTFJDJjhgVl5eyv2PpWoS2HFSYEdBP', //MQTT客戶端的管理員api_secret,在emqx中創(chuàng)建:系統(tǒng)設(shè)置-API密鑰
//管理員的設(shè)置是為了接收所有mqtt設(shè)備的上報,為了安全上線前最好進(jìn)行修改,如果更改(mqtt_client_username、mqtt_client_password、mqtt_client_id)的話,
//需要同步修改emqx的配置的sql語句,路徑在訪問控制-客戶端認(rèn)證-mysql里,否則無法連接
//mysql的sql語句如下:
// SELECT
// CASE
// WHEN ${username} = "admin" AND ${clientid} = "HiWADmy42NB4" THEN "123456"
// ELSE password
// END as password
// FROM wa_iot
// WHERE
// (username = ${username} AND code = ${clientid} AND del = 0)
// OR (${username} = "admin" AND ${clientid} = "HiWADmy42NB4")
// LIMIT 1
//更改后需restart重啟項目
4、設(shè)備添加的時候增加code重復(fù)校驗(yàn)
5、日志配置文件log.php里增加MqttClient
6、MQTT設(shè)備增加定時下發(fā)功能,可以設(shè)置發(fā)布的主題。增加下線設(shè)備功能。
7、TCP設(shè)備定時下發(fā)功能完善:定時器銷毀時清理變量