ESP32中MQTT通讯

news2024/11/15 8:25:32

MQTT文档介绍

一、在PC上可以使用 MQTT X 工具:(参考地址)

1、客户端下载:MQTT X 工具下载地址

2、EMQX服务器下载地址

3.打开命令行工具,进入目录运行EMQX服务。

电脑左下角,右键开始->运行->输入cmd,确定->打开命令行工具,操作如下:

1)切换到E盘:输入e:

2)进入到EMQX的bin目录:输入cd D:\EMQX\bin

3)启动EMQX服务器,输入emqx start,如需停止服务器,输入emqx stop

4)查看EMQX服务器状态,先进入bin目录:输入cd D:\EMQX\bin

5)接着输入:emqx_ctl status,可以看到EMQX服务器已启动

 4.登陆EMQX服务器,验证是否可用。

1)打开浏览器,输入地址:http://127.0.0.1:18083/#/login

2)输入用户名:admin,输入密码:public,点击Login

3)更改界面为中文。

二、wif配网:

配网app下载地址

智能配网

static void smartconfig_example_task(void * parm)
{
    wifi_config_t myconfig = {0};
    EventBits_t uxBits;
    esp_wifi_get_config(WIFI_IF_STA,&myconfig); //获取WiFi配网信息
    if( strlen((char*)myconfig.sta.ssid) > 0 ) //之前已经完成配网 直接连接
    {
        ESP_LOGI(TAG,"wifi already set,ssid %s start connect.", myconfig.sta.ssid);
        esp_wifi_connect();
    }
    else//以前未进行连接 
    {
        ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
        smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
        ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) ); //开始进行配网
    }
    while (1) {
        uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
        if(uxBits & CONNECTED_BIT) {
            ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if(uxBits & ESPTOUCH_DONE_BIT) {
            ESP_LOGI(TAG, "smartconfig over");
            esp_smartconfig_stop();
            vTaskDelete(NULL); //清除配网信息
        }
    }
}

蓝牙配网:通过蓝牙将wifi配置信息传给esp32。

手机通过蓝牙配网app,检索到esp蓝牙信号,连接。

然后通过app传输wifi名称和密码,交给esp32。

esp32接收到wifi配置,进行wifi连接。

API esp_wifi_set_config() //可用于配置 AP。配置的参数信息会保存到 NVS 中。

三、MQTT连接

1、esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config)

函数描述:根据配置创建MQTT客户端句柄

typedef struct {
    mqtt_event_callback_t event_handle; / *!<处理MQTT事件作为传统模式的回调* /
    esp_event_loop_handle_t event_loop_handle; / *!<MQTT事件循环库的句柄* /
    const char * host; / *!<MQTT服务器域(ipv4 as string)* /
    const char * uri; / *!<完整的MQTT代理URI * /
    uint32_t port; / *!<MQTT服务器端口* /
    const char * client_id; / *!<默认客户端ID是``ESP32_%CHIPID%``其中%CHIPID%是十六进制格式的MAC地址的最后3个字节* /
    const char * username; / *!<MQTT用户名* /
    const char *密码; / *!<MQTT密码* /
    const char * lwt_topic; / *!<LWT(遗嘱和遗嘱)消息主题(默认为NULL)* /
    const char * lwt_msg; / *!<LWT消息(默认为NULL)* /
    int lwt_qos; / *!<LWT消息qos * /
    int lwt_retain; / *!<LWT保留消息标志* /
    int lwt_msg_len; / *!<LWT消息长度* /
    int disable_clean_session; / *!<mqtt clean session,默认clean_session为true * /
    int keepalive; / *!<mqtt keepalive,默认为120秒* /
    bool disable_auto_reconnect; / *!<此mqtt客户端将重新连接到服务器(当出错/断开连接时)。设置disable_auto_reconnect = true以禁用* /
    void * user_context; / *!<将用户上下文传递给此选项,然后可以在``event-> user_context`` * /中接收该上下文
    int task_prio; / *!<MQTT任务优先级,默认为5,可以在``make menuconfig``中更改* /
    int task_stack; / *!<MQTT任务堆栈大小,默认为6144字节,可以在``make menuconfig``中更改* /
    int buffer_size; / *!<MQTT发送/接收缓冲区的大小,默认为1024 * /
    const char * cert_pem; / *!<用于服务器验证的PEM格式的证书数据指针(使用SSL),默认为NULL,不需要验证服务器* /
    const char * client_cert_pem; / *!<指向用于SSL相互身份验证的PEM格式的证书数据的指针,默认为NULL,如果不需要相互身份验证,则不需要。如果它不是NULL,则还必须提供`client_key_pem`。 * /
    const char * client_key_pem; / *!<指向用于SSL相互身份验证的PEM格式的私钥数据的指针,默认为NULL,如果不需要相互身份验证,则不需要。如果它不是NULL,则还必须提供`client_cert_pem`。 * /
    esp_mqtt_transport_t transport; / *!<覆盖URI传输* /
    int refresh_connection_after_ms; / *!<刷新此值后的连接(以毫秒为单位)* /
esp_mqtt_client_config_t;

2、sp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client)

