Keith
Published © GPL3+

Controlling Hardware with your Voice: Language Processing

Processing language is hard. Fortunately, it can be offloaded to giants such as Google, Amazon, Microsoft, or IBM. Welcome to the cloud.

IntermediateFull instructions provided971
Controlling Hardware with your Voice: Language Processing

Things used in this project

Hardware components

MSP-EXP432P401R SimpleLink MSP432 LaunchPad
Texas Instruments MSP-EXP432P401R SimpleLink MSP432 LaunchPad
×1
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Servo Module (Generic)
×1
LED (generic)
LED (generic)
×1
AIY Voice
Google AIY Voice
×1

Software apps and online services

Code Composer Studio
Texas Instruments Code Composer Studio
Google Dialogflow
Google Cloud Console
Google Assistant Actions Console

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Code

C file for the MSP432P401R

C/C++
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include "UART.h"

int countit = 0;
int timecheck = 0; // Keeps track of time; resolution 1ms

/* Variables for use in UART TX */
int UART_n; // Index variable
int UART_whentoprint = 0; // Time variable for UART TX
int UART_print = 0; // UART TX flag
int UART_size = 0; // Size variable for incrementing UART TX loop while printing to Tera Term
char UART_data[256]; // Buffer for transmission to Tera Term

unsigned char led_count = 0;

// I2C variables
#define NUM_OF_RX_BYTES        3
#define NUM_OF_TX_BYTES        1
uint8_t RXData[NUM_OF_RX_BYTES];
uint8_t TXData[NUM_OF_TX_BYTES] = {0xaa};
int i2c_index = 0;

// state machine vars
int i2c_int16 = 0;
char state = 0;
int beats_period = 0;

/* TimerA UpMode Configuration Parameter */
const Timer_A_PWMConfig pwmConfig = {
        TIMER_A_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
        TIMER_A_CLOCKSOURCE_DIVIDER_20,      // SMCLK/20
        48000,                              // 50 Hz
        TIMER_A_CAPTURECOMPARE_REGISTER_3, //TA0.3
        TIMER_A_OUTPUTMODE_RESET_SET,
        4800 //10%
        };

/* TimerA UpMode Configuration Parameter */
const Timer_A_UpModeConfig upConfig = {
        TIMER_A_CLOCKSOURCE_SMCLK,          // SMCLK Clock Source
        TIMER_A_CLOCKSOURCE_DIVIDER_1,      // SMCLK/1
        48000,                              // 1ms period for a 48MHz frequency
        TIMER_A_TAIE_INTERRUPT_DISABLE,     // Disable Timer interrupt
        TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE, // Enable CCR0 interrupt
        TIMER_A_DO_CLEAR                    // Clear value
        };

/*
 * UART Configuration Parameter. These are the configuration parameters to
 * make the eUSCI A UART module to operate with a 115200 baud rate at 48MHz. These
 * values were calculated using the online calculator that TI provides
 * at:
 * http://processors.wiki.ti.com/index.php/USCI_UART_Baud_Rate_Gen_Mode_Selection
 */
const eUSCI_UART_Config uartConfig = {
EUSCI_A_UART_CLOCKSOURCE_SMCLK,                         // SMCLK Clock Source
        5000,                                           // BRDIV = 5000
        0,                                              // UCxBRF = 0
        0,                                              // UCxBRS = 0
        EUSCI_A_UART_NO_PARITY,                         // No Parity; used for basic error detection
        EUSCI_A_UART_LSB_FIRST,                         // LSB First
        EUSCI_A_UART_ONE_STOP_BIT,                      // One stop bit
        EUSCI_A_UART_MODE,                              // UART mode
        EUSCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION  // No over-sampling
        };

