o
    L½iY.  ã                   @   s  d Z ddlZddlZddlmZmZmZmZmZ ddl	m
Z
mZmZmZmZ edeƒZdd„ Zdd	„ Ze d
¡dd„ ƒZe d¡dd„ ƒZdd„ Zdd„ Zejddgddd„ ƒZejdddgddd„ ƒZejdddgddd„ ƒZejd ddgdd!d"„ ƒZdS )#a  
Temps dashboard: latest record per unit_id from MySQL shop_stats.Temps.
Editable unit_id and node_name via PUT endpoints.
Receives sensor readings via POST /reading (device_command for sleep toggle).
MySQL entry_date is stored as local datetime (not UTC).
é    N)Ú	BlueprintÚrender_templateÚjsonifyÚrequestÚResponse©Ú
MYSQL_HOSTÚ
MYSQL_PORTÚMYSQL_DATABASEÚ
MYSQL_USERÚMYSQL_PASSWORDÚtempsc                   C   s   t ttttdœS )N)ÚhostÚportÚdatabaseÚuserÚpasswordr   © r   r   ú(/var/www/html/Server/blueprints/temps.pyÚ_get_config   s   ûr   c               
   C   s  t ƒ } | d s	dS d}ztj| d | d | d | d | d tjjd}W n tjy= } zd	t|ƒfW  Y d	}~S d	}~ww zBt|ƒ | ¡ }| 	|¡ | 
¡ }W d	  ƒ n1 s[w   Y  |D ]}| d
¡pjd ¡  ¡ }|dvrwd|d
< qbW | ¡  |d	fS | ¡  w )z<Return list of latest Temps row per unit_id (by entry_date).r   )NzTEMPS_MYSQL_PASSWORD is not seta¯  
        SELECT t.entry_date, t.unit_id, t.node_name, t.temp, t.humid, t.bat, t.firmware_version,
               COALESCE(NULLIF(LOWER(TRIM(dc.command)), ''), 'nosleep') AS command,
               dc.new_device_id, dc.new_node_name
        FROM Temps t
        INNER JOIN (
            SELECT unit_id, MAX(entry_date) AS max_entry_date
            FROM Temps
            WHERE entry_date >= NOW() - INTERVAL 20 MINUTE
            GROUP BY unit_id
        ) latest ON t.unit_id = latest.unit_id AND t.entry_date = latest.max_entry_date
        LEFT JOIN device_command dc ON dc.device_id = t.unit_id
        WHERE t.entry_date >= NOW() - INTERVAL 20 MINUTE
        ORDER BY t.unit_id
    r   r   r   r   ©r   r   r   r   r   ÚcursorclassNÚcommandÚnosleep©Úsleepr   Úreboot)r   ÚpymysqlÚconnectÚcursorsÚ
DictCursorÚErrorÚstrÚ_ensure_device_commandÚcursorÚexecuteÚfetchallÚgetÚstripÚlowerÚclose)ÚcfgÚqueryÚconnÚeÚcurÚrowsÚrÚcmdr   r   r   Úget_latest_per_unit   s@   
ú€ÿ


þ€ý
ÿr3   ú/c                   C   s   t dƒS )Nztemps/index.html)r   r   r   r   r   ÚindexG   s   r5   z/api/latestc                  C   sP   t ƒ \} }|rtd|iƒdfS | D ]}| d¡}|d ur#| d¡|d< qt| ƒS )NÚerroréô  Ú
entry_datez%Y-%m-%d %H:%M:%S)r3   r   r'   Ústrftime)r0   Úerrr1   Úedr   r   r   Ú
api_latestL   s   

