利用音箱TTS功能和企业微信配合实现语音留言板

萝卜的构思,我修改一下,

企业微信上面留言,不管是文本内容还是语音内容都可以,然后NR会自动将这些消息保存下来;
当触发读取消息后,这里的触发可以是一个米家小饼干,从已保存的记录中提取数据并生成TTS消息,让音箱播放;
留言获取后会自动清空;

[
    {
        "id": "efec3d7c.9b731",
        "type": "xiaoai-tts",
        "z": "ccf03ab3.fc74a8",
        "name": "",
        "xiaoai": "40bcf6b9.1ee278",
        "tts": "",
        "device": "3434d59f",
        "x": 520,
        "y": 460,
        "wires": [
            [
                "34445db1.286572"
            ],
            [
                "34445db1.286572"
            ]
        ]
    },
    {
        "id": "34445db1.286572",
        "type": "debug",
        "z": "ccf03ab3.fc74a8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 690,
        "y": 460,
        "wires": []
    },
    {
        "id": "b2b6247b.780878",
        "type": "bizwechat-input",
        "z": "ccf03ab3.fc74a8",
        "name": "",
        "bizwechat": "8a940403.c886a8",
        "x": 190,
        "y": 380,
        "wires": [
            [
                "8357d7a1.59bac8"
            ]
        ]
    },
    {
        "id": "8357d7a1.59bac8",
        "type": "function",
        "z": "ccf03ab3.fc74a8",
        "name": "保存留言",
        "func": "/**\n 时间戳\n 对Date的扩展,将 Date 转化为指定格式的String\n 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,\n 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)\n*/\nDate.prototype.Format = function(fmt){ //author: meizz\n    var o = {\n        \"M+\" : this.getMonth()+1,                 //月份\n        \"d+\" : this.getDate(),                    //日\n        \"h+\" : this.getHours(),                   //小时\n        \"m+\" : this.getMinutes(),                 //分\n        \"s+\" : this.getSeconds(),                 //秒\n        \"q+\" : Math.floor((this.getMonth()+3)/3), //季度\n        \"S\"  : this.getMilliseconds()             //毫秒\n    };\n    if(/(y+)/.test(fmt))\n    fmt=fmt.replace(RegExp.$1, (this.getFullYear()+\"\").substr(4 - RegExp.$1.length));\n    for(var k in o)\n    if(new RegExp(\"(\"+ k +\")\").test(fmt))\n    fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : ((\"00\"+ o[k]).substr((\"\"+ o[k]).length)));\n    return fmt;\n};\n\nvar FromUserName = {\n '111111':'三木'\n}\n\n//判断是打开企业微信后并发送了消息\nif(msg.message.MsgType != \"event\"){\n    //判断是有内容的消息\n    if(msg.message.AsrContent || msg.message.Content){\n        var message = \"\"\n        //如果是语音消息\n        if(msg.message.AsrContent) message = msg.message.AsrContent[0];\n        //如果是文本消息\n        if(msg.message.Content) message = msg.message.Content;\n        //获取未读的消息记录\n        var Message = flow.get(\"TTS_Message\") || [];\n        //统计消息数量\n        var i = Message.length;\n        //增加新消息\n        Message[i] = {};\n        Message[i]['FromUserName'] = FromUserName[msg.message.FromUserName];\n        Message[i]['CreateTime'] = new Date().Format(\"MM月dd日hh点mm分\");\n        Message[i]['Content'] = message;\n        //保存\n        flow.set(\"TTS_Message\", Message);\n        msg.payload = Message;\n        return msg;\n    }\n}\n\n",
        "outputs": 1,
        "noerr": 0,
        "x": 350,
        "y": 380,
        "wires": [
            [
                "b63f0510.079cf8"
            ]
        ]
    },
    {
        "id": "b63f0510.079cf8",
        "type": "debug",
        "z": "ccf03ab3.fc74a8",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 510,
        "y": 380,
        "wires": []
    },
    {
        "id": "6470267.594d9d8",
        "type": "inject",
        "z": "ccf03ab3.fc74a8",
        "name": "",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 190,
        "y": 500,
        "wires": [
            [
                "b225c74.5a80238"
            ]
        ]
    },
    {
        "id": "b225c74.5a80238",
        "type": "function",
        "z": "ccf03ab3.fc74a8",
        "name": "读取留言",
        "func": "//获取未读留言记录\nvar Message = flow.get(\"TTS_Message\");\n//销毁留言记录\nflow.set(\"TTS_Message\",[]);\n//计算留言数量\nvar i = Message.length;\nvar TTS = \"\";\n//如果存在未读留言\nif(i>0){\n    //构造TTS内容\n    var message= \"\";\n    for(var a=0;a<i;a++){\n        message += `${Message[a]['FromUserName']}于${Message[a]['CreateTime']}留言说:${Message[a]['Content']}。`;\n    }\n    TTS = \"您当前共有\"+ i +\"条未读消息,下面开始为您播报:\" + message;\n}else{\n    TTS = \"您当前没有留言消息\"\n}\nmsg.payload = TTS;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 350,
        "y": 460,
        "wires": [
            [
                "b63f0510.079cf8",
                "efec3d7c.9b731"
            ]
        ]
    },
    {
        "id": "b97df726.b550e8",
        "type": "function",
        "z": "ccf03ab3.fc74a8",
        "name": "用触发节点代替",
        "func": "\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 160,
        "y": 460,
        "wires": [
            [
                "b225c74.5a80238"
            ]
        ]
    },
    {
        "id": "40bcf6b9.1ee278",
        "type": "xiaoai-tts-configurator",
        "z": "",
        "name": "导出专用",
        "username": "11111",
        "password": "111111"
    },
    {
        "id": "8a940403.c886a8",
        "type": "bizwechat-configurator",
        "z": "",
        "name": "导出专用",
        "port": "",
        "corpid": "",
        "agentid": "",
        "corpsecret": "",
        "url": "",
        "token": "",
        "aeskey": "",
        "client_id": "",
        "client_secret": ""
    }
]

