Arduino 告警通知五部曲 ② 钉钉告警

专栏介绍

  • 能够实现数行代码即可在Arduino中接入告警功能,包括微信、QQ、飞书、钉钉等多个告警方式。

订阅用户须知

  • 订阅后私聊博主获取源码(搜索QQ:2421818708),专栏上遇到的问题尽可咨询。

🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请留言轰炸哦!及时修正!感谢支持!🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝

在这里插入图片描述

1、背景

在我们做Arduino项目(特别是环境监测、数据报警等等)开发学习的时候,总会考虑要是这些信息能够通知到我的微信、钉钉、飞书等等常用app的时候就好了。

现在,这些不再是高深想法,跟着鸟哥来学习,可以实现快速简单接入,并且提供对应案例代码以方便直接运行感受实验效果。

关于告警通知,鸟哥会循序渐进,计划五部曲,分别为:

  • 腾讯科技微信告警
  • 腾讯科技QQ告警
  • 字节跳动飞书告警
  • 阿里巴巴钉钉告警
  • 整合以上四者到NodeJs服务器,业务控制用服务代码实现

关于微信告警,我们已经在上一期详细讲解过。那么接下来,让我们接入第二篇 —— 钉钉告警。

2、钉钉告警

阿里作为当前国内巨头,旗下也有不少好的产品,比如钉钉,我们当然希望能结合智能硬件一起使用。这就不得不说钉钉开放平台的一些能力 ——机器人消息推送(一般也叫作推送消息提醒)。

在钉钉,机器人是独立存在的一个应用类型,可以开箱即用,也可以进行二次开发,无需和微应用或者群等场景进行强制绑定。
对于开发者而言,钉钉机器人是全局唯一的应用,即无论是在单聊中还是群聊中,都可以用来推送微应用的通知和用来对用户进行对话式服务,其对应的机器人ID都可以是唯一的。这意味着开发者既可以选择仅创建一个机器人,而后将其放在各个应用场景下使用,也可以创建多个机器人,然后分别部署再不同场景下。

而我们这里重点关注自定义机器人的接入。
官方文档 https://open.dingtalk.com/document/robots/custom-robot-access

接下来,请根据我的步骤来配置环境。

2.1 自定义机器人配置使用步骤

前提条件:假设你是有一个钉钉账号。

