@敖德薩
1)用戶端建立websocket通信
2)硬件端建立tcp通信
3)通過$_SERVER['REMOTE_PORT']和$_SERVER['REMOTE_ADDR']來區(qū)分過來的數(shù)據(jù)
4)每個端數(shù)據(jù)中傳一個相同參數(shù)作為互推依據(jù)。
可以給個具體方案嗎?你說通過$_SERVER['REMOTE_PORT']和$_SERVER['REMOTE_ADDR']來區(qū)分發(fā)過來的數(shù)據(jù) 那么問題來了 我在哪里接收?onmessge? onmessge怎樣接收tcp協(xié)議發(fā)過來的數(shù)據(jù)?這個也是現(xiàn)在困擾我的問題 所以你說了這么多 我還沒看到有希望的信息 能給個具體的信息嗎
@7269: 我沒有用walkor給我的方法 因為我寫完了walkor才給上面的方法 我也還沒有去驗證 不過我的方法我已經(jīng)分享到workerman官方10群里了
用戶(13969)在手機上發(fā)送指令(02 03 05 d5 aa 52 d5)給服務器,通過服務器再發(fā)送給dtu設備,dtu設備(2002)向服務器返回一個指令(02 03 05 d5 aa 52 d5),服務器收到指令后,我想通過sendtouid()發(fā)送給用戶,告知用戶設備正??梢允褂?。可是用戶的uid我沒法獲取。這個你怎么處理的?
GatewayWorker所有的數(shù)據(jù)通過Events.php里的onMessage來接收。
gatewayWorker支持多協(xié)議,如果增加一個協(xié)議只需要開一個端口設置對應的端口參數(shù)及協(xié)議即可。協(xié)議層對于開發(fā)者來說是透明的。也就是說調用所有的gatewayWorker 的 Gateway::XXX(如Gateway::bindUid Gateway::sendToUid)接口時,不需要考慮對應客戶端是什么協(xié)議,直接調用即可。
如何設置多個協(xié)議,參考http://doc2.workerman.net/multi-protocols.html
現(xiàn)在假設你設置了tcp協(xié)議和websocket協(xié)議。那么整個系統(tǒng)代碼及流程類似這樣
1)、硬件客戶端通過tcp向GatewayWorker發(fā)送一個數(shù)據(jù)包,包中包含了{請求類型:設備綁定, 設備id:設備具體id}(數(shù)據(jù)格式任意,這里是一個示意),GatewayWorker收到數(shù)據(jù)后,Events.php里的onMessage接收整個數(shù)據(jù),發(fā)現(xiàn)是設備綁定類型,然后調用Gateway::bindUid($client_id, '具體的設備id');
,這樣就將設備于具體的設備id綁定了,在Events.php中調用Gateway::sendToUid('具體的設備id', '數(shù)據(jù)');
就可以給這個設備發(fā)數(shù)據(jù)了。
2)、同樣的用戶端通過websocket發(fā)起連接,然后發(fā)送一個{請求類型:用戶綁定, 用戶id:用戶具體id}請求給GatewayWorker,Events.php里的onMessage接收整個數(shù)據(jù),發(fā)現(xiàn)是用戶綁定類型,然后調用Gateway::bindUid($client_id, '具體的用戶id');
,這樣就將用戶端與具體的用戶id綁定了,在Events.php中調用Gateway::sendToUid('具體用戶id', '數(shù)據(jù)');
就可以給這個用戶發(fā)數(shù)據(jù)了。
假設你上面的設備及用戶綁定已經(jīng)做好,現(xiàn)在說說你的圖中1 2 3 4 5 6的代碼及流程
1、設備發(fā)起tcp請求
假設請求數(shù)據(jù)格式為 {type: getData}
2、GatewayWorker收到tcp請求后返回該設備相關數(shù)據(jù)
給當前設備返回數(shù)據(jù),直接調用 Gateway::sendToClient($client_id, '數(shù)據(jù)');
即可。
3、用戶通過websocket發(fā)送開關指令
假設數(shù)據(jù)格式為 {type: opertation, operation: close, device_id:具體設備id}
4、服務端收到指令后發(fā)給設備
Events.php里onMessage里利用Gateway::sendToUid(具體設備id, '設備能識別的關閉數(shù)據(jù)');
給對應設備發(fā)送操作
5、設備返回成功或失敗
數(shù)據(jù)包假設格式為{type: opertation_result, result: success},同樣的Events.php里onMessage里接收這個數(shù)據(jù)
6、將成功或者失敗結果轉發(fā)給用戶
Events.php里onMessage里利用Gateway::sendToUid(具體用戶id, '結果數(shù)據(jù)');
給對應的用戶id
總的來說Events.php里代碼類似這樣。
假設設備和用戶發(fā)來的數(shù)據(jù)都是json數(shù)據(jù),代碼類似這樣
class Events {
public static function onMessage ($client_id, $data)
{
$data = json_decode($data);
switch ($data['type']) {
// {type:device_bind, device_id:具體的設備id}
case 'device_bind':
Gateway::bindUid($client_id, $data['device_id']);
// 通過數(shù)據(jù)庫或則某種方式查詢出當前設備屬于哪個用戶,并記錄到session方便后面直接使用
$user_id = your_find_user_function($data['device_id']);
$_SESSION['belong'] = $user_id;
break;
// {type:device_bind, user_id:具體的用戶id}
case 'user_bind':
Gateway::bindUid($client_id, $data['user_id']);
break;
case 'getData':
$getDataResult = '結果數(shù)據(jù)'; // 這里假設獲得了結果
Gateway::sendToClient($client_id, $getDataResult);
break;
// {type: opertation, operation: close, device_id:具體設備id}
case 'operation':
Gateway::sendToUid($data['device_id'], "{type: opertation, operation: close}");
break;
// {type: opertation_result, result: success}
case 'opertation_result':
// 之前在sessin中記錄了當前設備屬于哪個用戶
$user_id = $_SESSION['belong'];
// 給這個用戶發(fā)送結果
Gateway::sendToUid($uiser_id, "{type: opertation_result, result: success}");
break;
}
}
}
你好,你說:硬件客戶端通過tcp向GatewayWorker發(fā)送一個數(shù)據(jù)包,包中包含了{請求類型:設備綁定, 設備id:設備具體id}(數(shù)據(jù)格式任意,這里是一個示意)。用戶(13969)在手機上發(fā)送指令(02 03 05 d5 aa 52 d5)給服務器,通過服務器再發(fā)送給dtu設備,dtu設備(2002)向服務器返回一個指令(02 03 05 d5 aa 52 d5),服務器收到指令后,我想通過sendtouid()發(fā)送給用戶,告知用戶設備正??梢允褂???墒怯脩舻膗id我沒法獲取。這個你怎么處理的?
本人也有硬件與用戶的通訊操作,提供參考:
數(shù)據(jù)還是用redis+mysql的形式(websocket僅僅作為轉發(fā),請求全部走http)
采用先http后websocket的方式,由http先對訪問進行先認證后返回帶有websocket連接參數(shù)的頁面(連接websocket的信息包含uid在內(nèi)的一切),認證不成立不返回websocket的頁面。
這樣方式用起來比較爽,回歸傳統(tǒng)的http收到請求,處理后通過GatewayWorker的websocket進行通知,避免了三方操作
樓主,你看看 https://github.com/mouyong/laravel-octane-workerman 的截圖。里邊直接是給了完成通訊的截圖示例。
在 laravel 項目引入后,配置好相關端口。通過一行命令讓他們具備通訊支持。 php artisan workerman:gateway
。
然后按照老大的說明,直接玩就可以了。