
    $j                     (	   S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
r
S SKrS SKrS SKrS SKJr  S SKJrJrJr  S SKJr  S SKJrJr  \" \R2                  R5                  SS5      5      r\" \R2                  R5                  S\" \S	-  5      5      5      r\" \R2                  R5                  S
\" \S-  5      5      5      r\" \R2                  R5                  S\" \S-  5      5      5      r\" \R2                  R5                  S\" \S-  5      5      5      r \" \R2                  R5                  S\" \S-  5      5      5      r!\" \R2                  R5                  S\" \S-  5      5      5      r"\" \R2                  R5                  S\" \S-  5      5      5      r#\" \R2                  R5                  SS5      5      r$\%" \R2                  R5                  SS5      5      r&\'" \R2                  R5                  SS5      5      r(\%" \R2                  R5                  SS5      5      r)\%" \R2                  R5                  S\" S5      5      5      r*\%" \R2                  R5                  S S!5      5      r+\%" \R2                  R5                  S"S#5      5      r,S$\S%\4S& jr-S%\4S' jr.S(\S%\4S) jr/SyS* jr0SyS+ jr1S,\4S- jr2S%\4S. jr3S%\4S/ jr4S%\4S0 jr5S%\4S1 jr6S%\4S2 jr7S%\4S3 jr8S4\4S5 jr9S4\4S6 jr:S7\S%S4S8 jr;S,\S%S4S9 jr<S:\S%S4S; jr=S%\4S< jr>S%\4S= jr?S>\S%\4S? jr@S@\S%\4SA jrAS>\S%\4SB jrBSC\S%S4SD jrCS@\SE\S%S4SF jrDS>\S%\\   4SG jrESC\4SH jrFSI\S%\4SJ jrGSzSC\SK\%SL\'S%\H4SM jjrIS{SC\SK\%SN\H4SO jjrJSP\S%\H4SQ jrKS%\4SR jrLSS\ST\SU\S%\4SV jrMSW\\   SX\ST\SU\S%\4
SY jrNSZ\SI\SX\S%\4S[ jrOS\\\   SP\S%\\   4S] jrPS^\S_\%S`\Sa\Sb\\\'4   S%\\   4Sc jrQS|S\\\   SP\Sd\Se\%Sf\%Sg\%S%\4Sh jjrRS\\\   SP\Sd\S%\4Si jrSS%\\   4Sj jrTSk\\   4Sl jrU\)4Sm\%S%\\   4Sn jjrVSo\SX\4Sp jrWSq\\   SX\So\S%\4Sr jrXSW\\   S7\So\S>\ST\S@\Ss\SX\St\Su\S%\4Sv jrYS%\%4Sw jrZ\[Sx:X  a  \R                  " \Z" 5       5        gg)}    N)defaultdict)datetime	timedeltatimezone)Path)DictListWIFI_PRESENCE_LOG_DIRz,/home/sebas/runtime/agent-logs/wifi-presenceWIFI_PRESENCE_STATEz
state.jsonWIFI_PRESENCE_LOGzactivity.jsonlWIFI_PRESENCE_ALIASESzaliases.jsonWIFI_PRESENCE_FINGERPRINTSzfingerprints.jsonWIFI_PRESENCE_ALERT_PREFSzalert-prefs.jsonWIFI_PRESENCE_INVENTORYzinventory.jsonWIFI_PRESENCE_DAILY_SUMMARYzdaily-summary.jsonWIFI_PRESENCE_SUMMARYz"/var/www/wifi-tracker/summary.jsonWIFI_PRESENCE_PING_WORKERS32WIFI_PRESENCE_HOSTNAME_TIMEOUTz0.35 WIFI_PRESENCE_SUMMARY_TAIL_LINES20000WIFI_PRESENCE_ROTATE_MAX_BYTESi  @ WIFI_PRESENCE_ROTATE_KEEP0!WIFI_PRESENCE_OFFLINE_GAP_MINUTES5cmdreturnc                 h    [         R                  " U SS[         R                  S9R                  5       $ )NT)shelltextstderr)
subprocesscheck_outputDEVNULLstrip)r   s    +/home/sebas/pi-config/bin/wifi-presence-logshr(   $   s(    ""3djFXFXY__aa    c                  V    [         R                  " S[         R                  " 5       5      $ )N%Y-%m-%dT%H:%M:%SZ)timestrftimegmtime r)   r'   nowr0   (   s    ==-t{{}==r)   tsc                 f    [         R                  " U S5      R                  [        R                  S9$ )Nr+   )tzinfo)r   strptimereplacer   utc)r1   s    r'   parse_tsr7   ,   s(    R!56>>hll>SSr)   c                     [         R                  SSS9  [        R                  R                  SSS9  [        R                  5       (       d  [        R                  S5        [        R                  5       (       d  [        R                  S5        [        R                  5       (       d  [        R                  S5        [        R                  5       (       d  [        R                  S5        [        R                  5       (       d  [        R                  S5        [        R                  5       (       d  [        R                  S5        g g )NT)parentsexist_okz{"devices": {}}
z{}
z+{"new_device_alerts": true, "devices": {}}
z${"updated_at": null, "devices": {}}
)LOG_DIRmkdirSUMMARY_PATHparent
STATE_PATHexists
write_textALIASES_PATHFINGERPRINTS_PATHALERT_PREFS_PATHINVENTORY_PATHDAILY_SUMMARY_PATHr/   r)   r'   ensure_pathsrG   0   s    MM$M.dT:12  '##%%$$V,""$$##$RS  ""!!"56$$&&%%&MN 'r)   c                  4   [         R                  5       (       a&  [         R                  5       R                  [        :  a  g [
        R                  " S[
        R                  " 5       5      n [        SU  S3-  n[        SU  S3-  n[         R                  U5        UR                  S5       n[        R                  " USSS9 nUR                  U5        S S S 5        S S S 5        UR                  S	S
9  [        S:  ai  [        [!        [        R#                  S5      5      [!        [        R#                  S5      5      -   5      nUS [        *   H  n UR                  5         M     g g ! , (       d  f       N= f! , (       d  f       N= f! [$         a     MI  f = f)Nz%Y%m%d-%H%M%Sz	activity-z.jsonlz	.jsonl.gzrbwb   )compresslevelT)
missing_okr   activity-*.jsonlactivity-*.jsonl.gz)LOG_PATHr@   statst_sizeROTATE_MAX_BYTESr,   r-   r.   r;   r5   opengzip
writelinesunlinkROTATE_KEEPsortedlistglobFileNotFoundError)r1   rotated
compressedsrcdstoldpaths          r'   rotate_logsrc   A   s1   ?? 7 7:J J		6B)B4v..GYrd)44JW	d	sDIIj$a$PTWs %Q	NNdN#QT',,'9:;d7<<PeCf>ggh+&D '  %Q$P		 % s6   +E8E'E8F	'
E5	1E88
F	
FFrb   c                 p     [         R                  " U R                  5       5      $ ! [         a    Us $ f = fN)jsonloads	read_text	Exception)rb   defaults     r'   	load_jsonrk   T   s1    zz$..*++ s   #& 55c                  &    [        [        S0 05      $ Ndevices)rk   r?   r/   r)   r'   
load_statero   [   s    Z)R11r)   c                      [        [        0 5      n U R                  5        VVs0 s H-  u  p[        U[        5      (       d  M  UR                  5       U_M/     snn$ s  snnf re   )rk   rB   items
isinstancestrlower)datakvs      r'   load_aliasesrx   _   sC    \2&D%)ZZ\H\TQZ35GLAGGIqL\HHHs   AAc                  "    [        [        0 5      $ re   )rk   rC   r/   r)   r'   load_fingerprintsrz   d   s    &++r)   c                  (    [        [        S0 S.5      $ )NT)new_device_alertsrn   )rk   rD   r/   r)   r'   load_alert_prefsr}   h   s    %Tb'QRRr)   c                  &    [        [        S0 05      $ rm   )rk   rE   r/   r)   r'   load_inventoryr   l   s    ^i_55r)   c                  (    [        [        S 0 S.5      $ )N
updated_atrn   )rk   rF   r/   r)   r'   load_daily_summaryr   p   s    ')LMMr)   ru   c                 $    [        [        U 5        g re   )write_json_atomicrE   ru   s    r'   save_inventoryr   t   s    nd+r)   c                 $    [        [        U 5        g re   )r   rF   r   s    r'   save_daily_summaryr   x   s    ($/r)   statec                     [         R                  S5      nUR                  [        R                  " U SSS9S-   5        UR                  [         5        g Nz.tmp   T)indent	sort_keys
)r?   with_suffixrA   rf   dumpsr5   )r   tmps     r'   
save_stater   |   s<    

 
 
(CNN4::eA>EFKK
r)   c                     U R                  S5      nUR                  [        R                  " USSS9S-   5        UR	                  U 5        g r   )r   rA   rf   r   r5   )rb   ru   r   s      r'   r   r      s<    


6
"CNN4::d1=DEKKr)   eventc                     [        5         U R                  S[        5       5        [        R	                  S5       nUR                  [        R                  " U SS9S-   5        S S S 5        g ! , (       d  f       g = f)Nr1   aT)r   r   )rc   
setdefaultr0   rP   rT   writerf   r   )r   fs     r'   	log_eventr      sO    M	T35!	s	q	

5D1D89 
		s   (A++
A9c                      [        S5      $ )Nz+ip route | awk '/default/ {print $3; exit}'r(   r/   r)   r'   default_gatewayr          ;<<r)   c                      [        S5      $ )Nz+ip route | awk '/default/ {print $5; exit}'r   r/   r)   r'   default_ifacer      r   r)   ifacec                      [        SU  S35      $ )Nzip -o -f inet addr show dev z | awk '{print $4; exit}'r   )r   s    r'   
iface_cidrr      s    ,UG3NOPPr)   cidrc                 T    [        [        R                  " U 5      R                  5      $ re   )rs   	ipaddressip_interfacenetwork)r   s    r'   network_cidrr      s    y%%d+3344r)   c                 h    [        SU  35      nUR                  5       S   R                  S5      S   $ )Nzip -o -4 addr show dev    /r   )r(   split)r   outs     r'   local_ipr      s4    
&ug.
/C99;q>$Q''r)   ipc                 t    [         R                  " SSSSSU /[         R                  [         R                  S9  g )Npingz-c1z-W)stdoutr"   )r#   runr%   )r   s    r'   	ping_hostr      s,    NNFD#tS"5j>P>PYcYkYklr)   self_ipc                 N   [         R                  " U SS9nUR                  5        Vs/ s H  n[        U5      U:w  d  M  [        U5      PM!     nn[        R
                  " [        S9 n[        UR                  [        U5      5        S S S 5        g s  snf ! , (       d  f       g = f)NF)strict)max_workers)
r   
ip_networkhostsrs   cfThreadPoolExecutorPING_WORKERSrZ   mapr   )r   r   nethr   exs         r'   sweep_networkr      sw    


tE
2C(+		I1s1v7HAEI			<	8BRVVIu%& 
9	8 J	8	8s   BB( B
B$c                 V   [        SU  S35      n/ nUR                  5        H  nUR                  5       n[        U5      S:  a  M$  US   S US   U S.nSU;   a;  UR	                  S5      nUS-   [        U5      :  a  XFS-      R                  5       US	'   UR                  U5        M     U$ )
Nzip neigh show dev z || true   r   )r   macr   r   lladdr   r   )r(   
splitlinesr   lenindexrt   append)r   r   rowslinepartsrowis          r'   arp_entriesr      s    
!%1
2CD 

u:>1XdU2YOuH%A1us5z!"q5\//1E
C ! Kr)   c                      [         R                  " [        5        [         R                  " U 5      u  n  nU$ ! [         a     g f = fre   )socketsetdefaulttimeoutHOSTNAME_TIMEOUTgethostbyaddrri   )r   name_s      r'   reverse_namer      sC      !12))"-
a s   58 
AAgatewayc                    SU 0n [         R                  R                  SU  S3SS9 nUR                  S5      R	                  SS5      nS S S 5        S	W;   a  S	US
'   [
        R                  " SU5      nU(       a$  UR                  S5      R                  SS5      US'   U$ ! , (       d  f       N]= f! [         a  n[        U5      US'    S nAU$ S nAff = f)Nr   zhttp://r   r   )timeouti   utf-8ignoreHuaweivendorzProductName\s*=\s*'([^']+)'r   z\x2d-modelprobe_error)urllibrequesturlopenreaddecoderesearchgroupr5   ri   rs   )r   r   rhtmlmes         r'   probe_routerr      s    g
C	$^^##ggYa$8!#D66%='':D Et$CMII4d;771:--gs;CL J ED  $ VMJ$s/   "B2 "B!
AB2 !
B/+B2 2
C<CCportr   c                    [         R                   " 5       nUR                  U5         UR                  X45         UR                  5         g! [         a     UR                  5         gf = f! UR                  5         f = f)NTF)r   
settimeoutconnectcloseri   )r   r   r   ss       r'   tcp_openr      sc    ALL			2* 	
	  		 	
	s#   A 
A)A, (A))A, ,A>httpsc                 @    U(       a  [         R                  " 5       OS n[        R                  R	                  U(       a  SOSSU  SU S3-   SUS9 nUR                  S5      R                  S	S
5      nUsS S S 5        $ ! , (       d  f       g = f! [         a     g f = f)Nr   httpz://:r   g      ?)r   contexti   r   r   )ssl_create_unverified_contextr   r   r   r   r   ri   )r   r   r   ctxr   ru   s         r'   
http_sniffr     s    27c,,.T^^##W6s2$aPTvUVEW$Wadnq#rvw66$<&&w9D srr  s0   AB #A?5	B ?
B	B B 
BBr   c                 x     [        [        U R                  S5      S   S5      S-  5      $ ! [         a     gf = f)Nr   r      r   F)boolintr   ri   )r   s    r'   private_macr
     s=    C		#q)2.566 s   ), 
99c            	          [        S5      n [        [        5      nU R	                  5        H  nUR                  S5      (       d  M  UR                  S5      n[        U5      S:  a  M=  US   R                  SS5      nUS   nUS	   nUS
   nUS   nUSS  n	[        R                  " SU5      (       d  M  X   R                  UUUUU	S.5        M     [        U5      $ ! [         a    0 s $ f = f)Nz1timeout 8s avahi-browse -arpk 2>/dev/null || true=;	   r   z\032 r   rK         z\d+\.\d+\.\d+\.\d+)service_nameservice_typehostr   txt)r(   ri   r   rZ   r   
startswithr   r   r5   r   	fullmatchr   dict)
r   by_ipr   r   r  r  r  addrr   r  s
             r'   discover_mdnsr     s    DE E s##

3u:>Qx''5QxQxQxQxABi<<-t44K , ,   !( ;/  	s   C C,+C,devgwdiscoveriesc                 
   U R                  S5      nU R                  S5      =(       d    SR                  5       nU R                  S5      =(       d    SnUUU[        U5      / / SS SUR                  U/ 5      0S.	nX1:X  a  S US'   U$ / S	QnU H)  n[        X85      (       d  M  US
   R	                  U5        M+     UR                  U/ 5      n	U	 V
s/ s H  oR                  S5      PM     nn
U	 V
s/ s H  oR                  S5      PM     nn
[        S U 5       5      (       a8  US:X  a2  US   R	                  S5        XS   S'   SUS'   [        US   S5      US'   [        S U 5       5      (       ax  US   R	                  S5        XS   S'   [        S U 5       5      (       a  SUS'   [        US   S5      US'   O.[        S U 5       5      (       a  SUS'   [        US   S5      US'   [        S U 5       5      (       a+  US   R	                  S 5        S!US'   [        US   S5      US'   [        S" U 5       5      (       aB  US   R	                  S#5        [        S$ U 5       5      (       a  S%US'   [        US   S&5      US'   US:X  ao  US   R	                  S'5        [        US   S(5      US'   S)US'   S*US   S+'   S,US
   ;   a3  US   R	                  S-5        S,US   S.'   S/US'   [        US   S5      US'   S0US
   ;   aI  US   R	                  S15        US2:X  a  S3US'   [        US   S45      US'   OS5US'   [        US   S65      US'   S7US
   ;   a  S8US
   ;   a  [        US75      =(       d    SnUS   R	                  S95        US S: US   S;'   S<U;   d  S=U;   a  S>US'   [        US   S5      US'   O)S?U;   d  S@U;   d  SAU;   a  SBUS'   [        US   SC5      US'   USD:X  a4  SEUS
   ;   a+  US   R	                  SF5        SGUS'   [        US   S5      US'   SHUS
   ;   aV  SIUS
   ;   aM  US   R	                  SJ5        USK   (       a  SLUS'   [        US   SC5      US'   OSMUS'   [        US   SN5      US'   SOUS
   ;   a5  US   (       d+  US   R	                  SP5        SQUS'   [        US   SR5      US'   SSUS
   ;   aE  US   (       d;  [        USS5      =(       d    SnU(       a  US   R	                  ST5        US S: US   SU'   US   (       d5  USK   (       a+  US   R	                  SV5        SWUS'   [        US   SX5      US'   U$ s  sn
f s  sn
f )YNr   r    
oui_prefix        mdns)	r   r   r!  r
  
ports_opensources
confidenceguess_aliasevidencer'  )
P          ~    X  H  I  i   r$  r  r  c              3   *   #    U  H	  oS :H  v   M     g7f)z_matterc._udpNr/   .0ts     r'   	<genexpr>%fingerprint_device.<locals>.<genexpr>*  s     
4A   zCC:40:85r%  zmdns-matterr(  
mdns_typesz2WiZ / Matter smart light con mDNS Matter [from AI]r&  g\(\?c              3   *   #    U  H	  oS :H  v   M     g7f)z_googlecast._tcpNr/   r3  s     r'   r6  r7  /  s     
7Jq""Jr8  zmdns-googlecast
mdns_namesc              3   ,   #    U  H
  nS U;   v   M     g7f)Google Home MiniNr/   r4  ns     r'   r6  r7  2  s     ;
1!Q&
s   z1Google Home Mini / Google Cast con mDNS [from AI]gGz?c              3   D   #    U  H  nS U;   =(       d    SU;   v   M     g7f)zonn.TVNr/   r>  s     r'   r6  r7  5  s      >:a1)	):    z+Android TV / Google Cast con mDNS [from AI]g
ףp=
?c              3   *   #    U  H	  oS :H  v   M     g7f)z_androidtvremote2._tcpNr/   r3  s     r'   r6  r7  8  s     
=*Q((*r8  zmdns-androidtvz$Android TV con mDNS remote [from AI]c              3   *   #    U  H	  oS ;   v   M     g7f))z	_ssh._tcpz_sftp-ssh._tcpz_companion-link._tcpNr/   r3  s     r'   r6  r7  <  s     
Zz!EEzr8  zmdns-apple-macc              3   D   #    U  H  nS U;   =(       d    SU;   v   M     g7f)MacBookMacNr/   r>  s     r'   r6  r7  >  s      @ZyA~+!+ZrB  z0Apple MacBook con SSH / companion-link [from AI]gQ?zoui-wizgq=
ףp?z1WiZ / Matter smart light con vendor WiZ [from AI]WiZr   r,  mattermatter_portz:WiZ / Matter smart light con vendor WiZ y Matter [from AI]r.  z	tuya-6668zC4:82:E1z@Tuya smart controller / smart infrared con puerto 6668 [from AI]g(\?z+Tuya smart device con puerto 6668 [from AI]g)\(?r0  r1  zgoogle-cast   	http_8008r=  zGoogle-Home-Miniz8Google Home Mini / Google Cast con eureka_info [from AI]build_versioncast_build_revisionr   z2Android TV / Google Cast con eureka_info [from AI]gffffff?z74:E6:B8r*  zlg-tvz1LG Smart TV con puertos webOS / AirPlay [from AI]r-  r+  zapple-lockdowndr
  z:Apple iPhone con MAC privada y puertos lockdownd [from AI]z2Apple iPhone / iOS con puertos lockdownd [from AI]g?r/  airplayz0Apple / AirPlay device con puerto 7000 [from AI]g      ?r)  z
http-titlehttp_80zprivate-mac-onlyu7   Dispositivo con MAC privada / probable móvil [from AI]g?)getrt   r
  r   r   anymaxr  )r  r  r  r   r   prefixevports_to_prober   r#  xr9  r;  ru   s                 r'   fingerprint_devicerX    s   	B775>R
&
&
(CWW\"(bF"3'[__R45

B 
x =	QNB|##D)  ??2r"D156A%%'J6156A%%'J6

4
444:9M
9]+'1:|$P=r,/6<

7J
777
9./'1:|$;
;;; SB}"2l#3T:B|>:>>> MB}"2l#3T:B|

=*
===
9-.B=r,/6<

Zz
ZZZ
9-.@Z@@@ RB}"2l#3T:B|
9Y'r,/6<O=#(:x 2l##yM  *,0BzN=) \B}"2l#3T:B|r,
9[)Z bB}"2l#3T:B| MB}"2l#3T:B|r,DB|,<$<"d#)r
9]+&*4Cj:{#%);t)C ZB}"2l#3T:B|$(=(ESW TB}"2l#3T:B|<(8 8
9W%O=r,/6<<  Ub.>%>
9./m \B}"2l#3T:B| TB}"2l#3S9B|r,=(9
9Y'N=r,/6<	Rb&7"b!'RyM  .(,Tc
BzN9%mM!2
9/0U=r,/6<I] 76s   U0U
rn   aliasesc                    Sn[        5       nU  GH  nUR                  S5      =(       d    SR                  5       nU(       d  M5  [        XbU5      nUR                  U5      n	U	(       a  SU	;  a  SOSn
[	        5       UR                  S5      UR                  S5      UR                  S	5      UR                  S
5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      U
S.
XW'   Xq;   a  M  UR                  S5      nU(       d  GM  XU'   SnGM     [        [        U5        U(       a  [        [        U5        U$ )NFr   r   z	[from AI]manualair'  r&  r%  r(  r$  r   r!  r
  )
last_probe_tsr'  r&  r%  r(  r$  r   r!  r
  alias_sourceT)rz   rQ  rt   rX  r0   r   rC   rB   )rn   rY  r  r  changedfingerprintsr  r   fpexisting_aliassourceguesseds               r'   maybe_autonamere  y  s   G$&Lwwu~#**,5 S)+>0QW[ U66-0&&.vvi(z*&&.''$-'',/66-0"
 >&&'7"CLG1 2 '6,0Nr)   r   c                 f   U S   nU R                  S5      n[        U5      nX1:X  a  S/O/ nU R                  S5      nUS;   nUS:X  a  SnUUUR                  U5      UR                  U5      =(       d    U=(       d    UUU R                  S5      UUU(       a  UR                  5       S	S
 US.
$ S US.
$ )Nr   r   r   r   >   DELAYPROBESTALE	PERMANENT	REACHABLEFAILEDFr   r   r  )
r   r   aliasdisplay_namehostnamer   neighbor_state	reachabler!  roles)rQ  r   upper)	r   r   rY  r   r   ro  rr  r   rq  s	            r'   normalize_devicert    s    	TB
''%.CBH=YKbEGGGENNI	S!C(;H;!*-ciik!A&  48 r)   eventsc                 :   UR                  5       n/ nU  H  nUR                  S5      S:w  a  M  UR                  S5      =(       d    0 nUR                  S5      =(       d    SR                  5       U:w  a  Mb  UR                  S5      nU(       d  M|  UR                  [        U5      5        M     UR	                  5         U(       d  / $ / nUS   =px[        [        S9n	US	S   H"  n
X-
  U	:  a  UR                  XxS
.5        U
nU
nM$     UR                  XxS
.5        U$ )Nr   device_snapshotdevicer   r   r1   r   minutesr   startend)rt   rQ  r   r7   sortr   OFFLINE_GAP_MINUTES)ru  r   	snapshotsrU  r  r1   sessionsr|  prevgapdts              r'   build_sessionsr    s    
))+CI66'?//ffX$"GGEN b'')S0VVD\2Xb\*  NN	HQ<E
/
0Cm9s?OOe9:E	 
 OOe12Or)   r|  countstepkey_fmtvaluesc           
          / n[        U5       HI  nXU-  -   nUR                  U5      nUR                  U[        UR	                  US5      S5      S.5        MK     U$ )Nr   r   )bucketr  )ranger-   r   roundrQ  )	r|  r  r  r  r  r   r   r  keys	            r'   fill_bucket_seriesr    sY    
C5\AXkk'"

cE&**S!2Da,HIJ  Jr)   now_dthoursstep_minutesoffline_missesc                 H   U[        US9-
  R                  SSS9n/ n[        5       nU  H  n	U	R                  S5      S:w  a  M  U	R                  S5      =(       d    0 n
U
R                  S5      =(       d    SR	                  5       UR	                  5       :w  a  Mp  U	R                  S	5      nU(       d  M  [        U5      nX:  d  X[        US
9-   :  a  M  UR                  U-  U-  nUR                  USSS9nUR                  U5        M     UR                  UR                  U-  U-  SSS9nSnUnX::  a[  X;   nU(       a  SnSnOU(       a  US-  nUU:  a  SnUR                  UR                  S5      UUS.5        U[        US
9-  nX::  a  M[  / nS nU H?  nUS   (       a  Uc  US	   nUS   (       a  M!  Uc  M&  UR                  UUS	   S.5        S nMA     Ub!  U(       a  UR                  UUS   S	   S.5        UR                  S5      UR                  S5      XEUUS.$ )Nr  r   )secondmicrosecondr   rw  rx  r   r   r1   ry  minuter  r  FTr   r+   )r1   observedonliner  r{  r   )r|  r}  r  r  segmentsslots)
r   r5   setrQ  rt   r7   r  addr   r-   )ru  r   r  r  r  r  r|  r  r  rU  r  r1   r  r  r  cursorr   
miss_countseenr  	seg_startslots                         r'   summarize_presence_timeliner    s4   ie,,55QA5NEEuH66'?//ffX$"GGEN b'')SYY[8VVD\b\:y'FFF))|+|;6!CV  ]]5<<<#?<"OXYgh]iFEJ

!EJa
/!EFOO,@At_def)L11 
 HI>i/T
IH~~)"7OOiT
CDI  )E"IdODE^^$89&//RfBg  zF  v~  IN  O  Or)   c           
      T   [        [        5      n[        [        5      n[        [        5      nU[        SS9-
  R                  SSSS9nU[        SS9-
  R                  SSSSS9nU[        UR	                  5       S9-
  R                  SSSSS9nU[        SS	9-
  n	[        X5      n
U
 GH  nUS
   nUS   [        SS9-   n[        X5      nX:  ax  [        UR                  SSSS9[        SS9-   U5      nUR                  SSSS9R                  S5      nUU==   [        X-
  R                  5       S-  S5      -  ss'   UnX:  a  Mx  [        X5      nX:  aj  [        UR                  SSSSS9[        SS9-   U5      nUR                  S5      nUU==   [        X-
  R                  5       S-  S5      -  ss'   UnX:  a  Mj  [        X5      nX:  d  GM-  U[        UR	                  5       S9-
  R                  SSSSS9n[        U[        SS	9-   U5      nUR                  S5      nUU==   [        X-
  R                  5       S-  S5      -  ss'   UnX:  a  M  GM     [        US[        SS9SU5      [        US[        SS9SU5      [        U	S[        SS	9SU5      [        U
5      S.$ )N   r  r   r     dayshourr  r  r     )weeksr|  r}  r   ry  r   z%Y-%m-%dT%H:00Z  %Y-%m-%d         )r  dayweekr  )r   floatr   r5   weekdayr  rS  minr-   total_secondsr  r   )ru  r   r  hour_values
day_valuesweek_values
hour_start	day_startweek_anchor
week_startr  sessionr|  r}  r  nxtr  wks                     r'   summarize_activityr    s   e$KU#Je$K92..77qXY7ZJ),,551Qq^_5`II6>>+;<<EE1UV_`noEpKyr22Jf*H eny33U'lv~~Qqa~H9[\K]]`cdC..!.CLLM^_CS\$@$@$BT$I1 MMF	 l
 U&lv~~1Qqa~PS\bcSddgjkC//*-CsOsCL#?#?#AD#H!LLOF	 l
 U'l9&..*:;;DD!TU^_mnDoBb91--s3C++j)CS\$@$@$BT$I1 MMF ll! 0 #:r913EGXZef!)R1BJPZ[":r913EzS^_M	 r)   c                      [        [        [        R                  S5      5      [        [        R                  S5      5      -   [        R                  5       (       a  [        /-   5      $ / -   5      $ )NrO   rN   )rY   rZ   r;   r[   rP   r@   r/   r)   r'   event_filesr  .  sz    $w||$9:;d7<<PbCc>ddv~  wF  wF  wH  wHiqhr  Q  R  R  NP  Q  R  Rr)   pathsc              #   <  #    U  H^  nUR                   S:X  a  [        R                  O[        n U" US5       nU H  n [        R                  " U5      v   M     S S S 5        M`     g ! [
         a     M:  f = f! , (       d  f       M  = f! [         a     M  f = f7f)Nz.gzrt)suffixrU   rT   rf   rg   ri   r\   )r  rb   openerfhr   s        r'   iter_eventsr  2  s     "kkU2	d#rD!"jj..  $#  % ! !	 $# ! 		sn   ,B	BA9A(A9B#B(
A6	2A95A6	6A99
B	BBB
BBBBlimitc                 2   [         R                  5       (       d  / $  [         R                  5       R                  5       U * S  n/ nU H)  n UR                  [        R                  " U5      5        M+     U$ ! [         a    / s $ f = f! [         a     MN  f = fre   )rP   r@   rh   r   ri   r   rf   rg   )r  linesru  r   s       r'   read_recent_eventsr  @  s    ??	""$//15&': F	MM$**T*+ 
 M  	  		s#   &A6 %B6BB
BB	inventoryc           	         U R                  S0 5      n[        5        GH  nUR                  S5      =(       d    0 nUR                  S5      =(       d    SR                  5       nU(       d  MO  UR                  U0 5      n[	        U5      nUR                  UR                  5        VV	s0 s H  u  pU	c  M
  X_M     sn	n5        UR                  XWR                  S5      5      US'   UR                  S5      =(       dA    UR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      US'   UR                  S	5      =(       d)    UR                  S
5      =(       d    UR                  S	5      US	'   UR                  S
5      =(       d)    UR                  S5      =(       d    UR                  S5      US'   XrU'   GM     U $ s  sn	nf )Nrn   rx  r   r   rm  ro  r   rn  first_seen_tsr1   last_seen_ts)r   r  rQ  rt   r  updaterq   )
r  rY  inv_devicesrU  r  r   prev_invmergedrv   rw   s
             r'   hydrate_inventory_from_eventsr  P  sn   &&y"5K "ffX$"wwu~#**,??3+h		EqtqtEF!++c::g+>?w!'G!4!w

:8N!wRXR\R\]bRc!wgmgqgqrvgw~"*,,"?"k266$<"kSVSZSZ[jSk!#!h1H!hHLLYgLh~!C #  Fs   '	G4G
all_eventsc                    [        5       0 S.n[        [        5      nU  H  nUR                  S5      S:w  a  M  UR                  S5      =(       d    0 nUR                  S5      =(       d    SR	                  5       nUR                  S5      nU(       a  U(       d  M}  XG   R                  [        U5      5        M     UR                  S5      =(       d    0 n	UR                  5        GHq  u  pzU
R                  5         UR                  U5      =(       db    U	R                  U5      =(       d    0 R                  S	5      =(       d2    U	R                  U5      =(       d    0 R                  S
5      =(       d    Un[        U
 Vs/ s H  nSSU0UR                  S5      S.PM     snU5      n[        S 5      nU GH*  nUS   nUS   [        SS9-   nUR                  S5      nUU   S==   S-  ss'   UnUU:  d  MC  UR                  SSSSS9n[        U[        SS9-   U5      nUR                  S5      nUU   nUS==   [        UU-
  R                  5       S-  S5      -  ss'   UR                  S5      nUR                  S5      nUS   (       a  [        [!        S US   U/5      5      OUUS'   US   (       a  [        [!        S US   U/5      5      OUUS'   UnUU:  a  M  GM-     UU
S   R                  S5      U
S   R                  S5      [#        UR                  5       5       VVs0 s H  u  nnU0 UES[%        US   S5      0E_M     snnS.US   U'   GMt     ['        U5        U$ s  snf s  snnf )Nr   r   rw  rx  r   r   r1   rn   rm  rn  r+   )r   rx  r1   c                      SSS S S.$ )Nr"  r   )r  r  r  r  r/   r/   r)   r'   <lambda>&update_daily_summary.<locals>.<lambda>s  s    sTXjn%or)   r|  r}  r   ry  r  r  r   r   r  r  r  r  r  r  r   )rm  r  r  r  )r0   r   rZ   rQ  rt   r   r7   rq   r~  r  r-   r   r5   r  rS  r  filterrY   r  r   )r  rY  r  r   groupedrU  r  r   r1   r  timesrm  r5  r  by_dayr  r|  r}  	first_dayr  r  r  r  r   ts_startts_endr  valss                               r'   update_daily_summaryr  b  so   2
.C$G66'?//ffX$"wwu~#**,VVD\"HRL)  --	*0bKmmo


C   I[__S%9%?R$D$DW$M  IR]RaRabeRfRljlQqQq  sA  RB  I  FI!  JO  #P  JO  EF->5RU,^_^h^hi}^~#  JO  #P  RU  VopGG$E%.9Q#77Cz2I9j)Q.)F3,"NN!ASTNU	)iQ&77=((4SkGS6\$@$@$BT$I1 MM!??+?@&:;^abq^rs6$_9Mx8X+Y'Z  yAO$Z]^lZmc&N8KV7T*U&VsyN# 3,,  $ "1X../CD!"I../CDV\]c]i]i]kVlmVldSDTD7E$w-,CDDVlm	
Is- &8 sJ5 #P. ns   ?!M)
(#M.routeralert_prefsdaily_summaryc
                    [        5       n
[        U
5      n[        U  Vs/ s H  oR                  S5      (       d  M  UPM     sn5      n[	        S U  5       5      n[        S U  5       S 5      n0 n/ n/ n[        5       nU GH9  nUR                  S5      nUR                  S5      nUR                  S5      =(       d    0 nUR                  S5      =(       d    SR                  5       =(       d    S nUS	;   d  My  U(       d  M  UR                  S
5      =(       d    0 R                  U=(       d    S0 5      nUUUR                  S5      =(       d    UR                  S5      UU(       a  UR                  U5      OUR                  S5      U(       a  UR                  U5      OS S.nUS   =(       db    UR                  S5      =(       dJ    UR                  S5      =(       d2    UR                  S5      =(       d    U=(       d    UR                  S5      US'   UR                  U5        U(       a2  UR                  S
0 5      R                  U0 5      R                  SS5      OSnUS:X  a.  UR                  SS5      (       a  UR                  U5        GM  GM  US;   d  GM  U(       d  GM(  UR                  U5        GM<     U  H[  nUR                  S5      =(       d    SnUR                  US5      S-   UU'   [        UUS   U5      US'   [        UUS   U5      US'   M]     U R                  S S9  U
UUUUUU[        UR                  S
5      =(       d    0 5      [        UR                  5        VVs/ s H  u  nnU(       d  M  UPM     snn5      S.UU [        UR                  5       S S9 VVs/ s H  u  nnUUS.PM     snnUS S  US S  U	[        [        S!S".S#U0S$.n[!        ["        U5        U$ s  snf s  snnf s  snnf )%Nr  c              3   T   #    U  H  oR                  S 5      (       d  M  Sv   M      g7f)ro  r   NrQ  r4  ds     r'   r6   build_summary.<locals>.<genexpr>  s     87aeeJ&77s   (	(c              3   t   #    U  H.  nS UR                  S/ 5      ;   d  M  UR                  S5      v   M0     g7f)r   rr  r   Nr  r  s     r'   r6  r    s/     YgaeeGUWFX9Xegs   88r   r1   rx  r   r   >   device_onlinedevice_offlinenew_device_detectedrn   r   rm  )r1   r   r   r   rm  rn  rn  ro  alerts_enabledTr  r|   >   r  r  r!  unknownr   r   activitypresence_timelinec                     U R                  SS5      (       + SU R                  SS5      ;   a2  [        S U R                  SS5      R                  S5       5       5      4$ S4$ )	Nr  F.r   r   c              3   8   #    U  H  n[        U5      v   M     g 7fre   r	  r4  rW  s     r'   r6  2build_summary.<locals>.<lambda>.<locals>.<genexpr>  s     A|R{Q#a&&R{   255.255.255.255   r  r  r  rQ  tupler   r  s    r'   r  build_summary.<locals>.<lambda>  s    AEE(E$: :  AD  HI  HM  HM  NR  TV  HW  AWEA|RSRWRWX\^oRpRvRvwzR{A|<|   o  ]n   or)   r  )devices_nownamed_devicesknown_devicesaliased_devicesc                     U S   * U S   4$ )Nr   r   r/   )rW  s    r'   r  r    s    `abc`d_dfghifj^kr)   )r   r  irU   )rotate_max_bytesrotate_keeprotated_compressiongateway_mac)r   r   r   r   r  totalsrY  rn   vendorsrecent_eventsrecent_alertsr  	retention
highlights)r0   r7   r   rQ  sumnextr  rt   r   r  r  r~  rq   rY   rS   rX   r   r=   ) rn   r   r  r   r  r   r  rY  r  r  now_tsr  r  active_totalnamedr  r  timelinealert_eventsru  rU  etr1   r  r   invr   enabledrT  rv   rw   summarys                                    r'   build_summaryr#    s   UFfF7>7aeeHo7>?L8788EYgY[_`KGHL!FVVG_VVD\ffX$"wwu~#**,4KKPRPR==+1r66syb"ECggdm4swwt}-0S)cggg6F47C 0TC #&g,  #T#''.2I  #TSWWUcMd  #Thkhohopzh{  #T  @C  #T  GJ  GN  GN  OS  GTCOOC adkooi488bAEEFVX\]jnG**??#6== '', >::ww##C(- . |$1	!++fa014*61U8VD*!<VQuXv!V
	 
 LL  oL  p'" )--	":"@bB"'--/#G/$!QQA/#GH	
 8>w}}Tk8lm8l1Q+8lm!$%%de,& 0&#)

 %k2/G2 lG,N} ?\ $H ns   O2O20O7O7/O=c                     [        5         [        R                  " 5       n [        5       n[        5       n[	        U5      n[        U5      n[        U5      n[        5       n[        SXXCU[        S.5        [        U5      n[        5       n[        5       n	[        SUS.5        [        XE5        [        U5      n
U
 Vs/ s H>  oR                  S5      (       d  M  SUR                  SS5      ;   d  M2  [!        XU5      PM@     nn[#        XX)5      nU
 Vs/ s H>  oR                  S5      (       d  M  SUR                  SS5      ;   d  M2  [!        XU5      PM@     nnUR%                  S	 S
9  ['        5       n[)        [+        5       U5      nUR                  S0 5      n0 nU H  nUS   nUUU'   UR                  U0 5      nXUS.n[        SS0UE5        UU;  a&  UR                  SS5      (       a  [        SS0UE5        UR                  S5      (       a  Mw  UR                  S0 5      R                  U0 5      R                  SS5      (       d  M  [        SS0UE5        M     UR-                  5        Hn  u  nnUU;  d  M  UR                  S5      (       d  M&  UR                  S0 5      R                  U0 5      R                  SS5      (       d  M_  [        SXUS.5        Mp     S0 0n[/        5       n/ nUR-                  5        HV  u  nnSUS'   UUS'   UR                  U0 5      R                  S5      =(       d    UUS'   UUS   U'   UR1                  U5        MX     UR-                  5        H  u  nnUU;   a  M  [3        U5      nSUS'   UR                  UUR                  S5      5      US'   US   =(       d)    UR                  S5      =(       d    UR                  S5      US'   UUS   U'   UR1                  U5        M     UR5                  S0 5      nU GHb  nUR                  S5      nU(       d  M  UR                  U0 5      n[3        U5      nUR7                  UR-                  5        VVs0 s H  u  nnUc  M  UU_M     snn5        UR                  UUR                  S5      5      US'   UR                  S5      =(       dA    UR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      US'   UR                  S5      =(       d"    UR                  S5      =(       d
    [/        5       US'   UR                  S5      (       a  UR                  S5      US'   UUU'   GMe     [9        U5        [;        U5        [=        [?        [A        5       5      5      n [C        U Xo5      n![=        URE                  5       5      n"U"R%                  S S
9  [G        U"UXX$XvUU!5
        [        SX[I        U5      [K        [        R                  " 5       U -
  S5      S .5        g!s  snf s  snf s  snnf )"Ncycle_start)r   r   r   r   
iface_addrr   ping_workersrouter_probe)r   r  r   r  r   r   c                 J    [        S U S   R                  S5       5       5      $ )Nc              3   8   #    U  H  n[        U5      v   M     g 7fre   r  r  s     r'   r6  )main.<locals>.<lambda>.<locals>.<genexpr>  s     $H5GSVV5Gr   r   r  )r  r   r  s    r'   r  main.<locals>.<lambda>  s    u$HQtW]]35G$HHr)   r  rn   )r   r   rx  r   rw  r|   Tr  r  r  r  r  )r   r   r   rx  r  r  Frm  ro  rn  c                     U R                  SS5      (       + SU R                  SS5      ;   a2  [        S U R                  SS5      R                  S5       5       5      4$ S4$ )	Nr  Fr  r   r   c              3   8   #    U  H  n[        U5      v   M     g 7fre   r  r  s     r'   r6  r+  $  s&       LG  ]FWXCPQFF  ]Fr   r  r  r  r  s    r'   r  r,  $  s    aeeHe.D*D  KN  RS  RW  RW  X\  ^`  Ra  Kae  LG\]\a\abfhy\z  ]A  ]A  BE  ]F  LG  GG  *y  gx  *yr)   	cycle_endr   )r   r   r   seen_devicesduration_secr   )&rG   r,   r   r   r   r   r   rx   r   r   r   r}   r  r   r   rQ  rt  re  r~  ro   r  r   rq   r0   r   r  r   r  r   r   rZ   r  r  r  r  r#  r   r  )#startedr   r  r&  r   r   rY  r  r  r  r   r   raw_devicesrn   r   r  r  currentr  r   	dev_state
event_basera   	new_stateseen_tsall_devicesoffliner  r  r  rv   rw   r  r  inventory_devicess#                                      r'   mainr<    s   NiikGOE		BE"J
#DuoGnGd  zA  S_  `  a"F"$K/K&9:$ uD=AmTUU5\3VY]^]b]bcgik]lVl3#A73TKm[2CG9=iAu/RUYZY^Y^_cegYhRh/w/GiLLHLILE-n.>HI99Y#DG%jHHS"%	$sC
7-<<=d?{/BDIIw 5DDE}}X&&;??9b+I+M+McSU+V+Z+Z[kmq+r+rw>:>?  JJLSg#''("3"3y"-11#r:>>?OQUVV$4u_bcd !
 BIeGKMMOSH%N#xxR044_EPO$'	)S!3 $ JJLS'>s)!";;sGKK,@A")'"2"cgkk*6M"cQXQ\Q\]bQc$+	)S!7# ! &&y"5Kggen??3+h		E1qtq!tEF!++c6::g+>?w!'G!4!w

:8N!wRXR\R\]bRc!wgmgqgqrvgw~"*,,"?"d377?C["d_b_d77>""%(WW^%<F>"!C  y9k+-01J(WHM[//12   y  z#Y	"F]hjwxeTWX_T`rwx|  yB  yB  yD  GN  yN  PQ  sR  S  TG nib Fs0   ;X0X00X0X5/X5X50
X:>X:__main__)r   N)g      ?)r)  F)r  r   r   )]concurrent.futuresfuturesr   rU   r   rf   osr   r   r  r#   sysr,   urllib.requestr   collectionsr   r   r   r   pathlibr   typingr   r	   environrQ  r;   rs   r?   rP   rB   rC   rD   rE   rF   r=   r	  r   r  r   SUMMARY_TAIL_LINESrS   rX   r  r(   r0   r7   rG   rc   rk   ro   rx   rz   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  r
  r  rX  re  rt  r  r  r  r  r  r  r  r  r  r#  r<  __name__exitr/   r)   r'   <module>rJ     s       	 	  
  
   # 2 2  
rzz~~57ef
g"**..!6Gl<R8STU


2CBR8R4STUBJJNN#:C.@X<YZ[(Dc'TgJgFhij 

'BCRdHdDefg bjjnn%>GN^D^@_`a"**..)FGVjLjHklm BJJNN#:<`ab2::>>">EF(H&QR (JGTU rzz~~&FOH\]^ "**..!<cBC"**..)LcRS bC bC b>S >T T TO"&D 2D 2Id I
,4 ,S$ S6 6ND N, ,0T 0d t D 4 :T :d := ==s =Qc Qc Q5s 5s 5(C (C (
m# m$ m' 'c 'd 's tDz  S # $ 	 	C 	% 	$ 	3 c t S T t :eD ec e e ePDJ  3 T VZ D$  t  .4: C DJ 6h s ) c [_`cej`j[k ptuypz ,OT
 ,O ,Oh ,OWZ ,Oor ,O  IL ,O  UY ,O^&tDz & &X &$ &RRT$Z RtDz  %7 c 4:  T D $*T$Z *$ *4 *TX *ZA4: Ad At AC AUX A`c Amq A  }A A  PT A  ei A  nr AHUc Up zHHTV r)   