-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathread_pv.py
executable file
·132 lines (105 loc) · 5.4 KB
/
read_pv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# new improved version that should run in background and poll / post on timer loop rather than one-off via cron
import time
import ConfigParser
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
import requests
import paho.mqtt.client as mqtt
errcodes = {24: 'Auto Test Failed', 25:'No AC Connection', 26: 'PV Isolation Low', 27:'Residual Current High',
28:'DC Current High', 29: 'PV Voltage High', 30: 'AV V Outrange', 31: 'AC Freq Outrange', 32: 'Module Hot'}
# errcodes 1-23 are 'Error: (errorcode+99)
# read settings from config file
config = ConfigParser.ConfigParser()
config.read('/boot/pvoutput.txt')
SYSTEMID = config.get('pvoutput','SYSTEMID')
APIKEY = config.get('pvoutput','APIKEY')
port = config.get('connection','Inverter')
check = time.time()
interval = 300
com_str='None'
# connect to MQTT Broker
mqttc = mqtt.Client()
mqttc.connect(config.get('mqtt','broker'))
topic = config.get('mqtt','topic')
mqttc.loop_start()
# default state at poweron will be 'waiting'
laststate = 0
statetxt = {0: "Waiting", 1: "Normal", 3: "Fault"}
def post_pvoutput():
# we only attempt to upload to pvoutput if inverter online
if invstate == 1:
t_date = format(time.strftime('%Y%m%d'))
t_time = format(time.strftime('%H:%M'))
pv_headers = {'X-Pvoutput-Apikey': APIKEY, 'X-Pvoutput-SystemId':SYSTEMID }
payload1 = {'d':t_date, 't':t_time, 'v1':(info['Etoday']*1000), 'v2':info['Pac'], 'v5':info['Tinverter'], 'v6':info['Vpv1'], 'c1':0, 'v7':info['Vac1'], 'v8':info['Fac'] }
r = requests.post('http://pvoutput.org/service/r2/addstatus.jsp',headers=pv_headers,data=payload1)
print r.content,payload1
else:
print "Not uploading to pvoutput - Inverter Status != Normal"
# Read data from inverter
# pdf says that we can't read more than 45 registers in one go.
inverter = ModbusClient(method='rtu', port=port, baudrate=9600, stopbits=1, parity='N', bytesize=8, timeout=1)
inverter.connect()
while True:
try:
now = time.time()
info = {} # we'll build this up with the parsed output from the registers
rr = inverter.read_input_registers(0,33)
#print rr.registers
invstate=rr.registers[0]
info['Status'] = statetxt[invstate]
mqttc.publish(topic + '/status', statetxt[invstate])
if (invstate != laststate):
print "Changed state from %s to %s" % (laststate, invstate)
pushover = {'token':config.get('pushover','app_token'), 'user':config.get('pushover','user_key'), 'title': 'Inverter debug', 'priority': -1,
'message': "State changed from " + statetxt[laststate] + " to "+ statetxt[invstate], 'url':'http://pvoutput.org/intraday.jsp?sid=22888'}
r = requests.post('https://api.pushover.net/1/messages.json',data=pushover)
print r.content
if invstate == 3:
EC = inverter.read_input_registers(40,1)
if 1 <= EC <= 23: # No specific text defined
errstr = "Error Code " + str(99+EC)
else:
errstr = errcodes[EC.registers[0]]
print "Inverter FAULT: %s" % errstr
pushover = {'token':config.get('pushover','app_token'), 'user':config.get('pushover','user_key'), 'title': 'Inverter Fault', 'message': errstr }
r = requests.post('https://api.pushover.net/1/messages.json',data=pushover)
print r.content
laststate = invstate
info['Ppv'] = float((rr.registers[1]<<16) + rr.registers[2])/10 # Input Power
info['Vpv1'] = float(rr.registers[3])/10 # PV1 Voltage
info['PV1Curr'] = float(rr.registers[4])/10 # PV1 Input Current
info['PV1Watt'] = float((rr.registers[5]<<16) + rr.registers[6])/10 # PV1 input watt
# PV2 would be the same, but I only have one string connected
#info['Vpv2'] = float(rr.registers[7])/10
#info['PV2Curr'] = float(rr.registers[8])/10
#info['PV2Watt'] = float((rr.registers[9]<<16) + rr.registers[10])/10
# Total outputs for the inverter
info['Pac'] = float((rr.registers[11]<<16) + rr.registers[12])/10 # Output Power
info['Fac'] = float(rr.registers[13])/100 # Grid Frequency
# Single phase users just see the 1st set of these
info['Vac1'] = float(rr.registers[14])/10 # Single Phase (L1) grid voltage
info['Iac1'] = float(rr.registers[15])/10 # Single Phase (L1) grid output current
info['Pac1'] = float((rr.registers[16]<<16) + rr.registers[17])/10 # Single Phase (L1) grid output watt
#info['Vac2'] = float(rr.registers[18])/10 # L2 grid voltage
#info['Iac2'] = float(rr.registers[19])/10 # L2 grid output current
#info['Pac2'] = float((rr.registers[20]<<16) + rr.registers[21])/10 # L2 grid output watt
#info['Vac3'] = float(rr.registers[22])/10 # L3 grid voltage
#info['Iac3'] = float(rr.registers[23])/10 # L3 grid output current
#info['Pac3'] = float((rr.registers[24]<<16) + rr.registers[25])/10 # L3 grid output watt
info['Etoday'] = float((rr.registers[26]<<16) + rr.registers[27])/10
info['Etotal'] = float((rr.registers[28]<<16) + rr.registers[29])/10
info['ttotal'] = float((rr.registers[30]<<16) + rr.registers[31])/2 # seconds
info['Tinverter'] = float(rr.registers[32])/10 # Inverter temp
#print info
mqttc.publish(topic + '/raw', str(info))
if (((now - check) % interval) < 2):
post_pvoutput()
check = now
#except SerialException:
except:
print 'Serial Read Error?'
time.sleep(1)
mqttc.loop_stop()
inverter.close()