【ESP32S3 Sense接入语音识别+MiniMax模型+TTS模块语音播报】

news2024/11/18 4:43:19

【ESP32S3 Sense接入语音识别+MiniMax模型+TTS模块语音播报】

  • 1. 前言
  • 2. 功能模块概述
    • 2.1 语音接入
    • 2.2 大模型接入
    • 2.3 TTS模块接入
  • 3. 先决条件
    • 3.1 环境配置
    • 3.2 所需零件
    • 3.3 硬件连接步骤
  • 4. 核心代码
    • 4.1 源码分享
    • 4.2 代码解析
  • 5. 上传验证
    • 5.1 对话测试
    • 5.2 报错
  • 6. 总结

1. 前言

大家好,今天的教程将围绕如何实现精准的语音播报功能展开,我们用到了ESP32S3 Sense接入语音识别+MiniMax模型对话+SNR9816TTS模块。
在这里插入图片描述

在后续的测试过程中,我们用到了一款极致实用的AI工具——海螺AI!(有问题,找海螺AI)它是MiniMax旗下的一款自研AI平台,专注于解决实际问题,可以让你的工作更高效、更便捷!
在这里插入图片描述
本博客文本作为输入海螺AI,生成了以下视频文案,还是非常不错哒!👍👍👍
在这里插入图片描述

海螺AI提供了多种实用功能,能够满足多种场景下的需求。比如,你可以用它来处理图片和文件、进行知识搜索和问答、生成代码和文案,让你的工作流更畅通无阻!
在这里插入图片描述

MiniMax是海螺的母公司,MiniMax最近推出了大法师计划,为全球大模型初创公司和开发者免费提供2000亿tokens,以促进通用人工智能设计开发行业的发展。(MiniMax大法师计划)

在这里插入图片描述

2. 功能模块概述

首先串口输入“1”字符,随后麦克风采集2s声音数据,对接百度在线语音识别,将返回文本结果丢入MiniMax模型,进而返回第二次结果文本,实现语言对话文本效果。经过以上两次调用后,载入TTS模块就可完整对话,实现精准的语音播报功能。

讲解视频:

2.1 语音接入

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

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

2.2 大模型接入

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

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

MiniMax是一家中国科技公司,一直致力于进行大模型相关的研究。近期提出了MINIMAX大法师计划,获取更多的2000亿token,为全球 AI大模型领域创业公司以及优秀的个人开发者提供了丰富的资源。
在这里插入图片描述

模型响应时间内容质量免费token次数地址
MiniMax3s8分500万+2000亿tokenhttps://www.minimaxi.com/
智谱清言7s8分300万https://open.bigmodel.cn/
文心一言10s9分500万https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu
通义千问8s8分800万https://tongyi.aliyun.com/qianwen/

结合以上图表对比,无能是回复文本的质量与速度方面,MiniMax是海螺的母公司,是MiniMax开展的大法师计划领先!!!😘😘😘

STT语音接入+大模型Chat接入整合教程见:【ESP32S3 Sense接入语音识别+MiniMax模型对话】

在这里插入图片描述

2.3 TTS模块接入

在这里插入图片描述

SNR9816TTS 是基于独家语音合成算法开发的一款高流畅度,高自然度的优美人声语音合成模块。该模块方案基于新一代的神经网络算法,纯中文版选取了优质的女声发音人(默认)和男声发音人(指令切换),中英文版只支持女声发音人,以满足各种应用场景的合成播报。

模块以中文为主,支持数字、英文(纯中文版:单个字母发音、中英文版:英文单词发音),文本编码支持GB2312。优异的合成效果(可懂度、清晰度、自然度、表现力、节奏/停顿、语速、语调、音质、音色、理解程度)方面有显著提升。

调试教程见:【Arduino使用SNR9816TTS模块教程】

3. 先决条件

这一次还是采用Arduino编程就会轻松许多开发。这样就可以通过stt+chat+tts把MiniMax语言大模型装进口袋啦🤣🤣🤣
在继续此项目之前,请确保检查以下先决条件。我们将使用 Arduino IDE 对 ESP32/ESP8266 开发板进行编程,因此在继续本教程之前,请确保已在 Arduino IDE 中安装这些开发板。此外,为了实现ESP32C3与SNR9816TTS模块的串口通信,请确保您已经安装了ESPSoftwareSerial和UTF8ToGB2312库。💕💕💕