函数描述:启动MQTT客户端

参数:创建的MQTT句柄

返回值:ESP_OK表示成功ESP_ERR_无效_ARG错误初始化ESP_FERT其他错误

3、esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client)

函数描述:停止MQTT客户端

参数:创建的MQTT句柄

4、int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos)

函数描述:订阅主题

参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄

B、char *topic 订阅的主题

C、Qos级别 0 、1、 2

返回值:成功时订阅消息返回Message_id- 失败返回-1

5、int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic)

函数描述:取消订阅的主题

参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄

B、B、char *topic 订阅的主题

返回值:成功时订阅消息返回Message_id- 失败返回-1

6、int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain)

函数描述:往代理发布消息

参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄

B、char topic 发布的主题C、 const char data 发布的数据D、int len 数据长度,如果设置为0,则从发布的数据长度E、Qos级别F、retain 当我们使用MQTT客户端发布消息(PUBLISH)时,如果将RETAIN标志位设置为true,那么MQTT服务器会将最近收到的一条RETAIN标志位为true的消息保存在服务器端7、esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler, void event_handler_arg)函数描述:注册MQTT事件参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄B、esp_mqtt_event_id_t event 注册任何事件id的处理程序C、esp_event_handler_t event_handler 回调函数D、void event_handler_arg 处理程序上下文

连接发送测试:

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "esp_smartconfig.h"
#include "my_button.h"

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_event.h"
#include "protocol_examples_common.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
 
#include "esp_log.h"
#include "mqtt_client.h"

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t s_wifi_event_group;
static esp_mqtt_client_handle_t mqttclient;
/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "smartconfig_example";

static void smartconfig_example_task(void * parm);

static void event_handler(void* arg, esp_event_base_t event_base,
                                int32_t event_id, void* event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {
        ESP_LOGI(TAG, "Scan done");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {
        ESP_LOGI(TAG, "Found channel");
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {
        ESP_LOGI(TAG, "Got SSID and password");

        smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
        wifi_config_t wifi_config;
        uint8_t ssid[33] = { 0 };
        uint8_t password[65] = { 0 };
        uint8_t rvd_data[33] = { 0 };

        bzero(&wifi_config, sizeof(wifi_config_t));
        memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));
        memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));
        wifi_config.sta.bssid_set = evt->bssid_set;
        if (wifi_config.sta.bssid_set == true) {
            memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
        }

        memcpy(ssid, evt->ssid, sizeof(evt->ssid));
        memcpy(password, evt->password, sizeof(evt->password));
        ESP_LOGI(TAG, "SSID:%s", ssid);
        ESP_LOGI(TAG, "PASSWORD:%s", password);
        if (evt->type == SC_TYPE_ESPTOUCH_V2) {
            ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );
            ESP_LOGI(TAG, "RVD_DATA:");
            for (int i=0; i<33; i++) {
                printf("%02x ", rvd_data[i]);
            }
            printf("\n");
        }

        ESP_ERROR_CHECK( esp_wifi_disconnect() );
        ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
        esp_wifi_connect();
    } else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {
        xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);
    }
}

