+
    ÞDjé/  ã                   óÂ  € R t ^ RIt^ RIt^ RIHtHtHtHtHt ^ RI	H
t
HtHt ^ RIHtHtHtHtHt ]! R]4      tR tR t]P/                  R4      R	 4       t]P/                  R
4      R 4       tR tR t]P/                  RR.R7      R 4       t]P/                  RRR.R7      R 4       t]P/                  RRR.R7      R 4       t]P/                  RRR.R7      R 4       tR# )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)Úbattery_stateÚensure_alert_state_tableÚevaluate_and_notify©Ú
MYSQL_HOSTÚ
MYSQL_PORTÚMYSQL_DATABASEÚ
MYSQL_USERÚMYSQL_PASSWORDÚtempsc            
      óB   € R \         R\        R\        R\        R\        /# )ÚhostÚportÚdatabaseÚuserÚpasswordr
   © ó    Ú8/workplace/Workspace/Software/Server/blueprints/temps.pyÚ_get_configr      s%   € à”
Ø”
Ø”NØ”
Ø”Nðð r   c            	     óú  € \        4       p V R,          '       g   R# Rp \        P                  ! V R,          V R,          V R,          V R,          V R,          \        P                  P                  R7      p \        T4       TP                  4       ;_uu_ 4       pTP                  T4       TP                  4       pRRR4       X FH  pTP                  R	4      ;'       g    R
P                  4       P                  4       pTR9  g   KC  R
TR	&   KJ  	  TP                  4        TR3#   \        P
                   d   pR\        T4      3u Rp?# Rp?ii ; i  + '       g   i     L¡; i  TP                  4        i ; i)z<Return list of latest Temps row per unit_id (by entry_date).r   Na¯  
        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   ÚcursorclassÚcommandÚnosleep)NzTEMPS_MYSQL_PASSWORD is not set©Ú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Úcmds           r   Úget_latest_per_unitr9      s+  € ä
‹-€CØˆz�?Œ?Ø6Ð6ð€Eð
Ü�ŠØ�V•Ø�V•Ø�V•Ø˜•_Ø˜•_ÜŸ™×2Ñ2ô
ˆð
Ü˜tÔ$Ø�[‰[�]Œ]˜cØ�K‰K˜ÔØ—<‘<“>ˆD÷ ó ˆAØ—5‘5˜Ó#×0Ð0 y×7Ñ7Ó9×?Ñ?ÓAˆCØÐ8Ö8Ø(��)“ñ ð
 	�
‰
ŒØ�ˆ:Ðøô �=‰=ô Ø”S˜“Vˆ|Õûðú÷ �]ûð 	�
‰
�úsN   ŸAD& Á7#E( Â"EÂ<$E( Ã!#E( Ä		E( Ä&EÄ;EÅEÅEÅE%	Å E( Å(E:Ú/c                  ó   € \        R 4      # )ztemps/index.html)r   r   r   r   Úindexr<   H   s   € äÐ-Ó.Ð.r   z/api/latestc                  óÆ   € \        4       w  rV'       d   \        R V/4      R3# V  F.  pVP                  R4      pVf   K  VP                  R4      VR&   K0  	  \        V 4      # )Úerroréô  Ú
entry_datez%Y-%m-%d %H:%M:%S)r9   r   r-   Ústrftime)r6   Úerrr7   Úeds       r   Ú
api_latestrD   M   s_   € ä#Ó%�I€Dß
Ü˜ �~Ó&¨Ð+Ð+ãˆØ�U‰U�<Ó ˆØŒ>Ø Ÿk™kÐ*=Ó>ˆAˆl‹Oñ ô �4‹=Ðr   c            	      óÄ   € \        4       p \        P                  ! V R ,          V R,          V R,          V R,          V R,          \        P                  P                  R7      # )r   r   r   r   r   r   )r   r#   r$   r%   r&   )r1   s    r   Ú	_get_connrF   Z   sJ   € Ü
‹-€CÜ�?Š?Ø��[Ø��[Ø��[Ø�Z•Ø�Z•Ü—O‘O×.Ñ.ôð r   c                ó   € V P                  4       ;_uu_ 4       pVP                  R4        VP                  R4       RRR4       V P	                  4        \        V 4       R#   \        P                   d     L<i ; i  + '       g   i     LH; i)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Úcommitr   )r3   r5   s   & r   r)   r)   f   sl   € à	�‰�Œ˜#Ø�‰ð ô 	ð	Ø�K‰KÐ`Ôa÷ 
ð 	‡K�K„MÜ˜TÖ"øô ×'Ñ'ô 	Ùð	ú÷ 
�ús(   ™A=¬A"Á"A:Á7A=Á9A:Á:A=Á=B	z/readingÚPOST)Úmethodsc                 óZ
  €  \         P                  ! RRR7      p V '       g   \        RRRR/4      R3# V P                  R4      pV P                  R	4      pV P                  R
4      pV P                  R4      pV P                  R4      pV P                  R4      pV P                  R4      pV P                  R4      pVe	   Ve   Vf   \        RRRR/4      R3# \	        V\
        4      '       d   VP                  4       '       g   \        RRRR/4      R3# VP                  4       R,          p\	        V\
        4      '       d   TMRP                  4       R,          ;'       g    RpVe!   \        V4      P                  4       R,          MRpVe!   \        V4      P                  4       R,          MRp\	        V\
        4      '       d   TMRP                  4       R,          ;'       g    Rp\	        V\
        4      '       d   TMRP                  4       R,          ;'       g    RpVe9   \	        V\
        4      '       d   TM
\        V4      P                  4       R,          MRp\	        V\
        4      '       d   TMRP                  4       R,          ;'       g    Rp\        4       p	 \        V	4       V	P                  4       ;_uu_ 4       p
V
P                  RV34       V
P                  4       pV'       d
   VR,          MRP                  4       P                  4       pVR09  d   RpV'       d1   VP                  R4      ;'       g    RP                  4       R,          MRpV'       d1   VP                  R4      ;'       g    RP                  4       R,          MRpV
P                  RWWEWgWÂV3	4       V'       d   TMTpV'       d   TMT;'       g    R pV'       d   V
P                  R!V34       V'       d   V
P                  R"V34       VR8X  d   V
P                  R#V34       \        V4      pV'       d#   \        T	R$TR%TR&T;'       g    T R'V R(2R)7       RRR4       V	P                  4        V	P!                  4        \"        P$                  ! RRRXR*XR	X/R1R+7      p\'        V^ÈR,R-7      #   + '       g   i     L^; i  T	P!                  4        i ; i  \(        P*                   d    \        RRRR./4      R/3u # \,         d%   p\        RRR\        T4      /4      R/3u Rp?# Rp?ii ; i)2zjAccept temp/humidity reading from WifiTemps device; insert into Temps; return command/device_id/node_name.T©ÚforceÚsilentÚokFr>   zInvalid or missing JSONé�  Ú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ºNé
   NÚ ºNé2   N:Né   N:Né   NzUSELECT command, new_device_id, new_node_name FROM device_command WHERE device_id = %sr   r   r"   Únew_device_idºNé   NÚ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 = %szBUPDATE device_command SET command = 'nosleep' WHERE device_id = %sr   ÚbatteryzSolarMon alert: battery low on z
. Battery=Ú%)r3   Úsource_typeÚ	source_idÚmetricÚcurrent_stateÚalert_messageÚ	device_id)Ú
separatorszapplication/json)ÚstatusÚmimetypezDatabase errorr?   r    )Ú,Ú:)r   Úget_jsonr   r-   Ú
isinstancer(   r.   rF   r)   r*   r+   Úfetchoner/   r   r	   rI   r0   ÚjsonÚdumpsr   r#   r'   Ú	Exception)ÚdatarR   rS   rT   rU   rV   rW   rX   rY   r3   r5   ÚrowÚcurrent_commandra   rd   Úresp_device_idÚresp_node_nameÚ
batt_stateÚbodyr4   s                       r   Úreadingr€   y   sv  € ð[<Ü×Ò d°4Ô8ˆßÜ˜D %¨Ð2KÐLÓMÈsÐRÐRà—(‘(˜9Ó%ˆØ—H‘H˜[Ó)ˆ	Ø�x‰x˜ÓˆØ—‘˜Ó!ˆØ�h‰h�u‹oˆØ�X‰X�d‹^ˆØ�h‰h�u‹oˆØŸ8™8Ð$6Ó7ÐàŠ?˜dšl¨eªmÜ˜D %¨Ð2SÐTÓUÐWZÐZÐZä˜'¤3×'Ò'¨w¯}©}¯ªÜ˜D %¨Ð2VÐWÓXÐZ]Ð]Ð]Ø—-‘-“/ #Õ&ˆÜ",¨Y¼×"<Ò"<‘YÀ"×KÑKÓMÈcÕR×ZÐZÐVZˆ	Ø)-Ò)9Œs�4‹y�‰Ó  Ö%¸tˆØ+0Ò+<”�E“
× Ñ Ó" 3Ö'À$ˆÜ  ¤c×*Ò*‰s°×9Ñ9Ó;¸CÕ@×HÐHÀDˆÜ˜r¤3×'Ò'‰b¨R×6Ñ6Ó8¸Õ=×EÐEÀˆØJMÊ/”j ¤c×*Ò*‰s´°C³×?Ñ?ÓAÀ#ÖFÐ_cˆÜ0:Ð;KÌS×0QÒ0QÑ,ÐWY×`Ñ`ÓbÐcfÕg×oÐoÐkoÐä‹{ˆð4	Ü" 4Ô(Ø—‘—” #Ø—‘ØkØ�Jôð —l‘l“n�ß58 3 y¦>¸i×"NÑ"NÓ"P×"VÑ"VÓ"X�Ø"Ð*HÔHØ&/�OßQT §¡¨Ó!9×!?Ð!?¸R× FÑ FÓ HÈÖ MÐZ^�ßQT §¡¨Ó!9×!?Ð!?¸R× FÑ FÓ HÈÖ MÐZ^�à—‘ðMà E°¸ÐUeÐfô÷
 3@¡ÀW�ß2?¡Ài×FXÐFXÐSX�ß Ø—K‘KØ]Ø ˜
ô÷ !Ø—K‘KØ]Ø ˜
ôð
 # hÔ.Ø—K‘KØ\Ø ˜
ôô +¨3Ó/�
ßÜ'Ø!Ø$+Ø")Ø(Ø&0à=¸i×>RÐ>RÈ7Ð=Sð T'Ø'* e¨1ð.õ
÷K ð` �K‰KŒMà�J‰JŒLä�zŠzØ�4˜ O°[À.ÐR]Ð_mÐnØ!ô
ˆô ˜ SÐ3EÔFÐF÷q —ûðd �J‰J�Lûô �=‰=ô FÜ˜˜e WÐ.>Ð?Ó@À#ÐEÒEÜô <Ü˜˜e W¬c°!«fÐ5Ó6¸Ð;Õ;ûð<úsÊ   ‚S ¢S ³B$S Ã+S ÄS ÄAS Å"BS Ç'8S È A6S ÊS Ê%#R? ËA#R,Ì,R,Í!R,Í&R,Í>AR,Ï
R,Ï
R,ÏR,Ï4AR,ÑR,ÑR? Ñ.=S Ò,R<	Ò7R? Ò?SÓS Ó&T*Ó<T*ÔT*ÔT%ÔT*Ô%T*z/sensor/<unit_id>/unit_idÚPUTc           	     ó.  € \         P                  ! RRR7      ;'       g    / pVP                  R4      ;'       g    RP                  4       pV'       g   \	        RRRR/4      R	3# T ;'       g    RP                  4       p V '       g   \	        RRRR
/4      R	3# VR,          p \        4       p \        V4       VP                  4       ;_uu_ 4       pVP                  RW 34       VP                  RWV34       RRR4       VP                  4        \	        RRRV RV/4      ^È3VP                  4        #   + '       g   i     LC; i  TP                  4        i ; i  \        P                   d%   p\	        RRR\        T4      /4      R3u Rp?# Rp?ii ; i)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.TrM   rR   r\   rP   Fr>   zunit_id requiredrQ   úinvalid unit_id in URLrZ   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 = %sNÚprevious_idÚnew_idr?   ©r   rs   r-   r.   r   rF   r)   r*   r+   rI   r0   r#   r'   r(   )rR   ry   r…   r3   r5   r4   s   &     r   Úset_unit_idr‡   Ú   s_  € ô ×Ò $¨tÔ4×:Ð:¸€DØ�h‰h�yÓ!×'Ð' R×.Ñ.Ó0€FßÜ˜˜e WÐ.@ÐAÓBÀCÐGÐGØ�}ˆ}˜"×#Ñ#Ó%€GßÜ˜˜e WÐ.FÐGÓHÈ#ÐMÐMØ�C�[€Fð<Ü‹{ˆð	Ü" 4Ô(Ø—‘—” #Ø—‘ÐNÐQWÐPaÔbØ—‘ð [Ø fÐ-ô÷ ð �K‰KŒMÜ˜D $¨°wÀÈ&ÐQÓRÐTWÐWà�J‰J�L÷ —ûð �J‰J�LûÜ�=‰=ô <Ü˜˜e W¬c°!«fÐ5Ó6¸Ð;Õ;ûð<úsN   Â"
E Â-#E Ã(D3Ã8*E Ä"E Ä3E	Ä>E ÅEÅE ÅFÅ0FÆ	FÆFz/sensor/<unit_id>/commandc           	     ó  € \         P                  ! RRR7      ;'       g    / pVP                  R4      ;'       g    RP                  4       P	                  4       pVR9  d   \        RRRR/4      R	3# T ;'       g    RP                  4       p V '       g   \        RRRR
/4      R	3# V R,          p  \        4       p \        V4       VP                  4       ;_uu_ 4       pVP                  RWV34       RRR4       VP                  4        \        RRRV/4      ^È3VP                  4        #   + '       g   i     LA; i  TP                  4        i ; i  \        P                   d%   p\        RRR\        T4      /4      R3u Rp?# Rp?ii ; i)zESet command for sensor: body {"command": "sleep"|"nosleep"|"reboot"}.TrM   r   r\   rP   Fr>   z/command must be 'sleep', 'nosleep', or 'reboot'rQ   rƒ   rb   zdINSERT INTO device_command (device_id, command) VALUES (%s, %s) ON DUPLICATE KEY UPDATE command = %sNr?   r    )r   rs   r-   r.   r/   r   rF   r)   r*   r+   rI   r0   r#   r'   r(   )rR   ry   r8   r3   r5   r4   s   &     r   Úset_commandr‰   ÷   sT  € ô ×Ò $¨tÔ4×:Ð:¸€DØ�8‰8�IÓ×$Ð$ "×
+Ñ
+Ó
-×
3Ñ
3Ó
5€CØ
Ð0Ô0Ü˜˜e WÐ._Ð`ÓaÐcfÐfÐfØ�}ˆ}˜"×#Ñ#Ó%€GßÜ˜˜e WÐ.FÐGÓHÈ#ÐMÐMØ�c�l€Gð<Ü‹{ˆð
	Ü" 4Ô(Ø—‘—” #Ø—‘ØzØ 3Ð'ô÷ ð
 �K‰KŒMÜ˜D $¨	°3Ð7Ó8¸#Ð=à�J‰J�L÷ —ûð �J‰J�LûÜ�=‰=ô <Ü˜˜e W¬c°!«fÐ5Ó6¸Ð;Õ;ûð<úsN   Â/