3.1 环境配置

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

3.2 所需零件

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

名称端口功能购买地址
ESP32S3 SenseTXGPIO01 RXGPIO02主控官方地址
中文版 SNR9816TTSTXRX RXTXTTS模块淘宝地址

3.3 硬件连接步骤

  1. 电源连接:将SNR9816TTS模块的5V电源引脚连接到ESP32S3的5V输出端,模块的GND引脚连接到ESP32C3的GND。

  2. 串口通信:将SNR9816TTS模块的RX引脚连接到ESP32S3的GPIO01的TX引脚,模块的TX引脚连接到Arduino的GPIO02的RX引脚。这里使用软件串口(SoftwareSerial)库模拟额外的串行通信端口。

  3. 音响:喇叭(第 3、4 引脚)接到对应SPKN和SPKP引脚上,官方喇叭响度有点大,我拆了四六级听力耳机喇叭好多啦😘😘😘。
    在这里插入图片描述

4. 核心代码

下面准备进行了基于ESP32S3 Sense 的硬件测试,此部分有源码分享和代码解析两部分

4.1 源码分享

Arduino代码如下

#include <Arduino.h>
#include "base64.h"
#include <WiFi.h>
#include "HTTPClient.h"
#include "cJSON.h"
#include <I2S.h>
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
#include "UTF8ToGB2312.h"
#define MYPORT_TX 1
#define MYPORT_RX 2

EspSoftwareSerial::UART myPort;

uint8_t voicedata[] = { 0xFD, 0x00, 0x06, 0x01, 0x01, 0x5B, 0x76, 0x31, 0x5D };  //voicedata[7] =  0x31 ~ 0x39
// #define data_len 16000
// #define key 4             //端口0
// #define ADC 2             //端口39
// #define led 15            //端口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;
const int adc_data_len = 8000 * 3;
const int data_json_len = adc_data_len * 3;
uint16_t *adc_data;
char *data_json;
// uint16_t adc_data[data_len];    //16000个数据,8K采样率,即2秒,录音时间为2秒,想要实现更长时间的语音识别,就要改这个数组大小
// char data_json[json_len];          //用于储存json格式的数据,大一点,JSON编码后数据字节数变成原来的4/3,所以得计算好,避免出现越界
//和下面data_json数组的大小,改大一些。
uint8_t adc_start_flag = 0;     //开始标志
uint8_t adc_complete_flag = 0;  //完成标志


// 3. Replace with your MiniMax API key
const char *apiKey = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJHcm91cE5hbWUiOiIyMzQ1dm9yIiwiVXNlck5hbWUiOiIyMzQ1dm9yIiwiQWN.WlEj8Nk0j_WOMXZE9SbIC8sHpwJ6R6Pi8Spl5mahJsW3-Jsz7Ev53sGGz3v__Bd5dDkt7o9-Y8BOW0WZq2ImaN7Rof7YNtYnYnvPNDyGx23_xRqq5co9P5UkC3ciYEcIch2SUZ5QPkXR-sMUPzhdowSYvfdu1N25kdKJ8GE_63NfCnsdDVt8mv0wQSSweJK0yf_C8a8ADdB1uF4vg_WKMDjHlvzERsoNZgX6FYtr-bee85rIyu4U-OrbUvEpR1FLPXa7lTlx65QvhVIYGbIKde7ERIT_7QLOQoVFvPz0gX-H6V7UlmSRgRy4LK_R9mvV5TqCy3v90WK_AFuwEhPXcg";
// 3. Replace with your baidu voice detect token
String token = "24.8f6143793af71.2592000.1713789066.282335-57722200";
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 ISR
  portENTER_CRITICAL_ISR(&timerMux);
  if (adc_start_flag == 1) {
    //Serial.println("");
    // adc_data[num] = analogRead(ADC);
    adc_data[num] = I2S.read();
    num++;
    if (num >= adc_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 response
    deserializeJson(jsonDoc, response);
    String outputText = jsonDoc["choices"][0]["message"]["content"];
    return outputText;
    // Serial.println(outputText);
  } else {
    http.end();
    Serial.printf("Error %i \n", httpResponseCode);
    speech("语言大模型故障,请检查api是否失效");
    return "<error>";
  }
}

