#!/usr/local/bin/python
# -*- coding: utf-8 -*-
"""
Created on Sep 17, 2020

@author: Carima
"""
# from _socket import htonl
import serial
import logging
import binascii
from serial import serialutil
import os
from time import sleep
# import datetime
from xmlrpc import client


class serial_rw():
    """    derived board control class
    """
    def __init__(self, port, ser_newline='\r', spy=False):
        # self.logger = logging.getLogger('dp110server')
        # self.proxy = client.ServerProxy("http://127.0.0.1:8080")
        try:
            # ports = '/dev/ttyUSB%d' % port
            self.ser = serial.Serial('/dev/ttyUSB0', baudrate=9600)
        except:
            # return -1
            try:
                # ports = '/dev/ttyUSB%d' % port
                self.ser = serial.Serial('/dev/ttyUSB1',  baudrate=9600)
            except:
                # return -1
                try:
                    # ports = '/dev/ttyUSB%d' % port
                    self.ser = serial.Serial('/dev/ttyUSB2', baudrate=9600)
                except:
                    return -1
    
    def get_serial_port(self):
        return "/dev/"+os.popen("dmesg | egrep ttyACM | cut -f3 -d: | tail -n1").read().strip()
    
    def openSerialPort(self):
        try:
            if not self.ser.isOpen():
                self.ser.open()
            return self.ser.isOpen()
        except:
            return -1
        # except serial.SerialException, e:
        #     self.logger.error("Could not open serial port %s: %s\n" % (self.port, e))
        #     return False
             
    def closeSerialPort(self):
        try:
            if self.ser.isOpen():
                self.ser.close()
            return True
        except serial.SerialException as e:
            self.logger.error("Could not open serial port %s: %s\n" % (self.ser.portstr, e))
            return False

    def connect_PCBCom(self):
        return self.ser.open()

    def HexStrToByteArray(self, data, size=6):
        bstr = bytearray.fromhex(data)
        # if len(bstr) != size:
        #     return False
        return bstr

    def ByteArrayToHexStr(self, byte):
        return binascii.hexlify(byte)

    def readData(self, msecs=30000):
        self.ser.flush()
        sleep(0.2)
        ret = self.ser.readline()
        self.ser.flushOutput()
        return ret

    def writeData(self, data, msecs):
        self.ser.write(data)

    def readSignal(self, shex, msecs):
        # if len(self.HexStrToByteArray(shex, 4)) != 4:
        #     return None
        try:
            self.writeData(shex.encode(), msecs)
            s = self.readData(msecs)
            return s
        except:
            self.ser.flushOutput()
            self.proxy.ui_errorPython(True)
            self.logger.error("sendSignal exception:%d" % self.s)
            return None

    def sendCommand(self, shex, msecs):
        ret = self.readSignal(shex, msecs)
        if ret != None:
            return ret
        else:
            ret = self.readSignal(shex, msecs)
            return ret

    def convertMoveValue(self, value):  # 0.0003125
        # lvalue = value / 0.000390625  # 리드 5mm값
        # mm_per_step = 2.0 / 200 / 94 = 0.0025 (lead_screw_pitch: 2.0 mm/rot, motor: 200 steps / (1/4 microsteps) / rot)
        lvalue = value / 0.00015625
        lvalues = round(lvalue, 1)
        llvalues = int(lvalues)
        hexdata = '{:06X}'.format(llvalues)
        print("distance hexdata", hexdata)
        return hexdata
    
    def convertMoveValue_DM250K(self, value):
        lvalue = value / 0.00015625
        lvalues = round(lvalue, 1)
        llvalues = int(lvalues)
        hexdata = '{:06X}'.format(llvalues)
        return hexdata

    def convertMoveValue_tilt(self, value):  # 0.0003125
        lvalue = value / 0.0005625
        lvalues = round(lvalue, 1)
        llvalues = int(lvalues)
        hexdata = '{:06X}'.format(llvalues)
        return hexdata
    
    def convertValue(self, value):
        # mm_per_step = 2.0 / 200 / 4 = 0.0025 (lead_screw_pitch: 2.0 mm/rot, motor: 200 steps / (1/4 microsteps) / rot)
        # lvalue = value / 0.00015625
        # lvalues = round(lvalue, 1)
        llvalues = int(value)
        hexdata = '{:05X}'.format(llvalues)
        print("speed hexdata", hexdata)
        return hexdata

    def convertValue_pid(self, value):
        # mm_per_step = 2.0 / 200 / 4 = 0.0025 (lead_screw_pitch: 2.0 mm/rot, motor: 200 steps / (1/4 microsteps) / rot)
        # lvalue = value / 0.00015625
        # lvalues = round(lvalue, 1)
        llvalues = int(value)
        # nethex = htonl(llvalues)
        hexdata = '{:04X}'.format(llvalues)
        return hexdata

    def z_AbsoluteMove(self, value, msecs, check):
        if check == 0:
            sdata = "7E01%s0" % self.convertMoveValue(value)
        elif check == 1:
            sdata = "7E01%s1" % self.convertMoveValue(value)
        elif check == 2:
            sdata = "7E01%s2" % self.convertMoveValue(value)
        return self.sendCommand(sdata, msecs)

    def z_AbsoluteMove_DM250K(self, value, msecs, check):
        if check == 0:
            sdata = "7E01%s0B" % self.convertMoveValue_DM250K(value)
        elif check == 1:
            sdata = "7E01%s1B" % self.convertMoveValue_DM250K(value)
        elif check == 2:
            sdata = "7E01%s2B" % self.convertMoveValue_DM250K(value)
        return self.sendCommand(sdata, msecs)

    def z_AbsoluteMove1(self, value, msecs, check):
        if check == 1:
            sdata = "7E10%s1" % self.convertMoveValue(value)
        else:
            sdata = "7E10%s0" % self.convertMoveValue(value)
        return self.sendCommand(sdata, msecs)

    # add for dm250 tilt
    def z_AbsoluteMove_up_tilt(self, value, msecs, check):
        if check == 0:
            sdata = "7E32%s0" % self.convertMoveValue_tilt(value)
        elif check == 1:
            sdata = "7E32%s1" % self.convertMoveValue_tilt(value)
        return self.sendCommand(sdata, msecs)

    def z_AbsoluteMove_down_tilt(self, value, msecs, check):
        if check == 0:
            sdata = "7E33%s0" % self.convertMoveValue_tilt(value)
        elif check == 1:
            sdata = "7E33%s1" % self.convertMoveValue_tilt(value)
        return self.sendCommand(sdata, msecs)

    def z_home(self, msecs=50000):
        return self.sendCommand("7E03", msecs)

    def z_home_DM250K(self, msecs=50000):
        return self.sendCommand("7E0300000000B".encode(), msecs)

    def tilt_home_DM250K(self, msecs=50000):
        return self.sendCommand("7E34", msecs)
    
    def motorPositions_DM250K(self, msecs):
        postionValue = int(self.sendCommand("7E020000000B", msecs))
        realValue = postionValue * 0.00015625
        return realValue
    
    def motorPositions(self, msecs):
        postionValue = int(self.sendCommand("7E02", msecs))
        realValue = postionValue * 0.00015625
        return realValue

    def downBoardStop(self, msecs):
        return self.sendCommand("7E04", msecs)

    def upBoardStop(self, msecs):
        return self.sendCommand("7E05", msecs)

    def checkTmpSensor(self, msecs):
        return self.sendCommand("7E06", msecs)

    def initMotorpostion(self, msecs):
        return self.sendCommand("7E07", msecs)

    def InsideLED_fanON(self, msecs):
        return self.sendCommand("7E0A", msecs)

    def InsideLED_fanOFF(self, msecs):
        return self.sendCommand("7E0B", msecs)

    def Shutdown_allLED_fan(self, msecs):
        return self.sendCommand("7E0C", msecs)

    def ShutdownBuzzer(self, msecs):
        return self.sendCommand("7E0E", msecs)

    def EndPrintBuzzer(self, msecs):
        return self.sendCommand("7E0F", msecs)

    def lasersensor(self, msecs):
        return self.sendCommand("7E31", msecs)

    def lowCurrent(self, msecs):
        return self.sendCommand("7E210000000B", msecs)

    def HighCurrent(self, msecs):
        return self.sendCommand("7E220000000B", msecs)
    
    # def PumpOn(self, msecs):
    #     return self.sendCommand("7E32", msecs)
    #
    # def PumpOff(self, msecs):
    #     return self.sendCommand("7E33", msecs)

    def tiltmotorUp(self):
        return self.sendCommand("7E35", 1000)

    # def tiltmotorDown(self):
    #     return self.sendCommand("7E34", 1000)
    #
    # def tiltPoweron(self):
    #     return self.sendCommand("7E32", 1000)
    #
    # def tilePowerOff(self):
    #     return self.sendCommand("7E33", 1000)
    
    def test1111(self, msecs):
        return self.sendCommand("7E72", msecs)

    def test2222(self, msecs):
        return self.sendCommand("7E02", msecs)

    def changeSpeedValue(self, value, msecs):
        sdata = "7E08%s" % self.convertValue(value)
        return self.sendCommand(sdata, msecs)

    def changeSpeedValue_DM250K(self, value, msecs):
        sdata = "7E08%s00B" % self.convertValue(value)
        return self.sendCommand(sdata, msecs)

    def changeSpeedValue_tilt(self, value, msecs):
        sdata = "7E35%s" % self.convertValue(value)
        return self.sendCommand(sdata, msecs)

    def SerialTest(self, msecs=1000):
        return self.sendCommand("7E02000000000000000000000000000A", msecs)

    def readPidTemp(self):
        return  self.sendCommand("010403E80001B1BA")

    def setPidTemp(self, value):
        return  self.sendCommand("01060000%s8806" % self.convertValue_pid(value))

    # 시리얼 넘버 확인 프로토콜
    def CheckSerial(self, msecs):
        return self.sendCommands("7E0D", msecs)

    def readSignals(self, shex, msecs):
        try:
            # data = self.HexStrToByteArray(shex, 6)
            self.writeData(shex, msecs)
            s = self.readData(msecs)
            checkSerial = s.count('s')
            if checkSerial >= 1:
                return 1
            else:
                return -1
        except:
            self.proxy.ui_errorPython(True)
            self.logger.error("sendSignal exception:%d" % self.s)
            return None

    def sendCommands(self, shex, msecs):
        ret = self.readSignals(shex, msecs)
        return ret
