Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Supply Alexa notifications (alarms/timers/reminders) #144

Closed
Walter-Bishop opened this issue Mar 28, 2019 · 43 comments
Closed
Assignees
Labels
enhancement New feature or request

Comments

@Walter-Bishop
Copy link

Hello,

your component has been very useful for me. To further improve it, I'm suggesting the following new feature:

Since I'm using Alexa's alarm feature for waking up in the morning it would be great having access to the alarm time through home assistant. Then I would be able to create an automation that, for example, sets the heating or lights up the bedroom previously to the alarm ringing.

Do you think it would make sense to add such a feature to your component?

@alandtse alandtse added enhancement New feature or request question Further information is requested labels Mar 29, 2019
@alandtse
Copy link
Owner

Should be possible; I just don't know what alarm components exist in HA. Can you point to one?

@alandtse
Copy link
Owner

alandtse commented Apr 4, 2019

@Walter-Bishop Is your goal only to know when an alarm or timer goes off? Or are you also interested in setting them?

@eavanvalkenburg
Copy link

I'm also really interested in this! Mostly interested in knowing when it goes off, to trigger other stuff in HA.

@alandtse
Copy link
Owner

Would it work if you had to call a service to get the next alarm/timer time? The API doesn't appear to report when the timer or alarm goes off so it's a little hackey to figure it out.

@eavanvalkenburg
Copy link

I would be fine with that, would just be a scheduled service call at like 3AM, so that you know the next mornings alarm if any, and then setup some other stuff based off that.

@dlashua
Copy link

dlashua commented May 23, 2019

For me, just having the data available in a sensor entity would be useful.

https://alexa.amazon.com/api/notifications

The above API call will provide the reminders/alarms/timers information. Each of them includes an indication of which device it's set on via deviceSerialNumber. Exposing something like sensor.my_alexa_device_name_alarms, sensor.my_alexa_device_name_reminders, and sensor.my_alexa_device_name_timers that contained all of the data available from the API would be incredibly useful.

Even more... a service could be exposed to allow the setting of reminders. This is done with a PUT call to /api/notifications/createReminder with data like the following:

{
"type": "Reminder",
"status": "ON",
"alarmTime": 1545520380000,
"originalTime": "15: 13: 00.000",
"originalDate": "2018-12-22",
"timeZoneId": null,
"reminderIndex": null,
"skillInfo": null,
"sound": null,
"deviceSerialNumber": "deviceSerialNumber",
"deviceType": "deviceType",
"recurringPattern": null,
"reminderLabel": "test",
"isSaveInFlight": true,
"id": "createReminder",
"isRecurring": false,
"createdDate": 1545516813030
}

PUT and DELETE calls are also handled for /api/notifications/

I have a strong feeling that a PUT call to /api/notifications/createAlarm would work too, though I don't have sample JSON data for this yet.

@alandtse
Copy link
Owner

Thanks. The issue isn't so much the API as I found it but figuring out the best way to represent it in HA. I asked the dev channel and didn't get a response. The existing calendars are using binary sensors so I might just do that.

@dlashua
Copy link

dlashua commented May 24, 2019

That's a great idea! The binary_sensor can be ON if there are any alarms, reminders, timers, and OFF if there are not. And then the actual data can be in the binary_sensor attributes.

@eavanvalkenburg
Copy link

That would work perfectly, you can then trigger on the sensor change, and put the attribute in it's own sensor or use it some other way, either way, that will enable some truly smart stuff!

@alandtse
Copy link
Owner

To follow the other calendars, each alarm would have its own binary sensor. Let me know if you see any issues with that method.

If anyone can confirm the calls for setting alarms, I can also see about adding that somehow.

@dlashua
Copy link

dlashua commented May 24, 2019 via email

@alandtse
Copy link
Owner

alandtse commented May 25, 2019

@dlashua Can you please provide some examples of how an automation could iterate through the data so I can see about what would be the best implementation?

For example, I could do it in an ordered queue like attr.0 attr.1, etc.

@ronmichel
Copy link

An example is how the GoogleHome Alarm is displayed as a sensor within Homeassistant (see here). I personally don't like that it shows only the one next approaching but would prefer attributes with every alarm set...

@dlashua
Copy link

dlashua commented May 28, 2019

an ordered queue would be fine, as long as there is a separate sensor for each device.

This way I can make an automation that says when it's 30 minutes until the alarm in the bedroom, start turning on the lights. When the alarm in the kitchen has been going off for 30 seconds without being stopped, start blinking the lights in the house.

