��IkÂû91Ld­ìÉˆòè˜v�ºÄ?™<Š¢yi�!‰Í�Ì|×Ã•bsÛ»YXR´…«NÀÎÔü#¥o�Øë_w>¬Púd~ö�sÇ¿6‹Ü¼P4!q 'îÏ±k#­JvGE“;B�ÐWg:˜NÓhÅÕ*T®ä¯DèÄlyÇæŽd�‡óËùÂXÚ)¡F¬³'¤Ê›
)|Á¤7¾ò)";äxµWš\ÁÖÇþ˜8›�ÁXvúi¸L¹I¦ê
Üp²YŒíå<²Ù¯™
=;‘‹µõY2`×¹$û7à ¤<µœÔrƒ)õø³Æ@7‘†¤NãFnò)¼|YõL˜ƒûB¤¡Qa‘/úù˜RÿzÝŠÏ’ûÂ$ŽUçráû£t PiA¨À%¦T’…\"F/‡:ó‹êjßÑÂï Rß¨ú¥4!ßÞ¤âºäW(:KÖi¡m
Äûq´¡ ?dqº~S€î�NH³ÒÄ&âm•¯í�ÉT?\#=h_úÞ‡Ýkÿ¡íûÂ$ŽUçráû£t PiA¨À%¦T’…\"F/‡:ó‹êjßÑÂï Rß¨ú¥4!ßÞ¤âºäW(:KÖi¡m
Äûq´¡ ?dqº~S€}û˜³û0,îßÂÕ¹H>S¦vgrÒ¦Æ­’{!k„p½Äà{Ú­B»ZŸ„ìÈÈ‘´"6Î‡/íà±1ŠäÑ`>…æ:%w&®¸µ”š…¯rþ°¤ ‰2½8æüvŠ…Ò€Ò~ÃÝ‘gŸ+’Åyíê˜¯8 ÐW^‚diƒ¼DÂ×B«	U�cì±º*—<ÜÑ¯õùiú#ßKy<qÁ•K‘Ñ#îs…¤s±˜
‰;>´br-µ[‹@ Õ ‹*®È0L�±`lÇ^:ðäE›GÙöT¶úÖUeºUcå‹þî»Õâ÷ý¶¼>è†À�˜	"T¼lÈ†„°c¹yÌ®H¬�è¦+ràÆÕW£sÏxéâ@¬¬WÔê¡éªÔ*n÷±âzàh^Ë®½N-Þ!ëžSÌ×÷¿
µÂÔ, ‡úzd!T¿®/;�@sõF0ZÆÂKÝB–ñ×£«[/ÒƒÙ�*z‚»unQiB¶á4ÞÀ@#Œ’®}e…z�Q]„u}8*‹¿ômº9êúvè1£ðÍË´Ÿ5¶Èr«aZ•d"ê©ÌPY´¥·ãjÜ:º«d(2Ì9¶rn9°8�9H6N²í x®»FßÁdu©ô«ýBÿòõ‡‰m÷’¾‚/ÐQ ~jÈÒM˜ä£¬qð†¥Ô‘* S „:ëEÃ§‘,%/ß†˜ÏúDÆÉ"i§~î"ÐF0#·¤PåAó>hKLeñç½K=ôUMð­G†UžÄžÆ�kZíBÊ~X}ZM!½cu—g¨vÊ½’; ¼»ZÅgà‚1¿d€d×ÑjÊú°[¿;dT‚&Tÿ[ABŒ—ð.sð7EˆÀõŒªêÒ ÃaMß�–öÖOú�{‘>Ê8|DL@þ†}Ê§,Ï´J4¶Õ”ÊÿòfÌ
]*×i‡UAžEW7{Èbéí9”éÁ•ÿé×§_C¦³Õ1ÑïÓê$Dnm¶¹šzž¶›²’±¨L íNÉ&•V£lÔý›ª¹±º•Ydî³½¼Ô:Ý‚nKÝ§åS¸7ÉížÅ 0=&¾+Ëd9bÕGœn6ñDzÆ œoÜ·a¨fõ!ï® '½Ö3›èB7!wq	§¡ÓÞ�jMT@*EäpJåÑYˆ8…ÔÏsE€øÇÃÇÕÐT¬Gó³¦/eksÎî`ÐûLó—§´âìôÝðïô†À3˜YÐº�Ó²_]üy$¡DxŽô ±ý=™æ0{.îØ‚UËýÝw C´’‰âË’üQ }Fg+¥Û¶õs¢òQ¤ücnã–L°¼š mƒÉÊT —ÒÁ·’…C×dÔ:Ý‚nKÝ§åS¸7Éížåz„ý-kngImÙâYÑ+ó¥Êr“>5E�a<n)ÙŠžz}|êµ¸øSz“+›oûŽ'ßÞ8¡xà†L³šj"LÒÙ“ìÞmAÎýqä¥[k!p¿Q;ÿ�LCBÐo
éó:ºv*³”ê>ã¶SZÙŠžz}|êµ¸øSz“+&y"‹>«€SÂüX"›�Ù½!óo‹Óù÷ÅÓOºlMpãÎýDrèUTí±5	K”O¢hžs8Gëº@äÊ»Ó"'Oµ�8MÄ¸žëe&å7T³Oâ€P
®tâoã¥º�ön¡fùñ•àF¨´úöýÓíŒó^ ¾�­ˆ¦å“›»¡GÕK†e`îExî§$(cï{±…×Ää»Úöë×¤”9Ÿ:»æQ(Y}É:²ùU5³¤b\d	7”æ¼,~K˜�‰´¦¦MDG8Á�{C.0þ>#ê]af–Dqmwœò²|›Àµ ^TG�›J;ÆîPëX9êdåX¦±«<Ü×{l–…k5¤á�C43Q�_ó©®»¦t×0è´µ¿÷Ô°º9|oš,±*ÝcF&™þh†6ŠS­u®Ÿ±½G*|”ùÙãXý×käÔîý�É!±›Ž<�Ò¬"+·T;d7k6œXo%·Íík~®Éñ_ÚˆaÂX÷ÚžË¬87ko­±ï`;ÁÛML§ík¾Ý­—8³ðÑ]A¿NÝ8 îøÖrœE‘_FõÔ’Væ«=RÂnoD$Œ)±ûó¨Ì™B=(7ö¤Å2Uÿ—}~qHƒž%öê¸äöÏ
ïœh.YOÚýieàØÈoƒ†QÀ0/sä‰WµÖº,ÞØþâVB¼ã€W¶;{×©–˜nâïI8áQt½YOYGãÔp2Û5À{Q€,;ÕAý]:ÚëœâJ€0¤è>Yú”#˜˜i“’3^÷pž9Ð:}6ì ¦*ãÊîh�šÏÛáßW‚Èœp¥pÖf;‚ ß¯uaÖn#¬ÑÁÔ!ˆØ�X.ì ùG–‡Ó’Q	bžj£™2Ó•Yä¬Ì;›@’�À¹Ýe¬RqÏôq»g±,€þîéµÔ<¼ÐI~|€í³ôcñ‰�¹'b�ŸW¹ù­[Î‰:ÉkºcÎ/ºpEíÏX2Ás`Š¢ÚÂ‘ö,�)öã<ZR{³Mª•gwá¾¨æÜHõµRSûrrYé £„üZ¬E.‘mà“¤¿5ØC* %8iU3xbÙ
œ‰Êö¬á#eÀ>CM¾¤AÙ­e`p[ý³)*Ê”Ì�÷ß�³¤
2~®áæxœ"Œ*ëN6ë*Æž:pÉå�ë‰ÞX»Äç®ƒ}Ü$'gYbÄcŸÿ‡zMêãµDëú)WŠŸÄk\?NÂ•<ß¯‰ YÛç¹†ï™º“£‡ÃmÍë´*™äÓUq«ûyÓt„â ¿Ù‘~Ê§; q+‚®!2A}¹±á]Ë ÷¥Q³†^É)ÃµDvAsts`?�ý?/~xf½K D½¶öÏ°Ù#Ãó5ªAmÒ�ºÖÆƒ‰Éí{Ãh¦‹Ó�•%†ðixã‚¹]ócþšX:x)í äbÈ12ˆ84³ÏüS¥/˜ñ'æõZ·Þ[£lý\�Ø„Ÿ¬ÊJ®…	Î·tc?H5ÚOÖJ®…	Î·tc?H5ÚOÖøKFG‡Âo+Kj+ã–3¹²?$“ïÄ^$°ß<e†-=_ß­BÔ%ÍÊ¼äuKÞ(Ymãb×GÝY)óJ´s€Æ„÷ö¶Û­%‰ëòX7ÁÃ…Í]£?îž¬5 *T¤þùÃsRÔ)ÝË9øˆï–q°ÇÂÌì§C úOÇ:õv|#”ˆ7€W*…°Ô¢?4º0zn¸ñ1<Ù«5¿ƒMè»Í
%@¡{CQÏÈ%zÏ0Yú…U=_lBŒSÜ0ÆêY€òµJ �
’¢`‘wÖ@CL4Uè=OEóÍØ_p� ðÀéŒsgO?\š*ÝÌ¼qjj¡£:kÍà_ƒNc‚{†äj–`¾hà7Î™Ê©Åˆk€+ÿë*»žÆ Ì´e*;s˜sØ…Që¢#p¹?E¼7$f"Ÿ¬ïä>lÁ¬lë™ÉPñd^a–;³¶—jDÄŸ×ØA•ô�B~ðä#ßÄjlBú˜›-å±«ó/!ž1‚ Zô	�8˜jbZó;�†~bQžIÝØnÖNÁc¯2Dsv	¥k	Þ“–”÷ÎQ¥Ëkn·†ïZ<U1˜ì+Ìºxm>?Þi/ï�à2þ¾ºX^{¨Nël�\†pðÛ¦Š ×1|‹Ë6_@¸2òŒÀ‚/9µ¤Ë÷èqn~Îs¨sßZ	Ùµbî5õ�ãšk·tTñ*VôO®d„¢½�H×o÷ú.—•{]FøêY–	b¡Bºz^ÌÂ¡¯lí–I¤ûñ4t}èÊ!zÚ½¶Œ˜Nc—ž]‡›�ïN0s÷‘Žûñ}ÿn»à#ad‰�óî¹VÂ˜~àu€§çÎîÄªw‡æ%ê¾….˜?áû¼‡*Fx¢SØ®d_cÛihÍæëS¿æâ8$ÛÄ¦{7><n?–qÍ‚ôþÛN²qºŒrk}ÝÕÐkR`×®R™#±€Q§–ã	øîTægI�$OŸh½³�Ío{3bk`ßÌ­”/ÔÜØËGî'6/ÿxô—ÌÕ&™•�1ó}dÔò0VNðø®„Hs÷eIJ³ôízmÇ²˜©RâÎ Ñ°ç‘}­`1Ëì×Ó‚,­'†`#D~«
Ä²Téo$„m”�~×xžÈƒß&‚:œTbÎhjÊ¸_˜AÕÖøü|§=¹ öj¾‚O’Iôíá¡v¡]cu†M÷-h3”õcëTë«³„Ÿ½±­;ã‚˜™PFùÞ½–ÿRýv!2Á�’�xHCãÌAÁ¨0“wl@Þ¦ü@<ë|n/ÌiZ�ë» �ö�ý‘u‘À�þ¤â�Su)É8}¡(ë]kFù�ìëæèÙºÂËBy|$m³ý“)1Ö±e@©û‰xï&.’iM]jÑÄo›œ¤,ï¥mó¯j<?¿Í=²[7²yü ›øéKm“ƒÝ�,€Yª·èn÷§(Dl3Wj~ÞÈ¹lTK†`îŸ¿¾�þ‚¡4œ…V:§ký$€§½ ÅqØ5m&Œ¡®ºÛIc+Ú3KYÓzG¤¨Æ¦á<:Â|¤öÓñˆ¢Øðß˜£\p²Y8ñ¥+[ˆ•Ù0m›æ½åAoþaš‰	`Ù¶ås‡ùâf›Cçt7d¯9=^hO2Î¯Nceä…¯€ßü({¾O~(\q%?C)L”¬Çé7>}lâ‚¯ªuW5iý`±Jô– data_step

        res = dat

    elif func == 'get_info_single_sensor':
        pass
        # res = sensor_info

    elif func == 'get_data_all_sensors':
        t1 = p['start_time']
        t2 = p['end_time']
        data_cnt = p['data_cnt']
        val_selection = p['val_selection']
     
        dat = {}
        print('     ' + str(t1) + ', ' + str(t1) + ' - ' + str(data_cnt))
        
        for s_pid in sensor_info.keys():
            
            if 'start_time_ts' in sensor_info[s_pid].keys():

                data_idx = t1 - sensor_info[s_pid]['start_time_ts']
                data_step = (t2 - t1) / data_cnt
                dat_single = []
                
                for i in range(0, data_cnt):

                    # val = sensor_data[s_pid][int(data_idx)] if data_idx >= 0 and data_idx < len(sensor_data[s_pid]) else 0
                    if data_idx >= 0 and data_idx < len(sensor_data[s_pid]):
                      
                        #const valSelectionEnum = Object.freeze({"first": 0, "min": 1, "max": 2, "avg": 3});
                        val = sensor_data[s_pid][int(data_idx)] 

                        if val_selection == 1:
                            for j in range(int(data_idx), int(data_idx + data_step), 1):
                                v = sensor_data[s_pid][j] 
                                if val > v:
                                    val = v
                        elif val_selection == 2:
                            for j in range(int(data_idx), int(data_idx + data_step), 1):
                                v = sensor_data[s_pid][j] 
                                if val < v:
                                    val = v
                        elif val_selection == 3:
                            v_sum = 0
                            for j in range(int(data_idx), int(data_idx + data_step), 1):
                                v_sum += sensor_data[s_pid][j]
                            val = v_sum / int(data_step)
                    else:
                        val = 0

                    data_idx += data_step
                    dat_single.append(val)

                dat[s_pid] = dat_single

        res = dat
        
    elif func == 'get_info_all_sensors':
        res = sensor_info

    if res != None:
        writer.write((json.dumps({'res': res}) + "\n").encode('utf8'))
        await writer.drain()
        writer.close()


async def run_server():
    server = await asyncio.start_server(handle_client, HOST, PORT_DATA)
    async with server:
        await server.serve_forever()


async def update_data():
    global conn
    global sensor_info
    global sensor_data
    
    while True:
        print('> Updating data ...')

        for s_pid in sensor_info.keys():
            with conn.cursor() as cur:
                if 'end_time' in sensor_info[s_pid].keys():
                    last_val_time = sensor_info[s_pid]['end_time_ts']
                    last_val_pid = sensor_info[s_pid]['max_pid']

                    q = f'SELECT pid, val_time, val FROM data.sensor_data WHERE sensor = {s_pid} AND pid >= "{last_val_pid}" ORDER BY pid ASC LIMIT 10000'
                    # print(f'    {q}')
                
                    t1 = time.time()
                    cur.execute(q)
                    s_data = cur.fetchall()
                    t2 = time.time()

                    dl = s_data[len(s_data) - 1]
                    sensor_info[s_pid]['max_pid'] = dl[0]
                    sensor_info[s_pid]['end_time'] = str(dl[1])
                    sensor_info[s_pid]['end_time_ts'] = int(dl[1].timestamp())

                    di = 0
                    dtc = last_val_time + 1

                    for i in range(0, sensor_info[s_pid]['end_time_ts'] - last_val_time):
                        while i + last_val_time >= dtc:
                            di += 1
                            dtc = s_data[di][1].timestamp()
                        
                        sensor_data[s_pid].append(s_data[di][2])
        
                    print(f'  > {s_pid} : {int((t2 - t1) * 1000)} ms : {len(s_data)}')

        await asyncio.sleep(60)



# asyncio.run(run_server())
## asyncio.run(update_data())

loop = asyncio.get_event_loop()

loop.run_until_complete(asyncio.gather(
    run_server(),
    update_data()
))

print('> Exiting ...')

