EV Charging and load balancing with P1 electricity meter  [Solved]

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

Post Reply
gehoel
Posts: 9
Joined: Thursday 05 March 2020 19:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

EV Charging and load balancing with P1 electricity meter

Post by gehoel »

Hello,

I wanted to ask something.

I have an EVSE-WiFi charging station for my new MG ZS EV.
What I want to do is:
I want to aks the EVSE-WiFi to give me al the information about its satus. http://192.168.x.x/getParameters
This JSON response looks like the screenshot.
EVSE-WiFi response.jpg
EVSE-WiFi response.jpg (23.95 KiB) Viewed 2501 times
{"type":"parameters","list":[{"vehicleState":1,"evseState":false,"maxCurrent":15,"actualCurrent":10,"actualPower":0,"duration":0,"alwaysActive":false,"lastActionUser":"GUI","lastActionUID":"GUI","energy":0,"mileage":0,"meterReading":0,"currentP1":0,"currentP2":0,"currentP3":0}]}

Meaning of the values:
vehicleState Vehicle state (ready 1/ detected 2/ charging 3)
evseState EVSE State (active/not active)
maxCurrent Maximum Current depending on PP-limit and
actualCurrent Actual configured current in A (e.g. 20A)
actualPower actual power consumption (when S0 meter is used)
duration charging duration in milliseconds
alwaysActive Always Active Mode enabled (true/false)
lastActionUser The user name of the user who performed the last action (activate/deactivate)
lastActionUID The UID of the user who performed the last action (activate/deactivate)
energy charged energy of the current charging process in kWh
mileage charged energy in km
meterReading actual meter reading in kWh
currentP1 actual current in A (phase 1)
currentP2 actual current in A (phase 2)
currentP3 actual current in A (phase 3)

I would be nice the create an virtual switch that changes according the state of the EV charging station.
The next goal is the get load balancing to work so that the total current drain from my household does not exceeds my connection to the grid.

The power measurement I do for my household is with the P1 smart Meter USB.
My idea is to calculate the actual current using the data from the P1 smart Meter USB.
Name.Type.Subtype - Name.Type.Subtype / Voltage
Usage L1.Usage.Electric - Delivery L1.Usage.Electric / 230 = Actual Current
With that actual current I can calculate the maximum current for my car charger.

The EVSE-WiFi has the option to work with an JSON request to set the max Current for that moment.
http://192.168.x.x/setCurrent?current=10 (in this example it will set the max to 10Amp)
I have tested this in an browser and this works.

The hole idea would be:
1. Check the EVSE-WiFi state every minute
2. When status changes to Charging, change virtual Switch
3. Update other virtual devices (electricity meter, Amp meter etc.)
4. Compare the actual total household current to an max. value of "x"
5. When that limit is reached lower the charging value with 1.
6. If there is room left raise the charging current with 1.
7. Keep the comparing on going until charging state is done.
8. After charging is done set max. value to X (so it never starts at is theoretical max.)

I'm an noob in writing an script, especially from scrap.
When I have some peaces of an script I can understand than and make small changes.

Would some like the help me to get this script working.
Greetings,
Bart
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by waaren »

gehoel wrote: Sunday 05 July 2020 13:28 I want to aks the EVSE-WiFi to give me al the information about its status. http://192.168.x.x/getParameters
I would be nice the create an virtual switch that changes according the state of the EV charging station.
The next goal is the get load balancing to work so that the total current drain from my household does not exceeds my connection to the grid.
A first version to test

Code: Select all

--[[

        script to dynamically change max loading amperage of vehicle based on house usage / delivery

]]

local scriptVar = 'evCharger'

