§
    	tÃjN  ã                   ón   — d Z ddlZddlmZmZ ddlZddlZddlZ G d„ d¦  «        Z G d„ d¦  «        ZdS )zOTest-only device receiver. Traces contain metadata, never tokens or PCM/base64.é    N)ÚdatetimeÚtimezonec                   ó,   — e Zd Zd„ Zd„ Zddœd„Zd„ ZdS )ÚDownlinkRecorderc                 ó`   — t          j        ¦   «         | _        g | _        i | _        g | _        d S ©N)ÚtimeÚ	monotonicÚstartedÚrecordsÚstreamsÚdisconnects)Úselfs    úV/home/lighthouse/esp32-dev/.cache/physical-ui-cleanup-0.6a/server/tests/fake_device.pyÚ__init__zDownlinkRecorder.__init__
   s-   € Ý”~Ñ'Ô'ˆŒØˆŒØˆŒØˆÔÐÐó    c                 óò  — t          |t          ¦  «        s
J d¦   «         ‚t          j        |¦  «        }t	          j        ¦   «         }|d         }t          t          | j        ¦  «        t          j
        t          j        ¦  «                             ¦   «         || j        z
  |t          |                     d¦  «        ¦  «        ¬¦  «        }dD ]}||v r||         ||<   ŒdD ]4}||v r.t          ||                              d¦  «        ¦  «        ||dz   <   Œ5| j                             |¦  «         |dk    r`|d	         }|| j        vsJ ‚|d
         |d         |d         fdk    sJ ‚t          |g dg t%          j        ¦   «         d ¬¦  «        | j        |<   �na|dk    �r| j        |d	                  }|d         �J ‚|d         t          |d         ¦  «        k    s
J d¦   «         ‚t)          j        |d         d¬¦  «        }	dt          |	¦  «        cxk     rdk    rn nt          |	¦  «        dz  dk    sJ ‚|d                              |¦  «         |d                              t          |	¦  «        ¦  «         |dxx         t          |	¦  «        z  cc<   |d                              |	¦  «         nG|dk    rA| j        |d	                  }|d         €|d         t          |d         ¦  «        k    sJ ‚||d<   |S )Nz Gateway must send WebSocket TEXTÚtypezutf-8)ÚorderÚ	timestampÚelapsed_secondsr   Úpayload_bytes)Ú	speech_idÚsequenceÚchunksÚtargetÚ
session_idÚagentÚstateÚactivity_type)ÚactivityÚrecent_textÚ
final_textÚ_bytesÚspeech_startr   Úsample_rateÚbitsÚchannels)iD¬  é   é   r   )ÚstartÚtimesÚ	raw_bytesÚsizesÚdigestÚendÚspeech_chunkr0   r   r,   z$missing or duplicate speech sequenceÚaudioT)Úvalidatei�  é   r.   r-   r/   Ú
speech_endr   )Ú
isinstanceÚstrÚjsonÚloadsr	   r
   ÚdictÚlenr   r   Únowr   ÚutcÚ	isoformatr   ÚencodeÚappendr   ÚhashlibÚsha256Úbase64Ú	b64decodeÚupdate)
r   ÚwireÚeventr<   ÚkindÚrecordÚkeyÚsidÚstreamÚpcms
             r   ÚreceivezDownlinkRecorder.receive   s   € Ý˜$¥Ñ$Ô$ÐHÐHÐ&HÑHÔHÐHÝ”
