muzak icon indicating copy to clipboard operation
muzak copied to clipboard

creating lambda function

Open glacket opened this issue 8 years ago • 43 comments

I guess im not understanding how to create the lambda function. What do i code do i use for the body of the function. Can you please give an example. Also the readme alludes to install squeezenode within muzak folder on a linux box. Can this be done on a pi? does it always have to be running. does muzak need to be running as a bridge on the network between echo and squeezeserver?

glacket avatar Nov 07 '16 19:11 glacket

Hey glacket, Hopefully I can save you some time. There is a bit of a learning curve to dealing with AWS Lambda and Alexa skills.

The body of the function is the text taken directly from muzak.js. I added some functionality that has not yet been incorporated from the pull request - look at my fork for the update.

Muzak is run on AWS when the "Alexa Open Muzak" command is issued; nothing needs to be run locally to use muzak.

The config.js file gets zipped and uploaded to AWS. This points back to your password protected Squeezebox Server through a DNS entry you've created with FreeDNS.afraid.org (or any dynamic dns host), over port 9000 that you've opened on your router.

Some of my notes:

For creating the Alexa skill: https://developer.amazon.com/edw/home.html#/ Use all files in muzak's dir \speechAssets to configure the Interaction Model of the skill you're creating. Then use the skill ID in the config.js file.
The Configuration tab's "AWS Lambda ARN (North America)" format:
arn:aws:lambda:us-east-1:xxxxxxxxxxxx:function:squeezebox.

For creating the Function: https://console.aws.amazon.com/lambda/home?region=us-east-1#/functions?display=lis In the configuration tab: make sure to pick Runtime: Node.js 4.3 Handler: "muzak.handler" Role: "service-role/lambda_basic_execution".

NPM installer for Windows: https://nodejs.org/download/release/latest/ NPM Command from a cmd shell: (easiest to specify the full path to NPM, use quotes to handle the space in Program Files)
"C:\Program Files\node-v7.0.0-win-x64\npm" install

The AWS parts must be done in the order described in the How To Use section!

MikeDeSantis avatar Nov 07 '16 19:11 MikeDeSantis

Hi Mike, I really appreciate your reply. For the npm installer, i have npm installed in program files and i copied muzak to c:\temp\muzak and squeezenode to c:\temp\muzak\node_modules/squeezenode-lordpengwin. If i am going to run "c:\temp\muzak\node_modules/squeezenode-lordpengwin\npm" install wouldnt i need to create a windows environment variable or install npm into c:\temp\muzak\node_modules/squeezenode-lordpengwin? The instructions are requesting that i download the prerquisites for squeezenode using npm install, correct, not prerequsites for npm itself. I tried that and it needs git.

glacket avatar Nov 07 '16 21:11 glacket

Glacket, No environment variable necessary. Because you're running the command from the target directory, specifying a full path to NPM you are all set. Correct - you need dependencies of squeezenode, not npm via git.

When you open the cmd shell, cd to (in your case): c:\temp\muzak\node_modules\squeezenode-lordpengwin

Then issue command: (assuming you got the 64 bit version and installed it appropriately) "C:\Program Files\node-v7.0.0-win-x64\npm" install

image

-Mike

MikeDeSantis avatar Nov 07 '16 22:11 MikeDeSantis

Thanks for the description. I understand that now. I noticed you specified an interactive model configuration but I wanted to know if the smarthome skill type can be used so I don't have to say "alexa tell muzak".........

glacket avatar Nov 08 '16 05:11 glacket

i guess the default smarthome api would not work because it doesn't have the interaction utterances for squeezebox, so i am guessing i have to use the custom interaction model. At that point is there still a way around the "alexa ask muzak" utterance?

glacket avatar Nov 08 '16 05:11 glacket

Correct, OOTB api doesn't have the utterances necessary. You have to invoke muzak somehow and 'open' I thought was your only way in. 'tell' works too? I'm new to this as well.

For 'open' you start an interactive mode session w/o having to invoke Alexa between each thing you say: -Alex open muzak <Muzak online> -Play living room <Playing living room squeezebox> -Volume 75 <Player living room set to volume 75>

What I really want is simple to conceive but not to implement... "Alexa play Zac Brown on the living room squeezebox" or "Alexa play Daft Punk Get Lucky on the living room squeezebox"

MikeDeSantis avatar Nov 08 '16 14:11 MikeDeSantis

I didnt realize there were multiple invocations either. I understood the interaction model, but i am having trouble with the ARN. My skill id is this amzn1.ask.skill.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. I took the character string xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, removed the hyphens and added to North America AWS format so it looks like arn:aws:lambda:us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:function:squeezebox, but i am getting an Invalid ARN error. I also tried it with the version added to the end and still no luck. Is "function" a variable i need to specify as well?