2.1.1 步骤一:获取自定义机器人Webhook(其实就是一个请求地址)
  • 选择需要添加机器人的群聊,然后依次单击群设置 > 智能群助手
    请添加图片描述
  • 在机器人管理页面选择自定义机器人,输入机器人名字并选择要发送消息的群,同时可以为机器人设置机器人头像。完成必要的安全设置,勾选我已阅读并同意《自定义机器人服务及免责条款》,然后单击完成。
    在这里插入图片描述
  • 这里我们可以自定义关键词(发送文本时需要带上这个关键词,否则不给通过
  • 也可以自定义固定IP地址,只有该IP地址发送过来的信息才会处理。
  • 获取到一个webhook链接(这个链接就是我们的请求地址),复制出机器人的Webhook地址,可用于向这个群发送消息,点击完成。

https://oapi.dingtalk.com/robot/send?access_token=XXXXXX
最重要的就是AccessToken。这里每个人都不一样的

在这里插入图片描述

2.1.2 步骤二:使用自定义机器人

获取到Webhook地址后,用户可以向这个地址发起HTTP POST 请求,即可实现给该钉钉群发送消息。

也就是说我们只需要按照规定的数据格式要求发起一个HTTP消息请求即可,这又是后面博主封装sdk的目的。

当前自定义机器人支持文本 (text)、链接 (link)、markdown(markdown)、ActionCard、FeedCard消息类型。我们这里只关注文本类型(发送HTTP POST请求时构造这个JSON数据结构)。

{
    "at": {
        "atMobiles":[
            "180xxxxxx"
        ],
        "atUserIds":[
            "user123"
        ],
        "isAtAll": false
    },
    "text": {
        "content":"我就是我, @XXX 是不一样的烟火"
    },
    "msgtype":"text"
}

在这里插入图片描述

注意事项:

  • 每个机器人每分钟最多发送20条(对我们环境监控场景来说足够)。消息发送太频繁会严重影响群成员的使用体验,大量发消息的场景 (譬如系统监控报警) 可以将这些信息进行整合,通过markdown消息以摘要的形式发送到群里。
2.1.3 步骤三:了解常见问题(HTTP请求错误码)
  • 当出现以下错误时,表示消息校验未通过,请查看机器人的安全设置。
// 消息内容中不包含任何关键词
{
  "errcode":310000,
  "errmsg":"keywords not in content"
}

// timestamp 无效
{
  "errcode":310000,
  "errmsg":"invalid timestamp"
}

// 签名不匹配
{
  "errcode":310000,
  "errmsg":"sign not match"
}

// IP地址不在白名单
{
  "errcode":310000,
  "errmsg":"ip X.X.X.X not in whitelist"
}

接下来,我们就可以封装我们的sdk —— DingTalkMessageIoTSDK

2.2 DingTalkMessageIoTSDK实现

  • 第一步,构造消息体,仅仅文本类型
  • 第二步,发送消息
2.2.1 构造消息体,这里仅仅文本类型

官方文档案例模板:

{
    "at": {
        "atMobiles":[
            "180xxxxxx"
        ],
        "atUserIds":[
            "user123"
        ],
        "isAtAll": false
    },
    "text": {
        "content":"我就是我, @XXX 是不一样的烟火"
    },
    "msgtype":"text"
}

所以我们的sdk对应代码:

#define MESSAGE_BODY_FORMAT "{\"at\":{\"isAtAll\":true},\"msgtype\":\"text\",\"text\":{\"content\":\"%s\"}}"
2.2.2 发送消息

以上面消息体为参数。发起一个post请求

请求方式:POST(HTTPS)
请求地址: https://oapi.dingtalk.com/robot/send?access_token=ACCESS_TOKEN,其中token是填我们自己的

sdk对应代码:

/**
 * 发送文本到钉钉群
 * @param payload 文本内容
 */
void DingTalkMessageIoTSDK::sendText(const char *payload)
{
   Serial.print(F("[HTTPS] begin...\n"));
   char jsonBuf[500];
   sprintf(jsonBuf, MESSAGE_BODY_FORMAT, payload);
   Serial.println(jsonBuf);
   Serial.println(DINGTALK_API_SEND_MSG);
   bool sendMessageOK = false;
   if(https.begin(*client, DINGTALK_API_SEND_MSG)) {  // HTTPS
          Serial.print(F("[DINGTALK] sendMessage...\n"));
          // start connection and send HTTP header
          https.addHeader("Content-Type", "application/json");
          int httpCode = https.POST(jsonBuf);

          // httpCode will be negative on error
          if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            Serial.printf("[DINGTALK] POST... code: %d\n", httpCode);

            // file found at server
            if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
               String payload = https.getString();
               Serial.println(payload);
               sendMessageOK = true;
             } else {
               Serial.printf("[DINGTALK] POST... failed, error: %s\n", https.errorToString(httpCode).c_str());
               sendMessageOK = false;
             }

             https.end();
           }
    }else {
       Serial.print(F("[HTTPS] Unable to connect\n"));
    }

    if (sendMessageOK) {
       Serial.print(F("[DINGTALK] sendMessage Ok...\n"));
    } else {
       Serial.print(F("[DINGTALK] sendMessage error...\n"));
    }

   Serial.print(F("[HTTPS] end...\n"));
}

接下来,我们来测试完整的sdk代码。

3、测试SDK效果

3.1 测试代码

/**
 *  时间:2022-05-03
 *  描述:
 *     测试钉钉提醒
 */

#include <ESP8266WiFi.h>
#include <stdlib.h>
#include <Ticker.h>
#include "DingTalkMessageIoTSDK.h"

/******************* 常量声明 **********************/
#define SSID "TP-LINK_5344"          // 填入自己的WiFi账号
#define PASSWORD "xxxxx"      // 填入自己的WiFi密码

//---------------- 钉钉自定义机器人相关配置信息 ------------------//
#define ACCESS_TOKEN "xxxxx"     // token,从机器人链接得到,替换为自己的
#define INTERVAL 10000              // 读取时间间隔,默认10s

//---------------- 钉钉自定义机器人相关配置信息 ------------------//

/******************* 函数声明 **********************/
void initWifiConnect(void);   // 初始化Wifi连接
void doWiFiConnectTick(void); // 检测WiFi连接状态
void initDingTalkIotSDK(void);  // 初始化钉钉IOT SDK
void sendDataToDingTalk(void);  // 发送文本到钉钉
/******************* 函数声明 **********************/

