Can't see sonos devices on Spotify connect - python

I am trying to connect my Spotify to my sonos. I am using the Tekore library to consume the Spotify API. When I try to list all devices on Spotify Connect, i.e. spotify.playback_devices(), I get only some of the available devices. Especially, the Sonos devices are not listed. Does anybody know why?

The documentation for the Spotify Connect Web API is pretty clear about this type of scenario:
Devices not Appearing on Device List
Connect Web API relies on local network connections to discover and interact with some devices.
For example, when:
A new device is added to the network
A device is in “sleep” mode
A device on the local network is currently tied to another user account, or
Other reasons specific to the device
As a result, some devices that appear in the Connect picker within the
Spotify application may not always be visible or available on the
Connect Web API
Endpoints.
Translation: if it doesn't appear in the API, there's likely a reason for that. You might be able to get further guidance from the development team if you tweet at them #SpotifyPlatform.

Related

Refreshing Authentication token for Google Calendar API with Python on Raspberry Pi

We are prototyping on a Raspberry Pi using the Google Calendar API.
Each user of this service will connect his or her own calendar to the Raspberry Pi and use the calendar information.
The Raspberry Pi we are using does not have a keyboard or display connected to it.
We are planning to connect a smartphone to the Raspberry Pi and have it set up a calendar, but we are using SSH to temporarily complete the authentication process.
We were able to retrieve the calendar information by following the steps below.
https://developers.google.com/calendar/quickstart/python
But after about two weeks, an authentication error occurred.
It may depend on the expiration date of the refresh token.
Authentication once every two weeks is very annoying to customers.
Can we get around this?
We found out about Delegating domain-wide authority.
https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority
Does this solve our problem?
Can this be used to display the Calendar for domain-independent email addresses?
For example, if we delegate to admin#example.com can we get the Calendar information associated with example#gmail.com?
We have already been struggling with this for months.
Please give us any advice you can.
Add: Our code is as shown in the sample, but we will describe it here.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'/home/pi/credentials.json', SCOPES)
// --- Try Kelo's advice ------------------------
flow.params['access_type'] = 'offline'
flow.params['include_granted_scopes'] = 'true'
// --- Try Kelo's advice ------------------------
creds = flow.run_console()
# Save the credentials for the next run
with open('/home/pi/token.pickle', 'wb') as token:
pickle.dump(creds, token)
If we use the wizard, we will see this warning.
Google API and direct access
Whenever you access user data, the user will need to authorize that, there is no way to go around this fact. You will always require a UI with the ability to "log in" or pass in a token. At the moment you are doing it via SSH, which is fine.
One part of your question is addressed towards whether you can get permanent access to the Google APIs from a device that does not have a interactive UI, and the answer is unfortunately, no, you cannot. Assuming your display is only able to give information, and not able to log-in to Google, then you'll need to do it via SSH or another method.
Service Accounts and non UI methods
Another question of yours is about whether Service accounts will work for your purposes. Unfortunately the answer is also no. Service accounts are for Workspace domains (people in the same organization) which I understand is not your case.
Offline Access
I understand that this is an IoT device and not a web server. However, there is a type of access called the "Offline" type. This is made available by Google to Web Server type applications.
Which is found when creating the credentials.
To be clear, I do not think this is a good solution for you. It would be possible, but not for people without a lot of tech knowledge, as each user would have to manage the Pi-as-server.
This is what a lot of people do with their IoT devices. Then they can "visit" the Pi as a web-page to give authorization and then it is granted the "Offline" type of access, and so, the authentication lasts longer. The Pi-as-server, usually only ever serves one web-page, to one person, usually on the local network. You can call it an IoT device or a web-server, in the end it serves the same function.
Managing IoT Devices
I am not an expert in this field, but I understand that there are services designed for IoT devices, such as:
https://cloud.google.com/iot-core/
Essentially to manage IoT devices you can set up something like this:
The key part being the bit in the middle that will manage the user's login information and access tokens. This will essentially be the "server" part that has "offline" access. Then this will query the Calendar API for the information and send it to the appropriate IoT device for that user.
This of course means keeping a database with the user info, access token, and which Raspberry Pi should be updated.
There are also PubSub services that act as a way to send messages between devices:
https://cloud.google.com/pubsub/
Please note: this does not mean that you have to manage the calendar information, all you need to do is to manage the logins, tokens and communication between the Calendar API and the Raspberry Pis.
Why can you do it on Android?
These types of applications work on android because you are logged in in a web-UI environment. Since you have already authorized your device, you can authorize apps through your device. Since you are not logged in with your Raspberry Pi, and you are in a CLI envionment you need to refresh the tokens.
Disclaimer
There may be a way to do what you want easily, but I don't know it. If you find one, please add your own answer, I would be happy to read about it as I also have Raspberry Pis and this would be very interesting to me!

Google Assistant API, controlling a light switch connected to Google Home

