#!/usr/local/bin/python
# -*- coding: utf-8 -*-
"""
Created on Jun 07, 2021

@author: dkyoo
"""
from printThread_info import printThread_info
import os
import threading
import zipfile
from configparser import ConfigParser
from xmlrpc import client
from time import sleep
# import sys
import datetime
import cv2
import logging.handlers
# from logging.handlers import TimedRotatingFileHandler
import time
# from PIL import Image
# from multiprocessing import Process
import RPi.GPIO as GPIO
from serial_blade import serial_Blade

logger = logging.getLogger('dp110server')


class mainprintThread(threading.Thread):

    def setPrint(self, parent, printer, rpcprinter, totalLayer, baseNumber, thickness, ZeroPoint):
        self.parent = parent
        self.printer = printer
        self.rpcprinter = rpcprinter
        self.baseNumber = baseNumber
        self.totalLayer = totalLayer
        self.nowLayer = 1
        self.totalHeight = float(totalLayer * thickness)
        self.thickness = thickness
        self.ZeroPoint = ZeroPoint
        self.beginningTime = float(self.printer.LightTime_Beginning)
        self.basicTime = float(self.printer.LightTime_Basic)
        self.LightStep_Beginning = float(self.printer.LightStep_Beginning)
        self.BasicwaitTime = float(self.printer.basicWaitTime)
        self.beginningWaitTime = float(self.printer.beginWaitTime)
        self.motorSpeed = float(self.printer.ZMotorSpeed * 2)
        self.pause = False
        self.interimPause = False
        self.interimResume = False
        self.interimcheck = False
        self.printHight = 0
        self.stop = False
        self.startPoint = False
        self.proxy = client.ServerProxy('http://127.0.0.1:8181')
        # self.proxy = xmlrpclib.ServerProxy('http://192.168.0.80:8282')
        self.MoveMount = 0
        self.fastZeroMove = self.ZeroPoint - 10
        self.zeroMoveTime = self.fastZeroMove / 0.00015625
        self.ZeroPointMP = self.ZeroPoint / 0.00015625
        self.DivfastZeroMove = self.fastZeroMove / 10
        self.sumfastZeroMove = 0
        self.endFlagSumfastZeroMove = self.printer.ZeroPoint - 80
        self.divMotorTime = int((self.DivfastZeroMove / 4) - 0.13)
        self.tempCurrent = 0
        self.display_opencv = 0
        # blade
        self.blade_type_set = self.printer.blade_type  # 0: no use, 1 : use
        print("set print Blade_type: ", self.blade_type_set)
        self.blade_used = 0     # if used when self.blade_type_set is 1

    def run(self):
        print('thread run start')
        if self.display_opencv:
            #  openCV declare start
            print('opencv set start')
            self.img = cv2.imread(os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/black.png',
                                  cv2.IMREAD_GRAYSCALE)
            # self.mask_image = cv2.imread(os.environ.get('HOME', '/home/pi') + '/carima/basic/mask.png',
            #                              cv2.IMREAD_GRAYSCALE)
            print('cv2 self.img')   # can't below twice
            cv2.namedWindow("main", cv2.WINDOW_NORMAL)
            print('cv2.namedWindow')
            cv2.setWindowProperty("main", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
            # print('cv2.setWindowProperty')
            cv2.moveWindow("main", 800, 0)
            # print('cv2.moveWindow')
            cv2.imshow("main", self.img)
            # print('cv2.imshow')
            cv2.waitKey(50)
            print('opencv set end')
            #  openCV declare end
        else:
            self.printer.printConnect1()
            cv2.waitKey(1)
            cv2.waitKey(1)

        self.proxy.ui_lamp(False)
        sleep(0.2)
        self.printer.boardGo(0, 1)
        while self.sumfastZeroMove < self.fastZeroMove:
            self.sumfastZeroMove += self.DivfastZeroMove
            self.endFlagSumfastZeroMove += self.DivfastZeroMove
            if self.parent.printendPositionFlag == 0:
                if self.sumfastZeroMove >= self.fastZeroMove:
                    self.printer.boardGo(self.fastZeroMove, 0)
                else:
                    self.printer.boardGo(self.sumfastZeroMove, 0)
            else:
                if self.endFlagSumfastZeroMove >= self.fastZeroMove:
                    self.printer.boardGo(self.fastZeroMove, 0)
                    # 분할된 영점 값이 출력물 높이에 따른 출력 완료 후 높이가 달라짐에 따른 오차로 인해 발생되는 영점값에 대한 처리
                else:
                    self.printer.boardGo(self.endFlagSumfastZeroMove, 0)
            if self.stop:
                self.run_stop()
                return 1
            if self.endFlagSumfastZeroMove >= self.fastZeroMove and self.parent.printendPositionFlag == 1:
                # cv2.waitKey(100)
                sleep(0.1)
            elif self.sumfastZeroMove >= self.fastZeroMove and self.parent.printendPositionFlag == 0:
                # cv2.waitKey(100)
                sleep(0.1)
            elif self.endFlagSumfastZeroMove < self.fastZeroMove or self.sumfastZeroMove < self.fastZeroMove:
                sleep(self.divMotorTime)

        sleep(0.1)
        self.printer.changeTimer(self.motorSpeed)
        sleep(0.1)
        self.printer.boardGo(self.ZeroPoint, 1)
        sleep(0.1)

        # blade
        self.parent.blade_max_speed()
        sleep(0.1)

        if self.stop:
            self.run_stop()
            return 1

        if (self.beginningTime > self.basicTime) and (self.LightStep_Beginning != 0):
            Minus_beginningTime = int((self.beginningTime - self.basicTime) / self.LightStep_Beginning)
        else:
            Minus_beginningTime = 0
        self.printer.printConnect1()
        self.printer.changeTimer(self.motorSpeed)
        while self.nowLayer <= self.totalLayer:  # 조형 반복 시퀀스
            # pause and resume
            if self.pause:
                if self.stop:
                    self.run_stop()
                    return 1
                if self.interimPause:
                    self.printer.changeTimer(16)
                    sleep(0.2)
                    if self.printHight <= 30:
                        self.printer.boardGo(30, 1)
                    elif 30 < self.printHight <= 60:
                        self.printer.boardGo(15, 1)
                    elif 60 < self.printHight:
                        self.printer.boardGo(1, 1)
                    self.interimPause = False
                    self.interimcheck = True
                    sleep(0.5)
                    continue
                else:
                    if self.stop:
                        self.run_stop()
                        return 1
                    sleep(0.5)
                    continue
            elif self.interimResume & self.interimcheck:  # 일시정지 해제
                self.printer.boardGo(self.ZeroPoint - self.MoveMount - self.printer.LowSpeedAmount, 1)
                self.interimResume = False
                self.interimcheck = False
                sleep(0.1)
                self.printer.changeTimer(self.motorSpeed)

            if self.startPoint:
                if self.nowLayer <= self.totalLayer:
                    self.MoveMount += self.thickness
                    # 1) motor down
                    # self.parent.Insertlog('==> 1. motor down')
                    self.printer.boardGo(self.ZeroPoint - self.MoveMount, 1)
                    self.printHight = self.thickness * self.nowLayer
                    self.tempCurrent = self.printer.checkTmpSensor()

            if self.stop:
                self.run_stop()
                return 1

            if self.nowLayer <= self.totalLayer:
                # 2) notice to qt
                # self.parent.Insertlog('==> 2. proxy info Layer : ' + str(self.nowLayer))
                self.proxy.ui_layer(self.nowLayer)

            # 3) WaitTime on by resin cfg
            # self.parent.Insertlog('==> 3. WaitTime : ' + str(self.BasicwaitTime))
            if self.nowLayer <= self.printer.LightStep_Beginning:
                if self.beginningWaitTime != 0:
                    # cv2.waitKey(self.beginningWaitTime)
                    sleep(self.beginningWaitTime)
            else:
                if self.BasicwaitTime != 0:
                    # cv2.waitKey(self.BasicwaitTime)
                    sleep(self.BasicwaitTime)

            if self.stop:
                self.run_stop()
                return 1

            # 4) image on
            # self.parent.Insertlog('==> 4. image on')
            if self.display_opencv:
                ori_image = cv2.imread(os.environ.get('HOME', '/home/pi') + '/carima/buffer/image/SEC_%04d.png' %
                                       self.nowLayer, cv2.IMREAD_GRAYSCALE)
                cv2.imshow("main", ori_image)
                # cv2.waitKey(50)
                cv2.waitKey(1)
            else:
                self.printer.image_display(self.nowLayer)

            # 5) engine on
            # self.parent.Insertlog('==> 5. engine on')
            self.proxy.ui_lamp(True)

            # 6) display continue time
            # self.parent.Insertlog('==> 6. display continue time')
            if self.nowLayer <= self.printer.LightStep_Beginning:
                sleep(self.beginningTime)
            else:
                sleep(self.basicTime)

            # self.printer.lightOn1(self.nowLayer, self.basicTime, self.beginningTime)
            if self.stop:
                self.run_stop()
                return 1

            # 7) image off
            # self.parent.Insertlog('==> 7. image off')
            if self.display_opencv:
                self.img = cv2.imread(os.environ.get('HOME', '/home/pi') + '/carima/dp110server/images/black.png',
                                      cv2.IMREAD_GRAYSCALE)
                cv2.imshow("main", self.img)
                # cv2.waitKey(50)
                cv2.waitKey(1)
            else:
                self.printer.display.showSliceOffImage()

            # add layer
            self.nowLayer += 1

            if self.stop:
                self.run_stop()
                return 1

            # 8) Lamp off
            # self.parent.Insertlog('==> 8. engine off')
            self.proxy.ui_lamp(False)

            # 9) sleep between engine off and motor up
            # self.parent.Insertlog('==> 9. sleep 0.1')
            sleep(0.1)  # wait between light off and motor up
            if self.nowLayer <= self.LightStep_Beginning:
                self.beginningTime = self.beginningTime - Minus_beginningTime

            # 10) motor up
            # self.parent.Insertlog('==> 10. motor up')
            self.printer.boardGo(self.ZeroPoint - self.printer.LowSpeedAmount - self.MoveMount, 1)
            if self.stop:
                self.run_stop()
                return 1

            # add blade for kist =======================>>
            if self.blade_type_set is 1:
                sleep(1.5)
                print("=====>> blade t=1 start: ", self.blade_used)
                if self.blade_used is 0:
                    self.blade_used = 1
                    # self.parent.avr_board.z_AbsoluteMove(20, 30000, 0)
                    self.parent.py_blade_board_down(30)
                else:   # self.blade_used is 1
                    self.blade_used = 0
                    # self.parent.avr_board.z_AbsoluteMove(10, 30000, 0)
                    self.parent.py_blade_board_up(30)

                print("=====>> blade down end")
                sleep(10)
                print("=====>> sleep end")
            # elif self.blade_type_set is 2:
            #     print("===>> blade down/up start")
            #     sleep(1)
            #     # self.parent.avr_board.z_AbsoluteMove(30, 30000, 1)
            #     self.parent.py_blade_board_down(30, 0)
            #     sleep(10)
            #     # self.parent.avr_board.z_AbsoluteMove(5, 30000, 1)
            #     self.parent.py_blade_board_up(30, 0)
            #     print("=====>> blade end")
            #     sleep(10)
            else:
                print("===>> blade type is 0")
            # add blade for kist =======================>>

            # TODO:check sequence
            self.startPoint = True
            # 11) loop or end
            if self.nowLayer > self.totalLayer:
                cv2.destroyAllWindows()
                self.printer.MaxSpeed()
                self.printer.boardGo(1, 1)
                print("boardGo end")
                self.printer.removeImageFile()
                print("removeImageFile end")
                self.printer.EndPrintBuzzer()

                self.proxy.ui_isPrinting()
                self.proxy.ui_isPrinting()
                self.parent.Insertlog('printing complete')
                # self.printer.InsideLED_fanOFF()
                self.parent.is_printing = 3
                self.blade_go_start_position()
                return 1

    def run_stop(self):
        # self.printer.InsideLED_fanOFF()
        print("run_stop start")
        cv2.destroyAllWindows()
        self.printer.MaxSpeed()
        sleep(0.2)
        self.printer.boardGo(1, 0)
        sleep(0.2)
        self.proxy.ui_isPrinting()
        sleep(0.2)
        self.proxy.ui_isPrinting()
        self.parent.is_printing = 3
        self.blade_go_start_position()

    def blade_go_start_position(self):
        if self.blade_type_set is 1 and self.blade_used is 1:
            self.parent.py_blade_board_up(30)
            print("blade go to start position")
        else:
            print("blade is already start point")


class printThread_Kist(object):
    """
    classdocs
    """

    def __init__(self, params):
        """
        Constructor
        """
        self.printer = printThread_info()
        self.rpcprinter = printThread_Kist
        self.is_open = -1
        self.is_printing = 3
        self.new_img = 0
        self.homebutton = 0
        self.homebutton_blade = 0
        self.openPort = 0
        self.is_light_on = False
        self.Initlog()
        self.Insertlog('system on')
        self.proxy = client.ServerProxy("http://127.0.0.1:8181")
        self.printer.display.xmlrpcclient()
        self.trySerial = 0
        self.firstboot = 0
        self.upSignal = 0
        self.downSignal = 0
        self.printendPositionFlag = 0
        self.upSignal_blade = 0
        self.downSignal_blade = 0
        self.printendPositionFlag_blade = 0
        print(params)
        self.engineUSEStartTime = 0
        self.printThread_opencv_test = 1
        self.maskImagePath = os.environ.get('HOME', '/home/dp110') + '/carima/basic/mask.png'
        # self.focusImagePath = os.environ.get('HOME', '/home/dp110') + '/carima/basic/focus.png'
        # self.blade_zero_z_axis_position = 0
        self.blade_position = 0

        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(38, GPIO.OUT)
        GPIO.setup(37, GPIO.OUT)
        GPIO.setup(40, GPIO.OUT)
        GPIO.output(38, 0)  # PCB
        GPIO.output(37, 0)  # PCB
        GPIO.output(40, 0)  # PCB

        if os.name == 'posix':
            self.configPath = os.environ.get('HOME', '/home/pi') + '/carima/system.cfg'
            self.resinconfigPath = os.environ.get('HOME', '/home/pi') + '/carima/resin.cfg'
        else:
            self.configPath = 'System.cfg'

    def testsleepTime(self):
        testdata = float(4.5)
        while 1:
            self.Insertlog('timeCheck')
            sleep(testdata)

    def lamponoffTest(self):
        while 1:
            self.proxy.ui_lamp(True)
            self.proxy.ui_lamp(False)
        return 1

    def testXML(self, T):
        return self.proxy.T(T)

    def py_isOpenPorts(self):
        return self.is_open

    def lampTest(self, on):
        if on == 1:
            self.proxy.ui_lamp(True)
            return 1
        else:
            self.proxy.ui_lamp(False)
            return 2

    def py_printPause(self, pauseinterim):
        if pauseinterim:
            self.pthread.pause = True
            self.pthread.interimPause = True
            self.Insertlog('printing interimpause')
        else:
            self.pthread.pause = True
            self.Insertlog('printing pause')
        return 1

    def py_printResume(self, pauseinterim):
        if pauseinterim:
            self.pthread.pause = False
            self.pthread.interimResume = True
        else:
            self.pthread.pause = False
        self.Insertlog('printing resume')
        return 1

    def py_reOpenPorts(self):
        print("py_reOpenPorts")
        GPIO.output(38, 1)
        sleep(3.5)
        GPIO.output(38, 0)
        sleep(3.5)
        self.Insertlog('reopen port')
        self.printer.rePrintConnet(1)
        if self.printer.printConnect() is False:
            self.Insertlog('Motor Serial Connect Failed')
            try:
                return self.proxy.ui_openPorts(False)
            except:
                print("proxy send fail")
        else:
            sleep(0.5)
            if self.homebutton != 1:
                self.openPort = 1
                try:
                    self.proxy.ui_openPorts(True)
                except:
                    print("proxy send fail")
        self.Insertlog('Motor Serial Connect success')

        # blade
        self.py_blade_open_ports()
        #blade
        return 1

    def py_openPorts(self):
        self.printer.readConfig(self.configPath)
        self.Insertlog('open port')
        self.printer.openPorts(1)
        if self.printer.printConnect() is False:
            self.py_reOpenPorts()
            return self.proxy.ui_openPorts(True)
        else:
            self.printer.printConnect1()
            data1 = self.printer.boardHome()
            self.Insertlog("py_openPorts Z=" % data1)
            print("boardHome : ", data1)
            self.Insertlog('First Home')
            sleep(0.1)
            self.printer.printConnect2()
            sleep(2)
            try:
                self.proxy.ui_initZeroPoint(False)
            except:
                print("proxy send fail")
            self.Insertlog('Motor Serial Connect success')
            return 1

    def py_isPrinting(self):
        return self.is_printing

    def py_printStart(self, reginame, totalLayer, thickness):
        self.printer.readConfig(self.configPath)
        self.printer.resinConfig(self.resinconfigPath, reginame)
        # ifolder = os.environ.get('HOME','/home/dp110') + '/carima/build-3DPrinter-Desktop-Release/buffer/image'
        ifolder = os.environ.get('HOME', '/home/dp110') + '/carima/buffer/image'
        if not os.path.exists(ifolder):
            self.logger.error('path not exists: %s' % ifolder)
            return False
        base_index = 1

        self.printer.display.imageRoot = ifolder
        self.printer.display.fileType = 'png'

        self.pthread = mainprintThread()
        self.pthread.setPrint(self, self.printer, self.rpcprinter, totalLayer, base_index,
                              thickness, self.printer.ZeroPoint)

        # self.printer.InsideLED_fanON()
        self.printer.set_first_motor_speed()     # originalTimer()
        self.py_engineLightOn()
        self.pthread.start()
        self.Insertlog('printing start - %d' % totalLayer)
        self.is_printing = 1
        return 1

    # TODO: receive file data and unzip file
    def py_uploadFile(self, fileName, fileData):
        if os.path.isdir(os.environ.get('HOME', '/home/pi') + '/carima/buffer/image'):
            self.printer.removeImageFile()
        fileNames = os.environ.get('HOME', '/home/dp110') + '/carima/buffer/' + fileName
        with open(fileNames, "wb") as handle:
            handle.write(fileData.data)

        fzip = zipfile.ZipFile(fileNames)
        fzip.extractall(os.environ.get('HOME', '/home/pi') + '/carima/buffer/image')

        fzip.close()
        return 1

    def py_sliceUpload(self, fileName, fileData):
        fileNames = os.environ.get('HOME', '/home/dp110') + '/carima/data/' + fileName
        with open(fileNames, "wb") as handle:
            handle.write(fileData.data)
        return 1

    def py_sliceDownload(self):
        with open("/home/dp110/carima/system.cfg", "rb") as handle:
            return client.Binary(handle.read())
        handle.close()

    def py_getCurrentLayer(self):
        sleep(0.3)
        return self.pthread.nowLayer

    def py_printStop(self):
        self.is_printing = 3
        self.pthread.stop = True
        self.Insertlog('printing stop')
        try:
            self.printer.removeImageFile()
        except:
            return 1
        return 1

    def py_isPause(self):
        return self.pthread.pause

    def py_isEngineOn(self):
        return 1

    def py_enginePower(self, isOn):
        return 1

    def py_isLightOn(self):
        return 1

    def py_engineLightOn(self):
        self.Insertlog('engine_on')
        self.engineUSEStartTime = datetime.datetime.now().replace(microsecond=0)
        return 1

    def py_boardHome(self):
        self.homebutton = 1
        self.printendPositionFlag = 0
        self.printer.printConnect1()
        sleep(0.5)
        self.printer.boardHome()
        sleep(0.5)
        self.printer.printConnect2()
        sleep(2)
        try:
            self.proxy.ui_initZeroPoint(True)
        except:
            print("boardHome send fail")
        return 1

    def py_led_fanOn(self):
        return self.printer.led_fanOn()

    def py_ledOn_fanOff(self):
        return self.printer.ledOn_fanOff()

    def py_ledblink_fanOn(self):
        return self.printer.ledblink_fanOn()

    # TODO: stuff
    def py_shutdown(self):
        self.printer.ShutdownBuzzer()
        self.Insertlog('system off')
        os.system("sudo shutdown -h 0")
        return 1

    def py_boardGo(self, A):
        self.printer.boardGo(A, 0)
        return 1

    def py_boardDown(self, ZMotorAmount):
        self.Insertlog("start")
        self.printer.boardDown(ZMotorAmount, 0)
        self.Insertlog("stop")
        self.downSignal = 1
        return 1

    def py_boardUp(self, ZMotorAmount):
        self.Insertlog("start")
        self.printer.boardUp(ZMotorAmount, 0)
        self.Insertlog("stop")
        self.upSignal = 1
        return 1

    def py_boardStop(self):
        if self.upSignal == 1:
            self.printer.upboardStop()
            self.upSignal = 0
        elif self.downSignal == 1:
            self.printer.downboardStop()
            self.downSignal = 0
        return 1

    def py_zeroPointUp(self, ZMotorAmount):
        self.Insertlog('start %d' % ZMotorAmount)
        self.printer.printConnect1()
        self.printer.zeroboardUp(ZMotorAmount, 1)
        self.Insertlog('finish')
        return self.printer.printConnect2()

    def py_zeroPointDown(self, ZMotorAmount, value):
        self.Insertlog('start %d' % ZMotorAmount)
        self.printer.printConnect1()
        self.printer.zeroboardDown(ZMotorAmount, 0, 1)
        self.Insertlog('finish')
        return self.printer.printConnect2()

    def py_motorUpDir(self):
        self.printer.motorUpDir()
        return 1

    def py_motorPosition(self):
        return self.printer.motorPositions()

    def py_basicImage(self, status):
        if status == 1:
            self.printer.BasicImageOn()
            self.Insertlog('basicimage_on')
            return 1
        else:
            self.printer.BasicImageOff()
            self.Insertlog('basicimage_off')
            return 1

    def py_focusImage(self, status):
        if status == 1:
            self.printer.display.focusImageOn()
            self.Insertlog('FocusImgOn')
            return 1
        else:
            self.printer.display.clear()
            self.Insertlog('FocusImgOff')
            return 1

    def BasicImageOncont(self):
        self.printer.display.whiteclearcont()
        return 1

    def py_setupGrid(self, xres, yres, xgrid, ygrid, line):
        return self.printer.display.setupGrids(xres, yres, xgrid, ygrid, line)

    def py_showGrid(self, x, y, val):
        self.printer.display.makeGrids((5 - x), y, val)
        self.printer.display.gridImageOn()
        return 1

    def py_clearGrid(self):
        self.printer.display.clear()
        return 1

    def cv_show_img(self, imgPath):
        cv2.namedWindow("main", cv2.WINDOW_NORMAL)
        cv2.setWindowProperty("main", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
        cv2.moveWindow("main", 800, 0)
        # cv2.startWindowThread()
        # cv2.waitKey(50)
        img = cv2.imread(imgPath, cv2.IMREAD_COLOR)
        cv2.imshow("main", img)
        cv2.waitKey(50)

    def py_maskImage(self, turn):
        # Exposure Light for Cleaning
        print('py_maskImage turn is %d' % turn)
        if self.printThread_opencv_test:
            if turn == 1:
                self.cv_show_img(self.maskImagePath)
            else:
                cv2.destroyAllWindows()
            return 1
        else:
            if turn == 1:
                self.printer.display.maskImageOn()
            else:
                self.printer.display.clear()
            return 1

    def py_buildImage(self, turn):
        if turn == 1:
            self.printer.display.buildImageOn()
        else:
            self.printer.display.clear()
        return 1

    def py_whiteImage(self, turn):
        if turn == 1:
            self.printer.display.whiteImageOn()
        else:
            self.printer.display.clear()
        return 1

    def py_whiteImageOff(self):
        self.printer.display.whiteImageOff()
        return 1

    def py_adminSet(self):
        self.Insertlog('admin set')
        return 1

    def Insertlog(self, logmsg):
        now = datetime.datetime.now()
        if self.logtime != now.strftime('%d-%H'):
            self.logbytime.removeHandler(self.logbytime.handlers[0])
            self.Initlog()
        self.logbytime.info(logmsg)
        return 1

    def Initlog(self):
        # 년월에 해당하는 폴더가 생성되어 있는지 먼저 파악 -> 매번 해당 루틴을 수행하는 은 좋지 않다. 처음 프린터가 실행되었을 때만 확인
        now = datetime.datetime.now()
        nowDateYM = now.strftime(os.environ.get('HOME', '/home/pi') + '/SystemLog/%Y-%m')
        if not os.path.exists(nowDateYM):
            os.makedirs(nowDateYM)
        self.logtime = now.strftime('%d-%H')
        nowDateMDH = now.strftime(os.environ.get('HOME', '/home/pi') + '/SystemLog/%Y-%m/%m-%d-%H')
        self.logbytime = logging.getLogger('imjlog')
        hdlr = logging.handlers.TimedRotatingFileHandler(nowDateMDH)
        formatter = logging.Formatter('[%(asctime)s] %(message)s')
        hdlr.setFormatter(formatter)
        self.logbytime.addHandler(hdlr)
        self.logbytime.setLevel(logging.INFO)
        return 1

    def py_checkxmlrpcclient(self):
        return self.printer.display.xmlrpcclient()

    def py_bufferTest(self):
        self.printer.display.bufferImgTest()
        return 1

    def Ainitmotor(self):
        self.printer.initMotorpostion()
        return 1

    def enterPasswd(self):
        return self.printer.enterPasswd()

    def printEndBuzzer(self):
        return self.printer.EndPrintBuzzer()

    def SystemEndBuzzer(self):
        return self.printer.ShutdownBuzzer()

    def checkTempSensor(self):
        return self.printer.checkTmpSensor()

    def readPidTemp(self):
        return self.printer.Aboard.readPidTemp()

    def setPidTemp(self):
        return self.printer.Aboard.setPidTemp()

    def checkSenSorPin(self):
        return self.printer.Aboard.checkSensor(1000)

    def CheckSignal_pin4(self):
        return self.printer.Aboard.CheckSignal_pin4(1000)

    def CheckSignal_pin2(self):
        return self.printer.Aboard.CheckSignal_pin3(1000)

    def leftmove2(self):
        self.printer.printConnect1()
        return self.printer.Aboard.leftmove2(1000)

    def leftmove2_1(self):
        return self.printer.Aboard.leftmove2_1(1000)

    def rightmove3(self):
        self.printer.printConnect1()
        return self.printer.Aboard.rightmove3(1000)

    def rightmove3_1(self):
        return self.printer.Aboard.rightmove3_1(1000)

    def moveStop(self):
        return self.printer.Aboard.StopMove(1000)

    def TestMotorSpeed(self, motor_time):
        self.Insertlog('1')
        self.printer.New_changeTimer(motor_time)
        self.Insertlog('2')
        return 1

    def TestSensor(self):
        return self.printer.Aboard.test1111(1000)

    def TestPosition(self):
        return self.printer.Aboard.test2222(1000)

    def T(self):
        self.Insertlog('test_complete')
        return 1

    def changeMotorSpeed(self, value):
        self.printer.New_changeTimer(value)
        return 1

    def testMotorTime(self, speed, thickness):
        self.printer.printConnect1()
        self.printer.New_changeTimer(speed)
        count = 1
        retry = 0
        moveMount = 0
        while count < 11:
            retry = 0
            self.printer.boardGo(0, 1)
            while retry < 4:
                self.Insertlog('start motor %d' % count)
                startTime = time.time()
                self.printer.boardGo(count, 1)
                endTime = time.time()
                runningTime = endTime - startTime
                self.Insertlog(runningTime)

                startTime = time.time()
                self.printer.boardGo(thickness, 1)
                endTime = time.time()
                runningTime = endTime - startTime
                self.Insertlog(runningTime)

                retry += 1
            count += 1
        return 1

    # =======================>> z, blade serial test
    # 1. connect serial
    def py_blade_open_ports(self):
        self.avr_board = serial_Blade(0)
        self.py_blade_board_home()
        print("blade set ok")
        return 1

    # 2. set 0 position for blade
    def py_blade_board_home(self):
        self.homebutton_blade = 1
        data1 = self.avr_board.blade_motor_home()
        print("blade home : ", data1)
        self.blade_position = 0
        return 1

    # 3. Up/Down blade
    def py_blade_board_down(self, value):
        check = 0   # if 1, no response from firmware
        zero_value = self.blade_position + value
        self.blade_position = zero_value
        # print("==> blade down to : ", self.blade_position)
        if self.blade_position > 140:
            s = self.avr_board.z_AbsoluteMove(140, 30000, 0)
            self.blade_position = 140
        else:
            s = self.avr_board.blade_motor_move(zero_value, check)
        # print("==> board_down return : ", s)
        # print("blade down : ", self.blade_position)
        return 1

    def py_blade_board_up(self, value):
        check = 0   # if 1, no response from firmware
        zero_value = self.blade_position - value
        if zero_value < 0:
            zero_value = 0
        self.blade_position = zero_value
        # print("==> blade up to : ", self.blade_position)
        s = self.avr_board.blade_motor_move(zero_value, check)
        # print("==> board_up return : ", s)
        # print("blade up : ", self.blade_position)
        return 1

    def py_blade_is_open(self):
        if self.avr_board.openSerialPort() == -1:
            # self.logger.debug('blade connect failed')
            print("blade connect failed")
            return False
        else:
            return True

    def blade_change_speed(self, value):
        one_motor_step = int(round((value / 0.00015625), 4))
        two_motor_step = int(one_motor_step + 2740)
        return self.avr_board.changeSpeedValue(two_motor_step, 1000)

    def blade_max_speed(self):
        speed_data = int((6400 / 0.125) * 2.5)
        return self.avr_board.changeSpeedValue(speed_data, 1000)
