U
    01jP1                     @   s   d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm  m	Z e
ddZee
ddZe
dd	Ze
d
dZee
ddZee
ddZee
ddZed Zed Zed Zed Zed Zed Zed Zed Zed ZdZdZdZdZdZ dZ!dZ"eehZ#eee hZ$ddddhZ%d d!hZ&d"Z'i a(da)da*da+d#a,d$d% Z-d&d' Z.ed(d)d*Z/d+d, Z0d-d. Z1d/d0 Z2d1d2 Z3d3d4 Z4d5d6 Z5d7d8 Z6d9d: Z7d;d< Z8d=d> Z9dJd?d@Z:dAdB Z;dCdD Z<dEdF Z=dGdH Z>e?dIkre>  e@ dS )K    N)Path)datetimeZTESVOR_MQTT_HOSTz192.168.88.56ZTESVOR_MQTT_PORTZ1883ZTESVOR_MQTT_USERmqttZTESVOR_MQTT_PASSWORDz5905*1-8ZTESVOR_BASE_DIRz/volume2/docker/tesvor-mapZTESVOR_PUBLIC_DIRz#/volume2/docker/mh-map-gateway/htmlZTESVOR_HA_PUBLIC_DIRz,/volume2/docker/homeassistant/www/tesvor-mapzcurrent.jsonarchivezarchive_index.jsonztesvor/x500/map/pointsztesvor/x500/statez&tesvor/x500/sensor/map_path_json/stateztesvor/x500/sensor/state/statez%tesvor/x500/sensor/vacuum_state/stateztesvor/x500/statusztesvor/x500/map/resetZcleaningZspot_cleaningZedge_cleaningZzmode_cleaningZchargingZdocked   Fc                   C   s   t  jddS )NsecondsZtimespec)r   now	isoformat r   r   //volume2/docker/tesvor-map/tesvor_map_writer.pynow_isoL   s    r   c                   C   sX   t jddd tjddd tjddd tjddd tjddd tjddd d S )NTparentsexist_ok)BASE_DIRmkdirARCHIVE_DIR
PUBLIC_DIRPUBLIC_ARCHIVE_DIRHA_PUBLIC_DIRHA_PUBLIC_ARCHIVE_DIRr   r   r   r   ensure_dirsP   s    r   )pathc                 C   sn   | j jddd | | jd }|jtj|ddddd ||  zt	| d	 W n t
k
rh   Y nX d S )
NTr   z.tmpF),:)Zensure_asciiZ
separatorsutf-8)encoding  )parentr   Z	with_namenameZ
write_textjsondumpsreplaceoschmod	Exception)r   payloadZtmpr   r   r   atomic_write_jsonY   s    
r(   c               
   C   s   zt tD ]z\} }}|D ]2}zt t| | d W q tk
rJ   Y qX q|D ]2}zt t| | d W qR tk
r   Y qRX qRqW n4 tk
r } ztd| dd W 5 d }~X Y nX d S )Ni  r   z![WARN] chmod public tree failed: Tflush)r$   walkr   r%   r   r&   print)rootdirsfilesdfer   r   r   chmod_public_treeg   s    r3   c                  C   s,   dd t t D } dt tt| | dS )Nc                 S   s   g | ]}t | qS r   )points_by_seq).0kr   r   r   
<listcomp>y   s     z)build_current_payload.<locals>.<listcomp>Ztesvor_x500)ZdeviceupdatedZstartedpoint_countZpoints)sortedr4   keysr   session_startedlen)Zorderedr   r   r   build_current_payloadx   s    r>   c                  C   s>   t  } tt|  tt|  tt|  td| d  dd d S )Nz[SAVE] current point_count=r9   Tr)   )r>   r(   CURRENT_FILEPUBLIC_CURRENT_FILEHA_PUBLIC_CURRENT_FILEr,   r'   r   r   r   save_current   s
    


rC   c                  C   s   g } t tdddD ]|}z<| }| |jd|j |jt|j	j
ddd W q tk
r } ztd| d	| dd
 W 5 d }~X Y qX qt | dS )N*.jsonT)reversezarchive/r   r   )r    r   sizeZmodifiedz[WARN] archive index skip : r)   )r8   r/   )r:   r   globstatappendr    st_sizer   Zfromtimestampst_mtimer
   r&   r,   r   )r/   r1   rI   r2   r   r   r   build_archive_index_payload   s    
