Æü«oëVÅux‚‚vè5ˆ¹NùpG6(QfY>@ôÉ–X„N ÙQrÑúSZ–O¼rÅWÁ”EMŒþbõÅ”)Mœàÿ>X:pÓ±<zøÆ›¡Ê(ŽÊ�¥¡»Õ-<Ì¢Ë24g”Y+Ê—¿G�p»ij¬ÁK�¡,á•õß-O}–5aO[¥¢ý)Š`I+?9ròÀÙcgL 2Ã�²RZUoØžÊsé  #‘±ò\æ’°ð¾�‚B²G�fLû}TÒCljŠº¬&^Ùy�_ àìíâ=B³Ý^ÕÃ`6‹J¢Â6ó·	O€'@HmdeL Â&…Ã`L[_ê¡gí–Ž/d1vÑíxkU�Y…7õ�`ÒïÎ<3RÒ|”exvýI€•5Y¤Júƒâï§j[Y–”Žê±,4U^•"œÝ îýÓÚeòáÂä£Åñ](ÌÇá†•ö.}€ünGÊC—u³ñ'4²é2ãCr‡Tå0qŒ×m•mvRÔƒ'4Œy7+zŠ�N¥ÌPƒÆo÷úzuÈAz]ÞMZ¸¿«¥¯mÄASAÕåÖ™Ùç�†jq…±”f8i:
f©²ƒ±{ßÍïÉ¬˜Q¼~B6�ÏWõvÑÞ±�ß¥£�oe[ò{]ÒÝðQ�Œ
¿ãEÔ¾5âh…´R$“²•.ˆj•ÕìsH¸:Tx”E(Ì"í9‘þPzñŽŠ™¯SÛ²%x0°.gŒîÀÝ·2 ¤Ì¾ ãl‚êvÝpÕHW—º´d<«¥•Ç„°.7(Ô+.µš}TîuÞ}·ß2á²ÿ×�†u2ÖÆø'eŒZ¸e�Ï=ï%þëþë«—�v¤b¶O�ÜfØ¢xª&=(2(Uœ�a¬�.d:¶OROË­8¼YÇë±¼”™t)�-Vñ*ÿ
q�Ø[Ön—ŒÓÙïïÃ1èã5åXŽìŒ­•ŠS¢
U+úVWëf\ ÷\À$¸]�á\fR÷ö;éšG@¥V›ÏÞBÇàa¯tÜ¡»æ@B“qv�@_E
!bžb¸ú‹ó#VõDFï›áÅé*Ða¸úÖ	üÏÂ`õ~àí'¸B�£Ïb/¯Œð,Sù65,!´¡ï–#‰[/òºéè¯ËATF¤‡†mYï’[a÷ö$ÁÊJâ=1§»±Ž.^×è/RùÔ_Ã«‘(Âd·ÏEnÒ»©(Š€°é'ÿš£×„Ú	÷ÜA2Ì‰$CS:EU2lî50EóY©Ô�ag¬¨-m»©­ð}Hd˜�¦]^¯M™ó>J5�f¾Äz;&'GÛ�úº¬^D;ÝbÙæg{Vœ¾ÚŽà'"º^þ{Õ Åtì±ü�6¶2pÁå»Í4ç£Qá%Þ#6ig3‘Ã–³È÷nGÚB¢¹ô›­ƒY±5Î„k];ý+¥‡WþJb™ú<¸}Ý­£�Âï¶41†]N5o–ùfAØ-KEF°0¥iãºI¼xs9a—µ®×ºig›·ÏìªÍCgéz“‘žHšb³ÁÃõY£:J®…	Î·tc?H5ÚOÖJ®…	Î·tc?H5ÚOÖ:v|ÖèÒpe�Ši�ÙÛ!›ÇU�Ó¡"	ß@úfèO@_ÿµ Þjüuÿ9ê×SðwÒšÃJ�‹§ý‰À…âÖ²S8.ÿŒ6fþ&ù€`eåÖò“G¼PˆœNðÏßñ3E 9q†i�ž3
Ægò�;Ä³*ýz¾%±ÿ„m�#R1ïü´¸jhfÄ¯®VWPý—Ï¥þÑÀ•L¬h"ß+Qàí.Š@¡Ðf¸›Á¢�¦¿0ÎÚv»™t0ÛÙ}À.z�$ü
G"ï ±Pk’[{RLíóåßó€÷pu9”èƒšma0GÉ°æ]áRŸ©sEô%VXÄt ÿ+P¯M3Ú«(SâŽÍmî%ÏÇ«ÇÛÐÒžôˆ–‘âjgÛúKŒC@ß¶¹ú…îz¥ê!Ñ$ÂÉrð;“Gîõåv£x}î­Í��”8{ÏWyÂùyöO¬‡_´ögì#hï’{JŸjÐÚ” ÜJ®…	Î·tc?H5ÚOÖJ®…	Î·tc?H5ÚOÖJ®…	Î·tc?H5ÚOÖVx‰ŽÈÐÐqž0µaK›£¹Bc6:½Tãª»ŽVƒ�©Wœ¼ æ:07‘;øÄÞnæ¦>!éãb·ÎÓ•{mÍ/t5È9-y1 Q¢æ©ÖÒ‰XíÍèàëêâøKãƒ�æ'ýq>ÞÁ!ÇM!µÀ¸s—âO×´»~?;2sB‰úã¸zØpòý	*ÄŸjÂ˜i©©ûþ‡ªüv ±PF”×¸IF�ºxãõñýrÄ]4µân¯2­ÉkÖ«'öµ¶]K!~‹EK¿öû]eùR§AØÈv´Yõä¡HãøRì¬€ÑÇ��¬ØùÖ™ôŒX¤£óî‰Cv@µ©9µeš“L§Ì±ÖžI(Ê  ‰ü‘Á´‰åN>Ô¥cLj°"ÆÍVªcM°®'ÀV/ŸX‹às¨å!èfÖætãCV¬mRÜ8PFG¬¿™@ð½œZ0(=42ü�¹Žx³—@þ‚•«{­Œ-'f±ö/;hl“uÏ4Í‘µ­å¤ÃôuX<-#Çøt÷â•2óÆÎ¡]Oé#•5óÒdêtnèJYZ‚4UñA¬H^Ò—ãPŠú20Ÿ¾í�ÏØ¹¹[§
U}‰�×õ8Ð¼¿FäUÕ_Œ ŸuPf[_GëMTGGøH×“ÇÓzôÇ¤þ´!ê(}“jÏÊÖØ9�›…Ø¨m«¢<[…Ì«/ÌD%ßÌ„Í¼—g�öÎ<˜ƒ’ô^Èl!‡+¤“¹ÙlÕG~b¬Ë˜é#xg/€æDß®Ý¡<“ ^	`©\K#J{æ×8Ü[æ]«ð:5‘×�½\¸8b1æ^ŽCgEßG.^fŒ?ò¥é‡	Y ÂÐ
ò¨þ!^�®„!@iÃÃÄŽ@I°iS`Š˜ ¸"æé«lHtæ^ŽCgEßG.^fŒ$Þn�™ÞÙ‡.†5•‚í[-%VCÓ;ïÐàÙi`NhõèË^Š4§¹�„¼ %-ÉÅøú®Ëf£LùñIÖg‘È6”†ðžôùH„©†®ùðûMaóÀÁâ4bÛ›2M÷�Çÿ	w« 8ÐÈå?Vÿ´*êñFº4?Ó²E´›þFzø²©hl|Ç+¶z€à¦JíÍ¦C6ö@ˆ|v	éøD†ÌÉê¥ ÕØà8#ÙÖ©êpë–ºœÏ©÷iJk�Ðeå„ìÆ¿ôUã�A@Œó�Ô„Îš	‚ö£(Ãô–h­—á,§Åµ<ˆDð&Z”ƒ‚Ö’økÛØr Ô§õQ¿q| öñ˜�É¸lšÈ4·�XêÑ·x!¬�™æ®1òuiiä¦¹*Ìgè±»žÉ`Gn**`•á÷…ª­~\*ÂÔÅ@ñã�‰Rú@¬LØ�‘'F-µ©?-Ü›”—ƒIåo<fs'�9&±IcC+©�ô	½
M/KÔxå¼ÞV!ôþÞ ¥P»ŸáªÒ†P*b¦…ä\(=F`bN×½·ùhoþxÎ£-+Gn3ÐgÏakN+¸¿a 3dýë±ª€<Zñ„÷–¿iÇ%X¾Ó\ªõâÜ€ÇrV„êsðêRNbŸGW·Î+.‹á�¼øÖ=2úê½,§˜/.)ˆ¿ ºå.Ó}dýë±ª€<Zñ„÷–DL,lÝÂ†ñÜ÷T
Ñ˜]ÙT"«CPŸ5áödš;šúå�Ò5í3â UˆwAóJî:‚´ûÕoë|7šhog}¦�6ª¦XÆ¯#QÊÖ:eÚž%µúÄ¾ÞÚ¦töðÊy3SSœ:|£`î¿éòÊ�Ù—uÓ@wT	ÉXÄè»W7z‹ÛtkNNldýë±ª€<Zñ„÷–1Ò¯Œ?ì†ŠãF=/ŒúuÝÖ šàè‘7	ýÖë@˜_Píœû¼oâÎ÷Zo¾É±$f÷×v…tˆd•Š .1í²¤ÊŸ¹€ïhfm‰g:z'¥`X“fÅ°éƒº{ŸZÓ< ØUåÉîµh¿:íOJ®…	Î·tc?H5ÚOÖôÊÖŠB¬ln¸™‹PÒ¤”•þ†éÄ†¾ÉñpCµ‚“´ˆhfClë|Î�!‰)íGe“f¸®gIc9ð¥k"Ø{~~]wåÁÊ‹¤(1\Š“H_Uû"ÌD?Æ ]†§1ƒÌr¿ìlòmñÍ4ÏÑuV™è6^‰
r†@W¾ƒhñd’pÚï2§j#…á`Ój„M¡È’:û`AÞX,uƒAÀrŸ–ÐùðoEàìæÑ½û/è!FÛÒ¶J”3bÞúdÈ˜W’qØ…&©us#.´òñOaÌX@¿”ÿ»UÇMÇ ~	L¢yhbÃÈ2æ¢ØŒ—ìÚYÇ©—º·í[ú÷�>&çÒ”[»•h›b$qs5�¾.ö�2ìW^$â‘õÿå“­ßÞ„®W»¢%•žø²|›Àµ ^TG�›J;Æî×­™?Þä�4ëŒØ’ƒ†¸*¢-/cF(Tùv¬/ã#[¿yU�VãÖº‘é.:ÚÁww/Ü¥ÄEÅ6:“ÁºKôRèC“Ëûß­—m7Þ¶5KŠ	°²ñÏ‰¯{=oû§(øþæw•û‰nàx¨e^'®¤ Cýôù¤…î?PÔŽ~ÜÓIß£b>=Û«¡.]´€ÆôÁŸ¹9f0y•Iº{Êwæ!&©<ji½œE�ú*¬uÖµãó ÄuÐ 6Q§¥HMˆ¾é&NÃrŒñŽ“°$šŠ³0{G=ˆ6V,CÏ–úY�õOƒ�\ù«ßk†HN5	£§MlÜ~3dõs³úÈAÆÁ®¶ë4m¯ -žGé%j ‘;6\ð5.	•ÅVÖ}&÷ÐîŽ•VÊIòpì·N'hŽ/.
3Àø’T�Ú(,^™VG�|Ò{4u¾˜ŒùçQ¥’]4�-»oÑ²ÃIíïk;°;g„ÖÆ�Sá7†],oœäé?’�£Íj]ýNÝjí4Æ·’Þ…é|Þ %Æ«P³®ªó
»ÅuA~xüSó²MÀG‰1s�d^la‡íÏ-â8ÚÇçi£�çb­@_TP¸J¥=ÑøwŠB³†žCÁü%iË²YÈÅ½-+¨ü
ïSµ½à@àá¿ì1ÿÇJå�"xä\\¶GW
ZE»3g¹hÉpzXa;�•%Ì§µm$d¹ƒÂ�}~ÊNò	–~öñ–#¤.Jmâz78UHpº”bþEÎ³~tÒ}¦aú6èCo€Þ¤ATA, PORT_SEN_DATA))

        try:
            sock.sendall(request)
            resp_meta = sock.recv(11)
            # print(f'{len(resp_meta)}, {len(resp_meta[1:3])}')
            
            resp_type = struct.unpack('1B', resp_meta[:1])[0]
            resp_length = struct.unpack('1H', resp_meta[1:3])[0]
            resp_time = struct.unpack('1Q', resp_meta[3:])[0]

            # print(f'{str(request)} > {resp_type}, {resp_length} | {resp_meta}')

            if resp_length > 0:
                resp = b''
                while len(resp) < resp_length:
                    chunk = sock.recv(resp_length - len(resp))
                    if not chunk:
                        raise ConnectionError("Connection closed")
                    resp += chunk

                # print(f'  {len(resp)} ')
            
            return (resp_time, resp_length, resp)

        except (socket.error, BrokenPipeError):
            print('!!! socket error')



def fetch_data():
    global val_cnt
    global measure_data_lock

    global vals
    global vals_raw
    global vals_times
    global tilts

    global ffts
    global freqs
    global fft_ffts
    global fft_ffts_freqs

    global save_to_file
    global save_to_file_starttime
    global vals_save

    qc = 0

    socket_perform_request(b'clear_data')

    while True:
        (resp_time, resp_length, acc_gyr_raw) = socket_perform_request(b'query_data')
        # print(f'{len(acc_gyr_raw)}')

        tilt = {}
        tilt_xs = []
        tilt_ys = []

        measure_data_lock.acquire()

        for i in range(0, len(acc_gyr_raw), MPU6050_FIFO_BYTES_PER_PACKAGE):
            v = list(struct.unpack(">hhhhhh", bytearray(acc_gyr_raw[i : i + MPU6050_FIFO_BYTES_PER_PACKAGE])))

            vals_acc = (np.array(v[:3]) / MPU6050_ACC_SCALING).tolist()
            vals_gyr = (np.array(v[3:]) / MPU6050_GYRO_SCALING).tolist()

            tilt_x = np.rad2deg(np.arctan2(v[2], v[1]) + np.pi / 2) - TILT_X_AVG
            tilt_y = np.rad2deg(np.arctan2(v[2], v[0]) + np.pi / 2) - TILT_Y_AVG
            # print(f'{tilt_x:.2f}, {tilt_y:.2f}')
            tilt_xs.append(tilt_x)
            tilt_ys.append(tilt_y)

            v.append(tilt_x)
            v.append(tilt_y)

            vals_raw.append(v)

            # vals_all = vals_acc + vals_gyr
            vals_all = vals_acc + vals_gyr + [tilt_x] + [tilt_y]

            vals.append(vals_all)
            # vals.append((np.array(v) / MPU6050_ACC_SCALING).tolist())

            # print(vals[-1:])
            # print(type(vals[-1:]))

        vals_times.append(resp_time)

        measure_data_lock.release()

        # print(len(vals))

        # if qc > 100:
        #     tilt_x_avg = np.average(np.array(tilt_xs))
        #     tilt_y_avg = np.average(np.array(tilt_ys))
        #     print(f'{tilt_x_avg:.2f}, {tilt_y_avg:.2f}')


        tilt['x'] = np.average(np.array(tilt_xs))
        tilt['y'] = np.average(np.array(tilt_ys))
        tilts.append(tilt)

        # if vals.length > FFT_VAL_CNT:
        # if qc > FFT_VAL_CNT:
        if len(vals) > FFT_VAL_CNT:
            t0 = time.perf_counter()
            
            ffts_loc = []
            freqs_loc = []

            fft_ffts_loc = []
            fft_ffts_freqs_loc = []

            fft_vals = vals[-FFT_VAL_CNT:]

            for i in range(MPU6050_FIFO_VALUES_PER_PACKAGE + 2):
                fft_vals_single = [r[i] for r in fft_vals]
                # fft_vals = vals[-FFT_VAL_CNT][:, i]

                #fft = np.abs(np.fft.fft(fft_vals_single)[:FFT_VAL_CNT // 2]).tolist()[1:100]
                #freq = np.fft.fftfreq(FFT_VAL_CNT, 1 / MEAS_SAMPLE_RATE)[:FFT_VAL_CNT // 2].tolist()[1:100]

                fft = np.abs(np.fft.fft(fft_vals_single)[:FFT_VAL_CNT // 2]).tolist()[1:500]
                freq = np.fft.fftfreq(FFT_VAL_CNT, 1 / MEAS_SAMPLE_RATE)[:FFT_VAL_CNT // 2].tolist()[1:500]

                ffts_loc.append(fft)
                freqs_loc.append(freq)

                fft_fft = np.abs(np.fft.fft(fft)[:len(fft) // 2]).tolist()[1:]
                fft_fft_freq = np.fft.fftfreq(len(fft), 1)[:len(fft) // 2].tolist()[1:]

                fft_ffts_loc.append(fft_fft)
                fft_ffts_freqs_loc.append(fft_fft_freq)

                # positive_fft = np.abs(fft_result[:len(fft_result)//2])
                # positive_freqs = frequencies[:len(frequencies)//2]

            ffts.append(ffts_loc)
            freqs.append(freqs_loc)

            fft_ffts.append(fft_ffts_loc)
            fft_ffts_freqs.append(fft_ffts_freqs_loc)

            t1 = time.perf_counter()
            d = t1 - t0
            # print(d)

        qc += 1

        print(vals_all)

        if save_to_file:
            vals_save.append(vals_all)
            print(f'  > {len(vals_all)}, {len(vals_save)}')
            
            if time.time() - save_to_file_starttime > SAVE_DURATION:
                fn =  os.path.join(Path(__file__).parent, DATA_FILEPATH, str(int(save_to_file_starttime)))
                
                print(f'    > saving file {fn}')
                with open(fn, "wb") as f:
                    pickle.dump(vals_save, f)

                vals_save.clear()
                save_to_file = False

        if len(vals) > 100000:
            del vals[:9000]

        time.sleep(FETCH_DATA_INTERVAL)


## --- main ----------------------------------------------------------------

val_cnt = 0

# --- python deque (> RingBuffer) --- 
# vals = RingBuffer()
# vals_raw = RingBuffer()
# vals_times = RingBuffer()

# tilts = RingBuffer()

# ffts = RingBuffer()
# freqs = RingBuffer()
# fft_ffts= RingBuffer()
# fft_ffts_freqs = RingBuffer()

# --- python list --- 
vals = []
vals_raw = []
vals_times = []

tilts = []

ffts = []
freqs = []
fft_ffts= []
fft_ffts_freqs = []

save_to_file = False
save_to_file_starttime = None
vals_save = []

measure_state = threading.Event()
measure_data_lock = threading.Lock()

data_fetcher_thread = threading.Thread(target=fetch_data)
data_fetcher_thread.start()

asyncio.run(run_server())



