Currently I use the code below to calculate the consumption.
Code: Select all
--[[
This script collects the values below from Domoticz
* The Power and energy values (import and export) from a smartmeter
* The Power and energy values from a Solar power inverter
It then calculates the (average) consumed power and energy from the values above with the formula's
* EnergyConsumption = EnergyGeneration + EnergyImport - EnergyExport
* PowerConsumption = PowerGeneration + PowerImport - PowerExport
The average power is calculated because it fluctuates much and can cause negative consumption due to timing issues.
It then updates a virtual device which displays the consumed power and energy in Domoticz
The base of this scrip comes from
https://www.domoticz.com/forum/viewtopic.php?f=61&t=4714&p=251778#p251778
]]--
local smartMeterIDX = 10-- IDX of Smart meter device
local solarPanelsIDX = 20 -- IDX of Solar Panels device
local consumptionIDX = 30 -- IDX of Own Usage / calculated value / dummy Elekta kWh + counter
return {
active = true,
on =
{
devices =
{
-- Devices on which this calculation script should trigger.
smartMeterIDX,
solarPanelsIDX,
}
},
logging =
{
--level = domoticz.LOG_DEBUG,
level = domoticz.LOG_ERROR,
marker = 'Consumption',
},
data =
{
PowerImportHistory = { history = true, maxMinutes = 4 },
PowerExportHistory = { history = true, maxMinutes = 4 },
PowerGenerationHistory = { history = true, maxItems = 24 },
},
execute = function(dz, item)
----------------------------------------------------------------------------------------------------------
-- Domoticz IDX of the needed devices
----------------------------------------------------------------------------------------------------------
local Smartmeter = dz.devices(smartMeterIDX)
local Generation = dz.devices(solarPanelsIDX)
local Consumption = dz.devices(consumptionIDX)
----------------------------------------------------------------------------------------------------------
-- Smartmeter
----------------------------------------------------------------------------------------------------------
-- Energy import and export
local EnergyImportLow = Smartmeter.usage1
dz.log('EnergyImportLow = ' .. EnergyImportLow/1000 .. ' kWh ', dz.LOG_DEBUG)
local EnergyImportHigh = Smartmeter.usage2
dz.log('EnergyImportHigh = ' .. EnergyImportHigh/1000 .. ' kWh ', dz.LOG_DEBUG)
local EnergyExportLow = Smartmeter.return1
dz.log('EnergyExportLow = ' .. EnergyExportLow/1000 .. ' kWh ', dz.LOG_DEBUG)
local EnergyExportHigh = Smartmeter.return2
dz.log('EnergyExportHigh = ' .. EnergyExportHigh/1000 .. ' kWh ', dz.LOG_DEBUG)
local EnergyImport = EnergyImportLow + EnergyImportHigh
local EnergyExport = EnergyExportLow + EnergyExportHigh
-- Power import and export
-- Add new data for calculating average
if item == Smartmeter then
dz.data.PowerImportHistory.add(Smartmeter.usage)
dz.data.PowerExportHistory.add(Smartmeter.usageDelivered)
end
----------------------------------------------------------------------------------------------------------
-- Generation
----------------------------------------------------------------------------------------------------------
-- Energy generated
local EnergyGeneration = Generation.WhTotal
dz.log('EnergyGeneration = ' .. EnergyGeneration .. ' Wh ', dz.LOG_DEBUG)
-- Power generated
-- Add new data for calculating average
if item == Generation then
dz.data.PowerGenerationHistory.add(Generation.actualWatt)
end
----------------------------------------------------------------------------------------------------------
-- Check historical storage entries
----------------------------------------------------------------------------------------------------------
if dz.data.PowerImportHistory.size < 3 or dz.data.PowerGenerationHistory.size < 3 then
dz.log('Not enough data points yet to produce something useful', dz.LOG_DEBUG)
dz.log('PowerImportHistory entries = ' .. dz.data.PowerImportHistory.size, dz.LOG_DEBUG)
dz.log('PowerGeneration entries = ' .. dz.data.PowerGenerationHistory.size, dz.LOG_DEBUG)
return
end
----------------------------------------------------------------------------------------------------------
-- Calculate
----------------------------------------------------------------------------------------------------------
-- Average power generated
local PowerGeneration = dz.utils.round(dz.data.PowerGenerationHistory.avgSince('00:02:00'), 2)
dz.log('PowerGeneration = ' .. PowerGeneration .. ' W ', dz.LOG_DEBUG)
-- Average power imported and exported
local PowerImport = dz.utils.round(dz.data.PowerImportHistory.avgSince('00:02:00'), 2)
dz.log('PowerImport = ' .. PowerImport .. ' W ', dz.LOG_DEBUG)
local PowerExport = dz.utils.round(dz.data.PowerExportHistory.avgSince('00:02:00'), 2)
dz.log('PowerExport = ' .. PowerExport .. ' W ', dz.LOG_DEBUG)
-- Power consumption
local PowerConsumption = dz.utils.round(PowerGeneration + PowerImport - PowerExport, 0)
dz.log('PowerConsumption = ' .. PowerConsumption .. ' W ', dz.LOG_DEBUG)
----------------------------------------------------------------------------------------------------------
-- Debug for negative power consumption
----------------------------------------------------------------------------------------------------------
if PowerConsumption < 0 then
dz.log('(NEGATIVE) PowerConsumption = PowerGeneration + PowerImport - PowerExport', dz.LOG_INFO)
dz.log('' .. PowerConsumption .. ' W = ' .. PowerGeneration .. ' W + ' .. PowerImport .. ' W - ' .. PowerExport, dz.LOG_INFO)
dz.log('PowerConsumption set to 0', dz.LOG_INFO)
local PowerConsumption = 0
else
dz.log('PowerConsumption = PowerGeneration + PowerImport - PowerExport', dz.LOG_INFO)
dz.log('' .. PowerConsumption .. ' W = ' .. PowerGeneration .. ' W + ' .. PowerImport .. ' W - ' .. PowerExport, dz.LOG_INFO)
end
-- Energy consumption
local EnergyConsumption = dz.utils.round(EnergyGeneration + EnergyImport - EnergyExport, 0)
dz.log('EnergyConsumption = ' .. EnergyConsumption/1000 .. ' kWh ', dz.LOG_DEBUG)
----------------------------------------------------------------------------------------------------------
-- Update device
----------------------------------------------------------------------------------------------------------
Consumption.updateElectricity(PowerConsumption, EnergyConsumption)
end
}
and the code below to post the data to PVoutput.
Code: Select all
-- The base of this scrip comes from
-- https://www.domoticz.com/forum/viewtopic.php?f=61&t=4714&p=251778#p251778
-- https://www.domoticz.com/forum/viewtopic.php?f=59&t=28056&p=261029#p261029
local scriptVar = 'PVOutput'
return {
on = {
timer = { 'every 1 minutes'},
httpResponses = { scriptVar },
},
logging = {
level = domoticz.LOG_INFO,
-- level = domoticz.LOG_DEBUG,
marker = scriptVar
},
execute = function(dz, item)
local function post2PVOutput(PVSettings, postData)
dz.openURL({
url = PVSettings.url,
method = 'POST',
headers = {
['X-Pvoutput-Apikey'] = PVSettings.api,
['X-Pvoutput-SystemId'] = PVSettings.id
},
callback = scriptVar,
postData = postData
})
end
local function makepostData()
----------------------------------------------------------------------------------------------------------
-- Domoticz IDX of the needed devices
----------------------------------------------------------------------------------------------------------
local Solar = dz.devices(10) -- (v1+v2) IDX of Solar Panels
local Consumption = dz.devices(20) -- (v3+v4) IDX of Consumption device (from consumption.lua script)
local Temperature = dz.devices(30) -- (v5) IDX of outside temp device
local Voltage = dz.devices(40) -- (v6) IDX of a device with a Voltage value
local c1 = 1 -- (c1) Cumulative Flag. c1 = 0 when v1 is today's energy. c1 = 1 when v1 is lifetime energy.
local n = 0 -- (n) Net Flag. n = 0 is default, n = 1 When the net export/import and generation/consumption data is uploaded separately
--local Water = dz.devices(50) -- (v7) IDX of the water consumption
local InverterFrequency = dz.devices(60) -- (v8) IDX of the inverter frequency
local InverterVoltage = dz.devices(70) -- (v9) IDX of the inverter temperature
local InverterCurrent = dz.devices(80) -- (v10) IDX of the inverter current
local InverterTemperature = dz.devices(90) -- (v11) IDX of the inverter temperature
local Gas = dz.devices(100) -- (v12) IDX of Smart Gas Meter
local round = dz.utils.round
dz.log('-- Energy generation (v1) = ' .. Solar.WhTotal/1000 .. ' Wh ', dz.LOG_DEBUG)
dz.log('-- Power generation (v2) = ' .. Solar.actualWatt .. ' W ', dz.LOG_DEBUG)
dz.log('-- Energy consumption (v3) = ' .. Consumption.WhTotal/1000 .. ' Wh ', dz.LOG_DEBUG)
dz.log('-- Power consumption (v4) = ' .. Consumption.actualWatt .. ' W ', dz.LOG_DEBUG)
dz.log('-- Temperature (v5) = ' .. round(Temperature.temperature,1) .. ' C ', dz.LOG_DEBUG)
dz.log('-- Voltage (v6) = ' .. round(Voltage.voltage,1) .. ' V ', dz.LOG_DEBUG)
dz.log('-- c1 = ' .. c1 .. ' ', dz.LOG_DEBUG)
dz.log('-- n = ' .. n .. ' ', dz.LOG_DEBUG)
--dz.log('-- Water (v7) = ' .. Water.counterToday .. ' l ', dz.LOG_DEBUG)
dz.log('-- Inverter Frequency FAC (v8) = ' .. InverterFrequency.rawData[1] .. ' Hz ', dz.LOG_DEBUG)
dz.log('-- Inverter voltage VAC (v9) = ' .. round(InverterVoltage.voltage,1) .. ' V ', dz.LOG_DEBUG)
dz.log('-- Inverter current UAC (v10) = ' .. InverterCurrent.rawData[1] .. ' A ', dz.LOG_DEBUG)
dz.log('-- Inverter Temperature (v11) = ' .. round(InverterTemperature.temperature,1) .. ' C ', dz.LOG_DEBUG)
dz.log('-- Gas (v12) = ' .. Gas.counterToday .. ' m3 ', dz.LOG_DEBUG)
local postdDataAsString =
--[[
v1 - energy generation
v2 - power generation
v3 - energy consumption
v4 - power consumption
v5 - Temperature
v6 - Voltage
v7 - Water Consumption in l
v8 - Frequency (FAC)
v9 - Voltage (VAC)
v10 - Current (IAC)
v11 - Inverter Temperature
v12 - Gas Consumption
]] --
'd=' .. os.date("%Y%m%d") ..
'&t=' .. os.date("%H:%M") ..
'&v1=' .. Solar.WhTotal ..
'&v2=' .. Solar.actualWatt ..
'&v3=' .. Consumption.WhTotal ..
'&v4=' .. Consumption.actualWatt ..
'&v5=' .. round(Temperature.temperature,1) ..
'&v6=' .. round(Voltage.voltage,1) ..
'&c1=' .. c1 ..
'&n=' .. n ..
--'&v7=' .. Water.counterToday ..
'&v8=' .. InverterFrequency.rawData[1] ..
'&v9=' .. round(InverterVoltage.voltage,1) ..
'&v10=' .. InverterCurrent.rawData[1] ..
'&v11=' .. round(InverterTemperature.temperature,1) ..
'&v12=' .. Gas.counterToday
return postdDataAsString
end
if item.isHTTPResponse then
if item.statusText=='OK' then
dz.log("Data successfully added to PVoutput")
else
dz.log("Error: the return from PVOutput was : " .. item.data,dz.LOG_ERROR)
end
else
PVSettings =
{
url = 'HTTPS://pvoutput.org/service/r2/addstatus.jsp',
api = dz.variables('PVoutput_API').value,
id = dz.variables('PVoutput_ID').value,
}
post2PVOutput(PVSettings, makepostData())
end
end
}