当前位置: 首页 > news >正文

初出茅庐的小李博客之使用立创开发板(ESP32)连接到EMQX Platform【MQTT TLS/SSL 端口连接】

介绍

手上有一块立创开发板,本着不吃灰的原则把它用起来,今天就来用它来连接上自己部署的MQTT服务器进行数据通信。

硬件:立创开发板
开发环境:Arduino IDE Win11
MQTT 平台:EMQX Platform

在这里插入图片描述

立创开发板介绍:

初出茅庐的小李博客之立创开发板初体验【Arduino IDE开发环境】:
地址:https://blog.csdn.net/weixin_43176183/article/details/139101412?spm=1001.2014.3001.5501

MQTT.fx客户端接入EMQX Platform

初出茅庐的小李博客之MQTT.fx客户端接入EMQX Platform
地址:https://blog.csdn.net/weixin_43176183/article/details/139190727?spm=1001.2014.3001.5501

参考文档:
https://docs.emqx.com/zh/cloud/latest/connect_to_deployments/esp32.html

过程记录:

安装MQTT依赖库

在 Arduino IDE 中完成以下安装。
先安装 ESP32 开发板。
点击工具 -> 开发板 -> 开发板管理。搜索 ESP32,点击安装 我已经安装过。
安装 PubSub client 库
点击项目 -> 加载库 -> 管理库…。搜索 PubSubClient,安装 PubSubClient by Nick O’Leary。
通过 TCP 端口连接
在这里插入图片描述

写代码

  • 引入对应的库

#include "WiFi.h"
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
  • 定义用户自定义参数

// WiFi Credentials
const char *ssid     = "AQST";             // Replace with your WiFi name
const char *password = "12345678";         // Replace with your WiFi password// MQTT Broker Settings
const char *mqtt_broker   = "xxxxxx.ala.cn-hangzhou.emqxsl.cn";//这里定义自己的连接地址
const char *mqtt_topic    = "emqx/esp32";
const char *mqtt_username = "AQ";
const char *mqtt_password = "123456";
const int   mqtt_port     = 8883;
  • 编写连接代码【准确的来说叫改写】
