搜索代码

使用Heltec WiFi LoRa 32 V3通过DHT22传输温度到1.4公里

本课是……的一部分: WiFi LoRa简介

使用Heltec WiFi LoRa 32 V3通过DHT22传输温度到1.4公里

在本教程中,我们将探讨如何使用 Heltec WiFi LoRa 32 V3 模块通过 DHT22 传感器传输温度数据,传输距离可达 1.4 公里。此功能得益于 LoRa 技术的应用,该技术支持低功耗、远距离通信。到本指南结束时,您将拥有一个可以无线发送温度读数的工作系统。

Wifi LoRa 32 V3 内部 Meshnology N30 发送和接收

我们将首先概述本项目涉及的硬件组件,包括 Heltec WiFi LoRa 32 V3 模块和 DHT22 传感器。之后,我们将进行接线说明,在这里你将学习如何连接这些组件。最后,我们将逐步展示使该系统运行所需的代码。有关视觉指导,请参考视频中的各个时间戳(在视频中的 00:00)。

硬件说明

本项目的主要组件是Heltec WiFi LoRa 32 V3模块和DHT22温湿度传感器。Heltec模块配备ESP32微控制器,具有Wi-Fi和蓝牙功能,同时支持LoRa通信。这使得数据传输选项更加灵活。

Wifi LoRa 32 V3 在 Meshnology N30 内部作为温度传输器

DHT22传感器是一种数字传感器,能够提供准确的温度和湿度读数。它通过一个数字输出引脚与ESP32通信,使其易于在项目中连接和使用。这些组件共同构成了一个强大的无线温度监测系统。

数据表详细信息

制造商 赫尔特克自动化
零件编号 WiFi LoRa 32 V3
逻辑/输入输出电压 3.3 伏
供电电压 3.7-4.2 V
输出电流(每个通道) ~1 A
峰值电流(每通道) ~2 A
PWM频率指导 1 kHz(典型)
输入逻辑阈值 0.7 伏 (高), 0.3 伏 (低)
电压降 / RDS(开)/ 饱和度 0.3 V(最大)
热限制 85 °C (最高)
包裹 PCB模块
备注 / 变体 可选择多种频率选项(例如,433 MHz、868 MHz、915 MHz)

  • 确保DHT22供电为3.3V,而不是5V。
  • 在ESP32和DHT22之间进行通信时,使用适当的逻辑电平。
  • 考虑在长时间以高电流运行时进行散热。
  • 检查LoRa的天线连接,以最大化范围。
  • 请注意您所在地区的LoRa频率规定。

接线说明

Heltec_WiFi_loRa_32V3_DHT22_wiring

将 Heltec WiFi LoRa 32 V3 与 DHT22 传感器连接,首先将传感器的 VCC 引脚连接到 Heltec 模块的 3.3V 引脚。接下来,将 DHT22 的 GND 引脚连接到 Heltec 上的一个 GND 引脚。DHT22 的数据引脚应连接到 Heltec 的 GPIO 引脚 3。

确保在数据引脚和VCC之间使用一个拉升电阻(大约10kΩ),以获得稳定的读数。此外,确保LoRa天线牢固连接,以增强传输范围。如果您使用外部电源,请确保Heltec模块正确供电,以避免任何操作问题。

安装 Heltec ESP32 开发板

将此路径添加到您的 Arduino IDE 首选项中,如视频所示:https://resource.heltec.cn/download/package_heltec_esp32_index.json

代码示例与操作指南

以下代码片段说明如何设置Heltec模块以从DHT22传感器读取温度数据并通过LoRa传输。代码初始化显示器并设置DHT传感器。

#include 
#define DHTPIN 3         // GPIO pin for DHT22
#define DHTTYPE DHT22    // Define DHT type
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(115200);
  dht.begin(); // Initialize DHT sensor
}

在这个代码片段中,我们定义了DHT22传感器连接的引脚并对其进行初始化。setup()函数。TheSerial.begin(115200)该行用于调试输出。

void loop() {
  float tempC = dht.readTemperature(); // Read temperature in Celsius
  float tempF = dht.convertCtoF(tempC); // Convert to Fahrenheit
  sendData(tempC, tempF); // Function to send temperature data
}

该摘录展示了如何读取温度数据。loop()函数。该sendData()函数被调用以通过LoRa传输温度读数。