/* Main function */
int main(void)
{
    /* Halting WDT and disabling master interrupts */
    MAP_WDT_A_holdTimer();
    MAP_Interrupt_disableMaster();

    /* Setting power mode of MCU */
    MAP_PCM_setCoreVoltageLevel(PCM_VCORE1);

    /* Set 1 flash wait state for flash banks 0 and 1 */
    /* Necessary when running MCU at 48Mhz */
    MAP_FlashCtl_setWaitState(FLASH_BANK0, 1);
    MAP_FlashCtl_setWaitState(FLASH_BANK1, 1);

    /* Initialize clock signals to 48MHz */
    MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); // Specifying the operating range for the clock
    MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); // Set MCLK
    MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); // Set HSMCLK
    MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); // Set SMCLK

    /* Configuring P1.0, GPIO output */
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN0); // Setting 1.0 low
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); // Setting 1.0 as an output pin

    // Init Port 4 LEDs
    MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, PIN_ALL8);
    MAP_GPIO_setAsOutputPin(GPIO_PORT_P4, PIN_ALL8);


    /* Configuring PWM generation on P2.6*/
    MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
    MAP_Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig);

    /* Select Port 1 for I2C - Set Pin 6, 7 to input Primary Module Function,    (UCB0SIMO/UCB0SDA, UCB0SOMI/UCB0SCL).*/
    // check datasheet 4-2

    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

    /* eUSCI I2C Slave Configuration */
    MAP_I2C_initSlave(EUSCI_B0_BASE, 0x25, EUSCI_B_I2C_OWN_ADDRESS_OFFSET0, EUSCI_B_I2C_OWN_ADDRESS_ENABLE);

    /* Enable the module and enable interrupts */
    MAP_I2C_enableModule(EUSCI_B0_BASE);
    MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0|EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
    MAP_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
    MAP_Interrupt_enableInterrupt(INT_EUSCIB0);

    //////////////////////////////////

    /* Configuring Timer A1 */
    MAP_Timer_A_configureUpMode(TIMER_A1_BASE, &upConfig); // Configure Timer A1
    MAP_Timer_A_startCounter(TIMER_A1_BASE, TIMER_A_UP_MODE); // Starting Timer A1 in up mode
    MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0); // Clearing the CCR0 interrupt for Timer A1
    MAP_Interrupt_enableInterrupt(INT_TA1_0); // Enabling interrupts for TA1_0

    /* Selecting P1.2 and P1.3 in UART mode and configuring UART communication */
    MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION); // P1.2-.3 set to work in UART mode; P1.2 - RXD, P1.3 - TXD
    MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); // Configure UART eUSCI_A0
    MAP_UART_enableModule(EUSCI_A0_BASE); // Enable eUSCI_A0
    MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT|EUSCI_A_UART_RECEIVE_INTERRUPT); // Allow transmit/reveive interrupts for eUSCI_A0
    MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT|EUSCI_A_UART_RECEIVE_INTERRUPT); // Clear transmit interrupt flag (set when the TXBuff is ready to accept more information)
    MAP_Interrupt_enableInterrupt(INT_EUSCIA0); // Enable eUSCI_A0 interrupts

    /* Enabling master interrupts */
    MAP_Interrupt_enableMaster();

    /* Main while loop */
    while (1)
    {

        /* Flag set once every UART_whentoprint time variable period */
        if (UART_print)
        {
            UART_print = 0; // Reset UART_print

            countit++;
            UART_printf("RX:0x%x %d\r\n",state, i2c_int16);
            //UART_printf("RX:0x%x 0x%x 0x%x\r\n",RXData[0], RXData[1], RXData[2]);
           // UART_size = sprintf(UART_data, "Count = %d\r\n ",countit);

            //MAP_UART_transmitData(EUSCI_A0_BASE, UART_data[0]); // Place first byte of information in TXBuff which will set the UART transmit flag when done transferring
        }
    }
}

