基于嵌入式的智能智能通风系统
基于嵌入式的智能智能通风系统
功能说明
通过微信小程序控制窗户的开关状体以及倒计时开关和定时开关,小程序上实时显示当前温度湿度和光照强度。
功能展示
02智能通风系统
Mqtt服务器
- http://www.yoyolife.fun/iot:Mqtt服务器,我是在这里注册的,免费一个,之后每个2块钱每月。主要是结构简单,用起来容易。
- 下位机即ESP32要选择
mqtt地址:t.yoyolife.fun 端口:1883
地址(里边有三个地址) - 微信小程序要选择
mqtt:wss地址:t.yoyolife.fun/mqtt 端口:8084
地址,不可选错。 - 两边的发布和订阅要对应起来,一个发布一个订阅,跟串口的Tx、Rx一样。服务器的主题可以随意定,意为服务器要监听哪个地址。
- 设备ID即是用户名,密码即是密码。
- 调试软件为mqttx,可自行下载https://mqttx.app/zh,调试下位机的时候可以连接上边提到的微信小程序8084那个端口,即服务器地址:
wss://t.yoyolife.fun
、端口:8084
、Path:/mqtt
、用户名即设备ID、密码即密码,然后订阅ESP32发布的那个地址,或者向ESP32订阅的那个地址发布信息。
程序思路
下位机每隔1秒发送当前状态数据,上位机改变值之后发送一次当前改变的数据。下位机接收之后再去分析是哪个数据,再去解析。
关于时间思路:接受NTP时间后,转为北京时间,然后将时间化为分钟,即小时x60+分钟。精度到分钟,然后秒等于0的话执行一次。然后上位机发送倒计时后,当前时间再加上倒计时的时间,得到一个时间A,当当前时间再走到时间A时就是倒计时结束的时间。关于定时开和定时关,也是如此,将时间化为分钟传递给下位机,下位机再获取当前时间去对比。
硬件制作
采用的是ESP32+微信小程序+Mqtt协议。
硬件选型
- ESP32开发板(VSCode+PlatformIO环境)
- DHT11温湿度传感器
- 光敏电阻
- 0.96寸OLED屏
- SG90舵机(用来开关窗户)
- 杜邦线若干
硬件连接
如图所示,需要注意的是光敏电阻接的是模拟位引脚,共电共地要外接可以找一排排针然后一端全部连在一起,板子3V3和GND出来后,分别插在一排上,然后需要共地和共电的地方插到排针上,注意千万要区分开来,否则短路会烧坏板子。
硬件程序
程序采用VSCode+PlatformIO环境。安装以下库
ArduinoJson
库:解析Mqtt协议收发的json格式数据。DHT sensor library
库:用于DHT11采集温湿度数据。NTPClient
库:获取网络NTP时间。PubSubClient
库:Mqtt通讯协议。U8g2
库:OLED显示库。
代码展示
以下展示部分重要代码,完整完成在文章末尾。
Mqtt连接
const char *ssid = "Hide_2805"; // ESP32连接的WiFi账号
const char *password = "asdfghjkl"; // WiFi密码
const char *mqttServer = "t.yoyolife.fun"; // 要连接到的服务器IP
const int mqttPort = 1883; // 要连接到的服务器端口号
const char *mqttUser = "75bdfb62a1c56065949702a3a6430e38"; // MQTT服务器账号
const char *mqttPassword = "123465"; // MQTT服务器密码
const char *mqttsub = "/iot/4432/wsy"; // MQTT订阅主题
const char *mqttpub = "/iot/4432/waa"; // MQTT发送主题WiFiClient espClient; // 定义wifiClient实例
PubSubClient client(espClient); // 定义PubSubClient的实例DynamicJsonDocument Json(1024); // 定义Json实例String Debug_Mqtt = "";// Mqtt回调函数
void callback(char *topic, byte *payload, unsigned int length)
{String Str = "";Serial.print("来自订阅的主题:"); // 串口打印:来自订阅的主题:Serial.println(topic); // 串口打印订阅的主题Serial.print("信息:"); // 串口打印:信息:for (int i = 0; i < length; i++) // 使用循环打印接收到的信息{Serial.print((char)payload[i]);Str += (char)payload[i];}Serial.println();Serial.println("-----------------------");Debug_Mqtt = Str;deserializeJson(Json, Str);if (Json.containsKey("debug")){Debug = Json["debug"].as<unsigned char>();}// 倒计时if (Json.containsKey("time")){Time = Json["time"].as<unsigned char>();if (Time)Time = Now_Time + Time;}if (Json.containsKey("open")){Open_Time = Json["open"].as<unsigned int>();if(Open_Time)Open_State = 1;elseOpen_State = 0;}if (Json.containsKey("close")){Close_Time = Json["close"].as<unsigned int>();if(Close_Time)Close_State = 1;elseClose_State = 0;Serial.println("Close_Time");Serial.println(Close_Time);}if (Json.containsKey("Win_State")){Win_State = Json["Win_State"].as<bool>();if (Win_State)Ment = true;elseMent = false;}Serial.print("Json:"); // 串口打印:来自订阅的主题:Serial.println(Debug_Mqtt); // 串口打印订阅的主题
}void WiFi_Click(void)
{while (WiFi.status() != WL_CONNECTED) // 若WiFi接入成功WiFi.status()会返回 WL_CONNECTED{Serial.println("连接wifi中"); // 串口输出:连接wifi中WiFi.begin(ssid, password); // 接入WiFi函数(WiFi名称,密码)重新连接wifdelay(2000); // 若尚未连接WiFi,则进行重连WiFi的循环}Serial.println("wifi连接成功"); // 连接wifi成功之后会跳出循环,串口并输出:wifi连接成功client.setServer(mqttServer, mqttPort); // MQTT服务器连接函数(服务器IP,端口号)client.setCallback(callback); // 设定回调方式,当ESP32收到订阅消息时会调用此方法while (!client.connected()) // 是否连接上MQTT服务器{Serial.println("连接服务器中"); // 串口打印:连接服务器中if (client.connect("ESP32Client", mqttUser, mqttPassword)) // 如果服务器连接成功{Serial.println("服务器连接成功"); // 串口打印:服务器连接成功}else{Serial.print("连接服务器失败"); // 串口打印:连接服务器失败Serial.print(client.state()); // 重新连接函数delay(2000);}}client.subscribe(mqttsub); // 连接MQTT服务器后订阅主题Serial.print("已订阅主题,等待主题消息...."); // 串口打印:已订阅主题,等待主题消息client.publish(mqttpub, "Hello from ESP32"); // 向服务器发送的信息(主题,内容)
}void Pub_Mqtt(void)
{char payload[200];StaticJsonDocument<200> jsonDocument; // 声明一个Json格式变量jsonDocument["windowstate"] = Ment;jsonDocument["temperature"] = Temp;jsonDocument["humidity"] = Humi;jsonDocument["light"] = Light;serializeJson(jsonDocument, payload);Serial.println(payload);client.publish(mqttpub, payload); // 向服务器发送的信息(主题,内容)son转换为字符串
}
主函数及时间片
// 时间片
void Time_Slice(void)
{if (F_Time_10ms){F_Time_10ms = 0;}if (F_Time_100ms){F_Time_100ms = 0;Display();Log_Print();// Ctrl_Motor();Ctrl_Window();}if (F_Time_500ms){F_Time_500ms = 0;Light = analogRead(LIGHT_PIN);Light = 100 - (Light * 100 / 4095);}if (F_Time_2s){F_Time_2s = 0;DHT11_Get();Pub_Mqtt();TimeClient.update();Serial.println(TimeClient.getFormattedTime());Hour = TimeClient.getHours();Min = TimeClient.getMinutes();Sec = TimeClient.getSeconds();Now_Time = Hour * 60 + Min;}if (F_Time_5s){F_Time_5s = 0;Serial.print("目前时间");Serial.println(Now_Time);Serial.print("开窗时间");Serial.println(Open_Time);Serial.print("关窗时间");Serial.println(Close_Time);Serial.print("倒计时时间");Serial.println(Time);}
}
// 初始化
void setup()
{Sys_Init();U8g2_Init();u8g2.setCursor(0, 8);u8g2.print("U8g2 OK!");u8g2.sendBuffer();Serial.begin(115200); // 串口函数,波特率设置u8g2.setCursor(0, 8 + 12 * 1);u8g2.print("串口 OK!");u8g2.sendBuffer();WiFi_Click();u8g2.setCursor(0, 8 + 12 * 2);u8g2.print("WiFi OK!");u8g2.sendBuffer();Timer0_Init();Motor_Init();TimeClient.begin();TimeClient.setTimeOffset(28800); //+1地区偏移3600u8g2.setCursor(0, 8 + 12 * 3);u8g2.print("NTP OK!");u8g2.sendBuffer();DHT.begin();u8g2.setCursor(0, 8 + 12 * 4);u8g2.print("DHT11 OK!");u8g2.sendBuffer();delay(2000);
}
// 主函数
void loop()
{client.loop(); // 回旋接收函数 等待服务器返回的数据Time_Slice();
}
舵机控制函数
// 控制窗户
void Ctrl_Window(void)
{if (Open_State){if (Open_Time == Now_Time){Ment = true;Open_State = 0;}}if (Close_State){if (Close_Time == Now_Time){Ment = false;Close_State = 0;}}if (Time){if (Time == Now_Time){Time = 0;Ment = !Ment;}}if (Ment){ledcWrite(2, 26);}else{ledcWrite(2, 70);}
}
硬件修改代码作为己用
用户如需借用代码,只需修改关键部分即可,例如Mqtt的Key、发布订阅地址,WiFi的账号密码等。
初始化修改
// 硬件宏定义
#define LED_Pin 2 // 板载LED
#define DHT11_Pin 4
#define DHTTYPE DHT11
#define LIGHT_PIN 33#define MOTOR_A1 12 // 预留步进电机
#define MOTOR_A2 14
#define MOTOR_A3 27
#define MOTOR_A4 26#define Lamp_Pin1 12
#define Lamp_Pin2 13
#define LED_Pin_Gnd 14
#define DuJ_Pin 25 // 开窗舵机const char *ssid = "Hide_2805"; // ESP32连接的WiFi账号
const char *password = "asdfghjkl"; // WiFi密码
const char *mqttServer = "t.yoyolife.fun"; // 要连接到的服务器IP
const int mqttPort = 1883; // 要连接到的服务器端口号
const char *mqttUser = "75bdfb62a1c56065949702a3a6430e38"; // MQTT服务器账号
const char *mqttPassword = "123465"; // MQTT服务器密码
const char *mqttsub = "/iot/4432/wsy"; // MQTT订阅主题
const char *mqttpub = "/iot/4432/waa"; // MQTT发送主题
callback函数中修改地方
// 倒计时
if (Json.containsKey("time")) // 判断当前接受的是哪个字符串
{Time = Json["time"].as<unsigned char>(); // 做一些处理if (Time)Time = Now_Time + Time;
}
Pub_Mqtt函数中修改地方
jsonDocument["windowstate"] = Ment;// 需要发布的Json键和值
jsonDocument["temperature"] = Temp;
jsonDocument["humidity"] = Humi;
jsonDocument["light"] = Light;
微信小程序制作
软件采用的是微信开发者工具,下载软件即可使用,无需复杂环境,成品直接发布就能使用,方便快捷。
软件程序
- 引入Mqtt的js包。
- 请求获取系统地址权限,请求天气API(高德),获取当地天气。
- 请求Mqtt服务器,订阅相关地址。
- 获取接受的数据,Json解析。
- 按键像相关地址发布Json数据。
下边是具体代码。
天气数据
getUserLocation: function () {let that = this;wx.getSetting({success: (res) => {console.log("天气", res);if (res.authSetting["scope.userLocation"] != undefined &&res.authSetting["scope.userLocation"] != true) {wx.showModal({title: "请求授权当前位置",content: "需要获取您的地理位置,请确认授权",success: function (res) {if (res.cancel) {wx.showToast({title: "拒绝授权",icon: "none",duration: 1000,});} else if (res.confirm) {wx.openSetting({success: function (dataAu) {if (dataAu.authSetting["scope.userLocation"] == true) {wx.showToast({title: "授权成功",icon: "success",duration: 1000,});//再次授权,调用wx.getLocation的APIthat.getLocation();} else {wx.showToast({title: "授权失败",icon: "none",duration: 1000,});}},});}},});} else if (res.authSetting["scope.userLocation"] == undefined) {//调用wx.getLocation的APIthat.getLocation();} else {//res.authSetting['scope.userLocation'] == true//调用wx.getLocation的APIthat.getLocation();}},});},getLocation() {let that = this;wx.getLocation({type: "wgs84",success(res) {console.log("经纬度", res);if (res?.errMsg === "getLocation:ok") {/* ----------------通过经纬度获取地区编码---------------- */wx.request({url: "https://restapi.amap.com/v3/geocode/regeo?parameters",data: {key: KEY, //填入自己申请到的Keylocation: res.longitude + "," + res.latitude, //传入经纬度},header: {"content-type": "application/json",},success: function (res) {console.log("坐标转换和查询天气", res.data);wx.setStorageSync("city",res.data.regeocode.addressComponent.adcode //地区编码);that.setData({location: res.data.regeocode.addressComponent.city +" " +res.data.regeocode.addressComponent.district,});wx.request({url: "https://restapi.amap.com/v3/weather/weatherInfo",data: {key: KEY, //填入自己申请到的Keycity: res.data.regeocode.addressComponent.adcode, //传入地区编码},header: {"content-type": "application/json",},success: function (weather) {console.log("天气", weather.data);that.setData({temp: weather.data.lives[0].temperature, //温度weatherText: weather.data.lives[0].weather, //天气描述 晴天 下雨天...welcome: "今天的天气是 " + weather.data.lives[0].weather + ",又是爱豆的一天!", //欢迎语});},});},});}},});},
Mqtt协议
connectMqtt() {let that = this;const options = {connectTimeout: 4000,address: "t.yoyolife.fun/mqtt", //输入的地址port: 8084, //输入的端口号username: "75bdfb62a1c56065949702a3a6430e38", //输入的用户名password: "123465", //输入的密码};console.log("address是:", options.address);client = mqtt.connect(MQTTADDRESS, options); //连接client.on("connect", (e) => {console.log('连接成功');})client.on("reconnect", (error) => {console.log("正在重连:", error);wx.showToast({icon: "none",title: "正在重连",});});client.on("error", (error) => {console.log("连接失败:", error);wx.showToast({icon: "none",title: "mqtt连接失败",});});// 订阅一个主题let message = this.data.push;client.subscribe(this.data.push, {qos: 0}, function (err) {if (!err) {console.log("订阅成功", message);wx.showToast({icon: "none",title: "添加成功",});}});client.on("message", (topic, message) => {console.log("收到地址:", topic);console.log("收到消息:", message.toString());let getMessage = {}; //收到的消息try {getMessage = JSON.parse(message); //收到的消息转换成json对象console.log(getMessage);that.setData({temperature: getMessage.temperature,humidity: getMessage.humidity,light: getMessage.light,windowsta: getMessage.windowstate,})} catch (error) {console.log("JSON解析失败!");}})}
修改代码作为己用
用户如需借用代码,只需修改关键部分即可,例如Mqtt的Key、发布订阅地址,WiFi的账号密码等。
程序初始化
const KEY = "1acc1391bf1593cf96f258d2f9ebe552"; //注意这里是高德地图的KEY 不是Mqtt服务器的KEYconst app = getApp();
import mqtt from "../../utils/mqtt.min"; //加载的Mqtt协议的文件名
const MQTTADDRESS = "wxs://t.yoyolife.fun/mqtt"; //mqtt服务器地址
data中数据
welcome: "你好,这里是Shiboven。",//主页显示push: "/iot/4432/waa", //订阅地址subscr: "/iot/4432/wsy", //发布地址
connectMqtt函数
const options = {connectTimeout: 4000, //重连时间address: "t.yoyolife.fun/mqtt", //Mqtt服务器地址port: 8084, //Mqtt服务器端口号username: "75bdfb62a1c56065949702a3a6430e38", //Mqtt用户名password: "123465", //Mqtt密码};
总结
项目本身功能简单,但是包含内容还是挺多的,扩展的话也比较容易。
项目地址:
https://download.csdn.net/download/weixin_42320020/88758864
相关文章:

基于嵌入式的智能智能通风系统
基于嵌入式的智能智能通风系统 功能说明 通过微信小程序控制窗户的开关状体以及倒计时开关和定时开关,小程序上实时显示当前温度湿度和光照强度。 功能展示 02智能通风系统 Mqtt服务器 http://www.yoyolife.fun/iot:Mqtt服务器,我是在这里注…...

如何编写一个好的测试用例?才能防止背黑锅
如何编写一个好的测试用例?才能防止背黑锅 什么是测试用例?一个好的测试用例包含什么?测试用例的编写思路总结 什么是测试用例? 在这之前,思考一个问题,下面这个简单的QQ登录页面,一共又多少条…...

笨蛋学设计模式行为型模式-观察者模式【14】
行为型模式-观察者模式 8.1观察者模式:arrow_up::arrow_up::arrow_up:8.1.1概念8.1.2场景8.1.3优势 / 劣势8.1.4观察者模式可分为观察者的基本结构: 8.1.5观察者模式8.1.6实战8.1.6.1题目描述8.1.6.2输入描述8.1.6.3输出描述8.1.6.4代码 8.1.7总结 8.1观察者模式⬆️…...

上海智慧岛大数据云计算中心项目正式封顶!
上海智慧岛大数据云计算中心封顶仪式现场 1月15日,云端股份在上海智慧岛大数据云计算中心举行封顶仪式。云之端网络(江苏)股份有限公司(以下称“云端股份”)总经理贡伟力先生,常务副总张靖先生等公司成员&…...

靶场实战(19):OSCP备考之VulnHub HA WORDY
交流技术可以关注公众号 OneMoreThink 或后台添加微信,欢迎提出宝贵建议。 0、总结 0.1、攻击思路 资产发现 主机发现服务发现漏洞发现(获取权限) 80端口/HTTP服务 组件漏洞URL漏洞:RFI、FileUpload提升权限 www-data用户 sudosui…...

大模型学习与实践笔记(九)
一、LMDeply方式部署 使用 LMDeploy 以本地对话方式部署 InternLM-Chat-7B 模型,生成 300 字的小故事 2.api 方式部署 运行 结果: 显存占用: 二、报错与解决方案 在使用命令,对lmdeploy 进行源码安装是时,报错 1.源…...

fpga目前就业形势咋样?
FPGA今年各厂给本科生的薪资大概是15-30K,研究生是20-40K,平均薪资在25k左右, 当然具体薪资还要看去哪个公司,哪个城市,以及个人的学校、专业、能力水平、及包括面试时的表现,运气等,这些都会导…...

Linux7 安装 Oracle 19C RAC 详细图文教程
实战篇:Linux7 安装 Oracle 19C RAC 详细图文教程 本文是按照:https://www.modb.pro/db/154424的思路进行编写 一、安装前规划 安装RAC前,当然要先做好规划。具体包含以下几方面: 节点主机版本主机名实例名Grid/Oracle版本Publi…...

【SpringBoot】SpringBoot 项目初始化方法
github 搜索 springboot 模板 github 搜索 springboot 模板,拉取现成代码。 SpringBoot 官方的模板生成器 SpringBoot 官方的模板生成器(https://start.spring.io/) 在 IDEA 开发工具中生成 这里我修改成阿里的镜像主要是要使用 Java8。 …...

34. 在排序数组中查找元素的第一个和最后一个位置(二分查找)
二分查找到目标值然后左右找到坐标 问题在于:找左右坐标的时候时间复杂度不是O(logN) class Solution {public int[] searchRange(int[] nums, int target) {int[] ans {-1, -1};if (nums.length 0) return ans;int l 0, r nums.length;while (l < r) {int…...

Mysql深度分页优化的一个实践
问题简述: 最近在工作中遇到了大数据量的查询场景, 日产100w左右明细, 会查询近90天内的数据, 总数据量约1亿, 业务要求支持分页查询与导出. 无论是分页或导出都涉及到深度分页查询, mysql通过limit/offset实现的深度分页查询会存在全表扫描的问题, 比如offset1000w, limit10…...

【JavaEE进阶】 SpringBoot配置⽂件
文章目录 🍀配置⽂件的作⽤🌴SpringBoot配置⽂件🎋配置⽂件的格式🎄properties配置⽂件🚩properties基本语法🚩读取配置⽂件🚩properties的缺点 🌳yml配置⽂件yml基本语法Ƕ…...

excel 常用函数
求和函数: SUM: 将单个值、单元格引用或区域相加。 案例:SUM(A1:A5) (结果:A1到A5单元格的值求和) SUMIF: 对选中范围内符合指定条件的值求和。 案例:SUMIF(B1:B5, ">50&qu…...

【React基础】– JSX语法
文章目录 认识JSX为什么React选择了JSXJSX的使用 React事件绑定this的绑定问题事件参数传递 React条件渲染React列表渲染列表中的key JSX的本质createElement源码Babel官网查看直接编写jsx代码 虚拟DOM的创建过程jsx – 虚拟DOM – 真实DOM声明式编程 阶段案例练习 认识JSX ◼ …...

SpringBoot 项目中后端实现跨域的5种方式!!!
文章目录 SpringBoot 项目中后端实现跨域的5种方式!!!一、为什么会出现跨域问题二、什么是跨域三、非同源限制四、Java后端 实现 CORS 跨域请求的方式1、返回新的 CorsFilter(全局跨域)2、重写 WebMvcConfigurer(全局跨域)3、使用注解 (局部跨…...

Vue3前端开发,provide和enject的基础练习,跨层级传递数据
Vue3前端开发,provide和enject的基础练习,跨层级传递数据! 声明:provide虽然可以跨层级传递,但是依旧是需要由上向下的方向传递。根传子的方向。 <script setup> import {onMounted, ref} from vue import Base from ./components/Base.vue impor…...

Python 循环结构值while循环
while循环是一种常用的循环结构,它会在满足特定条件的情况下重复执行一段代码块。 基本语法: while condition:# 循环体代码while循环的执行过程如下: 首先,判断循环条件condition(布尔表达式)是否为真。…...

MSSQL-识别扩展extended event(扩展事件)中的时间单位
经常使用sqlserver extended event(扩展事件),但是总是忘记扩展事件使用的时间单位,不确定它们是 秒、毫秒、还是微秒? 以下下代码能够从 相关DMV中提取description字段内容来识别时间单位: SELECT [p].[name] [package_name],[o…...

vue3中l和vue2中v-model不同点
vue2比较让人诟病的一点就是提供了两种双向绑定:v-model和.sync, 在vue3中,去掉了.sync修饰符,只需要使用v-model进行双向绑定即可。 为了让v-model更好的针对多个属性进行双向绑定(vue2中自定义组件中v-model只能使用…...

使用 Swift 代码优化项目编译速度
引言 软件的性能是评价一个软件质量的重要指标,尤其在今天这个时代,性能已成为大型项目不可或缺的考虑因素之一。对于用户量极大的软件,如网银系统、在线购物商城等,更是必须保证其高效稳定的性能。在这种背景下,优化…...

基于springboot+vue的社区团购系统(前后端分离)
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…...

three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>three.js从入门到精通系列教程002 - three.js正交相机OrthographicCamera</title><script src"ThreeJS/three.js"></script><script src&qu…...

Golang 搭建 WebSocket 应用(七) - 性能、可用性
在前面的文章中,提到过非功能性需求决定了架构。 今天我们再来考虑一下另外两个非功能性需求:性能和可用性。 前言 关于性能,其实并不是只有我们这个消息推送系统独有的问题。 对于所有的开发者而言,都多多少少会处理过性能相关…...

Qt 状态机框架:The State Machine Framework (一)
传送门: Qt 状态机框架:The State Machine Framework (一) Qt 状态机框架:The State Machine Framework (二) 一、什么是状态机框架 状态机框架提供了用于创建和执行状态图/表[1]的类。这些概念和表示法基于Harel的Statecharts:一种复杂系统的可视化形式,也是UML状态图的基…...

高通平台学习一
什么是QMI? Qualcom Message Interface 高通信息接口 高通平台目前都是非对称多核心,最主要的是AP和Modem。两个处理器怎么进行通信呢,我们把AP和Modem当作两个主机,问题就变得了很简单,TCP/IP协议不是一种非常成功的进程间跨主…...

Python爬虫时被封IP,该怎么解决?四大动态IP平台测评
在使用 Python 进行爬虫时,很有可能因为一些异常行为被封 IP,这主要是因为一些爬虫时产生的异常行为导致的。 在曾经的一次数据爬取的时候,我尝试去爬取Google地图上面的商家联系方式和地址信息做营销,可是很不幸,还只…...

积分梳状滤波器CIC原理与实现
CIC(Cascade Intergrator Comb):级联积分梳状滤波器,是由积分器和梳状滤波器级联而得。滤波器系数为1,无需对系数进行存储,只有加法器、积分器和寄存器,资源消耗少,运算速率高&#…...

【项目管理】CMMI-原因分析与解决过程(CAR)
概述: “原因分析与解决”通过预防缺陷或者问题的引入以及识别并适当纳入优秀过程性能的原因,改进质量与生产率。 目录 1、文档结构 2、原因分析与解决过程域包括如下活动 3、选择需要加以分析的结果(启动条件) 4、过程活动与实践对照表 5、实例 1、…...

【设计模式】文件目录管理是组合模式吗?
组合模式是什么? 组合模式是一种将对象组合成树形结构以表示"部分-整体"的层次结构的设计模式。它使得用户对单个对象和组合对象的使用具有一致性。 组合模式在什么情况下使用? 当你发现你需要在代码中实现树形数据结构,让整体-部…...

利用appium自动控制移动设备并提取数据
安装appium-python-client模块并启动已安装好的环境 安装appium-python-client模块 在window的虚拟环境下执行pip install appium-python-client 启动夜神模拟器,进入夜神模拟器所在的安装路径的bin目录下,进入cmd终端,使用adb命令建立adb…...