void sendData(float tempC, float tempF) {
  String data = "Temperature: " + String(tempC) + "°C"; // Create data string
  Radio.Send(data.c_str(), data.length()); // Send data
}

这里,我们创建包含温度的数据字符串并使用它发送。Radio.Send()方法。这将无线传输数据到接收模块。

请参阅文章下方加载的完整代码以获取详细实现。

演示 / 期待什么

一旦一切设置完成,并且代码已上传到 Heltec 模块,您应该会在 OLED 屏幕上看到温度读数。系统将传输温度数据,另一个配置为读取数据的 Heltec 模块可以接收这些数据。您可以通过将接收器移动得更远来测试范围,以确认达到的最大距离(视频中在 1:30)。

注意常见的陷阱,例如接线不正确、电源供应不足或使用错误的LoRa频率。确保DHT22正常工作,并且天线已连接,以最大化范围。

视频时间戳

  • 00:00 开始
  • 3:51 规格
  • 8:32 文档页面
  • 9:52 包装和电池
  • 12:58 第一次启动
  • 16:37 正在安装库
  • 18:19 发射器基本代码
  • 19:43 接收器基本代码
  • 20:39 演示发送接收文本
  • 23:02 OLED 演示代码
  • 24:06 OLED显示代码的基础文本
  • 26:26 OLED演示的基础文本
  • 26:58 使用DHT22读取温度
  • 28:49 LoRa发射器温度和显示
  • 30:07 LoRa接收器温度和显示
  • 32:13 温度升高时触发LED
  • 22:26 LoRa传输范围测试
  • 35:01 dBm 和毫瓦

图像

Heltec_WiFi_loRa_32V3_DHT22_wiring
Heltec_WiFi_loRa_32V3_DHT22_wiring
Wifi LoRa 32 V3 inside Meshnology N30 as transmitter of Temperature
Wifi LoRa 32 V3 inside Meshnology N30 as transmitter of Temperature
meshnology-N30-LoRa-v3-red-black
meshnology-N30-LoRa-v3-red-black
Wifi LoRa 32 V3 inside Meshnology N30 RX and TX
Wifi LoRa 32 V3 inside Meshnology N30 RX and TX
563-Printing Simple Text on the screen of WiFi LoRa 32 V3
语言: C++
/*
This is a simple code to display text on the OLED display
WiFi LoRa 32 V3 ESP32 module
Written by Ahmad Shamshiri 02 April 2025
Watch full video explanation https://youtu.be/WkyQMXkQhE8
Resources page https://robojax.com/tutorial_view.php?id=387
*/
#include <Wire.h>               
#include "HT_SSD1306Wire.h"


static SSD1306Wire  display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr , freq , i2c group , resolution , rst


void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  VextON();
  delay(100);

  // Initialising the UI will init the display too.
  display.init();

  display.setFont(ArialMT_Plain_10);

}


void displayTemperature(double temperature, int unit) {
    display.clear();  // Clear display before new content
    
    // Line 1: "Temperature:" in 16pt font
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 0, "Temperature:");

    // Line 2: Temperature value in 24pt font
    display.setFont(ArialMT_Plain_24);
    
    // Format temperature with correct unit symbol
    String tempString = String(temperature, 1); // 1 decimal place
    switch(unit) {
        case 1:  tempString += "�C"; break;  // Celsius
        case 2:  tempString += "�F"; break;  // Fahrenheit
        default: tempString += "�U"; break;  // Unknown unit
    }
    
    display.drawString(0, 20, tempString);  // Display at Y=20 (below label)
    display.display();  // Update OLED
}



void VextON(void)
{
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, LOW);
}

void VextOFF(void) //Vext default OFF
{
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, HIGH);
}



void loop() {
  // clear the display
  display.clear();
  displayTemperature(23.5, 1); // Displays "23.5�C" /1
  delay(2000);

}
773-Transmitter Code for Heltec WiFi LoRa 32 V3 to send temperature using DHT11, DHT22
语言: C++
/*
written on March 27, 2025
written by Ahmad Shamshiri for www.Robojax.com
Transmits Temperature and Humidity over LoRa RF using ESP32 LoRA 32 V3 module.
and displays the information on the screen.
Watch full video explanation https://youtu.be/WkyQMXkQhE8
Resources page: https://robojax.com/tutorial_view.php?id=387
*/

#include <Wire.h>               
#include "HT_SSD1306Wire.h"
static SSD1306Wire  display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr , freq , i2c group , resolution , rst