E Â:#D> ÃD+Ã2(D> ÄE Ä+D;	Ä6D> Ä>EÅE ÅFÅ(FÆFÆFz/sensor/<unit_id>/node_namec           	     óJ  € \         P                  ! RRR7      ;'       g    / pVP                  R4      ;'       g    RP                  4       R,          pT ;'       g    RP                  4       p V '       g   \	        RRRR	/4      R
3#  \        4       p \        V4       VP                  4       ;_uu_ 4       pTP                  RT;'       g    RV 34       TP                  RY;'       g    RT;'       g    R34       RRR4       VP                  4        \	        RRRT RT;'       g    R/4      ^È3VP                  4        #   + '       g   i     LM; i  TP                  4        i ; i  \        P                   d%   p\	        RRR\        T4      /4      R3u Rp?# Rp?ii ; i)zqSet node_name for this sensor: body {"node_name": "Name"}. Updates Temps and pushes to device via device_command.TrM   rS   r\   r]   rP   Fr>   rƒ   rQ   z2UPDATE Temps SET node_name = %s WHERE unit_id = %sNz„INSERT INTO device_command (device_id, command, new_node_name) VALUES (%s, 'nosleep', %s) ON DUPLICATE KEY UPDATE new_node_name = %srR   r?   r†   )rR   ry   Únew_namer3   r5   r4   s   &     r   Úset_node_namerŒ     sc  € ô ×Ò $¨tÔ4×:Ð:¸€DØ—‘˜Ó%×+Ð+¨×2Ñ2Ó4°SÕ9€HØ�}ˆ}˜"×#Ñ#Ó%€GßÜ˜˜e WÐ.FÐGÓHÈ#ÐMÐMð<Ü‹{ˆð	Ü" 4Ô(Ø—‘—” #Ø—‘ÐPÐS[×ScÐScÐ_cÐelÐRmÔnØ—‘ð [Ø×.Ð.¨$°×0@Ð0@¸DÐAô÷ ð �K‰KŒMÜ˜D $¨	°7¸KÈ×IYÐIYÐUYÐZÓ[Ð]`Ð`à�J‰J�L÷ —ûð �J‰J�LûÜ�=‰=ô <Ü˜˜e W¬c°!«fÐ5Ó6¸Ð;Õ;ûð<ús`   Â
E) Â#E Â53EÃ)
EÃ4EÃ<*E Ä'	E Ä0E) ÅE	ÅE ÅE&Å&E) Å)F"Å>FÆF"ÆF") Ú__doc__rv   r#   Úflaskr   r   r   r   r   Úblueprints.alertsr   r   r	   Úconfigr   r   r   r   r   Ú__name__Úbpr   r9   Úrouter<   rD   rF   r)   r€   r‡   r‰   rŒ   r   r   r   Ú<module>r”      s  ðñó Û ß HÕ Hç ZÑ Zß UÕ Uáˆw˜Ó!€òò*ðZ ‡�ˆ#ƒñ/ó ð/ð ‡�ˆ-Óñ	ó ð	ò	ò#ð& ‡�ˆ*˜v˜h€Ó'ñ]<ó (ð]<ð@ ‡�Ð
%°°v¨€Ó?ñ<ó @ð<ð8 ‡�Ð
%°°v¨€Ó?ñ<ó @ð<ð6 ‡�Ð
'°%¸°€ÓAñ<ó Bò<r   