三木大佬,牛逼

我都设置好,企业微信上发文字 小爱可以留言, 不过发语音却没反应,不知道为啥

有问题 请发log

加入接收人功能,有需要的可以试试

保存留言function替换:

/**
 时间戳
 对Date的扩展,将 Date 转化为指定格式的String
 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
*/
Date.prototype.Format = function(fmt){ //author: meizz
    var o = {
        "M+" : this.getMonth()+1,                 //月份
        "d+" : this.getDate(),                    //日
        "h+" : this.getHours(),                   //小时
        "m+" : this.getMinutes(),                 //分
        "s+" : this.getSeconds(),                 //秒
        "q+" : Math.floor((this.getMonth()+3)/3), //季度
        "S"  : this.getMilliseconds()             //毫秒
    };
    if(/(y+)/.test(fmt))
    fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length));
    for(var k in o)
    if(new RegExp("("+ k +")").test(fmt))
    fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
    return fmt;
};

var FromUserName = {
 '1111':'三木'
}
var ReceiveUser = "";

//判断是打开企业微信后并发送了消息
if(msg.message.MsgType != "event"){
    //判断是有内容的消息
    if(msg.message.AsrContent || msg.message.Content){
        var message = ""
        //如果是语音消息
        if(msg.message.AsrContent){
            message = msg.message.AsrContent[0];
            if(message.indexOf("留言") != -1){
                var str1 = message.split("留言")[0];
                ReceiveUser = str1.substr(1,str1.length);
                message = message.substr(str1.length+2,message.length);
            }else{
                msg.payload = null;
                return msg;
            }
        } 
        //如果是文本消息
        if(msg.message.Content){
            message = msg.message.Content;
            if(message.indexOf("留言") != -1){
                var str1 = message.split("留言")[0];
                ReceiveUser = str1.substr(1,str1.length);
                message = message.substr(str1.length+2,message.length);
            }else{
                msg.payload = null;
                return msg;
            }
        } 
        //获取未读的消息记录
        var Message = flow.get("TTS_Message") || [];
        //统计消息数量
        var i = Message.length;
        //增加新消息
        Message[i] = {};
        Message[i]['FromUserName'] = FromUserName[msg.message.FromUserName];
        Message[i]['ReceiveUser'] = ReceiveUser;
        Message[i]['CreateTime'] = new Date().Format("MM月dd日hh点mm分");
        Message[i]['Content'] = message;
        //保存
        flow.set("TTS_Message", Message);
        msg.payload = Message;
        return msg;
    }
}

