How to return a list from a macro

To start and level-set, I’m not an experienced Python or Jinja coder. I don’t even play one on TV. I’ve got a fair amount of experience in C/C++/C#/PowerShell, but virtually none in Python/Jinja…

I’m trying to put together a macro that will return a list of entities that match specific conditions. Ideally I’d like to call the macro in some places to return the list of entity ids that match criteria, and in other places get the count of the number of items returned.

I’ve got it returning the ‘list’, but it’s actually returning just a string with the values.

macro code

{%- macro get_low_battery_entities() -%}
    {%- set myData = [] -%}
    {%- set myEntities = namespace(entities=[]) -%}
    {%- for sensor in states.sensor -%}
        {%- if sensor.attributes.device_class not in ['undefined','unknown'] -%}
            {%- if sensor.attributes.device_class in ['battery'] -%}
                {# {%- if sensor.state|int <= states('input_number.setting_battery_warning_percent')|int -%} #}
                {%- if sensor.state|int <= 100 -%}
                    {%- set myEntities.entities = myEntities.entities + [sensor.entity_id] -%}
                    {# {{ sensor.entity_id + "\n" }} #}
                {%- endif -%}
            {%- endif -%}
        {%- endif -%}
    {%- endfor -%}
    {{ myEntities.entities }}
{%- endmacro %}

In the Dev Tools template editor, I put in

{% from 'get_low_battery_entities.jinja' import get_low_battery_entities %}
{{ get_low_battery_entities() }}
{{ get_low_battery_entities()|count }}
****

And I get the following output

['sensor.trace_s_sm_g781v_battery_level', 'sensor.chelle_s_ipad_2_battery_level', 'sensor.chelles_sm_s916u_battery_level', 'sensor.toffice_printer_battery_charge', 'sensor.asustor_battery_charge', 'sensor.toffice_aux_battery_charge', 'sensor.toffice_monitors_battery_charge', 'sensor.coffice_main_battery_charge', 'sensor.master_closet_door_battery', 'sensor.trace_night_stand_scene_switch_battery', 'sensor.chelle_night_stand_scene_switch_battery', 'sensor.family_room_temperature_battery', 'sensor.laundry_room_dryer_vibration_battery', 'sensor.laundry_room_washer_button_battery', 'sensor.roomba_battery_level', 'sensor.kitchen_sink_spotlight_switch_battery', 'sensor.garage_door_sensor_battery', 'sensor.chelle_office_temperature_battery', 'sensor.garage_freezer_temperature_battery', 'sensor.master_bedroom_temperature_battery', 'sensor.trace_s_ipad_mini_4_battery_level', 'sensor.trace_s_ipad_mini_6_battery_level'] 
921 
****

I’m wanting the output count to be the number of entities in the list, but what seems to be coming back from the macro is a string, so I’m just getting the count of chars in the string. Any hints on where I’m going wrong would be greatly appreciated.

You could probably get around it with:

{{ get_low_battery_entities().split(',') | count }}

Everything returned is a string, so casting it as a list is still needed I believe.

 | list

My Color-Multi-Tool macro returns strings formatted as lists so I explain to the user to cast them to get what they expect.

Macros always return a string. You can make the macro return a JSON-formatted string with to_json at the end, then unpack it with from_json when you use its result. Example here (output is a dict, but same principle for a list):

Thanks, but in this case it just became a list of characters, not a list of strings.

This worked well. Thanks!!!