/* Timer A1 interrupt handler */
/* This function is called every 1ms as per the settings in the Timer A1 configuration above */
void TA1_0_IRQHandler(void) // Pre-defined interrupt handle
{
    MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A1_BASE,
                                             TIMER_A_CAPTURECOMPARE_REGISTER_0); // Clear the CCR0 interrupt flag

    timecheck++; // Keep track of time; 1ms period
    UART_whentoprint++; // Working variable for UART communication; 1ms period

    /* Flash a built in LaunchPad LED controlled by P1.0; 4s period */
    /* Used as a visual debugging cue for Timer A1 configuration */
    if (timecheck % 200 == 0)
    {
        MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0); // Toggle P1.0
    }

    switch (state) {
    case 0x11: // command servo to angle
    {
        int upper = (int)(((long)TA0CCR0*12L)/100L);
        int lower = (int)(((long)TA0CCR0*4L)/100L);

        int servo_percent = i2c_int16;
        int servo_command = lower+(int)(((long)(upper-lower)*(long)servo_percent)/100);

        if (servo_command > upper) servo_command = (long)upper;
        if (servo_command < lower) servo_command = (long)lower;
        TA0CCR3 = (int)servo_command;
        break;
    }
    case 0x21: // turn off all leds
        MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P4, PIN_ALL8);
        break;
    case 0x31: // turn on a specific led
    {
        int led_num = i2c_int16;
        if (led_num < 1) led_num = 1;
        else if (led_num > 8) led_num = 8;
        P4OUT = 0b1<<(led_num-1);
        break;
    }
    case 0x41: // turn on a  number of leds
    {
        int led_count = i2c_int16;
        if (led_count < 1) led_count = 1;
        else if (led_count > 8) led_count = 8;
        int sum = 0;
        int i = 0;
        for (i=0; i<led_count; i++) sum += 0b1<<i;
        P4OUT = sum;
        break;
    }
    case 0x51: // flash LEDs randomly
        if (timecheck % 300 == 0) P4OUT = (int)(255*rand());
        break;
    case 0x61:
    {
        TA0CCR3 = (int)(((long)TA0CCR0*69L)/1000L);
        int bpm = i2c_int16;
        if (bpm > 300) bpm = 300;
        else if (bpm < 1) bpm = 1;
        beats_period = (int)(60000L/(long)bpm); //ms
        if ((timecheck%beats_period) == 0) state = 0x62;
        break;
    }
    case 0x62:
    {
        TA0CCR3 = (int)(((long)TA0CCR0*79L)/1000L);
        if ((timecheck%beats_period) == 0) state = 0x61;
        break;
    }
    default:
        //TA0CCR3 = (int)(((long)TA0CCR0*74L)/1000L); // upright
        TA0CCR3 = TA0CCR0/10;
        if (timecheck % 1000 == 0) MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P4, PIN_ALL8);
        break;
    }

    if (UART_whentoprint == 1000) // Time variable tracking printing to Tera Term
    {
        UART_whentoprint = 0; // Reset UART_whentoprint
        if (MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE) == 0) // If there are no pending transmit interrupts for EUSCI_A0_BASE set UART_print flag and n
        {
            UART_print = 1;
            UART_n = 1;
        }
    }
}
char rec_char = 0;
int USCIA_status  = 0;
/* EUSCI A0 UART interrupt handler. Terra Term Communication */
void EUSCIA0_IRQHandler(void) // Pre-defined EUSCI_A0 interrupt handle
{
    USCIA_status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); // Assign RX/TX interrupt flag to variable


    if (USCIA_status & EUSCI_A_UART_TRANSMIT_INTERRUPT_FLAG) // Checking if a TX interrupt flag triggered this IRQHandler
    {
        MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_INTERRUPT); // Clear transmit interrupt which is initially set in main while loop every UART_whentoprint time interval
//        if (UART_n < (UART_size + 1)) // While n is less than, or equal to, the size of the data vector being transmitted enter this loop
//            {
//                MAP_UART_transmitData(EUSCI_A0_BASE, UART_data[UART_n]); // Place the next byte of data in the TXBuff for transmission which will trigger a transmit interrupt when done transferring and thereby re-entery this interrupt service routine
//                UART_n++; // Increment to next step in data vector being transmitted
//            }

        if(printf_flag) {
            if (currentindex == txcount) {
                senddone = 1;
                printf_flag = 0;
            } else {
            MAP_UART_transmitData(EUSCI_A0_BASE, printbuff[currentindex]);
            currentindex++;
            }
        } else if(UART_flag) {
            if(!donesending) {
                MAP_UART_transmitData(EUSCI_A0_BASE, txbuff[txindex]);
                if(txbuff[txindex] == 255) {
                    donesending = 1;
                    txindex = 0;
                } else {
                    txindex++;
                }
            }
        }

    }
    if (USCIA_status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) // Checking if a RX interrupt flag triggered this IRQHandler
    {
        MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); // Clear transmit interrupt which is initially set in main while loop every UART_whentoprint time interval
        rec_char = MAP_UART_receiveData(EUSCI_A0_BASE); // Assign received data to input
        if(!started) {  // Haven't started a message yet

            if(rec_char == 253) {
                started = 1;
                newmsg = 0;
            }
        } else { // In process of receiving a message
            if((rec_char != 255) && (msgindex < (MAX_NUM_FLOATS*5))) {
                rxbuff[msgindex] = rec_char;

                msgindex++;
            } else { // Stop char received or too much data received
                if(rec_char == 255) { // Message completed
                    newmsg = 1;
                    rxbuff[msgindex] = 255; // "Null"-terminate the array
                }
                started = 0;
                msgindex = 0;
            }
        }

    }
}

