【NodeMCU实时天气时钟温湿度项目 7】和风天气API返回JSON数据信息的解压缩实现——ArduinoUZlib功能库

        今天是第七专题,主要内容是:导入ArduinoUZlib功能库,借助该库把从【和风天气】官网返回的经过Gzip压缩的JSON数据,进行解压缩和t解析,在串口监视器上输出解析后的JSON信息。

        如您需要了解其它专题的内容,请点击下面的链接。
        第一专题内容,请参考:连接点亮SPI-TFT屏幕和UI布局设计
        第二专题内容,请参考:WIFI模式设置及连接
        第三专题内容,请参考:连接SHT30传感器,获取并显示当前环境温湿度数据(I2C)
        第四专题内容,请参考:通过NTPClient库获取实时网络时间并显示在TFT屏幕上
        第五专题内容,请参考:获取关于城市天气实况和天气预报的JSON信息(心知天气版)
        第六专题内容,请参考:解析天气信息JSON数据并显示在 TFT 屏幕上(心知天气版)

一、【心知天气】官网JSON数据特点

        1、订阅模式。和风天气开发服务采用订阅模式,当你创建项目时,至少需要选择一种订阅。使用和风天气的服务订阅非常简单和自由,免费或者你只需要为你实际使用的部分付费。现有三种订阅模式:免费订阅、标准订阅、高级订阅。
        每种订阅模式均可获取完整的天气信息数据。区别主要体现在数据请求量和更新频率方面。


        2、经过压缩的JSON数据。通过官网API接口返回的JSON数据,是进行Gzip压缩后的JSON数据,客户端需要先进行解压缩,然后再借助ArduinoJson功能库解析出解压缩后JSON数据,比心知天气返回JSON数据增加了一个解压缩过程。
        3、获取和风天气数据的方法。如果需要获得通过官网API接口返回的天气信息数据,需要首先心知天气注册账号、创建项目、选择订阅模式,然后获取API访问密钥KEY。具体操作方法网上有很多文档可供参考,请自行查询,比如:如何获取和风天气Web API的KEY?

二、添加ArduinoUZlib功能库

        1. ArduinoUZlib 的功能。该库是从uzlib移植到Arduino框架的功能库,主要用来解压https请求服务器返回的gzip数据。这个库占用内存比较小。
        2. 添加库方法。该库暂时无法从 PlatformIO 界面  -------> Libraries 加入。
        具体方法是:(1)进入该库 Github 网站,下载 zip 压缩文件。

        (2)解压 zip 文件,生 成ArduinoUZlib-main 文件夹。
        (3)将此文件夹复制到 项目目录下的 lib 文件夹内,就可以使用该库的全部功能了。
        

三、主要功能函数

        该库使用方法简单方便,主要是通过调用 ArduinoUZlib::decompress(inbuff, size, outbuf,outsize) 这个功能函数来实现。

size_t size = stream->available(); // 还剩下多少数据没有读完?
uint8_t inbuff[size]; // 准备一个数组来装流数据,有多少装多少
stream->readBytes(inbuff, size); // 将http流数据写入inbuff中
uint8_t *outbuf=NULL; //解压后的输出流
uint32_t outsize=0; // 解压后多大?在调用解压方法后会被赋值。
// 调用解压函数
int result=ArduinoUZlib::decompress(inbuff, size, outbuf,outsize);
// 输出解密后的数据到控制台。
Serial.write(outbuf,outsize);

        详细内容可参考该库 example 目录下的示例:StreamHttpsClientGzipDemo,用来解压缩返回的 gzip数据。       

/**
   StreamHTTPClient.ino

    Created on: 24.05.2015

*/
#include <ArduinoJson.h>
#include <Arduino.h>
#include "ArduinoUZlib.h" 
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>
ESP8266WiFiMulti WiFiMulti;

// ESP.getFreeHeap(), ESP.getMinFreeHeap(), ESP.getHeapSize(), ESP.getMaxAllocHeap()
void heap(){
  Serial.print("FREE_HEAP[");
  Serial.print(ESP.getFreeHeap());
  Serial.print("]\n");
}
void setup() {

  Serial.begin(115200);
  // Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  for (uint8_t t = 4; t > 0; t--) {
    Serial.printf("[SETUP] WAIT %d...\n", t);
    Serial.flush();
    delay(1000);
  }

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("ssid", "password");
}
void log(const char *str) {
  Serial.println(str);
}