,rM   c                  C   sJ   t  } tt|  tt|  tt|  t  tdt| d  ddd d S )Nz[INDEX] r/   z archive filesTr)   )rM   r(   ARCHIVE_INDEX_FILEPUBLIC_ARCHIVE_INDEX_FILEHA_PUBLIC_ARCHIVE_INDEX_FILEr3   r,   r=   rB   r   r   r   write_archive_index   s    


rQ   c                  C   sj  d} t dD ]}t|j }t|j }zl| rX| j| jksX| j| jkrt	
|| t|d t	
|| t|d | d7 } W q tk
r } ztd| d| dd W 5 d }~X Y qX qt rFz4t	
tt ttd t	
tt ttd W n6 tk
rD } ztd	| dd W 5 d }~X Y nX | r`td
|  ddd t  d S )Nr   rD   r      z[WARN] sync archive failed rG   Tr)   z[WARN] sync current failed: z[SYNC] copied z archive file(s) to public)r   rH   r   r    r   existsrI   rK   rL   shutilcopy2r$   r%   r&   r,   r?   r@   rA   rQ   )ZcopiedsrcZdstZha_dstr2   r   r   r    sync_existing_archives_to_public   s0    

0,
$rW   c                 C   s  t rd S t s tddd d S tttk rHtdtt ddd d S ddd | D }t	 
d	}td
| d| d }t|j }t|j }tt| t|d tt| t|d tt| t|d da t  td| dd td| dd d S )Nz"[ARCHIVE] skipped: no current.jsonTr)   z[ARCHIVE] skipped: only z	 point(s) c                 s   s&   | ]}|  s|d kr|ndV  qdS ))-_rZ   N)isalnum)r5   cr   r   r   	<genexpr>   s     z"archive_current.<locals>.<genexpr>z%Y-%m-%d_%H-%M-%SZtesvor_map_rZ   z.jsonr   z
[ARCHIVE] z
[PUBLIC]  )archived_this_sessionr?   rS   r,   r=   r4   MIN_ARCHIVE_POINTSjoinr   r	   strftimer   r   r    r   rT   rU   r$   r%   rQ   )reasonZsafe_reasonZtsZarchive_fileZpublic_archive_fileZha_public_archive_filer   r   r   archive_current   s.    

rc   c                   C   s$   i a t adat  tddd d S )NFz[SESSION] resetTr)   )r4   r   r<   r^   rC   r,   r   r   r   r   reset_session   s
    rd   c                 C   s   t |   ddS )N rZ   )strstriplowerr#   )textr   r   r   normalize_state   s    rj   c                 C   sj   t | } | sd S | tkr.td|  dd | a| tkrPtd krPt atddd | tkr`t|  t  d S )Nz[STATE] Tr)   z[SESSION] started)	rj   
last_stater,   CLEANING_STATESr<   r   FINISHED_STATESrc   rC   )stater   r   r   handle_state   s    ro   c              
   C   sP  |rt ddd d S td kr"t  zt| }W nH tk
rx } z*t d| d| d d  dd W Y d S d }~X Y nX |dg }|dd	kr|g krt d
dd t  d S t|tsd S d	}|d}d}|rLt|d	 trLt	|d	 dkrLd}z"t
|}td|t	| d }W n* tk
rJ   tt d	dd }Y nX t|D ]\}	}
t|
tslqTzrt	|
dkr|
\}}}}t
|}n2t	|
dkr|r|
\}}}t
||	 }nW qTt
|}t
|}t
|}W n tk
r   Y qTY nX |tkrT||||dt|< |d7 }qT|rLt d| dt	t dd t  d S )Nz[MAP] retained payload ignoredTr)   z[WARN] invalid map json: rG      pnr   z[RESET] map_path_json n=0 p=[]F   rR   )default   )seqxytypez
[POINTS] +z, total=)r,   r<   rd   r!   loadsr&   get
isinstancelistr=   intmaxr4   r;   	enumeraterC   )ri   retaineddatar2   Zp_listZaddedZtotal_nZuse_synth_seqZ	start_seqidxrq   rv   rw   rx   Zkindr   r   r   handle_map_payload  sj     

(



r   c                 C   sL   t d| dd tttB tthB D ] }| | t d| dd q&d S )Nz[MQTT] connected rc=Tr)   z[MQTT] subscribed )r,   r:   POINT_TOPICSSTATE_TOPICSESPHOME_AVAILABILITY_TOPICRESET_TOPICZ	subscribe)clientuserdataflagsrctopicr   r   r   
on_connectg  s    
r   c                 C   s   t d| dd d S )Nz[MQTT] disconnected rc=Tr)   )r,   )r   r   r   r   r   r   on_disconnecto  s    r   c                 C   s   |j }|jjddd }tt|dd}|tkrHtddd t  d S |t	krzt
|}|tkrvtd	| dd |ad S |tkr|rtd
| dd d S t| d S |tkrt||d d S d S )Nr   r#   )errorsZretainFz[RESET] mqtt reset requestedTr)   z[AVAIL] z[STATE] retained ignored: )r   )r   r'   decoderg   boolgetattrr   r,   rd   r   rj   last_availabilityr   ro   r   r   )r   r   msgr   ri   r   Zavailabilityr   r   r   
on_messages  s,    r   c               
   C   sP  t   t  tddd tdt dt dd tdt dd tdt dd tdt dd td	d
t	t
 dd tdd
t	t dd t } tr| tt t| _t| _t| _z| ttd |   W q tk
r
   tddd Y qLY q tk
rH } z td| dd td W 5 d }~X Y qX qd S )Nz[CONFIG]Tr)   z  MQTT:        r   z  BASE_DIR:    z  PUBLIC_DIR:  z  HA_PUBLIC_DIR: z  POINT_TOPICS: z, z  STATE_TOPICS: <   z[EXIT] interruptedz[ERROR] mqtt loop failed: 
   )r   rW   r,   	MQTT_HOST	MQTT_PORTr   r   r   r`   r:   r   r   r   ZClient	MQTT_USERZusername_pw_setMQTT_PASSWORDr   r   r   ZconnectZloop_foreverKeyboardInterruptr&   timesleep)r   r2   r   r   r   main  s0    
r   __main__)F)Ar!   r$   rT   r   pathlibr   r   Zpaho.mqtt.clientr   r   getenvr   r~   r   r   r   r   r   r   r?   r   rN   r@   r   rO   rA   r   rP   ZCUSTOM_POINT_TOPICZCUSTOM_STATE_TOPICZESPHOME_MAP_TOPICZESPHOME_STATE_TOPICZESPHOME_VACUUM_STATE_TOPICr   r   r   r   rl   rm   r_   r4   r<   rk   r   r^   r   r   r(   r3   r>   rC   rM   rQ   rW   rc   rd   rj   ro   r   r   r   r   r   __name__ZEOFr   r   r   r   <module>   s   		%
R!
