|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +import configparser |
| 5 | +from hermes_python.hermes import Hermes |
| 6 | +from hermes_python.ffi.utils import MqttOptions |
| 7 | +from hermes_python.ontology import * |
| 8 | +import io |
| 9 | +import requests |
| 10 | +# import urllib2 |
| 11 | +import json |
| 12 | +import jellyfish |
| 13 | + |
| 14 | +MAX_JARO_DISTANCE = 0.4 |
| 15 | + |
| 16 | +CONFIGURATION_ENCODING_FORMAT = "utf-8" |
| 17 | +CONFIG_INI = "config.ini" |
| 18 | + |
| 19 | +class SnipsConfigParser(configparser.SafeConfigParser): |
| 20 | + def to_dict(self): |
| 21 | + return {section : {option_name : option for option_name, option in self.items(section)} for section in self.sections()} |
| 22 | + |
| 23 | + |
| 24 | +def read_configuration_file(configuration_file): |
| 25 | + try: |
| 26 | + with io.open(configuration_file, encoding=CONFIGURATION_ENCODING_FORMAT) as f: |
| 27 | + conf_parser = SnipsConfigParser() |
| 28 | + conf_parser.readfp(f) |
| 29 | + return conf_parser.to_dict() |
| 30 | + except (IOError, configparser.Error) as e: |
| 31 | + return dict() |
| 32 | + |
| 33 | +#def subscribe_intent_callback(hermes, intentMessage): |
| 34 | +# conf = read_configuration_file(CONFIG_INI) |
| 35 | +# action_wrapper(hermes, intentMessage, conf) |
| 36 | + |
| 37 | +def subscribe_intent_callback(hermes, intentMessage): |
| 38 | + conf = read_configuration_file(CONFIG_INI) |
| 39 | + print(conf) |
| 40 | + print(hermes) |
| 41 | + print(intentMessage) |
| 42 | + # a=IntentClassifierResult(intentMessage).intent_name |
| 43 | + # hermes.publish_end_session(intentMessage.session_id, u"Ok, das mache ich.") |
| 44 | + hermes.publish_continue_session(intentMessage.session_id, u"Ok,",["ryanrudak:switch","ryanrudak:verschiedene"]) |
| 45 | + #hermes.publish_continue_session(intentMessage.session_id, "Ok",texte) |
| 46 | + |
| 47 | + if len(intentMessage.slots.verschiedene) > 0: |
| 48 | + print('---------diverse direkt----------') |
| 49 | + action_wrapperOrdreDirect(hermes, intentMessage, conf) |
| 50 | + else: |
| 51 | + print('---------diverse Aktionen----------') |
| 52 | + action_wrapperOrdre(hermes, intentMessage, conf) |
| 53 | + |
| 54 | + |
| 55 | +def action_wrapperOrdre(hermes, intentMessage, conf): |
| 56 | + myListSceneOrSwitch=dict() |
| 57 | + print(" - action_wrapperOrdre - - - Scenen ermitteln") |
| 58 | + myListSceneOrSwitch= getSceneNames(conf,myListSceneOrSwitch) |
| 59 | + print("Schalter ermitteln") |
| 60 | + myListSceneOrSwitch= getSwitchNames(conf,myListSceneOrSwitch) |
| 61 | + intentSwitchActionList=BuildActionSlotList(intentMessage) |
| 62 | + # print(" - action_wrapperOrdre intentSwitchActionList: "+intentSwitchActionList) |
| 63 | + actionText="" |
| 64 | + myAction = True |
| 65 | + for intentSwitchAction in intentSwitchActionList: |
| 66 | + #print("intentSwitchAction: "+intentSwitchAction) |
| 67 | + Match= ActionneEntity(intentSwitchAction["Name"],intentSwitchAction["State"],myListSceneOrSwitch,conf) |
| 68 | + #print("Match: "+Match) |
| 69 | + DomoticzRealName=Match[1] |
| 70 | + print("DomoticzRealName: "+DomoticzRealName) |
| 71 | + myAction=myAction and Match[0] |
| 72 | + if intentSwitchAction["State"]=="On": |
| 73 | + texte = u"Einschalten" |
| 74 | + else: |
| 75 | + texte = u"Ausschalten" |
| 76 | + # actionText=u'{}, {} {}'.format(actionText,texte,str(DomoticzRealName)) |
| 77 | + if myAction and len(intentSwitchActionList)>0: |
| 78 | + hermes.publish_end_session(intentMessage.session_id, actionText) |
| 79 | + else: |
| 80 | + hermes.publish_end_session(intentMessage.session_id, u"Entschuldigung, ich habe es nicht verstanden.") |
| 81 | + |
| 82 | + |
| 83 | +def getSceneNames(conf,myListSceneOrSwitch): |
| 84 | +# response = urllib2.urlopen(global_conf.get("secret").get("hostname")+'/json?type=scenes') |
| 85 | +# jsonresponse = json.load(response) |
| 86 | + myURL="http://"+conf['secret'].get("username")+':'+conf.get('secret').get("passwd")+'@'+conf['secret'].get("hostname")+':'+conf.get('secret').get("port")+"/json.htm?type=scenes" |
| 87 | + response = requests.get(myURL) |
| 88 | + jsonresponse = response.json() |
| 89 | + #jsonresponse = json.load(response) |
| 90 | + for scene in jsonresponse["result"]: |
| 91 | + myName=scene["Name"].encode('utf-8') |
| 92 | + myListSceneOrSwitch[(scene["idx"])] = {'Type':'switchscene','Name':myName} |
| 93 | + print('---------SceneName----------') |
| 94 | + return myListSceneOrSwitch |
| 95 | + |
| 96 | + |
| 97 | +def getSwitchNames(conf,myListSceneOrSwitch): |
| 98 | +# response = urllib2.urlopen(global_conf("secret").get("hostname")+'/json?type=command¶m=getlightswitches') |
| 99 | +# jsonresponse = json.load(response) |
| 100 | + myURL='http://'+conf['secret'].get("username")+':'+conf.get('secret').get("passwd")+'@'+conf['secret'].get("hostname")+':'+conf['secret'].get("port")+'/json.htm?type=command¶m=getlightswitches' |
| 101 | + response = requests.get(myURL) |
| 102 | + jsonresponse = response.json() |
| 103 | + # json.load(response) |
| 104 | + for sw in jsonresponse["result"]: |
| 105 | + myName=sw["Name"].encode('utf-8') |
| 106 | + myListSceneOrSwitch[(sw["idx"])] = {'Type':'switchlight','Name':myName} |
| 107 | + print('---------SwitchName----------') |
| 108 | + return myListSceneOrSwitch |
| 109 | + |
| 110 | +def BuildActionSlotList(intent): |
| 111 | + intentSwitchList=list() |
| 112 | + intentSwitchActionList=list() |
| 113 | + intentSwitchState='None' #by default if no action |
| 114 | + for (slot_value, slot) in intent.slots.items(): |
| 115 | + print("Slot_value: "+slot_value) |
| 116 | + if slot_value=="action" or slot_value=="switch": |
| 117 | + for slot_value2 in slot.all(): |
| 118 | + print("Slot_Value2: "+slot_value2.value) |
| 119 | + print("---------------------------------") |
| 120 | + for (slot_value, slot) in intent.slots.items(): |
| 121 | + print('Slot {} -> Raw: {} Value: {}'.format(slot_value, slot[0].raw_value, slot[0].slot_value.value.value)) |
| 122 | +# print('Slot {} -> Raw: {} Value: {}'.format(slot_value, slot[0].raw_value, slot[0].slot_value.value.value)) |
| 123 | + print(" BuildActionSlotList - action: "+slot_value) |
| 124 | + print(" slot_value: "+slot_value) |
| 125 | + if slot_value=="switch": |
| 126 | + #NLU parsing does not preserve order of slot, thus it is impossible to have different action ON and OFF in the same intent=> keep only the first: |
| 127 | + print(" - BuildAcitionSlotList - slot[0].slot_value.value.value: "+slot[0].slot_value.value.value) |
| 128 | + if slot[0].slot_value.value.value=="TurnOn": |
| 129 | + intentSwitchState='On' |
| 130 | + print(" - Wenn TurnOn, dann: "+intentSwitchState) |
| 131 | + else : |
| 132 | + intentSwitchState='Off' |
| 133 | + print(" - ansonsten, dann: "+intentSwitchState) |
| 134 | + print(" - SchalterStatus: "+intentSwitchState) |
| 135 | + elif slot_value=="action": |
| 136 | + for slot_value2 in slot.all(): |
| 137 | + intentSwitchList.append(slot_value2.value) |
| 138 | + print(" - Slotvalue: "+slot_value2.value) |
| 139 | + |
| 140 | + # wenn intentSwitchState nicht 'None' enthält, dann mySwitch zusammenstellen |
| 141 | + if not intentSwitchState=='None': |
| 142 | + for mySwitch in intentSwitchList: |
| 143 | + intentSwitchActionList.append({'Name':mySwitch,'State':intentSwitchState}) |
| 144 | + print(mySwitch+"------>"+intentSwitchState) |
| 145 | + return intentSwitchActionList |
| 146 | + |
| 147 | +def curlCmd(idx,myCmd,myParam,conf): |
| 148 | + command_url="http://"+conf['secret'].get("username")+':'+conf.get('secret').get("passwd")+'@'+conf.get("secret").get("hostname")+':'+conf.get("secret").get("port")+'/json.htm?type=command¶m='+myParam+'&idx='+str(idx)+'&switchcmd='+myCmd |
| 149 | + ignore_result = requests.get(command_url) |
| 150 | + |
| 151 | + |
| 152 | +def ActionneEntity(name,action,myListSceneOrSwitch,conf): |
| 153 | + #derived from nice work of https://github.com/iMartyn/domoticz-snips |
| 154 | + lowest_distance = MAX_JARO_DISTANCE |
| 155 | + lowest_idx = 65534 |
| 156 | + lowest_name = "Unknown" |
| 157 | + MyWord=name |
| 158 | + DomoticzRealName="" |
| 159 | + print(" - ActionneEntity: "+MyWord) |
| 160 | + for idx,scene in myListSceneOrSwitch.items(): |
| 161 | + print("Scene/Schalter: "+str(scene['Name'],'utf-8')+" idx: "+idx) |
| 162 | + distance = 1-jellyfish.jaro_distance(str(scene['Name'],'utf-8'), MyWord) |
| 163 | + print(" Distance is "+str(distance)) |
| 164 | + if distance < lowest_distance: |
| 165 | + print(" Low enough and lowest!") |
| 166 | + lowest_distance = distance |
| 167 | + lowest_idx = idx |
| 168 | + lowest_name = scene['Name'] |
| 169 | + lowest_Type= scene['Type'] |
| 170 | + if lowest_distance < MAX_JARO_DISTANCE: |
| 171 | + print(" - ActionneEntity - lowest_Type: "+lowest_Type) |
| 172 | + DomoticzRealName=str(lowest_name,'utf-8') |
| 173 | + print(" - ActionneEntity - DomoticzRealName: "+DomoticzRealName) |
| 174 | + print(" - ActionneEntity - lowest_idx: "+lowest_idx) |
| 175 | + curlCmd(lowest_idx,action,lowest_Type,conf) |
| 176 | + return True,DomoticzRealName |
| 177 | + hermes.publish_end_session(intent_message.session_id, "Einschalten "+lowest_name) |
| 178 | + else: |
| 179 | + return False,DomoticzRealName |
| 180 | + |
| 181 | + |
| 182 | +def action_wrapperOrdreDirect(hermes, intentMessage, conf): |
| 183 | + myListSceneOrSwitch=dict() |
| 184 | + myListSceneOrSwitch= getSceneNames(conf,myListSceneOrSwitch) |
| 185 | + actionText = u"{}".format(str(intentMessage.slots.OrdreDivers.first().value)) |
| 186 | + print("actionText "+actionText) |
| 187 | + DomoticzRealName="" |
| 188 | + MyAction=ActionneEntity(actionText,'On',myListSceneOrSwitch,conf) |
| 189 | + result_sentence = u"OK. Du hast {} angefordert.".format(str(MyAction[1])) # The response that will be said out loud by the TTS engine. |
| 190 | + if MyAction[0] : |
| 191 | + hermes.publish_end_session(intentMessage.session_id, result_sentence) |
| 192 | + else: |
| 193 | + print(" - action_wrapperOrdreDirect - keine Action:") |
| 194 | + hermes.publish_end_session(intentMessage.session_id, u"Entschuldigung, es ist etwas schief gegangen.") |
| 195 | + |
| 196 | + |
| 197 | +if __name__ == "__main__": |
| 198 | + mqtt_opts = MqttOptions() |
| 199 | + with Hermes(mqtt_options=mqtt_opts) as h: |
| 200 | + h.subscribe_intent("ryanrudak:switch", subscribe_intent_callback)\ |
| 201 | + .subscribe_intent("ryanrudak:verschiedene", subscribe_intent_callback)\ |
| 202 | + .start() |
0 commit comments