本项目中的邮件报警模块在用户在网页激活后会自动监测当前的温度,并且与用户设置的温度阈值做比较,一旦检测到当前温度超过用户设定的温度阈值,系统便会向用户所指定的邮箱发送一封报警邮件。当然,你也可以接入各种各样的监测模块,实现更多状态的监测与报警。
目录
SMTP 软件包的使用
邮件报警模块源码详解
模块结构体
模块函数简介
模块函数详解
smtp_module_init
prepare_content
smtp_thread
smtp_data_config
smtp_enable&smtp_disable
json_create_smtp_data
SMTP 软件包的使用
邮件使用的是SMTP_CLIENT软件包,查看软件包链接。
该软件包实现了基于SMTP协议的邮件发送功能,并且支持加密端口,但其对用户提供的接口非常简洁易懂,使用者并不需要了解SMTP协议的具体内容便可非常方便地使用。在本项目中,使用到了如下接口:
smtp_client_init() //初始化 smtp_client 客户端
smtp_set_server_addr() //设置服务器的地址及端口
smtp_set_auth() //设置服务器认证信息
smtp_add_receiver() //添加收件人地址
smtp_send_mail() //发送邮件
以上接口顺序执行就是一个完整的smtp邮件发送流程。在本项目中,虽然对其中的几个接口进行了进一步的封装从而实现更加高级的功能,但底层的逻辑还是上述接口。
邮件报警模块源码详解
模块结构体
邮件模块结构体如下所示:
typedef struct
{
uint8_t enable; //邮件功能使能
uint32_t cold_time; //报警冷却时间
char server_addr[100]; //邮件服务器地址
char server_port[10]; //邮件服务器端口
char username[50]; //用户名
char password[50]; //密码
char receiver[100]; //收件人地址
} smtp_module_t;
enable成员是邮件功能的开启标志,cold_time存储了报警冷却时间,即两个连续的报警之间的最小间隔,若在这个间隔内模块不会进行第二次报警。server_addr为邮件服务器地址,server_port为邮件服务器端口,普通端口一般为 25,同时该软件包也支持465/587两个加密端口,需要注意的是,使用加密端口前应开启软件包加密功能,在env工具中的配置如下:
username与password分别为所要使用的发件人的用户名及密码,receiver是收件人的邮箱地址。
模块函数简介
函数名 | 函数简介 |
smtp_module_init | 邮件模块初始化 |
prepare_content | 生成报警内容 |
smtp_thread | 邮件核心处理线程 |
smtp_data_config | 配置邮件参数 |
smtp_enable&smtp_disable | 邮件报警功能启用/禁用 |
json_create_smtp_data | 生成邮件参数json字符串 |
模块函数详解
smtp_module_init
该函数为smtp模块初始化函数,该函数实现了邮件工作线程的创建与开启。
int smtp_module_init(void)
{
rt_thread_t smtp_client_tid;
//创建邮件发送线程(如果选择在主函数中直接调用邮件发送函数,需要注意主函数堆栈大小,必要时调大)
smtp_client_tid = rt_thread_create("smtp", smtp_thread, RT_NULL, SMTP_CLIENT_THREAD_STACK_SIZE, 20, 5);
if (smtp_client_tid != RT_NULL)
{
rt_thread_startup(smtp_client_tid);
}
return RT_EOK;
}
prepare_content
该函数实现了邮件内容的拼接,将当前温湿度加入到报警字符串中。
//准备邮件内容
static void prepare_content(void)
{
sprintf(content,
"W601监测系统报警\r\n-------------------------\r\n当前温度:%.2f C\r\n当前湿度:%.2f%% \r\n",
w601_aht10.cur_temp,
w601_aht10.cur_humi);
}
smtp_thread
该函数为邮件工作的主线程,在该线程的一开始对smtp客户端进行初始化。在线程中,首先会检测邮件报警功能是否开启,若开启了该功能,系统会比对当前温度和报警阈值温度,若当前温度超出了报警阈值温度,同时报警冷却时间已到(最近一段时间内没有产生过报警),系统便会生成报警字符串并且发送报警邮件。
void smtp_thread(void *param)
{
//初始化smtp客户端
smtp_client_init();
//清空设置
rt_memset(&w601_smtp, 0, sizeof(smtp_module_t));
while (1)
{
if (w601_smtp.cold_time)
{
w601_smtp.cold_time--;
}
if (w601_smtp.enable) //使能邮件功能
{
if (w601_aht10.cur_temp > w601_aht10.temp_warn) //有报警
{
//冷却时间内不重复报警
if (w601_smtp.cold_time)
{
}
else
{
//设置报警冷却时间
w601_smtp.cold_time = WARNING_COLD_TIME;
LOG_W("system warning,smtp send!");
prepare_content();
smtp_send_mail(SMTP_SUBJECT, content);
}
}
}
rt_thread_mdelay(1000);
}
}
smtp_data_config
该函数实现了邮件参数的设置功能,当接收到前端传来的设置请求时,系统会提取相对应的设置参数,并且将参数传入该函数,在该函数中进行参数的配置。需要注意的是,由于本项目只支持一个收件人(软件包本身支持多收件人),所以在函数开头会删除原先已保存的收件人,并且在下面添加新的收件人。当然你也可以通过修改模块源码使其支持多收件人。
int smtp_data_config(char *server_addr, char *server_port,
char *username, char *password,
char *receiver, char *temp_warn)
{
if (w601_smtp.receiver[0] != '\0')
{
smtp_delete_receiver(w601_smtp.receiver);
}
strcpy(w601_smtp.server_addr, server_addr);
strcpy(w601_smtp.server_port, server_port);
strcpy(w601_smtp.username, username);
strcpy(w601_smtp.password, password);
strcpy(w601_smtp.receiver, receiver);
smtp_set_server_addr(w601_smtp.server_addr,
ADDRESS_TYPE_DOMAIN,
w601_smtp.server_port);
smtp_set_auth(w601_smtp.username, w601_smtp.password);
smtp_add_receiver(receiver);
w601_aht10.temp_warn = atof(temp_warn);
return 0;
}
smtp_enable&smtp_disable
这两个函数非常简单,通过给模块结构体的使能成员赋值来实现邮件功能的开关。用户通过网页进行开关设置。
void smtp_enable(void)
{
w601_smtp.enable = 1;
}
void smtp_disable(void)
{
w601_smtp.enable = 0;
}
json_create_smtp_data
该函数是将邮件模块的参数转换为json格式的字符串,主要用于与网页的通信。将当前邮件参数传输给网页显示。
char *json_create_smtp_data(void)
{
char *json_data = RT_NULL;
char value[10] = "";
cJSON *root = cJSON_CreateObject();
snprintf(value, sizeof(value), "%.2f", w601_aht10.temp_warn);
cJSON_AddItemToObject(root, "server_addr", cJSON_CreateString(w601_smtp.server_addr));
cJSON_AddItemToObject(root, "server_port", cJSON_CreateString(w601_smtp.server_port));
cJSON_AddItemToObject(root, "username", cJSON_CreateString(w601_smtp.username));
cJSON_AddItemToObject(root, "password", cJSON_CreateString(w601_smtp.password));
cJSON_AddItemToObject(root, "receiver", cJSON_CreateString(w601_smtp.receiver));
cJSON_AddItemToObject(root, "temp_warn", cJSON_CreateString(value));
cJSON_AddItemToObject(root, "enable", cJSON_CreateNumber(w601_smtp.enable));
json_data = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
return json_data;
}