emuland
| Inviato il: 17/05/2020 16:05:26
|
import serial, time
import struct, string
import shutil
import os
import csv
from ctypes import c_ubyte, c_ushort
from pathlib import Path
from serial import Serial
#String QPIGS = "\x51\x50\x49\x47\x53\xB7\xA9\x0D";
#String QPIWS = "\x51\x50\x49\x57\x53\xB4\xDA\x0D";
#String QDI = "\x51\x44\x49\x71\x1B\x0D";
#String QMOD = "\x51\x4D\x4F\x44\x49\xC1\x0D";
#String QVFW = "\x51\x56\x46\x57\x62\x99\x0D";
#String QVFW2 = "\x51\x56\x46\x57\x32\xC3\xF5\x0D";
#char username[] = "f";
#char password[] = "";
#char clientID[] = "";
#String POP02 = "\x50\x4F\x50\x30\x32\xE2\x0B\x0D"; //SBU priority
#String POP01 = "\x50\x4F\x50\x30\x32\xE2\xD2\x69"; //solar first
#String POP00 = "\x50\x4F\x50\x30\x30\xC2\x48\x0D"; //utility first
#from influxdb import InfluxDBClient
percorso=Path('./DATA.txt')
def CalcoloCRC( str ):
crc_ta = [ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, \
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef ]
lunghezza = len(str)
Calcolo = list(str)
crc = 0
for idx in range(0,lunghezza):
da=c_ubyte((c_ubyte(crc>>8).value)>>4).value
crc = c_ushort(crc << 4).value
crc = c_ushort(crc ^ crc_ta[da^c_ubyte(c_ubyte(ord(Calcolo[idx])).value >> 4).value]).value
da = (c_ubyte(crc>>8).value) >> 4
crc <<= 4
crc = c_ushort(crc ^ crc_ta[ da ^ ( ord(Calcolo[idx]) & 0x0f )]).value
bCRCLow = c_ubyte(crc).value
bCRCHign = c_ubyte(crc>>8).value
if ( bCRCLow==0x28 or bCRCLow==0x0d or bCRCLow==0x0a ):
bCRCLow += 1
if ( bCRCHign==0x28 or bCRCHign==0x0d or bCRCHign==0x0a ):
bCRCHign += 1
crc = c_ushort(bCRCHign).value << 8
crc += bCRCLow;
return crc
class Inverter:
def __init__(self,serialport):
self.ser = serial.Serial()
self.ser.port = serialport
self.ser.baudrate = 2400
self.ser.bytesize = serial.EIGHTBITS #number of bits per bytes
self.ser.parity = serial.PARITY_NONE #set parity check: no parity
self.ser.stopbits = serial.STOPBITS_ONE #number of stop bits
self.ser.timeout = 1 #non-block read
self.ser.xonxoff = False #disable software flow control
self.ser.rtscts = False #disable hardware (RTS/CTS) flow control
self.ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
self.ser.writeTimeout = 2 #timeout for write
try:
self.ser.open()
print("connesso")
except Exception as e:
print ("error open serial port: " + str(e))
exit()
if self.ser.isOpen():
try:
print("pulisco input e output")
self.ser.flushInput() #flush input buffer, discarding all its contents
self.ser.flushOutput() #flush output buffer, aborting current output
#and discard all that is in buffer
except Exception as e1:
# print ("error communicating...: " )
print ("error communicating...: " + str(e1))
else:
print ("cannot open serial port ")
def QueryCMD(self,CMD):
# try:
print ("invio comandi")
print (CMD)
QPIGS = b"\x51\x50\x49\x47\x53\xB7\xA9\x0D";
#TEST= QPIGS.encode("QPIGS")
#send= CMD + struct.pack('!H',CalcoloCRC(CMD))
#self.ser.write(CMD + struct.pack('!H',CalcoloCRC(CMD)) + '\x0D')
#self.ser.write(CMD)
self.ser.write(CMD)
time.sleep(2) #give the serial port sometime to receive the data
self.response =( self.ser.readline())
#bytetostring= str(self.response, "utf-8")
#print (bytetostring)
#risposta= self.ser.readline()
#print (risposta)
#print ("response" + str(self.response) )
tronca= self.response[2:len(self.response)-5]
print (tronca)
return str(tronca)
#c= str(self.response.decode('utf-8'))
#print (c)
#self.CRCSENT = ord(self.response[-3]) * 256 + ord(self.response[-2])
#if ( CalcoloCRC(self.response[:-3]) == self.CRCSENT ):
# return self.response[:-3]
# print ("crc passato")
#else:
# return -1
# print ("crc errato")
#except:
# print ("eccezione!!!")
#return -1
def Update(self):
print ("aggiorno")
#qpigs= str.encode("QPIGS")
CMD = self.QueryCMD(b"\x51\x50\x49\x47\x53\xB7\xA9\x0D")
print("cmd ricevuto: ")
#CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
# bytetostring= str(CMD, "utf-8")
# print (bytetostring)
#CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
print (CMD)
if(CMD == -1):
print("errorer lettura dati gpigs")
return -1
print ("qpigs ok")
#print (CMD)
#CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
all = str.split(CMD[1:])
self.grid_voltage = float(all[0+1])
print ("grid votl")
print (self.grid_voltage)
self.grid_frequency = float(all[1])
self.ac_output_voltage = float(all[2])
self.ac_output_frequency = float(all[3])
self.ac_output_apparent_power = int(all[4])
self.ac_output_active_power = int(all[5])
self.output_load_percent = int(all[6])
self.bus_voltage = float(all[7])
self.battery_voltage = float(all[8])
self.battery_charging_current = int(all[9])
self.battery_capacity = int(all[10])
self.heatsink_temperature = int(all[11])
self.pv_current = int(all[12])
self.pv_voltage = float(all[13])
self.battery_voltage_scc = float(all[14])
self.battery_discharge_current = int(all[15])
self.pv_power = int(all[19])
self.line_power = self.ac_output_active_power - self.pv_power
CMD = self.QueryCMD(b"\x51\x4D\x4F\x44\x49\xC1\x0D")
print ("QMOD REQUEST")
if (CMD == -1):
print ("qmod errato")
return -1
#CMD="230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
mode = CMD[1:]
self.isLineMode = 0
if ( mode == "L" ):
print ("line mode")
self.isLineMode = 1
self.isBatteryMode = 0
if ( mode == "B" ):
print ("battery mode")
self.isBatteryMode = 1
CMD = self.QueryCMD(b"\x51\x50\x49\x57\x53\xB4\xDA\x0D")
print ("QPIWS request")
#CMD= "230.1 50.0 230.4 50.0 1474 1444 036 395 50.20 000 080 0038 0007 081.0 50.34 00025 00010110 00 00 00357 010"
if (CMD == -1):
print ("QPIWS")
print ("ERRORE QPIWS")
return -1
self.inverter_fault = CMD[1:2]
self.BusOvervolt = CMD[2:3]
self.BusUndervolt = CMD[3:4]
self.SoftStartFail = CMD[4:5]
self.LineFail = CMD[5:6]
self.PvShort = CMD[6:7]
self.InvVoltLow = CMD[7:8]
self.InvVolrHigh = CMD[8:9]
self.OverTemp = CMD[9:10]
self.BatteryVoltHigh = CMD[10:11]
self.BatteryVoltLow = CMD[11:12]
return 0
#####################################################################
## ##
## MAIN ##
#####################################################################
sp5000 = Inverter("COM1")
#client = InfluxDBClient('localhost', 񡌆', 'roor', '', 'fotovoltaico')
while True:
if (sp5000.Update() == 0):
#with open('DATA.txt', mode='a') as csv_file:
# fieldnames = ['grid_voltage','grid_frequency' ,'ac_output_voltage', 'ac_output_frequency', 'ac_output_frequency','ac_output_apparent_power', 'ac_output_active_power', 'output_load_percent','bus_voltage','battery_voltage','battery_charging_current','battery_capacity','heatsink_temperature','pv_current','pv_voltage','battery_voltage_scc','battery_discharge_current','isLineMode','isBatteryMod', 'inverter_fault','BusOvervolt','BusUndervolt','SoftStartFail','LineFail','PvShort','InvVoltLow','InvVolrHigh','OverTemp','BatteryVoltHigh','BatteryVoltLow','PvPower','LinePower']
# fieldnames=[]
# writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
# if percorso.is_file():
# writer.writerow({"grid_voltage":str(sp5000.grid_voltage),"grid_frequency": str(sp5000.grid_frequency),"ac_output_voltage": str(sp5000.ac_output_voltage),"ac_output_frequency": str(sp5000.ac_output_frequency),"ac_output_apparent_power": str(sp5000.ac_output_apparent_power), "ac_output_active_power": str(sp5000.ac_output_active_power), "output_load_percent": str(sp5000.output_load_percent), "bus_voltage": str(sp5000.bus_voltage), "battery_voltage": str(sp5000.battery_voltage), "battery_charging_current": str(sp5000.battery_charging_current), "battery_capacity": str(sp5000.battery_capacity), "heatsink_temperature": str(sp5000.heatsink_temperature),"pv_current": str(sp5000.pv_current), "pv_voltage": str(sp5000.pv_voltage), "battery_voltage_scc": str(sp5000.battery_voltage_scc), "battery_discharge_current": str(sp5000.battery_discharge_current), "isLineMode": str(sp5000.isLineMode), "isBatteryMod": str(sp5000.isBatteryMode), "inverter_fault": str(sp5000.inverter_fault),"BusOvervolt": str(sp5000.BusOvervolt),"BusUndervolt": str(sp5000.BusUndervolt), "SoftStartFail": str(sp5000.SoftStartFail),"LineFail": str(sp5000.LineFail),"PvShort": str(sp5000.PvShort), "InvVoltLow": str(sp5000.InvVoltLow), "InvVolrHigh": str(sp5000.InvVolrHigh), "OverTemp": str(sp5000.OverTemp), "BatteryVoltHigh": str(sp5000.BatteryVoltHigh), "BatteryVoltLow": str(sp5000.BatteryVoltLow), "PvPower": str(sp5000.pv_power), "LinePower": str(sp5000.line_power)
# })
# print ("sto salvando su file")
# else:
# writer.writeheader() # file doesn't exist yet, write a header
# print ("non sto scrivendo su file")
print("vado")
# str(sp5000.grid_voltage)
else:
print ("non ci siamo")
#client.write_points(json_body)
time.sleep(5)
il codice è quello originale, modificato per "funzionare" con pyton 3.7 64bit
non fa nulla se non stampare nella shell quello che legge.
se qualcuno ha un sistema di domotica, creando l'oggetto giusto può sparare i dati verso questo e vederli aggiornati (io ho domoticz, il problema grosso è che non ho ancora deciso di prendere l'inverter, anche se poco prima della pandeSUA stavo prendendo 2 48v in parallelo)
--------------- 4A per mmq per Legge Rane Fritte, cavallette, bagarozzi e cotillon! Venite fuori alla festa!
|