˜4Ñ Ô ˆÝŒnÑÔˆØ�VŒ}ˆÝ�C ¤Ñ-Ô-½¼ÅhÄlÑ9SÔ9S×9]Ò9]Ñ9_Ô9_Ø&)¨$¬,Ñ&6¸TÕQTÐUY×U`ÒU`ÐahÑUiÔUiÑQjÔQjðlñ lô lˆàqð 	)ð 	)ˆCØ�eˆ|ˆ|Ø# Cœj��s‘øØ<ð 	Ið 	IˆCØ�eˆ|ˆ|Ý),¨U°3¬Z×->Ò->¸wÑ-GÔ-GÑ)HÔ)H��s˜X‘~Ñ&øØŒ×Ò˜FÑ#Ô#Ð#Ø�>Ò!Ð!Ø˜Ô$ˆCØ˜dœlÐ*Ð*Ð*Ð*Ø˜-Ô(¨%°¬-¸¸zÔ9JÐKÈ~Ò]Ð]Ð]Ð]Ý $¨3°bÀAÈRÕX_ÔXfÑXhÔXhÐnrÐ sÑ sÔ sˆDŒL˜ÑÑØ�^Ò#Ñ#Ø”\ %¨Ô"4Ô5ˆFØ˜%”=Ð(Ð(Ð(Ø˜Ô$­¨F°7¬OÑ(<Ô(<Ò<Ð<Ð<Ð>dÑ<Ô<Ð<ÝÔ" 5¨¤>¸DÐAÑAÔAˆCØ•s˜3‘x”xÐ'Ð'Ò'Ð' 4Ò'Ð'Ð'Ð'Ð'­C°©H¬H°q©L¸AÒ,=Ð,=Ð,=Ð,=Ø�7ŒO×"Ò" 3Ñ'Ô'Ð'Ø�7ŒO×"Ò"¥3 s¡8¤8Ñ,Ô,Ð,Ø�;ÐÐÔ¥3 s¡8¤8Ñ+ÐÐÑØ�8Ô×#Ò# CÑ(Ô(Ð(Ð(Ø�\Ò!Ð!Ø”\ %¨Ô"4Ô5ˆFØ˜%”=Ð(¨U°8¬_ÅÀFÈ7ÄOÑ@TÔ@TÒ-TÐ-TÐ-TÐ-TØˆF�5‰MØˆr   F)Úexpectedc                óê   — | j                              t          t          j        t
          j        ¦  «                             ¦   «         t          j	        ¦   «         | j
        z
  ||¬¦  «        ¦  «         d S )N)r   r   ÚcoderO   )r   r@   r:   r   r<   r   r=   r>   r	   r
   r   )r   rQ   rO   s      r   Ú
disconnectzDownlinkRecorder.disconnect3   sr   € ØÔ×Ò¥­x¬|½H¼LÑ/IÔ/I×/SÒ/SÑ/UÔ/UÝ59´^Ñ5EÔ5EÀdÄlÑ5RÐY]Ðhpð!rñ !rô !rñ 	sô 	sð 	sð 	sð 	sr   c                 ó  ‡— | j         ‰         }|d         €J ‚|d         |d         z
  }d„ t          |d         |d         dd …         ¦  «        D ¦   «         }ˆfd„| j        D ¦   «         }t          |d         t	          |d         ¦  «        |d                              ¦   «         t          d	„ |D ¦   «         ¦  «        ||d         |z  t          d
„ |D ¦   «         ¦  «        |z  t          |d¬¦  «        t          |d¬¦  «        ¬¦	  «	        S )Nr0   r+   c                 ó   — g | ]
\  }}||z
  ‘ŒS © rU   )Ú.0ÚaÚbs      r   ú
