#! /usr/bin/python # -*- coding: utf-8 -*- """ Valid-License-Identifier: GPL-2.0-only SPDX-URL: https://spdx.org/licenses/GPL-2.0-only.html (c) 2012 micha@librelight.de """ import os import time import struct import sys import tkinter as Tkinter import _thread as thread import datetime import traceback from cprint import cprint import nodescan _file_path = "/opt/LibreLight/Xdesk/" sys.path.insert(0,"/opt/LibreLight/Xdesk/") title = "TK-ArtNet-Nodscaner" sys.stdout.write("\x1b]2;"+title+"\x07") def connect_mc(): mc = None try: import memcache mc = memcache.Client(['127.0.0.1:11211'], debug=0) #mc.set("dmx-1", [1]*512) except Exception as e: cprint("Exception",e,color="red") return mc mc = connect_mc() class LOCK_BUF(): def __init__(self): self.data = [] self.lock = thread.allocate_lock() def append(self,data): try: self.lock.acquire() self.data.append(data) finally: self.lock.release() def set(self,data): try: self.lock.acquire() self.data = data[:] finally: self.lock.release() def get(self): out = [] try: self.lock.acquire() out = self.data[:] finally: self.lock.release() return out node_list = LOCK_BUF() #[] csel = 0 def fill_form(event=None): cprint(sys._getframe().f_code.co_name,color="yellow") global node_list,csel clear_form() node_list2 = node_list.get() sel=0 try: csel = li_nodes.curselection()[0] except Exception as e: cprint("ERR no node selected in node-list:",e,color="red") return 0 print("+++",[csel,len(node_list2)]) try: sel = int(li_nodes.get(csel).split()[0])-1 except: cprint("ERR no leeding number in Listbox.line" ,color="red") return 0 if not node_list2: return 0 print("INFO: sel,node_list2",sel,len(node_list2)) e_ip.configure(state='normal') e_ip.insert("end",node_list2[sel]["IP"].replace("[","").replace("]","")) #e_ip.configure(state='readonly') e_ip_new.insert("end",node_list2[sel]["IP"].replace("[","").replace("]","")) e_mac.delete("0","end") e_mac.insert("end",node_list2[sel]["MAC"].replace("[","").replace("]","")) e_mac2.delete("0","end") e_mac2.insert("end",node_list2[sel]["MAC"].split(":")[-1]) #print("load",node_list2[sel]) e_lname.delete("0","end") e_lname.insert("end",node_list2[sel]["lname"]) e_sname.delete("0","end") e_sname.insert("end",node_list2[sel]["sname"]) e_artnet_uni1.delete("0","end") univ = "0" try: if node_list2[sel]["PortTypes"][0] == "@": univ = ord(node_list2[sel]["SwIn"][0:1]) else: univ = ord(node_list2[sel]["SwOut"][0:1]) except Exception as e: cprint("load Exception",e,color="red") MSG["text"] = e MSG["bg"] = "red" e_artnet_uni1.insert("end",univ) def clear_form(): cprint(sys._getframe().f_code.co_name,color="yellow") e_ip.configure(state='normal') e_ip.delete("0","end") e_ip.configure(state='readonly') e_ip_new.delete("0","end") e_mac.delete("0","end") e_mac2.delete("0","end") e_lname.delete("0","end") e_sname.delete("0","end") e_artnet_uni1.delete("0","end") def main_loop(): while 1: try: poll() except Exception as e: print() cprint("Err main()",e,color="red") cprint(traceback.format_exc(),color="red") cprint("="*20,color="red") time.sleep(3) def poll(delay=1,ip=""): print() cprint(sys._getframe().f_code.co_name,"="*30,color="yellow") ip = "2.255.255.255" if not ip: cprint("err poll() no ip !",color="red") return log_text.insert("end", "ArtNetPoll -> "+str(ip)+"\n") log_text.yview("end") nodescan2.ArtPoll(ip=ip) nodes = load_node_list() refresh_node_list(nodes) import nodescan2 def load_node_list(): cprint(sys._getframe().f_code.co_name,"------------",color="yellow") global node_list,Scrollbar,mc #li_nodes.delete("0","end") ips = nodescan2.os_list_ip() #example nodes = [] if not mc: cprint("mc (memcached) is none",color="red") mc = connect_mc() node_list.set([]) return nodes = [] artpoll = mc.get("index-artpoll") if not artpoll: cprint("mc.get('index-artpoll') is none ",color="red") mc = connect_mc() node_list.set([]) return for k in artpoll: data = mc.get(k) opcode= nodescan2.artnet_get_opcode(data) if "ArtPollReplay" in opcode: # != '0x2100': #OpPollReplay node = nodescan2.ArtNet_decode_pollreplay(data) s = artpoll[k][1] s = datetime.datetime.strptime(s, '%Y-%m-%d %H:%M:%S') s = s.timestamp() node["UPDATESTAMP"] = s node["BOOT"] = 0 node["REFRESHSTAMP"] = s node["LASTPING"] = 0 #node1 = nodescan2.ArtNet_decode_pollreplay(data) nodes.append(node) ok=0 for n in nodes: if n not in node_list.get(): node_list.append(n) ok=1 return node_list old_node_listbox = [] def refresh_node_list(nodes): cprint(sys._getframe().f_code.co_name,color="yellow") global csel,old_node_listbox node_nr = 1 nodesB = {} for node in node_list.get(): #nodes: k = node["MAC"] nodesB[k] = node if not nodesB: li_nodes.delete("0","end") li_nodes.insert("end"," - none -") k_sort = list(nodesB.keys()) k_sort.sort() node_list.set([]) # =[] for k in k_sort: node_list.append(nodesB[k]) out = [] for k in k_sort: print(" ",k) node = nodesB[k] txt = str(node_nr).rjust(3," ") +" " + "-"*30 bg="" out.append({"txt":txt,"bg":bg}) bg = "white" #lightgrey" fg = "" #bg = "blue" #fg = "white" txt = str(node_nr).rjust(3," ") +" L-Name:"+ node["lname"] out.append({"txt":txt,"bg":bg,"fg":fg}) #bg = "blue" #fg = "white" txt = str(node_nr).rjust(3," ") +" S-Name:"+ node["sname"] out.append({"txt":txt,"bg":bg,"fg":fg}) bg = "" txt = str(node_nr).rjust(3," ") +" "+ node["IP"] if "PortTypes" in node: #print("-----", node["PortTypes"], node["PortTypes"][0] ,node["PortTypes"][0] == b"@") if not node["PortTypes"]: pass if node["PortTypes"][0] == 64: #b"@": txt += " DMX-in" bg ="yellow" else: txt += " DMX-out" bg ="lightgreen" out.append({"txt":txt,"bg":bg}) txt = str(node_nr).rjust(3," ") + " UNIVERS OUT="+ str(ord(node["SwOut"][0:1]))+" IN="+ str(ord(node["SwIn"][0:1])) bg = "" out.append({"txt":txt,"bg":bg}) txt = str(node_nr).rjust(3," ") +" MAC:"+ node["MAC"] bg = "" out.append({"txt":txt,"bg":bg}) txt = "" bg = "" try: last_change=time.time()-float(node["UPDATESTAMP"]) timeline = "" timeline += " CHANGE:%0.1f"% (last_change) REFRESHSTAMP = time.time()-float(node["REFRESHSTAMP"]) timeline +=" PING:%0.1f"% REFRESHSTAMP txt = str(node_nr).rjust(3," ") +timeline if last_change > 20: bg="ORANGE" except Exception as e: txt = str(e)+"\n" bg = "red" out.append({"txt":txt,"bg":bg}) txt="" bg = "" try: if node["BOOT"]: BOOT = time.time()-float(node["BOOT"]) else: BOOT = 0 timeline =" BOOT:%0.1f"% BOOT txt = str(node_nr).rjust(3," ") +timeline +" sec" bg = "" except Exception as e: txt = str(e)+"\n" bg = "red" out.append({"txt":txt,"bg":bg}) node_nr += 1 out.append({"txt":"","bg":"white"}) # insert nodes in listbox if out == old_node_listbox: return old_node_listbox = out[:] if out: li_node_scroll = li_nodes.yview() li_nodes.delete("0","end") for i in out: #print("list:",i) li_nodes.insert("end",i["txt"]) bg=i["bg"] fg="black" if "fg" in i: fg=i["fg"] if not bg: bg = "lightgrey" bg = "" ##ddd" li_nodes.itemconfig("end", bg=bg,fg=fg) print(csel) #li_nodes.yview(li_node_scroll ) li_nodes.selection_set(csel) def get_form(event=None): cprint(sys._getframe().f_code.co_name,color="yellow") x = e_ip_new.get().replace("[","").replace("]","") x = x.strip() x = x.replace(" ","") x = x.split(",") ip2 = ".".join(x) ip = e_ip.get() ip = ip.replace(" ","") ip = ip.replace(",",".") MASK = variable.get() #e_mask_new.get() #new_mac = b"CMD MAC6 " + struct.pack(" "+str(form["IP2"])+" univ:"+str(form["univ"])+" v="+ str(val)+"\n") log_text.yview("end") artnet = an.ArtNetNode(to=form["IP2"],univ=form["univ"],port=4566) artnet.send([val]*512,port=6454) print(artnet._data) return cb def _send_cmd(event=None,cmd=""): cprint(sys._getframe().f_code.co_name,color="yellow") #cmd = e_cmd.get() #"CMD DMX STORE " cmd = cmd.split(" ") value = cmd[-1] try: value = struct.pack("",width=10,command=poll,font=font2) log_text.configure(bg="#0f0") scrollbar = Tkinter.Scrollbar(cframe) scrollbar.pack(side=Tkinter.LEFT, fill="y") li_nodes = Tkinter.Listbox(cframe,exportselection=0,width=35,font=font1,height=16) li_nodes.pack(side="left",expand=0,fill="y") li_nodes.bind("",fill_form ) li_nodes.config(yscrollcommand=scrollbar.set) scrollbar.config(command=li_nodes.yview) eframe = Tkinter.Frame(cframe) eframe.pack(side="left",expand=0,fill="y") eframe1 = Tkinter.Frame(cframe) eframe1.pack(side="left",expand=0,fill="y") # ---------------------------------------------- line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") x=Tkinter.Label(line_frame,text=" ",font=font2,width=6) c= Tkinter.Label(line_frame,text=" ",font=font1,width=30,anchor="w") c.pack(side="left",expand=0,fill="y") # ---------------------------------------------- # TK-FORM # ---------------------------------------------- line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") x=Tkinter.Label(line_frame,text="MSG:",font=font3,width=6) x.pack(side="left",expand=0,fill="y") x.configure(bg="darkgrey") MSG = Tkinter.Label(line_frame,text="xxx",font=font1,width=60,anchor="w") MSG.pack(side="left",expand=0,fill="y") MSG.configure(bg="darkgrey") # ---------------------------------------------- line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") c= Tkinter.Label(line_frame,text=" ",font=font120,width=30,anchor="w") c.pack(side="left",expand=0,fill="y") # ---------------------------------------------- line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="OLD IP:",font=font3,width=6).pack(side="left",expand=0,fill="y") e_ip = Tkinter.Entry(line_frame,font=font20,width=16,state="disabled") e_ip["bg"] = "lightgrey" e_ip.pack(side="left") log_text = Tkinter.Button(line_frame,text="clean",font=font2,relief="flat",command=clear_form) log_text.pack(side="left",expand=0) #log_text = Tkinter.Button(line_frame,width=14,font=font3) #log_text.pack(side="left",expand=1) # ---------------------------------------------- line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") e_ip_label = Tkinter.Label(line_frame,text=" IP:",font=font3,width=6) e_ip_label.pack(side="left",expand=0,fill="y") e_ip_new = Tkinter.Entry(line_frame,font=font20,width=16) e_ip_new.bind("", set_ip ) e_ip_new.bind("", set_ip) e_ip_new.bind("", set_ip) e_ip_new.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") variable = Tkinter.StringVar(root) variable.set("255.0.0.0") # default value Tkinter.Label(line_frame,text="MASK:",font=font3,width=6).pack(side="left",expand=0,fill="y") e_mask_new = Tkinter.OptionMenu(line_frame, variable,"255.255.255.0","255.0.0.0") #,width=10) e_mask_new.configure(font=("Helvetica", 12)) e_mask_new.configure(width=13) e_mask_new["bg"] = "#fff" e_mask_new.pack(side="left") #e=Tkinter.Label(line_frame,text="") #e.configure(width=1) #e.pack(side="left") log_text = Tkinter.Button(line_frame,text="SEND TO NODE",bg="lightgreen",command=set_ip,width=13,font=font1) log_text.pack(side="left",expand=0) #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="MAC:",font=font3,width=6).pack(side="left",expand=0,fill="y") e_mac = Tkinter.Entry(line_frame,width=13,font=font20) e_mac.pack(side="left") e_mac["bg"] = "lightgrey" e_mac2 = Tkinter.Entry(line_frame,width=3,font=font20) e_mac2.pack(side="left") e_mac2.config(bg="orange") e_mac2.bind("", send_mac ) e_mac2.bind("", send_mac) Tkinter.Button(line_frame,text="SEND TO NODE !",bg="orange",command=send_mac,width=14,font=font1).pack(side="left",expand=0) # ---------------------------------------------- line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") c= Tkinter.Label(line_frame,text=" ",font=font120,width=30,anchor="w") c.pack(side="left",expand=0,fill="y") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="DMX:",font=font3,width=6).pack(side="left",expand=0,fill="y") b_set_node_pin = Tkinter.Button(line_frame,text="HW-PIN",bg="orange",command=set_node_pin,width=5,font=font3) b_set_node_pin.pack(side="left",expand=0) b_set_node_in = Tkinter.Button(line_frame,text="IN",bg="orange",command=set_node_in,width=2,font=font3) b_set_node_in.pack(side="left",expand=0) b_set_node_out = Tkinter.Button(line_frame,text="OUT",bg="orange",command=set_node_out,width=2,font=font3) b_set_node_out.pack(side="left",expand=0) #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="CMD",font=font3,width=6).pack(side="left",expand=0,fill="y") e_cmd = Tkinter.Entry(line_frame,font=font3,width=16) CMD="" #DMX OUT STORE" c=SEND_CMD(CMD,entry=e_cmd) e_cmd.bind("", c ) e_cmd.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="LName",font=font3,width=6).pack(side="left",expand=0,fill="y") e_lname = Tkinter.Entry(line_frame,font=font3,width=16) e_lname.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="SName",font=font3,width=6).pack(side="left",expand=0,fill="y") e_sname = Tkinter.Entry(line_frame,font=font3,width=16) e_sname.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="ArtNet",font=font3,width=6).pack(side="left",expand=0,fill="y") Tkinter.Label(line_frame,text="SUB:",font=font3,width=4).pack(side="left",expand=0,fill="y") e_artnet_uni1 = Tkinter.Entry(line_frame,font=font3,width=4,state="disabled") e_artnet_uni1.pack(side="left") Tkinter.Label(line_frame,text="NET:",font=font3,width=4).pack(side="left",expand=0,fill="y") e_artnet_uni1 = Tkinter.Entry(line_frame,font=font3,width=4,state="disabled") e_artnet_uni1.pack(side="left") Tkinter.Label(line_frame,text="UNI:",font=font3,width=4).pack(side="left",expand=0,fill="y") e_artnet_uni1 = Tkinter.Entry(line_frame,font=font3,width=4) e_artnet_uni1.pack(side="left") Tkinter.Button(line_frame,text="send ArtAddr",bg="lightgreen",command=send_artaddr,width=14,font=font1).pack(side="left",expand=0) #-------------------------------------------- line log_text = Tkinter.Text(eframe,width=10,font=font2) log_text.pack(side="top",expand=1,fill="x") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") e = Tkinter.Button(line_frame,text="DMX:0",font=font3,width=16,command=send_artdmx(0),bg="orange") e.pack(side="left") line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") e = Tkinter.Button(line_frame,text="DMX:127",font=font3,width=16,command=send_artdmx(127),bg="orange") e.pack(side="left") line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") e = Tkinter.Button(line_frame,text="DMX:255",font=font3,width=16,command=send_artdmx(255),bg="orange") e.pack(side="left") line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") e = Tkinter.Label(line_frame,text="",width=16) e.pack(side="left") line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="CMD",font=font3,width=6).pack(side="left",expand=0,fill="y") e_cmd2 = Tkinter.Entry(line_frame,font=font3,width=16) CMD="- DMX ERASE" c=SEND_CMD(CMD) e_cmd2.insert("end",CMD) e_cmd2.bind("", c ) e_cmd2.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="CMD",font=font3,width=6).pack(side="left",expand=0,fill="y") e_cmd3 = Tkinter.Entry(line_frame,font=font3,width=16) CMD="DMX OUT STORE" c=SEND_CMD(CMD) e_cmd3.insert("end",CMD) e_cmd3.bind("", c ) e_cmd3.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="CMD",font=font3,width=6).pack(side="left",expand=0,fill="y") e_cmd4 = Tkinter.Entry(line_frame,font=font3,width=16) CMD="DMX OUT SET 2" c=SEND_CMD(CMD) e_cmd4.insert("end",CMD) e_cmd4.bind("", c ) e_cmd4.pack(side="left") #-------------------------------------------- line line_frame = Tkinter.Frame(eframe1) line_frame.pack(side="top",expand=0,fill="x") Tkinter.Label(line_frame,text="CMD",font=font3,width=6).pack(side="left",expand=0,fill="y") e_cmd5 = Tkinter.Entry(line_frame,font=font3,width=16) CMD="REBOOT" c=SEND_CMD(CMD) e_cmd5.insert("end",CMD) e_cmd5.bind("", c ) e_cmd5.pack(side="left") def network_listenet(): cprint(sys._getframe().f_code.co_name,color="yellow") log_text.insert("end", "log:\n" ) while 1: #print(".") if nodescan2.node_cmd_buf_list: msg = str(nodescan2.node_cmd_buf_list) print("read_cmd_buf msg",msg) nodescan2.node_cmd_buf_list = [] stamp = str(time.time())+"\n" stamp = time.strftime("%Y-%m-%d %X\n") log_text.insert("end",stamp) log_text.insert("end", msg +"\n") log_text.see("end") time.sleep(0.1) def tk_loop(): while 1: root.update_idletasks() time.sleep(1) def main(): cprint(sys._getframe().f_code.co_name,color="yellow") thread.start_new_thread(main_loop, () ) #thread.start_new_thread(nodescan.node_cmd_recive, () ) #thread.start_new_thread(network_listenet, () ) thread.start_new_thread(tk_loop, () ) thread.start_new_thread(nodescan2.ArtNet_Server,()) #nodescan.bind_cmd_node() main() root.mainloop()