For alarms, specifically, that's about as far as it goes since Alexa doesn't allow you to name alarms. Timers, however, can also have a name, so even more things could be done. Like, when my "dinner" timer in the kitchen sounds, announce on all devices "dinner is ready".

@B1G1
Copy link

B1G1 commented Jul 2, 2019

Hi, it would be very usefull for me to set alarm timers from Home Assistant

@ronmichel
Copy link

ronmichel commented Jul 24, 2019

Can someone please help me to get the following sensor working:

- platform: command_line
  command:   '/usr/bin/curl -X GET https://alexa.amazon.com/api/notifications? -b /config/alexa_media.XXX@XXX.com.pickle'
  value_template: '{% if value_json.notifications[0].alarmTime is defined %}{{ value_json.notifications[0].alarmTime }}{% else %}none{% endif %}'

I want to use the cookie file of this custom component to get the alarm times. (In my browser it works with an active session)
Here, the curl doesn't seem to get any response from the server... Do I need any other Headers, Useragent etc?

Edit: working sensor see below.

@dlashua
Copy link

dlashua commented Jul 24, 2019

@ronmichel I don't think you can use the pickle file like that. At least, just on plain command line, it doesn't work for me.

On top of that, even if it did work, the value_template needed to get a specific alarm from a specific echo device would be far too complicated. What you have there would only get the very first alarm's time, which may, in fact, be a timer, not an alarm, and, even if it is an alarm, might be turned off.

I have some working code that gets the most recent alarm time from each echo device and sets it as a sensor that you can access. However, it's written for AppDaemon (so that would be a requirement). And, as of right now (though I'm adding this feature next) it doesn't read alexa_media_player's pickle file, so you have to perform the captcha for it as well.

This code can't be used in a python_script because it imports alexapy which python_scripts don't allow. It could be made into a custom_component, though. However, it would be getting the devices list a second time, so it's really better off being integrated into alexa_media_player.

@ronmichel
Copy link

I have some working code

Hi @dlashua,
Do you have the code on your github? thanks

@ronmichel
Copy link

ronmichel commented Jul 26, 2019

I have a working sensor now (@dlashua was right, the pickle can't be loaded into curl, it needs requests).
If anyone is interested:

  1. Create /config/echoalarms.py with the following content:
#!/usr/bin/python3
import requests
import pickle

with open('/config/alexa_media.XXX@XXX.XXX.pickle', 'rb') as myfile:
    cookies = pickle.load(myfile)

session = requests.Session()

session.headers = {
    'User-Agent': ('Mozilla/5.0 (Windows NT 6.3; Win64; x64) '
                   'AppleWebKit/537.36 (KHTML, like Gecko) '
                   'Chrome/68.0.3440.106 Safari/537.36'),
    'Accept': ('text/html,application/xhtml+xml, '
               'application/xml;q=0.9,*/*;q=0.8'),
    'Accept-Language': '*'
}

session.cookies = cookies

response = session.get('https://alexa.amazon.XXX/api/notifications?&')

print(response.text)
  1. Adapt the name of your pickle file and the amazon url to your data.
  2. In your configuration.yaml add the following:
sensor:
  - platform: command_line
    name: EchoAlarms
    command: 'python3 /config/echoalarms.py'
    value_template: "{% if value_json.notifications is defined %}{{(value_json.notifications|selectattr('status', 'equalto','ON')|map(attribute='alarmTime')|list|sort|first/ 1000)|timestamp_local}}{% else %}false{% endif %}"
    json_attributes:
      - notifications  
  1. The state of the sensor is the next upcoming alarm Time. If you want any more information you can use the attribute "notifications" with all the available date for an additional Template sensor.

  2. Can for sure be improved. Just a fast solution for me for the time being...

@dlashua
Copy link

dlashua commented Aug 23, 2019

I used the alexapy library to make an AppDaemon based integration to find currently set alarms and set a sensor to that value for each echo device. It's not feature complete, so I'm not sharing the AppDaemon app just yet. But the central code that finds the alarms and builds a list of them might be useful to kickstart this feature in the alexa_media_player code base:

    def update_devices(self):
        self._devices = AlexaAPI.get_devices(self.login)

    def get_entity_by_name(self, name):
        return re.sub(r'([^\w])', '_', name).lower()

    def get_entity_by_sn(self, sn):
        return self.get_entity_by_name(self.get_name_by_sn(sn))

    def get_name_by_sn(self, sn):
        try:
            for d in self._devices:
                if d['serialNumber'] == sn:
                    return d['accountName']
        except Exception:
            return None

        return None

    def update_notifications(self):
        notifications = AlexaAPI.get_notifications(self.login)
        alarms = {}
        for n in notifications:
            entity = self.get_entity_by_sn(n['deviceSerialNumber'])
            alarm_time_obj = None
            if n['status'] != "ON":
                continue
            
            if n['originalDate'] is None:
                continue

            if n['originalTime'] is None:
                continue

            alarm_time_string = n['originalDate'] + " " + n['originalTime']
            alarm_time_obj = datetime.datetime.strptime(
                alarm_time_string,
                "%Y-%m-%d %H:%M:%S.%f"
            )

            data = {
                "entity": entity,
                "alarm": alarm_time_obj,
            }

            if entity in alarms and alarms[entity]['alarm'] is not None:
                if data['alarm'] is not None:
                    if alarms[entity]['alarm'] > data['alarm']:
                        alarms[entity] = data
            else:
                alarms[entity] = data

@alandtse
Copy link
Owner

Thanks @dlashua. Is your sensor showing the next alarm or every alarm per device? I got stalled in trying to figure out the best way to show this but may be able to look at implementing this again now that async is done. You can tell when I got stalled because I added the underlying alexapy call but never implemented the feature. ;)

