Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New feature that allows to limit the max power from the Grid #220

Open
wants to merge 5 commits into
base: v1.2.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions TWCManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@
debugLog(1, "Unable to find a configuration file.")
sys.exit()




########################################################################
# Write the PID in order to let a supervisor restart it in case of crash
PIDfile=config["config"]["settingsPath"] + "/TWCManager.pid"
PIDTWCManager=open(PIDfile,"w")
PIDTWCManager.write(str(os.getpid()))
PIDTWCManager.close()

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hardcoded path would fail on any installation where the directory specified doesn't exist

Copy link
Author

@juanjoqg juanjoqg Feb 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, it should be changed for:

PIDfile=config["config"]["settingsPath"] + "/TWCManager.pid"
PIDTWCManager=open(PIDfile,"w")
PIDTWCManager.write(str(os.getpid()))
PIDTWCManager.close()

Should I submit a new PR?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can push a new commit to your branch, and that will then update the changes in the PR :)

# All TWCs ship with a random two-byte TWCID. We default to using 0x7777 as our
# fake TWC ID. There is a 1 in 64535 chance that this ID will match each real
# TWC on the network, in which case you should pick a different random id below.
Expand Down Expand Up @@ -237,6 +247,9 @@ def background_tasks_thread(master):
requests.post(task["url"], json=body)
elif task["cmd"] == "saveSettings":
master.saveSettings()
elif task["cmd"] == "checkMaxPowerFromGrid":
check_max_power_from_grid()


