# loRa_to_flash.py
# getestet am 10.07.2024 

# Eine LoRa-Nachricht wird als "Message" im Flash gespeichert. 

# Eine Message besteht aus drei Items, getrennt durch einen Delimiter
# 1. Absender (Adresse)
# 2. Text
# 3. Zeit-Datums-Stempel

# Aus empfangenen Strings (z. B. '+RCV=16,11,HALLO WELT,-14,11CRLF') die Adresse und den Payload
# nacheinander in der Form '10/HALLO WELT' zeilenweise in einer Message-Datei speichern; dabei ist / der hier gewählte Delimiter.

# für später:
# Aus der Message-Datei die einzelnen Zeilen lesen und diese als Liste mit den Elementen [Adresse, Payload, Zeit-Datums-Stempel] 

#################################### Importe und Instanziierungen ####################################

from time import sleep     
from machine import UART, SPI, Pin, RTC
import vga1_bold_16x32 as font2
import vga1_8x8 as font1
import st7789
import sys
from lora import send_command, read_response, response_to_list, lora_init, send_message

# Display:
spi = SPI(1, baudrate = 20_000_000, polarity = 1, sck = Pin(18), mosi = Pin(19))
display = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3)
display.init()
display.fill(0) # Display löschen

# UART:
uart1 = UART(1, baudrate = 57600, tx = 12, rx = 13)

# RTC
rtc = RTC()

############################# Einstellungen ######################################

delimiter = '/' # ggf. anderes Zeichen
data_fname = 'lorawan_data.txt'


############################# Funktionen #########################################

def received_to_list(s, rtc): # s ist vom Typ ByteString
    s = str(s, 'UTF-8')
    s = s[5:len(s)]
    print('s =', s)
    liste = s.split(',',2)
    print(liste)
    Addr = liste[0]
    Payload_length = int(liste[1])
    # print('PL_Länge: ', Payload_length)
    Payload = liste[2][0:Payload_length]
    d_t_tuple=rtc.datetime() # now() git es nicht!
    # print(d_t_tuple)
    Date_time_stamp = str(d_t_tuple[2])+'.'+str(d_t_tuple[1])+'.'+str(d_t_tuple[0])+' '+str(d_t_tuple[4])+':'+str(d_t_tuple[5])+':'+str(d_t_tuple[6])
    # print(Date_time_stamp)
    # print(Addr, Payload, Date_time_stamp)
    return [Addr, Payload, Date_time_stamp]

def save(fname, liste, delimiter): # auf ESP32 als Zeile (mit \n abgeschlossen) speichern:
    f = open(fname, 'a') # append mode
    f.write(liste[0] + delimiter)
    f.write(liste[1] + delimiter)
    f.write(liste[2])
    f.write('\n') 
    f.close()
    
def confirm(addr, d_t_stamp, display, uart): # addr und d_t_stamp sind Zeichenketten!
    display.text(font2, 'Bestaetigung:', 5, 45)
    display.text(font2, 'MSG von ' + addr + '     ', 5, 75) # ggf. Teil von vorheriger Adresse überschreiben
    display.text(font1, d_t_stamp+'      ', 5, 115) # ggf. Teil von vorheriger Adresse überschreiben
    msg = 'MSG confirmed'
    send_message(uart, int(addr), msg)
    print(read_response(uart1)) # Das ist die Antwort b'+OK\r\n'. Wichtig: Damit wird auch der Lese-Puffer gelöscht!

def receive_save_confirm(uart, display, rtc): # empfängt Daten voneinem LoRa-Modul, speichert die Message (s. o.) im Flash ab und bestätigt den Empfang
    s = read_response(uart) # ByteString
    item = received_to_list(s, rtc)
    print('item=', item)
    save(data_fname, item, delimiter)
    confirm(item[0], item[2], display, uart)  # Adresse u. Datum  

#######################################################################################
#                                                                                     #
#                                 Hauptprogramm                                       #
#                                                                                     #
#######################################################################################

# LoRa initialisieren...
lora_address = lora_init(uart1)
display.text(font2, 'LORA-ADR: ' + lora_address, 5, 10)
if lora_address == '???':
    display.text(font2, 'Resetten!', 5, 80, st7789.RED)
    print('Keine Verbindung zum LORA-Modul!')
    print('RESET-Knopf am TTGO betätigen!')
    sys.exit() # Programm beenden, wenn keine Antwort vom LoRa-Modul

while True:
    receive_save_confirm(uart1, display, rtc) # empfangen, speichern und bestätigen
    print()
   







