import pathlib,shutil
r=pathlib.Path('/home/lighthouse/esp32-dev/.cache/speech-playback-diagnostics-20261006')
d=r/'.cache/speech-diagnostics'
dst=r/'firmware/components/tcp_transport'
assert not dst.exists()
shutil.copytree('/home/lighthouse/esp32-dev/.cache/esp-idf-v5.5.4/components/tcp_transport',dst)
proto='\n#include "esp_timer.h"\n#include <sys/ioctl.h>\nextern void speech_diag_net_record(int,int64_t,int64_t,int,int,int,int);\n'
p=dst/'transport_ssl.c';s=p.read_text();s=s.replace('#include "esp_tls.h"','#include "esp_tls.h"'+proto)
s=s.replace('''    int poll = esp_transport_poll_read(t, timeout_ms);''','''    const int64_t poll_start=esp_timer_get_time();
    int pending=-1;ioctl(ssl->sockfd,FIONREAD,&pending);
    int cached=esp_tls_get_bytes_avail(ssl->tls);
    int poll = esp_transport_poll_read(t, timeout_ms);
    speech_diag_net_record(1,poll_start,esp_timer_get_time()-poll_start,len,poll,pending,cached);''',1)
s=s.replace('''    int ret = esp_tls_conn_read(ssl->tls, (unsigned char *)buffer, len);''','''    const int64_t tls_start=esp_timer_get_time();
    int ret = esp_tls_conn_read(ssl->tls, (unsigned char *)buffer, len);
    int saved_errno=errno;pending=-1;ioctl(ssl->sockfd,FIONREAD,&pending);
    speech_diag_net_record(2,tls_start,esp_timer_get_time()-tls_start,len,ret,pending,ret<0?saved_errno:0);
    errno=saved_errno;''',1);p.write_text(s)
p=dst/'transport_ws.c';s=p.read_text();s=s.replace('#include <string.h>','#include <string.h>'+proto)
old='''    if (bytes_to_read != 0 && (rlen = esp_transport_read_internal(ws, buffer, bytes_to_read, timeout_ms)) <= 0) {'''
new='''    int64_t read_start=esp_timer_get_time();
    if(bytes_to_read!=0) rlen=esp_transport_read_internal(ws,buffer,bytes_to_read,timeout_ms);
    speech_diag_net_record(3,read_start,esp_timer_get_time()-read_start,bytes_to_read,rlen,ws->frame_state.bytes_remaining,ws->frame_state.opcode);
    if (bytes_to_read != 0 && rlen <= 0) {'''
assert old in s;s=s.replace(old,new);p.write_text(s)
p=r/'firmware/managed_components/espressif__esp_websocket_client/esp_websocket_client.c';s=p.read_text();s=proto+s
old='''        rlen = esp_transport_read(client->transport, client->rx_buffer, client->buffer_size, client->config->network_timeout_ms);'''
new='''        const int64_t diag_start=esp_timer_get_time();
'''+old+'''
        speech_diag_net_record(4,diag_start,esp_timer_get_time()-diag_start,client->buffer_size,rlen,client->payload_offset,0);'''
assert old in s;s=s.replace(old,new)
old='''        esp_websocket_client_dispatch_event(client, WEBSOCKET_EVENT_DATA, client->rx_buffer, rlen);'''
new='''        const int64_t callback_start=esp_timer_get_time();
'''+old+'''
        speech_diag_net_record(5,callback_start,esp_timer_get_time()-callback_start,rlen,client->payload_len,client->payload_offset,client->last_opcode);'''
assert old in s;s=s.replace(old,new);p.write_text(s)
shutil.copy(d/'net_trace.cpp',r/'firmware/main/net_trace.cpp')
p=r/'firmware/main/CMakeLists.txt';s=p.read_text();s=s.replace('"wifi_manager.cpp"','"wifi_manager.cpp" "net_trace.cpp"');s+='\ntarget_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_net_recv")\n';p.write_text(s)
p=r/'firmware/main/cloud_client.cpp';s=p.read_text();s='extern "C" void speech_diag_net_init();\n'+s;s=s.replace('ESP_ERROR_CHECK(esp_websocket_client_start(s_client));','speech_diag_net_init();\n    ESP_ERROR_CHECK(esp_websocket_client_start(s_client));');p.write_text(s)
p=r/'boards/m5stack_stopwatch/audio_backend.cpp';s=p.read_text()
needle='''ESP_LOGW(TAG,"[SPEECH] receive idle timeout'''
if needle not in s:
    needle='''ESP_LOGW(TAG, "[SPEECH] receive idle timeout'''
assert needle in s
idx=s.index(needle)
extra='''char diag_accepted_hex[65],diag_written_hex[65];
                diag_digest(&s_diag_accepted,diag_accepted_hex);diag_digest(&written_ctx,diag_written_hex);
                ESP_LOGI(TAG,"[DIAG_SPEECH] timeout_totals accepted_bytes=%u accepted_frames=%u accepted_sha=%s written_bytes=%u written_frames=%u written_sha=%s",unsigned(s_diag_accepted_bytes),s_diag_frames,diag_accepted_hex,unsigned(written_bytes),written_frames,diag_written_hex);
                '''
s=s[:idx]+extra+s[idx:];p.write_text(s)
print('Isolated TCP transport override and metadata-only PSRAM trace prepared')