void speech(String data) {

  //0--空闲  1--繁忙  2--异常
  // while (workstate() > 0) {
  //   if (workstate() == 1) Serial.println("tts busy");
  //   if (workstate() == 2) Serial.println("tts wrong");
  // }
  String utf8_str = data;
  String gb2312_str = GB.get(utf8_str);
  unsigned char head[gb2312_str.length() + 6];
  // 定义无符号字符类型数组,将 GB2312 编码的字符串复制到数组中
  unsigned char gb2312_data[gb2312_str.length() + 1];
  memset(gb2312_data, 0, sizeof(gb2312_data));
  strncpy((char *)gb2312_data, gb2312_str.c_str(), gb2312_str.length());
  // head byte
  head[0] = 0xFD;
  // length bytes
  unsigned int dat_len = gb2312_str.length() + 3;
  head[1] = dat_len >> 8;
  head[2] = dat_len;
  // cmd byte
  head[3] = 0x01;
  // para byte
  head[4] = 0x01;
  // send each character individually
  for (int i = 0; i < gb2312_str.length(); i++) {
    head[i + 5] = gb2312_data[i];
  }
  // 计算异或值并添加到数组,额这个是syn那个芯片的例程,这个异或计算有没有用我懒得改了。反正代码能跑。
  head[gb2312_str.length() + 5] = head[0];
  for (int i = 1; i < gb2312_str.length() + 5; i++) {
    head[gb2312_str.length() + 5] ^= head[i];
  }
  // 发送字符数组到串口
  for (int j = 0; j < gb2312_str.length() + 6; j++) {
    myPort.write(head[j]);
  }
  delay(gb2312_str.length() * 100);
  // Serial.println(data);
}
// 查询tts合成工作状态 返回1表示繁忙 0表示空闲
int workstate() {
  unsigned char head[4] = { 0xFD, 0x00, 0x01, 0x21 };

  // 发送字符数组到串口
  for (int j = 0; j < 4; j++) {
    myPort.write(head[j]);
  }

  // 等待myPort的返回
  while (myPort.available() < 1) {
    // 可以在这里加入一些延时,以防止过快地查询
    delay(150);
  }

  // 读取并处理返回的数据
  byte response = myPort.read();

  // 返回相应的状态值
  if (response == 0x4E) {
    // 繁忙
    return 1;
  } else if (response == 0x4F) {
    // 空闲
    return 0;
  } else {
    // 未知状态,可以根据需要进行处理
    return 2;
  }
}


void setup() {

  //Serial.begin(921600);
  Serial.begin(115200);
  adc_data = (uint16_t *)ps_malloc(adc_data_len * sizeof(uint16_t));  //ps_malloc 指使用片外PSRAM内存
  if (!adc_data) {
    Serial.println("Failed to allocate memory for adc_data");
  }

  data_json = (char *)ps_malloc(data_json_len * sizeof(char));  // 根据需要调整大小
  if (!data_json) {
    Serial.println("Failed to allocate memory for data_json");
  }
  myPort.begin(115200, SWSERIAL_8N1, MYPORT_RX, MYPORT_TX, false);
  delay(1000);
  if (!myPort) {  // If the object did not initialize, then its configuration is invalid
    Serial.println("Invalid EspSoftwareSerial pin configuration, check config");
    while (1) {  // Don't continue with invalid configuration
      delay(1000);
    }
  }
  speech("系统开机");
  delay(1500);
  for (int i = 0; i < sizeof(voicedata) / sizeof(voicedata[0]); i++) {
    myPort.write(voicedata[i]);
  }
  delay(1000);
  speech("系统音量以调小");
  // 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(4000);
  http_client.setTimeout(4000);
  // gain_token();

  timer = timerBegin(0, 80, true);    //  80M的时钟 80分频 1M
  timerAlarmWrite(timer, 125, true);  //  1M  计125个数进中断  8K
  timerAttachInterrupt(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");
      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));  //将数组清空
      memset(data_json, '\0', data_json_len * sizeof(char));
      strcat(data_json, "{");
      strcat(data_json, "\"format\":\"pcm\",");
      strcat(data_json, "\"rate\":16000,");
      strcat(data_json, "\"dev_pid\":1537,");
      strcat(data_json, "\"channel\":1,");
      strcat(data_json, "\"cuid\":\"666666\",");
      strcat(data_json, "\"token\":\"");
      strcat(data_json, token.c_str());
      strcat(data_json, "\",");
      sprintf(data_json + strlen(data_json), "\"len\":%d,", adc_data_len * 2);
      strcat(data_json, "\"speech\":\"");
      strcat(data_json, base64::encode((uint8_t *)adc_data, adc_data_len * sizeof(uint16_t)).c_str());
      strcat(data_json, "\"");
      strcat(data_json, "}");
      // Serial.println(data_json);
      int httpCode;
      http_client.begin("http://vop.baidu.com/server_api");  //https://vop.baidu.com/pro_api
      http_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.print(response);
          // Parse JSON response
          // DynamicJsonDocument jsonDoc(512);
          deserializeJson(jsonDoc, response);
          String question = jsonDoc["result"][0];
          // 访问"result"数组,并获取其第一个元
          // 输出结果
          Serial.println("Input:" + question);
          answer = getGPTAnswer(question);
          speech(answer);
          Serial.println("Answer: " + answer);
          // Serial.println("Enter a prompt:");

        } else {
          Serial.printf("[HTTP] GET... failed, error: %s\n", http_client.errorToString(httpCode).c_str());
          speech("语音识别在线故障,请检查api是否失效");
        }
      }
      // while (!digitalRead(buttonPin))
      //   ;
      Serial.println("Recognition complete\r\n");
    }
  }
  vTaskDelay(1);
}