读取留言function替换:

//获取未读留言记录
var Message = flow.get("TTS_Message");
//获取查看留言的人
const ReceiveUser = msg.ReceiveUser;
//计算留言数量
var i = Message.length;
var messageCount = 0;
var TTS = "";
var userIndex = [];
//如果存在未读留言
if(i>0){
    //构造TTS内容
    var message= "";
    for(var a=0;a<i;a++){
        console.log(a);
        if("undefined" != Message[a]['ReceiveUser'] && Message[a]['ReceiveUser'] == ReceiveUser ){
            
            message += `${Message[a]['FromUserName']}于${Message[a]['CreateTime']}留言说:${Message[a]['Content']}。`;
           userIndex[messageCount] = a;
           messageCount++;
        }
    }
    if(messageCount === 0){
         TTS = "您当前没有留言消息"
    }else{
        TTS = "您当前共有"+ messageCount +"条未读消息,下面开始为您播报:" + message;
    }
    for(var b = 0; b<userIndex.length;b++){
        if(userIndex[b] !== 0){
            Message.splice(userIndex[b]-b,1);
        }else{
            Message.splice(0,1);
        }
        
    }
}else{
    TTS = ""
}
msg.payload = TTS;
return msg;

注意需要读取留言加入msg.ReceiveUser参数

这样配合摄像头加百度人脸识别就可以播放相应人员的留言了

留言格式: 给……留言……

1 个赞

简直是太棒了。音箱留言,看似是鸡肋,但实际上用户体验非常好。
在node-red下的自动化,部署简单、调试直观、流程灵活。我在这个流程的基础上,简单的增加了一个用户id转名称的map节点;另外,语音播报调用了hass下的tts,驱动小度dlna。image-20200415032207507

大神补充的看起来好牛掰!
不知道大神是否可以开新帖详细的说明一下?很多新人想玩未必能懂哦。

大神好!请问call service节点里面的Data需要怎么填?屏幕快照 2020-04-18 上午10.09.47

空着。你前面节点的输出,就是给他赋值的。

小白超详细解读: 家庭留言-基于企业微信和小度TTS播报

我是留空,但是节点报错

你前面节点赋值不对。你贴出来看看怎么赋值的?应该赋值给“data”
msg.payload.data = { "entity_id": "media_player.xiao_du_zhi_neng_yin_xiang_2811", "message":a, "cache":"false"}

找到你的原贴了谢谢,谢谢了 :joy:

大佬这个读取留言的时候 怎么名字是英文 名字我也是转换了


这个是总体
J~0A_9I%9SZ2JA9BJDJD00A
这个接收到手机的留言
这是保存页面 和读取页面

这个就小爱TTS播报的 是英文 不是王超!QQ图片20210114212126

还有就是 这个留言功能是不是需要在企业微信上重新创建一个助手啊 不能和平时的助手一起用吧 不然发个指令都成了 留言了

是的,要单独建立一个新的应用。
上面错误,请仔细检查代码。提示这个错误,是上游没有传递正常的信息过来

萝卜大佬 看第2张图 我已经转换过来了 那也就是保存下来了