# -*- 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 time import json import socket, struct import sys import os import _thread as thread import copy import random import traceback from cprint import cprint if __name__ == "__main__": sys.stdout.write("\x1b]2;Nodescan\x07") def UDP_Socket(bind=False,ip='',port=6454): sock = False try: print(sys._getframe().f_code.co_name,"BIND",(ip,port,bind),"?") sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) if bind: sock.bind((ip, port)) print(sys._getframe().f_code.co_name,"BIND",(ip,port),"OK") except socket.error as e: cprint(" Socket 6454 ", "ERR: {0} ".format(e.args),color="red") sock = False return sock def ArtPoll(sock=None,ip="2.255.255.255",port=6454): print("ArtPoll",ip,port) if not sock: sock=UDP_Socket() #port=6454 #ip="2.255.255.255" PKG=b'Art-Net\x00\x00 \x00\x0e\x06\x00' print(" -> SEND:",[PKG]) sock.sendto(PKG,(ip,port)) # ArtPol / ping sock.close() time.sleep(1) def convert_mac(MAC): #MAC = data[201:201+6] _MAC = [] for x in MAC: #x = hex(ord(x))[2:] x = hex(x)[2:] x = x.rjust(2,"0") _MAC.append(x) _MAC = ":".join(_MAC) return _MAC def convert_bin(d): return bin(d)[2:].rjust(8,"0") def convert_ip(d): IP="[0,0,0,0]" _ip = [] try: _ip.append( d[0] ) _ip.append( d[1] ) _ip.append( d[2] ) _ip.append( d[3] ) IP = str(_ip) except:pass return IP def convert_to_hex(x,d): out = b"" try: a = struct.unpack(x, d)[0] #out = hex(a) out = "{0:#0{1}x}".format(a,6) except: pass return out mc = None def connect_memcache(): global mc try: import memcache mc = memcache.Client(['127.0.0.1:11211'], debug=0) clean_mc_artpoll() return 1 except Exception as e: cprint("Err connect_memcache",e,color="red") return 0 #thread.start_new_thread(connect_memcache, () ) connect_memcache() from datetime import datetime def clean_mc_artpoll(): if mc: INDEX="index-artpoll" mc.set(INDEX ,{}) clean_mc_artpoll() def update_mc_artpoll_index(key,val=""): try: INDEX="index-artpoll" _index = mc.get(INDEX) #print("A",_index) if type(_index) is type(None): _index = {} #print("A",_index) #now = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S') now = datetime.now().strftime('%Y-%m-%d %H:%M:%S') if key not in _index: _index[key] = [0,""] _index[key][0] += 1 _index[key][1] = now #val mc.set(INDEX ,_index) except Exception as e: cprint(sys._getframe().f_code.co_name,opcode,color="red") cprint(" memcach exception",e,color="red") def ArtPollRawStore(data,addr): opcode=artnet_get_opcode(data) cprint(" ",sys._getframe().f_code.co_name,opcode,color="green") if "ArtPoll" in opcode or "ArtPollReplay" in opcode: #print("PKG3",addr, opcode,len(data)) try: k = "{}:{}".format(addr[0],opcode[0]) x=mc.set(k, data) if not x: cprint(" ArtPollRawStore memcache.not Connected mc.set",k,x,color="red") connect_memcache() update_mc_artpoll_index(k,val="") except Exception as e: cprint(" ArtPollRawStore err:",e,color="red") def artnet_get_opcode(head): #print([head]) #[9:10]) opcode=0x0000 name ="unkown" try: opcode=hex(struct.unpack('H',"oem":'>H',"esta":" 0x6000, Low Byte first header.append(struct.pack('H', 14)) data = header[:] # NetSwitch data.append(struct.pack(' 0: content = content + b"\x00"*fill def create_ip(IP,content): #CONF["IP"] = [10,14+1] x=[] j=10 for i in IP.split("."): i = 33 _ip = struct.pack("B",int(i)) # content = content[:10+j]+ _ip + content[10+j:] content = inject(j,_ip,content) j+=1 x.append([_ip,i]) print(IP,x) def patch(content,index,patch): _patch = patch[:] if type(_patch) != bytes: _patch=bytes(_patch,"ascii") content[index:index+len(_patch)] = _patch def pad(val,count,fill="\x00"): return val.ljust(count,fill)[:count] def ip_to_byte(IP): out=[] for i in IP.split("."): out.append( int(i) ) return bytes(out) print() #IP="2.0.0.255" #create_ip(IP,content) #sock.sendto(content, (IP, port)) # ======================================= content = [0]*(282-42) # new empty PKG bytes([0,0,0,..]) patch(content,0, b"Art-Net\x00") patch(content,8, b"\x00\x21") # revers 0x2100 protocol hostname=os.popen("hostname").read().strip() #hostname+="0123456789012345678901234567890123456789012345678901234567890" sname=pad(hostname,18) # Short Name, len == 30 patch(content,26,sname) lname=pad("LibreLight "+hostname,64) # Long Name, len == 64 patch(content,26+18,lname) Report="LibreLight is ready CPU:40%" #Report+="12345678901234567890123456789012345123456789012345678901234567890" Report=pad(Report,64) patch(content,26+28+54,Report) ips=os_list_ip() mac= os_get_MAC() if "vmbr0" in mac: mac = mac["vmbr0"][0] print() print([mac]) print() mac=mac.replace(":","") print([mac]) if len(mac) == 12: mac=bytes.fromhex(mac) #content[201:] = mac patch(content,201,mac) #print([mac]) print("send" ,[content]) for IP in ["192.168.2.255","2.0.0.255","10.10.10.255"]: content2 = content[:] _IP = ip_to_byte(IP) patch(content2,10,_IP) content2 = bytes(content2) sock.sendto(content2, (IP, port)) print("send" ,[content]) def ArtNet_Server(verbose=0): print("start main()") sock = UDP_Socket(bind=True,ip='',port=6454) print(" -- loop --") while sock: data, addr = sock.recvfrom(300) cprint(" <- ArtNet_Server rcv:",[addr],color="cyan") ArtPollRawStore(data,addr) opcode="" if len(data) >= 10: opcode=convert_to_hex("