我有一些設(shè)備,是統(tǒng)一通過(guò)同一個(gè)4G模塊來(lái)發(fā)送指令,即這些設(shè)備的的clientid是一樣,但是發(fā)送過(guò)來(lái)的指令會(huì)攜帶具體的設(shè)備id,此時(shí)該如何判斷具體某臺(tái)設(shè)備的在線(xiàn)情況呢?目前想法是在onMessage里面,等收到設(shè)備的登錄指令時(shí),根據(jù)不同的設(shè)備id,創(chuàng)建對(duì)應(yīng)的一分鐘定時(shí)器,然后監(jiān)聽(tīng)設(shè)備的心跳指令,如果某臺(tái)設(shè)備的心跳指令及時(shí)發(fā)送過(guò)來(lái),則刪除該設(shè)備的定時(shí)器,同時(shí)再創(chuàng)建一個(gè)新的定時(shí)器,如此反復(fù),如果一分鐘內(nèi)沒(méi)有收到對(duì)應(yīng)設(shè)備的心跳指令,則執(zhí)行業(yè)務(wù)邏輯更新數(shù)據(jù)庫(kù)設(shè)備的狀態(tài)為離線(xiàn),這樣反復(fù)創(chuàng)建定時(shí)器可以嗎
為什么不是設(shè)備id去綁定clientid呢
因?yàn)槎鄠€(gè)設(shè)備是通過(guò)公用同一個(gè)模塊來(lái)發(fā)送指令,即這些設(shè)備的clientid都一樣,如果用設(shè)備id去綁定,執(zhí)行Gateway::bindUid,那么之前綁定的設(shè)備id會(huì)被擠掉
只要重新綁定clientid就會(huì)變,通過(guò)設(shè)備id去查詢(xún)?cè)诰€(xiàn)狀態(tài),發(fā)生指令;即便是多個(gè)設(shè)備同樣的指令也是要單獨(dú)一個(gè)個(gè)的發(fā)
是要單獨(dú)一個(gè)個(gè)發(fā),可是這些設(shè)備是通過(guò)同一個(gè)模塊發(fā)送過(guò)來(lái)的,我這邊onmessage里面打印的數(shù)據(jù)顯示的clientId全都是一樣的
比如有十臺(tái)設(shè)備,發(fā)送了十個(gè)登錄指令過(guò)來(lái),這十個(gè)登錄指令里面的設(shè)備id不一樣,但是clientId都一樣
文檔里面說(shuō):uid與client_id是一對(duì)多的關(guān)系,系統(tǒng)允許一個(gè)uid下有多個(gè)client_id,但是一個(gè)client_id只能綁定一個(gè)uid,如果綁定多次uid,則只有最后一次綁定有效。
用Gateway::getClientIdByUid打印發(fā)現(xiàn)之前綁定的uid沒(méi)有了
返回一個(gè)數(shù)組,數(shù)組元素為與uid綁定的所有在線(xiàn)的client_id。如果沒(méi)有在線(xiàn)的client_id則返回一個(gè)空數(shù)組。
此方法可以判斷一個(gè)uid是否在線(xiàn)。
注意:返回值為與uid綁定的所有在線(xiàn)的client_id數(shù)組。因?yàn)橐呀?jīng)下線(xiàn)的client_id會(huì)自動(dòng)與uid解綁,所以已經(jīng)下線(xiàn)的client_id不會(huì)出現(xiàn)在返回值中。
是的,這些設(shè)備全部同個(gè)一個(gè)端口發(fā)送,就會(huì)導(dǎo)致前一個(gè)設(shè)備剛剛綁定,當(dāng)后一個(gè)設(shè)備登錄指令發(fā)送過(guò)來(lái),就會(huì)把前一個(gè)給擠掉
問(wèn)題就出在這里,我的多個(gè)設(shè)備是通過(guò)同一個(gè)端口來(lái)發(fā)送指令的,他們?cè)趃atewayworker這邊的clientid都是一樣的,這樣就導(dǎo)致了每個(gè)端口有且只有一臺(tái)設(shè)備可以在線(xiàn),所以我想用端口id來(lái)綁定clientid,然后用定時(shí)器來(lái)監(jiān)控心跳,判斷具體設(shè)備的在線(xiàn)情況,想問(wèn)這種頻繁的創(chuàng)建和刪除定時(shí)器是否支持
可以參考這個(gè),設(shè)置一個(gè)時(shí)間間隔,超出時(shí)間如果沒(méi)有接收到onMessage則默認(rèn)為關(guān)閉狀態(tài)
use Workerman\Connection\TcpConnection;
class BaseSocket
{
/** @var int 設(shè)置心跳間隔 */
const HEARTBEAT_TIME = 50;
/**
* 啟動(dòng)服務(wù)執(zhí)行
* @param Worker $worker
* @return void
*/
public function onWorkerStart(Worker $worker)
{
Timer::add(10, function () use ($worker) {
$time_now = time();
foreach ($worker->connections as $connection) {
// 有可能該connection還沒(méi)收到過(guò)消息,則lastMessageTime設(shè)置為當(dāng)前時(shí)間
if (empty($connection->lastMessageTime)) {
$connection->lastMessageTime = $time_now;
continue;
}
// 上次通訊時(shí)間間隔大于心跳間隔,則認(rèn)為客戶(hù)端已經(jīng)下線(xiàn)
if ($time_now - $connection->lastMessageTime > self::HEARTBEAT_TIME) {
$connection->onLine = 0; //設(shè)置為離線(xiàn)
}
}
});
}
public function onMessage(TcpConnection $connection, $data)
{
//處理數(shù)據(jù)完成后記錄上次收到消息的時(shí)間
$connection->lastMessageTime = time();
//設(shè)置為在線(xiàn)
$connection->onLine = 1;
}
}
你好,我在Events里面使用Timer定時(shí)器,通過(guò)use \Workerman\Timer;引用,但是提示找不到該文件,我使用的是Gatewayworker,請(qǐng)問(wèn)你知道這是什么原因嗎
你應(yīng)該先看看有沒(méi)有安裝workerman依賴(lài) composer require workerman/workerman
,http://wtbis.cn/doc/workerman/install/install.html 說(shuō)明文檔有寫(xiě)。如果還是沒(méi)有解決問(wèn)題的話(huà)可以發(fā)一下代碼嘗試讓大家看看并解決其問(wèn)題