I have overhauled the car charging script.
My personal script uses data from the Volvo plugin.
This simplified version relies on just the Power data from P1, a selector Switch and has a text sensor output which gives you insight in the charging situation.

- car charging.png (9.2 KiB) Viewed 246 times
The nice thing about this version is that it has an adaptable buffer for switching.
This is to prevent selecting another level too often when the solar power changes.
Code: Select all
-- Helper functions
local function spaces(count)
return string.rep(" ", count)
end
return {
on = {
timer = {'every 1 minutes', },
},
logging = {
level = domoticz.LOG_DEBUG,
marker = 'Simple EV Charging on House Power'
},
data = {
desiredLevel = { initial = 'Off' },
powerLevels = { initial = {
['16A'] = 3700,
['13A'] = 3000,
['10A'] = 2300,
['8A'] = 1850,
['6A'] = 1400,
Off = 0
}},
upBuffer = { initial = 200 }, -- Buffer for switching up
downBuffer = { initial = 200 }, -- Buffer for switching down
},
execute = function(domoticz, triggeredItem)
-- Start de timer om de uitvoeringstijd te meten
local startTime = os.clock()
-- Basisgegevens ophalen
local ChargingSwitchState = domoticz.devices('Charging Level').levelName
local EVSE_Connected = domoticz.globalData.EVSE_Connected
local newLevel = 'Off'
-- Huidig vermogen van de laadpaal bepalen
local PowerLaadpaal = domoticz.data.powerLevels[ChargingSwitchState] or 0
-- Power gegevens ophalen
local PowerReturn = tonumber(domoticz.devices('Power').rawData[6]) -- Terug naar het net
local PowerConsumption = tonumber(domoticz.devices('Power').rawData[5]) -- Verbruik
local availableEnergy = PowerLaadpaal + PowerReturn - PowerConsumption
-- Logging
domoticz.log('#1 EVSE connected: ' .. domoticz.globalData.EVSE_Connected, domoticz.LOG_DEBUG)
domoticz.log('#2 Energy usage from the network: ' .. PowerConsumption, domoticz.LOG_DEBUG)
domoticz.log('#3 Energy return to the network: ' .. PowerReturn, domoticz.LOG_DEBUG)
domoticz.log('#4 Actual power on laadpaal: ' .. PowerLaadpaal, domoticz.LOG_DEBUG)
domoticz.log('#5 Available energy: ' .. availableEnergy, domoticz.LOG_DEBUG)
-- Auto is niet aangesloten, zorg dat laadniveau uit staat
if EVSE_Connected ~= 'Connected' then
if domoticz.devices('Charging Level').levelName ~= 'Off' then
domoticz.devices('Charging Level').switchSelector('Off')
domoticz.log('#6 Charging Level switched Off because car is no longer connected', domoticz.LOG_DEBUG)
end
end
-- Alleen uitvoeren als de auto is aangesloten
if EVSE_Connected == 'Connected' then
-- Bepaal het gewenste laadniveau op basis van beschikbare energie
local currentLevel = domoticz.devices('Charging Level').levelName
domoticz.log('#7 currentLevel : ' .. currentLevel, domoticz.LOG_DEBUG)
-- Get current power level
local currentLevel = domoticz.devices('Charging Level').levelName
local currentPower = domoticz.data.powerLevels[currentLevel] or 0
-- Kies het juiste niveau met buffer
newLevel = currentLevel -- Start with current level as default
-- Sort power levels for ordered comparison
local sortedLevels = {}
for level, power in pairs(domoticz.data.powerLevels) do
if level ~= 'Off' then
table.insert(sortedLevels, {level = level, power = power})
end
end
table.sort(sortedLevels, function(a, b) return a.power < b.power end)
-- Check if we need to switch down
if currentLevel ~= 'Off' then
local needLowerLevel = true
for i, levelData in ipairs(sortedLevels) do
if levelData.level == currentLevel then
-- Check if current level is still acceptable with downBuffer
if availableEnergy >= (levelData.power - domoticz.data.downBuffer) then
needLowerLevel = false
break
end
end
end
if needLowerLevel then
-- Find the highest level that fits with available energy
newLevel = 'Off'
for i, levelData in ipairs(sortedLevels) do
if availableEnergy >= levelData.power then
newLevel = levelData.level
end
end
end
end
-- Check if we can switch up
if currentLevel == 'Off' then
-- If currently off, use normal threshold to turn on
for i, levelData in ipairs(sortedLevels) do
if availableEnergy >= levelData.power then
newLevel = levelData.level
end
end
else
-- If already on, check if we can go higher with upBuffer
for i = #sortedLevels, 1, -1 do
local levelData = sortedLevels[i]
if levelData.power > currentPower and availableEnergy >= (levelData.power + domoticz.data.upBuffer) then
newLevel = levelData.level
break
end
end
end
domoticz.log('#8 newLevel : ' .. newLevel, domoticz.LOG_DEBUG)
-- Update het laadniveau als het anders is
if domoticz.devices('Charging Level').levelName ~= newLevel then
domoticz.devices('Charging Level').switchSelector(newLevel)
domoticz.log('#9 Updated charging level to: ' .. newLevel, domoticz.LOG_DEBUG)
end
-- Stuur alleen een notificatie als het niveau is veranderd
if domoticz.devices('Charging Level').levelName ~= currentLevel then
local current_time = os.date('%d-%m-%Y %H:%M')
local subject, message
if newLevel == 'Off' and currentLevel ~= 'Off' then
subject = '@2 Charging ended'
message = newLevel ..', Energy : ' .. availableEnergy .. '\nTime : ' .. current_time
domoticz.notify(subject, message, domoticz.PRIORITY_NORMAL)
domoticz.log('#10 Notification sent: ' .. subject, domoticz.LOG_DEBUG)
elseif newLevel ~= 'Off' and (currentLevel == 'Off' or currentLevel ~= newLevel) then
subject = '@3 Charging'
message = newLevel .. ', Energy : ' .. availableEnergy .. '\nTime : ' .. current_time
domoticz.notify(subject, message, domoticz.PRIORITY_NORMAL)
domoticz.log('#11 Notification sent: ' .. subject, domoticz.LOG_DEBUG)
end
end
else
domoticz.log('#12 Car not connected. Script not controlling charging.', domoticz.LOG_DEBUG)
end
-- Tekst sensor bijwerken
local modeText = "Automatic"
-- Determine Home Power (Usage or Return)
local homePowerText
if PowerConsumption > 0 then
homePowerText = string.format("Home Power Usage: %d W", PowerConsumption)
else
homePowerText = string.format("Home Power Return: %d W", PowerReturn)
end
-- Get the theoretical power and Amps for the current charging level
local levelText
local currentLevel = domoticz.devices('Charging Level').levelName
if currentLevel == 'Off' then
levelText = "Off" -- Just 'Off' without the 'Level:' prefix
else
local theoreticalPower = domoticz.data.powerLevels[currentLevel]
levelText = string.format("%d W (%s)", theoreticalPower, currentLevel)
end
-- Format the display text
local displayText = string.format(
"Control Mode: %s\n" ..
"%s\n" ..
"Available Power: %d W\n" ..
"Charging Level: %s",
modeText,
homePowerText,
availableEnergy,
levelText -- Now just the value (e.g., 'Off' or '2300 W (10A)')
)
-- Update the text sensor
domoticz.devices('Car Charging Actual').updateText(displayText)
-- Stop de timer en bereken de uitvoeringstijd
local executionTime = os.clock() - startTime
-- Voeg de uitvoeringstijd toe aan scriptExecutionTime_car_charge
domoticz.globalData.scriptExecutionTime_car_charge.add(executionTime)
-- Log de uitvoeringstijd
domoticz.log('Uitvoeringstijd van het Simple EV Charging on House Power script: ' .. executionTime .. ' seconden', domoticz.LOG_DEBUG)
end
}
The switching logic for the selector relies on this script
Code: Select all
return {
on = {
devices = {'Charging Level'},
},
logging = {
level = domoticz.LOG_ERROR,
marker = '---- Charging Level Selector Switch -----',
},
execute = function(domoticz, device)
local level = device.level
domoticz.log('#1 Current charging level: ' .. level, domoticz.LOG_DEBUG)
local powerLevels = {
[0] = { name = 'Off', current = 0, mode = 'Off' },
[10] = { name = '6A', current = 60, mode = 'Normal' },
[20] = { name = '8A', current = 80, mode = 'Normal' },
[30] = { name = '10A', current = 100, mode = 'Normal' },
[40] = { name = '13A', current = 130, mode = 'Normal' },
[50] = { name = '16A', current = 160, mode = 'Normal' }
}
local levelSettings = powerLevels[level]
if not levelSettings then
domoticz.log('Unknown charging level: ' .. level, domoticz.LOG_ERROR)
return
end
-- MQTT broker settings
local broker = "192.168.2.104"
-- Send current override command
domoticz.executeShellCommand({
command = 'mosquitto_pub -h ' .. broker .. ' -t "SmartEVSE/Set/CurrentOverride" -m ' .. levelSettings.current,
callback = function(exitStatus, output)
if exitStatus ~= 0 then
domoticz.log('Failed to set current: ' .. tostring(output), domoticz.LOG_ERROR)
end
end
})
-- Send mode command
domoticz.executeShellCommand({
command = 'mosquitto_pub -h ' .. broker .. ' -t "SmartEVSE/Set/Mode" -m ' .. levelSettings.mode,
callback = function(exitStatus, output)
if exitStatus ~= 0 then
domoticz.log('Failed to set mode: ' .. tostring(output), domoticz.LOG_ERROR)
end
end
})
-- Set LED color only if charging is turned off
if levelSettings.mode == 'Off' then
domoticz.executeShellCommand({
command = 'mosquitto_pub -h ' .. broker .. ' -t "SmartEVSE/Set/ColorOff" -m 0,250,0',
callback = function(exitStatus, output)
if exitStatus ~= 0 then
domoticz.log('Failed to set LED color: ' .. tostring(output), domoticz.LOG_ERROR)
end
end
})
end
domoticz.log('Charging set to: ' .. levelSettings.name, domoticz.LOG_DEBUG)
end
}
It uses MQTT to switch a SmartEVSE switch.
See how it handles available power.

- Usage-return.png (56.75 KiB) Viewed 119 times
Power

- PV power.png (34.74 KiB) Viewed 118 times
PV Power
Bugs bug me.