o
    Dj¹  ã                   @   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mZm	Z	m
Z
mZmZmZmZmZ e  e¡Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Z d d!„ Z!d"d#„ Z"d$d%„ Z#dS )&é    N)Údatetime)	ÚALERT_TO_NUMBERÚBATTERY_LOW_PERCENTÚMOISTURE_DRY_THRESHOLDÚPUSHOVER_APP_TOKENÚPUSHOVER_USER_KEYÚSMS_PROVIDERÚTWILIO_ACCOUNT_SIDÚTWILIO_AUTH_TOKENÚTWILIO_FROM_NUMBERc                 C   s8   |   ¡ �}| d¡ W d   ƒ d S 1 sw   Y  d S )Na'  
            CREATE TABLE IF NOT EXISTS alert_state (
                source_type VARCHAR(24) NOT NULL,
                source_id VARCHAR(32) NOT NULL,
                metric VARCHAR(24) NOT NULL,
                last_state VARCHAR(16) NOT NULL,
                last_notified_at TIMESTAMP NULL DEFAULT NULL,
                updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                PRIMARY KEY (source_type, source_id, metric)
            )
            )ÚcursorÚexecute)ÚconnÚcur© r   ú)/var/www/html/Server/blueprints/alerts.pyÚensure_alert_state_table   s
   
ÿ"ÿr   c                   C   s0   t tpd ¡ tp	d ¡ tpd ¡ tpd ¡ gƒS ©NÚ )Úallr	   Ústripr
   r   r   r   r   r   r   Ú_is_twilio_configured'   s   



üÿr   c              
   C   sš   t ƒ sd}t d|¡ d|fS zddlm} |ttƒ}|jj| t	p"d 
¡ tp'd 
¡ d� W dS  tyL } zt d	|¡ dt|ƒfW  Y d }~S d }~ww )
Nz*Twilio config missing (SID/token/from/to).zSMS alert skipped: %sFr   )ÚClientr   )ÚbodyÚfrom_Úto©TNz#Failed to send Twilio SMS alert: %s)r   ÚloggerÚwarningÚtwilio.restr   r	   r
   ÚmessagesÚcreater   r   r   Ú	ExceptionÚ	exceptionÚstr)ÚmessageÚmsgr   ÚclientÚexcr   r   r   Ú_send_via_twilio2   s$   


ý€þr)   c                 C   s   t  d| ¡ dS )NzSMS provider=log message=%sr   )r   r   )r%   r   r   r   Ú_send_via_logF   ó   r*   c                 C   s   dS )Nr   r   )Ú_messager   r   r   Ú_send_via_noopK   s   r-   c              
   C   s–   zdd l }W n
 ty   Y dS w tpd ¡ sdS z| d¡}|jtp$d ¡ | d� W dS  tyJ } zt d|¡ d	t|ƒfW  Y d }~S d }~ww )
Nr   )Fz,boto3 is not installed for aws_sns provider.r   )FzALERT_TO_NUMBER missing.Úsns)ÚPhoneNumberÚMessager   z$Failed to send aws_sns SMS alert: %sF)	Úboto3r"   r   r   r'   Úpublishr   r#   r$   )r%   r1   r'   r(   r   r   r   Ú_send_via_aws_snsO   s    ÿ
€þr3   c                   C   s   t tpd ¡ tp	d ¡ gƒS r   )r   r   r   r   r   r   r   r   Ú_is_pushover_configured_   s   r4   c                 C   sž  t ƒ sdS tj tpd ¡ tpd ¡ | ddœ¡ d¡}tjj	d|ddid	d
�}zCtjj
|dd��0}| ¡ jddd�}|jdk sD|jdkrWdd|j› d|› �fW  d   ƒ W S W d   ƒ W dS 1 scw   Y  W dS  tjjy± } z9z| ¡ jddd�}W n tyŠ   d}Y nw d|j› �}|rš|d|› �7 }t d|¡ dd|› �fW  Y d }~S d }~w tyÎ } zt d|¡ dt|ƒfW  Y d }~S d }~ww )N)Fz?Pushover config missing (PUSHOVER_APP_TOKEN/PUSHOVER_USER_KEY).r   zSolarMon Alert)ÚtokenÚuserr%   Útitlezutf-8z(https://api.pushover.net/1/messages.jsonzContent-Typez!application/x-www-form-urlencodedÚPOST)ÚdataÚheadersÚmethodé
   )ÚtimeoutÚreplace)ÚerrorséÈ   i,  FzPushover HTTP z: r   zHTTP z!Failed to send pushover alert: %sz	Pushover )r4   ÚurllibÚparseÚ	urlencoder   r   r   ÚencodeÚrequestÚRequestÚurlopenÚreadÚdecodeÚstatusÚerrorÚ	HTTPErrorr"   Úcoder   r#   r$   )r%   ÚpayloadÚreqÚrespr   r(   Úerr_bodyÚdetailr   r   r   Ú_send_via_pushoverc   sZ   

