
	i                 @   sa  d  d l  m Z m Z m Z m Z d  d l Z d  d l Z d  d l Z d  d l Z d  d l	 Z	 d  d l
 m
 Z
 e e  Z e j d e j  d Z g  Z e	 j   Z d d   Z e e d d	 d
    Z e j d d d g d d    Z e j d d d g d d    Z e j d d d g d d    Z e d k r]e j d d d d d d  d S)    )FlaskrequestjsonifyResponseN)datetimelevelzno-sign-2025-11-03c          !   C   s   y! d t  j |  d d d } Wn< t k
 r_ } z t j j d |  d SWYd d } ~ Xn Xt B x: t t  D], } y | j	 |  Wqt t k
 r Yqt Xqt WWd QRXd S)u>   연결된 SSE 클라이언트들에게 payload(JSON)를 전송zdata: ensure_asciiFz

u   SSE 직렬화 실패: %sN)
jsondumps	Exceptionapploggererror_clients_locklist_clientsZ
put_nowait)Zpayloadmsgeq r   "/mod/web/acousticsspace/webhook.py_broadcast_to_clients   s    !r   )itreturnc             C   s   |  j  d  } |  j  d  } | } t | t  ry | d
 k rN | d k } n+ y t |  } Wn t k
 rx | } Yn Xd | d | d |  j  d  d |  j  d  d |  j  d  d |  j  d  d	 |  j  d	  i S)uJ   Aqara resource_report item 정규화: value를 bool/float로 변환 시도
resourceIdvalue01	subjectIdmodeltimeZ
statusCodeZtriggerSource)r   r   )get
isinstancestrfloatr   )r   Zridrawvalr   r   r   _normalize_item"   s"    r'   z/aqara/healthmethodsZGETc               C   s,   t  d d d t d t j   j   d i  S)NokTbuildZserver_timeZ)r   	BUILD_TAGr   ZutcnowZ	isoformatr   r   r   r   health<   s    r-   z/aqara/webhookZPOSTc              C   s  t  j d d  }  |  d  k r t  j d d d d  } t j j d t t  j  |  t d | d t	 t
 j
    i  t d	 d
 d t i  St j j d t j |  d d  |  j d  p |  j d  } | d k rz|  j d g   } d d   | D } xN | D]F } t j j d | j d  | j d  | j d  | j d   qWt d d d | d t	 t
 j
    i  n+ t d | i |  d t	 t
 j
    i   t d	 d
 d t i  S)NZsilentTcacheFZas_textz#Aqara PUSH (raw): headers=%s raw=%sr%   tscoder   r*   zAqara PUSH (json): %sr   ZmsgTypetypeZresource_reportdatac             S   s   g  |  ] } t  |   q Sr   )r'   ).0xr   r   r   
<listcomp>\   s   	 z!aqara_webhook.<locals>.<listcomp>u0   → resourceId=%s value=%s model=%s subjectId=%sr   r   r   r   Zeventitems)r   Zget_jsonget_datar   r   infodictheadersr   intr    r   r,   r	   r
   r!   )r2   r%   Zmsg_typer6   Znormednr   r   r   aqara_webhookJ   s$    ""8++r=   z/aqara/eventsc                 sj   t  j d d    t  t j    Wd  QRX  f d d   }  d d d d d	 d
 i } t |    d | S)Nmaxsize   c              3   s   d Vd d d t  d t t j    i }  d t j |   d Vt j   } ye x^ y   j d d	  } | VWqQ t j k
 r t j   | d	 k r d
 Vt j   } YqQ XqQ WWnF t k
 r t	 + y t
 j    Wn t k
 r Yn XWd  QRXYn Xd  S)Nzretry: 3000

r)   Tr*   r/   zevent: hello
data: z

timeout
   zevent: ping
data: {}

)r,   r;   r    r	   r
   r!   queueZEmptyGeneratorExitr   r   remove
ValueError)ZhelloZ	last_pingr   )r   r   r   streams   s&    $	zsse_events.<locals>.streamzContent-Typeztext/event-streamzCache-Controlzno-cacheZ
Connectionz
keep-aliver:   )rB   ZQueuer   r   appendr   )rF   r:   r   )r   r   
sse_eventsm   s    rH   __main__hostz0.0.0.0Zporti  debugT)Zflaskr   r   r   r   Zloggingr	   r    rB   Z	threadingr   __name__r   ZbasicConfigINFOr,   r   Lockr   r   r9   r'   Zrouter-   r=   rH   runr   r   r   r   <module>   s   "<$$#$,