As a note, with the new aiohttp library, the cookie format has changed. It may be possible to use curl with it but I haven't tested.

@dlashua
Copy link

dlashua commented Aug 24, 2019

I create one sensor per discovered device. There are other bits that look at "capabilities" returned by the device retrieval method and only add sensors if they have TIMERS_AND_ALARMS. The sensor is always set to the string of the next alarm for each device. It is False if there is no alarm. And I add a timestamp attribute with the epoch time to make the sensor usable in Home Assistant templates.

Also, in case it matters, this uses alexapy as it was maybe... 2 months ago. If there have been breaking changes since then, I've not kept it up to date.

@alandtse
Copy link
Owner

Yah, we just moved alexapy to async so it's a breaking change at 1.0.0.

@ronmichel
Copy link

@alandtse
My sensor still works with 1.0
It shows the next alarm as the sensor state but all other alarms can be retreived in the sensor attributes.

@alandtse
Copy link
Owner

@ronmichel it will probably work until 1.0.0 needs to create a new cookie. Then it'll save it in the aiohttp format which is the format that may work in curl. Requestcookies are different from standard cookies I think.

@UltraSub
Copy link

UltraSub commented Sep 11, 2019

Just bought an echo show 5 to be used as an alarm clock. I would also like to get the alarms set into HA, so I can do more automation, like for example do wake-up lights. This would require HA knowing what time the alarm is set to.
The other way around, setting an Alexa alarm from HA would also be very handy.
You guys think this would be possible?

@alandtse
Copy link
Owner

I have a version where it'll show the next alarm, reminder, and timer each as a separate sensor. In terms of showing all items, do you only want to see what is actually 'on' or everything?

If you've seen the notifications json, you'll notice that Amazon likes to create many items.

@eavanvalkenburg
Copy link

Just active ones for me @alandtse, since we set a different time most mornings we have a ton of alarms in the app and I wouldn't want all of those in my HA, just active ones!

@ronmichel
Copy link

@alandtse
Just the next upcoming alarm as one actual sensor for each device would be nice. The other (later or inactive) alarms could be implemented as sensor attributes (so anyone interested in the data could create template sensors for them)

@UltraSub
Copy link

Agree with @ronmichel on this!

@alandtse
Copy link
Owner

Ok. Is there value in throwing an alarm going off event or would exposing the time be enough?

Sending an event will be guess work since there isn't a direct event from the API to monitor.

@dlashua
Copy link

dlashua commented Sep 25, 2019

For me, just having the time is enough. If I need to know when it's going off I can make an automation that triggers at that exact time.

@UltraSub
Copy link

Also don’t see a use for sending events, especially if it isn’t easy to do. Once the time is in Hass, it’s easy enough to make an automation trigger.

@alandtse
Copy link
Owner

For the adventurous and advanced users, there's a PR staged which also requires replacing alexapy. It exposes sensors for each device that will tell you the next active notification (alarm/timer/reminder). It also exposes attributes with a sorted list of all upcoming notifications or all notifications in the system. For those who are building template sensors, let me know if it needs any tweaking.