static void initialise_wifi(void)
{
    ESP_ERROR_CHECK(esp_netif_init());
    s_wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) ); //wifi接口初始化

    ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
    ESP_ERROR_CHECK( esp_event_handler_register(SC_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );

    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_start() ); 
}

static void smartconfig_example_task(void * parm)
{
    wifi_config_t myconfig = {0};
    EventBits_t uxBits;
    esp_wifi_get_config(WIFI_IF_STA,&myconfig); //获取WiFi配网信息
    if( strlen((char*)myconfig.sta.ssid) > 0 ) //之前已经完成配网 直接连接
    {
        ESP_LOGI(TAG,"wifi already set,ssid %s start connect.", myconfig.sta.ssid);
        esp_wifi_connect();
    }
    else//以前未进行连接 
    {
        ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH) );
        smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT();
        ESP_ERROR_CHECK( esp_smartconfig_start(&cfg) ); //开始进行配网
    }
    while (1) {
        uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
        if(uxBits & CONNECTED_BIT) {
            ESP_LOGI(TAG, "WiFi Connected to ap");
        }
        if(uxBits & ESPTOUCH_DONE_BIT) {
            ESP_LOGI(TAG, "smartconfig over");
            esp_smartconfig_stop();
            vTaskDelete(NULL); //清除配网信息
        }
    }
    
}
 
 
//事件处理函数
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    // your_context_t *context = event->context;
    switch (event->event_id) {
    case MQTT_EVENT_CONNECTED: //MQTT连上事件
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
        //发送订阅
        msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        //取消订阅主题 (测试加上后接受一次消息就会断开)
        // msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos0");
        // ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED: //MQTT断开连接事件
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;

    case MQTT_EVENT_SUBSCRIBED: //MQTT发送订阅事件
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED: //MQTT取消订阅事件
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED: //MQTT发布事件
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA: //MQTT接受数据事件
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
        printf("DATA=%.*s\r\n", event->data_len, event->data);
        break;
    case MQTT_EVENT_ERROR: //MQTT错误事件
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        // if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
        //     log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
        //     log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
        //     log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
        //     ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
        //}
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
    return ESP_OK;
}

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    /* The argument passed to esp_mqtt_client_register_event can de accessed as handler_args*/
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%ld", base, event_id);
    mqtt_event_handler_cb(event_data);
}

//mqtt初始化
static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        // .event_handle = mqtt_event_handler,              //MQTT事件
        .broker.address.uri =  "mqtt://broker.emqx.io", 
        // .broker.address.hostname = "192.168.12.34" ,            //MQTT服务器IP
        // .broker.address.port = 1883,                       //端口
        .credentials.username = "admin" ,                   //用户名
        // .credentials.client_id = "emqx_OTM5OD",          //客户端id
        .credentials.authentication.password = "public" ,   //密码
    };
