TcpServer+SocketServer+EMQTT组合,实现基础设备控制

大家好,我是小智。

今天,我们结合前面的文章内容,进行一个简单的物联应用。

在物联网中最简单直接的应用就远程开关电灯,今天小智将为大家一一讲述。

 

 智能灯控

本文用到的技术和工具都相对简单,在阅读本文时,建议没有关注小智往期文章的朋友回头去看看,对前面的一些知识有所了解。

物联网通讯之Swoole创建Websocket服务器,一切从简单开始

物联网之实时通讯,使用WorkerMan创建websocket服务器 

物联网通讯之Swoole创建TCP服务器,并与调试工具进行通讯 

云端服务控制485继电器开关电灯 

回顾完全文后,正式进入主题。

一、设计一个简单实用的架构

 系统架构

从上图可以看出,云端需要建立三个服务,分别是:tcp服务、mqtt服务、websocket服务。

线下需要准备串口服务器(tcp转485)、485硬件(继电器)。

控制端则可以是浏览或者App,当然小程序也可以,只要支持websocket的客户端都行。

二、服务器搭建

我们将用上一期学到的swoole建立websocket服务器应用到这里,做到真正的学以致用。然后在这个基础上,再建立一个tcp服务器。

代码相当简单,暂不考虑安全性,稳定性等方面(这些需要大家自己深入,小智只能把朋友们带进门)。

下面是详细代码:

tcpserver.php

<?php

use TrytoMqtt\Client;
require_once __DIR__ . '/vendor/autoload.php';

$device_maps = [];

//创建Server对象,监听 localhost:39001端口
$serv = new Swoole\Server("localhost", 39001);
$options = [
 'clean_session' => false,
 'client_id' => 'demo-tcpserver-123456',
 'username' => '',
 'password' => '',
];

$mqtt = new Client('localhost', 1883, $options);

$serv->on('WorkerStart', function ($serv, $worker_id) use ($mqtt) {
 echo "tcp worker start\r\n";
 $mqtt->onConnect = function ($mqtt) {
 $mqtt->subscribe('/websocket485');
 };
 $mqtt->onMessage = function ($topic, $content) use ($serv) {
 global $device_maps;
 var_dump($device_maps);
 echo date('Y-m-d H:i:s') . "Mqtt Receive=================================\r\n";
 var_dump($topic, $content);
 $json = json_decode($content, true);
 var_dump($json);
 if (isset($device_maps[$json['device']])) {
 var_dump($json['msg']);
 $data = json_decode($json['msg'], true);
 echo "send instruction \n";
 $serv->send($device_maps[$json['device']]['fd'], hex2bin(str_replace(' ', '', $data['instruction'])));
 }
 };
 $mqtt->onError = function ($exception) use ($mqtt) {
 echo "error\n";
 };
 $mqtt->onClose = function () {
 echo "close\n";
 };
 $mqtt->connect();
});

//监听连接进入事件
$serv->on('Connect', function ($serv, $fd) {
 echo "Client: Connect.\n";
});

//监听数据接收事件
$serv->on('Receive', function ($serv, $fd, $from_id, $msg) use ($mqtt) {
 global $device_maps;
 var_dump($device_maps);
 echo date('Y-m-d H:i:s') . "=================================\r\n";
 $json = json_decode($msg, true);
 var_dump($json);

 //todo已经注册的TCP串口服务器,不能再注册
 if (is_array($json) && isset($json['reg'])) {
 if (!isset($device_maps[$json['reg']])) {
 $device_maps[$json['reg']] = ['device' => $json['reg'], 'fd' => $fd];
 echo "device register done";
 } else {
 echo "device has been registered";
 }
 } else {
 if (!is_array($json)) {
 foreach ($device_maps as $map) {
 if ($map['fd'] == $fd) {
 var_dump($map);
 $msg = json_encode(['device' => $map['device'], 'msg' => bin2hex($msg)]);
 break;
 }
 }
 }
 }
 $mqtt->publish('/tcp485', $msg);
});

//监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
 echo "Client: Close.\n";
 global $device_maps;
 foreach ($device_maps as $key => $map) {
 if ($map['fd'] == $fd) {
 unset($device_maps[$key]);
 echo "remove " . $key;
 break;
 }
 }
});

//启动服务器
$serv->start(); 

websocket.php

<?php
use TrytoMqtt\Client;
require_once __DIR__ . '/vendor/autoload.php';
$socket_maps = [];
$server = new swoole_websocket_server("localhost", 39002);
$options = [
 'clean_session' => false,
 'client_id' => 'demo-websocket-123456',
 'username' => '',
 'password' => '',
];
$mqtt = new Client('localhost', 1883, $options);
$server->on('WorkerStart', function ($serv, $worker_id) use ($mqtt) {
 echo "websocket worker start\r\n";
 $mqtt->onConnect = function ($mqtt) {
 $mqtt->subscribe('/tcp485');
 };
 $mqtt->onMessage = function ($topic, $content) use ($serv) {
 global $socket_maps;
 var_dump($socket_maps);
 echo "Mqtt=================================" . date('Y-m-d H:i:s') . "\r\n";
 var_dump($topic, $content);
 $json = json_decode($content, true);
 var_dump($json);
 if (isset($socket_maps[$json['device']])) {
 var_dump($json['msg']);
 echo "response \n";
 $serv->push($socket_maps[$json['device']]['fd'], $json['msg']);
 }
 };
 $mqtt->onError = function ($exception) use ($mqtt) {
 echo "error\n";
 };
 $mqtt->onClose = function () {
 echo "close\n";
 };
 $mqtt->connect();
});
$server->on('open', function ($server, $req) {
 echo "connection open: {$req->fd}\n";
});
$server->on('message', function ($server, $frame) use ($mqtt) {
 global $socket_maps;
 echo "received tcp message: {$frame->data}" . date('Y-m-d H:i:s') . "\n";
 $server->push($frame->fd, $frame->data);
 var_dump($socket_maps);
 $json = json_decode($frame->data, true);
 var_dump($json);
 //已经注册的客户端不能再注册
 if (isset($json['reg'])) {
 if (!isset($socket_maps[$json['reg']])) {
 $socket_maps[$json['reg']] = ['device' => $json['reg'], 'fd' => $frame->fd];
 echo "websocket client register done";
 } else {
 echo "websocket client has been registered";
 }
 $msg = $frame->data;
 } else {
 foreach ($socket_maps as $map) {
 if ($map['fd'] == $frame->fd) {
 var_dump($map);
 $msg = json_encode(['device' => $map['device'], 'msg' => $frame->data]);
 break;
 }
 }
 }
 $mqtt->publish('/websocket485', $msg);
});
$server->on('close', function ($server, $fd) {
 global $socket_maps;
 echo "connection close: {$fd}\n";
 foreach ($socket_maps as $key => $map) {
 if ($map['fd'] == $fd) {
 unset($socket_maps[$key]);
 echo "remove " . $key;
 break;
 }
 }
});
$server->start();

三、调试

服务器搭建好后,接着是调试。调试只需要在服运器运行上述两个文件,具体操作请回看往期的文章,小智这里上一张动图,朋友们看看最终效果。

左边是Websocket客户端,右边是TCP客户端

从上图可以看出,Websocket客户端与TCP客户端已经能够正常通讯。

「干货」物联网实操,有人串口服务器透传控制485继电器

获取源码的朋友们可以私信小智:先关注“智云说”,然后私信小智,小智收到后会尽快回复。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智云说

你的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值