MagicMirror² v2.12.0 is available! For more information about this release, check out this topic.

MMM-GoogleAssistant problem with .asoundrc



  • Hello,
    I am trying to install MMM-GoogleAssistant from: https: //www.magicmirrorcentral.com/get-google-assistant-magic-mirror/ because I did not succeed from the official link: https: // github.com/gauravsacc/MMM-GoogleAssistant.

    I block with the .asoundrc and I have a doubt with the node_helper.js

    This is my arecord -land my aplay -l

    pi@raspberrypi:~ $ arecord -l
    **** Liste des Périphériques Matériels CAPTURE ****
    carte 1: USB [WordForum USB], périphérique 0: USB Audio [USB Audio]
      Sous-périphériques: 1/1
      Sous-périphérique #0: subdevice #0
    pi@raspberrypi:~ $ aplay -l
    **** Liste des Périphériques Matériels PLAYBACK ****
    carte 0: b1 [bcm2835 HDMI 1], périphérique 0: bcm2835 HDMI 1 [bcm2835 HDMI 1]
      Sous-périphériques: 4/4
      Sous-périphérique #0: subdevice #0
      Sous-périphérique #1: subdevice #1
      Sous-périphérique #2: subdevice #2
      Sous-périphérique #3: subdevice #3
    carte 2: Headphones [bcm2835 Headphones], périphérique 0: bcm2835 Headphones [bcm2835 Headphones]
      Sous-périphériques: 4/4
      Sous-périphérique #0: subdevice #0
      Sous-périphérique #1: subdevice #1
      Sous-périphérique #2: subdevice #2
      Sous-périphérique #3: subdevice #3
    pi@raspberrypi:~ $ 
    

    If I understand correctly, my microphone is card 2 and device 0 and my headphones are card 1 and device 0, is that correct ?

    I wanted to create a .asoundrc in /home/pi but apparently I had a hidden file. Whenever I open the .asoundrc file here is what is written :

    pcm.!default {
      type asym
      capture.pcm "mic"
      playback.pcm "speaker"
    }
    pcm.mic {
      type plug
      slave {
        pcm "hw:,"
      }
    }
    pcm.speaker {
      type plug
      slave {
        pcm "hw:,"
      }
    }
    
    pcm.output {
    	type hw
    	card 2
    }
    
    ctl.!default {
    	type hw
    	card 2
    }
    
    

    as explained here : https://developers.google.com/assistant/sdk/guides/library/python/embed/audio I copy in .asoundrc file like this :

    pcm.!default {
      type asym
      capture.pcm "mic"
      playback.pcm "speaker"
    }
    pcm.mic {
      type plug
      slave {
        pcm "hw:,"
      }
    }
    pcm.speaker {
      type plug
      slave {
        pcm "hw:,"
      }
    }
    

    but when i type the commands speaker-test -t wav, arecord --format=S16_LE --duration=5 --rate=16000 --file-type=raw out.raw et aplay --format=S16_LE --rate=16000 out.raw
    the terminal display :

    pi@raspberrypi:~ $ speaker-test -t wav
    
    speaker-test 1.1.8
    
    Le périphérique de lecture est default
    Les paramètres du flux sont 48000Hz, S16_LE, 1 canaux
    fichier(s) WAV
    ALSA lib conf.c:4926:(parse_args) Parameter DEV must be an integer
    ALSA lib conf.c:5031:(snd_config_expand) Parse arguments error: Argument invalide
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM hw:,
    Erreur d'ouverture à la lecture: -22,Argument invalide
    pi@raspberrypi:~ $ arecord --format=S16_LE --duration=5 --rate=16000 --file-type=raw out.raw
    ALSA lib conf.c:4926:(parse_args) Parameter DEV must be an integer
    ALSA lib conf.c:5031:(snd_config_expand) Parse arguments error: Argument invalide
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM hw:,
    arecord: main:828: erreur à l'ouverture audio: Argument invalide
    pi@raspberrypi:~ $ aplay --format=S16_LE --rate=16000 out.raw
    ALSA lib conf.c:4926:(parse_args) Parameter DEV must be an integer
    ALSA lib conf.c:5031:(snd_config_expand) Parse arguments error: Argument invalide
    ALSA lib pcm.c:2565:(snd_pcm_open_noupdate) Unknown PCM hw:,
    aplay: main:828: erreur à l'ouverture audio: Argument invalide
    pi@raspberrypi:~ $ 
    
    

    and when i open again the .asoundrc file the therminal display :

    pcm.!default {
      type asym
      capture.pcm "mic"
      playback.pcm "speaker"
    }
    pcm.mic {
      type plug
      slave {
        pcm "hw:,"
      }
    }
    pcm.speaker {
      type plug
      slave {
        pcm "hw:,"
      }
    }
    
    pcm.output {
    	type hw
    	card 2
    }
    
    ctl.!default {
    	type hw
    	card 2
    }
    
    

    WHAT IS THE PROBLEM ?

    also, as explained here [https://www.magicmirrorcentral.com/get-google-assistant-magic-mirror/]
    i copied my keys i copied my keys in the following files node_helper.js, MMM-GoogleAssistant.js, pi/assistant.py are they well completed ? because I have a doubt about the node_helper.js ?
    my node_helper.js :

    /* Magic Mirror
     * Module: MMM-GA
     *
     * By Gaurav
     *
     */
    'use strict';
    
    var NodeHelper = require("node_helper");
    var PubNub = require('pubnub');
    
    module.exports = NodeHelper.create({
    
      initGoogleAssistant: function(payload) {
        var self = this;
        this.pubnub = new PubNub({
          //publishKey,subscribeKey
          pub-c-387c2c32-ca85-4491-b6b3-7a38708ba39c, sub-c-286db504-bcfd-11ea-9208-3200fd38a8e3
          publishKey: payload.publishKey,
          subscribeKey: payload.subscribeKey,
        });
    
        this.pubnub.addListener({
          status: function(statusEvent) {
            if (statusEvent.category === "PNConnectedCategory") {
              //publishSampleMessage();
            }
          },
          message: function(message) {
            if (message.message === 'ON_CONVERSATION_TURN_STARTED') {
              self.sendSocketNotification('ON_CONVERSATION_TURN_STARTED', null);
            } else if (message.message === 'ON_CONVERSATION_TURN_FINISHED') {
              self.sendSocketNotification('ON_CONVERSATION_TURN_FINISHED', null);
            } else if (message.message.includes('ON_RECOGNIZING_SPEECH_FINISHED')) {
              var query = message.message.split(":");
              self.sendSocketNotification('ON_RECOGNIZING_SPEECH_FINISHED', query[1]);
            }
          },
          presence: function(presenceEvent) {
            // handle presence
          }
        });
    
        this.pubnub.subscribe({
          channels: ['magicmirror']
        });
      },
    
      socketNotificationReceived: function(notification, payload) {
        if (notification === 'INIT') {
          console.log("now initializing assistant");
          this.initGoogleAssistant(payload);
        }
      }
    
    });
    
    

    My MMM-GoogleAssistant.js :

    /* Magic Mirror
     * Module: MMM-GoogleAssistant
     *
     * By Gaurav
     *
     */
    
    Module.register("MMM-GoogleAssistant", {
      // Module config defaults.
      defaults: {
        header: "Google Asistant",
        maxWidth: "100%",
        publishKey: 'pub-c-387c2c32-ca85-4491-b6b3-7a38708ba39c',
        subscribeKey: 'sub-c-286db504-bcfd-11ea-9208-3200fd38a8e3',
        updateDelay: 500
      },
    
      // Define start sequence.
      start: function() {
        Log.info('Starting module: Google Assistant Now');
        var self = this;
        this.assistantActive = false;
        this.processing = false;
        this.userQuery = null;
        //this.sendSocketNotification('INIT', 'handshake');
        this.sendSocketNotification('INIT', self.config);
      },
    
      getDom: function() {
        Log.log('Updating DOM for GA');
        var wrapper = document.createElement("div");
    
        if (this.assistantActive == true) {
          if (this.processing == true) {
            wrapper.innerHTML = "<img src="MMM-GoogleAssistant/assistant_active.png" /><br />" + this.userQuery;
          } else {
            wrapper.innerHTML = "<img src="MMM-GoogleAssistant/assistant_active.png" />";
          }
        } else {
          wrapper.innerHTML = "<img src="MMM-GoogleAssistant/assistant_inactive.png" />";
        }
        return wrapper;
      },
    
      socketNotificationReceived: function(notification, payload) {
        var self = this;
        delay = self.config.updateDelay;
        if (notification == 'ON_CONVERSATION_TURN_STARTED') {
          this.assistantActive = true;
          delay = 0;
        } else if (notification == 'ON_CONVERSATION_TURN_FINISHED') {
          this.assistantActive = false;
          this.processing = false;
        } else if (notification == 'ON_RECOGNIZING_SPEECH_FINISHED') {
          this.userQuery = payload;
          this.processing = true;
          delay = 0;
        }
        this.updateDom(delay);
      },
    });
    
    

    My pi/assistant.py :

    #!/usr/bin/env python
    
    # Copyright (C) 2017 Google Inc.
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    
    from __future__ import print_function
    
    import argparse
    import os.path
    import json
    import os
    
    import google.oauth2.credentials
    #import RPi.GPIO as GPIO
    from google.assistant.library import Assistant
    from google.assistant.library.event import EventType
    from google.assistant.library.file_helpers import existing_file
    
    from pubnub.callbacks import SubscribeCallback
    from pubnub.enums import PNStatusCategory
    from pubnub.pnconfiguration import PNConfiguration
    from pubnub.enums import PNReconnectionPolicy
    from pubnub.pubnub import PubNub
    
    #GPIO.setmode(GPIO.BCM)
    #GPIO.setup(25, GPIO.OUT)
    
    global pubnub
    
    #Pubnub Communication
    def my_publish_callback(envelope, status):
        # Check whether request successfully completed or not
        if not status.is_error():
            pass  # Message successfully published to specified channel.
        else:
            pass  # Handle message publish error. Check 'category' property to find out possible issue
            # because of which request did fail.
            # Request can be resent using: [status retry];
    
    class MySubscribeCallback(SubscribeCallback):
        def presence(self, pubnub, presence):
            pass  # handle incoming presence data
    
        def status(self, pubnub, status):
            if status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
                pass  # This event happens when radio / connectivity is lost
    
            elif status.category == PNStatusCategory.PNConnectedCategory:
                # Connect event. You can do stuff like publish, and know you'll get it.
                # Or just use the connected event to confirm you are subscribed for
                # UI / internal notifications, etc
                pubnub.publish().channel("magicmirror").message("hello from python!!").async(my_publish_callback)
            elif status.category == PNStatusCategory.PNReconnectedCategory:
                pass
                # Happens as part of our regular operation. This event happens when
                # radio / connectivity is lost, then regained.
            elif status.category == PNStatusCategory.PNDecryptionErrorCategory:
                pass
                # Handle message decryption error. Probably client configured to
                # encrypt messages and on live data feed it received plain text.
    
        def message(self, pubnub, message):
            print (message.message)
            # pass  # Handle new message stored in message.message
    
    def init_pubnub():
        global pubnub
        pnconfig = PNConfiguration()
        pnconfig.subscribe_key = 'sub-c-286db504-bcfd-11ea-9208-3200fd38a8e3'
        pnconfig.publish_key = 'pub-c-387c2c32-ca85-4491-b6b3-7a38708ba39c'
        pnconfig.reconnect_policy = PNReconnectionPolicy.LINEAR
        pubnub = PubNub(pnconfig)
        pubnub.add_listener(MySubscribeCallback())
        pubnub.subscribe().channels('magicmirror').execute()
        print ('pubnub subscription completed')
    
    
    #googleassistant events processing
    def process_event(event):
        """Pretty prints events.
        Prints all events that occur with two spaces between each new
        conversation and a single space between turns of a conversation.
        Args:
            event(event.Event): The current event to process.
        """
        if event.type == EventType.ON_CONVERSATION_TURN_STARTED:
            os.system("aplay start.wav")
            pubnub.publish().channel("magicmirror").message("ON_CONVERSATION_TURN_STARTED").async(my_publish_callback)
            print()
            #GPIO.output(25,True)
        if (event.type == EventType.ON_CONVERSATION_TURN_FINISHED and
                event.args and not event.args['with_follow_on_turn']):
            pubnub.publish().channel("magicmirror").message("ON_CONVERSATION_TURN_FINISHED").async(my_publish_callback)
            print()
            #GPIO.output(25,False)
        if event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED:
            pubnub.publish().channel("magicmirror").message("ON_RECOGNIZING_SPEECH_FINISHED : "+event.args['text']).async(my_publish_callback)
            print()
    
    def init_googleAssistant():
        parser = argparse.ArgumentParser(
            formatter_class=argparse.RawTextHelpFormatter)
        parser.add_argument('--credentials', type=existing_file,
                            metavar='OAUTH2_CREDENTIALS_FILE',
                            default=os.path.join(
                                os.path.expanduser('/home/pi/.config'),
                                'google-oauthlib-tool',
                                'credentials.json'
                            ),
                            help='Path to store and read OAuth2 credentials')
        args = parser.parse_args()
        with open(args.credentials, 'r') as f:
            credentials = google.oauth2.credentials.Credentials(token=None,
                                                                **json.load(f))
    
        with Assistant(credentials,"magic-mirror-device-id") as assistant:
            for event in assistant.start():
                process_event(event)
    
    def main():
        init_pubnub()
        init_googleAssistant()
    
    if __name__ == '__main__':
        main()
    
    

    Finally, if I try to open with VLC the start.wav file in /home/pi/MagicMirror/modules/MMM-GoogleAssistant/pi, here is what is displayed, is there a link ?

    La sortie audio a échoué:
    Le périphérique audio « default » ne peut pas être utilisé :
    Argument invalide.
    La sortie audio a échoué:
    Le périphérique audio « default » ne peut pas être utilisé :
    Argument invalide.
    ...
    


  • @RIKKO14 headphones is things u put over your ears to hear sound.

    arecord -l showed one device for capturing sound (a microphone) at card 0, device 0

    aplay -l showed two devices that can make sound.



  • @sdeweil sorry but i don’t anderstand…
    you say :

    arecord -l showed one device for capturing sound (a microphone) at card 0, device 0

    But I see with the arecord-l :

    pi@raspberrypi:~ $ arecord -l
    **** Liste des Périphériques Matériels CAPTURE ****
    carte 1: USB [WordForum USB], périphérique 0: USB Audio [USB Audio]
    

    so my microphone should be on card 1, device 0, no ?

    and you said :

    aplay -l showed two devices that can make sound.

    So :

    **** Liste des Périphériques Matériels PLAYBACK ****
    carte 0: b1 [bcm2835 HDMI 1], périphérique 0: bcm2835 HDMI 1 [bcm2835 HDMI 1]
    

    HDMI free in card 0, device 0 (i don’t use it)
    and my headphones in card 2, device 0,

    carte 2: Headphones [bcm2835 Headphones], périphérique 0: bcm2835 Headphones [bcm2835 Headphones]

    I would have mistakenly switched the 2 ?

    And why when i open the .asoundrc file after writing what’s here : https://developers.google.com/assistant/sdk/guides/library/python/embed/audio the file is different after writting the command speaker-test -t wavand arecord --format=S16_LE --duration=5 --rate=16000 --file-type=raw out.raw

    Do you know if i wrote in my my node_helper.js, my My MMM-GoogleAssistant.jsand my pi/assistant.py are good ?

    And finally, does the procedure described in Introduction to the Google Assistant Library (https://developers.google.com/assistant/sdk/guides/library/python) still work because I just read at the top of the page ( I hadn’t paid attention): “Warning: The Google Assistant Library for Python is deprecated as of June 28th, 2019. Use the Google Assistant Service instead.”, and return to the Introduction to "the Google Assistant Service page "(https://developers.google.com/assistant/sdk/guides/service/python) so should I rather follow the procedure described in the Google Assistant Service and then continue step 3 of this page: https://www.magicmirrorcentral.com/get-google-assistant-magic-mirror/ ?



  • @RIKKO14 sorry, got the mic card wrong

    you are mixing instructions.
    I don’t care what Google doc you read.

    MMM-GoogleAssistant doc is the only doc that matters.

    and NEVER change the module source code files. change config.js only.

    @Bugsounet will have to help on his module



  • So my mic card is card 0, device 0 ?
    and my 3.5 jacks speakers is card 2, device 0 ?
    is that correct ?

    The MMM-GoogleAssistant of @Bugsounet doen’t work, at the end of the page it’s write : “By terms of Google Assistant SDK, You are not allowed to use or provide this module for commercial purpose.”
    the only MMM-GoogleAssistant which works is the gauravsacc/MMM-GoogleAssistant, but i don’t anderstand what to do in the part :
    “Register your GA device
    Register your GA device using the register-tool available here and replace the magic-mirror-device-id in the assistant.py with your unique device id https://developers.google.com/assistant/sdk/reference/device-registration/device-tool”,

    I dont’ anderstand the open page : “Registration Tool Help” in the link.
    and finally, the link to Setup Google Assistant on Pi return to the same google page for Introduction to the Google Assistant Library and it’s wrote in red at the top of the page “Warning: The Google Assistant Library for Python is deprecated as of June 28th, 2019. Use the Google Assistant Service instead.”

    can you just confirm me my number of card and device for my mic and my headphones according to you ? Thank you



  • @RIKKO14 we are not selling mm, so not commercial use. you are adding a module to your personal system ( unless YOU intend to sell it)

    I don’t know about the older module. only that @Bugsounet has done a lot of work to get it going


  • Module Developer

    @RIKKO14 said in MMM-GoogleAssistant problem with .asoundrc:

    The MMM-GoogleAssistant of @Bugsounet doen’t work

    je ne savais pas que je fesais des module qui ne fonctionnait pas 😉
    Merci toutefois de me l’apprendre 🙂

    “By terms of Google Assistant SDK, You are not allowed to use or provide this module for commercial purpose.”

    cela veux simplement dire qu’il n’est pas permis d’utiliser ce module a des fin commerciale



  • @Bugsounet TOUTES MES PLATES EXCUSES !!! J’avais donc mal compris, vraiment désolé…
    I continue in English because it is required here (and that you will understand that I all pages and tutorials read with google translate …):
    But then why in the page of your MMM-GoogleAssistant there is only the link git@github.com: bugsounet / MMM-GoogleAssistant.git and not all the description to install MMM-GoogleAssistant ?


  • Module Developer

    It’s on wiki page …

    just read 😉

    It’s write on Readme page



  • Great, thank you !
    So can you confirm me the card and device for my mic and headphones ?


Log in to reply