4.2 代码解析

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

  1. 引入必要的库文件,包括
    ① Arduino.h:包含Arduino核心库,提供了基本的Arduino函数和结构
    ② base64.h:引入一个用于Base64编码和解码的库
    ③ WiFi.h:用于连接WiFi网络的库
    ④ HTTPClient.h:用于Arduino上进行HTTP请求的库
    ⑤ cJSON.h:用于处理JSON数据的库
    ⑥ I2S.h:I2S(Inter-IC Sound)库,用于在Arduino上进行音频处理
    ⑦ ArduinoJson.h:ArduinoJson库,用于解析和生成JSON数据
    ⑧ SoftwareSerial.h:软串口库,用于模拟多个串口
    ⑨ UTF8ToGB2312.h:一个自定义的UTF-8到GB2312编码的转换库
    然后,定义了一些必要的常量和变量。

  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.eyJHcm91cE5hbWUiOiIyMzQ1dm9yIiwiVXNlck5hbWUiOiIyMzQ1d6Im1pbmltYXgifQ.WlEj8Nk0j_WOMXZE9SbIC8sHpwJ6R6Pi8Spl5mahJsW3-Jsz7Ev53sGGz3v__Bd5dDkt7o9-Y8BOW0WZq2ImaN7Rof7YNtYnYnvPNDyGx23_xRqq5co9P5UkC3ciYEcIch2SUZ5QPkXR-sMUPzhdowSYvfdu1N25kdKJ8GE_63NfCnsdDVt8mv0wQSSweJK0yf_C8a8ADdB1uF4vg_WKMDjHlvzERsoNZgX6FYtr-bee85rIyu4U-OrbUvEpR1FLPXa7lTlx65QvhVIYGbIKde7ERIT_7QLOQoVFvPz0gX-H6V7UlmSRgRy4LK_R9mvV5TqCy3v90WK_AFuwEhPXcg";

修改百度api

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

  2. 构建函数 getGPTAnswer() ,用于向一个预先定义的API发送HTTP POST请求,以获取对特定输入文本的GPT模型生成的响应。

  3. 构建函数 speech() ,用于将输入的文本数据转换为语音,并通过串口与语音合成模块进行通信,实现语音合成的功能。

  4. 构建函数 workstate(),用于查询语音合成模块的工作状态,并返回相应的状态值。

  5. setup()函数,它在程序开始时被调用,用于初始化设置和准备工作。具体来说,该函数会初始化系统各个部分的设置,包括串口通信、内存分配、软件串口、语音提示、GPIO设置、I2S音频初始化、Wi-Fi连接和定时器初始化。

  6. loop()函数,它在程序运行过程中会一直执行,用于处理主要的逻辑流程。具体来说,它主要负责监听串口输入,控制语音识别的启动、停止和结果处理,与百度语音识别API的交互,以及延时等待。

5. 上传验证

如果提示Compilation error: ArduinoJson.h: No such file or directory

在这里插入图片描述

直接在库管理安装Arduinojson

在这里插入图片描述

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

5.1 对话测试

在这里插入图片描述

代码优化后可以减少动态内存使用:3s语言输入,2s识别,5s交互播报

