Skip to content

Adding an AI Fitness coach to a Smart Scale

Last updated:

eufy P2 Pro

We have previously hooked up the eufy Smart Scale to Home Assistant. Lets connect the data we get to an AI Assistant so it can coach us on our fitness goals. While it is also possible to implement this using native Home Assistant automations I found it quite cumbersome to debug, so instead I went with a Node-Red which is fairly straight forward for this use case.

Setup

Prerequisites

  • Home Assistant with the Node-Red Add-on setup.
  • An AI integration is set up to act as a conversation agent.

Setting up the Node-Red Automation

  1. Create a Node-RED flow

    • Create a new flow by clicking on the ”+” icon.
    • Drag and drop an “inject” node, a “state” node, a “get history” node, three “function” nodes, an “API” node and a “debug” node into the workspace.

    The output of every node while working on it can be seen by connecting it to the debug node and selecting the debug tab on the right sidebar. We can connect multiple nodes simultaneously to the same debug node which makes it easy to see any mistakes in any of the steps.

    We will build up the autmoation node by node, connecting them up one by one.

  2. Configure the “inject” node

    • We will be using this to debug the output of each step, we can trigger the automation anytime after deploying by clicking its button.
  3. Configure the “get history” node

    • Double-click on the “get history” node to configure it.
    • Lets name it getWeightMeasurements.
    • Select the sensor entity that stores the weight measurements.
    • Check “Use relative time” and select a suitable time range e.g. 7d.
    • Output type is array, Output location is the default msg.payload.

    This give us a list of measurements, that looks like this:

    {"entity_id":"sensor.weight","state":"81.25","attributes":{"state_class":"measurement","unit_of_measurement":"kg","device_class":"weight","friendly_name":"Weight"},"last_changed":"2025-03-21T12:08:28.123122+00:00","last_updated":"2025-03-21T12:08:28.123122+00:00"}

    That’s a lot of extraneous data that we will cull with the next function node.

  4. Configure the toSimpleList “function” node

    • Double-click on the “function” node to configure it.
    • Name it toSimpleList.
    • Add code to only keep the weight and timestamp of each measurement and prune it so a manageable amount of entries:
    const maxEntries = 8;
    function toSimpleList (item = {}) {
    const {
    state,
    last_updated: timestamp
    } = item;
    const value = parseFloat(state);
    if (!value || !timestamp) return null;
    const unit = item.attributes?.unit_of_measurement || 'kg';
    const weight = `${value} ${unit}`;
    return {
    weight,
    timestamp
    }
    }
    const measurementsToAnalyze = msg.payload
    .map(toSimpleList)
    .filter(Boolean)
    .slice(-maxEntries);
    return {
    payload: measurementsToAnalyze
    };
  5. Configure the simpleListToAiRequest “function” node

    • Double-click on the “function” node to configure it.
    • Name it simpleListToAiRequest.
    • Add code convert the structured data into an AI prompt:
    const weightMeasurements = JSON.stringify(msg.payload);
    return {
    payload: `You are a health coach, famous for phrasing
    sentences with laconic wit. The person tracking their
    weight is 175 cm tall, with an target weight of 70 kg.
    Here is the JSON data of the weight measurements of the last
    few days: \`${weightMeasurements}\`.
    Based on the weight trend and their current weight,
    analyze the progress and estimate a target date.
    `.replace(/\n/g, ' ')
    };
  6. Configure the “API” node

    • This node will send the request to Home Assisttant’s AI conversation agent.
    • Double-click on the “API” node to configure it.
    • Name it getAiResponse.
    • Set “Protocol” Webocket.
    • Set “msg.payload” to results.
    • Set Data to JSON format and paste the request config:
    {
    "type": "execute_script",
    "sequence": [
    {
    "service": "conversation.process",
    "data": {
    "agent_id": "conversation.openai_conversation",
    "text": "{{payload}}"
    },
    "response_variable": "service_result"
    },
    {
    "stop": "done",
    "response_variable": "service_result"
    }
    ]
    }
  7. Configure the getAiResponse “function” node

    • Double-click on the “function” node to configure it.
    • Name it getAiResponse.
    • Add code convert retrieve the AI response text from the response object:
    const weightMeasurements = JSON.stringify(msg.payload);
    return {
    payload: msg.payload.response.response.speech.plain.speech
    };

    This could be extended to output the response to a nearby speaker.

  8. Connect the nodes and test

    • Connect the nodes in series and test if everything works.
  9. Add an automatic trigger when using the scale

    • Double-click on the “state” node to configure it.
    • Name it weightMeasurementTrigger.
    • Select the weight sensor as the entity.
    • “State type” is String.
    • Connect it up to the getWeightMeasurements node.

Smart Scale Flow

Conclusion

Node-Red on Home Assistant allows us to easily integrate an LLM with our smart scale. Depending on our individual requirements we can now tweak the AI prompt to provide better advice tailored to our needs. Note that there may be issues if the prompt sent to the TTS engine is too long. This could be mitigated by splitting the response into smaller chunks and sending them one at a time.

We have built a simple flow, but this could be extended with additional sensors or data points to provide more comprehensive coaching.