Graph of used Solar Energy

Use this forum to discuss possible implementation of a new feature before opening a ticket.
A developer shall edit the topic title with "[xxx]" where xxx is the id of the accompanying tracker id.
Duplicate posts about the same id. +1 posts are not allowed.

Moderators: leecollings, remb0

Post Reply
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Graph of used Solar Energy

Post by jslegers »

Hi,

Is it possible to create an extra graph that shows how many power is used from the solar panels. We see the total generation. We also see the total returned energy. So if we can have a nice graph of those two values subtracted.

John
User avatar
gizmocuz
Posts: 3026
Joined: Thursday 11 July 2013 18:59
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Top of the world
Contact:

Re: Graph of used Solar Energy

Post by gizmocuz »

There are two ways you could implement this.

- Write a dzVents script (see below, not tested!)
- Write a custom template file to display this (there are examples in the www/templates folder)

Code: Select all

-- Solar Self-Consumption Calculator
-- Shows how much solar energy was actually used in the house
-- Formula: Self-Consumed = Solar Generation - Returned to Grid
--
-- SETUP REQUIRED:
--   1. In Domoticz: Setup > Hardware > add "Dummy" hardware (if not present)
--   2. Create a virtual sensor: type "Electric (Instant+Counter)" — note its idx
--   3. Fill in the three idx values below

local IDX_GENERATION    = 0   -- idx of your solar generation device (kWh counter)
local IDX_RETURN        = 0   -- idx of your return-to-grid device (kWh counter)
local IDX_SELF_CONSUMED = 0   -- idx of the new virtual kWh device you just created