在这里插入图片描述

串口发送“1”,开始录音,然后返回对话结果,进行TTS语音播报😘😘😘

5.2 报错

  1. 如果返回error ,大家对照列表查询错误代码,结合提示排查解决

在这里插入图片描述
2. 如果第一次可以二次自动重启,可以配置下载程序运行在core0

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

  1. 百度在线语音识别错误码自查表
    在这里插入图片描述

6. 总结

博主强烈推荐大家使用🎈🎈🎈海螺AI并且加入大法师计划,支持国产!它是一款由MiniMax自研的,没有调用其他产品的接口的大型语言模型。作为一个强有力的生产力工具,无论是大学生还是职场人,海螺AI都能成为你的得力助手。💕💕💕

  1. 对于大学生,它可以帮助你提升论文写作的效率,解放你的创作灵感;在求职面试中,它能够为你提供丰富的资料和实用的建议,让你轻松应对各种挑战。👍👍👍
  2. 而对于职场人来说,海螺AI更是一个不可或缺的生产力工具,能够帮助你高效处理工作任务,提升工作效率,节省宝贵的时间。👍👍👍

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

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

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

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

相关文章

Zabbix6 - Web管理网络拓扑/端口流量监控配置手册

Zabbix6 - Web管理网络拓扑/端口流量监控配置手册 概述: 1)Zabbix能监视各种网络参数,保证服务器系统的安全运营;并提供灵活的通知机制以让系统管理员快速定位/解决存在的各种问题。 Zabbix由两部分构成,Zabbix Server与可选组件Zabbix Agent。通过C/S模式采集数据,通过B…

element-ui divider 组件源码分享

今日简单分享 divider 组件&#xff0c;主要有以下两个方面&#xff1a; 1、divider 组件页面结构 2、divider 组件属性 一、组件页面结构 二、组件属性 2.1 direction 属性&#xff0c;设置分割线方向&#xff0c;类型 string&#xff0c;horizontal / vertical&#xff0…

《QT实用小工具·九》设备按钮控件

1、概述 源码放在文章末尾 该项目实现了设备按钮控件&#xff0c;主要包含如下功能&#xff1a; 可设置按钮样式 圆形、警察、气泡、气泡2、消息、消息2。可设置按钮颜色 布防、撤防、报警、旁路、故障。可设置报警切换及对应报警切换的颜色。可设置显示的防区号。可设置是否…

【多线程】震惊~这是我见过最详细的ReentrantLock的讲解

一.与synchronized相比ReentrantLock具有以下四个特点: 可中断&#xff1a;synchronized只能等待同步代码块执行结束&#xff0c;不可以中断&#xff0c;强行终断会抛出异常, 而reentrantlock可以调用线程的interrupt方法来中断等待&#xff0c;继续执行下面的代码。 在获取锁…

学浪m3u8视频解密

学浪的m3u8中的key进行了加密&#xff0c;而且还是难度比较高的vmp&#xff0c;为了让非程序专业用户能够下载学浪的视频&#xff0c;这里将学浪key解密和学浪获取课程集成在一个软件 小浪助手:专门下载学浪视频而生 小浪助手我打包在一起 链接&#xff1a;https://pan.baid…

【信号处理】基于变分自编码器(VAE)的图片典型增强方法实现

关于 深度学习中&#xff0c;经常面临图片数据量较小的问题&#xff0c;此时&#xff0c;对数据进行增强&#xff0c;显得比较重要。传统的图片增强方法包括剪切&#xff0c;增加噪声&#xff0c;改变对比度等等方法&#xff0c;但是&#xff0c;对于后端任务的性能提升有限。…

Redis 主从复制,哨兵模式,集群

目录 主从复制 主从复制 作用 缺陷 主从复制流程 实现Redis主从复制 哨兵模式 主从复制切换的缺点 哨兵的核心功能 哨兵模式原理 哨兵模式的作用 哨兵结构组成 故障转移机制 主节点的选举 实现哨兵模式 集群(Cluster) redis群集有三种模式&#xff0c;主从复制…

解决PDF打开后显示名称与文档名称不一致的问题【不需要word模板!!!】

文章目录 简介原因解决办法参考资料 简介 最近&#xff0c;博主在使用Acobat打开一个PDF文件的时候发现&#xff1a;打开后的PDF文件标签跟该文件的存储名称不一致。这是一件令人并不十分愉快和顺心的事情&#xff0c;网上搜索得到的解决办法基本上都是出奇的相似&#xff0c;…