int RXcount = 0;
int TXcount = 0;
//This is the EUSCI_B0 interrupt vector service routine.
void EUSCIB0_IRQHandler(void)
{

    //  uint32_t spi_status = MAP_SPI_getEnabledInterruptStatus(EUSCI_B0_BASE);
    //  MAP_SPI_clearInterruptFlag(EUSCI_B0_BASE, spi_status);

    uint_fast16_t i2c_status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE);

    if((i2c_status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) && (UCB0IE & 0x1)){
        // USCI_B0 RX interrupt for I2C
        RXcount++;
        RXData[i2c_index] = MAP_I2C_slaveGetData(EUSCI_B0_BASE);
        i2c_index++;
        // MUST clear both flags, very important
        MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0|EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
        if (i2c_index == NUM_OF_RX_BYTES){
            TXData[0] = RXData[0];
            i2c_index = 0;
            MAP_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
            MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
            // separate and store received vars
            i2c_int16 = (RXData[1]<<8)|(RXData[2]);
            state = RXData[0];
        }
    }

    if((i2c_status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) && (UCB0IE & 0x2)){
        // USCI_B0 TX interrupt for I2C
        TXcount++;
        MAP_I2C_slavePutData(EUSCI_B0_BASE, TXData[i2c_index]);
        i2c_index++;
        MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); // only clear Transmit
        if (i2c_index == NUM_OF_TX_BYTES){
            i2c_index = 0;
            MAP_I2C_disableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0);
            MAP_I2C_enableInterrupt(EUSCI_B0_BASE, EUSCI_B_I2C_RECEIVE_INTERRUPT0);
        }
    }

//    //check this code later
//    if((UCB0IE&UCNACKIE) && (UCB0STAT&UCNACKIFG)) { // I2C NACK interrupt
//
//        UCB0STAT &= ~UCNACKIFG;
//    }
//    if((UCB0IE&UCSTPIE) && (UCB0STAT&UCSTPIFG)) { // I2C Stop interrupt
//
//        UCB0STAT &= ~UCSTPIFG;
//    }
//    if((UCB0IE&UCSTTIE) && (UCB0STAT&UCSTTIFG)) { //  I2C Start interrupt
//
//        UCB0STAT &= ~UCSTTIFG;
//    }
//    if((UCB0IE&UCALIE) && (UCB0STAT&UCALIFG)) {  // I2C Arbitration Lost interrupt
//
//        UCB0STAT &= ~UCALIFG;
//    }
}

Python file for the Ras Pi 3

Python
### google assistant imports ###
import logging
import platform
import sys

from google.assistant.library.event import EventType

from aiy.assistant import auth_helpers
from aiy.assistant.library import Assistant
from aiy.board import Board, Led

### dialogflow imports ###
import dialogflow_v2 as dialogflow
import os
from google.api_core.exceptions import InvalidArgument

### i2c import ###
import smbus2 as smbus

### terminal imports ###
from subprocess import call
import random

### dialogflow globals ###
DIALOGFLOW_PROJECT_ID = 'your-project-id-here' # change this with your own value
DIALOGFLOW_LANGUAGE_CODE = 'en-US'
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = os.path.expanduser('~/dialogflow.json')
SESSION_ID = 'hackster-io-demo' # can set to something unique

session_client = dialogflow.SessionsClient()
session = session_client.session_path(DIALOGFLOW_PROJECT_ID, SESSION_ID)

### i2c globals ###
# I2C channel 1 is connected to the GPIO pins
channel = 1

#  slave address
address = 0x25

# Register addresses
#reg_write_dac = 0xaa

# Initialize I2C (SMBus)
bus = smbus.SMBus(channel)

TXData = [0x00, 0x00, 0x00]
RXData = [None] * 1
num_tx_bytes = len(TXData)
num_rx_bytes = len(RXData)

