workerman中,如果发送的两次modbus tcp连接需要一定的间隔时间,怎么办?

bobshipwood

问题描述

业务需要定时去PLC获取数据,为此我在一个进程内,定义了多个定时器


foreach ($devicePlcs as $devicePlc) {
            // 如果不存在,则表示新增,需创建timer数组
            if (!isset($this->timers[$devicePlc->id])) {
                $timer_id = Timer::add($this->execute, function() use ($devicePlc) {
                    $this->executeDeviceTask2($devicePlc); // 执行实际业务代码;
                });
                $this->timers[$devicePlc->id] = ['timer_id' => $timer_id]; // 往timers数组设置该key
            }
        }

然后这是我的业务代码,在$new和$totalCount之间需要有间隔100ms的延迟,这是PLC本身的机制所决定的。
但是如果加入了sleep(1)的话,他理论上是n个sleep(1)同时阻碍着进程的,有啥好的方案?

protected function executeDeviceTask2($devicePlc)
    {
        // 提取旧值
        if (empty($devicePlc->params)) {
            // notthing to do
        } else {
            $old = $devicePlc->params;
        }
        $connection =  BinaryStreamConnection::getBuilder()->setPort(502)->setHost($devicePlc->ip)->setConnectTimeoutSec(2.5)->setWriteTimeoutSec(0.5)->setReadTimeoutSec(1.5)->build();

        $new = $this->readHoldingRegisters($connection, $devicePlc, 25,  1, 1);
        $totalCount = $this->readHoldingRegisters($connection, $devicePlc, 400, 2, 0); // 累计计数
        var_dump($new, $totalCount);
    }

为此你搜索到了哪些方案及不适用的原因

百度无果

112 1 0
1个回答

北月妖王

再来一次 Timer,相当于将 Timer 作为异步队列来用,但如果定时器里的业务很慢,会影响当前进程处理其它请求。

Timer::add(0.1, function () use ($connection, $devicePlc, $new) {
    $totalCount = $this->readHoldingRegisters($connection, $devicePlc, 400, 2, 0);
    var_dump($new, $totalCount);
}, [], false);
  • bobshipwood 1天前

    嗯嗯,有没有更好的方法呢,

  • bobshipwood 15小时前

    另外,如果totalcount要放在timer这个函数外面去使用呢?
    要怎么用它?

  • bobshipwood 14小时前

    比方说有没有协程的方法?

  • 北月妖王 13小时前

    可以直接把整个方法用协程包裹,协程内部可以直接使用 Timer::sleep ,这样子代码看起来更直观了

    Coroutine::create(function() use($devicePlc)){
    // 提取旧值
    if (empty($devicePlc->params)) {
    // notthing to do
    } else {
    $old = $devicePlc->params;
    }
    $connection = BinaryStreamConnection::getBuilder()->setPort(502)->setHost($devicePlc->ip)->setConnectTimeoutSec(2.5)->setWriteTimeoutSec(0.5)->setReadTimeoutSec(1.5)->build();
    $new = $this->readHoldingRegisters($connection, $devicePlc, 25, 1, 1);
    Timer::sleep(0.1);
    $totalCount = $this->readHoldingRegisters($connection, $devicePlc, 400, 2, 0); // 累计计数
    var_dump($new, $totalCount);
    });

  • bobshipwood 13小时前

    谢谢,我正在看协程的部分。

🔝