Set power injection for EET Solmate battery (Github mmattel integration)

Hi,

I use https://github.com/mmattel/EET-Solmate to integrate my small solar system in HA and I want to set the min and max injection of my EET-Solmate based on

  • remaining forcasted solar production
  • SoC of battery
  • EPEX price percentile (dynamic energy price from grid).
  • current energy consumption (Shelly 3EM pro)

With logic and Chat GPT I managed to get as far as having the values I want to post, but I failed by trying to set the number.solmate_set_inject_user_minimum_injection and number.solmate_set_inject_user_maximum_injection via action node, aswell as by mqtt directly.

First function taking remaining solar production, battery charge and EPEX percentile.

// Configuration
const BUFFER = 0.2;  // buffer value in kWh

// Store incoming values in context
if (msg.topic === "sensor.energy_production_today_remaining") {
    context.set("remainingProduction", Number(msg.payload));
} else if (msg.topic === "sensor.solmate_live_battery_state") {
    context.set("batteryState", Number(msg.payload));
} else if (msg.topic === "sensor.epex_spot_data_quantile") {
    context.set("epexQuantile", Number(msg.payload));
}

// Retrieve stored values
const remainingProduction = context.get("remainingProduction");
const batteryState = context.get("batteryState");
const epexQuantile = context.get("epexQuantile");

// Ensure all values are available
if (remainingProduction !== undefined && batteryState !== undefined && epexQuantile !== undefined) {
    // Calculate buffer-adjusted threshold
    const unchargedPart = 1.4 - batteryState; // battery state 0 (empty) to 1.4 (full) in kWh
    const energyThreshold = unchargedPart + BUFFER;

    // Condition: Remaining solar energy must exceed the adjusted threshold or EPEX >= 0.8
    if (remainingProduction > energyThreshold || epexQuantile >= 0.8) {
        return { payload: true, topic: "max_power_mode" };
    } else {
        return { payload: false, topic: "max_power_mode" };
    }
}

// If any data is missing, do nothing
return null;

The second function takes the output of the first function and the current energy consumption to calculate the injection value.

// Configuration
const DEFAULT_INJECTION = 105;   // Default injection value
const MAX_POWER_PERCENTAGE = 0.85; // Injection percentage in max power mode
const MAX_LIMIT = 800;          // Maximum injection limit

// Store incoming values in context
if (msg.topic === "sensor.total_power_usage") {
    context.set("totalPowerUsage", Number(msg.payload));
} else if (msg.topic === "max_power_mode") {
    context.set("maxPowerMode", msg.payload === true || msg.payload === "true");
}

// Retrieve stored values
const totalPowerUsage = context.get("totalPowerUsage");
const maxPowerMode = context.get("maxPowerMode");

// Ensure all required values are available
if (totalPowerUsage !== undefined && maxPowerMode !== undefined) {
    let newInjection;

    if (maxPowerMode) {
        newInjection = Math.min(totalPowerUsage * MAX_POWER_PERCENTAGE, MAX_LIMIT);
    } else {
        newInjection = DEFAULT_INJECTION;
    }

    // Only send value if it has changed
    const previousInjection = context.get("previousInjection");

    if (newInjection !== previousInjection) {
        context.set("previousInjection", newInjection);
        return [
            { 
            topic: "eet/number/solmate/user_minimum_injection", 
            payload: String(newInjection) 
            },
            { 
           topic: "eet/number/solmate/user_maximum_injection", 
           payload: String(newInjection) 
            }
        ];
    }
}

// If any required data is missing, do nothing
return null;

This output gets fed into a MQTT OUT Node set to:

  • server: mqtt://localhost
  • port: 1883
  • protocol: MQTT V5
  • User and PW set correct
  • topic: empty as it is defined in function two
  • QoS: 0
  • retain: true

Is there anything I missed or misunderstood? Maybe something ChatGPT got wrong and I couldn’t find (limited IT knowledge).

I am grateful for any help.

Have a great day,
Georg

Hi,

I figured it out (with the help of a friend).
First function was fine.

Corrections:

  • Send payload as intager
  • reduce min by one so tit is smaller than max
  • create two outputs to the second function and a dedicated MQTT out node for min and max.

Second function:

// Configuration
const DEFAULT_INJECTION = 105;   // Default injection value
const MAX_POWER_PERCENTAGE = 0.85; // Injection percentage in max power mode
const MAX_LIMIT = 800;          // Maximum injection limit

// Store incoming values in context
if (msg.topic === "sensor.total_power_usage") {
    context.set("totalPowerUsage", Number(msg.payload));
} else if (msg.topic === "max_power_mode") {
    context.set("maxPowerMode", msg.payload === true || msg.payload === "true");
}

// Retrieve stored values
const totalPowerUsage = context.get("totalPowerUsage");
const maxPowerMode = context.get("maxPowerMode");

// Ensure all required values are available
if (totalPowerUsage !== undefined && maxPowerMode !== undefined) {
    let newInjection;

    if (maxPowerMode) {
        newInjection = Math.min(totalPowerUsage * MAX_POWER_PERCENTAGE, MAX_LIMIT);
    } else {
        newInjection = DEFAULT_INJECTION;
    }

    // Only send value if it has changed
    const previousInjection = context.get("previousInjection");

    if (newInjection !== previousInjection) {
        context.set("previousInjection", newInjection);
        return [
            { 
            topic: "eet/number/solmate/user_minimum_injection", 
            payload: Math.floor(newInjection - 1) 
            },
            { 
            topic: "eet/number/solmate/user_maximum_injection", 
            payload: Math.floor(newInjection) 
            }
        ];
    }
}

// If any required data is missing, do nothing
return null;


Have a great day,
Georg