I put together a little script to read from the Solax X1 Hybrid Gen4 Inverter local API to forward to Emoncms. I would like to integrate this in emonhub in due course but here’s a basic functioning initial implementation:
import requests
import json
import time
def to_signed(val):
if val > 0x7FFF:
val -= 2**16
return val
def pack_u16(a, b):
return (b << 16) + a
def read_from_solax(url, password):
data = {
'optType': 'ReadRealTimeData',
'pwd': password
}
try:
response = requests.post(url, data=data)
except requests.exceptions.RequestException as ex:
return None
# Data example
# '{"sn":"SERIAL_NUMBER","ver":"3.003.02","type":15,"Data":[2498,38,928,5005,1688,1691,25,33,426,569,2,7887,0,27,12620,0,0,26,98,1443,0,2195,0,56,100,0,30,3870,0,0,0,0,809,0,50740,0,4576,0,119,36,256,1314,900,30,350,203,189,36,35,31,1,1,8,0,8998,0,64608,65535,65387,65535,0,0,0,0,0,0,0,0,0,0,397,0,62240,65535,1800,0,63736,65535,110,0,40,0,0,0,0,44,9,25,0,0,220,0,180,0,0,0,0,0,0,13831,1036,5895,603,258,9766,0,0,0,0,0,1,1290,0,0,3561,3546,45080,5,21302,14389,18757,12354,16697,12360,14384,21302,14389,18757,12354,16697,12360,14384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3585,258,770,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"Information":[3.000,15,"OTHER_SERIAL_NUMBER",8,1.29,0.00,1.27,1.04,0.00,1]}'
# Decode Solar X1 Hybrid Gen4 response
try:
data = json.loads(response.text)
except ValueError as ex:
return None
if 'Data' not in data:
print ('No data in response')
return None
data = data['Data']
if len(data) < 40:
print ('Unexpected data length')
return None
# From https://github.com/squishykid/solax/blob/master/solax/inverters/x1_hybrid_gen4.py
return {
'AC voltage R': data[0]*0.1,
'AC current': data[1]*0.1,
'AC power': to_signed(data[2]*1),
'AC frequency': data[3]*0.01,
'PV1 voltage': data[4]*0.1,
'PV2 voltage': data[5]*0.1,
'PV1 current': data[6]*0.1,
'PV2 current': data[7]*0.1,
'PV1 power': data[8]*1,
'PV2 power': data[9]*1,
'On-grid total yield': pack_u16(data[11],data[12])*0.1,
'On-grid daily yield': data[13]*0.1,
'Battery voltage': data[14]*0.01,
'Battery current': data[15]*0.01,
'Battery power': to_signed(data[16]*1),
'Battery temperature': data[17]*1,
'Battery SOC': data[18]*1,
'Grid power': to_signed(data[32]*1),
'Total feed-in energy': pack_u16(data[34],data[35])*0.01,
'Total consumption': pack_u16(data[36],data[37])*0.01
}
last_time = 0
while True:
if (time.time() - last_time) > 10:
last_time = time.time()
# Read from Solax
output = read_from_solax('http://192.168.0.39', 'SERIAL_NUMBER')
print(output)
if output is not None:
emoncms_url = 'https://emoncms.org'
# use requests to post data to emoncms
try:
requests.post(emoncms_url+'/input/post.json', data={
'apikey': 'WRITE_API_KWY',
'node': "solax",
'json': json.dumps(output)
})
except requests.exceptions.RequestException as ex:
pass
time.sleep(0.1)
This gives the following inputs in emoncms:
A little more detail on the AC power input processing:
PV2 power:
Battery power:
Grid power:
I was thinking perhaps I should do some of this input processing in the script above in order to simplify the input processing in emoncms… I might consider that…
MySolarBattery app