<listcomp>z+DownlinkRecorder.report.<locals>.<listcomp>;   s    € ÐOÐOÐO™T˜Q �Q�q‘SÐOÐOÐOr   r,   r*   c                 óF   •— g | ]}|                      d ¦  «        ‰k    ¯|‘ŒS )r   ©Úget)rV   ÚrrK   s     €r   rY   z+DownlinkRecorder.report.<locals>.<listcomp><   s/   ø€ ÐGÐGÐG˜¨Q¯UªU°;Ñ-?Ô-?À3Ò-FÐ-F�!Ð-FÐ-FÐ-Fr   r-   r/   c              3   ó&   K  — | ]}|d          V — ŒdS ©r   NrU   ©rV   r]   s     r   ú	<genexpr>z*DownlinkRecorder.report.<locals>.<genexpr>?   s(   è è € Ð<`Ð<`ÐTU¸Q¸Ô=OÐ<`Ð<`Ð<`Ð<`Ð<`Ð<`r   c              3   ó&   K  — | ]}|d          V — ŒdS r_   rU   r`   s     r   ra   z*DownlinkRecorder.report.<locals>.<genexpr>A   s'   è è € Ð5YÐ5YÈQ°a¸Ô6HÐ5YÐ5YÐ5YÐ5YÐ5YÐ5Yr   r   )Údefault)	Úraw_pcm_bytesÚchunk_countÚ
pcm_sha256Ú$maximum_websocket_text_payload_bytesÚtotal_transfer_secondsÚaverage_pcm_bytes_per_secondÚaverage_text_bytes_per_secondÚminimum_chunk_interval_secondsÚmaximum_chunk_interval_seconds)	r   Úzipr   r:   r;   Ú	hexdigestÚmaxÚsumÚmin)r   rK   rL   ÚdurationÚ	intervalsÚframess    `    r   ÚreportzDownlinkRecorder.report7   s,  ø€ Ø”˜cÔ"ˆØ�eŒ}Ð(Ð(Ð(Ø˜%”= 6¨'¤?Ñ2ˆØOÐO¥S¨°¬¸&À¼/È!È"È"Ô:MÑ%NÔ%NÐOÑOÔOˆ	ØGÐGÐGÐG˜Tœ\ÐGÑGÔGˆÝ &¨Ô"5Å3ÀvÈgÄÑCWÔCWØ% hÔ/×9Ò9Ñ;Ô;Ý9<Ð<`Ð<`ÐY_Ð<`Ñ<`Ô<`Ñ9`Ô9`Ø+3ÐRXÐYdÔReÐfnÑRnÝ25Ð5YÐ5YÐRXÐ5YÑ5YÔ5YÑ2YÔ2YÐZbÑ2bÝ36°yÈ!Ð3LÑ3LÔ3LÝ36°yÈ!Ð3LÑ3LÔ3LðNñ Nô Nð 	Nr   N)Ú__name__Ú
__module__Ú__qualname__r   rN   rR   ru   rU   r   r   r   r   	   sj   € € € € € ðð ð ð!ð !ð !ðF ,1ð sð sð sð sð sðNð Nð Nð Nð Nr   r   c                   ó    — e Zd ZdZdd„Zd„ ZdS )Ú
FakeDevicezMIn-process FastAPI websocket client using the same recorder as the TLS smoke.údownlink-testútest-device-onlyc                 óº   — |t          ¦   «         c| _        | _        |                     t	          d||ddddg¬¦  «        ¦  «         |                      d¦  «         d S )NÚhellozfake-devicez0.5.1Úagent_targetÚspeech_playback)r   Ú	device_idÚdevice_tokenÚboardÚfirmwareÚcapabilitiesÚ	hello_ack)r   ÚwsÚrecorderÚ	send_jsonr:   Úwait)r   r‡   r�   Útokens       r   r   zFakeDevice.__init__H   st   € Ø!#Õ%5Ñ%7Ô%7ÐˆŒ�”Ø
�Š•T˜w°)È%Ø -¸Ø(6Ð8IÐ'JðLñ Lô Lñ 	Mô 	Mð 	Mð 	�	Š	�+ÑÔÐÐÐr   c                 óÀ  ‡— t          d¦  «        D ]¼}| j                             ¦   «         }|d         dk    r8| j                             |d         ¦  «         t          d|d         › �¦  «        ‚| j                             |d         ¦  «        Š‰d         |k    r1t          ˆfd„|                     ¦   «         D ¦   «         ¦  «        r‰c S Œ½t          d|› �¦  «        ‚)	Ni,  r   zwebsocket.closerQ   zunexpected server disconnect: Útextc              3   óP   •K  — | ] \  }}‰                      |¦  «        |k    V — Œ!d S r   r[   )rV   ÚkÚvrG   s      €r   ra   z"FakeDevice.wait.<locals>.<genexpr>V   s6   øè è € Ð,ZÐ,ZÁ4À1Àa¨U¯YªY°q©\¬\¸QÒ->Ð,ZÐ,ZÐ,ZÐ,ZÐ,ZÐ,Zr   zmissing )Úranger‡   rN   rˆ   rR   ÚAssertionErrorÚallÚitems)r   rH   ÚfieldsÚ_ÚmessagerG   s        @r   rŠ   zFakeDevice.waitO   sá   ø€ Ý�s‘”ð 	ð 	ˆAØ”g—o’oÑ'Ô'ˆGØ�vŒÐ"3Ò3Ð3Ø”×(Ò(¨°¬Ñ9Ô9Ð9Ý$Ð%WÀgÈfÄoÐ%WÐ%WÑXÔXÐXØ”M×)Ò)¨'°&¬/Ñ:Ô:ˆEØ�VŒ} Ò$Ð$­Ð,ZÐ,ZÐ,ZÐ,ZÈ6Ï<Ê<É>Ì>Ð,ZÑ,ZÔ,ZÑ)ZÔ)ZÐ$Ø���øÝÐ.¨Ð.Ð.Ñ/Ô/Ð/r   N)r{   r|   )rv   rw   rx   Ú__doc__r   rŠ   rU   r   r   rz   rz   F   s=   € € € € € ØWÐWðð ð ð ð	0ð 	0ð 	0ð 	0ð 	0r   rz   )	r˜   rC   r   r   rA   r8   r	   r   rz   rU   r   r   ú<module>r™      sª   ðØ UÐ UØ €€€Ø 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ð 'Ø €€€Ø €€€Ø €€€ð:Nð :Nð :Nð :Nð :Nñ :Nô :Nð :Nðz0ð 0ð 0ð 0ð 0ñ 0ô 0ð 0ð 0ð 0r   