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