Files
SC200/sc200.py
Adrian Woodley c1770389f4 Initial commit
2016-12-15 12:52:35 +08:00

303 lines
8.8 KiB
Python
Executable File

#!/usr/bin/python3
from netaddr import IPNetwork
#from netaddr import IPAddress
from xmlrpc.client import ServerProxy
import sqlite3
import socket
import csv
import queue
import threading
import sys
import http.client
WORKERS = 10
if len(sys.argv) == 1:
Nets = [
'10.250.48.0/27',
'10.250.48.32/27',
'10.250.48.64/27',
'10.250.48.96/27',
'10.250.48.128/27',
'10.250.48.160/27',
'10.250.49.0/27',
'10.250.49.32/27',
'10.250.49.64/27',
'10.250.49.128/27',
'10.250.49.160/27',
'10.250.50.0/27',
'10.250.50.32/27',
'10.250.50.65/27',
'10.250.50.96/27',
'10.250.50.128/27',
'10.250.50.160/27',
'10.250.50.192/27',
'10.250.50.224/27',
'10.250.51.0/27',
'10.250.51.32/27',
'10.250.51.64/27',
'10.250.51.96/27',
'10.250.51.128/27',
'10.250.52.0/27',
'10.250.52.32/27',
'10.250.52.64/27',
'10.250.52.96/27',
'10.250.52.128/27',
'10.250.52.160/27',
'10.250.52.192/27'
]
else:
Nets = sys.argv[1:]
#Nets = [
#'10.250.48.0/27']
#print((Nets))
def Setup():
db.execute('''CREATE TABLE SC200 (
IP text PRIMARY KEY,
SiteName text,
SiteNotes text,
SerialNumber text,
FloatVoltage float,
OperatingVoltage float,
BatteryCapacity int,
ACRectifierCurrentLimit int,
HighFloatThreshold float,
EnableActiveVoltageControl bool,
EnableTemperatureCompensation bool,
TemperatureCompensationSlope float,
TemperatureCompensationReferenceTemperature float,
TemperatureCompensationUpperLimit float,
TemperatureCompensationLowerLimit float,
EnableEqualize bool,
EqualizeVoltage float,
EqualizeDuration int,
EnableFastCharge bool,
FastChargeVoltage float,
FastChargeVoltageThreshold float,
FastChargeAmpereHourThreshold int,
FastChargeRechargePercentage int,
FastChargeMaximumDuration int,
FastChargeAmpereHourStopThreshold int,
EnableBatterCurrentLimit bool,
BCLLimit int,
EnableBatterTest bool,
BatteryTestDuration int,
BatteryTestTerminationVoltage float,
LVDDisconnectVoltage float,
LVDReconnectVoltage float,
NumberOfRegisteredRectifiers int,
NumberOfRectifiersFailed int
)''')
SQL = '''CREATE TABLE AlarmNames (
SiteIP text primary key'''
for x in range(59):
SQL = SQL + ', Alarm' + repr(x) + ' text'
SQL = SQL + ')'
db.execute(SQL)
SQL = '''CREATE TABLE AlarmSeverities (
SiteIP text primary key'''
for x in range(59):
SQL = SQL + ', Alarm' + repr(x) + ' int'
SQL = SQL + ')'
db.execute(SQL)
def GetStatusCode(host, path="/"):
try:
conn = http.client.HTTPConnection(host)
conn.request("GET", path)
return conn.getresponse().status
except Exception:
return None
class Worker(threading.Thread):
def __init__(self, IPs, Results):
self.__IPs = IPs
self.__Results = Results
self.parent = threading.current_thread()
threading.Thread.__init__(self)
def run(self):
retry = False
socket.setdefaulttimeout(5)
#print ('Started')
while 1:
IP = self.__IPs.get()
#print((self.getName()))
if IP is None:
self.__Results.put(None)
#print('Exiting')
break
#s = socket.socket()
#if s.connect_ex((str(IP), 80)) == 0:
if GetStatusCode(str(IP), "/languages") == 200:
print((self.getName() + ' processing: ' + str(IP)))
#print(('Socket OK: %s' % IP))
#print(('%s' % IP))
while True:
proxy = ServerProxy('http://%s/xmlrpc' % IP)
try:
Values = proxy.db.get([
'Site-Name',
'Site-Notes',
'Serial-Number',
'Float-Voltage',
'Operating-Voltage',
'Battery-Capacity',
'AC-Rectifier-Current-Limit',
'High-Float-Threshold',
'Enable-Active-Voltage-Control',
'Enable-Temperature-Compensation',
'Temperature-Compensation-Slope',
'Temperature-Compensation-Reference-Temperature',
'Temperature-Compensation-Upper-Limit',
'Temperature-Compensation-Lower-Limit',
'Enable-Equalize',
'Equalize-Voltage',
'Equalize-Duration',
'Enable-Fast-Charge',
'Fast-Charge-Voltage',
'Fast-Charge-Voltage-Threshold',
'Fast-Charge-Ampere-Hour-Threshold',
'Fast-Charge-Recharge-Percentage',
'Fast-Charge-Maximum-Duration',
'Fast-Charge-Ampere-Hour-Stop-Threshold',
'Enable-Battery-Current-Limit',
'BCL-Limit',
'Enable-Battery-Test',
'Battery-Test-Duration',
'Battery-Test-Termination-Voltage',
'LVD-Disconnect-Voltage:1',
'LVD-Reconnect-Voltage:1',
'Number-Of-Registered-Rectifiers',
'Number-Of-Rectifiers-Failed'
])
except socket.timeout:
retry = True
continue
if retry:
retry = False
else:
break
if len(Values) > 0:
Values.insert(0, str(IP))
self.__Results.put(['SC200', Values])
AlarmNames = ['Alarm-Name:' + repr(x) for x in range(59)]
while True:
try:
Values = proxy.db.get(AlarmNames)
except socket.timeout:
retry = True
continue
if retry:
retry = False
else:
break
Values.insert(0, str(IP))
self.__Results.put(['AlarmNames', Values])
AlarmSeverities = ['Alarm-Severity:' + repr(x)
for x in range(59)]
Values = proxy.db.get(AlarmSeverities)
Values.insert(0, str(IP))
self.__Results.put(['AlarmSeverities', Values])
#s.close()
else:
print((self.getName() + ' skipping: ' + str(IP)))
def Loader():
Count = WORKERS
c = db.cursor()
while 1:
Row = Results.get()
if Row is None:
if Count > 1:
Count -= 1
print(Count)
else:
break
else:
print(('Loading: %s %s' % (Row[1][0], Row[0])))
SQL = 'INSERT INTO %s VALUES (' % Row[0]
for i in Row[1]:
SQL += '?,'
SQL = SQL[:-1]
SQL += ')'
c.execute(SQL, Row[1])
db.commit()
def Output():
c = db.cursor()
with open('/tmp/sc200.csv', 'w', newline='') as outFile:
csvWriter = csv.writer(outFile, delimiter=',', quotechar='"',
quoting=csv.QUOTE_MINIMAL)
c.execute('''SELECT * FROM SC200 ORDER BY IP''')
csvWriter.writerow([col[0] for col in c.description])
for row in c:
csvWriter.writerow(row)
outFile.close()
with open('/tmp/sc200-alarms.csv', 'w', newline='') as outFile:
csvWriter = csv.writer(outFile, delimiter=',', quotechar='"',
quoting=csv.QUOTE_MINIMAL)
c.execute('''SELECT * FROM AlarmNames LIMIT 1''')
for row in c:
csvWriter.writerow(row)
c.execute('''SELECT * FROM AlarmSeverities''')
for row in c:
csvWriter.writerow(row)
outFile.close()
db = sqlite3.connect(':memory:')
#db = sqlite3.connect('/tmp/sc200.db')
Setup()
IPs = queue.Queue(0)
Results = queue.Queue(0)
for i in range(WORKERS):
Worker(IPs, Results).start()
for SubNet in Nets:
Net = IPNetwork(SubNet)
for IP in Net:
if IP != Net.network and IP != Net.broadcast:
#print(('Queued: ' + str(IP)))
IPs.put(IP)
for i in range(WORKERS):
IPs.put(None)
if threading.current_thread() is not threading.main_thread():
sys.exit(0)
Loader()
Output()
sys.exit(0)