本次绿色建筑开发主要是对传感器的接入和数据处理:
传感器包括:风速、风向、温度、tvoc、二氧化碳、一氧化碳、PM0.3到PM100、光照,风力,危险气体等二十多种传感器进行接入
通信方式: 各个传感器使用5G模块,将信息通过TCP的方式传给服务端,modbos协议
过程
- 服务端在接收到数据后第一步进行CRC校验,验证数据的正确性
- 将16进制数据进行解析
- 解析后的数据分成两路,一路通过websocket发送给客户端用于显示实时数据,另外一路则进行数据库入库处理
代码附上
<?php
namespace app\worker\controller;
use GatewayClient\GatewayProtocol;
use think\worker\Server;
use GatewayClient\Gateway;
use Workerman\Connection\AsyncTcpConnection;
use Workerman\Lib\Timer;
use Workerman\Protocols\Ws;
date_default_timezone_set("PRC");
class Worker extends Server
{
protected $socket = 'tcp://0.0.0.0:25001';
protected $processes = 1;
public $ws_server;
protected static $heartbeat_time = 30;
/**
* 收到信息
* @param $connection
* @param $data
*/
public function onMessage($connection, $data)
{
$connection->lastMessageTime = time();
//原始数据 16进制
$array = getBytes($data);
#十进制
$dataStr = strToHex($data);
#CRC校验码----start----
$length = strlen($dataStr); // 获取字符串长度
$subStrLength = $length - 4; // 计算需要截取的子字符串长度(不包括最后4位)
$crc16_str = substr($dataStr, 0, $subStrLength); // 使用substr函数进行截取操作
$crc16_end= substr($dataStr,-4);
$crc16_str_pack = pack('H*',$crc16_str);
$crc16_str_pack_t = crc16($crc16_str_pack);
$crc16_str_crc16=unpack("H*",$crc16_str_pack_t);
$crc16_end_cc = $crc16_str_crc16[1];//CRC校验码
dump_log('收到消息了:'.json_encode($dataStr));
dump_log('CRC校验码:'.json_encode($crc16_end_cc));
#十六进制数组
$array_16 = strToArray($dataStr);
$device_id = substr($dataStr,0,2);
$ws_data = '';
#空气检测传感器 --已完成
if ($array_16 && (hexdec($crc16_end) == hexdec($crc16_end_cc))){
#序号---预留的参数
$number = $array_16[0];
$ch4 = hexdec($array_16[1]).hexdec($array_16[2]);
$co = hexdec($array_16[3]).hexdec($array_16[4]);
$o2 = hexdec($array_16[5]).hexdec($array_16[6]);
$h2s = hexdec($array_16[7]).hexdec($array_16[8]);
#温度数据
$temperature = hexdec($array_16[9] . $array_16[10]);
#湿度数据
$humidity = hexdec($array_16[11] . $array_16[12]);
#pm2.5
$pm2_5 = hexdec($array_16[13] . $array_16[14]);
#pm10
$pm10 = hexdec($array_16[15] . $array_16[16]);
$gas_data = $ws_data = [
'ch4' => $ch4,
'co' => $co,
'o2' => $o2,
'h2s' => $h2s,
'temperature' => $temperature,
'humidity' => $humidity,
'pm2_5' => $pm2_5,
'pm10' => $pm10
];
Workerbase::data_db($gas_data, $device_id);
}elseif ($array_16 && (hexdec($crc16_end)!= hexdec($crc16_end_cc))){
dump_log('CRC校验码错误');
}else{
dump_log('数据格式错误');
}
#转发websocket数据
if ($ws_data){
$ws_arr = [
'code' => 1,
'msg' => 'ok',
'time' => time(),
'data' => $ws_data
];
$this->ws_server->send(json_encode($ws_arr, 256) . "\r\n");
dump_log("转发websocket成功!");
}
#回复消息
$connection->lastMessageTime = time();
$connection->send(json_encode('获得成功'));
}
/**
* 当连接建立时触发的回调函数
* @param $connection
*/
public function onConnect($connection)
{
dump_log("连接 建立" . $connection->getRemoteIp() . ":". $connection->getRemotePort());
$connection->send(json_encode('connect success'));
}
/**
* 当连接断开时触发的回调函数
* @param $connection
*/
public function onClose($connection)
{
dump_log("连接 关闭");
#断线1秒后重新连接
$connection->reConnect(1);
}
/**
* 当客户端的连接上发生错误时触发
* @param $connection
* @param $code
* @param $msg
*/
public function onError($connection, $code, $msg)
{
dump_log("错误: $code $msg");
}
/**
* 每个进程启动
* @param $worker
*/
public function onWorkerStart($worker)
{
dump_log("TCP服务启动了");
// 以websocket协议连接远程websocket服务器
// $ws_connection = new AsyncTcpConnection("ws://127.0.0.1:22001");
$ws_connection = new AsyncTcpConnection("ws://域名或IP:22001");
$ws_connection->transport = 'ssl';
// $ws_connection->websocketClientProtocol = 'binary';
// 每隔55秒向服务端发送一个opcode为0x9的websocket心跳(可选)
$ws_connection->websocketPingInterval = 30;
// 远程websocket服务器发来消息时
$ws_connection->onMessage = function($connection, $data){
dump_log("来自websocket服务器的消息: $data");
};
// 连接上发生错误时,一般是连接远程websocket服务器失败错误(可选)
$ws_connection->onError = function($connection, $code, $msg){
dump_log("错误: $msg");
};
// 当连接远程websocket服务器的连接断开时(可选,建议加上重连)
$ws_connection->onClose = function($connection){
dump_log("连接已关闭并尝试重新连接");
// 如果连接断开,1秒后重连
$connection->reConnect(1);
};
// 设置好以上各种回调后,执行连接操作
$ws_connection->connect();
$this->ws_server = $ws_connection;
Timer::add(30, function()use($ws_connection){
$ws_connection->send('来自tcp客户端的心跳:heartbeat---');
});
}
/**
* 重启进程
* @param $worker
* @return void
*/
public function onWorkerReload($worker)
{
foreach($worker->connections as $connection)
{
$connection->send('worker reloading');
}
}
}
😊😊😊抱拳