rasolar/logger.py

321 lines
10 KiB
Python
Raw Normal View History

2019-05-23 07:26:30 -07:00
#!/usr/bin/env python
2019-05-26 20:55:16 -07:00
import numpy as np
2019-06-05 03:46:26 -07:00
import os, serial,time,socket,sys,json,logging,requests
import smbus2,bme280,getopt
2019-06-04 02:33:59 -07:00
# import the server implementation
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# import ADC
from Adafruit_ADS1x15 import ADS1115
2019-06-05 03:46:26 -07:00
from Adafruit_ADS1x15 import ADS1015
2019-06-04 20:47:41 -07:00
import vedirect
2019-06-05 12:52:30 -07:00
def upload_osm(sensor_id,value):
url="https://ingress.opensensemap.org/boxes/%s/%s" % (sensebox_id,sensor_id)
r = requests.post(url,json={'value': value})
if r.status_code != requests.codes.ok:
print("Error %d: %s" % (r.status_code,r.text))
2019-06-03 20:30:58 -07:00
2019-06-05 19:32:48 -07:00
configfile="config.json"
2019-06-05 03:46:26 -07:00
cf=open(configfile,"r")
log_conf=json.load(cf)
cf.close()
channel_names=["time","CPU_temp"]
2019-06-05 06:37:21 -07:00
devicename=socket.gethostname()
if "device" in log_conf:
devicename=log_conf['device']
2019-06-04 02:33:59 -07:00
2019-05-23 07:26:30 -07:00
a = 2
2019-06-04 02:33:59 -07:00
# push options to internet
2019-06-05 03:46:26 -07:00
bosm=False
if "opensensemap" in log_conf:
bosm=True
conf_osm=log_conf['opensensemap']
if "enable" in conf_osm:
if conf_osm['enable'] == 0:
bosm = False
try:
push_count=conf_osm['push_count']
except:
push_count=20 # wait 5 cycles till upload to opensensemap
push_counter=0
sensebox_id=conf_osm['sensebox_id'] # id of opensensemap
push_vars=conf_osm['sensors'].keys()
push_data={}
push_mean_counts={}
sensebox_sid={}
for i in push_vars:
push_data[i]=0
push_mean_counts[i]=0
sensebox_sid[i]=conf_osm['sensors'][i]
#luftdaten_id=56009074600018881
2019-06-04 02:33:59 -07:00
# host and port of internal logging server
2019-06-05 03:46:26 -07:00
bsql=False
if "sqlserver" in log_conf:
bsql=True
if "enable" in log_conf['sqlserver']:
if log_conf['sqlserver']['enable'] == 0:
bsql=False
sqlhost=log_conf['sqlserver']['host']
sqlport=log_conf['sqlserver']['port']
2019-06-04 02:33:59 -07:00
# config of bme280 sensor
2019-06-05 03:46:26 -07:00
bbme=False
if "bme280" in log_conf:
bbme=True
if "enable" in log_conf['bme280']:
if log_conf['bme280']['enable'] == 0:
bbme=False
if "port" in log_conf['bme280']:
bme_port=log_conf['bme280']['port']
else:
bme_port=1
if "address" in log_conf['bme280']:
2019-06-05 12:52:30 -07:00
bme_add=int(log_conf['bme280']['address'],16)
2019-06-05 03:46:26 -07:00
else:
bme_add=0x77
try:
bme_bus=smbus2.SMBus(bme_port)
except:
bbme=False
else:
calibration_params=bme280.load_calibration_params(bme_bus,bme_add)
channel_names.append("temperature")
channel_names.append("humidity")
channel_names.append("pressure")
2019-05-23 07:26:30 -07:00
# configure the client logging
logging.basicConfig()
log = logging.getLogger('./modbus.error')
log.setLevel(logging.ERROR)
2019-06-05 03:46:26 -07:00
# configure tristar
btristar=False
if "tristar" in log_conf:
btristar=True
if "enable" in log_conf['tristar']:
if log_conf['tristar']['enable'] == 0:
btristar=False
2019-06-05 12:52:30 -07:00
tri_port='/dev/ttyUSB0'
2019-06-05 03:46:26 -07:00
if "port" in log_conf['tristar']:
tri_port=log_conf['tristar']['port']
2019-06-05 12:52:30 -07:00
tri_baud=9600
2019-06-05 03:46:26 -07:00
if "baud" in log_conf['tristar']:
tri_baud=log_conf['tristar']['baud']
2019-06-05 12:52:30 -07:00
tri_timeout=1
2019-06-05 03:46:26 -07:00
if "timeout" in log_conf['tristar']:
tri_timeout=log_conf['tristar']['timeout']
try:
triclient = ModbusClient(method='rtu', port=tri_port, baudrate=tri_baud, timeout=tri_timeout)
except:
btristar=False
else:
triclient.connect()
2019-06-05 12:52:30 -07:00
for i in ["volt_scale","amp_scale","volt_bat_term","volt_bat_sens","volt_arr","amp_bat","amp_arr","temp_heatsink","temp_bat","ah_res","ah_tot","kwh_res","kwh_tot","watt_in","watt_out","hour_tot","state","volt_sweep_mp","volt_sweep_oc"]:
channel_names.append(i)
2019-06-05 03:46:26 -07:00
2019-06-03 20:30:58 -07:00
# declare ve mppt
2019-06-04 20:09:54 -07:00
bve=False
2019-06-05 03:46:26 -07:00
if "vedirect" in log_conf:
bve=True
if "enable" in log_conf['vedirect']:
if log_conf['vedirect']['enable'] == 0:
bve=False
if "port" in log_conf['vedirect']:
bve_port=log_conf['vedirect']['port']
else:
bve_port='/dev/serial/by-id/usb-VictronEnergy_BV_VE_Direct_cable_VE1SSBVT-if00-port0'
try:
ve=vedirect(bve_port,60)
except:
bve=False
else:
for i in ["volt_bat_ve","volt_arr_ve","amp_ve","watt_ve","days_ve"]:
2019-06-05 12:52:30 -07:00
channel_names.append(i)
2019-06-03 20:30:58 -07:00
2019-05-26 07:33:17 -07:00
# declare adc
2019-06-05 03:46:26 -07:00
badc=False
if "ads1x15" in log_conf:
badc=True
adc={}
if "enable" in log_conf['ads1x15']:
if log_conf['ads1x15']['enable'] == 0:
badc=False
if "gain" in log_conf['ads1x15']:
GAIN=log_conf['ads1x15']['gain']
else:
GAIN=1
if "adc" in log_conf['ads1x15']:
adc_count=0
2019-06-05 12:52:30 -07:00
tadc=log_conf['ads1x15']['adc']
for x in tadc:
y=tadc[x]
2019-06-05 03:46:26 -07:00
adc_address=0x48
if "address" in y:
2019-06-05 12:52:30 -07:00
adc_address=int(y['address'],16)
2019-06-05 03:46:26 -07:00
abc_bus=1
if "busnum" in y:
adc_bus=y['busnum']
adc_type=1015
if "type" in y:
adc_type=y['type']
adc_assigned=False
if adc_type == 1115:
try:
adc[adc_count]=ADS1115(address=adc_address,busnum=adc_bus)
adc_assigned=True
except:
print("could not assign ADC")
if adc_type == 1015:
try:
adc[adc_count]=ADS1015(address=adc_address,busnum=adc_bus)
adc_assigned=True
except:
print("could not assign ADC")
if adc_assigned:
for j in range(4):
2019-06-05 12:52:30 -07:00
channel_names.append("a"+str(adc_count)+"_"+str(j))
adc_count=adc_count+1
2019-06-05 03:46:26 -07:00
else:
badc=False
2019-06-05 12:52:30 -07:00
2019-05-26 07:33:17 -07:00
2019-05-26 20:55:16 -07:00
ch_val=np.zeros(len(channel_names))
2019-05-27 10:17:56 -07:00
for i in range(len(channel_names)):
ch_val[i]=(-1)
2019-05-26 20:48:39 -07:00
2019-05-23 07:26:30 -07:00
while a > 1:
2019-06-04 07:31:35 -07:00
# copy channel values to backup
2019-05-27 06:47:11 -07:00
ch_old=ch_val.copy()
2019-05-27 01:17:57 -07:00
# set actual time
timestamp=int(1000*time.time())
2019-05-27 06:47:11 -07:00
ch_val[channel_names.index("time")]=timestamp
2019-05-26 07:33:17 -07:00
2019-05-27 01:17:57 -07:00
# get cpu temperature
2019-05-26 07:33:17 -07:00
tempC=0
2019-05-26 09:55:53 -07:00
tFile = open('/sys/class/thermal/thermal_zone0/temp')
2019-05-26 20:55:16 -07:00
ch_val[channel_names.index("CPU_temp")] = float(tFile.read())
2019-05-26 09:55:53 -07:00
tFile.close()
2019-05-26 07:33:17 -07:00
# read adc's
2019-06-05 03:46:26 -07:00
if badc:
2019-06-05 12:52:30 -07:00
for i in adc:
cname="a"+str(i)+"_{0}"
2019-06-05 03:46:26 -07:00
for j in range(4):
2019-06-05 12:52:30 -07:00
ch_val[channel_names.index(cname.format(j))]=adc[i].read_adc(j,gain=GAIN)
2019-05-26 07:33:17 -07:00
2019-06-04 02:33:59 -07:00
if btristar:
2019-06-04 07:13:17 -07:00
try:
2019-06-05 03:46:26 -07:00
rr = triclient.read_holding_registers(0,90,unit=1)
2019-06-04 07:13:17 -07:00
except:
print("could not get data from tristar")
else:
2019-06-05 12:52:30 -07:00
try:
ch_val[channel_names.index("volt_scale")]=rr.registers[0]*65536+rr.registers[1]
except:
print("could not read from tristar")
else:
ch_val[channel_names.index("amp_scale")]= rr.registers[2]*65536+rr.registers[3]
ch_val[channel_names.index("volt_bat_term")]=rr.registers[25]
ch_val[channel_names.index("volt_bat_sens")]=rr.registers[26]
ch_val[channel_names.index("volt_arr")]=rr.registers[27] # Array voltage
ch_val[channel_names.index("amp_bat")]=rr.registers[28] # Battery current
ch_val[channel_names.index("amp_arr")]=rr.registers[29] # Array current
ch_val[channel_names.index("temp_heatsink")]=rr.registers[35] # Temperature heatsink
ch_val[channel_names.index("temp_bat")]=rr.registers[36] # Temperature battery
ch_val[channel_names.index("ah_res")]=rr.registers[52] * 65536 + rr.registers[53] # Ah resetable
ch_val[channel_names.index("ah_tot")]=rr.registers[54] * 65536 + rr.registers[55] # Ah total
ch_val[channel_names.index("kwh_res")]=rr.registers[56] # kwh resetable
ch_val[channel_names.index("kwh_tot")]=rr.registers[57] # kwh total
ch_val[channel_names.index("watt_in")]=rr.registers[58] # Power in
ch_val[channel_names.index("watt_out")]=rr.registers[59] # Power out
ch_val[channel_names.index("hour_tot")]=rr.registers[42] * 65536 + rr.registers[43] # hour total
ch_val[channel_names.index("state")]=rr.registers[50] # State
ch_val[channel_names.index("volt_sweep_mp")]=rr.registers[61] # Array voltage
ch_val[channel_names.index("volt_sweep_oc")]=rr.registers[62] # Array voltage
2019-05-26 07:33:17 -07:00
# read bme280 (temperature, humidity, pressure)
2019-06-04 02:33:59 -07:00
if bbme:
bme_data=bme280.sample(bme_bus,bme_add,calibration_params)
ch_val[channel_names.index("temperature")]=int(1000*bme_data.temperature) # Temperature
ch_val[channel_names.index("pressure")]=int(1000*bme_data.pressure) # Pressure
ch_val[channel_names.index("humidity")]=int(1000*bme_data.humidity) # Humidity
2019-06-03 20:50:55 -07:00
# read ve data
2019-06-04 02:33:59 -07:00
if bve:
2019-06-04 20:09:54 -07:00
try:
vedata=ve.read_data_single()
except:
print("could not read VE")
else:
ch_val[channel_names.index("volt_bat_ve")]=int(vedata['V']) # Battery voltage measured by ve
ch_val[channel_names.index("volt_arr_ve")]=int(vedata['VPV']) # Array voltage measured by ve
ch_val[channel_names.index("amp_ve")]=int(vedata['I']) # loading current by ve
ch_val[channel_names.index("watt_ve")]=int(vedata['PPV']) # Array power measured by ve
ch_val[channel_names.index("days_ve")]=int(vedata['HSDS']) # total days online ve
2019-06-03 20:50:55 -07:00
2019-06-03 06:43:48 -07:00
timefile=round(timestamp/3600000)
2019-05-27 01:17:57 -07:00
f1=open("/home/pi/log/data_{:d}.txt".format(int(timefile)),"a")
payload={}
2019-05-27 06:47:11 -07:00
for i in range(len(ch_val)):
2019-06-04 07:10:49 -07:00
if ch_val[i] != ch_old[i]:
f1.write(channel_names[i] + ":{0};".format(int(ch_val[i])))
if channel_names[i] != "time":
payload[channel_names[i]]=int(ch_val[i])
2019-06-05 03:46:26 -07:00
if channel_names[i] in push_vars and bosm:
2019-06-04 07:10:49 -07:00
if push_counter == push_count:
2019-06-04 07:33:39 -07:00
sense_data=push_data[channel_names[i]]/(1000*push_mean_counts[channel_names[i]])
2019-06-04 07:27:36 -07:00
upload_osm(sensebox_sid[channel_names[i]],round(sense_data,2))
2019-06-04 07:10:49 -07:00
push_data[channel_names[i]]=0
2019-06-04 07:27:36 -07:00
push_mean_counts[channel_names[i]]=0
2019-06-04 07:10:49 -07:00
else:
2019-06-04 07:27:36 -07:00
push_data[channel_names[i]]=push_data[channel_names[i]]+ch_val[i]
push_mean_counts[channel_names[i]]=push_mean_counts[channel_names[i]]+1
2019-05-27 01:17:57 -07:00
f1.write("\n")
f1.close()
2019-06-05 03:46:26 -07:00
if bsql:
2019-06-05 06:37:50 -07:00
json_out={"time": ch_val[channel_names.index("time")],"device": devicename,"payload":payload}
2019-06-05 03:46:26 -07:00
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("{}: could not connect to database".format(time.time()))
else:
s.connect((sqlhost, sqlport))
s.sendall(json.dumps(json_out))
s.close()
2019-05-26 07:33:17 -07:00
2019-05-27 01:17:57 -07:00
# volt_batt=rr.registers[24] * volt_scaling / 65536 / 32768
# volt_batt_t=rr.registers[25] * volt_scaling / 65536 / 32768
# volt_batt_sens=rr.registers[26] * volt_scaling / 65536 / 32768
# volt_arr=rr.registers[27] * volt_scaling / 65536 / 32768
# curr_batt=rr.registers[28] * amp_scaling / 65536 / 32768
# curr_arr=rr.registers[29] * amp_scaling / 65536 / 32768
# temp_heatsink=rr.registers[35]
# temp_batt=rr.registers[36]
# ah_reset = rr.registers[52] * 65536 + rr.registers[53]
# ah_total = rr.registers[54] * 65536 + rr.registers[55]
# kwh_reset = rr.registers[56]
# kwh_total = rr.registers[57]
# power_in = rr.registers[58] * volt_scaling * amp_scaling / 131072 / 65536 / 65536
# power_out = rr.registers[59] * volt_scaling * amp_scaling / 131072 / 65536 / 65536
# hourm = rr.registers[42]*65536+rr.registers[43]
# charge_state = rr.registers[50]
2019-05-26 07:34:38 -07:00
2019-06-04 07:27:36 -07:00
if push_counter>=push_count:
2019-06-04 20:09:54 -07:00
push_counter = 1
2019-06-04 02:33:59 -07:00
else:
2019-06-04 20:09:54 -07:00
push_counter=push_counter+1
2019-06-04 02:33:59 -07:00
2019-05-23 07:26:30 -07:00
time.sleep(5)
2019-05-26 07:33:17 -07:00
2019-05-23 07:26:30 -07:00
# close the client
client.close()
2019-05-26 07:33:17 -07:00
f1.close()
2019-05-23 07:26:30 -07:00
print("done")