#include <DHT.h>
#define DHTPIN 3         // GPIO21
#define DHTTYPE DHT22     // DHT22 (AM2302)

DHT dht(DHTPIN, DHTTYPE);

float tempC, tempF;
int humidity ;

  //1=C
  //2=F
  //3=C, Humidity //only for display not for transmission
  //4=F, Humidity //only for display not for transmission
  //5=Humidity only
int dataType = 2;
String labelTemp = "Temperature";
String labelHumidity = "Humidity";
const int TX_POWER = 2;//dBm from 2 to 20. when powered via battery 2 to 14dBm is the best option

#include "mbedtls/aes.h"
#include <cstring>  // For memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_876s"; //Security key. 


#include "LoRaWan_APP.h"
#include "Arduino.h"


#define RF_FREQUENCY                                915000000 // Hz

#define TX_OUTPUT_POWER                             TX_POWER        // dBm from 2 to 20. when powered via battery 2 to 14dBm

#define LORA_BANDWIDTH                              0         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
#define LORA_CODINGRATE                             1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         0         // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON                  false
#define LORA_IQ_INVERSION_ON                        false


#define RX_TIMEOUT_VALUE                            1000
#define BUFFER_SIZE                                 30 // Define the payload size here

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];

double txNumber;

bool lora_idle=true;

static RadioEvents_t RadioEvents;
unsigned long lastTxTime = 0;
void OnTxDone( void );
void OnTxTimeout( void );
void decryptAES(uint8_t *data, const char *key);
void encryptAES(uint8_t *data, const char *key);
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize);

void setup() {
  Serial.begin(115200);
  Serial.println();

  VextON();
  delay(100);

  // Initialising the UI will init the display too.
  display.init();

  display.setFont(ArialMT_Plain_10);
   dht.begin();

  //LoRa stuff
  Mcu.begin(HELTEC_BOARD,SLOW_CLK_TPYE);
	
    txNumber=0;

    RadioEvents.TxDone = OnTxDone;
    RadioEvents.TxTimeout = OnTxTimeout;
    
    Radio.Init( &RadioEvents );
    Radio.SetChannel( RF_FREQUENCY );
    Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
                                   LORA_SPREADING_FACTOR, LORA_CODINGRATE,
                                   LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
                                   true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );   

}


void displayTemperature(int unit) {
    display.clear();  // Clear display before new content
    
    // Line 1: "Temperature:" in 16pt font
    display.setTextAlignment(TEXT_ALIGN_LEFT);


    // Line 2: Temperature value in 24pt font
    display.setFont(ArialMT_Plain_24);
    
    // Format temperature with correct unit symbol
    String tempStringC = String(tempC, 1) + "°C"; // 1 decimal place
    String tempStringF = String(tempF, 1)+ "°F"; // 1 decimal place
    String tempStringHumidity = String(humidity)+ "% RH";   
    String tempString; 
    switch(unit) {
        case 1:  
          tempString =tempStringC; 
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 0, "Temperature:");        
          display.setFont(ArialMT_Plain_24);
          display.drawString(0, 15, tempString);  
          break;  // Celsius
        case 2:  tempString =tempStringF; 
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 0, "Temperature:");              
          display.setFont(ArialMT_Plain_24);
          display.drawString(0, 15, tempString);  
          break;  // Fahrenheit
        case 3:  tempString =tempStringC; 
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 0, "Temperature:");              
          display.setFont(ArialMT_Plain_24);        
          display.drawString(0, 15, tempString);  
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 40, "Humidity:");
          display.drawString(70, 40, tempStringHumidity);       
          break;  // Celsius    
        case 4:  tempString =tempStringF; 
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 0, "Temperature:");              
          display.setFont(ArialMT_Plain_24);        
          display.drawString(0, 15, tempString);  
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 40, "Humidity:");
          display.drawString(70, 40, tempStringHumidity );       
          break;  // Celsius       
        case 5: 
          display.setFont(ArialMT_Plain_16);
          display.drawString(0, 0, "Humidity:");
          display.setFont(ArialMT_Plain_24); 
          display.drawString(0, 20, tempStringHumidity);         
          break;  // Celsius                     
        default: tempString =tempStringC + "°C"; break;;  // default
    }
    

    display.display();  // Update OLED
}

