Skip to content
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
157 changes: 79 additions & 78 deletions DeltaPVOutput.py
Original file line number Diff line number Diff line change
@@ -1,78 +1,79 @@
#A simple script to read values from a delta inverter and post them to
#PVoutput.org

import time, subprocess,serial,argparse,sys
from deltaInv import DeltaInverter
from time import localtime, strftime

#PVOutput.org API Values - UPDATE THESE TO YOURS!
SYSTEMID=""
APIKEY=""

parser = argparse.ArgumentParser()

if __name__ == '__main__':

parser.add_argument('-v','--verbose',help='Enable verbose output to stderr',default=False,dest='verbose_mode',required=False,action='store_true')
parser_results = parser.parse_args()

#Edit your serial connection as required!!
connection = serial.Serial('/dev/ttyUSB0',19200,timeout=0.2);
localtime = time.localtime(time.time())

t_date = 'd={0}'.format(strftime('%Y%m%d'))
t_time = 't={0}'.format(strftime('%H:%M'))

inv1 = DeltaInverter(1) #init Inverter 1
#Get the Daily Energy thus far
cmd = inv1.getCmdStringFor('Day Wh')
connection.write(cmd)
response = connection.read(100)
#if no response the inverter is asleep
if response:
value = inv1.getValueFromResponse(response)
t_energy = 'v1={0}'.format(value)

#instanteous power
cmd = inv1.getCmdStringFor('AC Power')
connection.write(cmd)
response = connection.read(100)
value = inv1.getValueFromResponse(response)
t_power = 'v2={0}'.format(value)

#AC Voltage
cmd = inv1.getCmdStringFor('AC Volts')
connection.write(cmd)
response = connection.read(100)
value = inv1.getValueFromResponse(response)
t_volts = 'v6={0}'.format(value)

#Temp - this appears to be onboard somewhere not the heatsink
cmd = inv1.getCmdStringFor('DC Temp')
connection.write(cmd)
response = connection.read(100)
value = inv1.getValueFromResponse(response)
t_temp = 'v5={0}'.format(value)

#if verbose mode
if parser_results.verbose_mode==True:
sys.stderr.write('Date: %s, Time: %s\n' %(t_date, t_time))
sys.stderr.write('Energy Today: %sWh, Instantaneous Power: %sW\n' %(t_energy,t_power))
sys.stderr.write('Volts: %s, Temp: %s oC\n' % (t_volts,t_temp))
sys.stderr.flush()

#Send it all off to PVOutput.org
cmd = ['/usr/bin/curl',
'-d', t_date,
'-d', t_time,
'-d', t_energy,
'-d', t_power,
'-d', t_volts,
'-d', t_temp,
'-H', 'X-Pvoutput-Apikey: ' + APIKEY,
'-H', 'X-Pvoutput-SystemId: ' + SYSTEMID,
'http://pvoutput.org/service/r1/addstatus.jsp']
ret = subprocess.call (cmd)
else:
print "No response from inverter - shutdown? No Data sent to PVOutput.org"
connection.close()
#A simple script to read values from a delta inverter and post them to
#PVoutput.org

import time, subprocess,serial,argparse,sys
from deltaInv import DeltaInverter
from time import localtime, strftime

#PVOutput.org API Values - UPDATE THESE TO YOURS!
SYSTEMID=""
APIKEY=""

parser = argparse.ArgumentParser()

if __name__ == '__main__':

parser.add_argument('-v','--verbose',help='Enable verbose output to stderr',default=False,dest='verbose_mode',required=False,action='store_true')
parser_results = parser.parse_args()

#Edit your serial connection as required!!
connection = serial.Serial('/dev/ttyUSB0',19200,timeout=0.2);
localtime = time.localtime(time.time())

t_date = 'd={0}'.format(strftime('%Y%m%d'))
t_time = 't={0}'.format(strftime('%H:%M'))

inv1 = DeltaInverter(1) #init Inverter 1
#Get the Daily Energy thus far
cmd = inv1.getCmdStringFor('Day Wh')
connection.write(cmd)
response = connection.read(100)
#if no response the inverter is asleep
if response:
value = inv1.getValueFromResponse(response)
t_energy = 'v1={0}'.format(value)

#instanteous power
cmd = inv1.getCmdStringFor('AC Power')
connection.write(cmd)
response = connection.read(100)
value = inv1.getValueFromResponse(response)
t_power = 'v2={0}'.format(value)

#AC Voltage
cmd = inv1.getCmdStringFor('AC Volts')
connection.write(cmd)
response = connection.read(100)
value = inv1.getValueFromResponse(response)
t_volts = 'v6={0}'.format(value)

#Temp - this appears to be onboard somewhere not the heatsink
cmd = inv1.getCmdStringFor('DC Temp')
connection.write(cmd)
response = connection.read(100)
value = inv1.getValueFromResponse(response)
t_temp = 'v5={0}'.format(value)

#if verbose mode
if parser_results.verbose_mode==True:
sys.stderr.write('Date: %s, Time: %s\n' %(t_date, t_time))
sys.stderr.write('Energy Today: %sWh, Instantaneous Power: %sW\n' %(t_energy,t_power))
sys.stderr.write('Volts: %s, Temp: %s oC\n' % (t_volts,t_temp))
sys.stderr.flush()

#Send it all off to PVOutput.org
cmd = ['/usr/bin/curl',
'-d', t_date,
'-d', t_time,
'-d', t_energy,
'-d', t_power,
'-d', t_volts,
'-d', t_temp,
'-H', 'X-Pvoutput-Apikey: ' + APIKEY,
'-H', 'X-Pvoutput-SystemId: ' + SYSTEMID,
'http://pvoutput.org/service/r1/addstatus.jsp']
ret = subprocess.call (cmd)
else:
print ("No response from inverter - shutdown? No Data sent to PVOutput.org")
connection.close()

109 changes: 55 additions & 54 deletions crc.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,55 @@
class CRC16:

INITIAL_MODBUS = 0xFFFF
INITIAL_DF1 = 0x0000

table = (
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 )

def calcByte(self, ch, crc):
"""Given a new Byte and previous CRC, Calc a new CRC-16"""
if type(ch) == type("c"):
by = ord( ch)
else:
by = ch
crc = (crc >> 8) ^ self.table[(crc ^ by) & 0xFF]
return (crc & 0xFFFF)

def calcString(self, st, crc=INITIAL_DF1):
"""Given a bunary string and starting CRC, Calc a final CRC-16 """
for ch in st:
crc = (crc >> 8) ^ self.table[(crc ^ ord(ch)) & 0xFF]
return crc

class CRC16:

INITIAL_MODBUS = 0xFFFF
INITIAL_DF1 = 0x0000

table = (
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 )

def calcByte(self, byte, crc):
"""Given a new Byte and previous CRC, Calc a new CRC-16"""
if type(ch) == type("c"):
by = ord( ch)
else:
by = ch
crc = (crc >> 8) ^ self.table[(crc ^ by) & 0xFF]
return (crc & 0xFFFF)

def calcString(self, data, crc=INITIAL_DF1):
"""Given a bunary string and starting CRC, Calc a final CRC-16 """
for byte in data:
crc = (crc >> 8) ^ self.table[(crc ^ byte) & 0xFF]
return crc


Loading