Initial Python Script to Request Modbus Data
Basic Python script to request realtime data from the Inverter's RS422 port on a Raspberry PI and send it to a local EmonCMS to display the data.
This commit is contained in:
parent
20fbbbbe09
commit
82fedcba05
|
@ -0,0 +1,161 @@
|
||||||
|
import minimalmodbus
|
||||||
|
# import socket
|
||||||
|
import serial
|
||||||
|
import time
|
||||||
|
# import urlparse # obvious!
|
||||||
|
|
||||||
|
### PROGRAM FLOW:
|
||||||
|
### - Collect Data from Sofar HYD6000-ES inverter
|
||||||
|
### - Convert to individual bytes
|
||||||
|
### - Construct 2 messages
|
||||||
|
### - KWH Totals only sent when inverter is running, so they are not reset to zero
|
||||||
|
### - All other 'live' data set to zero when inverter shuts down
|
||||||
|
### - Send Packets to EMONHUB
|
||||||
|
###
|
||||||
|
### EmonHub Node IDs:
|
||||||
|
### - NodeID 3: All time energy KWH / Today KWH (not sent overnight)
|
||||||
|
### - NodeID 4: Live Data Readings - Zeros sent overnight
|
||||||
|
|
||||||
|
|
||||||
|
### COLLECT DATA FROM SOFAR HYD6000 INVERTER ###
|
||||||
|
|
||||||
|
# Base url
|
||||||
|
ubase = 'http://emonpi/input/post?node=emontx&fulljson={' # URL of your emon device
|
||||||
|
emon_apikey = "e5fe98dec735e5fa17139805d902517e" # add your key here for RW access
|
||||||
|
|
||||||
|
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 1) # port name, slave address
|
||||||
|
|
||||||
|
instrument.serial.baudrate = 9600 # Baud
|
||||||
|
instrument.serial.bytesize = 8
|
||||||
|
instrument.serial.parity = serial.PARITY_NONE
|
||||||
|
instrument.serial.stopbits = 1
|
||||||
|
instrument.serial.timeout = 0.5 # seconds
|
||||||
|
|
||||||
|
# while True:
|
||||||
|
success = False # Intialise Success/Failure Flag to ensure full data is only uploaded if all data is received.
|
||||||
|
|
||||||
|
Inverter_Freq = instrument.read_register(0x20c, 0, functioncode=3, signed=False) / 100.0 # read inverter frequency
|
||||||
|
|
||||||
|
Battery_ChargeDischargePwr = instrument.read_register(0x20d, 0, functioncode=3, signed=True) * 10.0 # read battery charge discharge pwr
|
||||||
|
Battery_Cycles = instrument.read_register(0x22c, 0, functioncode=3, signed=False) # read times batteries have been cycled
|
||||||
|
Battery_ChrgLevel = instrument.read_register(0x210, 0, functioncode=3, signed=False) # read battery charge level
|
||||||
|
Battery_Temp = instrument.read_register(0X211, 0, functioncode=3, signed=True) #Read Battery Temperature as Signed 16-Bit
|
||||||
|
|
||||||
|
Grid_IO_Pwr = instrument.read_register(0x212, 0, functioncode=3, signed=True) * 10.0 # read total grid pwr
|
||||||
|
|
||||||
|
House_Consumption_Pwr = instrument.read_register(0x213, 0, functioncode=3, signed=False) * 10.0 # read load pwr
|
||||||
|
|
||||||
|
Internal_IO_Pwr = instrument.read_register(0x214, 0, functioncode=3, signed=True) * 10.0 # read internal system I/O pwr
|
||||||
|
|
||||||
|
PV_Generation_Pwr = instrument.read_register(0x215, 0, functioncode=3, signed=False) * 10.0 # read SolarPV Generation Pwr
|
||||||
|
|
||||||
|
EPS_Output_V = instrument.read_register(0x216, 0, functioncode=3, signed=False) / 10.0 # read EPS Output volts
|
||||||
|
EPS_Output_Pwr = instrument.read_register(0x217, 0, functioncode=3, signed=False) * 10.0 # read EPS Output pwr
|
||||||
|
|
||||||
|
TodayGenerated_KWh = instrument.read_register(0x218, 0, functioncode=3, signed=False) / 100.0 # read Today's generation kWh
|
||||||
|
TodaySold_KWh = instrument.read_register(0x219, 0, functioncode=3, signed=False) / 100.0 # read Today's Generation sold kWh
|
||||||
|
TodayBought_KWh = instrument.read_register(0x21a, 0, functioncode=3, signed=False) / 100.0 # read Today's Power bought kWh
|
||||||
|
TodayConsumption_KWh = instrument.read_register(0x21b, 0, functioncode=3, signed=False) / 100.0 # read Today's consumption bought kWh
|
||||||
|
|
||||||
|
TotalLoadConsumption = instrument.read_register(0x222, 0, functioncode=3, signed=False) * 0xffff # Total Load Consumption kWh HighByte
|
||||||
|
TotalLoadConsumption = TotalLoadConsumption + instrument.read_register(0x223, 0, functioncode=3, signed=False) # Total Load Consumption kWh LowByte
|
||||||
|
|
||||||
|
InverterInternalTemp = instrument.read_register(0x238, 0, functioncode=3, signed=False) # Inverter Internal Temperature
|
||||||
|
InverterHeatsinkTemp = instrument.read_register(0x239, 0, functioncode=3, signed=False) # Inverter Heatsink Temperature
|
||||||
|
|
||||||
|
# try:
|
||||||
|
|
||||||
|
##Flag to stream all data to EmonHub
|
||||||
|
success = True
|
||||||
|
|
||||||
|
# except:
|
||||||
|
##EXCEPTION WILL OCCUR WHEN INVERTER SHUTS DOWN WHEN PANELS ARE OFF
|
||||||
|
|
||||||
|
##Flag to stream restricted data to EmonHub
|
||||||
|
|
||||||
|
### END COLLECT DATA FROM SOFAR INVERTER ###
|
||||||
|
|
||||||
|
# Add the variables into the URL
|
||||||
|
Grid_PwrStr = str(Grid_IO_Pwr)
|
||||||
|
House_Consumption_PwrStr = str(House_Consumption_Pwr)
|
||||||
|
Internal_IO_PwrStr = str(Internal_IO_Pwr)
|
||||||
|
PV_Generation_PwrStr = str(PV_Generation_Pwr)
|
||||||
|
EPS_Output_VStr = str(EPS_Output_V)
|
||||||
|
EPS_Output_PwrStr = str(EPS_Output_Pwr)
|
||||||
|
TodayGenerated_KWhStr = str(TodayGenerated_KWh)
|
||||||
|
TodaySold_KWhStr = str(TodaySold_KWh)
|
||||||
|
TodayBought_KWhStr = str(TodayBought_KWh)
|
||||||
|
TodayConsumption_KWhStr = str(TodayConsumption_KWh)
|
||||||
|
Battery_ChargeDischargePwrStr = str(Battery_ChargeDischargePwr)
|
||||||
|
Battery_CyclesStr = str(Battery_Cycles)
|
||||||
|
Battery_ChrgLevelStr = str(Battery_ChrgLevel)
|
||||||
|
InverterInternalTempStr = str(InverterInternalTemp)
|
||||||
|
InverterHeatsinkTempStr = str(InverterHeatsinkTemp)
|
||||||
|
Inverter_FreqStr = str(float("{:.1f}".format(Inverter_Freq)))
|
||||||
|
|
||||||
|
# print("Grid Power " + Grid_PwrStr + "W")
|
||||||
|
# print("House Consumption " + House_Consumption_PwrStr + "W")
|
||||||
|
# print("Solar PV Generation " + PV_Generation_PwrStr + "W")
|
||||||
|
# print("Internal I/O Power " + Internal_IO_PwrStr + "W")
|
||||||
|
# print("EPS Output Volts " + EPS_Output_VStr + "V")
|
||||||
|
# print("EPS Output Power " + EPS_Output_PwrStr + "W")
|
||||||
|
# print("Today's Generation " + TodayGenerated_KWhStr + "kWh")
|
||||||
|
# print("Today's Sold " + TodaySold_KWhStr + "kWh")
|
||||||
|
# print("Today's Bought " + TodayBought_KWhStr + "kWh")
|
||||||
|
# print("Today's Consuption " + TodayConsumption_KWhStr + "kWh")
|
||||||
|
# print("All time Consumption " + str(TotalLoadConsumption) + "kW")
|
||||||
|
|
||||||
|
# print("Battery Charge/Discharge Power " + Battery_ChargeDischargePwrStr + "W")
|
||||||
|
# print("Battery Cycles " + Battery_CyclesStr)
|
||||||
|
# print("Battery Charge Level " + Battery_ChrgLevelStr + "%")
|
||||||
|
# print("Inverter Internal Temp " + InverterInternalTempStr + "C")
|
||||||
|
# print("Inverter Heatsink Temp " + InverterHeatsinkTempStr + "C")
|
||||||
|
print("Grid Frequency " + Inverter_FreqStr + "Hz")
|
||||||
|
|
||||||
|
### STREAM RESULT TO EMONHUB ###
|
||||||
|
from urlparse import urlparse
|
||||||
|
# from urlparse import urljoin
|
||||||
|
|
||||||
|
# Component URL parts
|
||||||
|
str1 = "\"Grid Power\":" + Grid_PwrStr + ","
|
||||||
|
str2 = "\"House Consumption\":" + House_Consumption_PwrStr + ","
|
||||||
|
str3 = "\"Internal I/O Power\":" + Internal_IO_PwrStr + ","
|
||||||
|
str4 = "\"SolarPV Generation\":" + PV_Generation_PwrStr + ","
|
||||||
|
str5 = "\"EPS Output Volts\":" + EPS_Output_VStr + ","
|
||||||
|
str6 = "\"EPS Output Power\":" + EPS_Output_PwrStr + ","
|
||||||
|
str7 = "\"Today's Generation\":" + TodayGenerated_KWhStr + ","
|
||||||
|
str8 = "\"Today's Sold\":" + TodaySold_KWhStr + ","
|
||||||
|
str9 = "\"Today's Bought\":" + TodayBought_KWhStr + ","
|
||||||
|
str10 = "\"Today's Consumption\":" + TodayConsumption_KWhStr + ","
|
||||||
|
str11 = "\"Battery Charge/Discharge Power\":" + Battery_ChargeDischargePwrStr + ","
|
||||||
|
str12 = "\"Battery Cycles\":" + Battery_CyclesStr + ","
|
||||||
|
str13 = "\"Battery Charge Level\":" + Battery_ChrgLevelStr + ","
|
||||||
|
str14 = "\"Inverter Internal Temp\":" + InverterInternalTempStr + ","
|
||||||
|
str15 = "\"Inverter Heatsink Temp\":" + InverterHeatsinkTempStr + ","
|
||||||
|
str16 = "\"Grid Frequency\":" + Inverter_FreqStr
|
||||||
|
|
||||||
|
# Add the final part of the URL plus API key
|
||||||
|
strend = "}" + "&apikey=" + emon_apikey
|
||||||
|
|
||||||
|
# Construct the final URL
|
||||||
|
strTot = ubase + str1 + str2 + str3 + str4 + str5 + str6 + str7 + str8 + str9 + str10 + str11 + str12 + str13 + str14 + str15 + str16 + strend
|
||||||
|
|
||||||
|
udata = urlparse(strTot)
|
||||||
|
# print(udata.geturl())
|
||||||
|
import requests
|
||||||
|
# Think about using payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
|
||||||
|
# r = requests.get('https://httpbin.org/get', params=payload)
|
||||||
|
requests.put(udata.geturl())
|
||||||
|
|
||||||
|
## NOT SENT WHEN INVERTER TURNS OFF
|
||||||
|
# if success == True:
|
||||||
|
# header = "input/post?node=emontx&fulljson={"
|
||||||
|
# content =
|
||||||
|
# s.sendall(header + content)
|
||||||
|
# + str(B1) + ' ' + str(B2) + ' ' + str(B3) + ' ' + str(B4) + ' ' + str(C1) + ' ' + str(C2) + '\r\n')
|
||||||
|
|
||||||
|
# s.sendall('04 ' + str(A1) + ' ' + str(A2) + ' ' + str(A3) + ' ' + str(A4) + ' ' + str(D1) + ' ' + str(D2) + ' ' + str(E1) + ' ' + str(E2) + ' # ' + str(F1) + ' ' + str(F2) + ' ' + str(G1) + ' ' + str(G2) + ' ' + str(H1) + ' ' + str(H2) + ' ' + str(I1) + ' ' + str(I2) + '\r\n')
|
||||||
|
# s.close()
|
||||||
|
### END SEND TO EMON HUB #
|
||||||
|
# print("Sleeping...")
|
||||||
|
# time.sleep(10)
|
Loading…
Reference in New Issue