glacket avatar Nov 08 '16 20:11 glacket

heres the example from amazon. arn:aws:lambda:region:account-id:function:function-name. It looks like the first function is static and the second "function" is the variable.

glacket avatar Nov 08 '16 20:11 glacket

My Lambda ARN is: arn:aws:lambda:us-east-1:xxxxxxxxxxxx:function:squeezebox 12 digits between us-east-1: ... :function which is the function's ID.

image

My lambda function is called "squeezebox" image

-Mike

MikeDeSantis avatar Nov 08 '16 20:11 MikeDeSantis

I created the function and added the arn number. I am trying to upload the zip file to lambda. According to the read me the zip name can be muzak or lambda and it needs to contain the node_modules directory muzak.js config.js. Is this what did as well?

glacket avatar Nov 09 '16 03:11 glacket

I configured config.js and uploaded node_modules directory muzak.js config.js as muzak.zip. The code size now resembles yours, about 973kb. I am now trying to test the skill and i get the following response from lambda. The remote endpoint could not be called, or the response it returned was invalid. Should the test work if i did everything correctly?

glacket avatar Nov 09 '16 15:11 glacket

zip needs to contain the node_modules directory muzak.js config.js

Yes, this is exactly what I did.

The remote endpoint could not be called, or the response it returned was invalid.

I got this a few times when I didn't issue a valid utterance to test. I think I also got this before my squeezebox server's port was forwarded. Make sure you can ping your SBS from the Internet with a service like www.canyouseeme.org. Also, the service simulator test should just be the function invocation without the 'Alexa' or muzak invocations on the front; IE just "play living room".

Expected Lambda Response: { "version": "1.0", "response": { "outputSpeech": { "type": "PlainText", "text": "Playing Upper Deck squeezebox" }, "card": { "content": "SessionSpeechlet - Playing Living Room squeezebox", "title": "SessionSpeechlet - Start Player", "type": "Simple" }, "reprompt": { "outputSpeech": { "type": "PlainText" } }, "shouldEndSession": true }, "sessionAttributes": { "player": "living room" } }

MikeDeSantis avatar Nov 09 '16 17:11 MikeDeSantis

I can ping my server and connect to it remotely just fine. it looks like the problem is on the Lambda side. I must have messed something up in the script. Here is the log error from lambda not being able to load the module. I am going to try recreating the function again.

Unable to import module 'muzak': Error at Function.Module._resolveFilename (module.js:325:15) at Function.Module._load (module.js:276:25) at Module.require (module.js:353:17) at require (internal/module.js:12:17) at Object. (/var/task/muzak.js:8:21) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Module.require (module.js:353:17)

glacket avatar Nov 09 '16 20:11 glacket

Ok, I am stumped. I cannot get the muzak module to load in Lambda when trigged via aws. Here is a quick rundown of the basic process I did.

Unzipped muzak-master to c:\temp\muzak Unzipped squeezenode zip to c:\temp\muzak\node_modules/squeezenode-lordpengwin Initialized npm install from c:\temp\muzak\node_modules/squeezenode-lordpengwin directory Npm install downloaded squeezenode dependencies to c:\temp\muzak\node_modules/squeezenode-lordpengwin\node_modules Modified config.js with the string from the APP ID amzn1.ask.skill.(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)--------> amzn1.echo-sdk-ams.app. (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) Modified all connection info in config.js and saved file, never touched muzak.js Using 7-zip, zipped up muzak.js, config.js and node_modules folder which has squeezenode and dependencies Created function with “Squeezebox” as the name Alexa skill kit as the trigger Runtime node.js 4.3 Handler “muzak.handler” Exisiting role “lambda_basic_execution” Uploaded muzak.zip for the code The function has a notation stating “This function contains external libraries”. I am guessing the external libraries are the node_modules\squeezenode-lordpengwin folders from the zip. I switch to AWS and test using the utterance “play Kitchen” and I receive “The remote endpoint could not be called, or the response it returned was invalid.”

Here is what I get from lambda streaming log

Unable to import module 'muzak': Error at Function.Module._resolveFilename (module.js:325:15) at Function.Module._load (module.js:276:25) at Module.require (module.js:353:17) at require (internal/module.js:12:17) at Object. (/var/task/muzak.js:8:21) at Module._compile (module.js:409:26) at Object.Module._extensions..js (module.js:416:10) at Module.load (module.js:343:32) at Function.Module._load (module.js:300:12) at Module.require (module.js:353:17)

glacket avatar Nov 10 '16 18:11 glacket

Have you got the server address in config.js set to the FreeDNS (or similar) address?

