【ESP32S3 Sense接入语音识别+MiniMax模型对话】

1. 前言

围绕ESP32S3 Sense接入语音识别+MiniMax模型对话展开,首先串口输入“1”字符,随后麦克风采集2s声音数据,对接百度在线语音识别,将返回文本结果丢入MiniMax模型,进而返回第二次结果文本,实现语言对话文本效果。以上一共有两次调用,后期只需加入tts模块就可完整对话。

讲解视频:

ESP32S3 Sense接入语音识别+MiniMax模型对话

1.1 语音接入

百度在线语音接入教程:
【ESP32S3 Sense接入百度在线语音识别】
在这里插入图片描述

使用Seeed XIAO ESP32S3 Sense开发板接入百度智能云实现在线语音识别。自带麦克风模块用做语音输入,通过串口发送字符“1”来控制数据的采集和上传。

1.2 大模型接入

国产大模型接入分享如下:
【ESP32接入国产大模型之MiniMax】
【ESP32接入语言大模型之智谱清言】
【ESP32接入国产大模型之文心一言】
【ESP32接入语言大模型之通义千问】

下面是不标准测评,推荐使用MiniMax大模型,参考而已
在这里插入图片描述

MM智能助理是一款由MiniMax自研的,没有调用其他产品的接口的大型语言模型。MiniMax是一家中国科技公司,一直致力于进行大模型相关的研究。
|模型| 响应时间|内容质量|免费token次数|地址|
|–|–|–|–|–|
| MiniMax | 3s | 8分|500万|https://www.minimaxi.com/|
| 智谱清言 | 7s | 8分|300万|https://open.bigmodel.cn/|
|文心一言 | 10s | 9分|500万|https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu|
| 通义千问 | 8s | 8分|800万|https://tongyi.aliyun.com/qianwen/|

这一次还是采用Arduino编程就会轻松许多开发。这样就可以把stt+chat大模型装进口袋啦🤣🤣🤣,接下来就只差tts播报啦!

在这里插入图片描述

2. 先决条件

在继续此项目之前,请确保检查以下先决条件。

我们将使用 Arduino IDE 对 ESP32/ESP8266 开发板进行编程,因此在继续本教程之前,请确保已在 Arduino IDE 中安装这些开发板。

2.1 环境配置

  1. Arduino IDE:下载并安装 Arduino IDE;
  2. ESP32 开发板库:在 Arduino IDE 中添加 ESP32 支持;
    参考博客:【esp32c3配置arduino IDE教程】
    为安装过程留出一些时间,具体时间可能因您的互联网连接而异。

2.2 所需零件

要学习本教程,您需要1个 ESP32 开发板+马克风或者ESP32 Sense,建议使用后者,笔者发现同样的代码后者可以轻松调用,ESP32不行(可能板子坏了)

在这里插入图片描述

3. 核心代码

提供两种硬件测试

  1. ESP32S3 Sense
  2. ESP32 + max9814麦克风模块用做语音输入,一个按键来控制数据的采集和上传

3.1 ESP32S3 Sense

在这里插入图片描述
ESP32S3 Sense自带麦克风直接烧录
Arduino代码如下