€r<   c                  C   s4   t ƒ } tj| d | d | d | d | d tjjdS )Nr   r   r   r   r   r   )r   r   r   r   r    )r+   r   r   r   Ú	_get_connY   s   úr=   c              	   C   sb   |   ¡ }| d¡ z| d¡ W n
 tjy   Y nw W d  ƒ n1 s&w   Y  |  ¡  dS )zDEnsure device_command table exists (shared with moisture blueprint).a/  
            CREATE TABLE IF NOT EXISTS device_command (
                device_id VARCHAR(16) PRIMARY KEY,
                command VARCHAR(20) NOT NULL DEFAULT 'sleep',
                new_device_id VARCHAR(16) DEFAULT NULL,
                new_node_name VARCHAR(50) DEFAULT NULL
            )
        zFALTER TABLE Temps ADD COLUMN firmware_version VARCHAR(24) DEFAULT NULLN)r$   r%   r   ÚOperationalErrorÚcommit)r-   r/   r   r   r   r#   e   s   

ÿ€õr#   z/readingÚPOST)Úmethodsc                  C   s¾  z¬t jddd} | stdddœƒdfW S |  d¡}|  d¡}|  d	¡}|  d
¡}|  d¡}|  d¡}|  d¡}|  d¡}|du sI|du sI|du rStdddœƒdfW S t|tƒr\| ¡ sftdddœƒdfW S | ¡ dd… }t|tƒru|nd ¡ dd… p~d}|durt|ƒ ¡ dd… nd}|durt|ƒ ¡ dd… nd}t|tƒr¦|nd ¡ dd… p¯d}t|tƒr·|nd ¡ dd… pÀd}|durÖt|tƒrÌ|nt|ƒ ¡ dd… nd}t|tƒrß|nd ¡ dd… pèd}tƒ }	z¨t|	ƒ |	 	¡ }
|
 
d|f¡ |
 ¡ }|r|d nd ¡  ¡ }|dvrd}|r&| d¡pd ¡ dd… nd}|r9| d¡p2d ¡ dd… nd}|
 
d|||||||||f	¡ |rO|n|}|rV|n|pZd}|re|
 
d |f¡ |ro|
 
d!|f¡ |d"kr{|
 
d#|f¡ W d  ƒ n	1 s†w   Y  |	 ¡  W |	 ¡  n|	 ¡  w tjd|||d$œd%d&}t|d'd(d)W S  tjyÁ   tdd*dœƒd+f Y S  tyÞ } ztdt|ƒdœƒd+fW  Y d}~S d}~ww ),zjAccept temp/humidity reading from WifiTemps device; insert into Temps; return command/device_id/node_name.T©ÚforceÚsilentFzInvalid or missing JSON©Úokr6   é  Úunit_idÚ	node_nameÚtempÚhumidÚmacÚipÚbatÚfirmware_versionNzMissing unit_id, temp, or humidz"unit_id must be a non-empty stringé
   Ú é2   é   é   zUSELECT command, new_device_id, new_node_name FROM device_command WHERE device_id = %sr   r   r   Únew_device_idé   Únew_node_namez²INSERT INTO Temps (unit_id, entry_date, temp, humid, mac, ip, bat, command, node_name, firmware_version)
                       VALUES (%s, NOW(), %s, %s, %s, %s, %s, %s, %s, %s)ÚNEWzCUPDATE device_command SET new_device_id = NULL WHERE device_id = %szCUPDATE device_command SET new_node_name = NULL WHERE device_id = %sr   zBUPDATE device_command SET command = 'nosleep' WHERE device_id = %s)rF   r   Ú	device_idrI   )ú,ú:)Ú
separatorséÈ   zapplication/json)ÚstatusÚmimetypezDatabase errorr7   )r   Úget_jsonr   r'   Ú
isinstancer"   r(   r=   r#   r$   r%   Úfetchoner)   r?   r*   ÚjsonÚdumpsr   r   r!   Ú	Exception)ÚdatarH   rI   rJ   rK   rL   rM   rN   rO   r-   r/   ÚrowÚcurrent_commandrU   rW   Úresp_device_idÚresp_node_nameÚbodyr.   r   r   r   Úreadingw   s”   