css心跳动画

图标引入 <img class"icon" src"heart.svg" alt"" srcset""> CSS代码 <style>.icon {animation:bpm 1s linear,pulse 0.75s 1s linear infinite;}keyframes pulse {from,75%,to {transform: scale(1);}25% {transform:…

趣学前端 | 类,我想好好继承它的知识点

背景 最近睡前习惯翻会书&#xff0c;重温了《JavaScript权威指南》。这本书&#xff0c;文字小&#xff0c;内容多。两年了&#xff0c;我才翻到第十章。因为书太厚&#xff0c;平时都充当电脑支架。 JavaScript 类 话说当年类、原型、继承&#xff0c;差点给我绕晕。 在J…

生成式AI的情感实验——AI能否产生思想和情感?

机器人能感受到爱吗&#xff1f;这是一个很好的问题&#xff0c;也是困扰了科学家们很多年的科学未解之谜。虽然我们尚未准备好向智能机器赋予情感&#xff0c;但智能机器却已经可以借助生成式人工智能&#xff08;AI&#xff09;来帮助我们表达自己的情感。 自然情感表达 AI正…

【子集回溯】Leetcode 78. 子集 90. 子集 II

【子集回溯】Leetcode 78. 子集 90. 子集 II 78. 子集90. 子集 II ---------------&#x1f388;&#x1f388;78. 子集 题目链接&#x1f388;&#x1f388;------------------- 78. 子集 class Solution {List<List<Integer>> result new ArrayList<>()…

Java 7、Java 8常用新特性

目录 Java 8 常用新特性1、Lambda 表达式2、方法引用2.1 静态方法引用2.2 特定对象的实例方法引用2.3 特定类型的任意对象的实例方法引用2.4 构造器引用 3、接口中的默认方法4、函数式接口4.1 自定义函数式接口4.2 内置函数式接口 5、Date/Time API6、Optional 容器类型7、Stre…

【随笔】Git 基础篇 -- 分支与合并 git rebase(十)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

【Pt】马灯贴图绘制过程 05-铁丝与渲染出图

目录 效果 步骤 一、基本材质 二、浮尘 三、渲染 效果 步骤 一、基本材质 CtrlAlt鼠标右键选中指定的纹理集 在智能材质中将“Iron Forged Old”加入图层 将智能材质“Iron Forged Old”文件夹打开&#xff0c;将图层“Base”和“Edge”的基本颜色改暗一点 二、浮尘 新…

PHP+python高校教务处工作管理系统q535p

开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp/Laravel 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 运行环境:phpstudy/wamp/xammp等 系统根据现有的管理模块进行开发和扩展&#xff0c;采用面向对象的开发的思想和结构化的开发方…

21.兼容性测试

考试频率低&#xff1b; 一般考兼容性测试会结合web测试&#xff1b;&#xff08;兼容性矩阵&#xff09; 主要议题&#xff1a; 1.兼容性测试概述 2.硬件兼容性测试 最低配置不讲究工作负载&#xff0c;意思是软件能够运行的最低要求环境&#xff1b; 推荐配置&#xff0c…

【精品方案】智慧金融大数据分析平台总体架构方案

以下是部分PPT内容&#xff0c;请您参阅。如需下载完整PPTX文件&#xff0c;请前往星球获取&#xff1a; 1.实现数据共享 通过数据平台实现数据集中&#xff0c;确保金融集团各级部门均可在保证数据隐私和安全的前提下使用数据&#xff0c;充分发挥数据作为企业重要资产的业务价…

Nacos 服务发现 快速入门

Nacos 服务发现 快速入门 一、Nacos 服务发现 – 什么是服务发现 &#xff1f; 1、 Nacos 服务发现-什么是服务发现 在微服务架构中&#xff0c;整个系统会按职责能力划分为多个服务&#xff0c;通过服务之间协作来实现业务目标。 这样在我们的代码中免不了要进行服务间的远程…

[HackMyVM]靶场Zurrak

难度:medium kali:192.168.56.104 靶机:192.168.56.140 端口扫描 # nmap -sV -A 192.168.56.140 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-30 16:59 CST Nmap scan report for 192.168.56.140 Host is up (0.00039s latency). Not shown: 996 closed tcp po…