static uint8_t buffer[1280]={0};
size_t readBytesSize=0;


void fetchBuffer() {

   if ((WiFiMulti.run() == WL_CONNECTED)) {
    std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
    client->setInsecure();
    Serial.print("[HTTPS] begin...\n");
    HTTPClient https;

    if (https.begin(*client, "https://192.168.2.144:8082/test")) {
      https.addHeader("Accept-Encoding", "gzip");
      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK) {

          // get length of document (is -1 when Server sends no Content-Length header)
          int len = https.getSize();

          // create buffer for read
          static uint8_t buff[128] = { 0 };

          // read all data from server
          int offset=0;
          Serial.println("allocate");
          //  为什么这里分配内存会报错?
          // if(inbuf==NULL) inbuf=(uint8_t*)malloc(sizeof(uint8_t)*128);
          while (https.connected() && (len > 0 || len == -1)) {
            // get available data size
            size_t size = client->available();
            
            if (size) {
              // read up to 128 byte
              int c = client->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
              // int c = client->readBytes(buff, size);
              // Serial.println("memcpy");
              memcpy(buffer+offset, buff, sizeof(uint8_t)*c);
              offset+=c;
              if(c>0 && c!=16) {
                log("======rb====");
                Serial.printf("%d,", buff[c-3]);
                Serial.printf("%d,", buff[c-2]);
                Serial.printf("%d,", buff[c-1]);
                log("\n======rb end====");
              }
              // write it to Serial
              // Serial.write(buff, c);
              if (len > 0) {
                len -= c;
              }
              
            }
            delay(1);
          }
          readBytesSize=offset;
          Serial.printf("offset=%d\n", offset);
          Serial.write(buffer, offset);
          Serial.print("[HTTPS] connection closed or file end.\n");

        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("Unable to connect\n");
    }
  }
}

void loop() {
  uint8_t *outbuf1=NULL;
  // wait for WiFi connection
  fetchBuffer();
  Serial.printf("\nAfter fetch, buffer size=%d\n", readBytesSize);
  delay(1000);
  if(readBytesSize) {
    // write it to Serial
    log("===buf===");
    Serial.printf("%d,", readBytesSize-3);
    Serial.printf("%d,", readBytesSize-2);
    Serial.printf("%d,", readBytesSize-1);
    log("\n===buf end===");    
    Serial.write(buffer,readBytesSize);
    uint32_t out_size=0;
    int result=ArduinoUZlib::decompress(buffer, readBytesSize, outbuf1, out_size);
    printf("outsize=%d, result=\n", out_size,result);
    parseJSON((char*)outbuf1, out_size);
    // Serial.write(outbuf,out_size);
  }else {
    Serial.println("no avali size!");
  }
if (outbuf1!=NULL){
  free(outbuf1);
  outbuf1=NULL;
}
  Serial.println("Wait 10s before the next round...");
  delay(5000);
}