void readSensor()
{
  tempC = dht.readTemperature();
  humidity = dht.readHumidity(); 
  tempF = dht.convertCtoF(tempC);
}


void VextON(void)
{
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, LOW);
}

void VextOFF(void) //Vext default OFF
{
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, HIGH);
}

void sendData()
{
  

    String tempStringC = String(tempC, 1) + " °C"; // 1 decimal place
    String tempStringF = String(tempF, 1)+ " °F"; // 1 decimal place
    String tempStringHumidity = String(humidity)+ " % RH";   
    String txData; 
    //1=C
    //2=F
    //3=C, Humidity
    //4=F, Humidity
    //5=Humidity only
        switch(dataType) {
          case 1: 
           txData = labelTemp + " " + tempStringC;
            break; 
          case 2: 
           txData =  labelTemp + " " + tempStringF;
            break;
          case 3: 
           txData = labelHumidity + " " + tempStringHumidity;
            break;             
          default:
           txData = labelTemp + " " + tempStringC;
            break;

        }
  uint8_t data[32];       
  memset(data, 0, sizeof(data));  // Zero-padding
  strncpy((char*)data, txData.c_str(), sizeof(data) - 1); // Copy string safely

  encryptAES(data, userKey);  // Encrypt before sending  
  if(lora_idle == true)
    {
      delay(1000);
      Radio.Send(data,  sizeof(data));
      Serial.print("Sending: ");
      Serial.println((char *)data);
      lora_idle = false;
    }
    Radio.IrqProcess( );  
}



void loop() {
  readSensor();//read the data

  // clear the display
  display.clear();

  displayTemperature(dataType); // 
	sendData();
  delay(100);

}


void OnTxDone( void )
{
	Serial.println("TX done......");
	lora_idle = true;
}

void OnTxTimeout( void )
{
    Radio.Sleep( );
    Serial.println("TX Timeout......");
    lora_idle = true;
}


/**
 * Converts a user-provided plaintext key into a fixed-length 16-byte (128-bit)
 * or 32-byte (256-bit) key.
 */
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
    memset(processedKey, 0, keySize); // Fill with zeros
    size_t len = strlen(userKey);
    if (len > keySize) len = keySize; // Truncate if too long
    memcpy(processedKey, userKey, len); // Copy valid key part
}

/**
 * Encrypts a 16-byte (one block) message using AES-128.
 */
void encryptAES(uint8_t *data, const char *key) {
    uint8_t processedKey[16]; // 128-bit key
    processKey(key, processedKey, 16);

    mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_enc(&aes, processedKey, 128);
    mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, data, data);
    mbedtls_aes_free(&aes);
}

/**
 * Decrypts a 16-byte (one block) message using AES-128.
 */
void decryptAES(uint8_t *data, const char *key) {
    uint8_t processedKey[16]; // 128-bit key
    processKey(key, processedKey, 16);

    mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_dec(&aes, processedKey, 128);
    mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, data, data);
    mbedtls_aes_free(&aes);
}
867-Receiver Code for Heltec WiFi LoRa 32 to receive and display Temperature
语言: C++
/*
Written on April 01, 2025
written by Ahmad Shamshiri for www.Robojax.com
this sktech receives the secure temperature or humidity from WiFi LoRa 32 and decrypts it
and displays it on the OLED. There is action feature to triggerd if the temperature is below triggerdValue
Watch full video explaination https://youtu.be/WkyQMXkQhE8
Resources page: https://robojax.com/tutorial_view.php?id=387
*/
#include <Arduino.h>
// Alert configuration
const String triggerdText = "Too High"; // Correct String type
const float triggerdValue = 90.0f; // exclusive (this value is not included)
const int triggerdYpos = 45;
const bool triggerdType = true;//true is > (greter than triggerdValue) and false is < (less  than triggerdValue)
const int triggerdOutputPin = 7;//GPIO07 goes HIGH when triggered
const bool triggerdBlink4Me= true;//should blink or not

#include "mbedtls/aes.h"
#include <cstring>  // For memset, memcpy
mbedtls_aes_context aes;
const char *userKey = "hyhT676#h~_876s"; //Security key

#define MIN_RSSI -120  // Worst possible signal
#define MAX_RSSI -50   // Best possible signal


// For a connection via I2C using the Arduino Wire include:
#include <Wire.h>               
#include "HT_SSD1306Wire.h"

