├── .gitignore ├── README.md ├── install.sh └── mico.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /etc 3 | /root -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mico 2 | 3 | 小爱拦截器 4 | 5 | ## 具体见帖子 6 | https://bbs.hassbian.com/thread-5110-1-1.html 7 | 8 | ## 一键安装 9 | ```shell 10 | curl -s "https://raw.githubusercontent.com/FlashSoft/mico/master/install.sh?`date +%s`" > /root/install.sh 11 | sh /root/install.sh 12 | ``` -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | # @author FlashSoft 2 | root=`pwd` 3 | root="" 4 | # 脚本存放地址 5 | mico_path="${root}/root/mico.sh" 6 | # 脚本开机启动 7 | mico_initpath="${root}/etc/init.d/mico_enable" 8 | mico_tmppath="/tmp" 9 | rm $mico_initpath > /dev/null 2>&1 10 | echo "===============================================================" 11 | echo "" 12 | echo " 欢迎使用'小爱拦截器'安装工具 v0.9(2019.06.14)" 13 | echo "" 14 | echo " 本工具通过拦截小爱的识别词和响应词" 15 | echo " 把拦截的请求转发给NodeRed服务进行自定义设备的操作" 16 | echo " 论坛地址 https://bbs.hassbian.com/thread-5110-1-1.html" 17 | echo "" 18 | echo "===============================================================" 19 | echo "" 20 | 21 | # 环境检测,必须为小爱环境才继续 22 | [ -z "`uname -a|grep mico`" ] && echo "当前不是小爱设备,请到小爱上执行此命令" && exit 23 | 24 | 25 | echo "[!!!注意] 需要先有NodeRed服务并且提供了/miai这样的get接口(导入论坛提供的流就好)" 26 | echo "请输入NodeRed服务地址,默认值[http://192.168.1.1:1880/miai]:" 27 | read -p "" nodered_url 28 | [ -z "${nodered_url}" ] && nodered_url="http://192.168.1.1:1880/miai" 29 | 30 | echo "请输入你的NodeRed的账号和密码,如果没有密码请直接回车:" 31 | echo "格式为 账号:密码" 32 | read -p "" nodered_auth 33 | [ -z "${nodered_auth}" ] && nodered_auth=':' 34 | 35 | echo "[!!!注意] 从安装器v0.5版本开始,拦截未知设备无需填写拦截词,如果需要拦截特定情况的可以输入" 36 | echo "请输入响应拦截词,多个拦截词使用|分割,默认值为[空]:" 37 | read -p "" keywords 38 | [ -z "${keywords}" ] && keywords="" 39 | 40 | echo "请输入响应拦截词的更新频率,单位秒,0为不更新,默认值[0]:" 41 | read -p "" keywords_update_timeout 42 | [ -z "${keywords_update_timeout}" ] && keywords_update_timeout=0 43 | 44 | echo "===============================================================" 45 | echo "" 46 | echo " NodeRed服务地址: ${nodered_url}" 47 | echo " NodeRed账号密码: `[ "$nodered_auth" == ":" ] && echo "无密码" || echo "有密码"`" 48 | echo " 响应拦截词: `[ "$keywords" == "" ] && echo "无" || echo "有"`" 49 | echo " 响应拦截词更新频率: ${keywords_update_timeout}" 50 | echo "" 51 | echo "===============================================================" 52 | 53 | echo "以上信息是否正确?任意键继续安装,ctrl+c取消安装:" 54 | read -p "" enterkey 55 | 56 | echo "开始验证nodered访问是否通畅" 57 | echo "" 58 | header=`curl --insecure –connect-timeout 2 -m 4 -sI -u "${nodered_auth}" ${nodered_url}|head -n 1` 59 | echo "状态信息: ${header}" 60 | echo "" 61 | if [ -z "`echo ${header}`" ];then 62 | echo "验证不通过: NodeRed网址不通" 63 | exit 64 | else 65 | if [[ "`echo $header|awk '{print $2}'`" -eq "401" ]];then 66 | echo "验证不通过: NodeRed密码不正确" 67 | exit 68 | else 69 | echo "验证通过" 70 | fi 71 | fi 72 | 73 | if [ -d "/tmp/mibrain" ];then 74 | echo "小爱固件版本: 旧版固件" 75 | else 76 | if [ -d "/tmp/mipns/mibrain" ];then 77 | mico_tmppath="/tmp/mipns" 78 | echo "小爱固件版本: 新版固件" 79 | else 80 | echo "小爱固件版本: 未知固件版本" 81 | exit 82 | fi 83 | fi 84 | 85 | # 下载远程脚本并检查是否成功 86 | now=`date +%s` 87 | mico=`curl --insecure -s –connect-timeout 4 -m 4 "https://raw.githubusercontent.com/FlashSoft/mico/master/mico.sh?${now}"` 88 | # mico=`cat ./mico.sh` 89 | if [[ -z `echo "${mico}"|awk 'match($0,/FlashSoft/){print 1}'` ]];then 90 | echo "脚本下载不成功,可能你需要个酸酸乳" 91 | exit 92 | fi 93 | 94 | # 替换变量并存储 95 | echo "${mico}" | 96 | awk '{gsub("^keywords=.*", "keywords=\"'${keywords}'\""); print $0}' | 97 | awk '{gsub("^keywords_update_timeout=.*", "keywords_update_timeout='${keywords_update_timeout}'"); print $0}' | 98 | awk '{gsub("^nodered_url=.*", "nodered_url=\"'${nodered_url}'\""); print $0}' | 99 | awk '{gsub("^asr_file=.*", "asr_file=\"'${mico_tmppath}'/mibrain/mibrain_asr.log\""); print $0}' | 100 | awk '{gsub("^res_file=.*", "res_file=\"'${mico_tmppath}'/mibrain/mibrain_txt_RESULT_NLP.log\""); print $0}' | 101 | awk '{gsub("^nodered_auth=.*", "nodered_auth=\"'${nodered_auth}'\""); print $0}' > $mico_path 102 | chmod a+x $mico_path 103 | 104 | # 部署脚本 105 | echo "部署启动脚本" 106 | echo "#!/bin/sh /etc/rc.common 107 | START=96 108 | start() { 109 | sh '${mico_path}' & 110 | } 111 | 112 | stop() { 113 | kill \`ps|grep 'sh ${mico_path}'|grep -v grep|awk '{print \$1}'\` 114 | }" > $mico_initpath 115 | chmod a+x $mico_initpath > /dev/null 2>&1 116 | $mico_initpath enable > /dev/null 2>&1 117 | $mico_initpath stop > /dev/null 2>&1 118 | 119 | echo "安装完毕" 120 | echo "可以使用/etc/init.d/mico_enable start 启动小爱拦截器" 121 | -------------------------------------------------------------------------------- /mico.sh: -------------------------------------------------------------------------------- 1 | # @author FlashSoft 2 | # == 自定义配置======================================== 3 | # 设定拦截词,以竖线分割每个拦截词,被拦截的内容会转发给nodered服务器进行处理 4 | keywords="" 5 | # 配置nodered的接收地址 6 | nodered_url="http://192.168.200.209:1880/miai" 7 | # 配置从nodered更新拦截词的间隔,单位秒 8 | # 0代表不更新,一直使用本地拦截词 9 | # 大于0则更新,会从上面设定的nodered_url去获取拦截词,并覆盖本地的拦截词 10 | keywords_update_timeout=0 11 | # == /自定义配置======================================== 12 | 13 | asr_file="/tmp/mipns/mibrain/mibrain_asr.log" 14 | res_file="/tmp/mipns/mibrain/mibrain_txt_RESULT_NLP.log" 15 | nodered_auth="ben:benbendediannao" 16 | 17 | # 解决可能存在第一次文件不存在问题 18 | touch $res_file && touch $asr_file 19 | res_md5="" 20 | last_time=`date +%s` 21 | 22 | echo "== 拦截词: $keywords" 23 | echo "== NodeRed地址:$nodered_url" 24 | echo "== 更新拦截词时间间隔 $keywords_update_timeout 秒" 25 | 26 | while true;do 27 | # 计算md5值 28 | new_md5=`md5sum $res_file | awk '{print $1}'` 29 | # 如果是第一次,就赋值比较用的md5 30 | [ -z $res_md5 ] && res_md5=$new_md5 31 | # 如果md5不等则文件变化 32 | if [[ $new_md5 != $res_md5 ]];then 33 | # 记录md5变化后结果 34 | res_md5=$new_md5 35 | 36 | 37 | # 获取asr内容 38 | asr_content=`cat $asr_file` 39 | # 获取res内容 40 | res_content=`cat $res_file` 41 | 42 | # echo $asr_content 43 | # echo "" 44 | # echo $res_content 45 | 46 | # 如果拦截词不为空,且匹配到了拦截词则试图拦截 47 | 48 | # if [ "`echo "$res_content"|grep '"domain": "smartMiot"'`" ];then 49 | miai_domain=`echo "$res_content"|awk -F '"domain":' '{print $2}'|awk -F '"' '{print $2}'` 50 | miai_errcode=`echo "$res_content"|awk -F '\"extend\":' '{print $2}'|awk -F '\"code\":' '{print $2}'|awk -F ',' '($1>200){print $1}'` 51 | echo "== 有内容更新 | type: $miai_domain errcode: $miai_errcode" 52 | 53 | if ([[ ! -z $keywords ]] && [[ ! -z `echo "$res_content"|awk 'match($0,/'$keywords'/){print 1}'` ]]) || [ $miai_errcode ];then 54 | echo "== 试图停止" 55 | # 若干循环,直到resume成功一次直接跳出 56 | seq 1 200 | while read line;do 57 | code=`ubus call mediaplayer player_play_operation {\"action\":\"resume\"}|awk -F 'code":' '{print $2}'` 58 | if [[ "$code" -eq "0" ]];then 59 | echo "== 停止成功" 60 | break 61 | fi 62 | usleep 50 63 | done 64 | 65 | # 记录播放状态并暂停,方便在HA服务器处理逻辑的时候不会插播音乐,0为未播放,1为播放中,2为暂停 66 | play_status=`ubus -t 1 call mediaplayer player_get_play_status | awk -F 'status' '{print $2}' | cut -c 5` 67 | # echo $play_status 68 | ubus call mediaplayer player_play_operation {\"action\":\"pause\"} > /dev/null 2>&1 69 | 70 | # @todo: 71 | # 转发asr和res给服务端接口,远端可以处理控制逻辑完成后返回需要播报的TTS文本 72 | # 2秒连接超时,4秒传输超时 73 | tts=`curl --insecure -u "$nodered_auth" –connect-timeout 2 -m 4 -s --data-urlencode "asr=$asr_content" --data-urlencode "res=$res_content" $nodered_url` 74 | echo "== 请求完成" 75 | 76 | # 如果远端返回内容不为空则用TTS播报之 77 | if [[ -n "$tts" ]];then 78 | echo "== 播报TTS | TTS内容: $tts" 79 | ubus call mibrain text_to_speech "{\"text\":\"$tts\",\"save\":0}" > /dev/null 2>&1 80 | # 最长20秒TTS播报时间,20秒内如果播报完成跳出 81 | seq 1 20 | while read line;do 82 | media_type=`ubus -t 1 call mediaplayer player_get_play_status|awk -F 'media_type' '{print $2}'|cut -c 5` 83 | if [ "$media_type" -ne "1" ];then 84 | echo "== 播报TTS结束" 85 | break 86 | fi 87 | sleep 1 88 | done 89 | fi 90 | 91 | # 如果之前音乐是播放的则接着播放 92 | if [[ "$play_status" -eq "1" ]];then 93 | echo "== 继续播放音乐" 94 | # 这里延迟一秒是因为前面处理如果太快,可能引起恢复播放不成功 95 | sleep 1 96 | ubus call mediaplayer player_play_operation {\"action\":\"play\"} > /dev/null 2>&1 97 | fi 98 | fi 99 | fi 100 | 101 | # 以某频度去更新拦截词 102 | if [[ "$keywords_update_timeout" -gt "0" ]];then 103 | now=`date +%s` 104 | step=`expr $now - $last_time` 105 | # 根据设定时间间隔获取更新词 106 | if [[ "$step" -gt "$keywords_update_timeout" ]];then 107 | keywords=`curl --insecure -u "$nodered_auth" –connect-timeout 2 -m 4 -s $nodered_url` 108 | echo "== 更新关键词 | 关键词内容: $keywords" 109 | last_time=`date +%s` 110 | fi 111 | fi 112 | usleep 10 113 | done 114 | --------------------------------------------------------------------------------