使用RestTemplate调用EMQX API查询MQTT客户端列表信息

news2024/9/30 21:43:54

项目中集成mqtt客户端查询功能,使用到了EMQX api-v5,具体步骤:

一、准备工作

首先在EMQX dashboard中添加API 密钥
在这里插入图片描述
填写密钥名称,点击确定,会生成API KeySecret Key,保存起来备用。
在这里插入图片描述

二、配置文件

在springboot的配置文件中添加如下配置

spring:
  # mqtt 配置
  mqtt:
    api:
      # mqtt dashboard的访问地址
      host: http://xxx.xxx.xxx.xxx:18083
      # 上图中的apiKey
      apiKey: xxxxxxxxxxxx
      # 上图中的secretKey
      secretKey: xxxxxxxxxxxx
三、后端实现

创建配置类MqttApiConfig

@Data
@Configuration
@ConfigurationProperties(prefix = "spring.mqtt.api")
public class MqttApiConfig {
    private String host;
    private String apiKey;
    private String secretKey;
}

查询参数DeviceStatusRequest

@Data
public class DeviceStatusRequest {
    private String deviceId;
    private int pageNum = 1;
    private int pageSize = 20;
}

接收参数DeviceStatusInfo

@Data
public class DeviceStatusInfo {
    private Boolean connected;
    private String node;
    private Integer port;
    private Integer keepalive;
    private String ip_address;
    private String username;
    private String created_at;
    private String clientid;
    private String connected_at;
    private Boolean clean_start;
}

创建Controller的接口

@Slf4j
@RequestMapping("/mqtt/client")
@RestController
public class ClientController extends BaseController {
	@Resource
    private MqttApiConfig mqttConfig;
    @Resource
    private RestTemplate restTemplate;

/**
     * 获取所有MQTT客户端列表
     */
    private final String GET_ALL_MQTT_CLIENTS_URL = "%s/api/v5/clients?page=%s&limit=%s&fields=clientid,username,connected,ip_address,port,keepalive,clean_start,connected_at,node,disconnected_at,created_at";

    /**
     * 获取单个MQTT客户端状态信息
     */
    private final String GET_MQTT_CLIENT_STATUS_URL = "%s/api/v5/clients?clientid=%s&fields=clientid,username,connected,ip_address,port,keepalive,clean_start,connected_at,node,disconnected_at,created_at";
    
 	/**
     * 分页查询所有MQTT客户端
     *
     * @return
     */
    @GetMapping("/all")
    public PageResult<List<DeviceStatusInfo>> getClients(DeviceStatusRequest request) {
        String deviceId = request.getDeviceId();
        String url = String.format(GET_ALL_MQTT_CLIENTS_URL, mqttConfig.getHost(), request.getPageNum(), request.getPageSize());
        if (StringUtils.isNotBlank(deviceId)) {
            url = String.format(GET_MQTT_CLIENT_STATUS_URL, mqttConfig.getHost(), deviceId);
        }
        JSONObject object = exchange(url);
        if (object != null) {
            List<DeviceStatusInfo> list = JSONArray.parseArray(object.getString("data"), DeviceStatusInfo.class);
            JSONObject meta = object.getJSONObject("meta");
            Page<DeviceStatusInfo> page = new Page<>();
            page.addAll(list);
            page.setPageNum(meta.getInteger("page"));
            page.setPageSize(meta.getInteger("limit"));
            page.setTotal(meta.getLong("count"));
            return PageResult.success(page);
        }
        return new PageResult(500, "没有查询到数据");
    }