/******************* 变量定义 **********************/
Ticker delayTimer;                   // 表示定时模块,用来做一个定时器
unsigned long previousMillis = 0; // 记录上次读取的时间戳
/******************* 变量定义 **********************/

/**
 * 初始化
 */
void setup() {
  delay(2000);          // 延时2秒,用于等待系统上电稳定
  Serial.begin(115200); // 初始化串口,波特率 115200
  Serial.println("");                       // 串口默认先换行显示
  Serial.println("测试钉钉消息提醒~"); // 串口打印信息表示项目启动~

  initWifiConnect(); // 初始化Wifi连接
  initDingTalkIotSDK(); // 初始化企业微信信息
  ESP.wdtEnable(5000); //  启用看门狗
}

void loop() {
  ESP.wdtFeed();// 定时喂狗
  unsigned long currentMillis = millis();        // 获取当前时间戳
  doWiFiConnectTick(); // wifi连接状态检测以及重连

  if(currentMillis - previousMillis >= INTERVAL) // 每隔一段时间 interval为时间间隔
  {
      previousMillis = currentMillis; // 记录当前时间戳
      sendDataToDingTalk();
  }

  delay(2000); // 延时2秒
}

/**
 * 检测WiFi连接状态
 */
void doWiFiConnectTick(void)
{
  static uint32_t lastWiFiCheckTick = 0; // 记录最近一次检测WiFi连接状态的时间点
  static uint32_t disConnectCount = 0;   // 记录WiFi断开连接的次数

  if(WiFi.status() == WL_CONNECTED) // 当前WiFi处于连接状态
  {
    disConnectCount = 0;// 重置WiFi断开连接为0
    return;
  }

  if(millis() - lastWiFiCheckTick > 1000) // 检测间隔大于1秒
  {
    lastWiFiCheckTick = millis();       // 记录时间点
    Serial.println("WiFi disConnect!"); // 串口输出.表示设备已经断开连接

    disConnectCount++;      // WiFi断开连接的次数累计加1
    if(disConnectCount>=40) // 断开连接累计次数达到40次,表示可能wifi连接异常
    {
      delayRestart(1);      //一直连接不上就重启ESP系统
    }
  }
}

/**
 * 延时t秒后重启ESP
 * @param t t秒
 */
void delayRestart(float t)
{
  Serial.print("Restart after ");
  Serial.print(t);
  Serial.println("s");
  // 开启一个定时器,定时时间为t秒
  delayTimer.attach(t, []() {
    Serial.println("\r\nRestart now!");
    ESP.restart();// 重启ESP模块
  });
}

/**
 * 初始化Wifi连接
 */
void initWifiConnect(void)
{
  Serial.printf("Connecting to WiFi:%s\n",SSID);// 串口打印当前WiFi热点的名字
  WiFi.disconnect();   // 默认断开之前的连接,回归初始化非连接状态
  WiFi.mode(WIFI_STA); // 设置ESP工作模式为Station模式
  WiFi.begin(SSID, PASSWORD);  // 连接到WiFi

  int cnt = 0; // 记录重试次数
  while (WiFi.status() != WL_CONNECTED) // 当还没有连接上WiFi热点时
  {
     delay(1000);       // 延时等待1秒
     cnt++;             // 累计次数+1
     Serial.print("."); // 串口输出.表示设备正在连接WiFi热点
     if(cnt>=40)        // 超过40秒还没有连接上网络
     {
       delayRestart(1); //一直连接不上就重启ESP系统
     }
  }

  Serial.println(WiFi.localIP()); // 打印当前IP地址
}

/**
 * 初始化钉钉IOT SDK
 */
void initDingTalkIotSDK(void)
{
  // 初始化 iot sdk
  DingTalkMessageIoTSDK::begin(ACCESS_TOKEN);
}

/**
 * 发送数据
 */
void sendDataToDingTalk(void)
{
  DingTalkMessageIoTSDK::sendText("告警 这里是8266 收到请回复!");
}


这里的效果是每隔一段时间给微信发送一条消息。

告警 这里是8266 收到请回复!

这里接入sdk非常简单,只需要调用初始化方法之后,可以在适当时机调用一下sendText方法即可完美。

3.2 测试结果

3.2.1 串口打印结果

在这里插入图片描述

3.2.2 打开钉钉,看消息

在这里插入图片描述

自此,我们就可以愉快接入钉钉消息提醒,接入鸟哥写的钉钉提醒sdk,调用两行代码即可快速接入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单片机菜鸟爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值