return
{
    on =
    {
        timer =
        {
            'every minute',
        },

        devices =
        {
            'evTrigger' -- for test only
        },

        httpResponses =
        {
            scriptVar .. '_*' ,
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'evCharger',
    },

    execute = function(dz, item)

        -- enter you settings below this line

        local maxHouseCurrent = 15

        local chargingStationIP = '192.168.xxx.xxx'

        local evse = dz.devices('EVSEState') -- Selector switch with hidden Off level and levels 'Active' and 'not Active'
        local vehicle = dz.devices('vehicleState') -- Selector switch with hidden Off level and levels 'ready', 'detected' and 'charging'
        local evseCurrent = dz.devices('EVSECurrent') -- Ampere 1 phase
        local houseCurrent = dz.devices('houseCurrent') -- Ampere 1 phase

        local usage = dz.devices('Usage L1').actualWatt        -- smart meter usage electric
        local delivered = dz.devices('usageDelivered').actualWatt -- smart meter usage electric

        local testing = false

        -- no changes required below this line

        local getCall = 'getParameters'
        local setCall = 'setCurrent?current='

        local function sendURL(call, current)
            local url = 'http://' .. chargingStationIP .. '/' .. call .. (current or '')
            if testing then url
                   'http://dz:8084/json.htm?type=command&param=getversion'
            end
            dz.openURL(
            {
                url = url,
                callback = scriptVar .. '_' .. call,
            })
        end

        local function setCurrent(rt)
            dz.log('vehicleState: ' .. rt.vehiclState,dz.log_DEBUG )
            if rt.vehicleState == 'charging' then
                if rt.houseCurrent > maxHouseCurrent and rt.actualCurrent > 0 then
                    dz.log('decreasing',dz.log_DEBUG )
                    sendURL(setCall, rt.actualCurrent - 1 )
                elseif rt.houseCurrent < ( maxHouseCurrent - 1) and  rt.actualCurrent < ( rt.maxCurrent - 1 ) then
                    sendURL(setCall, rt.actualCurrent + 1)
                    dz.log('increasing',dz.log_DEBUG )
                end
            end
        end

        local function updateDevices(rt)
            -- set vehicleState
            vehicleStates = { 'ready','detected','charging'}
            local vehicleState =  vehicleStates[rt.vehicleState]
            if vehicle.state ~= vehicleState then
                vehicle.switchSelector(vehicleState)
            end

            -- set evseState
            if rt.evseState and evse.state ~= 'Active' then
                evse.switchSelector('Active')
            elseif not(rt.evseState) and evse.state ~= 'not Active' then
                evse.switchSelector('not Active')
            end

            -- set houseCurrent
            local current = dz.utils.round(( usage - delivered ) / 230 , 2)
            houseCurrent.updateCurrent(current)
            rt.houseCurrent = current

            -- set evseCurrent
            if evseCurrent.current ~= rt.actualCurrent then
                evseCurrent.updateCurrent(rt.actualCurrent)
            end
        end

        -- main
        if item.isTimer or item.isDevice then
           sendURL(getCall)
           return
        end

        -- handling response
        if item.isHTTPResponse and item.ok then
            if item.trigger:match('getParameters') then
                if testing then
                    local testJSON = '{"type":"parameters","list":[{"vehicleState":1,"evseState":false,"maxCurrent":15,"actualCurrent":10,"actualPower":0,"duration":0,"alwaysActive":false,"lastActionUser":"GUI","lastActionUID":"GUI","energy":0,"mileage":0,"meterReading":0,"currentP1":0,"currentP2":0,"currentP3":0}]}'
                    item.json = dz.utils.fromJSON(testJSON)
                end
                local rt = item.json.list[1]
                updateDevices(rt)
                setCurrent(rt)
            else
                dz.log('current successfully adjusted',dz.LOG_DEBUG)
            end
        else
            dz.log('There was a problem handling the request', dz.LOG_ERROR)
            dz.log(item, dz.LOG_ERROR)
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
gehoel
Posts: 9
Joined: Thursday 05 March 2020 19:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by gehoel »

I have tested the script.
See the LOG:
Spoiler: show

Code: Select all

 2020-07-06 08:15:00.495 Status: dzVents: Info: evCharger: ------ Start internal script: EV Charging:, trigger: "every minute"
2020-07-06 08:15:00.632 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSEState: Switch device adapter
2020-07-06 08:15:00.639 Status: dzVents: Debug: evCharger: Processing device-adapter for vehicleState: Switch device adapter
2020-07-06 08:15:00.645 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSECurrent: 1-phase Ampere device adapter
2020-07-06 08:15:00.652 Status: dzVents: Debug: evCharger: Processing device-adapter for houseCurrent: 1-phase Ampere device adapter
2020-07-06 08:15:00.658 Status: dzVents: Debug: evCharger: Processing device-adapter for Usage L1: Electric usage device adapter
2020-07-06 08:15:00.664 Status: dzVents: Debug: evCharger: Processing device-adapter for Delivery L1: Electric usage device adapter
2020-07-06 08:15:00.665 Status: dzVents: Debug: evCharger: OpenURL: url = http://192.168.xx.xx/getParameters
2020-07-06 08:15:00.666 Status: dzVents: Debug: evCharger: OpenURL: method = GET
2020-07-06 08:15:00.666 Status: dzVents: Debug: evCharger: OpenURL: post data = nil
2020-07-06 08:15:00.666 Status: dzVents: Debug: evCharger: OpenURL: headers = nil
2020-07-06 08:15:00.666 Status: dzVents: Debug: evCharger: OpenURL: callback = evCharger_getParameters
2020-07-06 08:15:00.667 Status: dzVents: Info: evCharger: ------ Finished EV Charging
2020-07-06 08:15:00.669 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua
2020-07-06 08:15:02.630 Status: dzVents: Info: Handling httpResponse-events for: "evCharger_getParameters"
2020-07-06 08:15:02.631 Status: dzVents: Info: evCharger: ------ Start internal script: EV Charging: HTTPResponse: "evCharger_getParameters"
2020-07-06 08:15:02.897 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSEState: Switch device adapter
2020-07-06 08:15:02.920 Status: dzVents: Debug: evCharger: Processing device-adapter for vehicleState: Switch device adapter
2020-07-06 08:15:02.927 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSECurrent: 1-phase Ampere device adapter
2020-07-06 08:15:02.950 Status: dzVents: Debug: evCharger: Processing device-adapter for houseCurrent: 1-phase Ampere device adapter
2020-07-06 08:15:02.956 Status: dzVents: Debug: evCharger: Processing device-adapter for Usage L1: Electric usage device adapter
2020-07-06 08:15:02.974 Status: dzVents: Debug: evCharger: Processing device-adapter for Delivery L1: Electric usage device adapter
2020-07-06 08:15:02.975 Status: dzVents: Info: evCharger: vehicleState: 1
2020-07-06 08:15:02.976 Status: dzVents: Info: evCharger: ------ Finished EV Charging
2020-07-06 08:15:02.976 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua 
I get an Value in EVSECurrent and in houseCurrent in Domoticz.
Also the switches EVSEState and vehicleState are updating.
In line 71 was an typing error verhiclState instead of vehicleState, i have changed it.

The last thing that I wanted to test if the current would change.
To test it whiteout the car connected I have changed in the line 72 'charging' to 'ready'.
This didn't result in an change of in an error.
I'm I missing something?
Greetings,
Bart
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by waaren »

gehoel wrote: Monday 06 July 2020 8:33 I have tested the script.
The last thing that I wanted to test if the current would change.
This didn't result in an change of in an error.
updated version

Code: Select all

--[[

        script to dynamically change max loading amperage of vehicle based on house usage / delivery

        history:
        20200705: Initial release
        20200706: Mapped numeric vehicleState to string vehicleStateText

]]

local scriptVar = 'evCharger'

return
{
    on =
    {
        timer =
        {
            'every minute',
        },

        devices =
        {
            'evTrigger' -- for test only
        },

        httpResponses =
        {
            scriptVar .. '_*' ,
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'evCharger',
    },

    execute = function(dz, item)

        -- enter you settings below this line

        local maxHouseCurrent = 15

        local chargingStationIP = '192.168.xxx.xxx'

        local evse = dz.devices('EVSEState') -- Selector switch with hidden Off level and levels 'Active' and 'not Active'
        local vehicle = dz.devices('vehicleState') -- Selector switch with hidden Off level and levels 'ready', 'detected' and 'charging'
        local evseCurrent = dz.devices('EVSECurrent') -- Ampere 1 phase
        local houseCurrent = dz.devices('houseCurrent') -- Ampere 1 phase

        local usage = dz.devices('Usage L1').actualWatt        -- smart meter usage electric
        local delivered = dz.devices('usageDelivered').actualWatt -- smart meter usage electric

        local testing = false

        -- no changes required below this line

        local getCall = 'getParameters'
        local setCall = 'setCurrent?current='

        local function sendURL(call, current)
            local url = 'http://' .. chargingStationIP .. '/' .. call .. (current or '')
            if testing then url
                   'http://dz:8084/json.htm?type=command&param=getversion'
            end
            dz.openURL(
            {
                url = url,
                callback = scriptVar .. '_' .. call,
            })
        end

        local function setCurrent(rt)
            dz.log('vehicleState: ' .. rt.vehicleStateText,dz.log_DEBUG )
            if rt.vehicleStateText == 'charging' then
                if rt.houseCurrent > maxHouseCurrent and rt.actualCurrent > 0 then
                    dz.log('decreasing',dz.log_DEBUG )
                    sendURL(setCall, rt.actualCurrent - 1 )
                elseif rt.houseCurrent < ( maxHouseCurrent - 1) and  rt.actualCurrent < ( rt.maxCurrent - 1 ) then
                    sendURL(setCall, rt.actualCurrent + 1)
                    dz.log('increasing',dz.log_DEBUG )
                end
            end
        end

        local function updateDevices(rt)
            -- set vehicleState
            vehicleStates = { 'ready','detected','charging'}
            rt.vehicleStateText =  vehicleStates[rt.vehicleState]
            if vehicle.state ~= rt.vehicleStateText then
                vehicle.switchSelector(rt.vehicleStateText)
            end

            -- set evseState
            if rt.evseState and evse.state ~= 'Active' then
                evse.switchSelector('Active')
            elseif not(rt.evseState) and evse.state ~= 'not Active' then
                evse.switchSelector('not Active')
            end

            -- set houseCurrent
            local current = dz.utils.round(( usage - delivered ) / 230 , 2)
            houseCurrent.updateCurrent(current)
            rt.houseCurrent = current

            -- set evseCurrent
            if evseCurrent.current ~= rt.actualCurrent then
                evseCurrent.updateCurrent(rt.actualCurrent)
            end
        end

        -- main
        if item.isTimer or item.isDevice then
           sendURL(getCall)
           return
        end

        -- handling response
        if item.isHTTPResponse and item.ok then
            if item.trigger:match('getParameters') then
                if testing then
                    local testJSON = '{"type":"parameters","list":[{"vehicleState":1,"evseState":false,"maxCurrent":15,"actualCurrent":10,"actualPower":0,"duration":0,"alwaysActive":false,"lastActionUser":"GUI","lastActionUID":"GUI","energy":0,"mileage":0,"meterReading":0,"currentP1":0,"currentP2":0,"currentP3":0}]}'
                    item.json = dz.utils.fromJSON(testJSON)
                end
                local rt = item.json.list[1]
                updateDevices(rt)
                setCurrent(rt)
            else
                dz.log('current successfully adjusted',dz.LOG_DEBUG)
            end
        else
            dz.log('There was a problem handling the request', dz.LOG_ERROR)
            dz.log(item, dz.LOG_ERROR)
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
gehoel
Posts: 9
Joined: Thursday 05 March 2020 19:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by gehoel »

2020-07-06 09:15:03.427 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua
2020-07-06 09:15:03.425 Error: dzVents: Error: (3.0.2) evCharger: An error occurred when calling event handler EV Charging
2020-07-06 09:15:03.426 Error: dzVents: Error: (3.0.2) evCharger: ...moticz/scripts/dzVents/generated_scripts/EV Charging.lua:75: attempt to concatenate a nil value (field 'vehiclStateText')
Greetings,
Bart
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by waaren »

gehoel wrote: Monday 06 July 2020 9:18 2020-07-06 09:15:03.426 Error: dzVents: Error: (3.0.2) evCharger: ...moticz/scripts/dzVents/generated_scripts/EV Charging.lua:75: attempt to concatenate a nil value (field 'vehiclStateText')
can you change

Code: Select all

dz.log('vehicleState: ' .. rt.vehiclStateText,dz.log_DEBUG )
to

Code: Select all

dz.log('vehicleState: ' .. rt.vehicleStateText,dz.log_DEBUG )
and try again?
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
gehoel
Posts: 9
Joined: Thursday 05 March 2020 19:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by gehoel »

The raising of the current works:
Spoiler: show

Code: Select all

 2020-07-06 09:46:00.783 Status: dzVents: Info: evCharger: ------ Start internal script: EV Charging:, trigger: "every minute"
2020-07-06 09:46:00.911 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSEState: Switch device adapter
2020-07-06 09:46:00.918 Status: dzVents: Debug: evCharger: Processing device-adapter for vehicleState: Switch device adapter
2020-07-06 09:46:00.925 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSECurrent: 1-phase Ampere device adapter
2020-07-06 09:46:00.931 Status: dzVents: Debug: evCharger: Processing device-adapter for houseCurrent: 1-phase Ampere device adapter
2020-07-06 09:46:00.937 Status: dzVents: Debug: evCharger: Processing device-adapter for Usage L1: Electric usage device adapter
2020-07-06 09:46:00.943 Status: dzVents: Debug: evCharger: Processing device-adapter for Delivery L1: Electric usage device adapter
2020-07-06 09:46:00.944 Status: dzVents: Debug: evCharger: OpenURL: url = http://192.168.20.215/getParameters
2020-07-06 09:46:00.944 Status: dzVents: Debug: evCharger: OpenURL: method = GET
2020-07-06 09:46:00.945 Status: dzVents: Debug: evCharger: OpenURL: post data = nil
2020-07-06 09:46:00.945 Status: dzVents: Debug: evCharger: OpenURL: headers = nil
2020-07-06 09:46:00.945 Status: dzVents: Debug: evCharger: OpenURL: callback = evCharger_getParameters
2020-07-06 09:46:00.946 Status: dzVents: Info: evCharger: ------ Finished EV Charging
2020-07-06 09:46:00.948 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua
2020-07-06 09:46:01.457 Status: dzVents: Info: Handling httpResponse-events for: "evCharger_getParameters"
2020-07-06 09:46:01.458 Status: dzVents: Info: evCharger: ------ Start internal script: EV Charging: HTTPResponse: "evCharger_getParameters"
2020-07-06 09:46:01.593 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSEState: Switch device adapter
2020-07-06 09:46:01.600 Status: dzVents: Debug: evCharger: Processing device-adapter for vehicleState: Switch device adapter
2020-07-06 09:46:01.607 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSECurrent: 1-phase Ampere device adapter
2020-07-06 09:46:01.613 Status: dzVents: Debug: evCharger: Processing device-adapter for houseCurrent: 1-phase Ampere device adapter
2020-07-06 09:46:01.619 Status: dzVents: Debug: evCharger: Processing device-adapter for Usage L1: Electric usage device adapter
2020-07-06 09:46:01.626 Status: dzVents: Debug: evCharger: Processing device-adapter for Delivery L1: Electric usage device adapter
2020-07-06 09:46:01.627 Status: dzVents: Info: evCharger: vehicleState: ready
2020-07-06 09:46:01.628 Status: dzVents: Debug: evCharger: OpenURL: url = http://192.168.20.215/setCurrent?current=14
2020-07-06 09:46:01.628 Status: dzVents: Debug: evCharger: OpenURL: method = GET
2020-07-06 09:46:01.628 Status: dzVents: Debug: evCharger: OpenURL: post data = nil
2020-07-06 09:46:01.629 Status: dzVents: Debug: evCharger: OpenURL: headers = nil
2020-07-06 09:46:01.629 Status: dzVents: Debug: evCharger: OpenURL: callback = evCharger_setCurrent?current=
2020-07-06 09:46:01.630 Status: dzVents: Info: evCharger: increasing
2020-07-06 09:46:01.630 Status: dzVents: Info: evCharger: ------ Finished EV Charging
2020-07-06 09:46:01.632 Status: EventSystem: Script event triggered: /home/pi/domoticz/dzVents/runtime/dzVents.lua
2020-07-06 09:46:03.771 Status: dzVents: Info: Handling httpResponse-events for: "evCharger_setCurrent?current="
2020-07-06 09:46:03.772 Status: dzVents: Info: evCharger: ------ Start internal script: EV Charging: HTTPResponse: "evCharger_setCurrent?current="
2020-07-06 09:46:03.778 Status: dzVents: Debug: evCharger: Processing device-adapter for EVSEState: Switch device adapter
2020-07-06 09:46:03.802 Status: dzVents: Debug: evCharger: Processing device-adapter for vehicleState: Switch device adapter
2020-07-06 09:46:03.809 Status: dzVents: Debug: evCharger: Processing device-adapter for houseCurrent: 1-phase Ampere device adapter
2020-07-06 09:46:03.825 Status: dzVents: Debug: evCharger: Processing device-adapter for Usage L1: Electric usage device adapter
2020-07-06 09:46:03.842 Status: dzVents: Debug: evCharger: Processing device-adapter for Delivery L1: Electric usage device adapter
2020-07-06 09:46:03.843 Status: dzVents: Debug: evCharger: current successfully adjusted
2020-07-06 09:46:03.843 Status: dzVents: Info: evCharger: ------ Finished EV Charging 
the only thing left for testing is de lowering, but at the time I have no power consumption at home.

The thing that would be nice to at is an "default" value to set when the status is "ready". (lest say 6A)
This will prevent that the charging will start at the latest value set.
When the state changes to charging it will then always start at 6A and raise when possible.
Greetings,
Bart
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by waaren »

gehoel wrote: Monday 06 July 2020 9:58 the only thing left for testing is de lowering, but at the time I have no power consumption at home.
Added that.

Code: Select all

--[[

        script to dynamically change max loading amperage of vehicle based on house usage / delivery

        history:
        20200705: Initial release
        20200706: Mapped numeric vehicleState to string vehicleStateText
        20200706: Add default Current to be set when state is 'ready'

]]

local scriptVar = 'evCharger'

return
{
    on =
    {
        timer =
        {
            'every minute',
        },

        devices =
        {
            'evTrigger' -- for test only
        },

        httpResponses =
        {
            scriptVar .. '_*' ,
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'evCharger',
    },

    execute = function(dz, item)

        -- enter you settings below this line

        local maxHouseCurrent = 15
        local defaultCurrent = 6

        local chargingStationIP = '192.168.xxx.xxx'

        local evse = dz.devices('EVSEState') -- Selector switch with hidden Off level and levels 'Active' and 'not Active'
        local vehicle = dz.devices('vehicleState') -- Selector switch with hidden Off level and levels 'ready', 'detected' and 'charging'
        local evseCurrent = dz.devices('EVSECurrent') -- Ampere 1 phase
        local houseCurrent = dz.devices('houseCurrent') -- Ampere 1 phase

        local usage = dz.devices('Usage L1').actualWatt        -- smart meter usage electric
        local delivered = dz.devices('usageDelivered').actualWatt -- smart meter usage electric

        local testing = false

        -- no changes required below this line

        local getCall = 'getParameters'
        local setCall = 'setCurrent?current='

        local function sendURL(call, current)
            local url = 'http://' .. chargingStationIP .. '/' .. call .. (current or '')
            if testing then url
                   'http://dz:8084/json.htm?type=command&param=getversion'
            end
            dz.openURL(
            {
                url = url,
                callback = scriptVar .. '_' .. call,
            })
        end

        local function setCurrent(rt)
            dz.log('vehicleState: ' .. rt.vehicleStateText,dz.LOG_DEBUG )
            if rt.vehicleStateText == 'charging' then
                if rt.houseCurrent > maxHouseCurrent and rt.actualCurrent > 0 then
                    dz.log('decreasing',dz.LOG_DEBUG )
                    sendURL(setCall, rt.actualCurrent - 1 )
                elseif rt.houseCurrent < ( maxHouseCurrent - 1) and  rt.actualCurrent < ( rt.maxCurrent - 1 ) then
                    sendURL(setCall, rt.actualCurrent + 1)
                    dz.log('increasing',dz.LOG_DEBUG )
                end
            elseif rt.vehicleStateText == 'ready' and rt.actualCurrent ~= defaultCurrent then
                sendURL(setCall, defaultCurrent)
            end
        end

        local function updateDevices(rt)
            -- set vehicleState
            vehicleStates = { 'ready','detected','charging'}
            rt.vehicleStateText =  vehicleStates[rt.vehicleState]
            if vehicle.state ~= rt.vehicleStateText then
                vehicle.switchSelector(rt.vehicleStateText)
            end

            -- set evseState
            if rt.evseState and evse.state ~= 'Active' then
                evse.switchSelector('Active')
            elseif not(rt.evseState) and evse.state ~= 'not Active' then
                evse.switchSelector('not Active')
            end

            -- set houseCurrent
            local current = dz.utils.round(( usage - delivered ) / 230 , 2)
            houseCurrent.updateCurrent(current)
            rt.houseCurrent = current

            -- set evseCurrent
            if evseCurrent.current ~= rt.actualCurrent then
                evseCurrent.updateCurrent(rt.actualCurrent)
            end
        end

        -- main
        if item.isTimer or item.isDevice then
           sendURL(getCall)
           return
        end

        -- handling response
        if item.isHTTPResponse and item.ok then
            if item.trigger:match('getParameters') then
                if testing then
                    local testJSON = '{"type":"parameters","list":[{"vehicleState":1,"evseState":false,"maxCurrent":15,"actualCurrent":10,"actualPower":0,"duration":0,"alwaysActive":false,"lastActionUser":"GUI","lastActionUID":"GUI","energy":0,"mileage":0,"meterReading":0,"currentP1":0,"currentP2":0,"currentP3":0}]}'
                    item.json = dz.utils.fromJSON(testJSON)
                end
                local rt = item.json.list[1]
                updateDevices(rt)
                setCurrent(rt)
            else
                dz.log('current successfully adjusted',dz.LOG_DEBUG)
            end
        else
            dz.log('There was a problem handling the request', dz.LOG_ERROR)
            dz.log(item, dz.LOG_ERROR)
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
gehoel
Posts: 9
Joined: Thursday 05 March 2020 19:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter  [Solved]

Post by gehoel »

Tested it and that works as well.
Now it's waiting for some more power uses in my house to see if de lowering of the current works as well.

For now it's working as I hoped for.

Many thanks for this.
Greetings,
Bart
gehoel
Posts: 9
Joined: Thursday 05 March 2020 19:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by gehoel »

Is there a way to run the script more often then every minute, lets say every 20 seconds?
Greetings,
Bart
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: EV Charging and load balancing with P1 electricity meter

Post by waaren »

gehoel wrote: Saturday 11 July 2020 8:43 Is there a way to run the script more often then every minute, lets say every 20 seconds?
Can you try this

Code: Select all

--[[

        script to dynamically change max loading amperage of vehicle based on house usage / delivery

        history:
        20200705: Initial release
        20200706: Mapped numeric vehicleState to string vehicleStateText
        20200706: Add default Current to be set when state is 'ready'
        20200711: Add frequency (trigger customEvent)

]]

local scriptVar = 'evCharger'

return
{
    on =
    {
        timer =
        {
            'every minute',
        },

        customEvents =
        {
            scriptVar,
        },

        httpResponses =
        {
            scriptVar .. '_*' ,
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = scriptVar,
    },

    execute = function(dz, item)

        -- enter you settings below this line

        local maxHouseCurrent = 15
        local defaultCurrent = 6
        local scriptFrequency = 3 -- times a minute
        local chargingStationIP = '192.168.xxx.xxx'

        local evse = dz.devices('EVSEState') -- Selector switch with hidden Off level and levels 'Active' and 'not Active'
        local vehicle = dz.devices('vehicleState') -- Selector switch with hidden Off level and levels 'ready', 'detected' and 'charging'
        local evseCurrent = dz.devices('EVSECurrent') -- Ampere 1 phase
        local houseCurrent = dz.devices('houseCurrent') -- Ampere 1 phase

        local usage = dz.devices('Usage L1').actualWatt        -- smart meter usage electric
        local delivered = dz.devices('usageDelivered').actualWatt -- smart meter usage electric

        local testing = false

        -- no changes required below this line

        local getCall = 'getParameters'
        local setCall = 'setCurrent?current='

        local function sendURL(call, current)
            local url = 'http://' .. chargingStationIP .. '/' .. call .. (current or '')
            if testing then url
                   'http://dz:8084/json.htm?type=command&param=getversion'
            end
            dz.openURL(
            {
                url = url,
                callback = scriptVar .. '_' .. call,
            })
        end

        local function setCurrent(rt)
            dz.log('vehicleState: ' .. rt.vehicleStateText,dz.LOG_DEBUG )
            if rt.vehicleStateText == 'charging' then
                if rt.houseCurrent > maxHouseCurrent and rt.actualCurrent > 0 then
                    dz.log('decreasing',dz.LOG_DEBUG )
                    sendURL(setCall, rt.actualCurrent - 1 )
                elseif rt.houseCurrent < ( maxHouseCurrent - 1) and  rt.actualCurrent < ( rt.maxCurrent - 1 ) then
                    sendURL(setCall, rt.actualCurrent + 1)
                    dz.log('increasing',dz.LOG_DEBUG )
                end
            elseif rt.vehicleStateText == 'ready' and rt.actualCurrent ~= defaultCurrent then
                sendURL(setCall, defaultCurrent)
            end
        end

        local function updateDevices(rt)
            -- set vehicleState
            vehicleStates = { 'ready','detected','charging'}
            rt.vehicleStateText =  vehicleStates[rt.vehicleState]
            if vehicle.state ~= rt.vehicleStateText then
                vehicle.switchSelector(rt.vehicleStateText)
            end

            -- set evseState
            if rt.evseState and evse.state ~= 'Active' then
                evse.switchSelector('Active')
            elseif not(rt.evseState) and evse.state ~= 'not Active' then
                evse.switchSelector('not Active')
            end

            -- set houseCurrent
            local current = dz.utils.round(( usage - delivered ) / 230 , 2)
            houseCurrent.updateCurrent(current)
            rt.houseCurrent = current

            -- set evseCurrent
            if evseCurrent.current ~= rt.actualCurrent then
                evseCurrent.updateCurrent(rt.actualCurrent)
            end
        end

        local function repeatScript(frequency)
            local interval = math.floor(60/frequency)
            for secondsDelay = interval, (60 - interval), interval do
                dz.emitEvent(scriptVar).afterSec(secondsDelay)
           end
        end

        -- main
        if not(item.isHTTPResponse) then
            sendURL(getCall)
            if item.isTimer then repeatScript(scriptFrequency) end
            return
        end

        -- handling response
        if item.isHTTPResponse and item.ok then
            if item.trigger:match('getParameters') then
                if testing then
                    local testJSON = '{"type":"parameters","list":[{"vehicleState":1,"evseState":false,"maxCurrent":15,"actualCurrent":10,"actualPower":0,"duration":0,"alwaysActive":false,"lastActionUser":"GUI","lastActionUID":"GUI","energy":0,"mileage":0,"meterReading":0,"currentP1":0,"currentP2":0,"currentP3":0}]}'
                    item.json = dz.utils.fromJSON(testJSON)
                end
                local rt = item.json.list[1]
                updateDevices(rt)
                setCurrent(rt)
            else
                dz.log('current successfully adjusted',dz.LOG_DEBUG)
            end
        else
            dz.log('There was a problem handling the request', dz.LOG_ERROR)
            dz.log(item, dz.LOG_ERROR)
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest