Compare commits

..

No commits in common. "c5c0081976157651b799efc793c576331e36b497" and "b551a09b7e1b4124084176f896e239ae2f21c11a" have entirely different histories.

5 changed files with 45 additions and 6343 deletions

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
# ignore our binary Excel file
*.xlsx

View file

@ -22,7 +22,7 @@ pd.set_option("display.max_rows", 150)
# point to our various input files - adjust this to your environment
data_dir = '/home/syncthing/ham-radio/ARES-RACES/Nets--PNW_ARES_DMR_Weekly_Net'
data_dir = '/home/ed/syncthing/ham-radio/ARES-RACES/Nets--PNW_ARES_DMR_Weekly_Net'
filename = 'Check_In_Data.xlsx'
data_file = os.path.join(data_dir, filename)
output_file = os.path.join(data_dir, "PNW_Digital_ARES_EMCOMM_Weekly_Net_Check_In_Form.txt")
@ -88,18 +88,18 @@ checkins_df["Date"] = pd.to_datetime(checkins_df["Date"]).dt.strftime('%Y-%m-%d'
callinfo_df = pd.read_excel(xls, "Call_Data", dtype=str)
#print("callinfo_df:")
#print(callinfo_df)
hoip_dir_df = pd.read_excel(xls, "hoip_subscribers", dtype=str)
#print("hoip_dir_df:")
#print(hoip_dir_df)
hh_dir_df = pd.read_excel(xls, "Hamshack_Hotline", dtype=str)
#print("hh_dir_df:")
#print(hh_dir_df)
# build dictionary of HH phone numbers
hoip_phone_dict = {"Callsign" : "HH Number"}
for i,row in hoip_dir_df.iterrows():
hh_phone_dict = {"Callsign" : "HH Number"}
for i,row in hh_dir_df.iterrows():
callsign = row.iloc[1]
hoip_num = row.iloc[0]
# we only add the hoip number first seen for a unique callsign
if callsign not in hoip_phone_dict.keys():
hoip_phone_dict.update({callsign : hoip_num})
hh_num = row.iloc[7]
# we only add the hh number first seen for a unique callsign
if callsign not in hh_phone_dict.keys():
hh_phone_dict.update({callsign : hh_num})
# fill in any missing data (NAN's) with default text
callinfo_df.fillna({'Name' : ''}, inplace=True)
@ -127,27 +127,27 @@ for i,row in checkins_df.iterrows():
# build dictionary of call info indexed by callsign
call_data_dict = {}
for i,row in callinfo_df.iterrows():
# row of data is call, name, state, district, county, affiliation, hoip_num
# dictionary becomes: { call: [name[0], state[1], district[2], county[3], affiliation[4]], hoip_num[5]}
# row of data is call, name, state, district, county, affiliation, hh_num
# dictionary becomes: { call: [name[0], state[1], district[2], county[3], affiliation[4]], hh_num[5]}
callsign = row.iloc[0]
if callsign in hoip_phone_dict.keys():
hoip_num = hoip_phone_dict[callsign]
if callsign in hh_phone_dict.keys():
hh_num = hh_phone_dict[callsign]
else:
hoip_num = ""
call_data_dict.update({callsign:[row.iloc[1],row.iloc[2],row.iloc[3],row.iloc[4],row.iloc[5],hoip_num]})
hh_num = ""
call_data_dict.update({callsign:[row.iloc[1],row.iloc[2],row.iloc[3],row.iloc[4],row.iloc[5],hh_num]})
# build checkin_form_dict dictionary
checkin_form_dict = blank_checkin_form_dict
for call in call_data_dict.keys():
#print("Looking at:", call)
#if call in hoip_phone_dict.keys():
#print("Call "+call+" has HOIP #"+hoip_phone_dict[call])
#if call in hh_phone_dict.keys():
#print("Call "+call+" has HH VOIP #"+hh_phone_dict[call])
call_state = call_data_dict[call][1]
call_dist = call_data_dict[call][2]
call_county = call_data_dict[call][3]
call_affil = call_data_dict[call][4]
call_hoip_num = call_data_dict[call][5]
#print("State, Dist, Cnty, Affil, HH Num: ", call_state, call_dist, call_county, call_affil, call_hoip_num)
call_hh_num = call_data_dict[call][5]
#print("State, Dist, Cnty, Affil, HH Num: ", call_state, call_dist, call_county, call_affil, call_hh_num)
# sanity check the data - error if not found in dictionary keys...
# print("Verifying at: ", call, call_state, call_dist, call_county)
@ -218,8 +218,8 @@ with open(output_file,"w") as outfile:
checkin_str = ""
if checkin_count > 0:
outfile.write(" "+call+", "+call_name+checkin_str)
if call in hoip_phone_dict.keys():
outfile.write(", HOIP #"+hoip_phone_dict[call])
if call in hh_phone_dict.keys():
outfile.write(", HH VOIP #"+hh_phone_dict[call])
if call_affil != "":
outfile.write(", "+call_affil+"\n")
else:
@ -237,8 +237,8 @@ with open(output_file,"w") as outfile:
checkin_str = ""
if checkin_count > 0:
outfile.write(" "+call+", "+call_data_dict[call][0]+checkin_str)
if call in hoip_phone_dict.keys():
outfile.write(", HOIP #"+hoip_phone_dict[call])
if call in hh_phone_dict.keys():
outfile.write(", HH VOIP #"+hh_phone_dict[call])
affil = call_data_dict[call][4]
if affil != '':
outfile.write(", "+affil+"\n")
@ -263,8 +263,8 @@ with open(output_file,"w") as outfile:
checkin_count = 0
checkin_str = ""
outfile.write(" "+call+", "+call_data_dict[call][0]+checkin_str)
if call in hoip_phone_dict.keys():
outfile.write(", HOIP #"+hoip_phone_dict[call])
if call in hh_phone_dict.keys():
outfile.write(", HH VOIP #"+hh_phone_dict[call])
affil = call_data_dict[call][4]
if affil != '':
outfile.write(", "+affil+"\n")
@ -337,21 +337,14 @@ for net_day in net_day_list:
with open(output_file,"w") as outfile:
# Opening text
headertext = '\n'.join([
'PNW Digital ARES & EmComm Check-In Net - '+str(num_checkins)+
' check-ins on '+net_day+'\n',
'There were '+str(num_checkins)+' check-ins on '+net_day+' to the Pacific',
'Northwest (PNW) Digital ARES & EmComm Check-In Net.',
' ',
'The following is the detailed check-in list grouped',
'by our region\'s ARRL ARES districts. If any of the',
'info (i.e. name or agency affiliation) below is',
'incomplete or incorrect, please IM me on Jabber/',
'XMPP at n7ekb@n7ekb.net, e-mail me at ed@n7ekb.net, or',
'call me on HOIP extension 103675 with your updates.',
'\n\n'
])
outfile.write(headertext)
outfile.write("\n ")
outfile.write("PNW Digital ARES & EMCOMM Check-In Net - "+str(num_checkins)+" check-ins on "+net_day+"\n")
outfile.write("\n")
outfile.write("We had a total of "+str(num_checkins)+" check-ins on "+net_day+" to the Pacific Northwest (PNW)\n")
outfile.write("Digital ARES & EMCOMM Check-In Net. Below is the detailed check-in list grouped\n")
outfile.write("by ARRL ARES districts. If any of the info (i.e. name or agency affiliation) below is\n")
outfile.write("incomplete or incorrect, please IM me on Jabber/XMPP (ed@n7ekb.net), or\n")
outfile.write("e-mail \"ed@n7ekb.net\" with the correction(s).\n\n\n")
# Check-in details
for state in sorted(report_dict):
@ -367,10 +360,8 @@ for net_day in net_day_list:
cur_call_list.sort()
for call in cur_call_list:
affil = call_data_dict[call][4]
hoip_num = call_data_dict[call][5]
hh_num = call_data_dict[call][5]
outfile.write(" "+call+", "+call_data_dict[call][0])
if hoip_num != '':
outfile.write(", HOIP #"+hoip_num)
if affil != '':
outfile.write(", "+affil+"\n")
else:
@ -382,10 +373,8 @@ for net_day in net_day_list:
cur_call_list.sort()
for call in cur_call_list:
affil = call_data_dict[call][4]
hoip_num = call_data_dict[call][5]
hh_num = call_data_dict[call][5]
outfile.write(" "+call+", "+call_data_dict[call][0])
if hoip_num != '':
outfile.write(", HOIP #"+hoip_num)
if affil != '':
outfile.write(", "+affil+"\n")
else:
@ -401,10 +390,8 @@ for net_day in net_day_list:
cur_call_list.sort()
for call in cur_call_list:
affil = call_data_dict[call][4]
hoip_num = call_data_dict[call][5]
hh_num = call_data_dict[call][5]
outfile.write(" "+call+", "+call_data_dict[call][0])
if hoip_num != '':
outfile.write(", HOIP #"+hoip_num)
if affil != '':
outfile.write(", "+affil+"\n")
else:
@ -413,24 +400,14 @@ for net_day in net_day_list:
outfile.write("\n")
# output the footer text...
footer = '\n'.join([
'About the net:\n',
'The PNW Digital ARES & EMCOMM Check-In Net is held',
'every Sunday evening at 7:30 PM local time on PNW',
'Regional, DMR talkgroup 31771. DMR Talk Group 31771 is',
'available on both the PNW Digital and the Brandmeister',
'DMR networks. Anyone interested in Amateur Radio and',
'Emergency Communications is welcome to check-in. The',
'net is an opportunity for DMR-capable ARES and EmComm',
'hams to exercise their DMR equipment in a regional,',
'directed net. The net demonstrates the wide coverage',
'area and capability of DMR repeaters and hot spots in',
'our Pacific Northwest region. It also highlights the',
'wide range of EmComm-related organizations who have',
'members with DMR capability.\n\n',
'#net-reports #hamradio #EmComm #ARES #DMR #HOIP #PNWDigital\n'
])
outfile.write(footer)
outfile.write("\nAbout the net:\n\n")
outfile.write("The PNW Digital ARES & EMCOMM Check-In Net is held every Sunday evening at 7:30 PM local\n")
outfile.write("time on PNW Regional, DMR talk group 31771 (available on both the PNW Digital http://pnwdigital.net\n")
outfile.write("and Brandmeister DMR networks). Anyone interested in Amateur Radio Emergency Communications is\n")
outfile.write("welcome to check-in. The net is an opportunity for DMR-capable ARES and EMCOMM hams to exercise\n")
outfile.write("their DMR equipment in a regional directed net. The net demonstrates the wide coverage area and\n")
outfile.write("capability of DMR repeaters and hot spots in our Pacific Northwest region. It also highlights the\n")
outfile.write("wide range of EMCOMM-related organizations who have members with DMR capability.\n\n")
# close this week's report file
outfile.close()

File diff suppressed because it is too large Load diff

View file

@ -1,56 +0,0 @@
from ldap3 import Server, Connection, ALL, SUBTREE
import pandas as pd
# LDAP connection details from the wiki
server_url = 'ldap://207.246.98.219:389' # Server and port (no TLS, as per "TLS Mode: LDAP or No" use 'ldaps://' if TLS needed)
search_base = 'ou=people,dc=hamsoverip,dc=com'
search_filter = '(telephoneNumber=*)' # Fetch all entries with an extension; adjust if needed, e.g., '(objectClass=person)'
attributes = ['cn', 'sn', 'telephoneNumber'] # Key attributes; add more if you discover others like 'callsign'
# Connect anonymously (no auth)
server = Server(server_url, get_info=ALL)
conn = Connection(server, auto_bind=True) # No user/password
# Perform the search
conn.search(
search_base=search_base,
search_filter=search_filter,
search_scope=SUBTREE,
attributes=attributes
)
# Extract data
data = []
for entry in conn.entries:
extension = entry.telephoneNumber.value if 'telephoneNumber' in entry else ''
cn_value = entry.cn.value if 'cn' in entry else ''
sn_value = entry.sn.value if 'sn' in entry else ''
# clean up data
hoipnumber = extension.partition(' ')[0]
callsign = cn_value.partition(' ')[0]
hamname = sn_value.partition(' ')[0]
if hoipnumber: # Only include entries with extensions
data.append({
'HOIP Extension': hoipnumber,
'Call': callsign,
'Name': hamname # Include raw for reference
})
# Save to CSV
if data:
df = pd.DataFrame(data)
# CSV output for debugging...
df.to_csv('hoip_subscribers.csv', index=False)
print(f'Saved {len(data)} entries to hoip_subscribers.csv')
# Excel output for production...
df.to_excel('hoip_subscribers.xlsx', index=False)
print(f'Saved {len(data)} entries to hoip_subscribers.xlsx')
else:
print('No entries found check filter or connection.')
# Unbind
conn.unbind()

View file

@ -1,14 +0,0 @@
# shell.nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
buildInputs = [
(pkgs.python3.withPackages (ps: with ps; [
numpy
openpyxl
pandas
python-dateutil
]))
];
}