When I was having the same problem, it turned out that I'd made a silly mistake and entered my internal IP address as opposed to external.

tmn103 avatar Nov 10 '16 18:11 tmn103

Hi tmn103, yes i am using dyndns as my dynamic name resolution host. in the config.js file i have "http://xxx.dyndns.org". prior to that i confirmed that the address was reachable from the internet

glacket avatar Nov 10 '16 19:11 glacket

I am sure it is something stupid that i forgot to do. i've recreated the function at least 10 times using the original mast file and also using Mikes branch and no difference.

glacket avatar Nov 10 '16 20:11 glacket

I have noticed that when i check the code for the squeezebox function, i only see the muzak.js code, not the config.js code. Am i suppose to see both. Should i upload config.js, music.js and Node_modules separately?

glacket avatar Nov 10 '16 20:11 glacket

Im not sure if custom slots has anything to do with it. My custom slot and values are below

Type Values
PLAYERS Office | Kitchen | Dining Room | living room |

glacket avatar Nov 10 '16 20:11 glacket

I tested custom slots with no spaces, got the same error

glacket avatar Nov 10 '16 21:11 glacket

The only issue I ran into with custom slots is that my players can not have an ampersand '&' in them.

Everything looks good in your rundown of actions taken. I don't see anything that you missed.

I was getting the same error until I figured out that the handler had to be muzak.handler, which is why I put it in my notes. I'm sure there are a few different issues that would generate that response. You did keep the .js file the same name, "muzak.js" correct?

I too only have muzak.js code visible in my Lambda function - you do not need to upload an individual config.js instance as it's handled through the zip file. You may want to retry the zipping using the following command instead of 7-zip. Not that there's anything wrong with doing it that way, but it's one of the only differences that I can see between what I did and what you did. Low probability of helping but something to try I suppose.

cd C:\muzak zip -r muzak.zip muzak.js config.js node_modules

DON'T GIVE UP! You are definitely close. It's such a thrill when you break through and have the voice integration with Squeezebox Server!

-Mike

MikeDeSantis avatar Nov 11 '16 17:11 MikeDeSantis

Is that zip command on Linux. it is not built into windows to my knowledge. in your squeezenode-lordpengwin directory do you have another node_modules directory? I do and it appears that's where the dependencies for squeezenode are stored. is that the correct file structure?

glacket avatar Nov 12 '16 02:11 glacket

I kept muzak.js the same. it looks like it finds it but stops at trying to compile it. I'm wondering if it may have something to do with npm permissions. not sure how to check that. I just made sure "everyone" has access to all files and unchecked readonly on the node_modules folder. I also tried send to "compressed zip" file in windows and same error. I also tried setting the wrong handler on purpose and got a similar error but it did progress as far. it never got to the compile stage.

glacket avatar Nov 12 '16 03:11 glacket

glacket - you've put in the time and I'm sure you are very close to a solution... sometimes the last 5% is the hardest, right? On Monday I'll try to post my .zip file here somehow (from my fork) with the config.js missing. Add your network specific version of config.js and uploading to create your lambda function should work.

MikeDeSantis avatar Nov 12 '16 04:11 MikeDeSantis

I appreciate all your help Mike. thanks.

glacket avatar Nov 12 '16 06:11 glacket

Here is a mostly complete zip file, just missing config.js. Customize your copy of config.js per the main page's instructions and add it to this zip, then upload to create your Lambda function.

This code is of my fork, 11/12/16 before the pull request (hopefully) incorporates it into the trunk.

muzak.zip

-Mike

MikeDeSantis avatar Nov 13 '16 02:11 MikeDeSantis

It worked! Thanks for uploading you configuration. for some reason yours worked after I commented out the application id check line. not sure why though. I don't know what id muzak.js is referencing. I thought it was my config.js but I have that set correctly. did you mention that you had added additional utterances to your branch?

glacket avatar Nov 13 '16 04:11 glacket

Awesome! Yes, there are a lot of utterance combinations that I added. Are they not available in the fork code? Here they are at any rate. utterences.txt

MikeDeSantis avatar Nov 13 '16 04:11 MikeDeSantis

that's my fault. i forgot i could just look at the utterances, however when i add them it gives the following error. I'm guessing its not specified in the muzak.js, but I'm using the one in the zip file you sent.

There was a problem with your request: The intent 'RandomizePlayer' was not found in the domain definition. Occurred in sample 'RandomizePlayer randomize' on line 57.

glacket avatar Nov 13 '16 04:11 glacket

Sorry, should have included this file as well. Update your intents.json. (Can't upload a json for some reason, dl and rename intents.json.txt to just intents.json) intents.json.txt

MikeDeSantis avatar Nov 13 '16 04:11 MikeDeSantis