/**
* 北斗通信创意开发系统
* 课程:向指定平台/终端发送汉字案例
* 作者:北京华云智联科技有限公司
* 时间:2023-3-6
* 备注:ESP32新版本
* 功能说明:
* 调用发送接口,配置成汉字模式,发送“北斗”两个汉字
* 依赖库:
* 无
*/
#include <Arduino.h>
#include <math.h> // 用于round()和modf()
#include "bdrd_esp32.h" // 包含北斗短报文库
// --- 常量定义 ---
const unsigned long SEND_INTERVAL_MS = 2 * 60 * 1000; // 发送间隔2分钟
char TARGET_PLATFORM_ID[] = "15950077"; // 转为字符串类型,与库匹配
const char MESSAGE_TYPE = '2'; // 使用代码类型,对应库中的type='2'
// 巡查区域定义
const double MIN_LON = 114.120000;
const double MAX_LON = 114.124000;
const double MIN_LAT = 40.120000;
const double MAX_LAT = 40.124000;
const double MIN_ALT = 300.0;
const double MAX_ALT = 500.0;
// --- 全局变量 ---
unsigned long lastSendTime = 0;
unsigned long flightDurationSec = 0;
double currentLatitude = 0.0;
double currentLongitude = 0.0;
double currentAltitude = 0.0;
int batteryPercentage = 100;
// --- 函数声明 ---
bool generate_monitoring_message(double latitude, double longitude, double altitude,
unsigned long flight_duration_sec, int battery_percent,
char* buffer, size_t bufferSize);
double randomDouble(double minVal, double maxVal);
void setup() {
Serial.begin(115200); // 调试串口
Serial2.begin(115200); // 北斗模块串口,与库匹配
randomSeed(analogRead(A0));
Serial.println("--- 无人机监控程序(北斗短报文)启动 ---");
Serial.print("数据发送频率: ");
Serial.print(SEND_INTERVAL_MS / 1000);
Serial.println(" 秒/次");
Serial.println("巡查区域:");
Serial.print(" 经度: "); Serial.print(MIN_LON, 6); Serial.print("° - "); Serial.println(MAX_LON, 6);
Serial.print(" 纬度: "); Serial.print(MIN_LAT, 6); Serial.print("° - "); Serial.println(MAX_LAT, 6);
Serial.print(" 海拔: "); Serial.print(MIN_ALT, 2); Serial.print("m - "); Serial.println(MAX_ALT, 2);
Serial.println("---------------------------------");
// 初始化变量
lastSendTime = 0;
flightDurationSec = 0;
batteryPercentage = 100;
// 延迟1秒,让北斗模块准备就绪
delay(1000);
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastSendTime >= SEND_INTERVAL_MS) {
lastSendTime = currentTime;
// 1. 生成随机监控数据
currentLatitude = randomDouble(MIN_LAT, MAX_LAT);
currentLongitude = randomDouble(MIN_LON, MAX_LON);
currentAltitude = randomDouble(MIN_ALT, MAX_ALT);
batteryPercentage -= 1;
if (batteryPercentage < 0) {
batteryPercentage = 0;
}
Serial.println("当前状态:");
Serial.print(" 经度: "); Serial.println(currentLongitude, 6);
Serial.print(" 纬度: "); Serial.println(currentLatitude, 6);
Serial.print(" 海拔: "); Serial.print(currentAltitude, 2); Serial.println(" m");
Serial.print(" 飞行时长: "); Serial.print(flightDurationSec); Serial.println(" 秒");
Serial.print(" 剩余电量: "); Serial.print(batteryPercentage); Serial.println(" %");
// 2. 生成监控信息字符串
char messageBuffer[40];
bool success = generate_monitoring_message(
currentLatitude,
currentLongitude,
currentAltitude,
flightDurationSec,
batteryPercentage,
messageBuffer,
sizeof(messageBuffer)
);
// 3. 使用北斗模块发送信息
if (success) {
Serial.print("生成协议字符串: ");
Serial.println(messageBuffer);
// 调用北斗短报文库发送信息
int result = sendSMS(TARGET_PLATFORM_ID, MESSAGE_TYPE, messageBuffer);
// 显示发送结果
if (result == 0) {
Serial.println("北斗短报文发送成功!");
} else {
Serial.print("北斗短报文发送失败,错误码: ");
Serial.println(result);
showError(result); // 显示详细错误信息
}
} else {
Serial.println("错误:未能生成有效的监控信息字符串");
}
// 4. 更新飞行时长
flightDurationSec += (SEND_INTERVAL_MS / 1000);
Serial.println("----------------------");
if (batteryPercentage <= 0) {
Serial.println("电量耗尽,任务结束");
while(1) {
delay(1000);
}
}
}
}
double randomDouble(double minVal, double maxVal) {
double scale = (double)random(0, 1000001) / 1000000.0;
return minVal + scale * (maxVal - minVal);
}
bool generate_monitoring_message(double latitude, double longitude, double altitude,
unsigned long flight_duration_sec, int battery_percent,
char* buffer, size_t bufferSize) {
if (!(latitude >= 0.0 && latitude <= 90.0)) {
Serial.print("错误:纬度 "); Serial.print(latitude, 6); Serial.println(" 超出范围");
return false;
}
if (!(longitude >= 0.0 && longitude <= 180.0)) {
Serial.print("错误:经度 "); Serial.print(longitude, 6); Serial.println(" 超出范围");
return false;
}
if (!(altitude >= (300.0 - 0.001) && altitude <= (500.0 + 0.001))) {
Serial.print("错误:海拔 "); Serial.print(altitude, 2); Serial.println(" 超出范围");
return false;
}
if (!(battery_percent >= 0 && battery_percent <= 100)) {
Serial.print("错误:电量 "); Serial.print(battery_percent); Serial.println(" 超出范围");
return false;
}
double lat_int_part, lat_frac_part;
double lon_int_part, lon_frac_part;
double alt_int_part, alt_frac_part;
lat_frac_part = modf(latitude, &lat_int_part);
lon_frac_part = modf(longitude, &lon_int_part);
alt_frac_part = modf(altitude, &alt_int_part);
long lat_frac_scaled = lround(lat_frac_part * 1000000.0);
long lon_frac_scaled = lround(lon_frac_part * 1000000.0);
long alt_frac_scaled = lround(alt_frac_part * 100.0);
if (lat_frac_scaled < 0) lat_frac_scaled = 0;
if (lat_frac_scaled > 999999) lat_frac_scaled = 999999;
if (lon_frac_scaled < 0) lon_frac_scaled = 0;
if (lon_frac_scaled > 999999) lon_frac_scaled = 999999;
if (alt_frac_scaled < 0) alt_frac_scaled = 0;
if (alt_frac_scaled > 99) alt_frac_scaled = 99;
int n = snprintf(buffer, bufferSize,
"%02d%06ld%03d%06ld%03d%02ld%06lu%03d",
(int)lat_int_part,
lat_frac_scaled,
(int)lon_int_part,
lon_frac_scaled,
(int)alt_int_part,
alt_frac_scaled,
flight_duration_sec,
battery_percent);
if (n < 0 || (unsigned int)n >= bufferSize) {
Serial.println("错误:缓冲区不足");
return false;
}
return true;
}