return {
    on = {
        devices = { IDX_GENERATION, IDX_RETURN },
        timer   = { 'every 5 minutes' },
    },

    logging = {
        level  = domoticz.LOG_INFO,
        marker = 'Solar Self-Consumption',
    },

    execute = function(domoticz, item)
        local gen  = domoticz.devices(IDX_GENERATION)
        local ret  = domoticz.devices(IDX_RETURN)
        local virt = domoticz.devices(IDX_SELF_CONSUMED)

        if not gen or not ret or not virt then
            domoticz.log('One or more device idx values are not configured correctly', domoticz.LOG_ERROR)
            return
        end

        -- Current power in Watt (clamp to 0 — can't be negative)
        local power_w = math.max(0, gen.usage - ret.usage)

        -- Cumulative counter in kWh (clamp to 0)
        -- WhTotal is in Wh, updateElectricity expects kWh for the counter
        local energy_kwh = math.max(0, (gen.WhTotal - ret.WhTotal) / 1000)

        domoticz.log(string.format(
            'Generation: %.0f W / %.2f kWh  |  Return: %.0f W / %.2f kWh  |  Self-consumed: %.0f W / %.2f kWh',
            gen.usage, gen.WhTotal / 1000,
            ret.usage, ret.WhTotal / 1000,
            power_w, energy_kwh
        ))

        virt.updateElectricity(power_w, energy_kwh)
    end,
}
Quality outlives Quantity!
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

Thanks for the heads up.

I needed some assistance from Claude AI to fix the script but it works. Will test it for a couple of days.

Updated script.

Code: Select all

local IDX_GENERATION    = 49  -- GoodWe Inverter - Today's Generation (General/kWh)
local IDX_P1            = 1   -- P1 Smart Meter - Power (P1 Smart Meter/Energy)
local IDX_SELF_CONSUMED = 56  -- Virtual kWh device for self-consumption

return {
    on = {
        devices = { IDX_GENERATION, IDX_P1 },
        timer   = { 'every 5 minutes' },
    },
    logging = {
        level  = domoticz.LOG_INFO,
        marker = 'Solar Self-Consumption',
    },
    execute = function(domoticz, item)
        local gen  = domoticz.devices(IDX_GENERATION)
        local p1   = domoticz.devices(IDX_P1)
        local virt = domoticz.devices(IDX_SELF_CONSUMED)

        if not gen or not p1 or not virt then
            domoticz.log('One or more device idx values are not configured correctly', domoticz.LOG_ERROR)
            return
        end

        -- Current power: generation minus what's being returned to grid
        local power_w = math.max(0, gen.WhActual - p1.usageDelivered)

        -- Cumulative today: kWh generated minus kWh returned today
        local energy_kwh = math.max(0, gen.WhTotal / 1000 - p1.counterDeliveredToday)

        domoticz.log(string.format(
            'Generation: %.0f W / %.3f kWh  |  Return: %.0f W / %.3f kWh  |  Self-consumed: %.0f W / %.3f kWh',
            gen.WhActual, gen.WhTotal / 1000,
            p1.usageDelivered, p1.counterDeliveredToday,
            power_w, energy_kwh
        ))

        virt.updateElectricity(power_w, energy_kwh)
    end,
}
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

Hi,

Small update but still having a small issue. After quite some sessions with claude ai because I had some issues with my previous script I came up with the following script :

Code: Select all

local IDX_GOODWE        = 50  -- GoodWe Inverter Solar (General/kWh)
local IDX_P1            = 1   -- P1 Smart Meter - Power (P1 Smart Meter/Energy)
local IDX_SELF_CONSUMED = 56  -- Virtual kWh device for self-consumption

local function parseKwh(val)
    if type(val) == 'number' then return val end
    return tonumber(tostring(val):match('[%d%.]+')) or 0
end

return {
    on = {
        timer = { 'every 1 minutes' },
    },
    logging = {
        level  = domoticz.LOG_INFO,
        marker = 'Solar Self-Consumption',
    },
    execute = function(domoticz, item)
        local gen  = domoticz.devices(IDX_GOODWE)
        local p1   = domoticz.devices(IDX_P1)
        local virt = domoticz.devices(IDX_SELF_CONSUMED)

        if not gen or not p1 or not virt then
            domoticz.log('One or more device idx values are not configured correctly', domoticz.LOG_ERROR)
            return
        end

        local gen_kwh  = parseKwh(gen.counterToday)
        local ret_kwh  = parseKwh(p1.counterDeliveredToday)
        local self_kwh = math.max(0, gen_kwh - ret_kwh)

        domoticz.log(string.format(
            'Generation today: %.3f kWh  |  Returned today: %.3f kWh  |  Self-consumed: %.3f kWh',
            gen_kwh, ret_kwh, self_kwh
        ), domoticz.LOG_INFO)

        virt.updateElectricity(0, self_kwh)
    end,
}
I have set it to 1 minute to test. In the log I see the following :

Code: Select all

2026-04-30 12:51:00.777  dzVents: Solar Self-Consumption: Generation today: 10.000 kWh  |  Returned today: 8.313 kWh  |  Self-consumed: 1.687 kWh
So looks like the script is working only it looks like it is not updating the dummy device the Today counter.

Image

What am I doing wrong I don't get it.
User avatar
waltervl
Posts: 7020
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2026.3
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by waltervl »

You are missing a factor 1000 as a general kWh device needs its value in Wh, not kWh.
But this general kWh device also need this Wh value to be a running increasing total counter, not a daily resetting to 0 value.

You better change it to a custom sensor with kWh value.
Edit: Or at 23.59 hours request the current total counter value and use that as a base to start the new day (total+(self_kwh*1000))
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

waltervl wrote: Thursday 30 April 2026 13:13 You are missing a factor 1000 as a general kWh device needs its value in Wh, not kWh.
But this general kWh device also need this Wh value to be a running increasing total counter, not a daily resetting to 0 value.

You better change it to a custom sensor with kWh value.
Edit: Or at 23.59 hours request the current total counter value and use that as a base to start the new day (total+(self_kwh*1000))
Thanks Walter for the answer. I will try it tonight.
So I need to change the line virt.updateElectricity(0, self_kwh) with virt.updateElectricity(0, self_kwh*1000)

My goal is indeed to start this script at 23:55.
User avatar
waltervl
Posts: 7020
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2026.3
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by waltervl »

I would trigger the script on every change of the goodwe inverter, not every minute (is also not needed).
And once on 23:55.
Then you can differ on trigger in your script, when:
- timer: read the total counter value and story it into a variable
- device: calculate the self_kwh and update the counter ( with total counter+self_kwh)

See for example https://wiki.domoticz.com/DzVents:_next ... ined_rules
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

Hi,

Script looks ok but have one small issue. (Sorry I am not a programmer).
The next day it starts with a negative value. So looks like it is not reset.

How can I fix this?
User avatar
waltervl
Posts: 7020
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2026.3
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by waltervl »

That is because you probably did not follow my advise to use the total counter just before midnight and add that to the daily self_kwh value you get from your device.

If you do not do that the counter will start at 0 and domoticz will interpret that as a negative value from the day before.....
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

I have setup some sensors. I will let it run for a week to see what happens. I let it run every day at 23:50. Via telegram I also get the values so the script runs. After a couple of days i will check if it works.
Hopefully it works.
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

Hi guys,

I am still testing. Still not getting the correct dummy device but still testing.
I will keep you updated.

John
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

I still have issues with storing the data. And I can't figure it out anymore.

Ok I have created the following development script.

Code: Select all

return {
    on = {
        timer = {
            'at 23:50'
        }
    },
    logging = {
        level = domoticz.LOG_INFO,
        marker = 'CounterReader'
    },
    execute = function(domoticz, timer)
        local P1 = domoticz.devices(1)
        local GoodWe = domoticz.devices(50)

        if not P1 then
            domoticz.log('Device with IDX 1 not found!', domoticz.LOG_ERROR)
            return
        end

        if not GoodWe then
            domoticz.log('Device with IDX 50 not found!', domoticz.LOG_ERROR)
            return
        end

        local deliveryToday = P1.counterDeliveredToday
        local generatedToday = GoodWe.counterToday
        local resultToday = generatedToday - deliveryToday
        
        local dailyUsage = domoticz.devices(56)  -- your new dummy device IDX

        if not dailyUsage then
            domoticz.log('Dummy device IDX 56 not found!', domoticz.LOG_ERROR)
            return
        end

        local dailyUsage2 = domoticz.devices(57)  -- your new dummy device IDX

        if not dailyUsage2 then
            domoticz.log('Dummy device IDX 57 not found!', domoticz.LOG_ERROR)
            return
        end
        
        local dailyUsage3 = domoticz.devices(58)  -- your new dummy device IDX

        if not dailyUsage3 then
            domoticz.log('Dummy device IDX 58 not found!', domoticz.LOG_ERROR)
            return
        end

       local dailyUsage4 = domoticz.devices(59)
       
        if not dailyUsage4 then
            domoticz.log('Dummy device IDX 59 not found!', domoticz.LOG_ERROR)
            return
        end

-- resultToday is in kWh, store directly (no *1000 needed for Custom Sensor)
        dailyUsage4.updateCustomSensor(resultToday)

        dailyUsage.updateCounter(resultToday*1000)
        dailyUsage2.updateElectricity(0, resultToday*1000)
        dailyUsage3.updateCounter(resultToday*1000)

        domoticz.log('CounterDeliveredToday IDX 1: ' .. tostring(deliveryToday) .. ' kWh', domoticz.LOG_INFO)
        domoticz.log('CounterToday IDX 50: ' .. tostring(generatedToday) .. ' kWh', domoticz.LOG_INFO)
        domoticz.log('Result: ' .. tostring(resultToday) .. ' kWh', domoticz.LOG_INFO)

        domoticz.notify(
            'Daily Usage Update',
            'The daily calculation result is: ' .. tostring(resultToday),
            domoticz.PRIORITY_NORMAL,
            nil,
            {domoticz.NSS_TELEGRAM}
        )
    end
}
The script calculation is working fine. I only have an issue with storing the issue on a dummy device.

I have created the following dummy devices :

Image

But none of the show the correct history :

Device 56
Image

Device 59
Image

These are the results that should be there :

5-6 : 6.232
4-6 : 3.746
3-6 : 5.779
2-6 : 5.28

I don't get what I am doing wrong. I just start the script at 23:50
Am I using the wrong dummy device?

Sorry I wanted to upload all the dummy's I had but was limit to 4 so In my next post there are the dummy switches.
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

Device 56
Image

Device 57
Image

Device 58
Image

Device 59
Image
jslegers
Posts: 56
Joined: Tuesday 23 February 2016 9:14
Target OS: Raspberry Pi / ODroid
Domoticz version: 2026.2
Location: NL
Contact:

Re: Graph of used Solar Energy

Post by jslegers »

Ok I have changed the script and will try a custom sensor again. Below is my cleaned up script.

Code: Select all

return {
    on = {
        timer = {
            'at 23:50'
        }
    },
    logging = {
        level = domoticz.LOG_INFO,
        marker = 'CounterReader'
    },
    execute = function(domoticz, timer)

        local P1 = domoticz.devices(1)
        local GoodWe = domoticz.devices(50)
        local dailyUsage = domoticz.devices(56)

        if not P1 then
            domoticz.log('Device with IDX 1 not found!', domoticz.LOG_ERROR)
            return
        elseif not GoodWe then
            domoticz.log('Device with IDX 50 not found!', domoticz.LOG_ERROR)
            return
        elseif not dailyUsage then
            domoticz.log('Dummy device IDX 56 not found!', domoticz.LOG_ERROR)
            return
        end

        local deliveryToday = P1.counterDeliveredToday
        local generatedToday = GoodWe.counterToday
        local resultToday = math.max(0, (generatedToday - deliveryToday) * 1000)
        
        dailyUsage.updateCustomSensor(resultToday)

        domoticz.log('CounterDeliveredToday IDX 1: ' .. tostring(deliveryToday) .. ' kWh', domoticz.LOG_INFO)
        domoticz.log('CounterToday IDX 50: ' .. tostring(generatedToday) .. ' kWh', domoticz.LOG_INFO)
        domoticz.log('Result: ' .. tostring(resultToday) .. ' kWh', domoticz.LOG_INFO)

        domoticz.notify(
            'Daily Usage Update',
            'The daily calculation result is: ' .. tostring(resultToday),
            domoticz.PRIORITY_NORMAL,
            nil,
            {domoticz.NSS_TELEGRAM}
        )
    end
}
I will keep you informed.
Post Reply