üÿùüý
þüÿ€€þrS   c                   C   s   t pd ¡  ¡ S )NÚpushover)r   r   Úlowerr   r   r   r   Ú_provider_name‰   ó   rV   c                 C   s   t | ƒ\}}|S )N)Úsend_sms_alert_detailed)r%   ÚokÚ_errr   r   r   Úsend_sms_alert�   r+   r[   c                 C   sf   t ƒ }|dkrt| ƒS |dkrt| ƒS |dkrt| ƒS |dkr#t| ƒS |dkr+t| ƒS dd|› d�fS )	NÚtwiliorT   Úaws_snsÚlogÚnoopFzUnsupported SMS_PROVIDER 'z'.)rV   r)   rS   r3   r*   r-   )r%   Úproviderr   r   r   rX   ’   s   rX   c                 C   s„   | d u rd S t | ttfƒrt| ƒ}n$t | tƒr4|  ¡  dd¡}|s#d S zt|ƒ}W n ty3   Y d S w d S |dk s>|dkr@d S |S )Nú%r   r   éd   )Ú
isinstanceÚintÚfloatr$   r   r>   Ú
ValueError)ÚvalueÚpctÚsr   r   r   Úparse_percent¡   s"   

ÿrj   c              	   C   s6   zt | ƒ}W n ttfy   Y d S w |tkrdS dS ©NÚlowÚnormal)rd   Ú	TypeErrorrf   r   )Úmoisture_valueÚmoisture_intr   r   r   Úmoisture_stateµ   s   ÿrq   c                 C   s$   t | ƒ}|d u r
d S |tkrdS dS rk   )rj   r   )Úpercent_valuerh   r   r   r   Úbattery_state½   s   rs   c                 C   s   t | ƒrdS dS rk   ©Úbool)Úis_lowr   r   r   Únutrient_stateÄ   rW   rw   c                 C   s   t | ƒs
t |ƒr
dS dS )zKAlert when pump is off but low-pressure error is active (unexpected fault).rl   rm   rt   )Úpump_onÚerror_pressure_lowr   r   r   Úpump_off_pressure_fault_stateÈ   s   rz   c              
   C   s´   |sddd dœS |   ¡ �D}| d|||f¡ | ¡ }|r |d nd }||k}	d}
|	r2|dkr2t|ƒ}
| d|||||
r?t ¡ nd f¡ |
|	|dœW  d   ƒ S 1 sSw   Y  d S )NF)ÚnotifiedÚstate_changedÚ
last_statez\SELECT last_state FROM alert_state WHERE source_type = %s AND source_id = %s AND metric = %sr}   rl   a)  
            INSERT INTO alert_state (source_type, source_id, metric, last_state, last_notified_at)
            VALUES (%s, %s, %s, %s, %s)
            ON DUPLICATE KEY UPDATE
                last_state = VALUES(last_state),
                last_notified_at = VALUES(last_notified_at)
            )r   r   Úfetchoner[   r   Úutcnow)r   Úsource_typeÚ	source_idÚmetricÚcurrent_stateÚalert_messager   ÚrowÚprevious_stater|   r{   r   r   r   Úevaluate_and_notifyÏ   s0   
þûø
$ãr‡   )$ÚloggingÚurllib.errorrA   Úurllib.parseÚurllib.requestr   Úconfigr   r   r   r   r   r   r	   r
   r   Ú	getLoggerÚ__name__r   r   r   r)   r*   r-   r3   r4   rS   rV   r[   rX   rj   rq   rs   rw   rz   r‡   r   r   r   r   Ú<module>   s0    ,
&