def next_i2c():
    global TXData, RXData, num_tx_bytes, num_rx_bytes
    
    for i2c_idx in range(num_tx_bytes):
        bus.write_byte(address, TXData[i2c_idx])
    for i2c_idx in range(num_rx_bytes):
        RXData[i2c_idx] = bus.read_byte(address)
    print(TXData[0], (TXData[1]<<8)|TXData[2], RXData[0])

def df_process(text_to_be_analyzed):
    global session
    
    text_input = dialogflow.types.TextInput(text=text_to_be_analyzed, language_code=DIALOGFLOW_LANGUAGE_CODE)
    query_input = dialogflow.types.QueryInput(text=text_input)
    response = session_client.detect_intent(session=session, query_input=query_input)

    try:
        response = session_client.detect_intent(session=session, query_input=query_input)
    except InvalidArgument:
        raise
    
    return response

def states(response):
    global TXData
    detected_intent = response.query_result.intent.display_name
    if detected_intent == "servo_command":
        servo_angle = int(response.query_result.parameters.values()[0])
        # MUST typecast
        TXData[0:3] = [0x11, (servo_angle&0xFF00)>>8, servo_angle&0xFF]
        next_i2c()
    elif detected_intent == "led_all_off":
        TXData[0:3] = [0x21, 0, 0]
        next_i2c()
    elif detected_intent == "led_single_command":
        which = int(response.query_result.parameters.values()[0])
        # MUST typecast
        TXData[0:3] = [0x31, (which&0xFF00)>>8, which&0xFF]
        next_i2c()
    elif detected_intent == "led_count_command":
        count = int(response.query_result.parameters.values()[0])
        # MUST typecast
        TXData[0:3] = [0x41, (count&0xFF00)>>8, count&0xFF]
        next_i2c()
    elif detected_intent == "flashing_lights":
        TXData[0:3] = [0x51, 0, 0]
        next_i2c()
    elif detected_intent == "metronome":
        bpm = int(response.query_result.parameters.values()[0])
        # MUST typecast
        TXData[0:3] = [0x61, (bpm&0xFF00)>>8, bpm&0xFF]
        next_i2c()
    elif detected_intent == "dan_count":
        call("cd /home/pi/Documents/461_proj/sounds; aplay one.wav; aplay two.wav; aplay three.wav; aplay four.wav; aplay five.wav", shell=True)
    elif detected_intent == "dan_words":
        word_list = ["alrightgood.wav", "astar.wav", "waypoint.wav", "weeds.wav"]
        word_choice = word_list[int(random.random()*len(word_list))]
        call("cd /home/pi/Documents/461_proj/sounds; aplay %s" %(word_choice), shell=True)
##    print(response.query_result.parameters.values())
##    print(response.query_result.parameters.keys())
##    print(response.query_result.parameters.items())
##    print("Query text:", response.query_result.query_text)
    print("Detected intent:", response.query_result.intent.display_name)
    print("Detected intent confidence:", response.query_result.intent_detection_confidence)
##    print("Fulfillment text:", response.query_result.fulfillment_text)

def process_event(led, event):
    logging.info(event)

    if event.type == EventType.ON_START_FINISHED:
        led.state = Led.BEACON_DARK  # Ready.
        logging.info('Say "OK, Google" then speak, or press Ctrl+C to quit...')

    elif event.type == EventType.ON_CONVERSATION_TURN_STARTED:
        led.state = Led.ON  # Listening.

    elif event.type == EventType.ON_END_OF_UTTERANCE:
        led.state = Led.PULSE_QUICK  # Thinking.

    elif (event.type == EventType.ON_CONVERSATION_TURN_FINISHED
          or event.type == EventType.ON_CONVERSATION_TURN_TIMEOUT
          or event.type == EventType.ON_NO_RESPONSE):
        led.state = Led.BEACON_DARK
        
    elif event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED:
        heard_text = event.args["text"]
        if heard_text != "":
            df_response = df_process(heard_text)
            states(df_response)

    elif event.type == EventType.ON_ASSISTANT_ERROR and event.args and event.args['is_fatal']:
        sys.exit(1)


def main():
    logging.basicConfig(level=logging.INFO)

    credentials = auth_helpers.get_assistant_credentials()
    with Board() as board, Assistant(credentials) as assistant:
        for event in assistant.start():
            process_event(board.led, event)


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        bus.close()
        sys.exit(1)

Credits

Keith

Keith

2 projects • 1 follower
Thanks to Vincent W..

Comments