rgraciano / echo-sonos

Amazon Echo integration with Sonos
Other
712 stars 234 forks source link

Default rooms #27

Open rgraciano opened 8 years ago

rgraciano commented 8 years ago

There's a general desire to be able to act on the system without always specifying which room to act on.

Eg, issue #16 - it would be nice for JoinGroup to be able to look up what room is currently the coordinator and default to that. It would not work in a scenario in which multiple groups are playing at the same time, but there's no way around that except to specify a room.

Functions like next, previous, and so on would also benefit from this feature.

kshartman commented 8 years ago

It could also use the default room when when the room slot comes in undefined (which it will if you don't say 'in') or when the room is garbled because alexa didn't hear you correctly.

kshartman commented 8 years ago

You can do something like this (specific to me)

function roomOrDefault(roomName) { var selectedRoom = 'shanesoffice'; if (roomName) { switch (roomName.toLowerCase()) { case 'bedroom': case 'kitchen': case 'livingroom': case 'sunroom': case 'patio': case 'shanesoffice': case 'kathysoffice': case 'mediaroom': selectedRoom = roomName; // known room break; // aliases case 'pool': selectedRoom = 'patio'; break; case 'media': case 'media room': case 'tvroom': case 'tv room': selectedRoom = 'mediaroom'; break; case 'sun room': selectedRoom = 'sunroom'; break; case 'bed room': selectedRoom = 'sunroom'; break; case 'den': selectedRoom = 'livingroom'; break; case 'shanes office': selectedRoom = 'shanesoffice'; break; case 'kathys office': selectedRoom = 'kathysoffice'; break; } } console.log('debug: ' + JSON.stringify(roomName) + ' = ' + selectedRoom); return selectedRoom; }

Then replace intent.slots.Room.value with roomOrDefault(intent.slots.Room.value) everywhere

jplourde5 commented 8 years ago

I just finished working on musicSearch for node-sonos-http-api and have been testing it with echo-sonos. It supports Apple Music, Spotify, Deezer, and the local music library. What I'm finding while testing is that the amount of utterances is growing rapidly to the point that it is breaking the model. As a result, I've been thinking about ways to greatly trim down the number of utterances.

I too think that there should be a means for setting a default room as well as a default service and include utterances for changing them. I would create a slot for the different service types including apple, spotify, deezer, library, siriusxm, pandora, and presets. I'm wrestling with where to store the defaults so that they can easily changed by an utterance. I'm thinking DynamoDB or S3.

I'm also talking to the Echo product manager about adding an Echo ID to the json message that is passed to Lambda so that the defaults could be set differently for different Echos/Rooms. (My company spends a TON with AWS so I have access to all of the PM's :)

Should I pursue making these changes?

bradanlane commented 8 years ago

I may be in the minority but I don't see myself using defaults on a per-room basis. I tend to pick music for the room (or rooms) I'm in. The room isn't the pivot point for me - it's the music and by correlation, the music service.

Further, I don't subscribe to multiple services and when I talk with some other big music listeners, they've invested heavily in one service or another and do not tend to use multiple services as normal practice. Some use Pandora One. Others are big users of Spotify. Still others have adopted Apple Music. In each case, they have their "go to" service. The exception is that a few of these contacts have big legacy libraries on a computer.

I guess all of this data points to the desire for setting a default service. However, default rooms is less valuble for the installations I work with.

jratliff681 commented 8 years ago

That is awesome you can get to the product managers! I would love to see an echo ID sent so your skills can know which device the request came from. If only that could also be used with the built in smart home skills too so you could say "turn on lights" and depending on which echo you were talking to would turn on different lights based on the room it's in. Would also be useful for "Tell Sonos to play" and control different speakers depending on the room. I have skills named "TV pause", "TV play", etc and would be able to set those up for multiple TV's/rooms with an echo ID to work with.

The only other thing I'd love is if they'd let you assign a skill as the default interface to open automatically when you say "Alexa". If the original interface is not default then you could do something like "Alexa, ask Amazon ..." I built a skill for work that interprets all aspects of our schedule and put an echo in our lounge. But people always screw up asking it stuff directly "Alexa, who works tomorrow" vs saying "Alexa, ask the schedule who works tomorrow".

As far as default room, for those of you who like to play around with it, I copied the Sonos core skill into 5 duplicate skills. The skills all have invocation names the same as my speakers. So I have skills named "patio", "living room", "garage", etc. Each skill is coded via their options.js to send commands to that speaker only. Then I can say "Alexa, play pandora in the living room", "Alexa, tell the patio to pause", "Alexa, volume 40 in the garage", "Alexa, tell the living room to join the kitchen", etc... I think it just makes it more convenient to give commands.

jplourde5 commented 8 years ago

Bradalane, I agree on the services except for maybe many having two, Pandora and then another main streaming service. I also agree that you tend to use one more than any. I actually want three, SiriusXM, Pandora, and Apple Music. And then there are the presets.

As far as rooms go, the rub comes when you have multiple Echos and multiple Sonos and really would like to by default, associate a room to a specific Echo (which I can't do yet). Short of that, I still tend to play music in one room more than another and don't constantly wander around the house playing different music.

I'm thinking it should be more like a multi-room stereo tuner where you change service (FM, XM, CD, TV, ...) and can change the room setting too (eventually room by room). To do this there should be utterances:

Change service to X Change room to X

Which would change the defaults. You could then simply say:

Alexa, Ask Sonos to Play Coldplay

jratliff681, I've actually asked the PM for 2 things, the first being to pass the Echo Sonos ID, and the second to have support for multiple trigger words and be able to link the alternates to a skill. This way we could say:

Alexa, bla, bla

AND

Sonos, play Coldplay

What I'm really driving towards is being able to have the Echo NATIVE simple music experience with Sonos.

I'm thinking that it may be better to just fork this project to something like Echo-Sonos-Plus and implement this new behavior. That way I don't disrupt the current behavior.

Thoughts?

bradanlane commented 8 years ago

Forking initially does make sense. Then, once it's been "in the wild" for a few months, it can be decided if merging is desirable.

I have only one Echo so I didn't consider that option. I can see your point. I do have nine "zones" for my Sonos.

ryanmaule commented 8 years ago

Setting a default room would be useful for me as well and reduce utterance complexity. It's currently failing the wife test. Setting the default to the last used room would also make the flow easier. A command like "Alexa, tell Sonos I'm in the kitchen" as @jplourde5 suggests would be nice.

jplourde5 commented 8 years ago

I hear you on the wife test. My problem also, and one of the reasons I want more simplicity. I'm also running out of breath with some of these utterances ;)

I'll go the forked route and shoot for a default behavior that mimics what is here now. The main problem I have now is with the Play "something" preset command because it collides with where I'm headed. But I could make Presets the default service and effectively have the current behavior as a default, sans all of the other music service capabilities that don't exist in standard branch now anyway.

rgraciano commented 8 years ago

@jplourde5 - I'd vote for forging ahead in the same project, since merging the forks over time becomes problematic and most people seem to want some variant of all of these features anyway.

I would suggest:

1) Default room and default service in options. Default service is "preset" for backwards compatibility. "Play" command operates on default room and service.

2) If the user wants a stateful service, then "switch service" and "switch room" (or similar) work with either S3 or Dynamo. Could turn these off in options.js by default, so users who don't care don't have to go through the extra steps of setting the storage up.

Setting up lots of invocation names would be a great feature if Echo could support it easily. Might be something to document in "Optional Setup" someplace for the brave.

jplourde5 commented 8 years ago

Will do. I'd prefer not to fork it if we can avoid it.

jplourde5 commented 8 years ago

I finished the work and will begin testing tonight. I'll provide links to my branches for others to test once I finish my initial testing, hopefully before the weekend. The changes will add support for Apple Music, Spotify, Deezer, Sirius XM, and the local music library. Default behavior will be as echo-sonos works now. Advanced mode will allow users to change services and rooms, allowing for easier utterances.

jplourde5 commented 8 years ago

Okay, I've done some preliminary testing and things seem to be working. You can get the releases at:

node-sones-http-api Use the below release instead of what is is specified in the documentation https://github.com/jplourde5/node-sonos-http-api/releases

echo-sonos https://github.com/jplourde5/echo-sonos/releases

I'm sure that I'll be fixing, tuning, and updating the releases after further testing. Let me know if you run into any problems. Good luck and enjoy!

bradanlane commented 8 years ago

OK, I'm "up and running" with the new code. things seems to be good thus with one exception.

I'm performing the URL tests ...

In my node "server" command window, I am seeing "undefined" output to the command window after each command is issued.

eg1: I did the "zones" URL and I get back the xml in the browser and the command window for the server spits out "undefined". eg2: I issue the URL to start an applemusic radio station on my office sonos and the music starts, the xml "success" is displayed in the browser, and the command window for the server spits out "undefined".

I'm not sure where the message is coming from.

bradanlane commented 8 years ago

FYI @jplourde5 - the echo-sonos 'release' for v2.0.beta does not contain the full set of files. I was using git to fetch the files from master and it was missing some things like the slots files for XM. However, the master branch appears to be ahead of the beta branch. So, I then followed your instructions and grabbed the tar.gz file. It too was missing some files.

I've pulled the various files from the different branches and [hobefully] have a simialr source tree to what you are testing.

FYI2: Similar mismatch seems to have occurred with echo/intents.json which is missing 'PlayIntents' so the lambda test fails. Changing the test to use 'PlayPresetIntent' succeeds.

BTW: Nice work! I hope some of this testing will be helpful.

jplourde5 commented 8 years ago

Did you get it working? You may just want to go to my branch directories and pull down the files. Maybe there are some links back to the main branches.

I'll see about the undefined. It may just be a leftover console.log call.

BYW, I may have an issue with SuriusXM that I'm looking at now.

Keep me posted

jplourde5 commented 8 years ago

Found and fixed the SiriusXM issue. Update the siriusXM.js file with my latest copy in nod-sonos-http-api if you are using SiriusXM.

bradanlane commented 8 years ago

there may be an issue with enabling "advanced options" ...

steps:

  1. defaultRoom was set to 'living room' in options.js
  2. advancedMode was set to true in options.js
  3. started test "tell sonos pause office"

Alexa Skill reported: "the remote endpoint could not be called, or the response it returned was invalid" Lambda Service logged: (lots of stuff ...)

I addes some additional logging and have the following ...

2016-07-23T18:08:26.132Z    729bc63b-5100-11e6-aa4b-79cde05874a4    Create echo-sonos table - JSON:
{
    "TableName": "echo-sonos",
    "KeySchema": [
        {
            "AttributeName": "echoid",
            "KeyType": "HASH"
        }
    ],
    "AttributeDefinitions": [
        {
            "AttributeName": "echoid",
            "AttributeType": "S"
        }
    ],
    "ProvisionedThroughput": {
        "ReadCapacityUnits": 1,
        "WriteCapacityUnits": 1
    }
}
2016-07-23T18:08:26.593Z    729bc63b-5100-11e6-aa4b-79cde05874a4    Adding defaults - JSON:
{
    "TableName": "echo-sonos",
    "Item": {
        "echoid": "DefaultEcho",
        "currentRoom": "living room",
        "currentMusicService": "apple"
    }
}
2016-07-23T18:08:26.754Z    729bc63b-5100-11e6-aa4b-79cde05874a4    Unable to add default. Error JSON:
{
    "message": "Requested resource not found",
    "code": "ResourceNotFoundException",
    "time": "2016-07-23T18:08:26.753Z",
    "requestId": "2ITSA6SUHV1MQT5HD30O2CAVNRVV4KQNSO5AEMVJF66Q9ASUAAJG",
    "statusCode": 400,
    "retryable": false,
    "retryDelay": 0
}

I did add the AmazonDynamoDBFullAccess policy to my lambda_basic_execution role.

Suggestions?

bradanlane commented 8 years ago

@jplourde5 , when you say "branch directories", I believe that is what I attempted. However, there are some updates in master which are not in beta and the converse is true. If there is a single branch I can set to and get all of the latest work, I can go that route. just let me know.

jplourde5 commented 8 years ago

For the missing intents and slot files, did you happen to use the links in the read.me? If so, that is the problem there. They all link back to the main branch which is what they need to point to once I submit a pull request. I'll change them to point to my branch in the mean time.

If the "undefined" that your seeing is showing up in a repeated fashion in some sort of frequency by itself, I believe that is something in the main code of the beta branch. You have to stick with the beta branch because it is built using Promises and the main branch is not yet until jishi replaces the main with the beta. I've been using the beta code for a while and haven't really had any problems with it. The "undefined" message is puzzling, but it doesn't seem to hurt anything. Let me know if you figure out what is causing it.

jplourde5 commented 8 years ago

Okay, I fixed the links to the README so that they point to my file. You are going to have a lot of problems if you used something different. Redo the "Create The Alex Skill..." section, steps 4 and 5 if you attempted the earlier links. This may clear up your problems.

bradanlane commented 8 years ago

Thanks. I was not using the links. I was using the instructions to work with the files in the fetched source.

Anyway, Here is what I have [re] done ...

When I test, using a local URL in a web browser, the request executes correctly and the server console spits out undefined. To me, this suggests a variable is undefined (but I'm totally guessing). Since I've never debugged a nodeJS app, I'm not sure where to look.

The undefined string is output to the console from the nodeJS code near the end of completing each URL command. It does not occur between commands.

As you said, since it seems to be working at this step, I'm moving on and I'll circle back later.

Update:

After building and configuring the lamda function, I attempt to run the script from play_intent_testreq.json. It fails because there is no longer a PlayIntent entry in the Skill. The error is {"errorMessage":"Unsupported intent = PlayIntent"}

I changed PlayIntent to 'PlayPresetIntent` and it works. Not sure if ou want to change the test or restore the intent.

jplourde5 commented 8 years ago

Do you see musicSearch.js in your lib/actions directory?

Also, have you changed to the node-sones-http-api directory and executed npm install --production? This loads all of the dependencies into the node_modules directory. If you don't see a node_modules directory in the api directory where you should also see the lib directory, then you haven't installed the dependencies. Once installed, you should see a number of directories in node_modules, including a fuse.js directory. If so, then you should have all of the needed dependencies in place.

jplourde5 commented 8 years ago

...cont. Also, does http://localhost:5005/zones in your browser spit out a bunch of zone information?

jplourde5 commented 8 years ago

...cont. One other point, you need to follow all of the instructions very carefully, line by line. Missing a step is usually what causes a problem. Granted, the fact that we are using my interim builds does create some new ways for things to go wrong ;) If you want to give me your number, I'll call and try to help you through it.

bradanlane commented 8 years ago

sorry if I have sounded 'dumb'. trust me I'm not :-) ... well, not most of the time

I followed the steps - including verification at each step.

Yes, lib/actions/musicSearch.js is present. Yes, npm install --production was executed. Yes, the lib and node_modules are present. Yes, http://localhost:5005/zones works as does http://ip_redirector:5005/zones Yes, the lamdba service test works (after changing PlayIntent to PlayPresetIntent) Yes, the Alexa Skill Service Simulator works No, the Echo does not activate the Sonos Skill (see below).

At this point, I'm ignoring the undefined error messages.

I have hit an odd problem which does not appear to be echo-sonos.

The Skill works from the Service Simulator by typing in a command such as ask Sonos what is playing in the Office. However, if I utter the command to my Echo Alexa, ask Sonos what is playing in the Office It does not recognize it should invoke the Sonos Skill and it attempts to find movies in my area. I did verify the skill appears in the Alexa App on my iPhone as Enabled. I've seen this before where Amazon takes a while to start redirecting to a newly enables Skill but usually it is 30 minutes or less. I enabled the Skill a couple hours ago.

jplourde5 commented 8 years ago

...cont again. Reading further back regarding the table problem, I deleted my echo-sonos table and I'm having the same problem recreating the table. Looking at it now.

bradanlane commented 8 years ago

Update:

It seems some utterances are snatched or unrecognized by Amazon servers rather than handed to the Skill.

I can turn volume up/down. I can skip tracks. I can mute/unmute.

I cannot start an artist, track, station, or radio. I cannot ask for what is playing.

If I ask Alexa, tell Sonos to play SONG NAME radio in the ROOM it replies that I need to enable iHeartRadio. I think this has to do with getting Sonos to understand its music services. In the prior beta, the music service was stored in options.js file. It gets similarly baffled by Alexa, ask Sonos what is playing in the ROOM. In both of these examples, when I type the text into the Service Simulator (text tab of the Skill), the commands work.

jplourde5 commented 8 years ago

Do you see the following 2 lines in your utterance file? If not, redo steps 4 & 5 in the Create Alexa section using the links which will get you the right files now.

SiriusXMStationIntent play sirius XM {Station} in the {Room} SiriusXMStationIntent play sirius XM {Station}

Also, I found a problem with creating the dynamoDB table. Apparently there is a delay before you can access a newly created table. This creates some problems downstream. I'm working on a fix now.

BTW, thank you very much for working through this.

bradanlane commented 8 years ago

thanks for digging into the DB issue.

Yes I picked up the SiriusXM changes.

In my environment, the only music service I have to test with is Apple. It worked back on teh 7th of July, before this latest big update.

jplourde5 commented 8 years ago

Okay, found a fix. Have to make a DynamoDB waitFor call after creating the table before I can insert a row. I uploaded the fixed index.js file. Look for a function called addCurrent, which I changed from addDefault, and you know that you have the right file. Without this fix, reading the current settings probably will not work and it may lead to odd behavior. BTW, you can go to DynamoDB in the AWS dashboard and see if the file is there and has an item in it. Initially the values will be equal to the defaults specified in the options file. After that, it will get updated any time that you tell it to change or use a different room in a normal utterance. Let me know if this clears things up.

bradanlane commented 8 years ago

Thanks. I will get back to my Dev setup in the morning and will pick up the change.

Hopefully it will let apple work for me.

jplourde5 commented 8 years ago

Okay. Found a couple more things. I'll let you know what to adjust when I finish.

jplourde5 commented 8 years ago

Okay, I banged it around quite a bit. Update your lambda/index.js file with my latest version. You should see the ChangeRoomIntent look like below. If so, you have the latest one and it should work fine.

ChangeRoomIntent: function (intent, session, response) {
    console.log("ChangeRoomIntent received");
    if (!options.advancedMode) {
        response.tell("This command does not work unless advanced mode is turned on");

...

bradanlane commented 8 years ago

Will do.

I noticed there is an index.js in the root of the echo-Sonos project.

I'm assuming I ignore that one and zip up the files from the lambda directory as usual (with my edited version of the options file).

jplourde5 commented 8 years ago

I just deleted the one in root. The one in the lambda/src directory is correct. You should be good to go once you get it updated.

jplourde5 commented 8 years ago

Added back the utterances for the MusicRadioIntent

jplourde5 commented 8 years ago

How's it going today?

bradanlane commented 8 years ago

mixed results but it looks like the only way to get things right is to always start from the very beginning and nuking everything ...

  1. I had a problem where require-fu/index.js was loading everything from the actions directory including the sirius-channels.json. it didnt like that. I moved the JSON file to a peer directory and changed actions/siriusXM.js to look in the new location.
  2. I can set the default room and service. nice work. When I use the Skill Service Simulator and tell it to play a specific song, the nodeJS server throws an unhandled rejection error: player.coordinator.clearQueue is not a function.

Using the external URL http://ip_redirector:5005/office/applemusic/radio/radio:artist%20name works.

As I said, I'm just going to start all over again.

To make sure I have the correct code, which branch do I need to fetch for /jplourde5/node-sonos-http-api and for jplourde5/echo-sonos ?

jplourde5 commented 8 years ago

I'll do a quick install of my test distribution and see if I have similar problems. The sirius-channels.json file should not cause a problem. Only the .js files are "supposed" to get loaded. Thanks for going through all of this trouble. It is tedious and not so intuitive. But it works great once it is working.

bradanlane commented 8 years ago

no problem. I read the fu code and it does not distinguish file extensions. The documentation even worns that no extra files should be in the director.

I created a data folder that is a peer to the actions folder and moved the JSON file there. then just updated the code to look for it in the new location.

jplourde5 commented 8 years ago

Just reinstalled and works fine. Quick instructions:

  1. Click this link: https://github.com/jplourde5/node-sonos-http-api/archive/v1.6-beta.1.zip
  2. Copy or move the folder from your downloads to the folder where you are putting your NodeApps. It can really be anywhere.
  3. Change to node-sonos-http-api-1.6. directory on a command line and type npm install --production. You should see a pause and then a list of modules being installed.
  4. Type npm start
  5. Go to your browser and type http://localhost:5005/zones and you should see all of your zone information
  6. Type http://localhost:5005/ROOM/musicsearch/apple/song/boston and Boston should start playing. Substitute a valid room value for ROOM capitalized EXACTLY like you named them in Sonos.

This should work if everything is setup correctly. BTW, Are you using Windows or Mac ?

bradanlane commented 8 years ago

let me give the instructions a try. I'm curious how the ZIP compares to the repositories since I have been just using git against the repositories.

To be sure, you want to be grab v1.6-beta.1.zip rather than the code tagged v1.6-beta.2 ?

Also, to eliminate all possible mismatches, which code set for echo-sonos do you want me to test ?

I deployed this on a light weight linux server (no gui). Once it is up and running, I'll turn it into an appliance and bury it in cabinet with similar 24/7 services.

jplourde5 commented 8 years ago

Are you going to use a Raspberry for that?

bradanlane commented 8 years ago

more or less. I have a bunch of RPi 'knockoffs' that were $15 each. Once I have a project working, I port it over and turn it into a little black box.

bradanlane commented 8 years ago

utterances are still not fully working. Same as before. Tested with apple music.

working:

not working:

Everything is working via URL and via the Skill Service Simulator. This suggests the issue is with processing utterances.

jplourde5 commented 8 years ago

What do you see when you issue these two commands in your browser?

  1. http://localhost:5005/zones and you should see all of your zone information
  2. http://localhost:5005/ROOM/musicsearch/apple/song/boston and Boston should start playing. Substitute a valid room value for ROOM capitalized EXACTLY like you named them in Sonos.
bradanlane commented 8 years ago

the URLs all work as expected the Service Simulator works as expected actual voice utterances are only partially working

with Apple music set as the default service:

jplourde5 commented 8 years ago

Okay, great. node-sonos-http-api should be good now. Let's pivot to echo-sonos. Try downloading this zip and install everything from here per the instructions.

https://github.com/jplourde5/echo-sonos/archive/beta1.3.zip

jplourde5 commented 8 years ago

I've been want to play with an RPi and thinking about porting this to one just for S&Gs. Thinking about making it auto-upgrading and creating some install scripts to set all of this up in a much easier fashion.