I have machine A that just cranks out .png files. It gets synced to machine B and I view it on machine B.
Sometimes machine A crashes for whatever reason and stops doing the scheduled jobs, which means then files on machine B will be old.
I want machine B to run a script to see if the file is older than 1 day, and if it is, then reset the power switch on machine A, so that it can be cold booted. The switch is connected to Google Home but understand I have to use the Assistant API.
I have installed the google-assistant-sdk[samples] package. Can someone show me some code on how to query and return all devices then flip the switch on and off on that device?
Unfortunately, many smart home companies are building products for consumers, not developers. Google's SDK is letting developers stream consumer voice requests to their servers and turning that into actions. Gosund, similarly, is only interested in API access for Amazon and Google. They're API is probably not documented for public use.
To answer your specific question, if you want to use the Google Assistant SDK, you would name your switch something like "Server A Switch" and record a short clip of you saying "Turn off Server A Switch" and "Turn on Server A Switch" and send those two google. The way google matches the requests with your particular account is through OAuth2 tokens, which google will give you in exchange for valid sign in credentials.
If Gosund works with Google Assistant, it has a standard OAuth2 server endpoint as well as a Google Assistant compliant API endpoint. I only recommend this if you want to have some fun reverse engineering it.
In your Google Assistant app, if you try adding the Gosund integration, the first screen popup is the url endpoint where you can exchange valid Gosund account credentials for a one-time code which you can then exchange for OAuth2 access and refresh tokens. With the access token you can theoretically control your switch. The commands you'll want to send are standardized by Google. However, you'll have to figure out where to send them. The best bet here is probably to email their developers.
Are you familiar with OAuth2? If not, I don't recommend doing any of the above.
Your other option is to prevent Server A from hardware crashes. This is what I recommend as the least amount of work. You should start with a server that never crashes, keep it that way and add stuff on top of it. If you only have two servers, they should be able to maintain many months of uptime. Run your scheduled jobs using cron or systemctl and have a watchdog that restarts the job when it detects an error. If your job is crashing the server maybe put it in a VM like docker or something, which gives you neat auto-restart capabilities off the bat.
Another hacky thing you can do is schedule your gosund plug to turn off and on once a day through their consumer UI or app, or at whatever frequency you feel like is most optimal.
The google-assistant-sdk is intended for processing audio requests.
From the doc:
Your project captures an utterance (a spoken audio request, such as What's on my calendar?), sends it to the Google Assistant, and receives a spoken audio response in addition to the raw text of the utterance.
While you could use that with some recorded phrases it makes more sense to connect to the switch directly or use a service like IFTTT. What kind of switch is it?

how to design rest api which handle offline data

I have multiple api which we have provided to android developers.
Like :
1) Creating Business card API
2) Creating Contacts API
So these api working fine when app is online. So our requirement is to handle to create business card and contacts when app is offline.
We are following steps but not sure:-
1) Android developer store the business card when app offline and send this data to server using separate offline business card api when app comes online.
2) Same we do for creating contacts offline using offline contact api.
My problem is I want do in one api call to send all data to server and do operation.
Is this approach will right?? Also please suggest what is the best approach to handle offline data. Also how to handle syncing data when app would come online??
Please let me know if I could provide more information.
I'm confused as to how you're approaching this. My understanding is that when the app is offline you want to "queue up" any API requests that are sent.
Your process seems fine however without knowing the terms around the app being "offline" it's hard to understand if this best.
Assuming you're meaning the server(s) holding the application are offline you're correct you want a process in the android app that will store the request until the application becomes online. However, this can be dangerous for end users. They should be receiving a message on the application being offline and to "try again later" as it were. The fear being they submit a request for x new contacts to be queued and then re-submit not realizing the application was offline.
I would suggest you have the android app built to either notify the user of the app being down or provide some very visible notification that requests are queued locally on their phone until the application becomes available and for them to view/modify/delete said locally cached requests until the application becomes available. When the API becomes available a notification can be set for users to release their queue on their device.

How do you register a python-based client with GCM (Google Cloud Messenger) to get a registration_id for the device?

I have been trying to figure out how to use one of the following python packages to create a python-based client that is capable of receiving XMPP-based messages via Google Cloud Messenging.
https://github.com/geeknam/python-gcm
https://github.com/daftshady/py-gcm
https://pypi.python.org/pypi/gcm-client/
https://github.com/pennersr/pulsus
From all I can see, (e.g., the documentation for gcm-client), these packages can send messages to other clients that are identified by registration_id. But how do I get a registration IDs for each client in the first place? In other words, how do I register the client-app that I am creating so that it can receive messages?
It is starting to seem to me that these are not clients per-se, but just libraries that can be used to push messages to clients. I hope that I am wrong about that and just missing a key concept.
Each client application has to call the getRegistrationId() to get the registration id once. Then they can receive messages. A more detailed function call is here
I hope this give you an idea on client devices. :)

Find Lat/Long from python using Google

I'm coming up just a little short on this. I know google has a python client library, and it also has Client Location. However, i'm at a loss on how to access Client Location via the API.
What I'm trying to do is make a desktop app Location Aware.
Is it a desktop app running in a browser ? If so, then use the W3C GeoLocation API - see https://stackoverflow.com/a/8973377/156477 and many other questions on SO.
If not, then you need a service that determines location via WiFi MAC address or an IP geolocation lookup. For the WiFi MAC address lookup, check out http://code.google.com/p/maclocate/. For an IP based lookup, MaxMind provide a service (there is a free service accurate to a city, or a paid for service if you need more accuracy). There is also a Python library http://www.maxmind.com/app/python.
Note, I haven't tried either library so I can't vouch for them. I have used the MaxMind service and it works well, with the exception of users who are on a corporate network. These users will always be reported as being located where the corporate network hub is.

Categories