except:
master.debugLog(
Expand Down Expand Up @@ -285,6 +298,24 @@ def check_green_energy():
master.setMaxAmpsToDivideAmongSlaves(master.getMaxAmpsToDivideGreenEnergy())


def check_max_power_from_grid():
global config, hass, master

# Check solar panel generation using an API exposed by

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think this comment about HomeAssistant API is missplaced, (also in the function that it was copied from). Remove it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, you are wright, copy&paste issue...

# the HomeAssistant API.
#
# You may need to customize the sensor entity_id values
# to match those used in your environment. This is configured
# in the config section at the top of this file.
#
# Poll all loaded EMS modules for consumption and generation values
for module in master.getModulesByType("EMS"):
master.setConsumption(module["name"], module["ref"].getConsumption())
master.setGeneration(module["name"], module["ref"].getGeneration())
master.setMaxAmpsToDivideFromGrid(master.getMaxAmpsToDivideFromGrid())



def update_statuses():

# Print a status update if we are on track green energy showing the
Expand Down
45 changes: 45 additions & 0 deletions etc/twcmanager/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@
# wiringMaxAmpsPerTWC = 50 * 0.8 = 40 and wiringMaxAmpsAllTWCs = 40 + 40 = 80.
"wiringMaxAmpsPerTWC": 6,


# If you what to limit the power drawn from the Grid you need to set this
# maxAmpsAllowedFromGrid and extend the policy you what it to apply, i.e.:
# { "name": "Charge Now with Grid power limit",
# "match": [
# "settings.chargeNowAmps",
# "settings.chargeNowTimeEnd",
# "settings.chargeNowTimeEnd",
# ],
# "condition": ["gt", "gt", "gt"],
# "value": [0, 0, "now"],
# "background_task": "checkMaxPowerFromGrid",
# "charge_amps": "settings.chargeNowAmps",
# "charge_limit": "config.chargeNowLimit"},

# { "name": "Scheduled Charging with Grid power limit",
# "match": [ "checkScheduledCharging()" ],
# "condition": [ "eq" ],
# "value": [ 1 ],
# "background_task": "checkMaxPowerFromGrid",
# "charge_amps": "settings.scheduledAmpsMax",
# "charge_limit": "config.scheduledLimit"},

"maxAmpsAllowedFromGrid": 15,


# https://teslamotorsclub.com/tmc/threads/model-s-gen2-charger-efficiency-testing.78740/#post-1844789
# says you're using 10.85% more power (91.75/82.77=1.1085) charging at 5A vs 40A,
# 2.48% more power at 10A vs 40A, and 1.9% more power at 20A vs 40A. This is
Expand Down Expand Up @@ -258,6 +284,25 @@
#
# They should primarily be used to abort charging when necessary.
"emergency":[
{ "name": "Charge Now with Grid power limit",
"match": [
"settings.chargeNowAmps",
"settings.chargeNowTimeEnd",
"settings.chargeNowTimeEnd",
],
"condition": ["gt", "gt", "gt"],
"value": [0, 0, "now"],
"background_task": "checkMaxPowerFromGrid",
"charge_amps": "settings.chargeNowAmps",
"charge_limit": "config.chargeNowLimit"},

{ "name": "Scheduled Charging with Grid power limit",
"match": [ "checkScheduledCharging()" ],
"condition": [ "eq" ],
"value": [ 1 ],
"background_task": "checkMaxPowerFromGrid",
"charge_amps": "settings.scheduledAmpsMax",
"charge_limit": "config.scheduledLimit"},
],
# Rules in the before section here are evaluated after the Charge Now rule
"before":[
Expand Down
2 changes: 1 addition & 1 deletion lib/TWCManager/Control/themes/Default/jsrefresh.html.j2
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ $(document).ready(function() {
}

// Change the state of the Charge Now button based on Charge Policy
if (json["currentPolicy"] == "Charge Now") {
if (json["currentPolicy"] == "Charge Now" || json["currentPolicy"] == "Charge Now with Grid power limit") {
document.getElementById("start_chargenow").value = "Update Charge Now";
document.getElementById("cancel_chargenow").disabled = false;
} else {
Expand Down
40 changes: 40 additions & 0 deletions lib/TWCManager/TWCMaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class TWCMaster:
lastTWCResponseMsg = None
masterTWCID = ""
maxAmpsToDivideAmongSlaves = 0
maxAmpsToDivideFromGrid = 0
modules = {}
nextHistorySnap = 0
overrideMasterHeartbeatData = b""
Expand Down Expand Up @@ -532,6 +533,29 @@ def getMaxAmpsToDivideGreenEnergy(self):
amps = amps / self.getRealPowerFactor(amps)
return round(amps, 2)

def getMaxAmpsToDivideFromGrid(self):
# Calculate our current generation and consumption in watts
generationW = float(self.getGeneration())
consumptionW = float(self.getConsumption())

currentOffer = min(
self.getTotalAmpsInUse(),
self.getMaxAmpsToDivideAmongSlaves(),
)

# Calculate what we should max offer to align with max grid energy
amps = self.config["config"]["maxAmpsAllowedFromGrid"] + \
self.convertWattsToAmps(generationW - consumptionW) + \
Copy link

@mattiasclaesson mattiasclaesson Apr 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a solar production that is connected to a own fuse, Consumption has a smaller fuse. So the solar production is not really helping to increase the maxAmpsAllowedFromGrid. I guess this case needs to/could be added as a setting to ignore generationW.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be controled latelly by the wiringMaxAmpsAllTWCs and wiringMaxAmpsPerTWC, despite of the value given to the maxAmpsToDivideAmongSlaves it's always limited to the wiring limit.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But wiringMaxAmpsAllTWCs and wiringMaxAmpsPerTWC are hardcoded, right?

I'd like the charge power to be dynamic based on the other consumers in the house. So if the rest of the house consume 5A out of 16A, the car can still charge with 9A.

currentOffer

amps = amps / self.getRealPowerFactor(amps)
self.debugLog(
10, "TWCMaster", "MaxAmpsToDivideFromGrid: +++++++++++++++: " + str(amps)
)

return round(amps, 2)


def getNormalChargeLimit(self, ID):
if "chargeLimits" in self.settings and str(ID) in self.settings["chargeLimits"]:
result = self.settings["chargeLimits"][str(ID)]
Expand Down Expand Up @@ -1167,6 +1191,17 @@ def setMaxAmpsToDivideAmongSlaves(self, amps):
)
amps = self.config["config"]["wiringMaxAmpsAllTWCs"]

activePolicy=str(self.getModuleByName("Policy").active_policy)
if (activePolicy== "Charge Now with Grid power limit" or \
activePolicy== "Scheduled Charging with Grid power limit") and \
amps > self.maxAmpsToDivideFromGrid:
# Never tell the slaves to draw more amps from grid than allowed
amps = self.maxAmpsToDivideFromGrid
self.debugLog(
10, "TWCMaster","maxAmpsToDivideAmongSlaves limited to not draw more power from the grid than allowed: " + str(amps)
)


self.maxAmpsToDivideAmongSlaves = amps

self.releaseBackgroundTasksLock()
Expand All @@ -1175,6 +1210,11 @@ def setMaxAmpsToDivideAmongSlaves(self, amps):
# to console / MQTT / etc
self.queue_background_task({"cmd": "updateStatus"})

def setMaxAmpsToDivideFromGrid(self, amps):
# This is called when check_max_power_from_grid is run
# It stablished how much power we allow getting from the grid
self.maxAmpsToDivideFromGrid = amps

def setNonScheduledAmpsMax(self, amps):
self.settings["nonScheduledAmpsMax"] = amps

Expand Down
24 changes: 24 additions & 0 deletions svisorTWC.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
PROGRAM=/usr/bin/python3.5
PIDFILE=/etc/twcmanager/TWCManager.pid
TWCMANAGER_PATH=/home/pi/TWCManager

while true
do

if [ -f $PIDFILE ]; then
read PID <$PIDFILE
echo $PID
if [ -d /proc/$PID ] && [ "$(readlink -f /proc/$PID/exe)" = "$PROGRAM" ]; then
echo "done."
else
echo "PID not found, Starting..."
screen -dm -S TWCManager $TWCMANAGER_PATH/TWCManager.py
fi
else
echo "PID file not found "; echo $PIDFILE; echo ", Starting..."
screen -dm -S TWCManager $TWCMANAGER_PATH/TWCManager.py
fi
sleep 30
done