static SSD1306Wire  display(0x3c, 500000, SDA_OLED, SCL_OLED, GEOMETRY_128_64, RST_OLED); // addr , freq , i2c group , resolution , rst



#include "LoRaWan_APP.h"
#include "Arduino.h"


#define RF_FREQUENCY                                915000000 // Hz

#define TX_OUTPUT_POWER                             14        // dBm

#define LORA_BANDWIDTH                              0         // [0: 125 kHz,
                                                              //  1: 250 kHz,
                                                              //  2: 500 kHz,
                                                              //  3: Reserved]
#define LORA_SPREADING_FACTOR                       7         // [SF7..SF12]
#define LORA_CODINGRATE                             1         // [1: 4/5,
                                                              //  2: 4/6,
                                                              //  3: 4/7,
                                                              //  4: 4/8]
#define LORA_PREAMBLE_LENGTH                        8         // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT                         0         // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON                  false
#define LORA_IQ_INVERSION_ON                        false


#define RX_TIMEOUT_VALUE                            1000
#define BUFFER_SIZE                                 30 // Define the payload size here

char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];

static RadioEvents_t RadioEvents;

int16_t txNumber;

int16_t rssi,rxSize;

bool lora_idle = true;
unsigned long lastRxTime = 0;
const unsigned long SIGNAL_TIMEOUT = 5000; // 5 seconds

void decryptAES(uint8_t *data, const char *key);
void encryptAES(uint8_t *data, const char *key);
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize);

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();
  VextON();
  delay(100);

  // Initialising the UI will init the display too.
  display.init();

  display.setFont(ArialMT_Plain_10);
  pinMode(triggerdOutputPin, OUTPUT);
  //LoRa stuff blow this line
     Mcu.begin(HELTEC_BOARD,SLOW_CLK_TPYE);
    
    txNumber=0;
    rssi=0;
  
    RadioEvents.RxDone = OnRxDone;
    Radio.Init( &RadioEvents );
    Radio.SetChannel( RF_FREQUENCY );
    Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                               LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                               LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                               0, true, 0, 0, LORA_IQ_INVERSION_ON, true );
}


void displayTemperature(String data1, String data2) {

    display.clear();  // Clear display before new content
    
    // Line 1: "Temperature:" in 16pt font
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_16);
    display.drawString(0, 0, data1);

    // Line 2: Temperature value in 24pt font
    display.setFont(ArialMT_Plain_24);
    display.drawString(0, 20, data2);  // 
    displaySignalStrength(rssi);
   // display.display();  // Update OLED

    
}

void displayLine(String data, int y) {
    // Line 1: "Temperature:" in 16pt font
    display.setTextAlignment(TEXT_ALIGN_LEFT);
    display.setFont(ArialMT_Plain_10);

    if (triggerdBlink4Me) {
        // Blink effect: Display text, wait, clear text, wait, then return
        display.drawString(0, y, data);
        display.display();
        delay(500);  // Keep text visible for 500ms

        display.clear();  // Clear the screen
        display.display();
        delay(500);  // Keep screen blank for 500ms
    } 
    else {
        // Normal display without blinking
        display.drawString(0, y, data);
        display.display();
    }
}


void VextON(void)
{
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, LOW);
}

void VextOFF(void) //Vext default OFF
{
  pinMode(Vext,OUTPUT);
  digitalWrite(Vext, HIGH);
}



void loop() {
  RaIrqProcessdio( );
  if(lora_idle)
  {
    lora_idle = false;
    Serial.println("into RX mode");
    Radio.Rx(0);
  }
  noSignalCheck();

  delay(100);

}

void displaySignalStrength(int16_t rssi) {
    // Convert RSSI to percentage (0-100%)
    int percent = map(constrain(rssi, MIN_RSSI, MAX_RSSI), MIN_RSSI, MAX_RSSI, 0, 100);
    
    // Display at bottom right corner
    display.setTextAlignment(TEXT_ALIGN_RIGHT);
    display.setFont(ArialMT_Plain_16);
    
    // Create signal strength indicator
    String strength = String(percent) + "% [";
    for (int i = 0; i < 5; i++) {
        strength += (percent > (i * 20)) ? "|" : " ";
    }
    strength += "]";
    
    display.drawString(128, 45, strength); // Position at bottom-right
}