#if CONFIG_BROKER_URL_FROM_STDIN
    char line[128];
 
    if (strcmp(mqtt_cfg.uri, "FROM_STDIN") == 0) {
        int count = 0;
        printf("Please enter url of mqtt broker\n");
        while (count < 128) {
            int c = fgetc(stdin);
            if (c == '\n') {
                line[count] = '\0';
                break;
            } else if (c > 0 && c < 127) {
                line[count] = c;
                ++count;
            }
            vTaskDelay(10 / portTICK_PERIOD_MS);
        }
        mqtt_cfg.uri = line;
        printf("Broker url: %s\n", line);
    } else {
        ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
        abort();
    }
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
 
    printf("esp_mqtt_client_start\r\n");
 
    //通过esp_mqtt_client_init获取一个MQTT客户端结构体指针,参数是MQTT客户端配置结构体
    // esp_mqtt_client_handle_t 
    mqttclient = esp_mqtt_client_init(&mqtt_cfg);
    
    /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
    //注册MQTT事件
    esp_mqtt_client_register_event(mqttclient, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    //开启MQTT功能
    esp_mqtt_client_start(mqttclient);
 
    //等mqtt连上
    // xEventGroupWaitBits(mqtt_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}
//获取纳秒级时间
int64_t getTime(void)
{
    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    int64_t time_us = (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
    ESP_LOGI(TAG, "[APP] IDF time: %lld", time_us);
    return time_us;
}

void app_main(void)
{
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %lu bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
 
    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);

    ESP_ERROR_CHECK( nvs_flash_init() );
    initialise_wifi();
    button_start(); //按键清除配网信息
    mqtt_app_start();
    getTime();    
    while (1) {        
        printf("system is running!\r\n"); 
        //发布主题
        esp_mqtt_client_publish(mqttclient, "/topic/qos0", "Hello MQTT,I am huqin ", 0, 0, 0);
        vTaskDelay(1000 / portTICK_PERIOD_MS); 
    }    
}

测试采用公共服务器 mqtt://broker.emqx.io 进行通讯测试

客户端发送消息和接受的消息

也可以在不同服务器之间通讯

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

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

相关文章

“双碳”目标下二氧化碳地质封存技术应用前景及模型构建

我国二氧化碳地质封存技术起步较晚&#xff0c;目前仍没有一套相对完整的行业规范&#xff1b;且就该技术而言&#xff0c;涉及环节众多&#xff0c;理论相对复杂&#xff0c;对于行业的新入局者不太友好。因此&#xff0c;结合时代背景&#xff0c;我们首次尝试对二氧化碳地质…

升级多语言,应用国际化_三叠云

国际化配置 路径 表单设计 >> 字段属性 功能简介 【字段】新增 「国际化配置」 这是一个和国际化配合的功能&#xff0c;可以在用户通过切换不同的语言环境时&#xff0c;表单的标题、提示语等将会根据相应的语言环境切换到相应的表单字段标题、提示语&#xff0c;使…

Eureka注册中心-Ribbon负载均衡

1、Eureka注册中心服务注册与发现提供了一个服务注册中心、服务发现的客户端&#xff0c;还有一个方便查看所有注册的服务的界面。所有的服务使用Eureka的服务发现客户端来将自己注册到Eureka的服务器上。1.1 、Eureka的结构和作用1.1.1、Eureka的作用1.1.2、获取地址信息的流程…

【C++进阶】三、二叉搜索树

目录 一、二叉搜索树 1.1 概念 1.2 二叉搜索树操作 二、二叉搜索树实现 2.1 框架总览 2.2 实现接口总览 2.2.1 构造函数 2.2.2 拷贝构造 2.2.3 赋值重载 2.2.4 析构函数 2.2.5 二叉搜索树的遍历 2.2.6 插入函数 2.2.7 查找函数 2.2.8 删除函数 2.3 二叉搜索数完整…

MotionLayout动画效果实现的几种方式

前言MotionLayout 的使用大家应该都会了&#xff0c;如果不会看这里。本文就不科普如何使用&#xff0c;什么属性是什么意思&#xff0c;怎么使用之类的了&#xff0c;这里只是探讨一下 MotionLayout 效果实现的几种方式。一、ConstraintLayout 的方式定义我们知道 MotionLayou…

第三回:布局格式定方圆

import numpy as np import pandas as pd import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] #用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False #用来正常显示负号一、子图 1. 使用 plt.subplots 绘制均匀状态下的子图 返回元素分…

ROS1学习笔记:ROS中的坐标管理系统(ubuntu20.04)

参考B站古月居ROS入门21讲&#xff1a;ROS中的坐标系管理系统 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、机器人中的坐标变换二、TF功能包三、小海龟跟随实验3.1 启动实验3.2 查看当前的TF树3.3 坐标相对位置可视化3.3.1 tf_echo3.3.2 rviz一、机器人中的坐标变换…

2023上半年软考,广州/东莞/深圳/江苏报班是明智的选择

软考是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资格考试。 系统集成…

飞桨paddlenlp安装报错python setup.py egg_info did not run successfully.

原因缺少setuptools_scm 安装setuptools_scm pip install setuptools_scm 然后再安装paddlenlp就会噼里啪啦的下载一大堆东东了 下载OVER

【K8S系列】第十四讲:初识K8s架构之服务器的变迁

目录 序言 1简介 1.1 物理机时代 物理服务器的缺点 1.2 虚拟机 虚拟机优缺点 1.3 容器时代 1.4 总结 2 容器编排 2.1 什么是容器编排 序言 人生犹如一股奔流&#xff0c;没有暗礁&#xff0c;激不起美丽的浪花。 三言两语&#xff0c;不如细心探索 今天学习一下K8s…