"  ""."
þ
&&ýþþ
þ€á
#þ"€ÿrl   z/sensor/<unit_id>/unit_idÚPUTc              
   C   s2  t jdddpi }| d¡pd ¡ }|stdddœƒdfS | p d ¡ } | s.tdd	dœƒdfS |d
d… }zFtƒ }z=t|ƒ | ¡ }| d|| f¡ | d| ||f¡ W d
  ƒ n1 s]w   Y  | 	¡  td| |dœƒdfW | 
¡  W S | 
¡  w  tjy˜ } ztdt|ƒdœƒdfW  Y d
}~S d
}~ww )zSet new unit_id for this sensor: body {"unit_id": "NEW_ID"}. Updates Temps rows and pushes new_id to device via device_command.TrB   rH   rQ   Fzunit_id requiredrE   rG   úinvalid unit_id in URLNrP   z0UPDATE Temps SET unit_id = %s WHERE unit_id = %sz„INSERT INTO device_command (device_id, command, new_device_id) VALUES (%s, 'nosleep', %s) ON DUPLICATE KEY UPDATE new_device_id = %s)rF   Úprevious_idÚnew_idr]   r7   ©r   r`   r'   r(   r   r=   r#   r$   r%   r?   r*   r   r!   r"   )rH   rf   rp   r-   r/   r.   r   r   r   Úset_unit_idË   s4   
þþ"€ÿrr   z/sensor/<unit_id>/commandc              
   C   s(  t jdddpi }| d¡pd ¡  ¡ }|dvr!tdddœƒd	fS | p$d ¡ } | s2tdd
dœƒd	fS | dd… } z=tƒ }z4t|ƒ | ¡ }| 	d| ||f¡ W d  ƒ n1 sYw   Y  | 
¡  td|dœƒdfW | ¡  W S | ¡  w  tjy“ } ztdt|ƒdœƒdfW  Y d}~S d}~ww )zESet command for sensor: body {"command": "sleep"|"nosleep"|"reboot"}.TrB   r   rQ   r   Fz/command must be 'sleep', 'nosleep', or 'reboot'rE   rG   rn   NrV   zdINSERT INTO device_command (device_id, command) VALUES (%s, %s) ON DUPLICATE KEY UPDATE command = %s)rF   r   r]   r7   )r   r`   r'   r(   r)   r   r=   r#   r$   r%   r?   r*   r   r!   r"   )rH   rf   r2   r-   r/   r.   r   r   r   Úset_commandè   s2   
þÿ"€ÿrs   z/sensor/<unit_id>/node_namec              
   C   s(  t jdddpi }| d¡pd ¡ dd… }| pd ¡ } | s'tddd	œƒd
fS zNtƒ }zEt|ƒ | ¡ }| d|p;d| f¡ | d| |pFd|pIdf¡ W d  ƒ n1 sVw   Y  | 	¡  td| |peddœƒdfW | 
¡  W S | 
¡  w  tjy“ } ztdt|ƒd	œƒdfW  Y d}~S d}~ww )zqSet node_name for this sensor: body {"node_name": "Name"}. Updates Temps and pushes to device via device_command.TrB   rI   rQ   NrR   Frn   rE   rG   z2UPDATE Temps SET node_name = %s WHERE unit_id = %sz„INSERT INTO device_command (device_id, command, new_node_name) VALUES (%s, 'nosleep', %s) ON DUPLICATE KEY UPDATE new_node_name = %s)rF   rH   rI   r]   r7   rq   )rH   rf   Únew_namer-   r/   r.   r   r   r   Úset_node_name  s.   
þþ"€ÿru   )Ú__doc__rc   r   Úflaskr   r   r   r   r   Úconfigr   r	   r
   r   r   Ú__name__Úbpr   r3   Úrouter5   r<   r=   r#   rl   rr   rs   ru   r   r   r   r   Ú<module>   s,    

-


S