void noSignalCheck()
{
    // Automatic "No Signal" after timeout
    if (millis() - lastRxTime > SIGNAL_TIMEOUT) {
        display.clear();
        display.setTextAlignment(TEXT_ALIGN_CENTER);
        display.setFont(ArialMT_Plain_16);        
        display.drawString(64, 20, "No Signal");
        display.display();
    }
}

/**
 * Triggers an action based on a threshold comparison.
 *
 * @param type           - If true, triggers when floatValue **exceeds** triggerdValue.
 *                         If false, triggers when floatValue **falls below** triggerdValue.
 * @param floatValue     - The current measured value to compare.
 * @param triggerdValue  - The threshold value that determines the trigger condition.
 */
void triggerAction(float floatValue)
{
  if(triggerdType)
  {
    if (floatValue > triggerdValue) {
        displayLine(triggerdText, triggerdYpos);
        Serial.println(triggerdText);
        digitalWrite(triggerdOutputPin, HIGH);//turns triggerdOutputPin to HIGH
    }else{
        digitalWrite(triggerdOutputPin, LOW);
    }
  }else{
    if (floatValue < triggerdValue) {
        displayLine(triggerdText, triggerdYpos);
        Serial.println(triggerdText);
        digitalWrite(triggerdOutputPin, HIGH);//turns triggerdOutputPin to HIGH
    } else{
        digitalWrite(triggerdOutputPin, LOW);//turns triggerdOutputPin to LOW
    }   
  }
}
void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
{
    lastRxTime = millis(); // Reset timer on new data
    rssi=rssi;
    rxSize=size;
    memcpy(rxpacket, payload, size );

    rxpacket[size]='\0';
    Radio.Sleep( );
    Serial.printf("\r\nreceived packet \"%s\" with rssi %d , length %d\r\n",rxpacket,rssi,rxSize);
    // Serial.println("Encrypted Data (Hex):");
    // for (int i = 0; i < 16; i++) {
    //     Serial.printf("%02X ", rxpacket[i]);
    // }
    // Serial.println();
   decryptAES((uint8_t *)rxpacket, userKey);

    // Split the received packet into parts
    String receivedStr = String((char*)rxpacket);
    int firstSpacePos = receivedStr.indexOf(' ');
    if (firstSpacePos != -1) {
        // First part (before first space)
        String part1 = receivedStr.substring(0, firstSpacePos);  // "Temperature"
        
        // Find second space (after the number)
        int secondSpacePos = receivedStr.indexOf(' ', firstSpacePos + 1);
        
        if (secondSpacePos != -1) {
            // Second part (numeric value)
            String part2 = receivedStr.substring(firstSpacePos + 1, secondSpacePos); // "34.5"
            float floatValue = part2.toFloat();  // Convert to float 34.5
            
            // Third part (unit)
            String part3 = receivedStr.substring(secondSpacePos + 1); // "°C"
            
            displayTemperature(part1, part2+part3);
            display.display();
            Serial.print("part1: " + part1);
            Serial.print(" part2: " + part2);
            Serial.println(" part3: " + part3);
            Serial.println("floatValue " + String(floatValue));          
        
        //to trigger an action. 
        triggerAction(floatValue);

        } else {
            Serial.println("No second space found for unit");
        }
    }else {
        Serial.println("No space found in packet - can't split");
    }     


    lora_idle = true;
}

/**
 * Converts a user-provided plaintext key into a fixed-length 16-byte (128-bit)
 * or 32-byte (256-bit) key.
 */
void processKey(const char *userKey, uint8_t *processedKey, size_t keySize) {
    memset(processedKey, 0, keySize); // Fill with zeros
    size_t len = strlen(userKey);
    if (len > keySize) len = keySize; // Truncate if too long
    memcpy(processedKey, userKey, len); // Copy valid key part
}

/**
 * Encrypts a 16-byte (one block) message using AES-128.
 */
void encryptAES(uint8_t *data, const char *key) {
    uint8_t processedKey[16]; // 128-bit key
    processKey(key, processedKey, 16);

    mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_enc(&aes, processedKey, 128);
    mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, data, data);
    mbedtls_aes_free(&aes);
}

/**
 * Decrypts a 16-byte (one block) message using AES-128.
 */
void decryptAES(uint8_t *data, const char *key) {
    uint8_t processedKey[16]; // 128-bit key
    processKey(key, processedKey, 16);

    mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_dec(&aes, processedKey, 128);
    mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, data, data);
    mbedtls_aes_free(&aes);
}

Common Course Files

文件📁

其他文件