Skip to content

Commit

Permalink
prep for 3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
britkat1980 committed Nov 3, 2023
1 parent 2684876 commit a83f5a4
Show file tree
Hide file tree
Showing 26 changed files with 438 additions and 448 deletions.
Empty file removed .dayRate
Empty file.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ GivTCP/testdata.json
.gitattributes
GivTCP/settings.py
MQTT_TEST.py
REST_TEST.py
test.py
*.pkl
settings.py
__pycache__
givenergy_modbus/model/__pycache__/inverter.cpython-310.pyc
Expand Down
25 changes: 14 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# set base image (host OS)
FROM python:rc-alpine

RUN apk --no-cache add mosquitto
RUN apk add mosquitto
RUN apk add curl
RUN apk add --update npm
RUN npm install -g serve
Expand All @@ -11,31 +11,34 @@ RUN apk add musl-utils
RUN apk add xsel
RUN apk add redis
RUN apk add npm

RUN apk add nginx && mkdir -p /run/nginx

# set the working directory in the container
WORKDIR /app

# copy the dependencies file to the working directory
COPY requirements.txt .

# install dependencies
RUN pip install -r requirements.txt

COPY givtcp-vuejs/package.json ./config_frontend/package.json

RUN cd /app/config_frontend && npm install
COPY givtcp-vuejs ./config_frontend
RUN cd /app/config_frontend && npm run build

COPY ingress.conf /etc/nginx/http.d/
RUN rm /etc/nginx/http.d/default.conf

# copy the content of the local src directory to the working directory
COPY GivTCP/ ./GivTCP
COPY GivEnergy-Smart-Home-Display-givtcp/ ./GivEnergy-Smart-Home-Display-givtcp
COPY givenergy_modbus/ /usr/local/lib/python3.10/site-packages/givenergy_modbus

COPY startup.py startup.py
#COPY startup_3.py startup_3.py
COPY startup_3.py startup_3.py
COPY redis.conf redis.conf
COPY settings.json /app/settings.json

#COPY givtcp-vuejs/package.json ./config_frontend/package.json
#RUN cd /app/config_frontend && npm install
#COPY givtcp-vuejs ./config_frontend
#RUN cd /app/config_frontend && npm run build
COPY index.html /app/index.html

ENV NUMINVERTORS=1
ENV INVERTOR_IP_1=""
Expand Down Expand Up @@ -106,6 +109,6 @@ ENV EVC_IP_ADDRESS=""
ENV EVC_SELF_RUN_TIMER=5


EXPOSE 6345 1883 3000 5173 6379 9181
EXPOSE 1883 6379 8099

