import serial
import time
import numpy as np
import cv2
import math
from threading import Thread
from datetime import datetime

# 獲取溫度影像
cmd_get_image = [0XEE,0xE1,0x01,0x55,0xFF,0xFC,0xFD,0xFF]
# 設定發射率
cmd_set_emissivity = [0XEE,0xB2,0x55,0xAA,None,0xFF,0xFC,0xFD,0xFF]
# 獲取發射率
cmd_get_emissivity = [0xEE,0xB5,0xFF,0xFC,0XFD,0xFF]
# 設置偏移
cmd_set_offset = [0xEE,0xB7,0x55,0xAA,None,0XFF,0xFC,0xFD,0xFF]

class Thermal(object):
    def __init__(self, width = 80, height = 62, framerate = 4, frame_width = 80*5, frame_height = 62*5, log=None, port="/dev/ttyUSB0"):
        self.__log = self.__log if log is None else log
        self.__isCaptured = False
        self.__frame = None
        self.__frame2c = None
        self.isOpened = False
        self.isStopping = False
        self.isNotSleeping=True
        # comport 定義
        self.ser = serial.Serial()
        self.ser.port = port
        #921600,N,8,1
        self.ser.baudrate = 921600
        self.ser.bytesize = serial.EIGHTBITS #number of bits per bytes
        self.ser.parity = serial.PARITY_NONE #set parity check
        self.ser.stopbits = serial.STOPBITS_ONE #number of stop bits
        self.ser.timeout = 0.5          #non-block read 0.5s
        self.ser.writeTimeout = 0.5     #timeout for write 0.5s
        self.ser.xonxoff = False    #disable software flow control
        self.ser.rtscts = False     #disable hardware (RTS/CTS) flow control
        self.ser.dsrdtr = False     #disable hardware (DSR/DTR) flow control
        
        self.width = width
        self.height = height
        self.frame_width = frame_width
        self.frame_height = frame_height
        self.framerate = framerate
        self.__thread = Thread(target=self.__job)
    def start(self):
        self.__isCaptured = False
        self.__frame = None
        self.__frame2c = None
        self.isOpened = True
        self.isStopping = False
        self.__thread.start()
    def restart(self):
        self.__isCaptured = False
        self.__frame = None
        self.__frame2c = None
        self.isOpened = True
        self.isStopping = False
        del self.__thread
        self.__thread = Thread(target=self.__job)
        self.__thread.start()
    def stop(self):
        self.__isCaptured = False
        self.__frame = None
        self.__frame2c = None
        self.isStopping = True
        self.ser.close()
    def capture(self):
        return self.__isCaptured, self.__frame, self.__frame2c
    def __job(self):
        self.__log("Opened: {0}, Stopping: {1}".format(
            self.isOpened,
            self.isStopping,
        ))
        
        self.ser.open()
        self.ser.flushInput() # flush input buffer
        self.ser.flushOutput() # flush output buffer
        
        while self.isOpened and not self.isStopping and self.ser.isOpen():
            #write 8 byte data
            self.ser.write(cmd_get_image)
            #read 8 byte data
            response = self.ser.read(9927)
            a = self.bytes2temps(response)
            if(a is None):
                continue
            b = a.copy()                # 原始資料
            c = b.copy()
            self.__frame = cv2.resize(self.temp2image(b),(self.frame_width,self.frame_height), interpolation=cv2.INTER_AREA)
            self.__frame2c = self.temp_reshape(c)
            self.__isCaptured = True
            #time.sleep(0.15)
        self.__log("thermal stop")
        self.__frame = None
        self.__frame2c = None
        self.__isCaptured = False
        self.ser.close()
    def __log(self, message):
        print(message)
    def bytes2temps(self,bdata):
        data = list(bdata)
        temperatures = np.zeros(80*62)
        if(len(data) == 9927 and data[0] == 0xE1):
            for i in range(4960):
                htemp = data[i*2 + 1]
                ltemp = data[i*2 + 2]
                temperatures[i] = ((htemp*256 + ltemp) - 2731)/10
            return temperatures
        else:
            return None
    def temp_reshape(self,temperatures,height=62,width=80):
        reshaped_temp = np.zeros((height,width))
        for i in range(height):
            for j in range(width):
                reshaped_temp[i][j] = temperatures[width*i + j]
        return reshaped_temp
                
    def temp2image(self,temperatures,width = 80,height = 62,scale = 1):
        output = temperatures
        # scaling
        minValue = output.min()
        maxValue = output.max()
        output = output - minValue
        output = output * 255/ (maxValue - minValue) # Now scaled to 0 - 255

        img = np.zeros((height,width,1))
        for i in range(height):
            for j in range(width):
                img[i][j] = output[width*i + j]

        # apply colormap
        #dim = (width*scale, height*scale)
        img = img.astype(np.uint8)
        #img = cv2.resize(img, dim, interpolation = cv2.INTER_LINEAR )
        img = cv2.applyColorMap(img, cv2.COLORMAP_JET)
        return img
