gatewayworker如何实现硬件设备tcp与浏览器websocket互相通讯

敖德萨

8752 8 15
8个回答

taozywu

@敖德萨
1)用户端建立websocket通信
2)硬件端建立tcp通信
3)通过$_SERVER['REMOTE_PORT']和$_SERVER['REMOTE_ADDR']来区分过来的数据
4)每个端数据中传一个相同参数作为互推依据。

  • 暂无评论
敖德萨

可以给个具体方案吗?你说通过$_SERVER['REMOTE_PORT']和$_SERVER['REMOTE_ADDR']来区分发过来的数据 那么问题来了 我在哪里接收?onmessge? onmessge怎样接收tcp协议发过来的数据?这个也是现在困扰我的问题 所以你说了这么多 我还没看到有希望的信息 能给个具体的信息吗

  • 敖德萨 2020-07-30

    @7269: 我没有用walkor给我的方法 因为我写完了walkor才给上面的方法 我也还没有去验证 不过我的方法我已经分享到workerman官方10群里了

  • workerstar 2020-08-11

    用户(13969)在手机上发送指令(02 03 05 d5 aa 52 d5)给服务器,通过服务器再发送给dtu设备,dtu设备(2002)向服务器返回一个指令(02 03 05 d5 aa 52 d5),服务器收到指令后,我想通过sendtouid()发送给用户,告知用户设备正常可以使用。可是用户的uid我没法获取。这个你怎么处理的?

  • 敖德萨 2020-08-11

    @7269:你不是已经都互通了嘛 你只需要查表发送即可啊

  • workerstar 2020-08-11

    @7040:谢谢你的回复,查表的确可以。

walkor 打赏

GatewayWorker所有的数据通过Events.php里的onMessage来接收。

gatewayWorker支持多协议,如果增加一个协议只需要开一个端口设置对应的端口参数及协议即可。协议层对于开发者来说是透明的。也就是说调用所有的gatewayWorker 的 Gateway::XXX(如Gateway::bindUid Gateway::sendToUid)接口时,不需要考虑对应客户端是什么协议,直接调用即可。

如何设置多个协议,参考http://doc2.workerman.net/multi-protocols.html

现在假设你设置了tcp协议和websocket协议。那么整个系统代码及流程类似这样

1)、硬件客户端通过tcp向GatewayWorker发送一个数据包,包中包含了{请求类型:设备绑定, 设备id:设备具体id}(数据格式任意,这里是一个示意),GatewayWorker收到数据后,Events.php里的onMessage接收整个数据,发现是设备绑定类型,然后调用Gateway::bindUid($client_id, '具体的设备id');,这样就将设备于具体的设备id绑定了,在Events.php中调用Gateway::sendToUid('具体的设备id', '数据');就可以给这个设备发数据了。

2)、同样的用户端通过websocket发起连接,然后发送一个{请求类型:用户绑定, 用户id:用户具体id}请求给GatewayWorker,Events.php里的onMessage接收整个数据,发现是用户绑定类型,然后调用Gateway::bindUid($client_id, '具体的用户id');,这样就将用户端与具体的用户id绑定了,在Events.php中调用Gateway::sendToUid('具体用户id', '数据');就可以给这个用户发数据了。

假设你上面的设备及用户绑定已经做好,现在说说你的图中1 2 3 4 5 6的代码及流程
1、设备发起tcp请求
假设请求数据格式为 {type: getData}

2、GatewayWorker收到tcp请求后返回该设备相关数据
给当前设备返回数据,直接调用 Gateway::sendToClient($client_id, '数据');即可。

3、用户通过websocket发送开关指令
假设数据格式为 {type: opertation, operation: close, device_id:具体设备id}

4、服务端收到指令后发给设备
Events.php里onMessage里利用Gateway::sendToUid(具体设备id, '设备能识别的关闭数据');给对应设备发送操作

5、设备返回成功或失败
数据包假设格式为{type: opertation_result, result: success},同样的Events.php里onMessage里接收这个数据

6、将成功或者失败结果转发给用户
Events.php里onMessage里利用Gateway::sendToUid(具体用户id, '结果数据');给对应的用户id

总的来说Events.php里代码类似这样。
假设设备和用户发来的数据都是json数据,代码类似这样

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']);
                // 通过数据库或则某种方式查询出当前设备属于哪个用户,并记录到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 = '结果数据'; //  这里假设获得了结果
                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'];
                // 给这个用户发送结果
                Gateway::sendToUid($uiser_id, "{type: opertation_result, result: success}");
                break;
        }
    }
}
  • workerstar 2020-08-11

    你好,你说:硬件客户端通过tcp向GatewayWorker发送一个数据包,包中包含了{请求类型:设备绑定, 设备id:设备具体id}(数据格式任意,这里是一个示意)。用户(13969)在手机上发送指令(02 03 05 d5 aa 52 d5)给服务器,通过服务器再发送给dtu设备,dtu设备(2002)向服务器返回一个指令(02 03 05 d5 aa 52 d5),服务器收到指令后,我想通过sendtouid()发送给用户,告知用户设备正常可以使用。可是用户的uid我没法获取。这个你怎么处理的?

  • 10bang 2022-04-08

  • oscar 2022-04-20

    不得不佩服 @walkor 在问答这方面确实做得太好了!解答很清楚,甚至有时直接给出代码。今天也开始从swoole转入webman了!上手快!有点相见恨晚的感觉!

  • Tinywan 2022-04-20

    欢迎━(`∀´)ノ亻!

  • zjcyjj 2022-04-22

    老大威武 人狠话又多 注释也多

  • liziyu 2022-04-22

    收藏了,说不定哪天就用上了。

敖德萨

好的谢谢 已经解决了 谢谢提供思路和解法

  • 暂无评论
yeeser

您好,您的思路和解法可以给我发一份吗?谢谢

敖德萨

@walkor大佬已经给了解决的方法了 业务在Events.php中处理即可 这没有什么逻辑思路的

  • 暂无评论
diyya

本人也有硬件与用户的通讯操作,提供参考:
数据还是用redis+mysql的形式(websocket仅仅作为转发,请求全部走http)
采用先http后websocket的方式,由http先对访问进行先认证后返回带有websocket连接参数的页面(连接websocket的信息包含uid在内的一切),认证不成立不返回websocket的页面。
这样方式用起来比较爽,回归传统的http收到请求,处理后通过GatewayWorker的websocket进行通知,避免了三方操作

  • oscar 2022-04-21

    下午刚看到一个聊天程序,就是这种思路的,websocket就相当于发布命令一样,要干什么,你http按命令去执行就可以了。

= - =

楼主,你看看 https://github.com/mouyong/laravel-octane-workerman 的截图。里边直接是给了完成通讯的截图示例。

在 laravel 项目引入后,配置好相关端口。通过一行命令让他们具备通讯支持。 php artisan workerman:gateway

然后按照老大的说明,直接玩就可以了。

tcp - api -websocket 三方通讯

  • 暂无评论
年代过于久远,无法发表回答
×
🔝