CMD ["python3", "/app/startup.py"]
6 changes: 3 additions & 3 deletions GivEnergy-Smart-Home-Display-givtcp/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ class App {
me.givTcpHostname = null;
me.solarRate = null;
me.exportRate = null;

var host = window.location.protocol + "//" + window.location.hostname+":6345"
// Fetch the settings from `app.json`
fetch("./app.json")
.then(response => {
return response.json();
})
.then(data => {
me.givTcpHostname = data.givTcpHostname;
me.givTcpHostname = host;
me.solarRate = data.solarRate;
me.exportRate = data.exportRate;

Expand Down Expand Up @@ -47,7 +47,7 @@ class App {
fetchData() {
const me = this;

fetch(`http://${me.givTcpHostname}/readData`, {
fetch(`${me.givTcpHostname}/readData`, {
mode: 'cors',
headers: {
'Access-Control-Allow-Origin': 'localhost:63342'
Expand Down
2 changes: 1 addition & 1 deletion GivTCP/GivLUT.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ class GivLUT:
"Charge_End_Time":GEType("sensor","timestamp","","","",False,False,False),
"System_Time":GEType("sensor","timestamp","","","",False,False,False),
"Charging_Mode":GEType("select","","setChargingMode","","",False,False,False),
"Import_Cap":GEType("switch","","setImportCap","","",False,False,False),
"Import_Cap":GEType("number","","setImportCap","","",False,False,False),
"Max_Session_Energy":GEType("number","","setMaxSessionEnergy","","",False,False,False),
}
time_slots=[
Expand Down
18 changes: 12 additions & 6 deletions GivTCP/HA_Discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,26 +209,32 @@ def create_device_payload(topic,SN):
tempObj['options']=options
elif GivLUT.entity_type[str(topic).split("/")[-1]].devType=="number":
# If its a rate then change to Watts
if "SOC" in str(topic).lower():
item=str(topic).split("/")[-1]
if "soc" in str(item).lower():
tempObj['unit_of_meas']="%"
tempObj['min']=4
tempObj['max']=100
tempObj['mode']="slider"
elif "limit" in str(topic).lower(): #if EVC current
elif "limit" in str(item).lower(): #if EVC current
tempObj['unit_of_meas']="A"
tempObj['min']=6
tempObj['max']=32
tempObj['mode']="slider"
elif "charge" in str(topic).lower():
tempObj['unit_of_meas']="W"
elif "cap" in str(item).lower(): #if EVC current
tempObj['unit_of_meas']="A"
tempObj['min']=0
tempObj['max']=HAMQTT.getinvbatmax()
tempObj['max']=100
tempObj['mode']="slider"
elif "max_session_energy" in str(topic).lower():
elif "energy" in str(item).lower():
tempObj['unit_of_meas']="kWh"
tempObj['min']=0
tempObj['max']=100
tempObj['mode']="slider"
elif "charge" in str(item).lower():
tempObj['unit_of_meas']="W"
tempObj['min']=0
tempObj['max']=HAMQTT.getinvbatmax()
tempObj['mode']="slider"
else:
tempObj['unit_of_meas']="%"
elif GivLUT.entity_type[str(topic).split("/")[-1]].devType=="button":
Expand Down
44 changes: 41 additions & 3 deletions GivTCP/REST.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from flask_cors import CORS
import read as rd #grab passthrough functions from main read file
import write as wr #grab passthrough functions from main write file
import evc as evc
import config_dash as cfdash
from GivLUT import GivQueue, GivLUT
import os
Expand All @@ -21,11 +22,11 @@

@giv_api.route('/', methods=['GET', 'POST'])
def root():
return send_from_directory('/app/config_frontend/dist/', 'index.html')
return send_from_directory('/app/config_frontend/dist', 'index.html')

@giv_api.route('/config')
def get_config_page():
return send_from_directory('/app/config_frontend/dist/', 'index.html')
return send_from_directory('/app/config_frontend/dist', 'index.html')
# if request.method=="GET":
# return cfdash.get_config()
# if request.method=="POST":
Expand All @@ -42,7 +43,7 @@ def reboot():

@giv_api.route('/restart', methods=['GET'])
def restart():
return wr.rebootAddon
return wr.rebootAddon()

#Publish last cached Invertor Data
@giv_api.route('/readData', methods=['GET'])
Expand Down Expand Up @@ -209,5 +210,42 @@ def editFileData():
file.close()
return data

@giv_api.route('/setImportCap', methods=['POST'])
def impCap():
payload = request.get_json(silent=True, force=True)
return evc.setImportCap(payload)

@giv_api.route('/setCurrentLimit', methods=['POST'])
def currLimit():
payload = request.get_json(silent=True, force=True)
return evc.setCurrentLimit(payload)

@giv_api.route('/setChargeControl', methods=['POST'])
def chrgeControl():
payload = request.get_json(silent=True, force=True)
return evc.setChargeControl(payload)

@giv_api.route('/setChargeMode', methods=['POST'])
def chrgMode():
payload = request.get_json(silent=True, force=True)
return evc.setChargeMode(payload)

@giv_api.route('/setChargingMode', methods=['POST'])
def chrgingMode():
payload = request.get_json(silent=True, force=True)
return evc.setChargingMode(payload)

@giv_api.route('/setMaxSessionEnergy', methods=['POST'])
def maxSession():
payload = request.get_json(silent=True, force=True)
return evc.setMaxSessionEnergy(payload)

@giv_api.route('/getEVCCache', methods=['GET'])
def gtEVCChce():
payload = request.get_json(silent=True, force=True)
return evc.getEVCCache()



if __name__ == "__main__":
giv_api.run()
49 changes: 39 additions & 10 deletions GivTCP/evc.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ def getEVC():
with open(EVCLut.regcache, 'rb') as inp:
evcRegCache= pickle.load(inp)

if output['Charge_Session_Energy']==0:
if output['Charge_Session_Energy']==0 and not output['Charging_State']=='Charging': #If charging has finished, then hold the previous charge session energy
output['Charge_Session_Energy']=evcRegCache['Charger']['Charge_Session_Energy']


startTime=datetime.datetime.now().replace(hour=regs[74],minute=regs[75],second=regs[76],microsecond=0,tzinfo=datetime.timezone.utc).isoformat()
endtime=datetime.datetime.now().replace(hour=regs[82],minute=regs[83],second=regs[84],microsecond=0,tzinfo=datetime.timezone.utc).isoformat()
Expand All @@ -134,14 +135,15 @@ def getEVC():
output['Charge_End_Time']=datetime.datetime.now().replace(hour=regs[82],minute=regs[83],second=regs[84],microsecond=0,tzinfo=datetime.timezone.utc).isoformat()

if not "Import_Cap" in evcRegCache['Charger']:
output['Import_Cap']="disable"
output['Import_Cap']=0
else:
output['Import_Cap']=evcRegCache['Charger']['Import_Cap']

if not "Charging_Mode" in evcRegCache['Charger']:
output['Charging_Mode']="Grid"
else:
output['Charging_Mode']=evcRegCache['Charger']['Charging_Mode']

if not 'Max_Session_Energy' in evcRegCache['Charger']:
output['Max_Session_Energy']=0
else:
Expand All @@ -153,7 +155,7 @@ def getEVC():
output['Charge_End_Time']=ts.replace(tzinfo=datetime.timezone.utc).isoformat()
ts=datetime.datetime.now().replace(hour=regs[74],minute=regs[75],second=regs[76],microsecond=0)
output['Charge_Start_Time']=ts.replace(tzinfo=datetime.timezone.utc).isoformat()
output['Import_Cap']="disable"
output['Import_Cap']=0
output['Charging_Mode']="Grid"
output['Max_Session_Energy']=0
if regs[0]==4:
Expand All @@ -171,6 +173,8 @@ def getEVC():
output['Charge_Session_Duration']=str(td)
multi_output['Charger']=output
# Save new data to Pickle


with cacheLock:
with open(EVCLut.regcache, 'wb') as outp:
pickle.dump(multi_output, outp, pickle.HIGHEST_PROTOCOL)
Expand Down Expand Up @@ -248,7 +252,7 @@ def updateFirstRun(SN):
logger.error("Could not access settings file to update EVC Serial Number")
break
else:
logger.debug("Settings availble evc")
logger.debug("Settings available evc")
#Create setting lockfile
open(".settings_lockfile",'a').close()

Expand Down Expand Up @@ -302,6 +306,14 @@ def iterate_dict(array): # Create a publish safe version of the output (c
safeoutput[p_load] = output
return(safeoutput)

def getEVCCache():
if exists(EVCLut.regcache):
with open(EVCLut.regcache, 'rb') as inp:
evcRegCache= pickle.load(inp)
return json.dumps(evcRegCache)
else:
return json.dumps("No EVC data found")

def setChargeMode(mode):
if mode=="enable":
val=0
Expand All @@ -311,7 +323,7 @@ def setChargeMode(mode):
logger.error("Invalid control mode called: "+str(mode))
return
logger.info("Setting Charge mode to: "+ mode)
logger.info("numeric value "+str(val)+ " sent to EVC")
logger.debug("numeric value "+str(val)+ " sent to EVC")
try:
client=ModbusTcpClient(GiV_Settings.evc_ip_address)
client.write_registers(93,val)
Expand All @@ -323,7 +335,7 @@ def setChargeControl(mode):
if mode in GivLUT.charge_control:
logger.info("Setting Charge control to: "+ mode)
val=GivLUT.charge_control.index(mode)
logger.info("numeric value "+str(val)+ " sent to EVC")
logger.debug("numeric value "+str(val)+ " sent to EVC")
try:
client=ModbusTcpClient(GiV_Settings.evc_ip_address)
client.write_registers(95,val)
Expand Down Expand Up @@ -357,19 +369,36 @@ def test():
#getEVC()
print (result)

def chargeMode():
def chargeMode(once=False):
while True:
#Run a regular check and manage load based on current mode and session energy
if exists(EVCLut.regcache):
with open(EVCLut.regcache, 'rb') as inp:
evcRegCache= pickle.load(inp)
evcRegCache= pickle.load(inp)
if evcRegCache['Charger']['Charging_State']=="Charging" or evcRegCache['Charger']['Charging_State']=="Connected":
if evcRegCache['Charger']['Charging_Mode']=="Hybrid":
hybridmode()
elif evcRegCache['Charger']['Charging_Mode']=="Solar":
solarmode()
if not evcRegCache['Charger']['Max_Session_Energy']==0 and evcRegCache['Charger']['Charge_Session_Energy']>evcRegCache['Charger']['Max_Session_Energy'] and evcRegCache['Charger']['Charge_Control']=="Start":
if not evcRegCache['Charger']['Max_Session_Energy']==0 and evcRegCache['Charger']['Charge_Session_Energy']>=evcRegCache['Charger']['Max_Session_Energy'] and evcRegCache['Charger']['Charge_Control']=="Start":
logger.info("Session energy limit reached: "+str(evcRegCache['Charger']['Charge_Session_Energy'])+"kWh stopping charge")
setChargeControl("Stop")
if not int(evcRegCache['Charger']['Import_Cap'])==0:
if exists(GivLUT.regcache):
with open(GivLUT.regcache, 'rb') as inp:
invRegCache= pickle.load(inp)
if float(invRegCache[4]['Power']['Power']['Grid_Current'])>(float(evcRegCache['Charger']['Import_Cap'])*0.95):
target=float(evcRegCache['Charger']['Import_Cap'])*0.9
reduction=(float(invRegCache[4]['Power']['Power']['Grid_Current']))-target
newlimit=int(float(evcRegCache['Charger']['Charge_Limit'])-reduction)
if not int(evcRegCache['Charger']['Charge_Limit'])==4:
logger.info("Grid import threshold within 5%, reducing EVC charge current to: "+str(newlimit))
setCurrentLimit(newlimit)
else:
logger.info("Grid import threshold within 5%, cannot reduce Charge limit below 6A. Stopping Charge")
setChargeControl("Stop")
if once:
break
time.sleep(60)


Expand Down Expand Up @@ -456,7 +485,7 @@ def setChargingMode(mode):
with cacheLock:
with open(EVCLut.regcache, 'wb') as outp:
pickle.dump(evcRegCache, outp, pickle.HIGHEST_PROTOCOL)
chargeMode() # Run an initial call when changing modes
chargeMode(True) # Run an initial call when changing modes
else:
logger.error("Invalid selection for Charge Mode ("+str(mode)+")")

Expand Down
2 changes: 1 addition & 1 deletion GivTCP/palm_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class GE:
# Modify url with system name in place of CExxxxxx and paste API key generated on GivEnergy web portal in place of xxxx
url = "https://api.givenergy.cloud/v1/inverter/"+GiV_Settings.serial_number+"/"
# key = str(os.getenv('GEAPI'))
key = str(GiV_Settings.GEAPI)
key = str(GiV_Settings.GE_API)

# Most users will not need to touch that many of the pre-configured settings below

Expand Down
Loading

0 comments on commit a83f5a4

Please sign in to comment.