本帖最后由 Anooki 于 2020-11-30 08:41 编辑
开头声明:这篇教程内容很简单,大佬们可以略过,因为我也是小白,搞个这踩了很多坑,所以想给同为小白的一点帮助。不过如果有大佬能帮我优化那也是极好的。
前提条件:1.已注册好企业微信,并至少建立一个应用,可参照这篇教程。企业微信新建应用
一.整个流程图分为11步:(目前设备比较少,图中以窗帘为例,其他灯光、开关、风扇可忽略,控制方法和窗帘一样)
二.执行过程逻辑
1-接收企业微信端指令 ;
2-分析指令类型,文本或者语音(百度语音转文本功能好像不免费了,所以这里没测试成功);
3-对指令进行分析,要对哪里的什么设备进行什么样的操作(注意标红的内容);(这一步得到的结果用于第5部和第7步的设备筛选)
4-确认指令是否触发(指令错误或者设备不存在就不操作,并返回失败提示内容,左下角那一部分节点);
5&7-依据第3步得到的结果进行设备筛选,5和7的位置可以对调的,区别就是最终你的设备是按照同类型在一起,还是同一个位置的在一起;不过建议还是按照同类型的放在一起(和我案例一样),原因见下一条;
6-对操作(service)进行格式化,确保和ha的service是一致的。因为我第3步只分类了两种操作,turn_on和turn_off,但是ha里窗帘的操作(service)是open_cover和close_cover,所以这里把turn_on和turn_off,转化为open_cover和close_cove。如果ha里的操作就是turn_on和turn_off(比如switch),那么第这一步就可以省略了;
7-依据位置选定对应的设备;
8-到了这一步,我们要操作的设备应该是已经确定了,所以这一步我们就选择具体的设备就好了;
9-执行操作(service),因为这一步所需要的所有设备信息在前几步已经都确定了,所以内容就不用填了,系统自己获取
domain-第3步已经获取
service-第3步或者第6步已经获取
entity id-第8步已经获取
10-编辑执行成功的指令;
11-推送执行成功的指令到企业微信;
三.指令分析说明(第3步)
因为我也没有学过编程,js语法更是百度来的,所以有错误或简便的方案,还望指出(奇怪了,代码帖进去,怎么出来就不一样了)
var trigger_flag = false
var filter_entity = {
'cover': '窗帘|帘子|窗户',
'switch': '开关|插座$|电源$|声音$|显示屏$|显示器$|屏幕$|童锁$|儿童锁,
};
var filter_position = {
'livingroom': '客厅',
'bedroom': '卧室|主卧|主人卧|主人卧室',
'balcony': '阳台',
'kitchen': '厨房',
'toilet': '卫生间|洗手间|浴室|wc|WC|Wc|wC',
'airfilter': '空气净化器|净化器|空净',
'dc1': '插座总|DC总|dc总',
'dc2': '群晖|服务器|DC一|dc一|DC1|dc1',
'dc3': '小米摄像头|摄像头|摄像机|监控|DC二|dc二|DC2|dc2',
'dc4': '天猫||DC一|dc1|DC1|dc1',
'led': 'led|LED显示屏|显示器|屏幕',
'child_lock': ''
};
var filter_operate = {
'turn_on': '打开|开启|启动|开机',
'turn_off': '关闭|关机|停止|关掉|退出',
};
var entity_info = {}
for(let key in filter_entity){
if(msg.MsgContent.match(filter_entity[key])){
entity_info['entity'] = key
break
}
}
for(let key in filter_position){
if(msg.MsgContent.match(filter_position[key])){
entity_info['position'] = key
break
}
}
for(let key in filter_operate){
if(msg.MsgContent.match(filter_operate[key])){
entity_info['operate'] = key
break
}
}
if(Object.keys(entity_info).length == 3){
trigger_flag = true
}
msg.payload = entity_info
msg.payload.domain = entity_info['entity']
msg.payload.service = entity_info['operate']
msg.trigger = trigger_flag
return msg
总共定义了5个变量:
1.trigger_flag:用来判断指令是否执行,主要是通过entity_info是否包含3个内容(这个就是三面标红的那三个内容),如果包含,这位true,进行触发,不包含这3个内容则执行失败;
2.filter_entity:筛选设备类型,按照系统里的domain进行分类,依据你平时说话的习惯,尽可能的列出你对一个设备的称呼,不同的称呼之间用‘|’进行分割;
3.filter_position:筛选设备位置,同理,依据你平时的习惯尽可能的把所有的位置都列举出来,不过我的开关没有按照位置区分,因为我一个地方可能有很多开关,按照位置区分有问题,所以我按照设备区分,但是存在一个问题,详见下方蓝色字;
4.filter_operate:确认要执行的的操作,这里我只列举了打开和关闭两个操作,你可以自己增加,比如调高温度,降低风量,按照ha里的service进行分类就行,但是有一个原则比如“打开”对应一个turn_on,就不能对应open,不然系统就会可能判断错误,这就是我例子中窗帘为什么要增加第6步的原因;
5.entity_info:将2,3,4,合并成;
上面讲到的问题点:
比如当我们说“关闭客厅的电视”(目的是可能关机),这里的的对应关系是 filter_entity-电视 filter_position:客厅 filter_operate:关闭,
但是当我们说 “关闭电视的开关”(目的可能是断电),而这里对应关系 filter_entity-(插座)开关 filter_position:电视 filter_operate:关闭
发现问题没有,当我们用设备来定义开关的位置的时候,可能会和设备类型搞混淆,按照我们平常的说话方式一般都是
operate(关闭)+position(客厅的)+entity(电视),(要操作的设备或者对象在最后面)
所以我们在判断设备类型的时候有的文字后面加个个“$”符号,比如 '风扇|电扇|空气净化器$|净化器$|空净$',这里 $表示以这个内容结束(以空净结尾),这样就可以避免混淆,其他内容就比较简单,就不耽误大家的时间了。
再说一下我上面为什么建议先筛选设备类型(第5步)再筛选设备位置(第7步)吧,因为这样做,到了第8步是相同的设备再一起,那我们可以公用一个call-service节点(因为同类型设备,service肯定是一样的),如果我们是先第7步然后第5步,那么到了第8步,是一个区域的设备在一起,比如客厅的窗帘、客厅的灯,不同类型的设备service不一样(open_cover、turn_on),那就要用到几个call service节点,流程就很复杂混乱,不够清晰
最后面msg.payload.domain 、msg.payload.service就是第9步要用的信息
我觉得这个方案有一个有点就是后面增加设备、增加判断逻辑比较简单,只需要修改第三步的内容既可以,整个流程不要大的修改,而且流程看起来比较清晰。
|