    private JSONObject exchange(String url) {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        headers.setBasicAuth(mqttConfig.getApiKey(), mqttConfig.getSecretKey(), StandardCharsets.UTF_8);
        HttpEntity entity = new HttpEntity<>(headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
        log.info("response=>{}", response);
        if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
            String body = response.getBody();
            return JSONObject.parseObject(body);
        }
        return null;
    }
四、前端实现
<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px">
      <el-form-item label="客户端" prop="deviceId">
        <el-input
            v-model="queryParams.deviceId"
            placeholder="请输入设备id"
            clearable
            @keyup.enter.native="handleQuery"
            style="width: 160px"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-table v-loading="loading" :data="list" style="width: 100%;">
      <el-table-column label="序号" type="index" align="center"/>
      <el-table-column label="客户端ID" align="left" prop="clientid" min-width="180" :show-overflow-tooltip="true"/>
      <el-table-column label="用户名" align="center" prop="username" min-width="150" :show-overflow-tooltip="true"/>
      <el-table-column label="节点" align="left" prop="node" width="180" :show-overflow-tooltip="true"/>
      <el-table-column label="连接状态" align="center" width="120">
        <template v-slot="scope">
          <el-tag :type="scope.row.connected ? 'success' : 'danger'">{{ scope.row.connected ? '已连接' : '未连接' }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="IP地址" align="left" prop="ip_address" min-width="150" :show-overflow-tooltip="true">
        <template v-slot="scope">
          <span>{{ scope.row.ip_address}}:{{scope.row.port}}</span>
        </template>
      </el-table-column>
      <el-table-column label="心跳" align="center" prop="keepalive" width="120"/>
      <el-table-column label="清除会话" align="center" width="120">
        <template v-slot="scope">
          <el-tag>{{ scope.row.clean_start }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="会话创建时间" align="center" width="180">
        <template v-slot="scope">
          <span>{{ parseTime(scope.row.created_at) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="连接时间" align="center" width="180">
        <template v-slot="scope">
          <span>{{ parseTime(scope.row.connected_at) }}</span>
        </template>
      </el-table-column>
    </el-table>

    <pagination
        v-show="total>0"
        :total="total"
        :page.sync="queryParams.pageNum"
        :limit.sync="queryParams.pageSize"
        @pagination="getList"
    />

  </div>
</template>

<script>
import {getMqttClient} from "@/api/mqtt";

export default {
  name: "MqttClient",
  data() {
    return {
      // 遮罩层
      loading: true,
      // 总条数
      total: 0,
      // 表格数据
      list: [],
      // 查询参数
      queryParams: {
        deviceId: undefined,
        pageNum: 1,
        pageSize: 20
      }
    };
  },
  created() {
    this.getList();
  },
  methods: {
    /** 查询登录日志列表 */
    getList() {
      this.loading = true;
      getMqttClient(this.queryParams).then(response => {
        this.list = response.data;
        this.total = response.count;
        this.loading = false;
      });
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
  }
};
</script>
五、实现效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2180785.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SUP-NeRF-ECCV2024数据集: 单目3D对象重建的新突破

2024-09-25&#xff0c;由Bosch Research North America和Michigan State University联合发布的SUP-NeRF&#xff0c;是一个基于单目图像进行3D对象重建的新型方法。一个无缝集成姿态估计和物体重建的统一网格。 ECCV&#xff1a;欧洲计算机视觉会议的缩写&#xff0c;它是计算…

如何使用ssm实现科技银行业务管理系统+vue

TOC ssm743科技银行业务管理系统vue 第一章 绪论 1.1 研究背景 在现在社会&#xff0c;对于信息处理方面&#xff0c;是有很高的要求的&#xff0c;因为信息的产生是无时无刻的&#xff0c;并且信息产生的数量是呈几何形式的增加&#xff0c;而增加的信息如何存储以及短时间…

移除元素

移除元素 题目链接&#xff1a;移除元素 示例 1&#xff1a; 输入&#xff1a;nums [3,2,2,3], val 3 输出&#xff1a;2, nums [2,2,_,_] 解释&#xff1a;你的函数函数应该返回 k 2, 并且 nums 中的前两个元素均为 2。 你在返回的 k 个元素之外留下了什么并不重要&…

URL从输入到⻚面显示的过程(详细版)

URL从输入到⻚面显示的过程&#xff08;详细版&#xff09; 浏览器中输入网址 DNS 解析域名得到 IP 地址 DNS 解析首先会从你的浏览器的缓存中去寻找是否有这个网址对应的 IP 地址&#xff0c;如果没有就向OS系统的 DNS 缓存中寻找&#xff0c;如果没有就是路由器的 DNS 缓存&…

C++之 友元重载 以及最常用的几种友元函数

在之前的友元中就曾经讲过&#xff0c;我们为了去访问修改私有成员中的数据时&#xff0c;只能通过公有的办法去进行访问操作&#xff0c;非常的局限。所以C引用了友元函数&#xff0c;只要加上friend关键字&#xff0c;C的这个类&#xff0c;会自动把这个函数的权限拉到类内&a…

无水印短视频素材下载网站有哪些?十个高清无水印视频素材网站分享

你知道怎么下载无水印视频素材吗&#xff1f;今天小编就给大家推荐十个高清无水印视频素材下载的网站&#xff0c;如果你也是苦于下载高清无水印的短视频素材&#xff0c;赶紧来看看吧&#xff5e; 1. 稻虎网 首推的是稻虎网。这个网站简直就是短视频创作者的宝库。无论你需要…

编程魔法:基于LLM的AI function开发,如何实现高效数据生成?

基于大语言模型&#xff08;LLM&#xff09;的AI function开发&#xff0c;简直就是现代编程界的“魔法棒”&#xff01; 你好&#xff0c;我是三桥君 最近三桥君有个任务&#xff0c;需要造一些测试数据&#xff0c;比如姓名、手机号、银行卡号、邮箱啥的&#xff0c;用来做测…

每日OJ题_牛客_添加逗号_模拟_C++_Java

目录 牛客_添加逗号_模拟 题目解析 C代码1 C代码2 Java代码 牛客_添加逗号_模拟 添加逗号_牛客题霸_牛客网 题目解析 读取输入&#xff1a;读取一行字符串。分割字符串&#xff1a;使用空格将字符串分割成单词数组。拼接字符串&#xff1a;将单词数组中的每个单词用逗号…

群晖安装Gitea(代码托管工具)

一、Gitea介绍 Gitea 是一款开源的轻量级代码托管平台,可以为团队和开发者提供了一个易于部署、运行快速、使用体验良好的自建 Git 服务。相比于其它自部署代码托管平台,Gitea 的设计更加轻量,对系统资源的占用相对较少,能够在较低配置的服务器上流畅运行。相比于其他代码…

嘉楠科技AI芯片K230-初探

勘智K230 介绍入门购买开发板 安装开机开发学习点亮第1个LED点亮屏幕预览摄像头代码离线运行 在线训练平台 参考 介绍 K230芯片是嘉楠科技 Kendryte系列AIoT芯片中的最新一代SoC产品。该芯片采用全新的多异构单元加速计算架构&#xff0c;集成了2个RISC-V高能效计算核心&#x…

Spring系列 BeanPostProcessor

文章目录 BeanPostProcessor注册时机执行时机 InstantiationAwareBeanPostProcessorSmartInstantiationAwareBeanPostProcessor 本文源码基于spring-beans-5.3.31 参考&#xff1a;https://docs.spring.io/spring-framework/reference/core/beans/factory-extension.html#beans…

【ASE】第四课_高亮显示效果(手动切换)

今天我们一起来学习ASE插件&#xff0c;希望各位点个关注&#xff0c;一起跟随我的步伐 今天我们来学习高亮的效果。 思路&#xff1a; 1.添加纹理贴图和法线贴图&#xff0c;环境光遮挡贴图 2.添加高亮的参数&#xff0c;并设置 3.手搓一个边缘光,通过高亮参数调节 4.将模…

微信小程序——音乐播放器

目的 掌握swiper组件、scroll-view组件的使用掌握image组件的使用掌握音频API的使用掌握slider组件的使用 内容 了音乐小程序项目的完整开发流程&#xff0c;其开发步骤包括页面结构的分析、样式的设计、组件的运用等。通过本章的学习&#xff0c;读者能够掌握小程序的基本交…

聚星文社——绘唐科技有什么区别!

聚星文社和绘唐科技是两个不同的公司&#xff0c;有一些区别。下面是它们的一些区别&#xff1a; 绘唐科技——聚星文社https://iimenvrieak.feishu.cn/docx/ZhRNdEWT6oGdCwxdhOPcdds7nof 行业领域&#xff1a;聚星文社主要从事文化娱乐行业&#xff0c;包括出版、影视制作等&…

点餐小程序实战教程14点餐功能

目录 1 功能分析2 初始化菜品的数量3 加入购物车4 显示购物车5 最终的效果总结 上一篇我们讲解了如果通过扫码实现餐桌信息显示&#xff0c;本篇我们介绍一下点餐的功能。 1 功能分析 点餐的话一般我们是在菜品点击号或者-号来加入购物车&#xff0c;加入购物车之后还可以修改…

APP 安全测试项总结

一、安装包测试 1.1、关于反编译 目的是为了保护公司的知识产权和安全方面的考虑等&#xff0c;一些程序开发人员会在源码中硬编码一些敏感信息&#xff0c;如密码。而且若程序内部一些设计欠佳的逻辑&#xff0c;也可能隐含漏洞&#xff0c;一旦源码泄漏&#xff0c;安全隐患…

Temporal Dynamic Quantization for Diffusion Models阅读

文章目录 AbstractIntroductionBackgrounds and Related Works2.1 扩散模型2.2 量化2.3 量化感知训练和训练后量化 TemporalDynamic Quantization3.1 量化方法3.2 扩散模型量化的挑战3.3 TDQ模块的实现3.4 工程细节时间步的频率编码TDQ模块的初始化 Experimental SetupResults5…

#git 问题failed to resolve head as a valid ref

问题如下&#xff1a; 解决方法&#xff1a; 1、运行 git fsck --full 可以查看具体error信息&#xff0c;一般都是head索引问题 2、.git\refs\heads\xxx&#xff08;当前分支&#xff09;txt编辑器打开显示乱码&#xff0c;而不是hash编码 3、在.git\logs\refs\heads\xxx&a…

如何评价 Python 语言的运行速度

Python 作为一门编程语言&#xff0c;其运行速度一直是业界讨论的焦点。它的简洁语法和广泛的应用使得它在开发过程中非常高效&#xff0c;然而&#xff0c;运行速度与一些更底层的编程语言相比存在一定的劣势。这是否是由于 Python 语法的简洁性所带来的代价&#xff1f;我们可…

心觉:自我暗示语“正确姿势”的科学解释

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作185/1000天 “如何重塑高效学习的潜意识”这个系列文章其实昨天已经写完了 在写这个系列文章的时候&#xff0c;我突然有一个关于…