void parseJSON(char *input, int inputLength) {
  // char* input;
  // size_t inputLength; (optional)
  DynamicJsonDocument doc(6144);
  DeserializationError error = deserializeJson(doc, input, inputLength);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  const char* code = doc["code"]; // "200"
  const char* updateTime = doc["updateTime"]; // "2022-12-05T15:35+08:00"
  const char* fxLink = doc["fxLink"]; // "http://hfx.link/1u0r1"

  for (JsonObject hourly_item : doc["hourly"].as<JsonArray>()) {

    // const char* hourly_item_fxTime = hourly_item["fxTime"]; // "2022-12-05T17:00+08:00", ...
    const char* hourly_item_fxTime = hourly_item["fxTime"]; // "2022-12-05T17:00+08:00", ...
    const char* hourly_item_temp = hourly_item["temp"]; // "15", "13", "13", "12", "11", "11", "10", "10", ...
    Serial.printf("%s,", hourly_item_temp);
    const char* hourly_item_icon = hourly_item["icon"]; // "100", "150", "150", "150", "150", "150", "150", ...
    const char* hourly_item_text = hourly_item["text"]; // "晴", "晴", "晴", "晴", "晴", "晴", "晴", "多云", "多云", ...
    const char* hourly_item_wind360 = hourly_item["wind360"]; // "22", "24", "30", "33", "33", "31", "30", ...
    const char* hourly_item_windDir = hourly_item["windDir"]; // "东北风", "东北风", "东北风", "东北风", "东北风", "东北风", ...
    const char* hourly_item_windScale = hourly_item["windScale"]; // "3-4", "3-4", "3-4", "3-4", "3-4", ...
    const char* hourly_item_windSpeed = hourly_item["windSpeed"]; // "16", "16", "16", "16", "14", "14", ...
    const char* hourly_item_humidity = hourly_item["humidity"]; // "57", "63", "63", "65", "66", "67", "68", ...
    const char* hourly_item_pop = hourly_item["pop"]; // "1", "3", "6", "6", "6", "6", "6", "6", "7", "7", ...
    const char* hourly_item_precip = hourly_item["precip"]; // "0.0", "0.0", "0.0", "0.0", "0.0", "0.0", ...
    const char* hourly_item_pressure = hourly_item["pressure"]; // "1013", "1013", "1012", "1012", "1012", ...
    const char* hourly_item_cloud = hourly_item["cloud"]; // "5", "5", "4", "4", "7", "9", "11", "33", "54", ...
    const char* hourly_item_dew = hourly_item["dew"]; // "7", "6", "6", "6", "5", "5", "5", "5", "5", "4", ...
  }
  Serial.println();
  JsonArray refer_sources = doc["refer"]["sources"];
  const char* refer_sources_0 = refer_sources[0]; // "QWeather"
  const char* refer_sources_1 = refer_sources[1]; // "NMC"
  const char* refer_sources_2 = refer_sources[2]; // "ECMWF"

  const char* refer_license_0 = doc["refer"]["license"][0]; // "CC BY-SA 4.0"

}

四、和风天气JSON数据的解压缩实现

        这是个实现解压缩和风天气JSON数据的简单示例:(1)将服务器进行Gzip压缩后返回的JSON数据,接收并保存到缓冲区 buffer 中;(2)调用 ArduinoUZlib::decompress(inbuffer, size, outbuffer,outsize) 解压 buffer 中的经过压缩的JSON数据,同时将解压后JSON数据保存到输出 outbuffer 中;(3)调用 ArduinoJson 库的 deserializeJson(doc, outbuffer) 函数,对明文JSON数据进行解析,并保存到实况天气数据结构 wd 中,然后通过串口监视器输出。
        具体内容,请仔细阅读下面的代码实现。

// 实时天气
struct weather_data
{
  int code = -1;               // API状态码,具体含义请参考状态码
  String updateTime = "";      // 当前API的最近更新时间
  String now_obsTime = "";     // 数据观测时间
  String now_temp = "0";       // 温度,默认单位:摄氏度
  int now_feelsLike = 0;       // 体感温度,默认单位:摄氏度
  String now_icon = "";        // 天气状况和图标的代码,图标可通过天气状况和图标下载
  String now_text = "";        // 天气状况的文字描述,包括阴晴雨雪等天气状态的描述
  String now_wind360 = "-1";   // 风向360角度
  String now_windDir = "";     // 风向
  String now_windScale = "-1"; // 风力等级
  int now_windSpeed = -1;      // 风速,公里/小时
  int now_humidity = -1;       // 相对湿度,百分比数值
  int now_precip = -1;         // 当前小时累计降水量,默认单位:毫米
  int now_pressure = -1;       // 大气压强,默认单位:百帕
  int now_vis = -1;            // 能见度,默认单位:公里
} wd;

void get_now_weather_data(JsonDocument &doc);

size_t readBytesSize = 0;

// 用来存放解压前的JSON数据
static uint8_t buffer[1280] = {0};

// 用来存放解压后的JSON数据
uint8_t *outbuffer = NULL;

