【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 压缩文件。
(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.inoCreated 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 headerint httpCode = https.GET();if (httpCode > 0) {// HTTP header has been send and Server response header has been handledSerial.printf("[HTTPS] GET... code: %d\n", httpCode);// file found at serverif (httpCode == HTTP_CODE_OK) {// get length of document (is -1 when Server sends no Content-Length header)int len = https.getSize();// create buffer for readstatic uint8_t buff[128] = { 0 };// read all data from serverint 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 sizesize_t size = client->available();if (size) {// read up to 128 byteint 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 connectionfetchBuffer();Serial.printf("\nAfter fetch, buffer size=%d\n", readBytesSize);delay(1000);if(readBytesSize) {// write it to Seriallog("===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 headerint httpCode = https.GET();if (httpCode > 0){// HTTP header has been send and Server response header has been handledSerial.printf("[HTTPS] GET... code: %d\n", httpCode);// file found at serverif (httpCode == HTTP_CODE_OK){// get length of document (is -1 when Server sends no Content-Length header)int len = https.getSize();// create buffer for readstatic uint8_t buff[128] = {0};// read all data from serverint offset = 0;// 为什么这里分配内存会报错?// if(inbuf==NULL) inbuf=(uint8_t*)malloc(sizeof(uint8_t)*128);while (https.connected() && (len > 0 || len == -1)){// get available data sizesize_t size = client->available();if (size){// read up to 128 byteint 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 SerialSerial.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博客
相关文章:

【NodeMCU实时天气时钟温湿度项目 7】和风天气API返回JSON数据信息的解压缩实现——ArduinoUZlib功能库
今天是第七专题,主要内容是:导入ArduinoUZlib功能库,借助该库把从【和风天气】官网返回的经过Gzip压缩的JSON数据,进行解压缩和t解析,在串口监视器上输出解析后的JSON信息。 如您需要了解其它专题的内容,请…...
leetcode题目9
回文数 简单 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数:是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 思路 对于数字进行反转&a…...
CNAME记录
CNAME记录 维基百科,自由的百科全书 (重定向自CNAME) 真实名称记录(英语:Canonical Name Record),即CNAME记录,是域名系统(DNS)的一种记录。CNAME记录用于…...
pytest + yaml 框架 -69.新增depend 关键字,导入其它yaml用例
前言 有小伙伴提到,test_a.yml 中已经写了几个流程,test_b.yml 中希望能接着test_a.yml去写用例,于是就需要先导入test_a.yml用例。 为了满足此需求,v1.6.3版本 在config 中新增 depend 关键字。 需求场景 test_a.yml 中已经写…...
【网络】tcp的初始化序列号为什么要随机生成
TCP序列号和确认序列号 在TCP协议中,每个数据包都包含一个序列号和一个确认序列号,用于实现可靠的数据传输和流量控制。 序列号(Sequence Number):序列号是发送端为每个发送的数据包分配的唯一标识,用于标…...

【SRC实战】利用APP前端加密构造数据包
挖个洞先 https://mp.weixin.qq.com/s/ZnaRn222xJU0MQxWoRaiJg “ 以下漏洞均为实验靶场,如有雷同,纯属巧合” 01 — 漏洞证明 “ 参数加密的情况,不会逆向怎么办?” 1、新用户首次设置密码时抓包,此处设置为0000…...
ThreadLocal描述
ThreadLocal是Java中的一个类,用于在多线程环境下存储和获取线程相关的数据。每个ThreadLocal对象都可以维护一个线程本地的变量副本,这意味着每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。这种特性使得ThreadLocal非常适合…...

Linux-基础命令第三天
1、命令:wc 作用:统计行数、单词数、字符数 格式:wc 选项 文件名 例: 统计文件中的行数、单词数、字符数 说明:59代表行数,111代表单词数,2713代表字符数,a.txt代表文件名 选项…...

Windows Server 2022 环境下WEB和DNS服务器配置方法
目录 实验名称:WEB和DNS服务器配置实验目的实验原理:主要设备、器材:实验内容:配置本地WEB站点配置本地DNS服务器 实验名称:WEB和DNS服务器配置 实验目的 掌握 Windows Server 2022 环境下WEB服务器配置方法 掌握 Wi…...

静态住宅代理 IP 的影响
在不断发展的在线业务和数字营销领域,保持领先地位势在必行。在业界掀起波澜的最新创新之一是静态住宅代理 IP 的利用。这些知识产权曾经是为精通技术的个人保留的利基工具,现在正在成为各行业企业的游戏规则改变者。 一、静态住宅代理IP到底是什么&…...

IP代理中的SOCKS5代理是什么?安全吗?
在互联网世界中,网络安全和个人隐私保护变得日益重要。SOCKS5代理作为一种安全高效的网络工具,不仅可以保护个人隐私安全,还可以提供更稳定、更快度的网络连接。本文将带大家深入了解SOCKS5代理在网络安全领域中的应用。 什么是SOCKS5代理 …...
一个用Kotlin编写简易的串行任务调度器
引言 由于项目中有处理大量后台任务并且串行执行的需求,特意写了一个简易的任务调度器,方便监控每个任务执行和异常情况,任务之间互不影响。正如上所述,Kotlin中的TaskScheduler类提供了一个强大的解决方案,用于使用S…...

JavaScript异步编程——11-异常处理方案【万字长文,感谢支持】
异常处理方案 在JS开发中,处理异常包括两步:先抛出异常,然后捕获异常。 为什么要做异常处理 异常处理非常重要,至少有以下几个原因: 防止程序报错甚至停止运行:当代码执行过程中发生错误或异常时&#x…...

python如何做一个服务器fastapi 和flask
用 fastapi 方式的话 from fastapi import FastAPIapp FastAPI()app.get("/api") def index():return "hello world"然后需要安装 uvicorn 并执行下面的命令 uvicorn server:app --port 8000 --reload最终 如果是用 flask 直接写下面的代码 # -*- cod…...
Element-ui el-table组件单选/多选/跨页勾选讲解
文章目录 一、el-table介绍二、el-table单选三、el-table多选四、el-table跨页勾选五、热门文章 一、el-table介绍 el-table 是 Element UI(一个基于 Vue.js 的高质量 UI 组件库)中的一个组件,用于展示表格数据。通过 el-table,你…...

CentOS 安装 SeaweedFS
1. SeaweedFS 介绍 SeaweedFS 是一个简单且高度可扩展的分布式文件系统。有两个目标: to store billions of files! (存储数十亿个文件!)to serve the files fast! (快速提供文件!) Seaweedfs的中心节点(center master)…...

Redis如何避免数据丢失?——AOF
目录 AOF日志 1. 持久化——命令写入到AOF文件 写到用户缓冲区 AOF的触发入口函数——propagate 具体的实现逻辑——feedAppendOnlyFile 从用户缓冲区写入到AOF文件(磁盘) 函数write、fsync、fdatasync Redis的线程池 AOF文件的同步策略 触发的入口函数——…...

xFormers
文章目录 一、关于 xFormers二、安装 xFormers三、基准测试(可选)测试安装 四、使用 xFormers1、Transformers 关键概念2、Repo 地图注意力机制Feed forward mechanismsPositional embeddingResidual pathsInitializations 3、主要特征4、安装故障排除 一…...

LQ杯当时的WP
RC4 32位程序用IDA打开看看 进行反汇编 RC4提示,就是一个加密 在sub_401005函数中找到输出的变量,并且立下断点 动调 Packet 字符串搜索flag 看到是给192.168.11.128发送了cat flag的命令 看到它回传 Base64加密了 解一下密码就可以 CC 密码这…...

数据结构与算法学习笔记三---栈和队列
目录 前言 一、栈 1.栈的表示和实现 1.栈的顺序存储表示和实现 1.C语言实现 2.C实现 2.栈的链式存储表示和实现 1.C语言实现 2.C实现 2.栈的应用 1.数制转换 二、队列 1.栈队列的表示和实现 1.顺序队列的表示和实现 2.链队列的表示和实现 2.循环队列 前言 这篇文…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...