�¥ýà3hË±âdi˜Dèñ¨‰7§‹—9Õà‡©±šÚ)Û�%<÷Ã†8�Ðó^ÝÀÎ¡ŠL:>|ýY÷²¡õÒùF[kTcW¥}w_b.FàÚÏæ3tÖ]K}¾ùÝ�fz4gó`¡ïvýWÙ—;Iœð7×�p¿5È
¸Úi(ëÜ%I¢KáâgÃ=goE<Zbt~0¥2�ÜXj“ò„~a¶•{¢ÝÆ™).ªÄc¥¨ïÓ#{Y,šúü«¤`F�”t“(ïQ2iJÀÔî+ª”â{˜½>vÞð´KEW¼Hš˜ª£måêyÑ¶`ù=Ö	thÄÿÝ«MtJU&HŒÁÇÏ'wQŽÏÜtø!/wÉó,£µS�·”-3 ­ùdYªIl6B5¢í£³NçÄs€ñÕôí¬AÑ3˜¾Õ™È4ÌÆ~»GbBHˆð³jQfLdÄ@ŠžL™

îiFSO
}1À§ãZ¦E1 ¯¡µÓ ‰¡JtF]1_Ls¦@â¡
°…ƒ¶ð;-Š;a‹Ä…TñÖ½ŠÒñËzÕÞ•EJB)—pÈb·¦§*ƒÕõ	:½Èª+æ×´Òçt€|/c~£‘™X´ñÝeTõŸR‘–²Då‰p¢@	ˆur®·‹ÑNø€Œ96À@)Ý›àc¼ÐöGçßËž`´»ÁäÕ¾0Ë$q]¡Õu°ß±‚:ðZI»–tÚ0ZåwÅ·bÐÅo/‚Á¸Î÷ËU°Áþfi '™Ì‘ädxEe6?XW~›4•Ü'ôÅ„‡ÒL—|ïñ+mð·ÅØ>½'’~R¬ÂÚâ@ŒYÌiY:ØÑK[Éý5W3¥Mn?¬Ô¡?8c7t1H$Û!0ï˜9Ý¥×t?ñÔÈc^A>þÿ’t¿þ3sŒJØ€‰5/Å%{³úibIƒÍù÷~"Ö™ŠÀPŒD¯õ’wæKñ¬}X:¨9R¾Ž®åá¤ªj\*ÐZÇ¿»½­î*Ò™tR } À££¼|é eÆ·cXQf˜SªÎ8¢¤-7ð˜ú5|¿t[ÎwóQo³¼ÝOÕnk!Â¼õ@Èîà‰JèÞ½˜[g1vEŒ‡‚ šÃŽbZÄAÏæ_ÏRéÿE -ZÂŽûd=¢Gó×šŒöIj“žÈÀ7íÙ²Æ²@Ä^1z‡x³åþúHþuT|´AöR¡Î–ì‡Ä‘Å-.œïU†g¿»ô2èÿÉ.'ÆŒ‡áÿk -	¾Ýã3�˜?±hÏ>˜©6M¯–a  ª*§<ÎhKÝtþ.E�°‰Õë¢ ZÊàÎkx‹U4FÕD[Ï�UÒ—9_ûW„D_aéžqECo„XÞÏÚeOVjLˆ¦VÑ7ÔY€è�·É-§‰¥-3|‘6M@2o\ô1ðÔdã^"°êymÄÙJ®…	Î·tc?H5ÚOÖJ®…	Î·tc?H5ÚOÖ—
!<Ÿ—eOÌ+ |Òñ£7û—j*qyë+JÇYG8F?ñ}¶—+ÌDZ’ayÅbAò—Ì5wˆ%~‹³{¼»S'ã>:‰ÓÍ¡šf‡z²ã®Ï)b­ò¥ºœ%Épçh<Ì>µlJˆn-¥,AMÅÞF€¨ÉSU»,ß);ûO ¶5yŒÉUÑålðÕÌ¢*Ñ?â†µ¢ÔRwçTç¹�T GIÅ(9h{t~™Iì[œøÚ@$¦K¿OÌ,;Ã*KÇÔaÕæ}{2©´çÍ³`u~†>øH�×pY>ß³©hJ™ÑFË§{}VöC�õË*Ù ¿ÉXÆ²’Ôæ¾1êúð×!ŠÀ|ã+|µà[ßÚsZ2hƒB†]Ã`ûpÜ<=êiš‰”gÑ0”%_¼kÜí«*VkOÖO7ÊÂ–Êg¬ñ`ž³;PæŠt�8}ÿÊu£7*Ù¹iBS›ö ‘žHšb³ÁÃõY£:J®…	Î·tc?H5ÚOÖJ®…	Î·tc?H5ÚOÖr+X¨ÈúFîüŸñV´çŸì_F<ÇòâÙHÌ™5`¸¡ƒÒIÂŒÆ8àÈl Þ÷vV�ûD-K�ªŠåMÜ°X³þ²°3}’«â2ã‘-=•ÇÂP‘FãÌÐ*#©àÂ~ëT Vy# péóÌƒ [,BšYþ�Gâ“$ûY’XÓG@-%p ±èÉKà¼QP“kñ‘§™W¦ÉßÎ4�AS'>ìI4(ºñ|!è¾®Xº8D÷®eàÃ†ÍªI¤$YJ…må2{7cªìBãW+*Ø(f¶Š2
ÅöISýœÓÂMe¿Æm9ÀÈ#ó£}£½”±Ó»[¬·¼
ê ~xeÐô+ˆ:ÜÌ*õˆ`Îaå<Í[~T^zÃz›öH°†Jºu:äÉ†G­U¬E§½ÃK±#MumÇWvü›ó=œ;Ì §°Œ>vEfŠ#��ö#ÔX3¾Â9ájž÷îá—ˆà35æ£Eð@'¡‚åµ»G13=|„>Ì«:ô�0¡•RÆôó_Ì’}p=‡DàL˜ÃM‰€l5�,Ð^,b e£¿¨­\µuK²“º%Î<­Óx'vYFø‰[‹áFhüb>7u’”md]\é¸ê„Oˆe‰C.VßsXn}R-€1ãé|àÊ|�ß‚ñ„íõe¬>…8„•±o·+oeV-“Ä›Àò2ù`–øèHIóÁlqWó9Gù}
Tœ’5É¬¨IºRe`y.Vx?a¼WH
§¯7ç°‘“9†áL¾áoŸÖ c^o7vé:Ž©LêCTšà öbtáZûx•·„��”ú‘À_Ä¦¦È®ÍÂ¿âõbÛ¨9€q³»` 'öÕAÛâb-1ã:üuèdŽ:;jk«ZšÇ”çÁü<“uµœYÜþNóð<fŸbTW»ŽÿÞbt>È™a~/®Ö±ðoI‘8,PHÑ"�1™H&:kÕ:‘´°®ŸÇá¶ùEÔý1[åsþjda’MŽT²šWy
»¥çßdÅObœç—Á´z
˜ÝâN­Åü*ú8ÆÜ–…Æg@«¥zLŒ3ÙÌ·jªH!=¸ã`•–öpSv×¹.XK+—O±gÐNt€' /¥�0•P‰"Gó¨¨Qöt$àeO¼Ÿ�‹­Å¥™T½è€Ö—ÙæßÈQ r|&±Id"Yh¶ˆøáƒô\åóTŠW¯*’Df-…=EB¿:ÛdÁCÔiÊ¨6žÇˆØ.X$ykÕßmÐÿ¬*N
ÒuQòµÜ¡¾ƒF¬-qçxÓj\+Ô’oeü°+ó{‘*xPŠÖgCHÿá~
ËŠEfòÌ£‹mfØ�‹¹R÷�îÞ"1»›_4%!5©,î51XÀô¡`¸'ýYjÖxºJ˜]Õ‹áBŒÊnP" ý€ÆYßQ#ýÛnÀ{¬Â„‚„7YSâÂÁš-ëôoºÌq\�šdTÆâC4‹wè(¼2¯¶-�“�ïoz UˆbÐšÔó»M'[™�®I(t~ä	Ž¨a�5'Ú%ž€V³ƒÉ§�nŒQ­”–;L|ÉâÕë§š¨]8§ÐY‚ýÞ‰ØÜ•	T’™“•æxK~ûhXÓuM~,9dýë±ª€<Zñ„÷–¢¡ äg‹ô½ª8ðx¶8‚ÊO€6,»& ô\²éé&ˆ™FÂð³™lO˜à<©�P áôŸÂ`bSý�£ãw¦Nï'·ö0¬=ÊÝj�æo‚�µÀ>!!ªj&²ê±%”ãÖp�>ŒàBˆs8	H¤žr:@öý·ÔHQÀS�Žês.”tTš$”`^ÑôI‹ÎìœFÝøø.ZÁæ}ñ‹Â±•ežš2Weº%µÞù2V îÞˆ{Ùßc�s¨¡”Ç.ô$§j­3JîÜ—»!ÙJ®…	Î·tc?H5ÚOÖVÓÔ¬Î2Ï_<ˆHseÖQ=ùAíg‡¸ƒÜ©þ8&YG8ž®ùM>Ëƒ2>~´Jz|A­b”3©Zd� ghP6uH„ZF)óWÁ¾õ»‰/1It"½Æ¼ !XÞä¶C¸øŽ™ ¾7�º&ïÜ[vYçLo,’ûM¼Bö˜cšÝì™å5°L]¼‹¶Ì\ez¾Qá"/Wà¨›º­v@@.q+�Š‚bjÍÓ—ži.§_Óî›ÍµÇÝF¦ÜfÛ´ ÎÄÀ¹¿uö *JÕ0Óñèì+n¶,5²<•¿h´Öõy­ï€oÁ;ÁsúµøÐ¶m,(éIiZ!ÕoÀúHñØ9y2	
Y3zÃ4¥‹%“ Ñá¬®a�Êr»)2ÅÔ\ ¹'®ëOC�0<YÉÑ€ ÝÐÎ¢ãÒÍÚ�ªä\ô%(§�pt¬@ØÉå.¥9ìVÖûjAKþûÃŒ´…ÿákë{Ú¢“h ä/vä/.ç’ò$J5/D
Io¦p~Àd�}¹W½½ÃÝJŸá›"å^!ÅØÖçvŽslq¿„ÎL'#-ÿqI~è*‰Ì¿ØÍf,æ=gE½Ùb#›PŸë<Ù3B† +[?;¿!U9ÂÜÿI„ˆíŒœv‘qZJ	WŸ	0Ï<˜Â‰wòµƒ}.Ð†ÍàfêCU«…ÀFúÜìHœ4«¼F±ßQAJ«˜þt’…-ªCäøJ¡{ôhËUq;×<MU–}vÄŒØöÇ¡ 8¯ØiN“v»Zbÿ  °>¡J%yÌm	ã;Çå´èŒU»¦÷I©t�«V*º©«Ã‚"ÏôÔ=Žÿ]XÿOGúrkÙ‘‚9åAGxnP¾ßhÇ-¤�îz‰[ ŽIùH�ò§|c7Rm?ø‡5±Œ:Fkz¥ð<Š?ùÐ8|áš^õˆ"�3X5ôòçíâZ";à		›ä‚fì :¡lð”6¬mÖ	â{FxKy5¤ ¤ñ˜Û=À"§jÒ©7é KÉMâ1;1±ŒMhZDç=wÛ¨ÂìCïÚl¥TÙ ú^&O€<aõv²¢âVrùoUpatÍNÞ3Þ`@ŠúBXYWï¬ÿÍf8¨™³	ÓÚ{QÊT1ãpç©˜À×M*ÑÕó×§ÿÑ€4Ùz¨Ê¼9hÜ‡�ú*QïôÛ6a9�,¿“ÀLCÚ!KAçŽ9|é-Ôº¦àø¡ôKÛ8œ¬K»ì]ÁS`Ûº‹%†M!ÈàA=d¬éO<ÎË*,îç„Ç-h–˜°ÞÏ`0dy!øâ²‹irrYé £„üZ¬E.‘mø7¥HÓõ}4Ù3ZŽ}TÞsåîýL	�÷6Ç­B»V÷uÿ=,�rh`1-ß£;ÝÍ£#dv4‰~N&å B_ÿ:Ìn®øŽazù£(5èça‰ÊûOó¶­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

    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

        if len(vals) > 10000:
            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 = []

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())