// 获取实时天气数据
void get_now_Weather()
{
  // 检查WIFI是否连接
  if ((WiFi.status() == WL_CONNECTED))
  {
    // 准备发起请求
    std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
    client->setInsecure();
    Serial.print("[HTTPS] begin...\n");
    HTTPClient https;

    if (https.begin(*client, "https://devapi.qweather.com/v7/weather/now?key=" + key + "&location=" + cityid))
    {
      https.addHeader("Accept-Encoding", "gzip");
      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();
      if (httpCode > 0)
      {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK)
        {
          // get length of document (is -1 when Server sends no Content-Length header)
          int len = https.getSize();

          // create buffer for read
          static uint8_t buff[128] = {0};
          // read all data from server
          int offset = 0;
          //  为什么这里分配内存会报错?
          // if(inbuf==NULL) inbuf=(uint8_t*)malloc(sizeof(uint8_t)*128);
          while (https.connected() && (len > 0 || len == -1))
          {
            // get available data size
            size_t size = client->available();

            if (size)
            {
              // read up to 128 byte
              int c = client->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));

              memcpy(buffer + offset, buff, sizeof(uint8_t) * c);
              offset += c;
              // write it to Serial
              // Serial.write(buff, c);
              if (len > 0)
              {
                len -= c;
              }
            }
            delay(1);
          }
          readBytesSize = offset;

          delay(1000);
          if (readBytesSize)
          {
            // write it to Serial
            Serial.write(buffer, readBytesSize);
            Serial.println("");
            uint32_t out_size = 0;
            ArduinoUZlib::decompress(buffer, readBytesSize, outbuffer, out_size);

            Serial.write(outbuffer, out_size);

            // 调用解析函数
            JsonDocument doc;
            DeserializationError err = deserializeJson(doc, outbuffer);

            if (err.code() == DeserializationError::Ok)
            {
              get_now_weather_data(doc);
            }
            else
            {
              Serial.println("数据解析出错");
            }
          }
          else
          {
            Serial.println("no avali size!");
          }
          if (outbuffer != NULL)
          {
            free(outbuffer);
            outbuffer = NULL;
          }
        }
      }
      else
      {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }
      https.end();
    }
    else
    {
      Serial.printf("Unable to connect\n");
    }
  }
}

void get_now_weather_data(JsonDocument &doc)
{
  // 将数据保存到weahter_data 的结构体,方便后续调用

  Serial.println("");
  wd.code = doc["code"];
  wd.updateTime = doc["updateTime"].as<String>().substring(0, 16);
  wd.now_obsTime = doc["now"]["obsTime"].as<String>().substring(0, 16);
  wd.updateTime.replace("T", " ");
  wd.now_obsTime.replace("T", " ");

  wd.now_temp = doc["now"]["temp"].as<String>();
  wd.now_feelsLike = doc["now"]["feelsLike"].as<int>();
  wd.now_icon = doc["now"]["icon"].as<String>();
  wd.now_text = doc["now"]["text"].as<String>();
  wd.now_wind360 = doc["now"]["wind360"].as<String>();
  wd.now_windDir = doc["now"]["windDir"].as<String>();
  wd.now_windScale = doc["now"]["windScale"].as<String>();
  wd.now_windSpeed = doc["now"]["windSpeed"].as<int>();
  wd.now_humidity = doc["now"]["humidity"].as<int>();
  wd.now_precip = doc["now"]["precip"].as<int>();
  wd.now_pressure = doc["now"]["pressure"].as<int>();
  wd.now_vis = doc["now"]["vis"].as<int>();

  Serial.print("wd.code: ");
  Serial.println(wd.code);

  Serial.print("wd.updateTime: ");
  Serial.println(wd.updateTime);

  Serial.print("wd.now_obsTime: ");
  Serial.println(wd.now_obsTime);

  Serial.print("wd.now_temp: ");
  Serial.println(wd.now_temp);

  Serial.print("wd.now_feelsLike: ");
  Serial.println(wd.now_feelsLike);

  Serial.print("wd.now_icon: ");
  Serial.println(wd.now_icon);

  Serial.print("wd.now_text: ");
  Serial.println(wd.now_text);

  Serial.print("wd.now_wind360: ");
  Serial.println(wd.now_wind360);

  Serial.print("wd.now_windDir: ");
  Serial.println(wd.now_windDir);

  Serial.print("wd.now_windScale: ");
  Serial.println(wd.now_windScale);

  Serial.print("wd.now_windSpeed: ");
  Serial.println(wd.now_windSpeed);

  Serial.print("wd.now_humidity: ");
  Serial.println(wd.now_humidity);

  Serial.print("wd.now_precip: ");
  Serial.println(wd.now_precip);

  Serial.print("wd.now_pressure: ");
  Serial.println(wd.now_pressure);

  Serial.print("wd.now_vis: ");
  Serial.println(wd.now_vis);
}