/连接Wifi热点函数
void ConnectToWiFi(void) 
{WiFi.begin(ssid, password);Serial.print("Connecting to WiFi");while (WiFi.status() != WL_CONNECTED){delay(500);Serial.print(".");}Serial.println("\nConnected to WiFi");
}
//连接MQTT代理函数
void ConnectToMQTT(void) 
{while (!mqtt_client.connected()){String client_id = "esp32-client-" + String(WiFi.macAddress());Serial.printf("Connecting to MQTT Broker as %s...\n", client_id.c_str());if(mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {Serial.println("Connected to MQTT broker");mqtt_client.subscribe(mqtt_topic);mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 by Arduino IED ^^");  // Publish message upon connection}else {Serial.print("Failed to connect to MQTT broker, rc=");Serial.print(mqtt_client.state());Serial.println(" Retrying in 5 seconds.");delay(5000);}}
}
//MQTT 回调函数
void MqttCallback(char *topic, byte *payload, unsigned int length)
{Serial.print("Message received on topic: ");Serial.println(topic);Serial.print("Message: ");for (unsigned int i = 0; i < length; i++) {Serial.print((char) payload[i]);//打印有效载荷的信息}Serial.println("\n-----------------------");
}
  • 函数调用

void setup(void)
{Serial.begin(115200);                         //设置串口参数ConnectToWiFi();                              //连接Wifi热点// Set Root CA certificateespClient.setCACert(ca_cert);                 //设置CA证书mqtt_client.setServer(mqtt_broker, mqtt_port);//指定代理 指定端口mqtt_client.setKeepAlive(60);                 //保活时间mqtt_client.setCallback(MqttCallback);        //回调函数ConnectToMQTT();                              //连接MQTT 代理}void loop(void) 
{if (!mqtt_client.connected()) {ConnectToMQTT();}mqtt_client.loop();
}

特别提示:这里的地址要写自己的地址 CA证书也要用自己的证书 否则连不上

官方原话:
添加服务端证书。如果您在使用公共 MQTT Broker、Serverless 部署或基础版部署的 TLS/SSL 端口连接,在此下载 CA 证书。 如您使用专业版 / BYOC 部署的 TLS/SSL 端口连接,请使用自己的服务端证书。

  • 开启MQTT服务器
    在这里插入图片描述

  • 编译烧录代码

在这里插入图片描述

用MQTT.fx连接到MQTT服务器跟ESP32开发板进行通信

发布消息:

在这里插入图片描述

ESP32收到订阅消息

在这里插入图片描述
这里可以看到开发板收到了消息 但是客户端提示收到的消息不是标准json
在这里插入图片描述
改进一下发送的数据格式

{"mag": "This is Json Data"
}

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

总结:

利用Arduino IED 进行MQTT通信 确实很方便,很容易就能实现两个设备的交互、但是使用库的缺点也很明显 有很多api不太懂它的意思,还需要进一步研究。

完整代码


#include "WiFi.h"
#include <PubSubClient.h>
#include <WiFiClientSecure.h>// WiFi Credentials
const char *ssid     = "AQST";             // Replace with your WiFi name
const char *password = "12345678";         // Replace with your WiFi password// MQTT Broker Settings
const char *mqtt_broker   = "xxxxxxx.ala.cn-hangzhou.emqxsl.cn";//这里要改成自己的地址!!!!
const char *mqtt_topic    = "emqx/esp32";
const char *mqtt_username = "AQ";
const char *mqtt_password = "123456";
const int   mqtt_port     = 8883;WiFiClientSecure espClient;
PubSubClient mqtt_client(espClient);void ConnectToWiFi(void);//函数声明
void ConnectToMQTT(void);//函数声明
void MqttCallback(char *mqtt_topic, byte *payload, unsigned int length);//函数声明const char *ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
)EOF";void setup(void)
{Serial.begin(115200);                         //设置串口参数ConnectToWiFi();                              //连接Wifi热点// Set Root CA certificateespClient.setCACert(ca_cert);                 //设置CA证书mqtt_client.setServer(mqtt_broker, mqtt_port);//指定代理 指定端口mqtt_client.setKeepAlive(60);                 //保活时间mqtt_client.setCallback(MqttCallback);        //回调函数ConnectToMQTT();                              //连接MQTT 代理}//连接Wifi热点函数
void ConnectToWiFi(void) 
{WiFi.begin(ssid, password);Serial.print("Connecting to WiFi");while (WiFi.status() != WL_CONNECTED){delay(500);Serial.print(".");}Serial.println("\nConnected to WiFi");
}
//连接MQTT代理函数
void ConnectToMQTT(void) 
{while (!mqtt_client.connected()){String client_id = "esp32-client-" + String(WiFi.macAddress());Serial.printf("Connecting to MQTT Broker as %s...\n", client_id.c_str());if(mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {Serial.println("Connected to MQTT broker");mqtt_client.subscribe(mqtt_topic);mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 by Arduino IED ^^");  // Publish message upon connection}else {Serial.print("Failed to connect to MQTT broker, rc=");Serial.print(mqtt_client.state());Serial.println(" Retrying in 5 seconds.");delay(5000);}}
}
//MQTT 回调函数
void MqttCallback(char *topic, byte *payload, unsigned int length)
{Serial.print("Message received on topic: ");Serial.println(topic);Serial.print("Message: ");for (unsigned int i = 0; i < length; i++) {Serial.print((char) payload[i]);//打印有效载荷的信息}Serial.println("\n-----------------------");
}void loop(void) 
{if (!mqtt_client.connected()) {ConnectToMQTT();}mqtt_client.loop();
}// WiFiClient espClient;
// PubSubClient mqtt_client(espClient);// void setup(void) 
// {
//   Serial.begin(115200);
//   ConnectToWiFi(); //连接指定热点
//   //mqtt_client.setServer(mqtt_broker, mqtt_port);
//   espClient.setCACert(ca_cert);
//   mqtt_client.setKeepAlive(60);
//   mqtt_client.setCallback(MqttCallback); // Corrected callback function name
//   ConnectToMQTT();
// }// void loop(void) 
// {
//   if (!mqtt_client.connected()) 
//   {
//     ConnectToMQTT();
//   }
//   mqtt_client.loop();
// }//用户自定义函数
// void ConnectToWiFi(void) 
// {
//     WiFi.begin(ssid, password);
//     Serial.print("Connecting to WiFi");
//     while (WiFi.status() != WL_CONNECTED) 
//     {
//         delay(500);
//         Serial.print(".");
//     }
//     Serial.println("\nConnected to WiFi");
// }
// //用户自定义函数
// void ConnectToMQTT(void) 
// {
//   while (!mqtt_client.connected()) 
//   {
//     String client_id = "esp32-client-" + String(WiFi.macAddress());//     Serial.printf("Connecting to MQTT Broker as %s.....\n", client_id.c_str());//     if (mqtt_client.connect(client_id.c_str(), mqtt_username, mqtt_password))
//     {
//       Serial.println("Connected to MQTT broker");
//       mqtt_client.subscribe(mqtt_topic);
//       mqtt_client.publish(mqtt_topic, "Hi EMQX I'm ESP32 ^^"); // Publish message upon successful connection
//     }
//     else 
//     {
//       Serial.print("Failed, rc=");
//       Serial.print(mqtt_client.state());
//       Serial.println(" try again in 5 seconds");
//       delay(5000);
//     }
//   }
// }//用户自定义回调函数
// void MqttCallback(char *mqtt_topic, byte *payload, unsigned int length)
// {
//   Serial.print("Message received on mqtt_topic: ");
//   Serial.println(mqtt_topic);
//   Serial.print("Message: ");
//   for (unsigned int i = 0; i < length; i++) 
//   {
//     Serial.print((char) payload[i]);
//   }
//   Serial.println("\n-----------------------");
// }

视频:

https://www.bilibili.com/video/BV1gJ4m1A7bg/?pop_share=1

相关文章:

初出茅庐的小李博客之使用立创开发板(ESP32)连接到EMQX Platform【MQTT TLS/SSL 端口连接】

介绍 手上有一块立创开发板&#xff0c;本着不吃灰的原则把它用起来&#xff0c;今天就来用它来连接上自己部署的MQTT服务器进行数据通信。 硬件&#xff1a;立创开发板 开发环境&#xff1a;Arduino IDE Win11 MQTT 平台&#xff1a;EMQX Platform 立创开发板介绍&#xff1…...

js平滑滚动元素使其可见

直接上重点&#xff1a; let xpath "//*/div[idxxx]"; document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.scrollIntoView({ behavior: "smooth"})这段代码是JavaScript中使用XPath查询文档并执行平…...

TP6 事件绑定、监听、订阅

事件绑定与监听 命令行生成事件类 php think make:event EventDemo 命令行生成事件监听类php think make:listener ListenerDemo 事件类可作为保存与事件相关信息的容器,如没有额外需求可以不需要定义 事件系统的所有操作都通过think\facade\Event类进行静态调用 当定义…...

SpringCloud Gateway中Filters详细说明

前面 https://blog.csdn.net/J080624/article/details/139494909 我们研究了GateWay中各种路由断言的使用。SpringCloud GateWay 还提供了各种过滤器用来对请求和响应进行处理。 官网地址&#xff1a;SpringCloud Gateway Filter 【1】GatewayFilter Factories 路由过滤器允…...

力扣2156.查找给定哈希值的子串

力扣2156.查找给定哈希值的子串 rolling hash&#xff1a;求带权的值 左边是高位 右边是低位 本题要求左边低位 只要反向求即可 class Solution {public:string subStrHash(string s, int power, int modulo, int k, int hashValue) {int n s.size();long long M modulo,p…...

推荐低成本低功耗的纯数字现场可重构IC

CPLD采用CMOS EPROM、EEPROM、快闪存储器和SRAM等编程技术&#xff0c;从而构成了高密度、高速度和低功耗的可编程逻辑器件。 RAMSUN提供的型号LS98003是通用可配置的数字逻辑芯片&#xff0c;有体积小、超低功耗和高可靠性等特点。客户可以根据自己的功能需求设计芯片&#x…...

解决change事件与blur事件互不影响

<template><div style"margin-top: 40px"><el-selectv-model"form.name"placeholder"请选择名称"clearablefilterableref"selectName"allow-createblur"nameBlur($event)"visible-change"visibleNameCh…...

后端开发面经系列 -- 同程旅行C++一面

同程旅行C一面 公众号&#xff1a;阿Q技术站 文章目录 同程旅行C一面1、sizeof与strlen的区别&#xff1f;2、运算符和函数有什么区别&#xff1f;3、new和malloc&#xff1f;4、内存泄漏与规避方法&#xff1f;5、悬空指针与野指针&#xff1f;6、手撕冒泡排序&#xff1f;7、…...

推荐几个开源的c#的工作流引擎组件

以下是一个.NET Core领域可以推荐使用的流程引擎的表格&#xff1a; 名称 生产厂家 下载地址 支持二开 独立部署 ccflow 济南驰骋信息技术有限公司 https://gitee.com/opencc 是 是 Elsa Elsa Workflows GitHub - elsa-workflows/elsa-core: A .NET workflows li…...

视频汇聚EasyCVR视频监控云平台对接GA/T 1400视图库对象和对象集合XMLSchema描述

GA/T 1400协议主要应用于公安系统的视频图像信息应用系统&#xff0c;如警务综合平台、治安防控系统、交通管理系统等。在城市的治安监控、交通管理、案件侦查等方面&#xff0c;GA/T 1400协议都发挥着重要作用。 以视频汇聚EasyCVR视频监控资源管理平台为例&#xff0c;该平台…...

【JavaScript脚本宇宙】瞬息万变:探索实时Web应用的JavaScript库

鸟瞰实时Web开发&#xff1a;JavaScript库大比拼 前言 随着Web应用程序的发展&#xff0c;实时通讯已成为一个重要的需求。本篇文章将探索六个关键的JavaScript库&#xff0c;这些库为我们提供助力&#xff0c;使得实时Web应用程序的创建成为可能。 欢迎订阅专栏&#xff1a;…...

Java数据结构与算法(有向无环图)

前言 有向无环图&#xff08;Directed Graph&#xff09;是在有向图的基础上&#xff0c;增加无环的检查。 实现原理 使用邻接表表示法实现有向图相对简单明了&#xff0c;步骤也相对简单。 1:首先创建有向图 2.创建顶点 3.顶点间创建边 4.创建边的过程中检查节点是否存…...

QuanTA: 一种新的高秩高效微调范式

QuanTA方法的核心是利用张量操作来模拟量子电路中的门操作。这些张量被设计为仅在特定的轴上应用&#xff0c;类似于量子电路中的单量子比特或双量子比特门。通过这种方式&#xff0c;QuanTA能够以高秩参数化来适应LLMs的权重矩阵。 网址&#xff1a;QuanTA: 一种新的高秩高效微…...

【漏洞复现】用友NC downCourseWare 任意文件读取漏洞

0x01 产品简介 用友NC是一款企业级ERP软件。作为一种信息化管理工具&#xff0c;用友NC提供了一系列业务管理模块&#xff0c;包括财务会计、采购管理、销售管理、物料管理、生产计划和人力资源管理等&#xff0c;帮助企业实现数字化转型和高效管理。 0x02 漏洞概述 用友NC …...

度安讲 | 第二期「安全左移·业务护航」技术沙龙成功举办

当下&#xff0c;“安全左移”作为落地DevSecOps的重要实践之一&#xff0c;已在业界达成共识。DevSecOps作为一种集开发、安全、运维于一体的软件开发和运营模式&#xff0c;强调在敏捷交付下&#xff0c;“安全”在软件开发生命周期的全覆盖贯穿和核心位置。所谓“安全左移”…...

代码片段 | Matlab三维图显示[ R T 0 1] 的最佳方法

% 输入N组RT矩阵 N 4; R zeros(3, 3, N); T zeros(3, N); R(:,:,1) [-0.902608 0.250129 0.350335 ; 0.314198 0.939127 0.138996 ;-0.294242 0.235533 -0.926253 ]; T(:,1) [205.877;2796.02; 907.116];R(:,:,2) [-0.123936 0.643885 0.755018 ;0.816604 0.464468 -0.26…...

2024百度之星 跑步

原题链接&#xff1a;码题集OJ-跑步 题目大意&#xff1a;一个n个人在绕圈跑&#xff0c;第i个人跑一圈的时间是i分钟&#xff0c;每二个人位置相同就会打一次招呼&#xff0c;如果同时来到终点&#xff0c;他们就会停下来&#xff0c;请问会打多少次招呼&#xff1f; 思路&a…...

【git】TortoiseGitPlink Fatal Error 解决方法

背景 使用 TortoiseGit报错&#xff1a; TortoiseGitPlink Fatal Error No supported authentication methods available (server sent: publickey) 解决方法 1、有很多是重置git的秘钥解决的 2、重置ssh工具...

行心科技|中科利众:健康科技新合作,营养与科技融合前行

2024中国国际大健康产业文化节暨第34届国际大健康产业交易博览会于2024年5月31日在保利世贸博览馆盛大开幕&#xff0c;行心科技与中科利众&#xff08;贵州&#xff09;生物科技有限公司不谋而合&#xff0c;就“膳食机能健康问题解决方案”达成战略合作&#xff0c;共同开启膳…...

Xcode 打包报错Command PhaseScriptExecution failed with a nonzero exit code

解决办法: 1、在Xcode项目中 Pods -> Targets Support Files -> Pods-项目名 -> Pods-项目名-frameworks 中(大约在第44行) 加上 -f 2、CocoaPods版本太旧了,可以尝试升级CocoaPods版本 使用sudo gem update cocoapods更新cocoapods&#xff0c;问题将在1.12.1版本已…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

【决胜公务员考试】求职OMG——见面课测验1

2025最新版&#xff01;&#xff01;&#xff01;6.8截至答题&#xff0c;大家注意呀&#xff01; 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:&#xff08; B &#xff09; A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...