# -*- coding: utf-8 -*-
"""
Display data from MQTT broker on ePaper screen

@author: arofarn
"""

###########
# IMPORTS #
###########

from cameteo_conf import *
import paho.mqtt.client as mqtt
import time
import json
import netifaces, socket
import epd2in13
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

mqtt_client_id = "epaper_display"

# Colors codes
white = 255
black = 0


"""
Update ePaper Display
"""
def update_epd():
    #rotation de l'image de 90° + 180° si le paramètre epd_rotate est différent de 0
    # la translation permet de rattraper un petit décalage en cas de rotation de 90+180°
    screen = image.rotate(90 + (epd_rotate * 180), expand=True, translate=(-6*epd_rotate, 0))
    #Mis en memoire de l'image à afficher et affichage de l'image    
    epd.set_frame_memory(screen, 0, 0)
    epd.display_frame()

#############
# CALLBACKS #
#############

"""
Callback pour la connection au MQTT : souscriptions aux topics
"""
def on_connect(client, userdata, flags, rc):
    print(mqtt.connack_string(rc))
    if rc == 0:
        print("Subscribing to %s ..." % mqtt_topic)
        client.subscribe([(mqtt_topic, 0),
                          (camera_mqtt_topic + "/#", 0)]
                        )
        print("OK")
    
"""
Callback de gestion des messages arrivant au MQTT :
affichage et enregistrement en base de données
"""
def on_message(client, userdata, msg):
    top=msg.topic[len(mqtt_topic)-1:].strip()
    subtopics = top.split("/")
    
    if subtopics[0] == "AdaBME280_1":
        payload = msg.payload.decode()
        print(payload)
        val = json.loads(payload)
        
        #Test présence et cohérence de la valeur        
        try:
            val['value'] = float(val['value'] )
        except:
            print("Value error: {}".format(val['value']))
            val['value'] = float('nan')
        
        #Gestion du symbole des degrés parfois difficile pour certaines sources
        val['unit'] = val['unit'].replace('deg', '°')
        
        #Affichage des données
        coord_type = { 'AT'     : (12, 50),
                       'RH'     : (137, 50),
                       'MSLP'   : (12, 72),
                       'ALTI'   : (137, 72), 
                      }
        if val['type'] in coord_type:
            #erase former text
            draw.rectangle(coord_type[val['type']] + (coord_type[val['type']][0] + 112, coord_type[val['type']][1] + 20), fill=white)
            #draw new values            
            draw.text(coord_type[val['type']], "{:6.1f}{}  ".format(val['value'], val['unit']), font=font20_bold, fill=black)
    
"""
Callback managing date and time from MQTT broker 
"""
def on_message_date(client, userdata, msg):
    payload = msg.payload.decode()
    print("Date : " + payload)
    
    try:
        #Mise en forme de la date et heure reçu pour fuseau horaire configuré
        dt_texte = datetime.strftime(datetime.strptime(payload, "%H:%M:%S %d/%m/%Y") + TimeZone.utcoffset(None), "%d/%m/%Y %H:%M:%S")
    except:
        dt_texte = payload
    
    #Affichage du résultat
    draw.rectangle((0, 34, epd2in13.EPD_HEIGHT, 48), fill=white)    
    draw.text((0, 34), dt_texte, font=font14, fill=black)
    update_epd()

"""
Update display with info from camera (camera shooting new photo or name of the
last photo)
"""
def on_message_camera(client, userdata, msg):
    pl = msg.payload.decode()
    print("{} : {} ({})".format(msg.topic, pl, type(pl)))    
    
    # Photo en cours
    if pl == "1" and msg.topic == camera_mqtt_topic + "/shooting" :
        draw.rectangle((0, 106, epd2in13.EPD_HEIGHT, epd2in13.EPD_WIDTH), fill=white)
        draw.text((0, 106), "Shooting photo...              ", font=font14, fill=black)
        update_epd()
    
    #Dernière photo prise
    if msg.topic == camera_mqtt_topic + "/last_photo":
        draw.rectangle((0, 106, epd2in13.EPD_HEIGHT, epd2in13.EPD_WIDTH), fill=white)
        draw.text((0, 106), "Last: " + pl, font=font14, fill=black)
        update_epd()

"""
Callback de déconnexion au broker MQTT
"""
def on_disconnect(client, userdata, msg):
    if msg != 0:
        print("Déconnexion imprévu : %s" % msg)
    exit()

########
# Main #
########

#Screen init.
epd = epd2in13.EPD()
epd.init(epd.lut_full_update)

#List of TrueType fonts
font12 =        ImageFont.truetype(epd_font_file, 12)
font14 =        ImageFont.truetype(epd_font_file, 14)
font16 =        ImageFont.truetype(epd_font_file, 16)
font20 =        ImageFont.truetype(epd_font_file, 20)
font12_bold =   ImageFont.truetype(epd_bold_font_file, 12)
font14_bold =   ImageFont.truetype(epd_bold_font_file, 14)
font16_bold =   ImageFont.truetype(epd_bold_font_file, 16)
font20_bold =   ImageFont.truetype(epd_bold_font_file, 20)
#font12_obl =    ImageFont.truetype(epd_italic_font_file, 12)
#font14_obl =    ImageFont.truetype(epd_italic_font_file, 14)
#font16_obl =    ImageFont.truetype(epd_italic_font_file, 16)

#New image buffer
# Memo : 0=black, 255= white/blank
image = Image.new('1', (epd2in13.EPD_HEIGHT, epd2in13.EPD_WIDTH), 255)
draw = ImageDraw.Draw(image)

#Draw basic text and frame :
draw.rectangle((0, 0, epd2in13.EPD_HEIGHT, 18), fill=black)
draw.text((60, 1), "Projet Camétéo", font=font16_bold, fill=white)
draw.text((0, 19), "{} : IP= {}".format(socket.gethostname(), netifaces.ifaddresses('wlan0')[2][0]['addr']), font = font12, fill=black )
draw.line((0,49,epd2in13.EPD_HEIGHT, 49), fill=black)
draw.line((0,71,epd2in13.EPD_HEIGHT, 71), fill=black)
draw.line((0,93,epd2in13.EPD_HEIGHT, 93), fill=black)
draw.line((125, 49, 125, 93), fill=black)

#Display on ePaper screen
epd.clear_frame_memory(0xFF)
update_epd()

#
#screen = image.rotate(90, expand=True)
#epd.set_frame_memory(screen, 0, 0)
#epd.display_frame()

#Toggle to partial refresh
epd.init(epd.lut_partial_update)

#Connect to MQTT broker and loop...
mqtt_client = mqtt.Client(mqtt_client_id, clean_session=True)
mqtt_client.username_pw_set(mqtt_user, mqtt_pass)
mqtt_client.on_connect = on_connect
mqtt_client.on_message = on_message
mqtt_client.on_disconnect = on_disconnect

mqtt_client.message_callback_add("huzzah0/NTP/date", on_message_date)
mqtt_client.message_callback_add(camera_mqtt_topic + "/#", on_message_camera)

print(mqtt_host + ":" + str(mqtt_port))
mqtt_client.connect(mqtt_host, int(mqtt_port), 60)

mqtt_client.loop_forever()

