Skip to content

Instantly share code, notes, and snippets.

@chatziko
Created February 2, 2024 13:11
Show Gist options
  • Save chatziko/74a5eacad3fd934d2ec734dab17aa4c0 to your computer and use it in GitHub Desktop.
Save chatziko/74a5eacad3fd934d2ec734dab17aa4c0 to your computer and use it in GitHub Desktop.
AppDaemon return_result workaround

This is a workaround for AppDaemon/appdaemon#1837

  1. Add the call_service_with_response script to your HA config
  2. Inherit your app from ServiceResponseApp and use call_service as usual with return_result
class MyApp(ServiceResponseApp):
    async def initialize(self):
        list = await self.call_service(
            "todo.get_items",
            entity_id="todo.shopping_list",
            return_result=True,
        )
        self.log("list %s", list)
script:
call_service_with_response:
description: Calls a service and returns its response to AppDaemon
fields:
call_id:
name: Call id
default: 1
description: An id to uniquely identify the call
required: True
selector:
text:
service_name:
name: Service name
default: domain.some_service
description: The service to call
required: True
selector:
text:
service_data:
name: Service data
default: {}
description: Data to pass to the service
required: True
selector:
object:
sequence:
- service: "{{ service_name }}"
data: "{{ service_data }}"
response_variable: response
- event: call_service_with_response.finished # event name cannot be templated unfortunately
event_data:
call_id: "{{ call_id }}"
response: "{{ response }}"
import random
import asyncio
import hassapi as hass
class ServiceResponseApp(hass.Hass):
def call_service(self, service, return_result=False, **kwargs):
# standard call
if not return_result:
return super(ServiceResponseApp, self).call_service(service, **kwargs)
# call with result, using the script wrapper
res = asyncio.get_running_loop().create_future()
call_id = random.randrange(2**32)
def cb(name, data, kwargs):
res.set_result(data["response"])
self.listen_event(
cb,
"call_service_with_response.finished",
call_id=call_id,
oneshot=True,
)
self.call_service(
"script/call_service_with_response",
service_name=service,
service_data=kwargs,
call_id=call_id,
)
return res
@ArdJonker
Copy link

Hi chatziko,
Nice solution, thanks! It works nicely for me.
Now i can get all calendar events from a local Google integration calendar into AppDaemon code.
💪🙏

@chatziko
Copy link
Author

NOTE: since appdaemon 4.5.0 the workaround is no longer needed, check the doc for how to get the returned data.

If you want to quickly upgrade while keeping compatibility with your existing apps that inherit from ServiceResponseApp above, change the class with the one below:

import hassapi as hass

class ServiceResponseApp(hass.Hass):
    async def call_service(self, service, return_result=False, **kwargs):
        """Just a small compatibility layer to use the old workaround under 4.5.0."""
        res = await super().call_service(service, **kwargs)
        return res["result"]["response"] if return_result else None```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment