Batocera to Home Assistant via MQTT

Taken me some time to get here are my steps i did
1st getting MQTT working in batocera that was the hard bit
heres the code I found

###############################################################################
# Self-contained user service for exposing all Batocera events to MQTT
###############################################################################

# Next 4 lines must be customized to your MQTT system 
MQTT_HOST=<broker host or ip>
MQTT_PORT=<usually 1883>
MQTT_USER=<broker username>
MQTT_PASSWORD=<broker password>

MQTT_BASE_TOPIC=batocera/$(hostname)

SERVICE_NAME=$(basename "$0" .${0##*.})
ES_EVENTS=(game-start game-end game-selected system-selected theme-changed settings-changed controls-changed config-changed quit reboot shutdown sleep wake achievements)

###############################################################################
# Publish an event message to the MQTT broker as JSON dictionary.
#
# The first argument is the subtopic to publish to (source/event_name)
# The remaining arguments are converted to a list of strings, which
# is stored in the 'data' field of the message
# An ISO-formatted 'timestamp' field is automatically added to the message
#
# Only executes if this service is enabled
###############################################################################
publish() {
    if [[ " $(/usr/bin/batocera-settings-get system.services) " == *" $SERVICE_NAME "* ]]; then
        subtopic="$1"
        shift
        # Initialize an empty JSON array
        data='['
        # Iterate over the remaining arguments
        for arg in "$@"; do
            # Convert each argument to a JSON string and append it to the array
            data+="$(jq -Rn --arg arg "$arg" '$arg'),"
        done
        # Remove the trailing comma and close the JSON array
        data="${data%,}]"
        mosquitto_pub -h "$MQTT_HOST" -p "$MQTT_PORT" -u "$MQTT_USER" -P "$MQTT_PASSWORD" -t "$MQTT_BASE_TOPIC/$subtopic" -m '{"data": '"$data"', "timestamp": "'"$(date --iso-8601=ns)"'"}'
    fi
}

###############################################################################
# Start the MQTT service.
# - Installs any missing support files
# - Publishes a system startup event
###############################################################################
start() {
    install
    publish "system/startup"
}

###############################################################################
# Stop the MQTT service.
# - Publishes a system shutdown event
###############################################################################
stop() {
    publish "system/shutdown"
}

###############################################################################
# Create scripts that capture events and publish them to the MQTT broker.
###############################################################################
install() {
    # EmulationStation events
    for event in ${ES_EVENTS[@]}; do
        script_dir="/userdata/system/configs/emulationstation/scripts/$event"
        mkdir -p "$script_dir"
        script="$script_dir/$SERVICE_NAME.sh"
        if [[ -f "$script" ]]; then
            echo "WARNING: Skipping installation of '$script', as it already exists"
            continue
        fi
        echo "Installing '$script'"
        cat <<-EOF > "$script"
#!/bin/bash
/userdata/system/services/$SERVICE_NAME publish "emulationstation/$event" "\$@"
EOF
    chmod +x "$script"
    done

    # Game events
    script="/userdata/system/scripts/$SERVICE_NAME.sh"
    echo "Installing '$script'"
    cat <<-EOF > "$script"
#!/bin/bash
/userdata/system/services/$SERVICE_NAME publish "game/\$1" "\${@:2}"
EOF
}

###############################################################################
# Delete scripts that capture events and publish them to the MQTT broker.
###############################################################################
uninstall() {
    # Delete EmulationStation event scripts, and remove event directories if empty
    for event in ${ES_EVENTS[@]}; do
        script_dir="/userdata/system/configs/emulationstation/scripts/$event"
        script="$script_dir/$SERVICE_NAME.sh"
        echo "Deleting '$script'"
        rm "$script"
        if [ -z "$(ls -A "$script_dir")" ]; then
            echo "Deleting empty directory '$script_dir'"
            rm -rf "$script_dir"
        fi
    done

    # Delete Game event script
    script="/userdata/system/scripts/$SERVICE_NAME.sh"
    echo "Deleting '$script'"
    rm "$script"
}

###############################################################################
# Script entrypoint
###############################################################################
if [ $# -eq 0 ]; then
    echo "ERROR: No arguments provided"
    echo "Usage: $SERVICE_NAME publish|start|stop|install|uninstall [args]"
    exit 1
fi
if [[ $(type -t "$1") == function ]]; then
    FUNCTION="$1"
    shift
    $FUNCTION "$@"
else
    echo "ERROR: '$1' is not defined"
    echo "Usage: $SERVICE_NAME publish|start|stop|install|uninstall [args]"
    exit 1
fi

I changed the 4 MQTT to match my config

MQTT_HOST=192.168.something
MQTT_PORT=1883
MQTT_USER=mqttuser #not need to be a HA user
MQTT_PASSWORD=imnottellingyou

after a reboot of the batocera box

I look into mqtt explorer I see

one Happy camper here

Now the HA stuff

as I want to know the game-start

old school here love YAML

so in my mqtt sensor config i have

  - name: "Batocera Game Start"
    state_topic: "batocera/MAME/emulationstation/game-start"
    value_template: "{{value_json.data[2]}}"

as all data coming in is json format I want to read the game name

as its the 3 one in the array
I can read that value

value_template: "{{value_json.data[2]}}"

I get this in my sensor

now the fun starts lets automate something

=== Edit
change my thinking

  - name: "Batocera Game Playing"
    unique_id: 1bcc7fe6-8a55-4740-ba05-7917c7b2234e 
    state_topic: "batocera/MAME/emulationstation/game-start"
    value_template: "{{value_json.data[2]}}"

  - name: "Batocera Game Start"
    unique_id: f9eace35-4b3d-43ea-97d5-98c1aa424090
    state_topic: "batocera/MAME/emulationstation/game-start"
    value_template: "{{value_json.timestamp}}"
    json_attributes_topic: "batocera/MAME/emulationstation/game-start"
    json_attributes_template: '{{ value_json | tojson }}'

  - name: "Batocera Game End"
    unique_id: 3d56c98d-5498-4d77-af64-d4a725fa0e17
    state_topic: "batocera/MAME/emulationstation/game-end"
    value_template: "{{value_json.timestamp}}"
    json_attributes_topic: "batocera/MAME/emulationstation/end-start"
    json_attributes_template: '{{ value_json | tojson }}'  

give me this

Now the maths part work out playing time

Got it working adding watching the state change of the “sensor.batocera_game_end”
can do the maths on sensor.batocera_game_end - sensor.batocera_game_start

- trigger:
    - trigger: state
      entity_id:
        - sensor.batocera_game_end
  sensor:
    - name: Batocera Game Last
      unique_id: 6f8bb9d7-6f60-4b85-8645-8a70118ccf6e
      state: >-
        {%set s = states.sensor.batocera_game_start.state | as_datetime | as_local %}
        {%set e = states.sensor.batocera_game_end.state | as_datetime | as_local %}
        {%set n = states.sensor.batocera_game_playing.state %}
        {%set l = (e-s).total_seconds()  %}
        {% if e>s %}
        {{n}}  {{ l | timestamp_custom('%H:%M', false) }}
        {%else%}

        {%endif %}

now can add the marquee of the game.

1 Like

Nice.
It should be in Share your Projects! - Home Assistant Community, though.

Thanks bro move it