I'm looking at adding switches for enabling alarms/pausing timers or just doing a service call. That may make it in the next release or may be further along. May also look at adding the ability to add such notifications.

@alandtse alandtse changed the title Feature Request: Supply set alarm times Feature Request: Supply Alexa notifications (alarms/timers/reminders) Sep 27, 2019
@alandtse alandtse self-assigned this Sep 27, 2019
@alandtse alandtse removed the question Further information is requested label Sep 27, 2019
@alandtse
Copy link
Owner

This is live in 2.3.0.

@dlashua
Copy link

dlashua commented Oct 4, 2019

I'm assuming you mean the sensor.device_name_next_alarm entity. Mine doesn't seem to update after I've added an alarm to the device. Even though my custom code (that uses alexapy) sees the update. Thoughts?

@UltraSub
Copy link

UltraSub commented Oct 4, 2019

I’ve seen this happening twice in my setup. The first time I tested the hell out of it and it worked every time, until I added an alarm with Spotify playlist on shuffle and the sensor would show no alarm. Even restarted, no go. Removed the alarm and set it the simplest way, instantly updated.

The second time it was a simple alarm, but it just wouldn’t update. Restarting Hass fixed it.

Anyway, thanks for adding this feature. Love it. Might still need some ironing though :)

@alandtse
Copy link
Owner

alandtse commented Oct 4, 2019

There's a bug for MusicAlarms. #402

One thing to check is whether you're seeing websocket requests for alexapy in the logs when editing alarms. If you aren't, then you're probably experiencing other update issues as we've lost the connection to the server.

@AngelofromTurin
Copy link

ciao,
il mio "sensor.echo_living_next_alarm" ' status is 19:43:00+02:00 with the utc ,
it's not good for me to interact with some hassio automation, how can i remove "+02:00" to use it?
I thought I'd also use a template to read the "json" data in the description of the "sorted_active" attribute but I wasn't able to; tips?

@UltraSub
Copy link

UltraSub commented Oct 7, 2019

By doing something like this:
{{ as_timestamp(states("sensor.echo_living_next_alarm"))| timestamp_custom('%d %b %Y at %H:%M') }}

or minutes to next alarm:
{{ (((as_timestamp(strptime(states("sensor.echo_living_next_alarm"), "%Y-%m-%d %H:%M:%S%z"))) - as_timestamp( strptime( now().strftime("%Y-%m-%d %H:%M:%S%z"), "%Y-%m-%d %H:%M:%S%z") )) / 60) | int}}

@AngelofromTurin
Copy link

{{ as_timestamp(states("sensor.echo_living_next_alarm"))| timestamp_custom('%d %b %Y at %H:%M') }}

Thank You ! I will work on it :)

@ronmichel
Copy link

I created an issue: #409 (comment)

@AngelofromTurin
Copy link

AngelofromTurin commented Oct 14, 2019

ok lo faccio! : Slight_smile:
questo è il mio test di automazione:
`automation:

  • alias: Sveglia CountDown
    initial_state: 'on'
    trigger:
    • platform: template
      value_template: >-
      {{ ((as_timestamp(strptime(states("sensor.echo_camera_next_alarm"), "%H:%M, %Y-%m-%d")) - (as_timestamp(strptime(states("sensor.time_date"), "%H:%M, %Y-%m-%d")))) / 60) | int == 30 }}
      action:
    • service: notify.telegram
      data_template:
      title: "Sveglia Alexa - {{ states('sensor.time') }}"
      message: >-
      Suonerà fra: {{ ((as_timestamp(strptime(states("sensor.echo_camera_next_alarm"), "%H:%M, %Y-%m-%d")) - (as_timestamp(strptime(states("sensor.time_date"), "%H:%M, %Y-%m-%d")))) / 60) | int }} minuti
      alle: {{ as_timestamp(states.sensor.echo_camera_next_alarm.state) | timestamp_custom("%H:%M, %Y-%m-%d") }}`

`- id: RQ Attiva Buongiorno
alias: "RQ Sveglia Attiva Buongiorno"
initial_state: 'on'
trigger:

  • platform: template
    value_template: >-
    {{ states.sensor.time_date.state == as_timestamp(states.sensor.echo_camera_next_alarm.state) | timestamp_custom("%H:%M, %Y-%m-%d") }}
    action:
  • service: script.turn_on
    data:
    entity_id: script.rq_buongiorno`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

8 participants