DX Cluster client in Python
Condivido il codice sorgente in Python 3 per la realizzazione di un DX cluster client, con annessa serie di video in cui spiego il l’implementazione. Lo stesso programma che ho chiamato DX Fighter cluster, è stato da me scritto anche in Java.
Main Class
import socket, _thread
from termcolor import colored
from time import sleep
from Spot import Spot
from Entities import Entities, LOTW
MYCALL = 'IZ0KBA'
#host, port = 'clx.noantri.org', 23
host, port = 'dxfun.com', 8000
server = (host, port)
clxsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
entities = Entities()
lotw = LOTW()
def sendCmd(txt):
''' Send a string to server. Carry self included'''
txt = txt + '\n'
clxsock.send(txt.encode())
def connection():
''' Make connetion to server'''
global clxsock
connected = False
while not connected:
print(colored(f'Connection to: {host} {port}', 'blue'))
try:
clxsock.connect( server )
except:
print('Impossibile to connect')
sleep(5)
else:
print('Connected!!!')
connected = True
def run():
connection()
while True:
try:
clxmsg = clxsock.recv(2048).decode('latin-1')
for line in clxmsg.splitlines():
if line.upper().startswith('DX DE '):
#SPOT
spot = Spot(line)
print(spot.toString())
else:
print(colored(line, 'yellow'))
if 'login' in line.lower() or 'enter your call' in line.lower():
sendCmd(MYCALL)
except KeyboardInterrupt:
print('Disconnected')
if __name__ == '__main__':
_thread.start_new_thread(run, ())
while True:
comando = input('>')
sendCmd(comando)
Class Spot
import __main__
class Spot():
lunghezzaMaxSpot = 0
@staticmethod
def getBand(frequency):
'''Accept frequency as string, return Band and Mode'''
banda, modo = None, None
frequency = float(frequency)
if frequency < 2000:
if frequency <= 1838:
modo = 'CW'
elif frequency <= 1843:
modo = 'DATA'
else:
modo = 'PHONE'
banda = '160M'
elif frequency < 4000:
if frequency <= 3580:
modo ='CW'
elif frequency <= 3600:
modo ='DATA'
else:
modo ='PHONE'
banda = '80M'
elif frequency < 6000:
if frequency <= 5354:
modo ='CW'
else:
modo ='PHONE'
banda = '60M'
elif frequency < 7500:
if frequency <= 7040:
modo = 'CW'
elif frequency <= 7050:
modo = 'DATA'
else:
modo = 'PHONE'
banda = '40M'
elif frequency < 10200:
if frequency <= 10130:
modo = 'CW'
else:
modo = 'DATA'
banda = '30M'
elif frequency < 14500:
if frequency <= 14070:
modo = 'CW'
elif frequency <= 14100:
modo = 'DATA'
else:
modo = 'PHONE'
banda = '20M'
elif frequency < 18300:
if frequency < 18095:
modo = 'CW'
elif frequency < 18109:
modo = 'DATA'
else:
modo = 'PHONE'
banda = '17M'
elif frequency < 21500:
if frequency <= 21070:
modo = 'CW'
elif frequency <= 21110:
modo ='DATA'
else:
modo ='PHONE'
banda = '15M'
elif frequency < 25000:
if frequency < 24915:
modo ='CW'
elif frequency <= 24929:
modo ='DATA'
else:
modo ='PHONE'
banda = '12M'
elif frequency < 30000:
if frequency < 28070:
modo ='CW'
elif frequency <= 28190:
modo ='DATA'
else:
modo ='PHONE'
banda = '10M'
elif frequency < 55000:
if frequency < 50100:
modo = 'CW'
elif frequency < 50300:
modo = 'PHONE'
else:
modo = 'DATA'
banda = '6M'
elif frequency < 71000:
banda = '4M'
elif frequency < 150000:
banda = '2M'
else:
banda = 'UHF'
return (banda, modo)
def __init__(self, line):
self.txt = line
duepunti, punto = line.find(":"), line.find(".")
self.spotter = line[6 : duepunti]
self.qrg = line[duepunti + 1 : punto + 2].strip()
self.callsign = line[punto + 3 : 39].strip()
bm = self.getBand(self.qrg)
self.band = bm[0]
self.mode = bm[1]
info = __main__.entities.getEntities(self.callsign)
self.entities = info.name
self.lotw = __main__.lotw.getLotw(self.callsign)
if Spot.lunghezzaMaxSpot < len(line):
Spot.lunghezzaMaxSpot = len(line)
def toString(self):
return f'{self.txt.ljust(Spot.lunghezzaMaxSpot)} {self.lotw[0]} {self.entities} {self.lotw[1]}'
Class Entities
import os
from datetime import datetime
class Entita():
def __init__(self, line):
self.name = line[0]
self.continet = line[1]
self.dxccn = line[4]
class Entities():
def __init__(self, file = 'entities.ini'):
self.entities = {}
if os.path.exists(file):
with open(file, 'r') as inifile:
for line in inifile.read().splitlines():
if '=' in line:
k, v = line.split('=')
self.entities[k] = v
def getEntities(self, callsign):
"""Metodo ricorsivo - Recursive method"""
if callsign:
if callsign in self.entities:
return Entita(self.entities[callsign].split(';'))
return self.getEntita(callsign[:-1])
return Entita(['Sconosciuto'.ljust(35),'','0','0','-1'])
class LOTW():
def __init__(self, file = 'lotw-user-activity.csv'):
self.users = {}
with open(file, 'r') as f:
for line in f.read().splitlines():
callsign, data = line.split(',')[:-1]
self.users[callsign] = data
def getLotw(self, callsign):
if callsign in self.users:
data = self.users[callsign]
diff = (datetime.now() - datetime.strptime(data, '%Y-%m-%d')).days
data = ('{0} {1}'.format(data, diff)) if diff <= 365 else ('{0} {1}y'.format(data, diff//365))
return '< LOTW <', data
else:
return '< <',''
if __name__ == '__main__':
e = Entities()
2 commenti
kevin
What is lotw-user-activity.csv or where does it come from.
Kevin
IZ0KBA
Official LOTW user list from ARRL: https://lotw.arrl.org/lotw-user-activity.csv