#!/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)) Settings = [ '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' ] + \ ['Alarm-Name:' + repr(x) for x in range(59)] + \ ['Alarm-Severity:' + repr(x) for x in range(59)] def Setup(): db.execute('''CREATE TABLE SettingsValues ( IP TEXT, SettingsID TEXT, Value TEXT)''') #db.execute('''CREATE TABLE Settings ( #ID INTEGER PRIMARY KEY, #Name TEXT UNIQUE)''') #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(Settings) 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]) #print((list(zip(Settings, Row[1][1:])))) c.executemany('INSERT INTO SettingsValues VALUES ( \'%s\', ?, ?)' % Row[1][0], list(zip(Settings, Row[1][1:]))) db.commit() def Output(): c = db.cursor() fieldNames = ['IP'] + Settings with open('/tmp/sc200.csv', 'w', newline='') as outFile: csvWriter = csv.DictWriter(outFile, fieldnames=fieldNames, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) csvWriter.writeheader() c.execute('''SELECT DISTINCT IP FROM SettingsValues ORDER BY IP''') for Device in c: IP = Device print((('''SELECT SettingsID, Value FROM SettingsValues WHERE IP = \'%s\'''' % IP))) row = c.execute('''SELECT SettingsID, Value FROM SettingsValues WHERE IP = \'%s\'''' % IP) print(((row))) outFile.close() #csvWriter.writerow() #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 SettingsValues 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) or Net.broadcast is None): #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)