为了方便通知,我们给小爱音箱接入了系统的业务语音通知

439 阅读2分钟

需求来源

我们的业务系统告警信息之前是使用类似 企业微信 钉钉 飞书 等工具进行群消息的机器人通知的,但文字信息提醒还是不够明显,同事们也没有随时盯着电脑或者手机。

办公室有很多的小爱同学,于是我们考虑要不要通过小爱同学用语音来把系统的告警信息通知到办公室的同事们?

需求分析

我们使用小爱同学的 API 来实现主动说话,然后起一个 WebApi 提供给系统来调用:

之前我们就基于 mi-service-lite 这个库实现了:

const http = require("http")
const { MiServiceConfig, getMiIOT, getMiNA } = require("mi-service-lite");

const config = {
  userId: "", // 小米的 UserId,不是登录账号
  password: "", // 小米账号的密码
  did: "", // 设备ID或者名称,如果不填,则账号下所有的小爱都会说话。。。
};
async function init(){
    const mina = await getMiNA(config)
    const miot = await getMiIOT(config)
    async function say(str) {
      miot.doAction(3, 4);
      miot.doAction(5, 3, str);
      // action 可以查询文档: https://home.miot-spec.com/#google_vignette
    }
    const server = http.createServer(async (req, res) => {
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      if (req.method !== 'POST') {
        res.end('Post Only!\n');
        return
      }
      let body = '';
      req.on('data', chunk => {
        body += chunk.toString();
      });
      req.on('end', () => {
        say(body)
        res.end('Success!\n');
      });
    });
    const PORT = 18080;
    server.listen(PORT, () => {
      console.log(`Server is running at http://localhost:${PORT}`);
    });
}
init()

我们使用 NodeJS 使用 mi-service-lite 起了一个 Web服务,用来接受需要小爱同学说话的内容。

其实是使用 模拟登录 你的小米账号,然后调用小爱的主动说话 http-api 来下发小爱说话内容的。

然后我们的业务系统只需要请求这个Web服务即可通知小爱说话了。

系统代码设计

如我们之前文章里设计的 “如何使用WebHook的架构设计来扩展和开放你的业务系统”,我们只需要添加一个通知方式:

public enum WebHookType implements IDictionary {
    /**
     * <h2>企业微信</h2>
     */
    WORK_WECHAT(1, "企业微信"),

    /**
     * <h2>飞书</h2>
     */
    FEI_SHU(2, "飞书"),

    /**
     * <h2>钉钉</h2>
     */
    DING_TALK(3, "钉钉"),

    /**
     * <h2>邮件</h2>
     */
    EMAIL(4, "邮件"),

    /**
     * <h2>WebHook</h2>
     */
    WEB_HOOK(5, "WebHook"),

    /**
     * <h2>小爱同学</h2>
     */
    XIAO_AI(6, "小爱同学"),
    ;

    private final int key;
    private final String label;
}

添加完枚举之后,我们去抽象工厂 AbstractEventFactory 中支持小爱同学的调用,并添加一个抽象方法让需要通知的业务方去自行实现:

// ... 其他代码
Object object = switch (webHookType) {
    case WORK_WECHAT -> getWorkWechatMarkDown(notifyHook);
    case FEI_SHU -> getFeishuMarkDown(notifyHook);
    case DING_TALK -> getDingTalkMarkDown(notifyHook);
    case EMAIL -> getEmailBody(notifyHook);
    case WEB_HOOK -> getWebHookBody(notifyHook);
    // 添加小爱的支持,直接使用 `getWebHookContent()` 的返回值作为朗读内容
    case XIAO_AI -> getWebHookContent(notifyHook);
};
// ...

后端搞定,前端也枚举支持一下:

export class WebHookTypeEnum extends AirEnum {
  static readonly WORK_WECHAT = new WebHookTypeEnum(1, '企业微信')
  // ... 添加小爱同学支持
  static readonly XIAO_AI = new WebHookTypeEnum(6, '小爱同学')
}

前端搞定,如图:

image.png

保存后,接下来我们在 创建供应商 成功后,就会触发小爱同学说话啦~

image.png

此处假设你听到了语音

小爱同学:“管理员创建了供应商:123”

总结

就是玩~

Bye