#include <Arduino.h>
#include "base64.h"
#include <WiFi.h>
#include "HTTPClient.h"
#include "cJSON.h"
#include <I2S.h>
#include <ArduinoJson.h>
#define data_len 16000
// #define key 4             //端口0
// #define ADC 2             //端口39
// #define led 15            //端口2HTTPClient http_client;
// 1. Replace with your network credentials
const char* ssid = "J09 502";
const char* password = "qwertyuiop111";
// 2. Check your Aduio port
const int buttonPin = 1;  // the number of the pushbutton pin
const int ledPin = 21;    // the number of the LED pin
hw_timer_t* timer = NULL;
uint16_t adc_data[data_len];    //16000个数据,8K采样率,即2秒,录音时间为2秒,想要实现更长时间的语音识别,就要改这个数组大小//和下面data_json数组的大小,改大一些。
uint8_t adc_start_flag = 0;     //开始标志
uint8_t adc_complete_flag = 0;  //完成标志
char data_json[45000];          //用于储存json格式的数据,大一点,JSON编码后数据字节数变成原来的4/3,所以得计算好,避免出现越界// 3. Replace with your MiniMax API key
const char* apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiIyMzQ1dm9yIiwiVXNlck5hbWUiOiIyMzQ1dm9yIiwiQWNjb3VudCI6IiIsIlN1YmjE3NTk0ODIxODAxMDAxNzAyMDgiLCJQI6IjE3NTk0ODIxODAwOTU5NzU5MDQiLCJQYWdlTmFtZSI6IiIsIk1haWwiOiIiLCJDcmVhdGVUaW1lIjoiMjAyNC0wMy0xNiAxMzoyNDoxOCIsImlzcyI6Im1pbmltYXgifQ.WlEj8Nk0j_WOMXZE9SbIC8sHpwJ6R6Pi8Spl5mahJsW3-Jsz7Ev53sGGz3v__Bd5dDkt7o9-Y8BOW0WZq2ImaN7Rof7YNtYnYnvPNDyGx23_xRqq5co9P5UkC3ciYEcIch2SUZ5QPkXR-sMUPzhdowSYvfdu1N25kdKJ8GE_63NfCnsdDVt8mv0wQSSweJK0yf_C8a8ADdB1uF4vg_WKMDjHlvzERsoNZgX6FYtr-bee85rIyu4U-OrbUvEpR1FLPXa7lTlx65QvhVIYGbIKde7ERIT_7QLOQoVFvPz0gX-H6V7UlmSRgRy4LK_R9mvV5TqCy3v90WK_AFuwEhPXcg";
HTTPClient http;
String token_key = String("Bearer ") + apiKey;
// Send request to MiniMax API
String inputText = "你好,minimax!";
String apiUrl = "https://api.minimax.chat/v1/text/chatcompletion_v2";
int httpResponseCode;
String response,question,answer;
DynamicJsonDocument jsonDoc(1024);uint32_t num = 0;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {// Increment the counter and set the time of ISRportENTER_CRITICAL_ISR(&timerMux);if (adc_start_flag == 1) {//Serial.println("");// adc_data[num] = analogRead(ADC);adc_data[num] = I2S.read();num++;if (num >= data_len) {adc_complete_flag = 1;adc_start_flag = 0;num = 0;//Serial.println(Complete_flag);}}portEXIT_CRITICAL_ISR(&timerMux);
}String getGPTAnswer(String inputText) {http.begin(apiUrl);http.addHeader("Content-Type", "application/json");http.addHeader("Authorization", token_key);String payload = "{\"model\":\"abab5.5s-chat\",\"messages\":[{\"role\": \"system\",\"content\": \"你是鹏鹏的生活助手机器人,要求下面的回答严格控制在256字符以内。\"},{\"role\": \"user\",\"content\": \"" + inputText + "\"}]}";httpResponseCode = http.POST(payload);if (httpResponseCode == 200) {response = http.getString();http.end();Serial.println(response);// Parse JSON responsedeserializeJson(jsonDoc, response);String outputText = jsonDoc["choices"][0]["message"]["content"];return outputText;// Serial.println(outputText);} else {http.end();Serial.printf("Error %i \n", httpResponseCode);return "<error>";}
}void setup() {//Serial.begin(921600);Serial.begin(115200);// pinMode(ADC, ANALOG);// pinMode(buttonPin, INPUT_PULLUP);pinMode(ledPin, OUTPUT);// start I2S at 16 kHz with 16-bits per sampleI2S.setAllPins(-1, 42, 41, -1, -1);if (!I2S.begin(PDM_MONO_MODE, 16000, 16)) {Serial.println("Failed to initialize I2S!");while (1);  // do nothing}uint8_t count = 0;WiFi.mode(WIFI_STA);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {Serial.print(".");count++;if (count >= 75) {Serial.printf("\r\n-- wifi connect fail! --");break;}vTaskDelay(200);}Serial.printf("\r\n-- wifi connect success! --\r\n");Serial.println(WiFi.localIP());http.setTimeout(10000);// gain_token();timer = timerBegin(0, 80, true);    //  80M的时钟 80分频 1MtimerAlarmWrite(timer, 125, true);  //  1M  计125个数进中断  8KtimerAttachInterrupt(timer, &onTimer, true);timerAlarmEnable(timer);timerStop(timer);  //先暂停
}uint32_t time1, time2;
void loop() {if (Serial.available() > 0)  //按键按下{if (Serial.read() == '1') {Serial.printf("Start recognition\r\n\r\n");digitalWrite(ledPin, HIGH);adc_start_flag = 1;timerStart(timer);// time1=micros();while (!adc_complete_flag)  //等待采集完成{ets_delay_us(10);}// time2=micros()-time1;timerStop(timer);adc_complete_flag = 0;  //清标志digitalWrite(ledPin, LOW);memset(data_json, '\0', strlen(data_json));  //将数组清空strcat(data_json, "{");strcat(data_json, "\"format\":\"pcm\",");strcat(data_json, "\"rate\":16000,");                                                                        //采样率    如果采样率改变了,记得修改该值,只有16000、8000两个固定采样率strcat(data_json, "\"dev_pid\":1537,");                                                                      //中文普通话strcat(data_json, "\"channel\":1,");                                                                         //单声道strcat(data_json, "\"cuid\":\"666666\",");                                                                   //识别码    随便打几个字符,但最好唯一strcat(data_json, "\"token\":\"24.8f6143793af76e02f5e191.2592000.1713789066.282335-57722200\",");  //token	这里需要修改成自己申请到的tokenstrcat(data_json, "\"len\":32000,");                                                                         //数据长度  如果传输的数据长度改变了,记得修改该值,该值是ADC采集的数据字节数,不是base64编码后的长度strcat(data_json, "\"speech\":\"");strcat(data_json, base64::encode((uint8_t*)adc_data, sizeof(adc_data)).c_str());  //base64编码数据strcat(data_json, "\"");strcat(data_json, "}");// Serial.println(data_json);int httpCode;http_client.setTimeout(5000);http_client.begin("http://vop.baidu.com/server_api");  //https://vop.baidu.com/pro_apihttp_client.addHeader("Content-Type", "application/json");httpCode = http_client.POST(data_json);if (httpCode == 200) {if (httpCode == HTTP_CODE_OK) {response = http_client.getString();http_client.end();Serial.println(response);// Parse JSON response// DynamicJsonDocument jsonDoc(512);deserializeJson(jsonDoc, response);String question = jsonDoc["result"][0];// 访问"result"数组,并获取其第一个元// 输出结果Serial.println("\n Input:"+question);answer = getGPTAnswer(question);Serial.println("Answer: " + answer);Serial.println("Enter a prompt:");} else {Serial.printf("[HTTP] GET... failed, error: %s\n", http_client.errorToString(httpCode).c_str());}}// while (!digitalRead(buttonPin))//   ;Serial.printf("Recognition complete\r\n");}}vTaskDelay(1);
}

用于实现一个通过 I2S 接口采集音频信号并将其发送到百度语音识别 API 进行语音识别,然后将识别出的文本通过 MiniMax API 获取 AI 回答的功能。以下是代码的主要结构和功能说明:

  1. 引入必要的库文件,包括 Arduino.h、base64.h、WiFi.h、HTTPClient.h、cJSON.h、I2S.h 和 ArduinoJson.h,这些库分别提供了基本的 Arduino 功能、Base64 编解码、Wi-Fi 连接、HTTP 客户端操作、JSON 数据处理和 I2S 音频接口驱动。

  2. 定义了一些全局变量,如 Wi-Fi 的 SSID 和密码,以及与音频采集和处理相关的变量,如 ADC 数据缓冲区、录音标志位、完成标志位、JSON 格式数据缓冲区,还有 MiniMax API 的密钥(apiKey)。

修改Wi-Fi 的 SSID 和密码

// 1. Replace with your network credentials
const char* ssid = "J09 502";
const char* password = "qwertyuiop111";

修改MiniMax API 的密钥(apiKey)

// 3. Replace with your MiniMax API key
const char* apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiIyMzQ1dm9yIiwiVXNlck5hbWUiOiIyMzQ1dm9yIiwiQWNjb3VudCI6IiIsIlN1YmjE3NTk0ODIxODAxMDAxNzAyMDgiLCJQI6IjE3NTk0ODIxODAwOTU5NzU5MDQiLCJQYWdlTmFtZSI6IiIsIk1haWwiOiIiLCJDcmVhdGVUaW1lIjoiMjAyNC0wMy0xNiAxMzoyNDoxOCIsImlzcyI6Im1pbmltYXgifQ.WlEj8Nk0j_WOMXZE9SbIC8sHpwJ6R6Pi8Spl5mahJsW3-Jsz7Ev53sGGz3v__Bd5dDkt7o9-Y8BOW0WZq2ImaN7Rof7YNtYnYnvPNDyGx23_xRqq5co9P5UkC3ciYEcIch2SUZ5QPkXR-sMUPzhdowSYvfdu1N25kdKJ8GE_63NfCnsdDVt8mv0wQSSweJK0yf_C8a8ADdB1uF4vg_WKMDjHlvzERsoNZgX6FYtr-bee85rIyu4U-OrbUvEpR1FLPXa7lTlx65QvhVIYGbIKde7ERIT_7QLOQoVFvPz0gX-H6V7UlmSRgRy4LK_R9mvV5TqCy3v90WK_AFuwEhPXcg";

修改百度api

strcat(data_json, "\"token\":\"24.8f6143793af76e02f5e191.2592000.1713789066.282335-57722200\",");  //token	这里需要修改成自己申请到的token
  1. 定义了一个 HTTPClient 实例 http_client,用于向 API 发送请求。

  2. 函数 getGPTAnswer() 负责调用 MiniMax API,并传入用户输入文本以获取 AI 的回答。

  3. onTimer() 函数是一个中断服务程序,每当定时器触发时会读取 I2S 接口上的音频数据并存入缓冲区 adc_data 中。当缓冲区满或者录音结束时,会设置完成标志。

  4. setup() 函数负责初始化串口通信、配置 I2S 接口、连接 Wi-Fi,并设置定时器和中断。

  5. loop() 函数是 Arduino 主循环函数,在循环中检查是否有按键输入(这里未实际使用)。如果有特定输入,开始音频采集过程,并在采集完成后将音频数据转换为 Base64 编码,构建一个 JSON 请求体,然后通过 HTTP POST 方式发送到百度语音识别 API。收到识别结果后,调用 getGPTAnswer() 函数获取 AI 回答,并打印在控制台上。

3.2 ESP32 + max9814

ESP32 + max9814麦克风模块用做语音输入,一个按键来控制数据的采集和上传
注意端口:

#define key 0   //按键端口0
#define ADC 32  //max9814麦克风模块端口39
#define led 2   //LED端口2

stt_chat_max.ino

#include <Arduino.h>
#include "base64.h"
#include <WiFi.h>  //#include "WiFi.h"
#include "HTTPClient.h"
#include "cJSON.h"
// #include <I2S.h>
#include <ArduinoJson.h>
#define data_len 16000#define key 0   //端口0
#define ADC 32  //端口39
#define led 2   //端口2
HTTPClient http_client;
// 1. Replace with your network credentials
const char* ssid = "J09 502";
const char* password = "qwertyuiop111";
// 2. Check your Aduio port
// const int buttonPin = 1;  // the number of the pushbutton pin
// const int ledPin = 21;    // the number of the LED pin
hw_timer_t* timer = NULL;
uint16_t adc_data[data_len];    //16000个数据,8K采样率,即2秒,录音时间为2秒,想要实现更长时间的语音识别,就要改这个数组大小//和下面data_json数组的大小,改大一些。
uint8_t adc_start_flag = 0;     //开始标志
uint8_t adc_complete_flag = 0;  //完成标志
char data_json[45000];          //用于储存json格式的数据,大一点,JSON编码后数据字节数变成原来的4/3,所以得计算好,避免出现越界// 3. Replace with your MiniMax API key
const char* apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91iOiIyMzQ1dm9yIiwiQWNjb3VudCI6IiIsIlN1YmplY3RJRCI6IjE3NTk0ODIxODAxMDAxNzAyMDgiLCJQaG9uZSI6IjE1MDcyNjQxNTYxIiwiR3JvdXBJRCI6IjE3NTk0ODIxODAwOTU5NzU5MDQiLCJQYWdlTmFtZSI6IiIsIk1haWwiOiIiLCJDcmVhdGVUaW1lIjoiMjAyNC0wMy0xNiAxMzoyNDoxOCIsImlzcyI6Im1pbmltYXgifQ.WlEj8Nk0j_WOMXZE9SbIC8sHpwJ6R6Pi8Spl5mahJsW3-Jsz7Ev53sGGz3v__Bd5dDkt7o9-Y8BOW0WZq2ImaN7Rof7YNtYnYnvPNDyGx23_xRqq5co9P5UkC3ciYEcIch2SUZ5QPkXR-sMUPzhdowSYvfdu1N25kdKJ8GE_63NfCnsdDVt8mv0wQSSweJK0yf_C8a8ADdB1uF4vg_WKMDjHlvzERsoNZgX6FYtr-bee85rIyu4U-OrbUvEpR1FLPXa7lTlx65QvhVIYGbIKde7ERIT_7QLOQoVFvPz0gX-H6V7UlmSRgRy4LK_R9mvV5TqCy3v90WK_AFuwEhPXcg";
HTTPClient http;
String token_key = String("Bearer ") + apiKey;
// Send request to MiniMax API
String inputText = "你好,minimax!";
String apiUrl = "https://api.minimax.chat/v1/text/chatcompletion_v2";
int httpResponseCode;
String response, question, answer;
DynamicJsonDocument jsonDoc(1024);uint32_t num = 0;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {// Increment the counter and set the time of ISRportENTER_CRITICAL_ISR(&timerMux);if (adc_start_flag == 1) {//Serial.println("");adc_data[num] = analogRead(ADC);// adc_data[num] = I2S.read();num++;if (num >= data_len) {adc_complete_flag = 1;adc_start_flag = 0;num = 0;//Serial.println(Complete_flag);}}portEXIT_CRITICAL_ISR(&timerMux);
}String getGPTAnswer(String inputText) {http.begin(apiUrl);http.addHeader("Content-Type", "application/json");http.addHeader("Authorization", token_key);String payload = "{\"model\":\"abab5.5s-chat\",\"messages\":[{\"role\": \"system\",\"content\": \"你是鹏鹏的生活助手机器人,要求下面的回答严格控制在256字符以内。\"},{\"role\": \"user\",\"content\": \"" + inputText + "\"}]}";httpResponseCode = http.POST(payload);if (httpResponseCode == 200) {response = http.getString();http.end();Serial.println(response);// Parse JSON responsedeserializeJson(jsonDoc, response);String outputText = jsonDoc["choices"][0]["message"]["content"];return outputText;// Serial.println(outputText);} else {http.end();Serial.printf("Error %i \n", httpResponseCode);return "<error>";}
}void setup() {//Serial.begin(921600);Serial.begin(115200);pinMode(ADC, ANALOG);pinMode(key, INPUT_PULLUP);pinMode(led, OUTPUT);// pinMode(ADC, ANALOG);// pinMode(buttonPin, INPUT_PULLUP);// pinMode(ledPin, OUTPUT);// start I2S at 16 kHz with 16-bits per sample// I2S.setAllPins(-1, 42, 41, -1, -1);// if (!I2S.begin(PDM_MONO_MODE, 16000, 16)) {//   Serial.println("Failed to initialize I2S!");//   while (1)//     ;  // do nothing// }uint8_t count = 0;WiFi.mode(WIFI_STA);WiFi.begin(ssid, password);while (WiFi.status() != WL_CONNECTED) {Serial.print(".");count++;if (count >= 75) {Serial.printf("\r\n-- wifi connect fail! --");break;}vTaskDelay(200);}Serial.printf("\r\n-- wifi connect success! --\r\n");Serial.println(WiFi.localIP());http.setTimeout(10000);// gain_token();timer = timerBegin(0, 80, true);    //  80M的时钟 80分频 1MtimerAlarmWrite(timer, 125, true);  //  1M  计125个数进中断  8KtimerAttachInterrupt(timer, &onTimer, true);timerAlarmEnable(timer);timerStop(timer);  //先暂停
}uint32_t time1, time2;
void loop() {if (digitalRead(key)==0) {Serial.printf("Start recognition\r\n\r\n");digitalWrite(led,HIGH);adc_start_flag = 1;timerStart(timer);// time1=micros();while (!adc_complete_flag)  //等待采集完成{ets_delay_us(10);}// time2=micros()-time1;timerStop(timer);adc_complete_flag = 0;  //清标志digitalWrite(led, LOW);memset(data_json, '\0', strlen(data_json));  //将数组清空strcat(data_json, "{");strcat(data_json, "\"format\":\"pcm\",");strcat(data_json, "\"rate\":8000,");                                                                        //采样率    如果采样率改变了,记得修改该值,只有16000、8000两个固定采样率strcat(data_json, "\"dev_pid\":1537,");                                                                      //中文普通话strcat(data_json, "\"channel\":1,");                                                                         //单声道strcat(data_json, "\"cuid\":\"666666\",");                                                                   //识别码    随便打几个字符,但最好唯一strcat(data_json, "\"token\":\"24.8f6143793af76191.2592000.1713789066.282335-57722200\",");  //token	这里需要修改成自己申请到的tokenstrcat(data_json, "\"len\":32000,");                                                                         //数据长度  如果传输的数据长度改变了,记得修改该值,该值是ADC采集的数据字节数,不是base64编码后的长度strcat(data_json, "\"speech\":\"");strcat(data_json, base64::encode((uint8_t*)adc_data, sizeof(adc_data)).c_str());  //base64编码数据strcat(data_json, "\"");strcat(data_json, "}");// Serial.println(data_json);int httpCode;http_client.setTimeout(5000);http_client.begin("http://vop.baidu.com/server_api");  //https://vop.baidu.com/pro_apihttp_client.addHeader("Content-Type", "application/json");httpCode = http_client.POST(data_json);if (httpCode == 200) {if (httpCode == HTTP_CODE_OK) {response = http_client.getString();http_client.end();Serial.println(response);// Parse JSON response// DynamicJsonDocument jsonDoc(512);deserializeJson(jsonDoc, response);String question = jsonDoc["result"][0];// 访问"result"数组,并获取其第一个元// 输出结果Serial.println("\n Input:" + question);answer = getGPTAnswer(question);Serial.println("Answer: " + answer);Serial.println("Enter a prompt:");} else {Serial.printf("[HTTP] GET... failed, error: %s\n", http_client.errorToString(httpCode).c_str());}}// while (!digitalRead(buttonPin))//   ;Serial.printf("Recognition complete\r\n");}// }vTaskDelay(1);
}

4. 上传验证

如果提示Compilation error: ArduinoJson.h: No such file or directory
在这里插入图片描述
直接在库管理安装Arduinojson
在这里插入图片描述

打开串口监视器,注意右下角选择换行符,选择115200波特率,输入你想问的问题,他就可以回答你

4.1 对话测试

在这里插入图片描述

串口发送“1”,开始录音,然后返回对话结果,以上是两次连续对话效果😘😘😘

4.2 报错

  1. 如果返回error ,大家对照列表查询错误代码,结合提示排查解决
    在这里插入图片描述
  2. 如果第一次可以二次自动重启
  3. 在这里插入图片描述
    可以配置下载程序运行在core0
    在这里插入图片描述

5. 总结

🥳🥳🥳现在,我们在本教程中,您学习了如何使用ESP32S3 Sense接入语音识别+MiniMax模型对话。🛹🛹🛹从而实现对外部世界进行感知,充分认识这个有机与无机的环境,后期会持续分享esp32跑freertos实用案列🥳🥳🥳科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣

如果你有任何问题,可以通过下面的二维码加入鹏鹏小分队,期待与你思维的碰撞😘😘😘

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Day53:WEB攻防-XSS跨站SVGPDFFlashMXSSUXSS配合上传文件添加脚本

目录 MXSS UXSS&#xff1a;Universal Cross-Site Scripting HTML&SVG&PDF&SWF-XSS&上传&反编译(有几率碰到) SVG-XSS PDF-XSS Python生成XSS Flash-XSS 知识点&#xff1a; 1、XSS跨站-MXSS&UXSS 2、XSS跨站-SVG制作&配合上传 3、XSS跨站-…

【MySQL】6.MySQL主从复制和读写分离

主从复制 主从复制与读写分离 通常数据库的读/写都在同一个数据库服务器中进行&#xff1b; 但这样在安全性、高可用性和高并发等各个方面无法满足生产环境的实际需求&#xff1b; 因此&#xff0c;通过主从复制的方式同步数据&#xff0c;再通过读写分离提升数据库的并发负载…

Spring Boot | SpringBoo“开发入门“

目录 : 1.SpringBoot的“介绍”SpringBoot”概述” &#xff1a;SpringBoot”简介“SpringBoot的“优点” 2. SpringBoot入门程序环境准备使用 “Maven”方式构建SpringBoot 项目使用“Spring Initializr”方式构建Spring Boot 项目 3. “单元测试” 和“热部署”单元测试热部署…

【算法刷题 | 二叉树 05】3.28(左叶子之和、找树 左下角的值)

文章目录 11.左叶子之和11.1问题11.2解法一&#xff1a;递归11.2.1递归思路11.2.2代码实现 11.3解法二&#xff1a;栈11.3.1栈思想11.3.2代码实现 12.找树左下角的值12.1问题12.2解法一&#xff1a;层序遍历 11.左叶子之和 11.1问题 给定二叉树的根节点 root &#xff0c;返回…

大模型时代下的“金融业生物识别安全挑战”机遇

作者&#xff1a;中关村科金AI安全攻防实验室 冯月 金融行业正在面临着前所未有的安全挑战&#xff0c;人脸安全事件频发&#xff0c;国家高度重视并提出警告&#xff0c;全行业每年黑产欺诈涉及资金额超过1100亿元。冰山上是安全事件&#xff0c;冰山下隐藏的是“裸奔”的技术…

STM32 PWM通过RC低通滤波转双极性SPWM测试

STM32 PWM通过RC低通滤波转双极性SPWM测试 &#x1f4cd;参考内容《利用是stm32cubemx实现双极性spwm调制 基于stm32f407vet6》&#x1f4fa;相关视频链接&#xff1a;https://www.bilibili.com/video/BV16S4y147hB/?spm_id_from333.788 双极性SPWM调制讲解以及基于stm32的代码…

主流公链 - BCH BSV BTG

为什么出现分叉 BTC是自由的&#xff0c;BTC社区也是自由的&#xff0c;自然而然的会出现不同观点的群体 1. 比特币现金&#xff08;Bitcoin Cash&#xff0c;BCH&#xff09; 分叉日期&#xff1a; 2017年8月1日主要目的&#xff1a; 提高比特币的交易吞吐量和降低交易费用技术…

文献学习(自备)

收官大作&#xff0c;多组学融合的新套路发NC&#xff01;&#xff01; - 知乎 (zhihu.com) Hofbauer cell function in the term placenta associates with adult cardiovascular and depressive outcomes | Nature Communications 病理性胎盘炎症会增加几种成人疾病的风险&a…

火车头通过关键词采集文章的原理

随着互联网信息的爆炸式增长&#xff0c;网站管理员和内容创作者需要不断更新和发布新的文章&#xff0c;以吸引更多的用户和提升网站的排名。而火车头作为一款智能文章采集工具&#xff0c;在这一过程中发挥着重要作用。本文将探讨火车头如何通过关键词采集文章&#xff0c;以…

【TB作品】MSP430G2553,超声波倒车雷达PCB,单片机,超声波SR04,键盘,oled,

题目 硬件&#xff1a;MSP430G2553、 SR04超声波传感器 、3*4键盘、 无源蜂鸣器、oled显示屏 软件 1 、实时显示测量得到的距离 2、按键设置一个报警门限数值&#xff0c;直接输入数值后确认 3、低于报警门限数值就开始报警&#xff0c;而且距离越近蜂鸣器的鸣叫频率越高 程序…

数据库索引及优化

数据库索引及优化 什么是索引&#xff1f; MySQL官方对索引的定义为&#xff1a;索引&#xff08;INDEX&#xff09;是帮助MySQL高效获取数据的数据结构。 索引的本质&#xff1a; 数据结构 为什么要引入索引&#xff1f; 引入索引的目的在于提高查询效率&#xff0c;就好像是…

深入浅出的揭秘游标尺模式与迭代器模式的神秘面纱 ✨

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自&#xff1a;设计模式深度解析&#xff1a;深入浅出的揭秘游标尺模式与迭代…

Zabbix6 - Centos7源码编译部署HA高可用集群手册

Zabbix6 - Centos7源码编译部署HA高可用集群手册 HA高可用集群 总所周知,在我们IT运维的圈圈中,HA高可用集群服务算是逼格最高的吧也是运维里保障力度最大的环境。 HA是HighlyAvailable缩写,是双机集群系统简称,提高可用性集群,是保证业务连续性的有效解决方案,一般有两个…

深入探讨多线程编程:从0-1为您解释多线程(下)

文章目录 6. 死锁6.1 死锁原因 6.2 避免死锁的方法加锁顺序一致性。超时机制。死锁检测和解除机制。 6. 死锁 6.1 死锁 原因 系统资源的竞争&#xff1a;&#xff08;产生环路&#xff09;当系统中供多个进程共享的资源数量不足以满足进程的需要时&#xff0c;会引起进程对2…

Fastadmin给列表数据绑定添加内容

不同及服务需要收集不同的字段&#xff0c;在服务列表处增加按钮&#xff0c;弹出管理字段列表&#xff0c;单独管理每个服务的字段。如下图&#xff0c;给不同的服务绑定不同表单字段&#xff0c;点击表单按钮弹出页面维护当前服务的字段。 实现代码 //初始化表格处添加按钮 …

Linux根据时间删除文件或目录

《liunx根据时间删除文件》和 《Linux 根据时间删除文件或者目录》已经讲述了根据时间删除文件或目录的方法。 下面我做一些补充&#xff0c;讲述一个具体例子。以删除/home目录下的文件为例。 首先通过命令&#xff1a; ls -l --time-style"%Y-%m-%d %H:%M:%S"…

软件验收报告都包含哪些内容?为什么要做验收测试?

验收测试报告用于评估软件产品是否满足预定的要求和标准,是软件测试的重要输出文档。 通过验收测试报告&#xff0c;开发团队可了解软件存在问题和改进方向&#xff0c;进行修复和优化。同时&#xff0c;报告也可作为软件交付用户时提供的必要文档之一&#xff0c;帮助用户更好…

初识C++ · 入门(1)

目录 前言&#xff1a; 1 命名空间 2 输入和输出 3 缺省参数 5 函数重载 前言&#xff1a; C与C语言是有一定交集的&#xff0c;可以理解为本贾尼在使用C语言的时候认为有缺陷&#xff0c;于是加了一些小语法进行改良&#xff0c;后来经过委员会的修改&#xff0c;C98问世…

华为云使用指南02

5.​​使用GitLab进行团队及项目管理​​ GitLab旨在帮助团队进行项目开发协作&#xff0c;为软件开发和运营生命周期提供了一个完整的DevOps方案。GitLab功能包括&#xff1a;项目源码的管理、计划、创建、验证、集成、发布、配置、监视和保护应用程序等。该镜像基于CentOS操…

【已修复】iPhone13 Pro 长焦相机水印(黑斑)修复 洗水印

iPhone13 Pro 长焦相机水印&#xff08;黑斑&#xff09;修复 洗水印 问题描述 iPhone13 Pro 后摄3倍相机有黑色斑点&#xff08;水印&#xff09;&#xff0c;如图所示&#xff0c; 后摄相机布局如图所示&#xff0c; 修复过程 拆机过程有风险&#xff0c;没有把握最好不要…