import tkinter as tk
from tkinter import ttk, Canvas
import serial.tools.list_ports
from threading import Thread, Timer, Lock
import socket
import time

class MainWidget(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.protocol("WM_DELETE_WINDOW", self.on_closing)

        self.btn_val = 0
        self.sndpkg_no = 0
        self.netsndpkg_no = 0
        self.net_lock = Lock()
        self.ckbox_var1 = tk.IntVar()
        self.ckbox_var2 = tk.IntVar()
        self.ckbox_var3 = tk.IntVar()
        self.ckbox_var4 = tk.IntVar()
        self.ckbox_var5 = tk.IntVar()
        self.ckbox_var6 = tk.IntVar()
        self.ckbox_var7 = tk.IntVar()
        self.ckbox_var8 = tk.IntVar()
        self.ckbox_var9 = tk.IntVar()
        self.ckbox_var10 = tk.IntVar()
        self.netrcvrunning = False
        self.create_widgets()

    def on_closing(self):
        self.on_close()
        self.on_net_close()
        self.master.destroy()

    def create_widgets(self):
        self.devlist = serial.tools.list_ports.comports()
        self.s = serial.Serial(baudrate=115200, timeout=1);
        self.receiving = False

        self.frame_line1 = ttk.Frame(self.master)
        self.frame_line1.grid(column=0, row=0)

        self.frame_line11 = ttk.Frame(self.frame_line1)
        self.frame_line11.grid(column=0, row=0)

        self.devcombo = ttk.Combobox(self.frame_line11)
        self.devcombo['values'] = self.devlist
        self.devcombo.grid(column=0, row=0)

        self.open_btn = tk.Button(self.frame_line11, text = "Open",  command = self.on_open)
        self.open_btn.grid(column=1, row=0)
        
        self.info_btn_Front = tk.Button(self.frame_line11, text = "Front", command = self.on_btn_front)
        self.info_btn_Front.grid(column=2, row=0)
        self.info_btn_Rear = tk.Button(self.frame_line11, text = "Rear", command = self.on_btn_rear)
        self.info_btn_Rear.grid(column=3, row=0)
        self.info_btn_IR = tk.Button(self.frame_line11, text = "IR", command = self.on_btn_IR)
        self.info_btn_IR.grid(column=4, row=0)
        self.info_btn_NUC = tk.Button(self.frame_line11, text = "NUC", command = self.on_btn_NUC)
        self.info_btn_NUC.grid(column=5, row=0)

        self.frame_line12 = ttk.Frame(self.frame_line1)
        self.frame_line12.grid(column=0, row=1)

        self.ip_label = tk.Label(self.frame_line12, text='IP:')
        self.ip_label.grid(column=0, row=0)
        self.ip_editor = tk.Entry(self.frame_line12)
        self.ip_editor.grid(column=1, row=0)

        self.port_label = tk.Label(self.frame_line12, text='Port:')
        self.port_label.grid(column=2, row=0)
        self.port_editor = tk.Entry(self.frame_line12)
        self.port_editor.grid(column=3, row=0)

        self.net_btn_conn = tk.Button(self.frame_line12, text = "Connect",  command = self.on_net_conn)
        self.net_btn_conn.grid(column=4, row=0)

        video_list = ['video0', 'video1', 'video2', 'video3', 'video4', 'video5', 'video6', 'video7', 'video8', 'video9']

        self.VO1_label = tk.Label(self.frame_line12, text='Video Out 0:')
        self.VO1_label.grid(column=1, row=1)
        self.VI1_combo = ttk.Combobox(self.frame_line12)
        self.VI1_combo['values'] = video_list
        self.VI1_combo.grid(column=3, row=1)
        self.VI1_combo.bind('<<ComboboxSelected>>', self.VO1_send)

        self.VO2_label = tk.Label(self.frame_line12, text='Video Out 1:')
        self.VO2_label.grid(column=1, row=2)
        self.VI2_combo = ttk.Combobox(self.frame_line12)
        self.VI2_combo['values'] = video_list
        self.VI2_combo.grid(column=3, row=2)
        self.VI2_combo.bind('<<ComboboxSelected>>', self.VO2_send)

        self.VO3_label = tk.Label(self.frame_line12, text='Video Out 2:')
        self.VO3_label.grid(column=1, row=3)
        self.VI3_combo = ttk.Combobox(self.frame_line12)
        self.VI3_combo['values'] = video_list
        self.VI3_combo.grid(column=3, row=3)
        self.VI3_combo.bind('<<ComboboxSelected>>', self.VO3_send)

        self.VO4_label = tk.Label(self.frame_line12, text='Video Out 3:')
        self.VO4_label.grid(column=1, row=4)
        self.VI4_combo = ttk.Combobox(self.frame_line12)
        self.VI4_combo['values'] = video_list
        self.VI4_combo.grid(column=3, row=4)
        self.VI4_combo.bind('<<ComboboxSelected>>', self.VO4_send)

        self.VO5_label = tk.Label(self.frame_line12, text='Video Out 4:')
        self.VO5_label.grid(column=1, row=5)
        self.VI5_combo = ttk.Combobox(self.frame_line12)
        self.VI5_combo['values'] = video_list
        self.VI5_combo.grid(column=3, row=5)
        self.VI5_combo.bind('<<ComboboxSelected>>', self.VO5_send)

        self.VO6_label = tk.Label(self.frame_line12, text='Video Out 5:')
        self.VO6_label.grid(column=1, row=6)
        self.VI6_combo = ttk.Combobox(self.frame_line12)
        self.VI6_combo['values'] = video_list
        self.VI6_combo.grid(column=3, row=6)
        self.VI6_combo.bind('<<ComboboxSelected>>', self.VO6_send)

        self.VO7_label = tk.Label(self.frame_line12, text='Video Out 6:')
        self.VO7_label.grid(column=1, row=7)
        self.VI7_combo = ttk.Combobox(self.frame_line12)
        self.VI7_combo['values'] = video_list
        self.VI7_combo.grid(column=3, row=7)
        self.VI7_combo.bind('<<ComboboxSelected>>', self.VO7_send)

        self.VO8_label = tk.Label(self.frame_line12, text='Video Out 7:')
        self.VO8_label.grid(column=1, row=8)
        self.VI8_combo = ttk.Combobox(self.frame_line12)
        self.VI8_combo['values'] = video_list
        self.VI8_combo.grid(column=3, row=8)
        self.VI8_combo.bind('<<ComboboxSelected>>', self.VO8_send)

        self.frame_line13 = ttk.Frame(self.frame_line1)
        self.frame_line13.grid(column=0, row=2)

        self.net_ckbox_0 = tk.Checkbutton(self.frame_line13, text='UDP1', command=self.ckbox1_changed, variable=self.ckbox_var1, onvalue=1, offvalue=0)
        self.net_ckbox_0.grid(column=0, row=0)
        self.net_ckbox_1 = tk.Checkbutton(self.frame_line13, text='UDP2', command=self.ckbox2_changed, variable=self.ckbox_var2, onvalue=1, offvalue=0)
        self.net_ckbox_1.grid(column=1, row=0)
        self.net_ckbox_2 = tk.Checkbutton(self.frame_line13, text='UDP3', command=self.ckbox3_changed, variable=self.ckbox_var3, onvalue=1, offvalue=0)
        self.net_ckbox_2.grid(column=2, row=0)
        self.net_ckbox_3 = tk.Checkbutton(self.frame_line13, text='UDP4', command=self.ckbox4_changed, variable=self.ckbox_var4, onvalue=1, offvalue=0)
        self.net_ckbox_3.grid(column=3, row=0)
        self.net_ckbox_4 = tk.Checkbutton(self.frame_line13, text='UDP5', command=self.ckbox5_changed, variable=self.ckbox_var5, onvalue=1, offvalue=0)
        self.net_ckbox_4.grid(column=4, row=0)
        self.net_ckbox_5 = tk.Checkbutton(self.frame_line13, text='UDP6', command=self.ckbox6_changed, variable=self.ckbox_var6, onvalue=1, offvalue=0)
        self.net_ckbox_5.grid(column=5, row=0)
        self.net_ckbox_6 = tk.Checkbutton(self.frame_line13, text='UDP7', command=self.ckbox7_changed, variable=self.ckbox_var7, onvalue=1, offvalue=0)
        self.net_ckbox_6.grid(column=6, row=0)
        self.net_ckbox_7 = tk.Checkbutton(self.frame_line13, text='UDP8', command=self.ckbox8_changed, variable=self.ckbox_var8, onvalue=1, offvalue=0)
        self.net_ckbox_7.grid(column=7, row=0)
        self.net_ckbox_8 = tk.Checkbutton(self.frame_line13, text='UDP9', command=self.ckbox9_changed, variable=self.ckbox_var9, onvalue=1, offvalue=0)
        self.net_ckbox_8.grid(column=8, row=0)
        self.net_ckbox_9 = tk.Checkbutton(self.frame_line13, text='UDP10', command=self.ckbox10_changed, variable=self.ckbox_var10, onvalue=1, offvalue=0)
        self.net_ckbox_9.grid(column=9, row=0)
        
        self.frame_line14 = ttk.Frame(self.frame_line1)
        self.frame_line14.grid(column=0, row=3)

        self.sys_btn_mem = tk.Button(self.frame_line14, text = "Mem", bg = "green")
        self.sys_btn_mem.grid(column=0, row=0)
        self.sys_btn_log = tk.Button(self.frame_line14, text = "Log", bg = "green")
        self.sys_btn_log.grid(column=1, row=0)
        self.sys_btn_sen = tk.Button(self.frame_line14, text = "Sensor", bg = "green")
        self.sys_btn_sen.grid(column=2, row=0)
        self.sys_btn_pwr = tk.Button(self.frame_line14, text = "Power", bg = "green")
        self.sys_btn_pwr.grid(column=3, row=0)
        self.sys_btn_temp = tk.Button(self.frame_line14, text = "Temperature", bg = "green")
        self.sys_btn_temp.grid(column=4, row=0)
        self.sys_btn_key = tk.Button(self.frame_line14, text = "KEY", bg = "green")
        self.sys_btn_key.grid(column=5, row=0)
        self.sys_btn_ser = tk.Button(self.frame_line14, text = "Serial", bg = "green")
        self.sys_btn_ser.grid(column=6, row=0)
        self.sys_btn_vdu = tk.Button(self.frame_line14, text = "VDU", bg = "green")
        self.sys_btn_vdu.grid(column=7, row=0)

        self.frame_line15 = ttk.Frame(self.frame_line1)
        self.frame_line15.grid(column=0, row=4)

        self.sys_btn_vout0 = tk.Button(self.frame_line15, text = "VOUT1", bg = "green")
        self.sys_btn_vout0.grid(column=0, row=0)
        self.sys_btn_vout1 = tk.Button(self.frame_line15, text = "VOUT2", bg = "green")
        self.sys_btn_vout1.grid(column=1, row=0)
        self.sys_btn_vout2 = tk.Button(self.frame_line15, text = "VOUT3", bg = "green")
        self.sys_btn_vout2.grid(column=2, row=0)
        self.sys_btn_vout3 = tk.Button(self.frame_line15, text = "VOUT4", bg = "green")
        self.sys_btn_vout3.grid(column=3, row=0)
        self.sys_btn_vout4 = tk.Button(self.frame_line15, text = "VOUT5", bg = "green")
        self.sys_btn_vout4.grid(column=4, row=0)
        self.sys_btn_vout5 = tk.Button(self.frame_line15, text = "VOUT6", bg = "green")
        self.sys_btn_vout5.grid(column=5, row=0)
        self.sys_btn_vout6 = tk.Button(self.frame_line15, text = "VOUT7", bg = "green")
        self.sys_btn_vout6.grid(column=6, row=0)
        self.sys_btn_vout7 = tk.Button(self.frame_line15, text = "VOUT8", bg = "green")
        self.sys_btn_vout7.grid(column=7, row=0)
        self.sys_btn_osd0 = tk.Button(self.frame_line15, text = "OSD0", bg = "green")
        self.sys_btn_osd0.grid(column=8, row=0)

        self.frame_line16 = ttk.Frame(self.frame_line1)
        self.frame_line16.grid(column=0, row=5)
        
        self.sys_btn_sdi0 = tk.Button(self.frame_line16, text = "SDI1", bg = "green")
        self.sys_btn_sdi0.grid(column=0, row=0)
        self.sys_btn_sdi1 = tk.Button(self.frame_line16, text = "SDI2", bg = "green")
        self.sys_btn_sdi1.grid(column=1, row=0)
        self.sys_btn_sdi2 = tk.Button(self.frame_line16, text = "SDI3", bg = "green")
        self.sys_btn_sdi2.grid(column=2, row=0)
        self.sys_btn_sdi3 = tk.Button(self.frame_line16, text = "SDI4", bg = "green")
        self.sys_btn_sdi3.grid(column=3, row=0)
        self.sys_btn_sdi4 = tk.Button(self.frame_line16, text = "SDI5", bg = "green")
        self.sys_btn_sdi4.grid(column=4, row=0)
        self.sys_btn_sdi5 = tk.Button(self.frame_line16, text = "SDI6", bg = "green")
        self.sys_btn_sdi5.grid(column=5, row=0)
        self.sys_btn_sdi6 = tk.Button(self.frame_line16, text = "SDI7", bg = "green")
        self.sys_btn_sdi6.grid(column=6, row=0)
        self.sys_btn_sdi7 = tk.Button(self.frame_line16, text = "SDI8", bg = "green")
        self.sys_btn_sdi7.grid(column=7, row=0)
        self.sys_btn_sdi8 = tk.Button(self.frame_line16, text = "SDI9", bg = "green")
        self.sys_btn_sdi8.grid(column=8, row=0)
        self.sys_btn_sdi9 = tk.Button(self.frame_line16, text = "SDI10", bg = "green")
        self.sys_btn_sdi9.grid(column=9, row=0)

        self.frame_line17 = ttk.Frame(self.frame_line1)
        self.frame_line17.grid(column=0, row=6)

        self.label = tk.Label(self.frame_line17, text="maxRtpStream:")
        self.label.grid(column=0, row=0)
        self.maxRtpStream = tk.StringVar()
        self.label = tk.Label(self.frame_line17, textvariable=self.maxRtpStream)
        self.label.grid(column=1, row=0)
        self.maxRtpStream.set("-")

        self.label = tk.Label(self.frame_line17, text="currentActiveRtpStream:")
        self.label.grid(column=2, row=0)
        self.currentActiveRtpStream = tk.StringVar()
        self.label = tk.Label(self.frame_line17, textvariable=self.currentActiveRtpStream)
        self.label.grid(column=3, row=0)
        self.currentActiveRtpStream.set("-")

        self.label = tk.Label(self.frame_line17, text="MessageRunningNo:")
        self.label.grid(column=4, row=0)
        self.MessageRunningNo = tk.StringVar()
        self.label = tk.Label(self.frame_line17, textvariable=self.MessageRunningNo)
        self.label.grid(column=5, row=0)
        self.MessageRunningNo.set("-")

        self.label = tk.Label(self.frame_line17, text="CPU:")
        self.label.grid(column=6, row=0)
        self.CPU_Loading = tk.StringVar()
        self.label = tk.Label(self.frame_line17, textvariable=self.CPU_Loading)
        self.label.grid(column=7, row=0)
        self.CPU_Loading.set("-")

        self.label = tk.Label(self.frame_line17, text="Temperature:")
        self.label.grid(column=8, row=0)
        self.Temperature = tk.StringVar()
        self.label = tk.Label(self.frame_line17, textvariable=self.Temperature)
        self.label.grid(column=9, row=0)
        self.Temperature.set("-")

        self.frame_line18 = ttk.Frame(self.frame_line1)
        self.frame_line18.grid(column=0, row=7)
        
        self.label = tk.Label(self.frame_line18, text="Version:")
        self.label.grid(column=0, row=0)
        self.version = tk.StringVar()
        self.label = tk.Label(self.frame_line18, textvariable=self.version)
        self.label.grid(column=1, row=0)
        self.version.set("-")

        self.label = tk.Label(self.frame_line18, text="Serail No:")
        self.label.grid(column=2, row=0)
        self.SNo = tk.StringVar()
        self.label = tk.Label(self.frame_line18, textvariable=self.SNo)
        self.label.grid(column=3, row=0)
        self.SNo.set("-")
        
        self.label = tk.Label(self.frame_line18, text="Total Tick:")
        self.label.grid(column=4, row=0)
        self.ttick = tk.StringVar()
        self.label = tk.Label(self.frame_line18, textvariable=self.ttick)
        self.label.grid(column=5, row=0)
        self.ttick.set("-")

        self.frame_line19 = ttk.Frame(self.frame_line1)
        self.frame_line19.grid(column=0, row=8)

        self.vdu_btn_info = tk.Button(self.frame_line19, text = "VDU",  command = self.on_vdu_info)
        self.vdu_btn_info.grid(column=0, row=0)

        self.label = tk.Label(self.frame_line19, text="unitSerialNo:")
        self.label.grid(column=1, row=0)
        self.vdu_unitSerialNo = tk.StringVar()
        self.label = tk.Label(self.frame_line19, textvariable=self.vdu_unitSerialNo)
        self.label.grid(column=2, row=0)
        self.vdu_unitSerialNo.set("-")

        self.label = tk.Label(self.frame_line19, text="elapsedTimer:")
        self.label.grid(column=3, row=0)
        self.vdu_elapsedTimer = tk.StringVar()
        self.label = tk.Label(self.frame_line19, textvariable=self.vdu_elapsedTimer)
        self.label.grid(column=4, row=0)
        self.vdu_elapsedTimer.set("-")

        self.label = tk.Label(self.frame_line19, text="Version:")
        self.label.grid(column=5, row=0)
        self.vdu_version = tk.StringVar()
        self.label = tk.Label(self.frame_line19, textvariable=self.vdu_version)
        self.label.grid(column=6, row=0)
        self.vdu_version.set("-")

        self.label = tk.Label(self.frame_line19, text="bitReportMask:")
        self.label.grid(column=7, row=0)
        self.vdu_bitReportMask = tk.StringVar()
        self.label = tk.Label(self.frame_line19, textvariable=self.vdu_bitReportMask)
        self.label.grid(column=8, row=0)
        self.vdu_bitReportMask.set("-")

    def on_open(self):
        curSel = self.devcombo.current()
        port = self.devlist[curSel].device
        if self.s.is_open:
            self.s.close()
        self.s.port = port
        self.s.open()

        if self.s.is_open:
            self.open_btn['text'] = "Close"
            self.open_btn['command'] = self.on_close
            self.rcvtd = Thread(target=self.rcv_cb)
            self.rcvtd.start()
            self.sndtd = Timer(0.1, self.sending_cb)
            self.sndtd.start()
            
    def on_close(self):
        if self.receiving:
           self.receiving = False
           self.rcvtd.join()
        if self.s.is_open:
            self.s.close()
            self.sndtd.cancel()
        self.open_btn['text'] = "Open"
        self.open_btn['command'] = self.on_open

    def on_btn_front(self):
        self.btn_val = self.btn_val & 0xc
        self.btn_val = self.btn_val | 1
        
    def on_btn_rear(self):
        self.btn_val = self.btn_val & 0xc
        self.btn_val = self.btn_val | 2
        
    def on_btn_IR(self):
        self.btn_val = self.btn_val | 4
        
    def on_btn_NUC(self):
        self.btn_val = self.btn_val | 8

    def sending_cb(self):
        if self.s.is_open:
            sndstr = "$KEY,{0},{1:02X},0*".format(self.sndpkg_no, self.btn_val)
            snd_byte = bytearray(sndstr, 'utf-8')
            snd_byte.append(0x00)
            self.s.write(snd_byte)
            self.sndpkg_no = self.sndpkg_no + 1
            if self.sndpkg_no > 255:
                self.sndpkg_no = 0
            self.sndtd = Timer(0.1, self.sending_cb)
            self.sndtd.start()
            
    def rcv_cb(self):
        self.receiving = True
        rcv_data = bytearray()
        rcv_step = 0
        while self.receiving:
            rec = self.s.read(1)
            if len(rec) < 1:
                continue
            if rcv_step == 0 and rec[0] == 0x24:
                rcv_step = 1
            elif rcv_step == 1:
                if rec[0] == 0x2a:
                    rcv_step = 2
                else:
                    rcv_data.append(rec[0])
            elif rcv_step == 2:
                if rec[0] == 0 or rec[0] == 0x0d or rec[0] == 0x0a:
                    rcv_step = 3
            elif rcv_step == 3:
                rcv_step = 0
                print(rcv_data);
                rcvlist = rcv_data.decode().split(',')
                rcv_data = bytearray()
                if len(rcvlist) >= 3:
                    if rcvlist[0] == "KEYA":
                        keyval = int(rcvlist[2], 16)
                        if keyval & 0x1:
                            self.btn_val = self.btn_val & 0xe
                        if keyval & 0x2:
                            self.btn_val = self.btn_val & 0xd
                        if keyval & 0x4:
                            self.btn_val = self.btn_val & 0xb
                        if keyval & 0x8:
                            self.btn_val = self.btn_val & 0x7         
            else:
                rcv_step = 0

    def netsending_cb(self):
        sndstr = "$HST,{0}*".format(self.netsndpkg_no)
        self.netsndpkg_no = self.netsndpkg_no + 1
        if(self.netsndpkg_no > 255):
            self.netsndpkg_no = 0
        snd_byte = bytearray(sndstr, 'utf-8')
        snd_byte.append(0x00)
        self.net_lock.acquire(timeout=5)
        try:
            self.client.send(snd_byte)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return

        try:
            rcv_byte = self.client.recv(1500)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
        self.net_lock.release()
              
        self.net_rcv_cb(rcv_byte)

        sndstr = "$SYS,{0}*".format(self.netsndpkg_no)
        self.netsndpkg_no = self.netsndpkg_no + 1
        if(self.netsndpkg_no > 255):
            self.netsndpkg_no = 0
        snd_byte = bytearray(sndstr, 'utf-8')
        snd_byte.append(0x00)
        self.net_lock.acquire(timeout=5)
        try:
            self.client.send(snd_byte)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return

        try:
            rcv_byte = self.client.recv(1500)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
        self.net_lock.release()
        
        self.net_rcv_cb(rcv_byte)
        self.netsndtd = Timer(0.5, self.netsending_cb)
        self.netsndtd.start()

    def show_sysbit_status(self, sys_status):
        if sys_status & 0x1:
            self.sys_btn_mem.configure(bg = "red")
        else:
            self.sys_btn_mem.configure(bg = "green")
        if sys_status & 0x2:
            self.sys_btn_log.configure(bg = "red")
        else:
            self.sys_btn_log.configure(bg = "green")
        if sys_status & 0x4:
            self.sys_btn_sen.configure(bg = "red")
        else:
            self.sys_btn_sen.configure(bg = "green")
        if sys_status & 0x8:
            self.sys_btn_pwr.configure(bg = "red")
        else:
            self.sys_btn_pwr.configure(bg = "green")
        if sys_status & 0x10:
            self.sys_btn_temp.configure(bg = "red")
        else:
            self.sys_btn_temp.configure(bg = "green")
        if sys_status & 0x20:
            self.sys_btn_key.configure(bg = "red")
        else:
            self.sys_btn_key.configure(bg = "green")
        if sys_status & 0x40:
            self.sys_btn_vout0.configure(bg = "red")
        else:
            self.sys_btn_vout0.configure(bg = "green")
        if sys_status & 0x80:
            self.sys_btn_vout1.configure(bg = "red")
        else:
            self.sys_btn_vout1.configure(bg = "green")
        if sys_status & 0x100:
            self.sys_btn_vout2.configure(bg = "red")
        else:
            self.sys_btn_vout2.configure(bg = "green")
        if sys_status & 0x200:
            self.sys_btn_vout3.configure(bg = "red")
        else:
            self.sys_btn_vout3.configure(bg = "green")
        if sys_status & 0x400:
            self.sys_btn_vout4.configure(bg = "red")
        else:
            self.sys_btn_vout4.configure(bg = "green")
        if sys_status & 0x800:
            self.sys_btn_vout5.configure(bg = "red")
        else:
            self.sys_btn_vout5.configure(bg = "green")
        if sys_status & 0x1000:
            self.sys_btn_vout6.configure(bg = "red")
        else:
            self.sys_btn_vout6.configure(bg = "green")
        if sys_status & 0x2000:
            self.sys_btn_vout7.configure(bg = "red")
        else:
            self.sys_btn_vout7.configure(bg = "green")
        if sys_status & 0x4000:
            self.sys_btn_sdi0.configure(bg = "red")
        else:
            self.sys_btn_sdi0.configure(bg = "green")
        if sys_status & 0x8000:
            self.sys_btn_sdi1.configure(bg = "red")
        else:
            self.sys_btn_sdi1.configure(bg = "green")
        if sys_status & 0x10000:
            self.sys_btn_sdi2.configure(bg = "red")
        else:
            self.sys_btn_sdi2.configure(bg = "green")
        if sys_status & 0x20000:
            self.sys_btn_sdi3.configure(bg = "red")
        else:
            self.sys_btn_sdi3.configure(bg = "green")
        if sys_status & 0x40000:
            self.sys_btn_sdi4.configure(bg = "red")
        else:
            self.sys_btn_sdi4.configure(bg = "green")
        if sys_status & 0x80000:
            self.sys_btn_sdi5.configure(bg = "red")
        else:
            self.sys_btn_sdi5.configure(bg = "green")
        if sys_status & 0x100000:
            self.sys_btn_sdi6.configure(bg = "red")
        else:
            self.sys_btn_sdi6.configure(bg = "green")
        if sys_status & 0x200000:
            self.sys_btn_sdi7.configure(bg = "red")
        else:
            self.sys_btn_sdi7.configure(bg = "green")
        if sys_status & 0x400000:
            self.sys_btn_sdi8.configure(bg = "red")
        else:
            self.sys_btn_sdi8.configure(bg = "green")
        if sys_status & 0x800000:
            self.sys_btn_sdi9.configure(bg = "red")
        else:
            self.sys_btn_sdi9.configure(bg = "green")
        if sys_status & 0x1000000:
            self.sys_btn_osd0.configure(bg = "red")
        else:
            self.sys_btn_osd0.configure(bg = "green")
        if sys_status & 0x2000000:
            self.sys_btn_ser.configure(bg = "red")
        else:
            self.sys_btn_ser.configure(bg = "green")
        if sys_status & 0x4000000:
            self.sys_btn_vdu.configure(bg = "red")
        else:
            self.sys_btn_vdu.configure(bg = "green")
                                       
    def net_rcv_cb(self):
        self.netrcvrunning = True
        while self.netrcvrunning == True:
            rcv_bytes = self.client.recv(1500)
            if rcv_bytes.__len__() > 6:
                msgHeader = int.from_bytes(rcv_bytes[0:2], "little")
                dataLength = int.from_bytes(rcv_bytes[2:4], "little")
                ck = 0
                for data in rcv_bytes[0: (4 + dataLength) - 2]:
                    ck = ck + data
                ck = ck & 0xffff
                if ck != int.from_bytes(rcv_bytes[4 + dataLength -2:], "little"):
                    continue
                if dataLength == 50:
                    snd_bytes = bytearray(b'\x55\xaa\x04\x00\xff\x06\x08\x02')
                    self.client.send(snd_bytes)

                    maxRtpStream = int.from_bytes(rcv_bytes[4:5], "little")
                    currentActiveRtpStream = int.from_bytes(rcv_bytes[5:6], "little")
                    activeVidStreamStateMask = int.from_bytes(rcv_bytes[6:8], "little")
                    sdiOutputVidSource = rcv_bytes[8:18]
                    bitReportMask = int.from_bytes(rcv_bytes[18:22], "little")
                    unitSerialNo = rcv_bytes[22:42].decode()
                    elapsedTimer = int.from_bytes(rcv_bytes[42:46], "little")
                    version = "{0}.{1}.{2}".format(int.from_bytes(rcv_bytes[46:47], "little"), int.from_bytes(rcv_bytes[47:48], "little"), int.from_bytes(rcv_bytes[48:49], "little"))
                    messageRunningNo = int.from_bytes(rcv_bytes[49:50], "little")
                    cpu_loading = int.from_bytes(rcv_bytes[50:51], "little")
                    temperature = int.from_bytes(rcv_bytes[51:52], "little")

                    self.VI1_combo.current(sdiOutputVidSource[0])
                    self.VI2_combo.current(sdiOutputVidSource[1])
                    self.VI3_combo.current(sdiOutputVidSource[2])
                    self.VI4_combo.current(sdiOutputVidSource[3])
                    self.VI5_combo.current(sdiOutputVidSource[4])
                    self.VI6_combo.current(sdiOutputVidSource[5])
                    self.VI7_combo.current(sdiOutputVidSource[6])
                    self.VI8_combo.current(sdiOutputVidSource[7])

                    self.ckbox_var1.set(activeVidStreamStateMask & 0x1)
                    self.ckbox_var2.set((activeVidStreamStateMask >> 1)& 0x1)
                    self.ckbox_var3.set((activeVidStreamStateMask >> 2) & 0x1)
                    self.ckbox_var4.set((activeVidStreamStateMask >> 3) & 0x1)
                    self.ckbox_var5.set((activeVidStreamStateMask >> 4) & 0x1)
                    self.ckbox_var6.set((activeVidStreamStateMask >> 5) & 0x1)
                    self.ckbox_var7.set((activeVidStreamStateMask >> 6) & 0x1)
                    self.ckbox_var8.set((activeVidStreamStateMask >> 7) & 0x1)
                    self.ckbox_var9.set((activeVidStreamStateMask >> 8) & 0x1)
                    self.ckbox_var10.set((activeVidStreamStateMask >> 9) & 0x1)
                                      
                    self.show_sysbit_status(bitReportMask)

                    self.maxRtpStream.set("{0}".format(maxRtpStream))
                    self.currentActiveRtpStream.set("{0}".format(currentActiveRtpStream))
                    self.MessageRunningNo.set("{0}".format(messageRunningNo))
                    self.CPU_Loading.set("{0}".format(cpu_loading))
                    self.Temperature.set("{0}".format(temperature))
                    self.version.set(version)
                    self.SNo.set(unitSerialNo)
                    self.ttick.set("{0}".format(elapsedTimer))
                                       
                if dataLength == 28:
                    cmd = int.from_bytes(rcv_bytes[4:5], "little")
                    ack = int.from_bytes(rcv_bytes[5:6], "little")
                    print("cmd={0:X}, ack={1:X}".format(cmd, ack))
                    if cmd == 3:
                    	vduinfo = rcv_bytes[6:30]
                    	if int.from_bytes(vduinfo[0:1], "little") == 0:
                    		self.vdu_unitSerialNo.set("{0}".format(vduinfo[1:13].decode()))
                    		self.vdu_elapsedTimer.set("{0}".format(int.from_bytes(vduinfo[13:17], "little")))
                    		self.vdu_version.set("{0}.{1}.{2}".format(int.from_bytes(vduinfo[17:18], "little"), int.from_bytes(vduinfo[18:19], "little"), int.from_bytes(vduinfo[19:20], "little")))
                    		self.vdu_bitReportMask.set(int.from_bytes(vduinfo[20:24], "little"));
            else:
                self.net_btn_conn['text'] = "Connect"
                self.net_btn_conn['command'] = self.on_net_conn

                self.maxRtpStream.set("-")
                self.currentActiveRtpStream.set("-")
                self.MessageRunningNo.set("-")
                self.version.set("-")
                self.SNo.set("-")
                self.ttick.set("-")

                self.netrcvrunning = False

                self.client.close()
    def on_net_conn(self):        
        ipaddr = self.ip_editor.get()
        ipport = self.port_editor.get()
        port = int(ipport)
        print('ipaddr={0} port={1}'.format(ipaddr, port))
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.settimeout(1)
        try:
            self.client.connect((ipaddr, port))
        except socket.error as msg:
            print("connect error:{0}".format(msg))
            return

        self.net_btn_conn['text'] = "Disconnect"
        self.net_btn_conn['command'] = self.on_net_close

        self.netrcvtd = Thread(target=self.net_rcv_cb)
        self.netrcvtd.start()
	

    def on_net_close(self):
        self.net_btn_conn['text'] = "Connect"
        self.net_btn_conn['command'] = self.on_net_conn

        self.maxRtpStream.set("-")
        self.currentActiveRtpStream.set("-")
        self.MessageRunningNo.set("-")
        self.version.set("-")
        self.SNo.set("-")
        self.ttick.set("-")

        if self.netrcvrunning:
            self.netrcvrunning = False
            time.sleep(1)
            self.client.close()

    def VO1_send(self, event):
        insel = self.VI1_combo.current()
        self.VO_send(0, insel)

    def VO2_send(self, event):
        insel = self.VI2_combo.current()
        self.VO_send(1, insel)

    def VO3_send(self, event):
        insel = self.VI3_combo.current()
        self.VO_send(2, insel)

    def VO4_send(self, event):
        insel = self.VI4_combo.current()
        self.VO_send(3, insel)

    def VO5_send(self, event):
        insel = self.VI5_combo.current()
        self.VO_send(4, insel)

    def VO6_send(self, event):
        insel = self.VI6_combo.current()
        self.VO_send(5, insel)

    def VO7_send(self, event):
        insel = self.VI7_combo.current()
        self.VO_send(6, insel)

    def VO8_send(self, event):
        insel = self.VI8_combo.current()
        self.VO_send(7, insel)

    def VO_send(self, outsel, insel):
        snd_byte = bytearray(b'\x55\xaa\x0c\x00\x02')
        snd_byte.append(outsel)
        snd_byte.append(insel)
        snd_byte = snd_byte + bytearray(b'\xff\xff\xff\xff\xff\xff\xff')
        cksum = 0x55 + 0xaa + 0x0c + 0x00 + 0x02 + outsel + insel + 0xff + 0xff + 0xff + 0xff + 0xff + 0xff + 0xff
        cksum = cksum & 0xffff
        snd_byte.append(cksum&0xff)
        snd_byte.append((cksum >> 8) & 0xff)

        self.net_lock.acquire(timeout=5)
        try:
            self.client.send(snd_byte)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
		
        self.net_lock.release()
        
    def ckbox1_changed(self):
        self.ckbox_changed(0, self.ckbox_var1.get())

    def ckbox2_changed(self):
        self.ckbox_changed(1, self.ckbox_var2.get())

    def ckbox3_changed(self):
        self.ckbox_changed(2, self.ckbox_var3.get())

    def ckbox4_changed(self):
        self.ckbox_changed(3, self.ckbox_var4.get())

    def ckbox5_changed(self):
        self.ckbox_changed(4, self.ckbox_var5.get())

    def ckbox6_changed(self):
        self.ckbox_changed(5, self.ckbox_var6.get())

    def ckbox7_changed(self):
        self.ckbox_changed(6, self.ckbox_var7.get())

    def ckbox8_changed(self):
        self.ckbox_changed(7, self.ckbox_var8.get())

    def ckbox9_changed(self):
        self.ckbox_changed(8, self.ckbox_var9.get())

    def ckbox10_changed(self):
        self.ckbox_changed(9, self.ckbox_var10.get())

    def ckbox_changed(self, netno, onoff):
        snd_byte = bytearray(b'\x55\xaa\x0c\x00\x00')
        snd_byte.append(netno)
        snd_byte.append(onoff)
        snd_byte = snd_byte + bytearray(b'\xff\xff\xff\xff\xff\xff\xff')
        cksum = 0x55 + 0xaa + 0x0c + 0x00 + 0x00 + netno + onoff + 0xff + 0xff + 0xff + 0xff + 0xff + 0xff + 0xff
        cksum = cksum & 0xffff
        snd_byte.append(cksum&0xff)
        snd_byte.append((cksum >> 8) & 0xff)

        self.net_lock.acquire(timeout=5)
        try:
            self.client.send(snd_byte)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
		
        self.net_lock.release()

    def devinfo_read(self):
        sndstr = '$DEV,0*'
        snd_byte = bytearray(sndstr, 'utf-8')
        snd_byte.append(0x00)
        self.net_lock.acquire(timeout=5)
        try:
            self.client.send(snd_byte)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
		
        try:
            rcv_byte = self.client.recv(1500)
        except socket.error as msg:
            print("recv error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
        self.net_lock.release()
        
        self.net_rcv_cb(rcv_byte)

    def on_vdu_info(self):
        snd_byte = bytearray(b'\x55\xaa\x0c\x00\x03\x74\x53\xff\xff\xff\xff\xff\xff\xff')
        cksum = 0x55 + 0xaa + 0x0c + 0x00 + 0x03 + 0x74 + 0x53 + 0xff + 0xff + 0xff + 0xff + 0xff + 0xff + 0xff
        cksum = cksum & 0xffff
        snd_byte.append(cksum&0xff)
        snd_byte.append((cksum >> 8) & 0xff)

        self.net_lock.acquire(timeout=5)
        try:
            self.client.send(snd_byte)
        except socket.error as msg:
            print("send error:{0}".format(msg))
            self.on_net_close()
            self.net_lock.release()
            return
		
        self.net_lock.release()
        
         
if __name__ == "__main__":
    root = tk.Tk()
    mainwin = MainWidget(master = root)
    mainwin.mainloop()
