33import re
44import requests
55import json
6- from datetime import datetime
6+ import os
7+ import sys
78from watchdog .observers import Observer
89from watchdog .events import FileSystemEventHandler
9- import os
1010import threading
1111import traceback
1212
13+ PROJECT_ROOT = os .path .dirname (os .path .dirname (os .path .abspath (__file__ )))
14+ sys .path .insert (0 , PROJECT_ROOT )
15+
16+ from xlxd_common import get_flag , normalize_xlxd_xml , parse_xlxd_datetime , read_xlxd_xml
17+
1318ref_name = ""
14- with open ("./ config_tg.json" , "r" , encoding = "utf-8" ) as f :
19+ with open (os . path . join ( PROJECT_ROOT , " config_tg.json") , "r" , encoding = "utf-8" ) as f :
1520 config = json .load (f )
1621
1722modules = config ["service" ]["modules" ]
2530TG_URL = f"https://api.telegram.org/bot{ config ['service' ]['token' ]} /sendMessage"
2631
2732dt_format = "%A %a %b %d %H:%M:%S %Y"
28- call_country = "./xlxd_dash/callprefix.json"
29- with open (call_country , "r" , encoding = "utf-8" ) as f :
30- callprefix = json .load (f )
3133
3234nodes_old = {}
3335nodes_off = {}
4042
4143def send_message (msg , dest ):
4244 for CHAT_ID in dest :
43- data = {"chat_id" : CHAT_ID , "text" : msg }
44- res = requests .post (TG_URL , data = data )
45- # print(res.text)
46-
47- def call_flag (country ):
48- return '' .join (chr (0x1F1E6 + ord (letra ) - ord ('A' )) for letra in country .upper ())
49-
50- def get_flag (callsign ):
51- while callsign :
52- if callsign in callprefix :
53- return call_flag (callprefix [callsign ][0 ])
54- callsign = callsign [:- 1 ]
55- return ""
56-
57- def load_xml ():
58- with open (xml_file , "r" , encoding = "utf-8" ) as f :
59- XML = f .read ()
45+ while True :
46+ data = {"chat_id" : CHAT_ID , "text" : msg }
47+ try :
48+ res = requests .post (TG_URL , data = data , timeout = 10 )
49+ except Exception as e :
50+ print (f"Error: { e } " )
51+ time .sleep (5 )
52+ continue
6053
61- match = re . match ( r'(<\?xml.*?\?>)' , XML )
62- header = match . group ( 1 ) if match else ""
54+ if res . status_code == 200 :
55+ break
6356
64- ref_match = re .search (r"<(XLX\d+) " , XML )
65- if ref_match :
66- ref_name = ref_match .group (1 )
57+ print (f"Error HTTP { res .status_code } . Reintentando…" )
58+ time .sleep (5 )
6759
68- XML = XML [len (header ):].strip ()
60+ def split_node_callsign (callsign ):
61+ parts = callsign .split (maxsplit = 1 )
62+ if len (parts ) == 2 :
63+ return parts [0 ], parts [1 ]
64+ return callsign , ""
6965
70- XML = re . sub ( r"<([\w]+)\s+([\w\s]+)>" , lambda m : f"< { m . group ( 1 ) } _ { m . group ( 2 ). replace ( ' ' , '_' ) } >" , XML )
71- XML = re . sub ( r"</([\w]+)\s+([\w\s]+)>" , lambda m : f"</ { m . group ( 1 ) } _ { m . group ( 2 ). replace ( ' ' , '_' ) } >" , XML )
66+ def format_node_call ( call , initial ):
67+ return f" { call } - { initial } " if initial else call
7268
73- XML = f"<ROOT>\n { XML } \n </ROOT>"
69+ def load_xml ():
70+ xml = read_xlxd_xml (xml_file )
71+ if not xml ["available" ]:
72+ return xml
7473
75- return ref_name , XML
74+ data = normalize_xlxd_xml (xml ["xml" ], root_name = "ROOT" )
75+ data ["available" ] = True
76+ return data
7677
7778def analizar_xml ():
7879 global nodes_old , stations_old , notif , process , nodes_off , ref_name
7980 now = time .strftime ("%Y%m%d_%H%M%S" , time .localtime ())
8081 now_epoch = int (time .time ())
8182 try :
82- ref_name , XML = load_xml ()
83+ xml = load_xml ()
84+ if not xml ["available" ]:
85+ send_message (xml ["message" ], logger )
86+ return False
87+
88+ ref_name = xml ["name" ]
89+ XML = xml ["data" ]
8390
8491 if not process :
8592 send_message (f"REF: { ref_name } " , logger )
@@ -90,15 +97,15 @@ def analizar_xml():
9097 nodes_now = {}
9198 for node in root .findall (".//NODE" ):
9299 callsign = (node .findtext ("Callsign" ) or "" ).strip ()
93- call , initial = callsign . split ( maxsplit = 1 )
100+ call , initial = split_node_callsign ( callsign )
94101 ip = (node .findtext ("IP" ) or "" ).strip ()
95102 linked_module = (node .findtext ("LinkedModule" ) or "" ).strip ()
96103 protocol = (node .findtext ("Protocol" ) or "" ).strip ()
97104 connect_time = (node .findtext ("ConnectTime" ) or "" ).strip ()
98105 last_heard_time = (node .findtext ("LastHeardTime" ) or "" ).strip ()
99106
100- connect_time_epoch = int ( datetime . strptime ( connect_time , dt_format ). timestamp ()) if connect_time else 0
101- last_heard_time_epoch = int ( datetime . strptime ( last_heard_time , dt_format ). timestamp ()) if last_heard_time else 0
107+ connect_time_epoch = parse_xlxd_datetime ( connect_time )
108+ last_heard_time_epoch = parse_xlxd_datetime ( last_heard_time )
102109
103110 index = (callsign + "-" + protocol or "" ).strip ().replace (' ' ,'_' )
104111 if index in nodes_now .keys ():
@@ -137,44 +144,47 @@ def analizar_xml():
137144 for key in nuevos :
138145 Call = nodes_now [key ]["Call" ]
139146 Initial = nodes_now [key ]["Initial" ]
147+ NodeCall = format_node_call (Call , Initial )
140148 LinkedModule = nodes_now [key ]["LinkedModule" ]
141149 Protocol = nodes_now [key ]["Protocol" ]
142150 flag = get_flag (Call )
143151 if key in nodes_off .keys ():
144152 del nodes_off [key ]
145- send_message (f"Online { Call } - { Initial } On { ref_name } { LinkedModule } Protocol { Protocol } " , logger )
153+ send_message (f"Online { NodeCall } On { ref_name } { LinkedModule } Protocol { Protocol } " , logger )
146154 else :
147155 if (LinkedModule in modules ):
148156 notifto = logger + node_offline
149157 else :
150158 notifto = logger
151159
152- send_message (f"✅{ flag } { Call } - { Initial } On { ref_name } { LinkedModule } Protocol { Protocol } " , notifto )
160+ send_message (f"✅{ flag } { NodeCall } On { ref_name } { LinkedModule } Protocol { Protocol } " , notifto )
153161
154162 ### NODES - si faltan nodes que antes estaban (old - now)
155163 eliminados = nodes_old .keys () - nodes_now .keys ()
156164 if eliminados :
157165 for key in eliminados :
158166 Call = nodes_old [key ]["Call" ]
159167 Initial = nodes_old [key ]["Initial" ]
168+ NodeCall = format_node_call (Call , Initial )
160169 LinkedModule = nodes_old [key ]["LinkedModule" ]
161170 Protocol = nodes_old [key ]["Protocol" ]
162- send_message (f"Offline { Call } - { Initial } From { ref_name } { LinkedModule } Protocol { Protocol } " , logger )
171+ send_message (f"Offline { NodeCall } From { ref_name } { LinkedModule } Protocol { Protocol } " , logger )
163172 nodes_off [key ] = nodes_old [key ]
164173 nodes_off [key ]["last_off" ] = now_epoch
165174
166175 for key in list (nodes_off .keys ()):
167176 if nodes_off [key ]["last_off" ] + node_delay < now_epoch :
168177 Call = nodes_off [key ]["Call" ]
169178 Initial = nodes_off [key ]["Initial" ]
179+ NodeCall = format_node_call (Call , Initial )
170180 LinkedModule = nodes_off [key ]["LinkedModule" ]
171181 Protocol = nodes_off [key ]["Protocol" ]
172182 flag = get_flag (Call )
173183 if (LinkedModule in modules ):
174184 notifto = logger + node_offline
175185 else :
176186 notifto = logger
177- send_message (f"❌{ flag } { Call } - { Initial } From { ref_name } { LinkedModule } Protocol { Protocol } " , notifto )
187+ send_message (f"❌{ flag } { NodeCall } From { ref_name } { LinkedModule } Protocol { Protocol } " , notifto )
178188
179189 del nodes_off [key ]
180190
@@ -193,7 +203,7 @@ def analizar_xml():
193203 via_peer = (station .findtext ("Via_peer" ) or "" ).strip ()
194204 last_heard_time = (station .findtext ("LastHeardTime" ) or "" ).strip ()
195205
196- last_heard_time_epoch = int ( datetime . strptime ( last_heard_time , dt_format ). timestamp ()) if last_heard_time else 0
206+ last_heard_time_epoch = parse_xlxd_datetime ( last_heard_time )
197207
198208 index = (callsign or "" ).strip ().replace (' ' , '_' )
199209
@@ -287,4 +297,5 @@ def INITmonitor():
287297 process = analizar_xml ()
288298 if process :
289299 INITmonitor ()
290- time .sleep (1 )
300+ else :
301+ time .sleep (30 )
0 commit comments