From 3283770eac16e3c10280503c6eaddca182271de9 Mon Sep 17 00:00:00 2001 From: Henri Rantanen Date: Sat, 26 Mar 2022 21:51:02 +0200 Subject: [PATCH 1/3] Moved settings to YAML file --- glados.py | 80 ++--------- gladosHA.py | 261 ---------------------------------- gladosNotifyAPI.py | 5 +- gladosSerial.py | 14 +- gladosServo.py | 21 +-- gladosTTS.py | 18 ++- glados_functions.py | 13 +- glados_respeaker.py | 30 ++-- glados_settings.py | 33 +++++ settings.env.sample | 47 ------ settings/glados_settings.yaml | 42 ++++++ 11 files changed, 145 insertions(+), 419 deletions(-) delete mode 100644 gladosHA.py create mode 100644 glados_settings.py delete mode 100644 settings.env.sample create mode 100644 settings/glados_settings.yaml diff --git a/glados.py b/glados.py index 795d67d..9aa8442 100755 --- a/glados.py +++ b/glados.py @@ -21,12 +21,12 @@ # Edit settings.env to match your setup # -from gladosTTS import * +##from gladosTTS import * from gladosTime import * -from gladosHA import * from gladosSerial import * from gladosServo import * from glados_functions import * + from skills.glados_jokes import * from skills.glados_magic_8_ball import * from skills.glados_home_assistant import * @@ -39,14 +39,16 @@ import random import psutil -from importlib import import_module +#from importlib import import_module +import glados_settings + +glados_settings.load_from_file() -# Load settings to variables from setting file -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') def start_up(): + + # Show regular eye-texture, this stops the initial loading animation setEyeAnimation("idle") @@ -65,7 +67,7 @@ def start_up(): speak("it's been a long time", cache=True) time.sleep(1.5) speak("how have you been", cache=True) - print("\nWaiting for keyphrase: "+os.getenv('TRIGGERWORD').capitalize()) + print("\nWaiting for keyphrase: "+glados_settings.settings["assistant"]["trigger_word"].capitalize()) eye_position_default() @@ -114,8 +116,8 @@ def take_command(): print("\n\033[1;36mTEST SUBJECT:\033[0;37m: "+command.capitalize() + "\n") # Remove possible trigger word from input - if os.getenv('TRIGGERWORD') in command: - command = command.replace(os.getenv('TRIGGERWORD'), '') + if glados_settings.settings["assistant"]["trigger_word"] in command: + command = command.replace(glados_settings.settings["assistant"]["trigger_word"], '') return command @@ -170,65 +172,7 @@ def process_command(command): elif 'turn off' in command or 'turn on' in command and 'light' in command: speak(home_assistant_process_command(command)) - - - ##### DEVICE CONTROL ########################## - elif 'cinema' in command: - if 'turn on' in command: - runHaScript("kaynnista_kotiteatteri") - speak("Okay. It will take a moment for all the devices to start", cache=True) - if 'turn off' in command: - runHaScript("turn_off_home_cinema") - speak("Sure.") - - elif 'air conditioning' in command or ' ac' in command: - if 'turn on' in command: - speak("Give me a minute.", cache=True) - speak("The neurotoxin generator takes a moment to heat up.", cache=True) - call_HA_Service("climate.set_temperature", "climate.living_room_ac", data='"temperature": "23"') - call_HA_Service("climate.set_hvac_mode", "climate.living_room_ac", data='"hvac_mode": "heat_cool"') - call_HA_Service("climate.set_fan_mode", "climate.living_room_ac", data='"fan_mode": "auto"') - if 'turn off' in command: - call_HA_Service("climate.turn_off", "climate.living_room_ac") - speak("The neurotoxin levels will reach dangerously low levels within a minute.", cache=True) - - elif 'it smells' in command: - runHaScript("cat_poop") - speak("I noticed my air quality sensors registered some organic neurotoxins.", cache=True) - speak("Let me spread it around a bit!", cache=True) - - ##### SENSOR OUTPUT ########################### - - elif 'living room temperature' in command: - sayNumericSensorData("sensor.living_room_temperature") - - elif 'bedroom temperature' in command: - num = sayNumericSensorData("sensor.bedroom_temperature") - if(num>23): - speak("This is too high for optimal relaxation experience.") - - elif 'outside temperature' in command: - speak("According to your garbage weather station in the balcony") - sayNumericSensorData("sensor.outside_temperature") - - elif 'incinerator' in command or 'sauna' in command: - num = sayNumericSensorData("sensor.sauna_temperature") - if num > 55: - speak("The Aperture Science Emergency Intelligence Incinerator Pre-heating cycle is complete, you should get in", cache=True) - speak("You will be baked and then there will be cake.", cache=True) - elif num <= 25: - speak("Testing cannot continue", cache=True) - speak("The Aperture Science Emergency Intelligence Incinerator is currently offline", cache=True) - elif num > 25: - speak("The Aperture Science Emergency Intelligence Incinerator Pre-heating cycle is currently running", cache=True) - saySaunaCompleteTime(num) - - elif 'temperature' in command: - sayNumericSensorData("sensor.indoor_temperature") - - elif 'humidity' in command: - sayNumericSensorData("sensor.living_room_humidity") ##### PLEASANTRIES ########################### @@ -294,7 +238,7 @@ def process_command(command): start_up() # Local keyword detection loop -speech = LiveSpeech(lm=False, keyphrase=os.getenv('TRIGGERWORD'), kws_threshold=1e-20) +speech = LiveSpeech(lm=False, keyphrase=glados_settings.settings["assistant"]["trigger_word"], kws_threshold=1e-20) for phrase in speech: try: # Listen for command diff --git a/gladosHA.py b/gladosHA.py deleted file mode 100644 index 1a89342..0000000 --- a/gladosHA.py +++ /dev/null @@ -1,261 +0,0 @@ -import requests -import os -from gladosTTS import * -import random -import json -import datetime as dt - -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') - -# Get settings form environment file -token = os.getenv('HOME_ASSISTANT_TOKEN') -endpoint = os.getenv('HOME_ASSISTANT_ADDRESS')+"/api/" - -def addToShoppingList(item): - - item = item.replace(" to my shopping list", "") - item = item.replace(" on my shopping list", "") - item = item.replace("add ", "") - item = item.replace("ask ", "") - item = item.capitalize() - - url = endpoint+"services/shopping_list/add_item" - - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - payload = '{"name":"'+item+'"}' - response = requests.post(url, headers=headers, data=payload, verify=False) - - if 'Cake' in item: - speak("The Enrichment Center is required to remind you that you will be baked, and then there will be cake.") - elif 'French fries' in item: - speak("If you want to upset a human, just say their weight variance is above or below the norm.") - else: - speak("I have added "+item+" to your shopping list") - -def activateScene(scene): - url = endpoint+"services/scene/turn_on" - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - payload = '{"entity_id":"'+scene+'"}' - - response = requests.post(url, headers=headers, data=payload, verify=False) - -def runHaScript(script): - url = endpoint+"services/script/"+script - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - response = requests.post(url, headers=headers, verify=False) - -def lightSwitch(light, state="on"): - url = endpoint+"services/light/turn_"+state - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - payload = '{"entity_id":"'+light+'"}' - - response = requests.post(url, headers=headers, data=payload, verify=False) - -def setCoverTo(position): - url = endpoint+"services/script/" - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - if position == "closed": - url += "close_bedroom_blinds" - else: - url += "1583532017564" - - response = requests.post(url, headers=headers, verify=False) - -def sayNumericSensorData(sensor): - - speak("Hold on", cache=True) - - url = endpoint+"states/"+sensor - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - try: - response = requests.get(url, headers=headers, verify=False) - except: - return False - pass - sensorData = json.loads(response.text) - sensorValue = float(sensorData['state']); - sensorName = sensorData['attributes']["friendly_name"] - sensorUnit = sensorData['attributes']["unit_of_measurement"] - - if "°C" in sensorUnit: - sensorValue = round(sensorValue,1) - - elif "g/m³" in sensorUnit: - sensorValue = round(sensorValue,1) - - else: - sensorValue = int(sensorValue) - - speak(cleanTTSLine("The " + sensorName + " is currently " + str(sensorValue)+" "+sensorUnit)) - - - return sensorValue - -def saySaunaCompleteTime(temperature): - readyTemp = 60 - minutesLeft = int(8/3*(readyTemp-int(temperature))) - readyTime = dt.datetime.today() + dt.timedelta(minutes = minutesLeft) - hour = readyTime.strftime('%H') - minute = readyTime.strftime('%M') - - speak("The operational temperature will be reached approximately at "+hour+":"+minute) - - -def sayCurrentWeatherfromHA(): - url = endpoint+"states/"+os.getenv('HOME_ASSISTANT_WEATHER_ENTITY') - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - try: - response = requests.get(url, headers=headers, verify=False) - except: - return False - pass - - sensorData = json.loads(response.text) - weather = sensorData['state']; - temperature = str(sensorData['attributes']['temperature']); - - speak("The current atmospheric conditions near the enrichment center are") - speak(weather) - speak("Temperature on the surface is approximately") - speak(temperature) - speak("°C") - -# 0 being today, 1 tomorrow, etc -def sayforecastfromHA(days): - - # Apologize for TTS delay - speak("Let me check that for you, give me a moment.", cache=True) - - url = endpoint+"states/"+os.getenv('HOME_ASSISTANT_WEATHER_ENTITY') - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - try: - response = requests.get(url, headers=headers, verify=False) - except: - return False - pass - - sensorData = json.loads(response.text) - - # TODO: HA returns the forecast on +00:00 timezone. - # Currently this can give wrong day's forecast depending on what time you ask. - - forecast = sensorData['attributes']['forecast'][days] - - # Parse weekday of the forecast datetime - # Swedish Weather Institute format (SMHI) - forecastWeekday = dt.datetime.strptime(forecast["datetime"], '%Y-%m-%dT%H:%M:%S').strftime('%A') - - weather = "" - - if(days == 0): - weather += "Today it's expected to be " - day = "today" - elif(days == 1): - weather += "Tomorrow, the weather should be " - day = "tomorrow" - elif(days > 1): - weather += "On "+forecastWeekday+" the weather is expected to be " - day = "on " + forecastWeekday - - weather += str(forecast["condition"]) - weather += ", with the surface temperatures ranging from " - weather += str(forecast["temperature"]) - weather += " °, " - weather += "to the low of " - weather += str(forecast["templow"]) - weather += " °C." - - if(forecast["precipitation"] > 5): - weather += " Please note that, there is a " + str(forecast["precipitation"]) + " procent chance of rain " + day +"." - else: - weather += " It is not expected to rain " + day +"." - - if(days > 7): - weather = "Forecasts this long are out of the authority of my weather core" - - speak(weather, cache=False) - -def getDayIndex(command): - if 'today' in command: - return 0 - elif 'tomorrow' in command: - return 1 - elif 'the day after tomorrow' in command: - return 2 - elif 'monday' in command: - requestIndex = 0 - elif 'tuesday' in command: - requestIndex = 1 - elif 'wednesday' in command: - requestIndex = 2 - elif 'thursday' in command: - requestIndex = 3 - elif 'friday' in command: - requestIndex = 4 - elif 'saturday' in command: - requestIndex = 5 - elif 'sunday' in command: - requestIndex = 6 - else: - return 0 - - currentTimestamp = dt.datetime.today() - weekdayIndex = currentTimestamp.weekday() - - diff = requestIndex-weekdayIndex - if diff < 0: - diff = diff + 7 - - return diff - -def call_HA_Service(service, entity, data=""): - - domain = service.partition(".")[0] - service = service.partition(".")[2] - - url = endpoint+"services/"+domain+"/"+service - - headers = { - "Authorization": "Bearer "+token, - "content-type": "application/json", - } - - if data != "": - data = ", "+data - - payload = '{"entity_id": "'+entity+'"'+data+'}' - - response = requests.post(url, headers=headers, data=payload, verify=False) diff --git a/gladosNotifyAPI.py b/gladosNotifyAPI.py index 1df6aed..2521e04 100644 --- a/gladosNotifyAPI.py +++ b/gladosNotifyAPI.py @@ -1,5 +1,3 @@ -#flask run --host=0.0.0.0 - from flask import Flask, request from gladosTTS import * @@ -26,5 +24,4 @@ def notify(): # amixer -D pulse sset Master 50% if __name__ == "__main__": - app.run(host="0.0.0.0") - + app.run(host="0.0.0.0") \ No newline at end of file diff --git a/gladosSerial.py b/gladosSerial.py index 27e6f1e..f67a003 100644 --- a/gladosSerial.py +++ b/gladosSerial.py @@ -1,17 +1,19 @@ from gladosTTS import * import time import serial -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') + +import glados_settings +glados_settings.load_from_file() + def setEyeAnimation(animation="idle"): - if(os.getenv('EYE_SERIAL_ENABLE') == "true"): + if(glados_settings.settings["hardware"]["eye_controller"]["serial_enable"] == "true"): try: ser = serial.Serial( - port=os.getenv('EYE_SERIAL_PORT'), - baudrate=os.getenv('EYE_SERIAL_RATE'), + port=glados_settings.settings["hardware"]["eye_controller"]["serial_port"], + baudrate=oglados_settings.settings["hardware"]["eye_controller"]["serial_rate"], parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, @@ -36,4 +38,4 @@ def setEyeAnimation(animation="idle"): except serial.SerialException: #speak("It looks like some bird has stolen my eye") print(serial.SerialException) - print("ERROR: Serial connection to the eye failed.") \ No newline at end of file + print("ERROR: Serial connection to the eye failed.") diff --git a/gladosServo.py b/gladosServo.py index 2d971c8..782e2f4 100644 --- a/gladosServo.py +++ b/gladosServo.py @@ -1,12 +1,13 @@ import maestro import os from random import randint -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') + +import glados_settings +glados_settings.load_from_file() def eye_position_random(): - if(os.getenv('MAESTRO_SERIAL_ENABLE') == "true"): - servo = maestro.Controller(ttyStr=os.getenv('MAESTRO_SERIAL_PORT')) + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] == "true"): + servo = maestro.Controller(ttyStr=glados_settings["hardware"]["servo_controller"]["serial_port"]) servo.setAccel(0,25) servo.setSpeed(0,100) servo.setAccel(1,25) @@ -17,8 +18,8 @@ def eye_position_random(): servo.close() def eye_position_default(): - if(os.getenv('MAESTRO_SERIAL_ENABLE') == "true"): - servo = maestro.Controller(ttyStr=os.getenv('MAESTRO_SERIAL_PORT')) + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] == "true"): + servo = maestro.Controller(ttyStr=glados_settings["hardware"]["servo_controller"]["serial_port"]) servo.setAccel(0,15) servo.setSpeed(0,10) servo.setAccel(1,25) @@ -29,8 +30,8 @@ def eye_position_default(): servo.close() def eye_position_open(): - if(os.getenv('MAESTRO_SERIAL_ENABLE') == "true"): - servo = maestro.Controller(ttyStr=os.getenv('MAESTRO_SERIAL_PORT')) + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] == "true"): + servo = maestro.Controller(ttyStr=glados_settings["hardware"]["servo_controller"]["serial_port"]) servo.setAccel(0,15) servo.setSpeed(0,10) servo.setAccel(1,25) @@ -44,8 +45,8 @@ def eye_position_open(): servo.close() def eye_position_script(script): - if(os.getenv('MAESTRO_SERIAL_ENABLE') == "true"): - servo = maestro.Controller(ttyStr=os.getenv('MAESTRO_SERIAL_PORT')) + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] == "true"): + servo = maestro.Controller(ttyStr=glados_settings["hardware"]["servo_controller"]["serial_port"]) servo.setAccel(0,15) servo.setSpeed(0,100) servo.setAccel(1,25) diff --git a/gladosTTS.py b/gladosTTS.py index 7a7e4ae..d6b406d 100644 --- a/gladosTTS.py +++ b/gladosTTS.py @@ -5,21 +5,25 @@ from threading import Timer from gladosSerial import * from gladosServo import * - +from glados_functions import * import sys import urllib.parse import re import json import random -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') + import shutil from subprocess import call -if(os.getenv('TTS_ENGINE_API') == ''): from glados_tts.engine import * +import glados_settings +glados_settings.load_from_file() + +if(glados_settings.settings["tts"]["api"] == ''): from glados_tts.engine import * from glados_functions import * -synthFolder = os.getenv('TTS_CACHE_FOLDER') + "/" + +synthFolder = glados_settings.settings["tts"]["cache_folder"] + "/" + def playFile(filename): call(["aplay", "-q", filename]) @@ -58,7 +62,7 @@ def checkTTSLib(line): def fetchTTSSample(line): # Local TTS Engine - if(os.getenv('TTS_ENGINE_API') == ''): + if(glados_settings.settings["tts"]["api"] == ''): if(glados_tts(cleanTTSLine(line)) == True): print('Success: TTS sample "'+line+'" fetched') setEyeAnimation("idle") @@ -67,7 +71,7 @@ def fetchTTSSample(line): # Remote TTS Engine API else: text = urllib.parse.quote(cleanTTSLine(line)) - TTSCommand = 'curl -L --retry 5 --get --fail -o audio/GLaDOS-tts-temp-output.wav '+os.getenv('TTS_ENGINE_API')+text + TTSCommand = 'curl -L --retry 5 --get --fail -o audio/GLaDOS-tts-temp-output.wav '+glados_settings.settings["tts"]["api"]+text setEyeAnimation("wait") TTSResponse = os.system(TTSCommand) diff --git a/glados_functions.py b/glados_functions.py index d63774d..8570148 100644 --- a/glados_functions.py +++ b/glados_functions.py @@ -1,14 +1,15 @@ #!/usr/bin/python3 from glados_respeaker import * -from gladosSerial import * -from gladosServo import * +#from gladosSerial import * +#from gladosServo import * from word2number import w2n -from subprocess import call +import subprocess from skills.glados_home_assistant import home_assistant_utility_script import re import os -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') +import yaml +#from dotenv import load_dotenv +#load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') def started_listening(): @@ -122,4 +123,4 @@ def adjust_volume(command): elif volume_procent < 40: return "I will be speaking to you softly, with a volume of "+str(volume_procent)+"%." else: - return "OK. Fine. I have set the volume to "+str(volume_procent)+"%." + return "OK. Fine. I have set the volume to "+str(volume_procent)+"%." \ No newline at end of file diff --git a/glados_respeaker.py b/glados_respeaker.py index ea93a7f..f77978a 100644 --- a/glados_respeaker.py +++ b/glados_respeaker.py @@ -1,11 +1,22 @@ #!/usr/bin/python3 import os -from dotenv import load_dotenv -load_dotenv(dotenv_path=os.path.dirname(os.path.abspath(__file__))+'/settings.env') + +import glados_settings +glados_settings.load_from_file() + +def respeaker_init(): + + # Try to load the ReSpeaker pixel ring library + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] in ('true', '1', 't')): + try: + from pixel_ring import pixel_ring + except Exception as e: + respeaker_errors(e) # Parse error messages into most common help hints def respeaker_errors(e): + if "Access denied" in str(e): print("\nERROR: No permission to access ReSpeaker hardware.") print("Check the README.md for udev rules in the hardware/respeaker folder.") @@ -23,12 +34,6 @@ def respeaker_errors(e): else: print(e) -# Try to load the ReSpeaker pixel ring library -if(os.getenv('RESPEAKER_CONNECTED', 'False').lower() in ('true', '1', 't')): - try: - from pixel_ring import pixel_ring - except Exception as e: - respeaker_errors(e) # Set the ring to static color. # Input 8 bit HEX color codes @@ -36,15 +41,17 @@ def respeaker_pixel_ring(rgb=0x100000): # Set respeaker to dim glow inside the head. # See hardware folder for more info. - if(os.getenv('RESPEAKER_CONNECTED', 'False').lower() in ('true', '1', 't')): + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] in ('true', '1', 't')): try: pixel_ring.set_color(rgb) except Exception as e: respeaker_errors(e) + # Set respeaker to animation modes def respeaker_mode(mode): - if(os.getenv('RESPEAKER_CONNECTED', 'False').lower() in ('true', '1', 't')): + + if(glados_settings.settings["hardware"]["servo_controller"]["serial_enable"] in ('true', '1', 't')): if(mode == "listen"): try: pixel_ring.listen() @@ -55,3 +62,6 @@ def respeaker_mode(mode): pixel_ring.wait() except Exception as e: respeaker_errors(e); + + +respeaker_init() diff --git a/glados_settings.py b/glados_settings.py new file mode 100644 index 0000000..3be5ff6 --- /dev/null +++ b/glados_settings.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +import os +import yaml + +glados_settings_file = "settings/glados_settings.yaml" +settings = "" + +def load_from_file(): + # Load settings to variables from setting file + global glados_settings_file + global settings + + # Allow script to find the settings file if ran directly + if (os.path.exists("../"+glados_settings_file)): + glados_settings_file = "../"+glados_settings_file + + # Check for setting YAML + if (os.path.exists(glados_settings_file)): + + # Check if YAML is valid and load it to RAM + with open(glados_settings_file, "r") as stream: + try: + settings = yaml.safe_load(stream) + return settings + except yaml.YAMLError as exc: + print("\033[1;31mERROR:\033[1;97m Error parsing "+glados_settings_file+" file:\n") + print(exc) + exit() + + else: + settings = False + print(glados_settings_file + " file not found.") + exit() \ No newline at end of file diff --git a/settings.env.sample b/settings.env.sample deleted file mode 100644 index 846319a..0000000 --- a/settings.env.sample +++ /dev/null @@ -1,47 +0,0 @@ -##### GENERAL #################################### - -# What do you call the assistant? -TRIGGERWORD = "hey alexa" - -# Which sound card you use? -SOUND_CARD_ID = 0 -# Get a list with 'python3 -m sounddevice' -# Select "plugequal" if you wanna use ALSAMIX EQ - -# Enable amplifier GPIO pin -SOUND_MUTE_PIN = 17 - -# Use ReSpeaker -RESPEAKER_CONNECTED = false - -# To which serial port the eye is connected? -EYE_SERIAL_ENABLE = false -EYE_SERIAL_PORT = /dev/ttyACM2 -EYE_SERIAL_RATE = 9600 -MAESTRO_SERIAL_ENABLE = false -MAESTRO_SERIAL_PORT = /dev/ttyACM1 -MAESTRO_SERIAL_RATE = 9600 - -# If you are having issues with serial, check that your user belongs to dialout group -# sudo usermod -a -G dialout - -##### TTS Engine Settings ######################## - -# TTS Engine API - Leave blank for local TTS or enter address for remote API -# (example of remote api address: http://glados-tts.com:8124/synthesize/) -TTS_ENGINE_API = - -# TTS Cache - Folder to store TTS samples, absolute path -TTS_CACHE_FOLDER = /home/username/glados-voice-assistant/audio/tts - -##### HOME ASSISTANT API ######################### - -HOME_ASSISTANT_ADDRESS = https://192.168.1.100:8123 -HOME_ASSISTANT_TOKEN = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -HOME_ASSISTANT_WEATHER_ENTITY = weather.home - -##### SPOTIFY #################################### - -SPOTIFY_CLIENT_ID = 00000000000000000000000000000000 -SPOTIFY_CLIENT_SECRET = 00000000000000000000000000000000 -SPOTIFY_COUNTRY_CODE = FI diff --git a/settings/glados_settings.yaml b/settings/glados_settings.yaml new file mode 100644 index 0000000..af1dfbb --- /dev/null +++ b/settings/glados_settings.yaml @@ -0,0 +1,42 @@ +# This file contains the settings of the voice assistant core. +# Skill-related settings are under skill-spesific files. + +assistant: + + # What the assistant is listening for? + trigger_word: "hey alexa" + +hardware: + # Which sound card to use? + sound_card: 0 + # Get a list with 'python3 -m sounddevice' + # Select "plugequal" if you wanna use ALSAMIX EQ + + # Use ReSpeaker? + respeaker_connected: True + + # Animatronics | Teensy: LCD / LED controller + eye_controller: + serial_enable: True + serial_port: "/dev/ttyACM2" + serial_rate: "9600" + + # Animatronics | Pololu Micro Maestro: Servo controller + servo_controller: + serial_enable: True + serial_port: "/dev/ttyACM0" + serial_rate: "9600" + + + # NOTE: If you are having issues with serial, check that your user belongs to dialout group + # sudo usermod -a -G dialout + # To find Maestro and Teensy, replug devices and run: + # echo "EYE_SERIAL_PORT:" && dmesg | grep -A 2 Teensyduino | tail -3 && echo "MAESTRO_SERIAL_PORT:" && dmesg | grep -A 3 "Pololu Corporation" | tail -4 + +tts: + # TTS Engine API - Leave blank for local TTS or enter address for remote API + # (example of remote api address: http://glados-tts.com:8124/synthesize/) + api: "" + + # TTS Cache - Folder to store TTS samples, absolute path + cache_folder: "/home/nerdaxic/glados-voice-assistant/audio/tts" \ No newline at end of file From 948d95f3b5ffbdc39f4e61c8ff4fcbfdb624580d Mon Sep 17 00:00:00 2001 From: salleq Date: Sat, 9 Apr 2022 17:19:27 +0300 Subject: [PATCH 2/3] added glados_settings.yaml to .gitignore (#26) --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7fafe5f..395de8a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,10 @@ collectedWakeWords/** cancelledActivations.txt failed_commands.txt -# Local enviroment file +# Local environment file settings.env home_assistant_settings.yaml +glados_settings.yaml test.py From c08b8704fa5f9227397b47904a63ea5df1d68f6e Mon Sep 17 00:00:00 2001 From: eternalliving <70250520+eternalliving@users.noreply.github.com> Date: Fri, 9 Dec 2022 08:20:33 -0800 Subject: [PATCH 3/3] Update README.md Updating the instructions with the new yaml configuration files --- README.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5015fb0..d7f2649 100644 --- a/README.md +++ b/README.md @@ -126,9 +126,9 @@ Find the sound card ID: ```console python3 -m sounddevice ``` -Generate and edit the settings.env file: +Edit the settings files: ```console -cp ~/glados-voice-assistant/settings.env.sample ~/glados-voice-assistant/settings.env && nano ~/glados-voice-assistant/settings.env +nano ~/glados-voice-assistant/settings/glados_settings.yaml ``` #### 4. To run: Launch the voice assistant: @@ -143,11 +143,9 @@ crontab -e ``` ## Integrate to Home Assistant - To make Home Assistant integration work, you need to enable the API in the home assistant configuration file and generate a long-lived access token. -Add access token and IP-address of the home assistant server into the settings.env file. -### configuration.yaml +### Edit Home Assistants configuration.yaml ```YAML # This will enable rest api api: @@ -157,8 +155,24 @@ notify: - name: glados platform: rest resource: http://192.168.1.XXX:5000/notify +``` + +Generate and edit the settings files: +```console +cp ~/glados-voice-assistant/settings/home_assistant_settings.yaml.sample ~/glados-voice-assistant/settings/home_assistant_settings.yaml && nano ~/glados-voice-assistant/settings/home_assistant_settings.yaml ``` +Add access token and IP-address of the home assistant server into the settings/home_assistant_settings.yaml file. +### home_assistant_settings.yaml +```YAML +# Server related settings +api: + # Address of your Home Assistant server + address: "https://192.168.1.221:8123" + # Long-lived access token + token: "1234" +``` + ## Hardware List of reference hardware what [nerdaxic](https://github.com/nerdaxic/) is developing on, models might not need to be exact. Not a full bill of materials.