import network,aioespnow,asyncio,time,json,cryptolib,uselect,sys,os,ubinascii,binascii,micropython,machine,gc;from machine import Pin,WDT,freq
def naredi_geslo(length=16):random_bytes = os.urandom(length);return ubinascii.hexlify(random_bytes).decode()
#geslo = naredi_geslo();podatki = b'0123456789012345';šifra1 = cryptolib.aes(geslo,1);šifra2 = cryptolib.aes(geslo,1);kodirani_podatki = šifra1.encrypt(podatki);odkodirani_podatki = šifra2.decrypt(kodirani_podatki)
tipka=Pin(9,Pin.IN);rdeca=Pin(3,Pin.OUT, Pin.PULL_DOWN);zelena=Pin(4,Pin.OUT);modra=Pin(5,Pin.OUT)#;ESP32-S3 tipka=Pin(9,Pin.IN);modra=Pin(8,Pin.OUT, Pin.PULL_DOWN);#ESP32-C3_Mini_V1
stanje={'g':naredi_geslo(2),'i':'','a':0,'u':'','p':'','c':''}#(g)eslo,(i)me,(m)ac,(a)ktiven,(u)kaz,(p)arameter,(c)ilj
ponovi=stanje.copy();#freq(80000000)
j=[0,0,0,0,1500,0,0];s1=False;vrstniki ={};telegrami={};wdt = WDT(timeout=5000)
def stanje_zapis():f=open('/stanje.txt', 'w');f.write(str(stanje));f.close()
try:f = open('/stanje.txt', 'r');f.close();found = True
except:found = False
if found:f=open('/stanje.txt', 'r');stanje=eval(f.read(256));f.close();
else:stanje_zapis()
stanje["a"]=0;sta = network.WLAN(network.STA_IF);sta.active(True);sta.config(channel=1,protocol=sta.PROTOCOL_LR);sta.config(txpower=20);sta.disconnect()
e=aioespnow.AIOESPNow();e.active(True);e.add_peer(b'\xff\xff\xff\xff\xff\xff');e.MAX_DATA_LEN=1470
poll = uselect.poll();poll.register(sys.stdin, uselect.POLLIN);
async def oddaja(e):
    rdeca.value(True);await e.asend(b'\xff\xff\xff\xff\xff\xff', json.dumps(stanje).encode(), sync=True);rdeca.value(False);stanje["u"]='';stanje["c"]='';stanje["p"]=''
async def sprejem(e):
    global  s1,ponovi
    while True:
        async for mac, msg in e:
              j[1]+=1;modra.value(True);
              try:
                p = json.loads(msg.decode())  
              except Exception as err:
                print("Napaka 1:", repr(err))
                print("Dolzina telegrama:", len(msg))
                print("Telegram:", repr(msg))
                print("RAM alloc/free:", gc.mem_alloc(), gc.mem_free())
                print("QSTR:")
                micropython.qstr_info()
                print("ESP-NOW:", e.stats())
                raise
              vrstniki[p['i']]=mac,0;j[6]=max(len(msg),j[6]);j[5]=len(msg);j[4]=min(len(msg),j[4])
              if not p['g'] in telegrami:
                  if s1==False:j[3]+=1;s1=True;ponovi=p;
                  if p['u']=='i' and p['c']==stanje['i']:print(p['p'])
              telegrami[p['g']]=3;wdt.feed();modra.value(False)
async def sekunda(e):
    global s1,ponovi
    while True:
        for x in vrstniki.items():
            y=vrstniki[x[0]];z=y[1]+1;vrstniki[x[0]]=y[0],z
            if z>3:del(vrstniki[x[0]])
        for x in telegrami.items():
            z=telegrami[x[0]];z=z-1;telegrami[x[0]]=z
            if z<1 :del(telegrami[x[0]])
        j[0]=j[1];j[1]=0;j[2]=j[3];j[3]=0#0 vsi sprejeti na sekundo; 2 prvič sprejeti na sekundo    
        if s1==False:await oddaja(e)
        stanje["a"]+=1;stanje["g"]=naredi_geslo(2)
        for x in range(0,49,1):
            if s1==True:await e.asend(b'\xff\xff\xff\xff\xff\xff', json.dumps(ponovi).encode(), sync=True);s1=False
            await asyncio.sleep_ms(20)
async def vhod(e):
    vrstica = ""
    while True:
        try:
            if poll.poll(0):
                znak = sys.stdin.read(1)
                if znak in ("\r", "\n"):
                    if vrstica:x = vrstica.split();izpis(x);vrstica = ""
                elif znak:
                    if len(vrstica) < 200:vrstica += znak     
        except OSError as err:
            print("Napaka:", err)
        await asyncio.sleep_ms(1)
def izpis(x):
        if   len(x)==1 :#ukaz
           if   x[0]=='s':print(stanje)
           elif x[0]=='v':print(vrstniki)
           elif x[0]=='p':izpis_navodila()
           elif x[0]=='m':print(e.peers_table)
           elif x[0]=='t':print(telegrami)
        elif len(x)==2 :#ukaz in parameter
           if   x[0]=='ime':stanje['i']=x[1][:8];stanje_zapis();print('stanje  =',stanje)   
           elif x[0]=='i':print(x[1],' ')
        elif len(x)==3 :#ime,ukaz,parameter
           if x[1]=='i':
             for k,l in vrstniki.items():
                if k==x[0]:stanje["g"]=naredi_geslo();stanje["c"]=k;stanje["u"]='i';stanje["p"]=x[2];oddaja(e)
def izpis_navodila():
    print('UKAZ\t\tvrstnik',stanje["i"]);
    print('(s)tanje\tslovar stanje\t\t Deluje ',stanje["a"],'s');i=0;
    for l,y in vrstniki.items():i=i+1
    print('(v)rstniki\tslovar vrstniki\t\t Število',i);i=0;
    for l,y in telegrami.items():i=i+1
    print('(t)elegrami\tslovar telegrami\t Število',i);i=0;
    for l,y in e.peers_table.items():i=i+1
    print('(m)maci\t\tslovar maci\t\t Število',i);
    print('(p)omoč\t\tpomoč uporabniku\t Vsi sprejeti',j[0],'/ s');
    print('(i)zpis "tekst"\tizpiše "tekst"\t\t Prvič sprejeti ',j[2],'/ s');
    print('ime "ime"\tnastavi ime vrstnika');
    print('Ctrl-c\t\tkonec programa\t\t')
    print('Sprejem\t\tmin,zadnji,max - stat\t',j[4:7], e.stats());
    gc.collect()
    print("\n--- DIAGNOSTIKA RAM ---")
    print("GC:", gc.mem_alloc(), "/", gc.mem_free())
    print("QSTR:")
    micropython.qstr_info()
    print("Kopica:")
    micropython.mem_info()
    print("Slovarji:", len(vrstniki), len(telegrami))
    print("ESP-NOW:", e.stats())
    micropython.mem_info()
    micropython.qstr_info()
    print(os.uname())
izpis_navodila()
async def main(e):await asyncio.gather(sprejem(e), sekunda(e),vhod(e))
try:asyncio.run(main(e))
except KeyboardInterrupt:e.active(False);sta.active(False)