ROS从入门到精通2-6:Rviz可视化进阶(画坐标轴、直线、平面、圆柱等)

目录0 专栏介绍1 Rviz可视化2 环境配置3 使用方法4 测试用例0 专栏介绍 本专栏旨在通过对ROS的系统学习&#xff0c;掌握ROS底层基本分布式原理&#xff0c;并具有机器人建模和应用ROS进行实际项目的开发和调试的工程能力。 &#x1f680;详情&#xff1a;《ROS从入门到精通》…

因《狂飙》张颂文,吐槽广东人比内地人聪明,周杰才是地域黑鼻祖

最近一段时间&#xff0c;电视剧《狂飙》落下帷幕&#xff0c;但是关于这部电视剧的争议&#xff0c;却从来就没有停止过。尤其是主演张颂文&#xff0c;更是受到了大家的关注&#xff0c;不但圈住了很多的粉丝&#xff0c;影视圈很多同行也对他赞许有加。 自古以来同行是冤家&…

SSM-SpringBoot(快速启动,yaml配置)

1 SpingBoot简介 1.1 创建SpringBoot项目 创建 层次 boot程序最基本的架子 开发 RestController RequestMapping("/books") public class BookController {GetMapping("/{id}")public String getById(PathVariable Integer id){System.out.println(&qu…

亚马逊云科技张文翊:云计算正成为企业数字化的“技术底座”

在走进经济筑底重启回升的2023年&#xff0c;我们该如何直面这场需要时间验证的修复之旅&#xff1f;亚马逊全球副总裁、亚马逊云科技大中华区执行董事张文翊与《经济观察报》App的“企业家说2023”栏目展开对谈&#xff0c;分享亚马逊云科技如何立于云端&#xff0c;帮助企业上…

Java及JVM简介

世界上没有最好的编程语言&#xff0c;只有最适用于具体应用场景的编程语言 懂得JVM内部的内存结构、工作机制&#xff0c;是设计高扩展性应用和诊断运行时问题的基础&#xff0c;也是Java工程师进阶的必备能力。 java介绍 java是目前应用最为广泛的软件开发平台之一。随着…

Elasticsearch:创建一个简单的 “你的意思是?” 推荐搜索

“你的意思是” 是搜索引擎中一个非常重要的功能&#xff0c;因为它们通过显示建议的术语来帮助用户&#xff0c;以便他可以进行更准确的搜索。比如&#xff0c;在百度中&#xff0c;我们进行搜索时&#xff0c;它通常会显示一些更为常用推荐的搜索选项来供我们选择&#xff1a…

MyEclipse技术全面解析——EJB开发工具介绍(二)

在上文中&#xff08;点击这里回顾>>&#xff09;&#xff0c;我们为大家介绍了MyEclipse EJB开发工具以及如何创建一个EJB项目。本文将继续讲解如何EJB 3.x项目的持久性支持&#xff0c;以及EJB项目的参数等&#xff0c;欢迎下载最新版MyEclipse体验&#xff01;MyEclip…

【JAVA程序设计】【C00106】基于SSM(非maven)的演唱会网上订票系统——有文档

【C00106】基于SSM&#xff08;非maven&#xff09;的演唱会网上订票系统——有文档项目简介项目获取开发环境项目技术运行截图项目简介 基于SSMBootstrapMYSQL演唱会网上订票系统分为二个角色&#xff1a;系统管理员、用户 管理员角色包含以下功能&#xff1a; 管理员信息、网…

taobao.user.seller.get( 查询卖家用户信息 )

&#xffe5;开放平台基础API必须用户授权 查询卖家用户信息&#xff08;只能查询有店铺的用户&#xff09; 只能卖家类应用调用。 公共参数 请求地址: HTTP地址 http://gw.api.taobao.com/router/rest 公共请求参数: 公共响应参数: 请求参数 点击获取key和secret请求示例…

华为OD机试模拟题 用 C++ 实现 - 叠放书籍(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明叠放书籍题目输入输出示例一输入输出Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单…