五、解压缩JSON数据源代码下载和运行效果展示

        百度网盘下载:UZlib_Qweather_CompressedJsonData_7,  提取码:ivfq
        友情提示:(1)请务必将 ssid 和 password 修改成您所在环境的名称和密码;(2)请务必const String key 修改成您自己申请的和风天气API密钥。
        如果您能在串口监视器看到如下信息,那么恭喜您程序运行成功了。
        

参考文档
1. JSON 基本使用_json怎么用-CSDN博客
2. 如何获取和风天气Web API的KEY?(简要步骤)_天气预报web api key-CSDN博客
3. JSON——概述、JSON语法、序列化和反序列化_所有文档都可以通过json序列化吗-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

物联网应用开发--STM32与新大陆云平台通信(云平台控制开发板上蜂鸣器、LED)

实现目标 1、掌握云平台执行器的创建 2、熟悉STM32 与ESP8266模块之间的通信 3、具体实现目标&#xff1a;&#xff08;1&#xff09;创建5个执行器&#xff1a;蜂鸣器&#xff0c;LED1&#xff0c;LED2&#xff0c;ED3&#xff0c;LED4;&#xff08;2&#xff09;执行器能对…

CodeGeeX 智能编程助手 6 项功能升级,在Visual Studio插件市场霸榜2周!

CodeGeeX是支持适配Visual Studio 2019的唯一一款国产智能辅助编程工具&#xff0c;已经在Visual Studio趋势上霸榜2周&#xff01; CodeGeeX v1.0.4版本上线Visual Studio插件市场&#xff0c;带来了多项新功能和性能优化&#xff0c;提升编程体验。 新功能亮点速览&#xf…

用面向对象的思想编写实时嵌入式C程序

实时嵌入式系统的软件一般由C语言编写&#xff0c;程序结构基本上都是这样的&#xff1a; // 主程序 int main(void) {init(); // 初始化while(1){tick(); // 业务逻辑}return 0; }// 计时器 static unsigned int g_timer_tick_cnt 0; // 时钟中断回调 void isr_time…

Docker 基础认识

文章目录 概念铺垫&#xff08;1&#xff09;概念铺垫&#xff08;2&#xff09;概念铺垫 &#xff08;3&#xff09;概念铺垫&#xff08;4&#xff09;Docker 定义Docker 特点Docker 架构 概念铺垫&#xff08;1&#xff09; 虚拟化相关概念 物理机&#xff1a;实际的服务器…

【前端】CSS基础(2)

文章目录 前言1、CSS选择器1.1选择器的功能1.2 选择器的种类1.2.1 基础选择器1.2.1.1 标签选择器1.2.1.2 类选择器1.2.1.3 id选择器1.2.1.4 通配符选择器1.2.1.5 伪类选择器 1.2.2 复合选择器1.2.2.1 后代选择器1.2.2.2 子选择器1.2.2.3 并集选择器 前言 这篇博客仅仅是对CSS的…

vue3自定义指令​(通过指令钩子获得dom和钩子参数)

实现文本框自动获得焦点 Index.vue: <script setup> import { ref, onMounted } from vue import ./index.cssconst vFocus {mounted: (el, binding) > {el.focus()console.log(binding)} }onMounted(() > {}) </script><template><div class&qu…

JSPfilters过滤技术

1.创建动态web项目 2.创建filters的文件 3.创建主页面 4.配置xml项目 总结构 主页面代码 <% page language"java" contentType"text/html; charsetUTF-8"pageEncoding"UTF-8"%><!DOCTYPE html><html><head><meta cha…

C++学习第二十九课:C++ 输入输出流详解:从基础到高级应用

在 C 中&#xff0c;流&#xff08;stream&#xff09;是一种用于实现输入输出操作的抽象概念。流可以看作是字节的流动&#xff0c;这些字节可以从一个地方流向另一个地方&#xff0c;例如从键盘输入到程序中&#xff0c;或者从程序输出到屏幕。C 提供了一套完整的流库来处理各…

灵卡科技HDMI音视频采集及H.264编码一体化采集卡—LCC260

推荐一款由灵卡科技倾力打造的高品质HDMI音视频采集卡——LCC260。以创新的技术&#xff0c;精湛的工艺和卓越的性能&#xff0c;为您提供全方位的音视频解决方案。 LCC260是一款集HDMI音视频采集与H.264编码于一身的全功能采集卡。它的输入端配备了最先进的HDMI 1.4a标准接口&…

扩散模型diffusion model

