基于物联网设计的水稻田智能灌溉系统(STM32+华为云IOT)
一、项目介绍
随着科技的不断发展和人们生活水平的提高,农业生产也逐渐向智能化、高效化的方向发展。水稻作为我国主要的粮食作物之一,其生长过程中的灌溉管理尤为重要。传统的灌溉方式往往依赖于人工观察和控制,不仅效率低下,而且容易出现误差,无法满足现代农业生产的需求。
当前设计了一款基于STM32的水稻田智能灌溉系统。该系统能够通过水位传感器和温度传感器实时监测稻田的水位和水温,并根据设定的阈值自动控制水泵的开关,实现自动灌溉。同时,通过NBIOT模块将实时数据上传到华为云物联网云平台,用户可以通过手机APP远程监控和控制设备的运行,实现远程管理。相当于直接将水稻田搬到了云端,后期还会加入摄像头监控,加入图像处理,在家就可以了解到每一块稻田的生长情况。
整个系统的电源采用太阳能板供电。
整个系统的应用可以大大提高水稻灌溉的效率和准确性,减少人力资源的浪费,降低生产成本,并为农业生产提供更有力的技术保障。此外,系统还可以推广到其他领域的智能灌溉和控制中,具有广阔的市场应用前景。
二、设计需求
该系统通过水位传感器检测稻田的水位,根据预先设置的水位阈值,自动控制继电器开启水泵进行抽水灌溉,从而实现自动补充灌溉水。同时,温度传感器可以监测水温的变化,确保水温适宜。利用NBIOT模块实现与华为云物联网云平台的连接,将实时的水位和水温数据上传到云平台。
为了方便用户远程操作和监控,开发了手机APP。用户可以通过APP远程手动控制水泵的开关,实现远程操作。同时,手机APP可以实时显示设备上传的水温和水位数据,提供可视化的界面,方便用户监控农田状况。
主控芯片采用STM32F103C8T6,具有丰富的外设资源和良好的性能,能够满足系统的需求。水温检测方面采用DS18B20防水温度传感器,具有高精度和稳定性,可以准确地监测水温。NBIOT联网模块采用BC26,支持NB-IoT通信技术,能够实现与云平台的连接。云服务器采用华为云物联网服务器,提供稳定可靠的云端服务。手机APP采用Qt进行开发,可以在不同的平台上运行,并提供友好的用户界面和交互体验。
系统的功能主要包括以下几个方面:
(1)水位检测:系统需要通过水位传感器实时监测稻田的水位,并能够根据设定的阈值自动控制水泵的开关,实现自动灌溉。
(2)水温检测:系统需要通过温度传感器实时监测稻田的水温,并将数据传输到云平台进行远程监控。
(3)数据传输:系统需要通过NBIOT模块将实时水温和水位数据上传到华为云物联网云平台,实现远程监控和控制。
(4)远程控制:用户可以通过手机APP远程监控和控制设备的运行,包括水泵的开关和阈值的设置等。
(5)人机界面:手机APP需要提供友好的人机界面,能够实时显示设备上传的水温和水位数据,并提供相应的操作按钮。
在硬件选型方面,主要考虑了以下几个方面:
(1)主控芯片:选择了STM32F103C8T6作为主控芯片。STM32F103C8T6是一款基于ARM Cortex-M3内核的32位微控制器,具有高性能、低功耗、易于开发等优点。该芯片具有丰富的外设接口,能够满足本系统的需求。
(2)水位传感器:选择了防水型的水位传感器,以确保在潮湿环境下能够正常工作。该传感器具有高精度、高可靠性、低功耗等优点,能够满足本系统的需求。
(3)温度传感器:选择了DS18B20防水温度传感器,该传感器具有高精度、高可靠性、低功耗等优点,能够实时检测稻田的水温,并将数据传输到主控芯片。
(4)NBIOT模块:选择了BC26模块作为NBIOT通信模块。该模块具有低功耗、高稳定性、易于开发等优点,能够将实时数据上传到华为云物联网云平台。
(5)水泵:选择具有自动控制功能的水泵,能够根据主控芯片的控制信号自动开关。
三、华为云产品设备创建
这一章节主要是介绍华为云物联网云端产品与设备的创建流程。
3.1 开通物联网服务
地址: https://www.huaweicloud.com/product/iothub.html
点击总览
,查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。
总结:
端口号: MQTT (1883)
接入地址: e244e6efb9.st1.iotda-device.cn-north-4.myhuaweicloud.com
根据域名地址得到IP地址信息:
Microsoft Windows [版本 10.0.19045.3448]
(c) Microsoft Corporation。保留所有权利。C:\Users\11266>ping e244e6efb9.st1.iotda-device.cn-north-4.myhuaweicloud.com正在 Ping e244e6efb9.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:
来自 117.78.5.125 的回复: 字节=32 时间=41ms TTL=94
来自 117.78.5.125 的回复: 字节=32 时间=44ms TTL=94
来自 117.78.5.125 的回复: 字节=32 时间=43ms TTL=94
来自 117.78.5.125 的回复: 字节=32 时间=42ms TTL=94117.78.5.125 的 Ping 统计信息:数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):最短 = 41ms,最长 = 44ms,平均 = 42msC:\Users\11266>
MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口比较合适。 接下来的ESP8266就采用1883端口连接华为云物联网平台。
3.2 创建产品
(1)创建产品
点击产品页,再点击创建产品。
(2)填写产品信息
根据自己产品名字填写。
(3)品创建成功
(4)添加自定义模型
产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。
这个模型就是定义自己设备接下来需要向服务器上传那些数据类型。根据自己的数据类型进行编写。
3.3 添加设备
产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。
(1)注册设备
(2)根据自己的设备填写
设备标识码、密码这些根据自己情况认真填写。
(3)保存设备信息
创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。
创建之后,得到的设备信息如下:
{"device_id": "65113d05a559fd7cd41435f8_lock1","secret": "12345678"
}
(4)设备创建完成
可以点击设备进入到设备详情页面。
3.4 MQTT协议主题订阅与发布
(1)主题订阅格式
帮助文档地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
对于设备而言,一般会订阅平台下发消息给设备 这个主题。
设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。
如果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。
以当前设备为例,最终订阅主题的格式如下:
$oc/devices/{device_id}/sys/messages/down最终的格式:
$oc/devices/65113d05a559fd7cd41435f8_lock1/sys/messages/down
(2)主题发布格式
对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。
这个操作称为:属性上报。
帮助文档地址:https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html
根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结如下:
发布的主题格式:
$oc/devices/{device_id}/sys/properties/report最终的格式:
$oc/devices/65113d05a559fd7cd41435f8_lock1/sys/properties/report
发布主题时,需要上传数据,这个数据格式是JSON格式。上传的JSON数据格式如下:{"services": [{"service_id": <填服务ID>,"properties": {"<填属性名称1>": <填属性值>,"<填属性名称2>": <填属性值>,..........}}]
}
根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。根据这个格式,组合一次上传的属性数据:
{"services": [{"service_id": "lock","properties":{"lock":1}}]}
3.5 MQTT三元组
MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像我们平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。
接下来介绍,华为云平台的MQTT三元组参数如何得到。
(1)MQTT服务器地址
要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。
帮助文档地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home
MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。
根据上面的域名和端口号,得到下面的IP地址和端口号信息: 如果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。 (IP地址就是域名解析得到的)
华为云的MQTT服务器地址:117.78.5.125
域名:e244e6efb9.st1.iotda-device.cn-north-4.myhuaweicloud.com
华为云的MQTT端口号:1883
注意! 具体要看这里:
(2)生成MQTT三元组
华为云提供了一个在线工具,用来生成MQTT鉴权三元组: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。
下面是打开的页面:
填入设备的信息: (上面两行就是设备创建完成之后保存得到的)
得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。
ClientId 65113d05a559fd7cd41435f8_lock1_0_0_2023092508
Username 65113d05a559fd7cd41435f8_lock1
Password 1a3e7f486aa551bca7b6ff5c19c29d2006e940ec1f98ab416e10be1288106953
3.6 模拟设备登录测试
经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。
(1)填入登录信息
打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。
(2)打开网页查看
完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。
点击详情页面,可以看到上传的数据。
到此,云平台的部署已经完成,设备已经可以正常上传数据了。
四、硬件选型
下面是为了验证设计而选型的相关的硬件模型,能够实现最终的设计效果。 模型设计最终验证成功之后,重新画板选型硬件一体化设计产品就方便多了。
【1】STM32开发板
【2】水泵电机
【3】BC26-NBIOT
【4】水温检测
【5】水位检测
链接:https://item.taobao.com/item.htm?spm=a21n57.1.0.0.636b523cIyIKxC&id=735112974467&ns=1&abbucket=19#detail
【6】太阳能板
五、代码设计
5.1 主函数代码框架
#include "stm32f10x.h"
#include "ds18b20.h"
#include "nbiot.h"// 定义水位传感器引脚和继电器引脚
#define WATER_LEVEL_PIN GPIO_Pin_0
#define WATER_LEVEL_PORT GPIOA
#define RELAY_PIN GPIO_Pin_1
#define RELAY_PORT GPIOA// 定义温度传感器引脚
#define TEMP_SENSOR_PIN GPIO_Pin_2
#define TEMP_SENSOR_PORT GPIOA// 定义NBIOT模块和云服务器相关参数
#define NBIOT_RX_PIN GPIO_Pin_3
#define NBIOT_RX_PORT GPIOA
#define NBIOT_TX_PIN GPIO_Pin_4
#define NBIOT_TX_PORT GPIOA
#define SERVER_ADDRESS "your_server_address"
#define DEVICE_ID "your_device_id"
#define DEVICE_KEY "your_device_key"// 定义APP开关水泵控制命令
#define CMD_PUMP_ON '1'
#define CMD_PUMP_OFF '0'// 初始化函数
void init();
// 获取水位值
uint8_t getWaterLevel();
// 控制水泵
void controlPump(uint8_t state);
// 获取温度值
float getTemperature();
// 更新数据到华为云服务器
void updateDataToCloud(float temperature, uint8_t waterLevel);
// 处理NBIOT模块接收到的命令
void handleNBIOTCommand(char cmd);int main(void) {// 初始化init();while (1) {// 获取水位值uint8_t waterLevel = getWaterLevel();// 控制水泵controlPump(waterLevel);// 获取温度值float temperature = getTemperature();// 更新数据到华为云服务器updateDataToCloud(temperature, waterLevel);// 处理NBIOT模块接收到的命令char command = receiveNBIOTCommand();handleNBIOTCommand(command);}
}void init() {// 初始化GPIO和相关外设// ...// 初始化DS18B20温度传感器DS18B20_Init(TEMP_SENSOR_PIN);// 初始化NBIOT模块NBIOT_Init(NBIOT_RX_PIN, NBIOT_TX_PIN, SERVER_ADDRESS, DEVICE_ID, DEVICE_KEY);
}uint8_t getWaterLevel() {// 读取水位传感器的值// ...
}void controlPump(uint8_t state) {if (state == 0) {// 关闭继电器,停止水泵GPIO_ResetBits(RELAY_PORT, RELAY_PIN);} else {// 打开继电器,启动水泵GPIO_SetBits(RELAY_PORT, RELAY_PIN);}
}float getTemperature() {// 读取温度传感器的值// ...
}void updateDataToCloud(float temperature, uint8_t waterLevel) {// 将温度和水位值上传到华为云服务器// ...
}void handleNBIOTCommand(char cmd) {if (cmd == CMD_PUMP_ON) {// 手机APP发送打开水泵的命令controlPump(1);} else if (cmd == CMD_PUMP_OFF) {// 手机APP发送关闭水泵的命令controlPump(0);}
}
5.2 BC26模块代码
#include <stm32f10x.h>
#include <usart.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <delay.h>// 定义BC26串口
#define BC26_USART USART1// 定义MQTT服务器信息
#define MQTT_SERVER_IP "192.168.1.100"
#define MQTT_SERVER_PORT "1883"
#define MQTT_USERNAME "username"
#define MQTT_PASSWORD "password"
#define MQTT_CLIENT_ID "client_id"// 串口发送字符串
void sendString(const char *str) {while (*str) {USART_SendData(BC26_USART, *str++);while (USART_GetFlagStatus(BC26_USART, USART_FLAG_TC) == RESET);}
}// 延时等待响应
bool waitForResponse(const char *response, uint32_t timeout) {uint32_t startTime = millis();uint32_t elapsedTime = 0;uint8_t rxData = 0;uint8_t responseIndex = 0;while (elapsedTime < timeout) {if (USART_GetFlagStatus(BC26_USART, USART_FLAG_RXNE) != RESET) {rxData = USART_ReceiveData(BC26_USART);if (rxData == response[responseIndex]) {responseIndex++;if (response[responseIndex] == '\0') {return true; // 收到完整响应}} else {responseIndex = 0; // 重置响应索引}}elapsedTime = millis() - startTime;}return false; // 超时未收到完整响应
}// 初始化BC26模块
bool initBC26Module() {sendString("AT+CFUN=1\r\n"); // 设置BC26模块为全功能模式if (!waitForResponse("OK", 1000)) {return false;}sendString("AT+CIMI\r\n"); // 获取SIM卡的IMSI号码if (!waitForResponse("OK", 1000)) {return false;}sendString("AT+QCFG=\"nwscanmode\",0,1\r\n"); // 设置网络扫描模式为自动模式if (!waitForResponse("OK", 1000)) {return false;}sendString("AT+QCFG=\"iotopmode\",2,1\r\n"); // 设置连接模式为Cat M1/NB1优先模式if (!waitForResponse("OK", 1000)) {return false;}sendString("AT+QICSGP=1,1,\"your_apn\",\"\",\"\",1\r\n"); // 配置APN参数,根据具体网络运营商设置if (!waitForResponse("OK", 1000)) {return false;}sendString("AT+QIACT=1\r\n"); // 激活PDP上下文if (!waitForResponse("OK", 10000)) {return false;}sendString("AT+QMTOPEN=0,\"");sendString(MQTT_SERVER_IP); // 连接MQTT服务器sendString("\",");sendString(MQTT_SERVER_PORT);sendString("\r\n");if (!waitForResponse("+QMTOPEN: 0,0", 20000)) {return false;}sendString("AT+QMTCONN=0,\"");sendString(MQTT_CLIENT_ID); // 使用指定的Client ID连接MQTT服务器sendString("\",\"");sendString(MQTT_USERNAME);sendString("\",\"");sendString(MQTT_PASSWORD);sendString("\"\r\n");if (!waitForResponse("+QMTCONN: 0,0,0", 10000)) {return false;}return true; // 初始化成功
}int main(void) {// 初始化系统时钟等USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 9600;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_Init(BC26_USART, &USART_InitStructure);USART_Cmd(BC26_USART, ENABLE);initBC26Module();while (1) {// 执行其他操作或处理MQTT消息}
}
5.3 电机控制代码
#include <stm32f10x.h>
#include <stdbool.h>// 定义电机引脚
#define MOTOR_PORT GPIOA
#define MOTOR_PIN GPIO_Pin_0// 初始化电机引脚
void initMotor() {// 使能GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 初始化GPIO引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = MOTOR_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(MOTOR_PORT, &GPIO_InitStructure);
}// 控制电机状态
void setMotorState(bool enabled) {if (enabled) {GPIO_SetBits(MOTOR_PORT, MOTOR_PIN); // 电机打开} else {GPIO_ResetBits(MOTOR_PORT, MOTOR_PIN); // 电机关闭}
}int main(void) {// 初始化系统时钟等initMotor();while (1) {// 控制电机状态setMotorState(true); // 打开电机// 延时一段时间setMotorState(false); // 关闭电机// 延时一段时间}
}
5.4 水位检测代码
#include <stm32f10x.h>
#include <stdio.h>
#include <delay.h>// 定义ADC引脚和通道
#define ADC_PORT GPIOA
#define ADC_PIN GPIO_Pin_0
#define ADC_CHANNEL ADC_Channel_0// ADC初始化
void initADC() {// 使能ADC时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);// 初始化GPIO引脚GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = ADC_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;GPIO_Init(ADC_PORT, &GPIO_InitStructure);// 初始化ADC参数ADC_InitTypeDef ADC_InitStructure;ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // 独立模式ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 单通道扫描模式ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // 连续转换模式ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 不用外部触发ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐ADC_InitStructure.ADC_NbrOfChannel = 1; // 采样通道数量ADC_Init(ADC1, &ADC_InitStructure);// 配置ADC采样通道ADC_RegularChannelConfig(ADC1, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);// 使能ADCADC_Cmd(ADC1, ENABLE);// ADC校准ADC_ResetCalibration(ADC1);while (ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1));
}// 读取ADC转换值
uint16_t readADC() {ADC_RegularChannelConfig(ADC1, ADC_CHANNEL, 1, ADC_SampleTime_55Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE);while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));return ADC_GetConversionValue(ADC1);
}int main(void) {// 初始化系统时钟等initADC();while (1) {uint16_t adcValue = readADC();printf("ADC Value: %d\r\n", adcValue);// 进行水位传感器的处理和其他操作delay_ms(1000); // 延时1秒}
}
5.5 水温检测代码
#include <stm32f10x.h>
#include <delay.h>// 定义温度传感器引脚
#define TEMPERATURE_PIN GPIO_Pin_1
#define TEMPERATURE_GPIO GPIOA// 初始化温度传感器
void initTemperatureSensor() {GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = TEMPERATURE_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 使用开漏输出模式GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(TEMPERATURE_GPIO, &GPIO_InitStructure);
}// 发送复位信号
void resetSensor() {GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(500);GPIO_ResetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(500);GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(500);
}// 读取一位数据
uint8_t readBit() {uint8_t data = 0;GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(2);GPIO_ResetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(2);GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(1);if (GPIO_ReadInputDataBit(TEMPERATURE_GPIO, TEMPERATURE_PIN)) {data = 1;}delay_us(60);return data;
}// 读取一个字节数据
uint8_t readByte() {uint8_t byte = 0;for (int i = 0; i < 8; i++) {byte |= readBit() << i;}return byte;
}// 写入一位数据
void writeBit(uint8_t bit) {GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(2);GPIO_ResetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);delay_us(2);if (bit) {GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);}delay_us(60);GPIO_SetBits(TEMPERATURE_GPIO, TEMPERATURE_PIN);
}// 写入一个字节数据
void writeByte(uint8_t byte) {for (int i = 0; i < 8; i++) {writeBit(byte & 0x01);byte >>= 1;}
}// 获取温度值
float getTemperature() {uint8_t temperature[2];resetSensor();writeByte(0xCC); // 跳过ROM命令writeByte(0x44); // 启动温度转换命令delay_ms(800); // 等待转换完成resetSensor();writeByte(0xCC); // 跳过ROM命令writeByte(0xBE); // 读取温度值命令temperature[0] = readByte();temperature[1] = readByte();int16_t rawTemperature = (temperature[1] << 8) | temperature[0];float temp = rawTemperature * 0.0625;return temp;
}int main(void) {// 初始化系统时钟等initTemperatureSensor();while (1) {float temperature = getTemperature();// 处理温度数据}
}
六、上位机开发
这篇主要介绍硬件端的设计、华为云物联网服务器端的设计。下一篇详细介绍WEB网页端、手机APP和微信小程序的开发。
相关文章:
基于物联网设计的水稻田智能灌溉系统(STM32+华为云IOT)
一、项目介绍 随着科技的不断发展和人们生活水平的提高,农业生产也逐渐向智能化、高效化的方向发展。水稻作为我国主要的粮食作物之一,其生长过程中的灌溉管理尤为重要。传统的灌溉方式往往依赖于人工观察和控制,不仅效率低下,而…...
【数据结构】数据结构初识
前言: 数据结构是计算存储,组织数据的方式。数据结构是指相互间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 Data Structure Vi…...
java多线程测试websocket demo(使用文件流)
这个demo主要是利用Java多线程来测试WebSocket通信。首先,创建一个WebSocket服务器和客户端,然后使用多线程来模拟多个客户端同时连接服务器进行通信。通过多线程测试,可以验证WebSocket通信的并发性能和稳定性。同时,可以通过多线…...
Tosei 自助网络店铺管理系统network_test.php_RCE漏洞复现
简介 Tosei 自助洗衣机是日本一家公司的产品,在 network_test.php 文件存在命令执行 漏洞复现 FOFA语法: body="tosei_login_check.php" 主要是日本 访问界面如下所示: 验证POC: /cgi-bin/network_test.php 拼接访问url: https://ip:port/cgi-bin/network_tes…...
uni-app 国际化
vue i18n v9的迁移后的$t()无法获取数组、对象 http://t.csdnimg.cn/WkCHy api:vue i18n [intlify] Not found ‘language’ key in ‘zh-Hans’ locale messages. [intlify] Fall back to translate ‘language’ key with ‘zh’ locale. [intlify] Not found ‘languag…...
git:git reset 和 git revert
在使用 git 进行项目开发的过程中,有时会出现错误提交的情况,这时就需要能够撤销错误的提交,将代码恢复到提交之前的样子。根据不同情况,可以使用 git reset 或 git revert 命令。 一. git reset git reset 的原理是修改 HEAD 的…...
LeetCode:670. 最大交换(Java 贪心)
目录 670. 最大交换 题目描述: 实现代码与解析; 贪心 原理思路: 670. 最大交换 题目描述: 给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释…...
【STM32】STM32学习笔记-Unix时间戳(41)
00. 目录 文章目录 00. 目录01. Unix时间戳02. UTC/GMT03. 时间戳转换04. C 标准库 <time.h>05. 时间相关函数示例5.1 time函数5.2 gmtime函数5.3 localtime函数5.4 mktime函数5.5 ctime函数5.6 asctime函数5.7 strftime函数 06. 预留07. 附录 01. Unix时间戳 •Unix 时…...
2016年认证杯SPSSPRO杯数学建模B题(第一阶段)低分辨率下看世界全过程文档及程序
2016年认证杯SPSSPRO杯数学建模 B题 低分辨率下看世界 原题再现: 数码摄像技术被广泛使用于多种场合中。有时由于客观条件的限制,拍摄设备只能在较低的分辨率下成像。为简单起见,我们只考虑单色成像。假设成像的分辨率为 32 64,…...
16、Kafka ------ SpringBoot 整合 Kafka (配置 Kafka 属性 及对应的 属性处理类 解析)
目录 配置 Kafka 及对应的 属性处理类配置KafkaKafka配置属性的约定代码演示生产者相关的配置消费者相关的配置 代码(配置文件)application.properties 配置 Kafka 及对应的 属性处理类 配置Kafka spring.kafka.* 开头的配置属性,这些属性将由…...
【蓝桥杯选拔赛真题61】python偶数平方 第十五届青少年组蓝桥杯python 选拔赛比赛真题解析
目录 python偶数平方 一、题目要求 1、编程实现 2、输入输出...
智能语音识别源码系统+语义理解+对话管理+语音合成 带完整的搭建教程
人工智能技术的不断发展,智能语音识别技术逐渐成为人们日常生活和工作中不可或缺的一部分。然而,目前市场上的智能语音识别产品大多存在一定的局限性,如识别率不高、功能单一等。为了解决这些问题,罗峰给大家分享一款基于智能语音…...
cdh6.3.2的hive配udf
背景 大数据平台的租户要使用udf,他们用beeline连接, 意味着要通过hs2,但如果有多个hs2,各个hs2之间不能共享,需要先把文件传到hdfs,然后手动在各hs2上create function。之后就可以永久使用了,…...
在DevEco开发工具中,使用Previewer预览界面中的UI组件
1、在DevEco工具中,点击并展开PreViewer预览器 2、在PreViewer预览器中,点击Tt按钮(Inspector)切换至组件查看模式 3、在组件查看模式下选择组件,代码呈现选中状态,右侧呈现组件树,右下方呈现组…...
【蓝桥杯冲冲冲】旅行计划
蓝桥杯备赛 | 洛谷做题打卡day18 文章目录 蓝桥杯备赛 | 洛谷做题打卡day18旅行计划题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示题解代码我的一些话 旅行计划 题目描述 Kira酱要去一个国家旅游。这个国家有 N N N 个城市,编号为 1 1 1 至 N N…...
Ultraleap 3Di配置以及在 Unity 中使用 Ultraleap 3Di手部跟踪
0 开发需求 1、硬件:Ultraleap 手部追踪相机(Ultraleap 3Di) 2、软件:在计算机上安装Ultraleap Gemini (V5.2) 手部跟踪软件。 3、版本:Unity 2021 LTS 或更高版本 4、Unity XR插件管理:可从软件包管理器窗…...
HarmonyOS鸿蒙学习基础篇 - Text文本组件
该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 Text文本组件是可以显示一段文本的组件。该组件从API Version 7开始支持,从API version 9开始,该接口支持在ArkTS卡片中使用。 子组件 可…...
pytorch学习笔记(十一)
优化器学习 把搭建好的模型拿来训练,得到最优的参数。 import torch.optim import torchvision from torch import nn from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear from torch.utils.data import DataLoaderdataset torchvision.datas…...
【并发编程】 synchronized的普通方法,静态方法,锁对象,锁升级过程,可重入锁,非公平锁
目录 1.普通方法 2.静态方法 3.锁对象 4.锁升级过程 5.可重入的锁 6.不公平锁 非公平锁的 lock 方法: 1.普通方法 将synchronized修饰在普通同步方法,那么该锁的作用域是在当前实例对象范围内,也就是说对于 SyncDemosdnewSyncDemo();这一个实例对象…...
jQuery 删除元素 —— W3school 详解 简单易懂(十四)
通过 jQuery,可以很容易地删除已有的 HTML 元素。 删除元素/内容 如需删除元素和内容,一般可使用以下两个 jQuery 方法: remove() - 删除被选元素(及其子元素)empty() - 从被选元素中删除子元素 jQuery remove() 方…...
在 Linux 上搭建 Java 环境
目录 一、安装jdk 1. 挑选 jdk 版本 2. 安装 3. 验证 jdk 二、安装tomcat 1. 下载压缩包 2. 上传压缩包给 Linux (需要用到 rz 命令) 3. 解压压缩包(需要用到 unzip) 4. 进入 bin 目录 5. 给启动脚本增加可执行权限 6. 启…...
深度学习-Pytorch如何保存和加载模型
深度学习-Pytorch如何保存和加载模型 用pytorch构建模型,并训练模型,得到一个优化的模型,那么如何保存模型?然后如何又加载模型呢? pytorch 目前在深度学习具有重要的地位,比起早先的caffe,te…...
2.数据结构 顺序表(自留笔记)
文章目录 一.静态顺序表:长度固定二.动态顺序表1.下面证明原地扩容和异地扩容代码如下:2.下面是写一段Print,打印数字看看:3.头插4.尾删5.头删6.越界一定会报错吗7.下标插入8.下标删除9.查找数字10.应用:利用顺序表写一…...
将python打包成exe文件
将python打包成exe文件 文章目录 将python打包成exe文件1.安装PyInstaller2.配置pyinstaller到环境变量3.打包 以上一篇文章🔗用python删除重复文件并放入回收站为例,演示了如何用python写一个删除重复文件并放入回收站的功能代码,但是每次都…...
大数据处理,Pandas与SQL高效读写大型数据集
大家好,使用Pandas和SQL高效地从数据库中读取、处理和写入大型数据集,以实现最佳性能和内存管理,这是十分重要的。 处理大型数据集往往是一项挑战,特别是在涉及到从数据库读取和写入数据时。将整个数据集加载到内存中的传统方法可…...
【2024年5月备考新增】《软考高项论文专题 (2)论文背景(合集)》
1 论文的项目背景 1.1 论文写法 段落字数 - 正文全部字数不少于2000字孙悟空大闹天宫,被如来镇压,唐僧收服孙悟空,开始去西天取经。背景500字因为路途遥远,所以需要九九八十一难,才能取得正经。过渡段150字第一难、第二难 … 第八十一难过程1300字取得正经,唐僧只受了八…...
Mysql复习1--理论基础+操作实践--更新中
Mysql 索引索引的分类索引失效sql优化 删除数据库数据恢复 索引InnoDB引擎MyISAM引擎Memory引擎Btree索引支持支持支持hash索引不支持不支持支持R-tree索引不支持支持不支持Full-text索引5.6版本以后支持支持不支持 索引 解释说明: 索引指的是帮助mysql高效的获取数据的结构叫…...
微信小程序打卡定位实现方案
1背景 业务场景是考勤打卡,在考勤打卡这个业务场景中有两个关键技术点:定位和人员识别。用户界面初步确定是用微信小程序来实现,本文就定位问题做了技术上的调研。 2调研内容 平台注意事项 获取位置 选择位置 查看位置 距离计算 定位精度 防作弊 Demo 3调研结果 3.1平台注…...
小迪安全23WEB 攻防-Python 考点CTF 与 CMS-SSTI 模版注入PYC 反编译
#知识点: 1、PYC 文件反编译 2、Python-Web-SSTI 3、SSTI 模版注入利用分析 各语言的SSIT漏洞情况: SSIT漏洞过程: https://xz.aliyun.com/t/12181?page1&time__1311n4fxni0Qnr0%3DD%2FD0Dx2BmDkfDCDgmrYgBxYwD&alichlgrefhtt…...
计算机毕业设计 基于SpringBoot的律师事务所案件管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…...
太原建设网站制作/seo综合诊断工具
计算机科学在现代教育中的应用 (4页)本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦!9.90 积分计算机科学在现代教育中的应用 摘 要:一般来说,教育技术经过视觉教育运动(191…...
wordpress成功的网站/企业培训课程安排表
void main(void){ Delay_ms(1000);//让设备稳定 InitUart(); //串口初始化while(1){ DHT11(); //获取温湿度 P0DIR | 0x40; //IO口需要重新配置 /******温湿度的ASC码转换*******/ temp[0]wendu_shi0x30; temp[1]wendu_ge0x30; humidity[0]shidu_shi0x30; humidity[1]shidu_ge0…...
网站可做哪些服务/武汉seo推广优化
(精)最新c语言程序设计考试模拟题(v20090531)C语言程序设计期末考试模拟题0 课程成绩组成与考试环境(1)课程成绩=平时成绩(100分制)0.3+考试成绩(100分制)0.7。(2)平时成绩中,教师应考虑30分以上的成绩为团队互助与协作能力考核。(3)考试成绩…...
一级a做爰片不卡的网站/网络营销策划师
MySQL 使用 InnoDB 的原因有以下几点: 支持事务:InnoDB 支持 ACID(原子性、一致性、隔离性、持久性)事务,保证数据的完整性和一致性。 提供外键约束:InnoDB 支持外键约束,可以保证数据的完整性和一致性。 提供行级锁&a…...
日本做暧小视频在线观看网站/爱站网关键词挖掘工具
导读 我附近有一家热闹的大型超市,每次结账队伍都比较长,15人左右,然后你会看到收银台旁立着这么一个牌子: 但是看似人性化的安排,却没有发挥作用,为什么呢? 原因这个牌子的设计者,…...
班级网站怎么做ppt/郑州seo优化顾问热狗
本文为大家分享了virtualenv建立多个Python独立虚拟开发环境,供大家参考,具体内容如下1、安装virtualenv:pip install virtualenv2、创建一个python的虚拟环境:virtualenv test_demo用virtualenv创建虚拟环境,是通过复…...