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 -l
and 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:<2>,<0>"
}
}
pcm.speaker {
type plug
slave {
pcm "hw:<1>,<0>"
}
}
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:<2>,<0>"
}
}
pcm.speaker {
type plug
slave {
pcm "hw:<1>,<0>"
}
}
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:<1>,<0>
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:<2>,<0>
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:<1>,<0>
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:<2>,<0>"
}
}
pcm.speaker {
type plug
slave {
pcm "hw:<1>,<0>"
}
}
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'></img><br/>" + this.userQuery;
} else {
wrapper.innerHTML = "<img src='MMM-GoogleAssistant/assistant_active.png'></img>";
}
} else {
wrapper.innerHTML = "<img src='MMM-GoogleAssistant/assistant_inactive.png'></img>";
}
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.
...