一 什么是扩散模型 1.1 现有生成模型 已经有大量的方法证明深度生成模型能够模拟人类的想象思维&#xff0c;生成人类难以分辨真伪的内容&#xff0c;主要方法如下&#xff1a; 1、GAN&#xff1a;用神经网络训练生成器和判别器 GAN 的主要思想&#xff1a; GAN 就是一个互搏的…

ChatGPT-4o发布了,所有人都可以免费用

前言 美国时间 5 月 13 日&#xff0c;在 Sam Altman 缺席的情况下&#xff08;为什么缺席&#xff0c;猜测是可能后面还有更重磅的消息&#xff0c;这次的产品只是一个中间过渡产品&#xff09;&#xff0c;OpenAI CTO Mira Murati 介绍了新的 ChatGPT 产品 ChatGPT-4o。这个…

go语言基础1

1.token token是构成源程序的基本不可在分割单元。编译器编译源程序的第一步就是将源程序分割为一个个独立的token&#xff0c;这个过程就是词法分析。Go语言的token可以分为关键字、标识符、操作符、分隔符和字面常量等&#xff0c;如图所示&#xff1a; Go token分隔符有两类…

Vscode编辑器 js 输入log自动补全

最近换了新电脑&#xff0c;新下载了Vscode&#xff0c;记录一下设置项。 Vscode 版本 想要的效果 js文件中输入log&#xff08;点击tab键&#xff09;&#xff0c;自动补全为 console.log() Vscode 文件》首选项》设置 搜索&#xff1a;snippets Emmet: Show Suggestions…

计算机毕业设计源码 | 基于SpringBoot的线上教学系统 答疑辅导网站(附源码)

1&#xff0c;项目介绍 1.1 项目背景 网络问答平台经历了多年的发展&#xff0c;目前处于一个日益成熟的状态。最早的网络问答平台是知乎&#xff0c;知乎的创立者认为有许多信息在互联网上没有被记录和共享&#xff0c;于是他们决定创造一个平台&#xff0c;能够让更多人可以…

【强训笔记】day22

NO.1 思路&#xff1a;将情况全部枚举出来。 代码实现&#xff1a; #include <iostream> #include<string> using namespace std;string a,b; int main() {cin>>a>>b;int ma.size(),nb.size();int retm;for(int i0;i<n-m;i){int tmp0;for(int j…

软文撰写注意事项有哪些?

软文&#xff0c;作为一种隐性的广告形式&#xff0c;越来越受到企业的青睐。一篇高质量的软文&#xff0c;不仅能吸引读者的眼球&#xff0c;还能在潜移默化中传递品牌价值。撰写一篇高质量的软文&#xff0c;并非一蹴而就。从开头到发布&#xff0c;每一个环节都需要精心打磨…

Charger之二输入电压动态电源原理(VIN-DPM)

主要内容 Charger的VIN-DPM 前篇内容&#xff1a;电池管理IC&#xff08;Charger&#xff09;了解一下&#xff1f; 领资料&#xff1a;点下方↓名片关注回复&#xff1a;粉丝群 正文 一、 VIN-DPM概念 VIN-DPM是指输入电压动态电源管理&#xff08;Input voltage dynamic…

C++ QT设计模式 (第二版)

第3章 Qt简介 3.2 Qt核心模块 Qt是一个大库&#xff0c;由数个较小的库或者模块组成&#xff0c;最为常见的如下&#xff1a;core、gui、xml、sql、phonon、webkit&#xff0c;除了core和gui&#xff0c;这些模块都需要在qmake的工程文件中启用 QTextStream 流&#xff0c;Qdat…

表现孤独的短视频:成都鼎茂宏升文化传媒公司

表现孤独的短视频&#xff1a;孤独之美与心灵的对话 在短视频的浪潮中&#xff0c;有一种特殊的情感表达形式逐渐崭露头角——那就是表现孤独的短视频。这些视频以其独特的视角和深刻的情感内涵&#xff0c;引发了广大观众的共鸣。表现孤独的短视频&#xff1a;成都鼎茂宏升文…

activiti——网关配置

文章目录 前言网关介绍代码案例测试各项网关排他网关 ExclusiveGateway1、绘制流程图2、编写测试代码 并行网关ParallelGateway1、绘制流程图2、编写测试代码 包含网关InclusiveGateway1、绘制流程图2、编写测试代码 前言 在activiti工作流中&#xff0c;还有一个组件也很重要…