_console.py 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405
  1. #! /usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. This file is part of LibreLight.
  5. LibreLight is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, version 2 of the License.
  8. LibreLight is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with LibreLight. If not, see <http://www.gnu.org/licenses/>.
  14. (c) 2012 micha@librelight.de
  15. """
  16. import sys
  17. import time
  18. import json
  19. import zlib
  20. rnd_id = ""
  21. rnd_id += " Beta 22.02 "
  22. import subprocess
  23. import tool.git as git
  24. rnd_id += git.get_all()
  25. if "__file__" in dir():
  26. sys.stdout.write("\x1b]2;"+str(__file__)+" "+rnd_id+"\x07") # terminal title
  27. else:
  28. sys.stdout.write("\x1b]2;"+str("__file__")+" "+rnd_if+"\x07") # terminal title
  29. __run_main = 0
  30. if __name__ == "__main__":
  31. __run_main = 1
  32. else:
  33. import __main__
  34. print(dir())
  35. if "unittest" not in dir(__main__):
  36. __run_main = 1
  37. import time
  38. import socket
  39. import struct
  40. import sys
  41. import random
  42. import math
  43. from collections import OrderedDict
  44. import lib.zchat as chat
  45. import lib.ArtNetNode as ANN
  46. import _thread as thread
  47. #thread.start_new_thread
  48. import lib.motion as motion
  49. #idmx = [0]*512 # incremental dmx
  50. dmx = [0]*512 # absolute dmx data
  51. gcolor = 1
  52. def cprint(*text,color="blue",space=" ",end="\n"):
  53. color = color.lower()
  54. #return 0 #disable print dbg
  55. if not gcolor:
  56. print(text)
  57. return 0
  58. if color == "green":
  59. txt = '\033[92m'
  60. elif color == "red":
  61. txt = '\033[0;31m\033[1m'
  62. elif color == "yellow":
  63. txt = '\033[93m\033[1m'
  64. elif color == "cyan":
  65. txt = '\033[96m'
  66. else:
  67. txt = '\033[94m'
  68. for t in text:
  69. txt += str(t ) +" "
  70. #HEADER = '\033[95m'
  71. #OKBLUE = '\033[94m'
  72. #OKCYAN = '\033[96m'
  73. #OKGREEN = '\033[92m'
  74. #WARNING = '\033[93m'
  75. #FAIL = '\033[91m'
  76. #ENDC = '\033[0m'
  77. #BOLD = '\033[1m'
  78. #UNDERLINE = '\033[4m'
  79. txt += '\033[0m'
  80. print(txt,end=end)
  81. #return txt
  82. def artnet_loop():
  83. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=12)
  84. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=0)
  85. artnet = ANN.ArtNetNode(to="10.10.10.255",univ=0)
  86. #artnet = ANN.ArtNetNode(to="2.0.0.255",univ=0)
  87. #artnet = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  88. #dmx[205] = 255 #205 BLUE
  89. artnet.dmx= dmx #[0]*512
  90. artnet.send()
  91. while 1:
  92. #artnet._test_frame()
  93. artnet.next()
  94. time.sleep(0.001)
  95. class CLOCK():
  96. def __init__(self):
  97. self.__time = 0
  98. self.__start = time.time() # only for debugging
  99. self.__tick = 0.01 # incremental timer drift's on highe cpu load ?
  100. def time(self):
  101. return self.__time
  102. def get_drift(self):
  103. run_time = time.time() - self.__start
  104. tick_time = self.__time # * self.__tick
  105. print( "runtime:{:0.2f} tick_timer:{:0.2f} drift:{:0.2f}".format(run_time,tick_time,run_time-tick_time))
  106. def loop(self):
  107. while 1:
  108. self.__time +=self.__tick
  109. #if int(self.__time*100)/10. % 10 == 0:# self.__time % 2 == 0:
  110. # print( self.get_drift())
  111. #print(self.__time)
  112. #for i in range(10):
  113. time.sleep(self.__tick)
  114. class CLOCK_REAL():
  115. def __init__(self):
  116. self.__time = 0
  117. self.__start = time.time() # only for debugging
  118. self.__tick = 0.001 # incremental timer drift's on highe cpu load ?
  119. def time(self):
  120. self.__time = time.time()
  121. return self.__time
  122. def get_drift(self):
  123. run_time = time.time() - self.__start
  124. tick_time = self.__time # * self.__tick
  125. print( "runtime:{:0.2f} tick_timer:{:0.2f} drift:{:0.2f}".format(run_time,tick_time,run_time-tick_time))
  126. def loop(self):
  127. pass
  128. #clock = CLOCK()
  129. clock = CLOCK_REAL()
  130. if __run_main:
  131. thread.start_new_thread(clock.loop,())
  132. class Fade():
  133. def __init__(self,start,target,ftime,clock,delay=0):
  134. #print("init Fade ",start,target,ftime,clock)
  135. if delay < 0:
  136. delay = 0.0001
  137. if ftime <= 0:
  138. ftime = 0.0001
  139. clock += delay
  140. self.__delay = delay
  141. self.__clock = clock
  142. self.__clock_curr = clock
  143. self.__ftime = ftime
  144. self.__start = start
  145. self.__last = start
  146. self.__target = target
  147. self.run = 1
  148. self.end = 0
  149. self.off = 0
  150. #print("INIT", str(self) )
  151. def __str__(self):
  152. return self.__repr__()
  153. def __repr__(self):
  154. return "<FADE Next:{:0.2f} from:{:0.2f} to:{:0.2f} ft:{:0.2f} Clock:{:0.2f} run:{} delay:{:0.2f}>".format(
  155. self.__last, self.__start,self.__target,self.__ftime,self.__clock_curr,self.run,self.__delay )
  156. def next(self,clock=None):
  157. if self.__ftime <= 0 and self.__delay <= 0:
  158. self.__last = self.__target
  159. self.end = 1
  160. self.run = 0
  161. if type(clock) is float or type(clock) is int:#not None:
  162. self.__clock_curr = clock
  163. if self.__target > self.__start:
  164. if self.__last >= self.__target:
  165. self.run = 0
  166. self.end = 1
  167. return self.__target
  168. else:
  169. if self.__last <= self.__target:
  170. self.run = 0
  171. self.end = 1
  172. return self.__target
  173. current = (self.__clock - self.__clock_curr) / self.__ftime
  174. length = self.__start - self.__target
  175. self.__last = self.__start+ length*current
  176. #if self.__last < 0:
  177. # self.__last = 0
  178. #if self.__last > 255:
  179. # self.__last = 255
  180. self.run = 1
  181. return self.__last
  182. def ctl(self,cmd="",value=None): # if x-fade cmd="%" value=50
  183. # start,stop,fwd,bwd,revers
  184. pass
  185. class _MASTER():
  186. def __init__(self,name="None"):
  187. self.__data = {}
  188. self.name = name
  189. def val(self,name,value=None):
  190. _value = 100 #%
  191. name = str(name)
  192. if name not in self.__data:
  193. self.__data[name] = 100
  194. _value = self.__data[name]
  195. if value is not None:
  196. if _value != value:
  197. print(self.name,"CHANGE MASTER:",name,"from:",_value,"to:",value)
  198. self.__data[name] = value
  199. _value = self.__data[name]
  200. return _value /100.
  201. exec_size_master = _MASTER("EXEC-SIZE")
  202. exec_speed_master = _MASTER("EXEC-SPEED")
  203. exec_offset_master = _MASTER("EXEC-OFFSET")
  204. size_master = _MASTER("SIZE")
  205. speed_master = _MASTER("SPEED")
  206. exe_master = []
  207. exe_master.append({"SIZE":100,"SPEED":100,"id":12,"link-ids":[2]})
  208. class MASTER_FX():
  209. def __init__(self):
  210. #cprint(self,"MASTER_FX INIT !",color="green")
  211. self.__data = []
  212. self.__ok = []
  213. self.i=0
  214. self.old_offsets = []
  215. self.offsets = []
  216. self.count = -1
  217. self.init = 10
  218. def add(self,fx):
  219. if fx not in self.__data:
  220. #cprint(self,"ADD TO MASTER !",color="green")
  221. self.__data.append(fx)
  222. info = fx._get_info()
  223. #cprint(self,"ADD" ,info,color="green")
  224. offset = 0
  225. if "offset" in info:
  226. offset = info["offset"]
  227. self.old_offsets.append(offset)
  228. self.offsets.append(offset)
  229. if "xtype" in info:
  230. if info["xtype"] == "rnd":
  231. self._shuffle()
  232. #self.init += 1
  233. def _shuffle(self):
  234. #cprint(self,"REORDER RANDOM !",color="green")
  235. #self.init = 0
  236. #cprint(self.old_offsets)
  237. random.seed(1000)
  238. random.shuffle(self.old_offsets)
  239. #cprint(self.old_offsets)
  240. def _init(self):
  241. self._shuffle()
  242. #self.offsets = []
  243. for i,v in enumerate(self.old_offsets):
  244. offset = self.old_offsets[i]
  245. self.offsets[i] = offset
  246. self.init = 0
  247. def next(self,child):
  248. i = self.__data.index(child)
  249. offset = self.old_offsets[i]
  250. self.offsets[i] = offset
  251. return offset
  252. #for i,v in enumerate(self.old_offsets):
  253. # offset = self.old_offsets[i]
  254. # self.offsets[i] = offset
  255. def get(self,child,count):
  256. offset = 0
  257. if child not in self.__data:
  258. return offset
  259. if self.init:
  260. self._init()
  261. idx = self.__data.index(child)
  262. if (self.count != count and idx == 0 ) or self.init == 0:
  263. self.init = 1
  264. self._shuffle()
  265. #print( count)
  266. self.count=count
  267. idx = self.__data.index(child)
  268. offset = self.offsets[idx]
  269. return offset
  270. class FX():
  271. def __init__(self,xtype="sinus",size=10,speed=10,invert=0,width=100,start=0,offset=0,base="",clock=0,master=None,master_id=0):
  272. self.__xtype=xtype
  273. self.__size = size
  274. self.__start = start
  275. self.__master_id = master_id
  276. if width > 200:
  277. width = 200
  278. if width <= 0:
  279. width = 1
  280. self.__fade_in_master = 0
  281. self.__width = width
  282. self.__invert = invert
  283. self.__base = base
  284. self.__speed = speed
  285. self.__offset = offset
  286. self.__clock = clock
  287. self.__clock_curr = clock
  288. self.__clock_delta = 0
  289. self.__clock_old = self.__clock_curr
  290. self.out = 0
  291. self.old_v = -1
  292. self.run = 1
  293. self.count = -1
  294. self.__angel = self.__clock_curr*360%360
  295. if master is None:
  296. cprint(master, "MASTER_FX ERR",master,color="red")
  297. self.__master = MASTER_FX()
  298. self.__master.add(self)
  299. else:
  300. #cprint( "MASTER_FX OK",master,color="red")
  301. self.__master = master
  302. self.__master.add(self)
  303. if self.__xtype == "rnd":
  304. self.__offset = self.__master.get(self,-2)
  305. self.__offset = self.__master.next(self)#,count)
  306. self._exec_id = None
  307. self.next()
  308. #print("init FX",self)
  309. def exec_id(self,_id=None):
  310. if type(_id) is not type(None):
  311. self._exec_id = str(_id)
  312. return self._exec_id
  313. def _get_info(self):
  314. #print("self.__offset",self.__offset)
  315. return {"offset":self.__offset,"xtype":self.__xtype}
  316. #return self.next(),self.__xtype, self.__size,self.__speed,self.__angel, self.__base,self.__clock_curr,self.run
  317. def __str__(self):
  318. return self.__repr__()
  319. def __repr__(self):
  320. return "<FX Next:{:0.2f} xtype:{} Size:{:0.2f} Speed:{:0.2f} ang:{:0.2f} base:{} Clock:{:0.2f} run:{} EXEC:{}>".format(
  321. self.next(), self.__xtype, self.__size, self.__speed, self.__angel
  322. , self.__base, self.__clock_curr, self.run, self._exec_id )
  323. def next(self,clock=None):
  324. if type(clock) is float or type(clock) is int:#not None:
  325. self.__clock_curr = clock
  326. d = (self.__clock_curr - self.__clock_old)
  327. #print()
  328. #print("A",d)
  329. m1 = ( speed_master.val(self.__master_id)) # global speed-master
  330. #print("B {:0.4}".format(m1))
  331. m2 = ( exec_speed_master.val(self._exec_id)) # exec start by 0
  332. #print("C {:0.4}".format(m2))
  333. shift = 0
  334. m = (m1 * m2) -1
  335. shift += d * m
  336. #print("D",shift)
  337. self.__clock_delta += shift
  338. #print(self.__clock_delta )
  339. self.__clock_old = self.__clock_curr
  340. t = self.__clock_curr
  341. t += self.__clock_delta
  342. t *= self.__speed / 60
  343. offset2 = self.__offset
  344. offset2 *= exec_offset_master.val(self._exec_id)
  345. #t += self.__offset / 100 #255 #1024 #255
  346. t += offset2 / 100
  347. t += self.__start / 1024 #255
  348. #t = t*speed_master.val(self.__master_id)
  349. tw = t%1
  350. count = t//1
  351. t = t * (100/self.__width)
  352. if tw > self.__width/100:
  353. t = 1
  354. self.__angel = t%1*360
  355. t = t%1
  356. rad = math.radians(self.__angel)
  357. v=0
  358. out = 0
  359. base = 0
  360. size = self.__size
  361. if self.__base == "+": # add
  362. base = size/2
  363. elif self.__base == "-": # sub
  364. base = size/2*-1
  365. if self.__xtype == "sinus":
  366. v = math.sin( rad )
  367. v/=2
  368. elif self.__xtype == "cosinus":
  369. v = math.cos( rad )
  370. if self.__base == "+": # add
  371. size *= -1
  372. v/=2
  373. elif self.__xtype == "rnd":
  374. #base = 0
  375. if self.__angel > 90 and self.__angel <=270:
  376. v=1
  377. else:
  378. v=0
  379. #if count != self.count and v: # % 2 == 0:#!= self.count:
  380. # #self.__offset = random.randint(0,1024)# /1024
  381. # self.__master._shuffle()
  382. if count != self.count and v == 0: # and v: # % 2 == 0:#!= self.count:
  383. self.__master.next(self)#,count)
  384. #self.__master.next(self)#,count)
  385. self.__offset = self.__master.get(self,count)
  386. base = 0
  387. if self.__base == "-": # sub
  388. if self.__invert:
  389. v = 1-v
  390. #base = -size
  391. size *=-1
  392. v *=-1
  393. elif self.__base == "+": # sub
  394. if self.__invert:
  395. v = v-1
  396. else:
  397. v = (t%1-0.5)
  398. elif self.__xtype == "on":
  399. #base = 0
  400. if self.__angel > 90 and self.__angel <=270:
  401. v=1
  402. else:
  403. v=0
  404. base = 0
  405. if self.__base == "-": # sub
  406. if self.__invert:
  407. v = 1-v
  408. #base = -size
  409. size *=-1
  410. v *=-1
  411. elif self.__base == "+": # sub
  412. if self.__invert:
  413. v = v-1
  414. else:
  415. v = (t%1-0.5)
  416. elif self.__xtype == "ramp" or self.__xtype == "ramp":
  417. v = (t%1)
  418. base = 0
  419. if self.__base == "-": # sub
  420. if self.__invert:
  421. v = 1-v
  422. #base = -size
  423. size *=-1
  424. v *=-1
  425. elif self.__base == "+": # sub
  426. if self.__invert:
  427. v = v-1
  428. else:
  429. v = (t%1-0.5)
  430. elif self.__xtype == "ramp2" or self.__xtype == "bump2":
  431. v = (t%1)
  432. v = 1-v
  433. if v == 1:
  434. v=0
  435. base = 0
  436. if self.__base == "-": # sub
  437. if self.__invert:
  438. v = 1-v
  439. #base = -size
  440. size *=-1
  441. v *=-1
  442. elif self.__base == "+": # sub
  443. if self.__invert:
  444. v = v-1
  445. else:
  446. v = (t%1-0.5)
  447. elif self.__xtype == "fade":
  448. x = t * 2
  449. if x > 1:
  450. x = 2-x
  451. x -= 0.5
  452. v = x*2
  453. #base /= 2
  454. #base *=2
  455. if self.__base == "+": # add
  456. pass#base /= 2
  457. else:
  458. v *= -1
  459. v/=2
  460. if self.__invert:
  461. v *=-1
  462. #if self.__fade_in_master < 255:
  463. # self.__fade_in_master += v*size
  464. out = v *size +base
  465. self.out = out
  466. self.count = count
  467. out = out * size_master.val(self.__master_id) # master
  468. out = out * exec_size_master.val(self._exec_id) # master
  469. #* (self.__fade_in_master /255.)
  470. return out
  471. class DMXCH(object):
  472. def __init__(self,dmx=-1):
  473. self._base_value = 0
  474. self._fade = None
  475. self._fx = [None,None] # None
  476. self._fx_value = 0
  477. self._dmx = dmx
  478. self._dmx_fine = 0
  479. self._fix_id = 0
  480. self._v_master_id=0
  481. self._flash = None
  482. self._flash_fx = None
  483. self._flash_fx_value = 0
  484. self._last_val = None
  485. self._exec_ids = [None,None,None,None] # go, go-fx, flash, flash-fx
  486. #self.next(clock)
  487. #print("init",self)
  488. def fade(self,target,ftime=0,clock=0,delay=0):
  489. if target != self._base_value:
  490. try:
  491. target = float(target)
  492. self._fade = Fade(self._base_value,target,ftime=ftime,clock=clock,delay=delay)
  493. #self._fade.next()
  494. #self._fade.next()
  495. except Exception as e:
  496. print( "Except:fade",e,target,ftime,clock)
  497. self.next(clock)
  498. #print("init fade",self)
  499. def fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="", clock=0,master=None):
  500. #print("DMXCH.fx",[self,xtype,size,speed,start,offset,base, clock])
  501. self._fx[0] = self._fx[1]
  502. if str(xtype).lower() == "off":
  503. fx_value = self._fx_value
  504. if fx_value != 0:
  505. cprint("???????______ FX OFF AS FADE",fx_value,0,255)
  506. self._fx[1] = Fade(fx_value,0,ftime=0.5,clock=clock)
  507. else:
  508. self._fx[1] = None
  509. self._fx_value = 0
  510. else:
  511. self._fx[1] = FX(xtype=xtype,size=size,speed=speed,invert=invert
  512. ,width=width,start=start,offset=offset,base=base
  513. ,clock=clock,master=master,master_id=1)
  514. self._fx[1].exec_id(self._exec_ids[1])
  515. self.next(clock)
  516. #print("init fx",self)
  517. def flash(self,target,ftime=0,clock=0,delay=0):
  518. if str(target).lower() == "off":
  519. #self._flash = None
  520. if self._flash:
  521. cur_val = self._flash.next()
  522. #cur_tar = self._fade.next()
  523. cur_tar = self._base_value
  524. self._flash = Fade(cur_val,cur_tar,ftime=ftime,clock=clock)
  525. self._flash.off = 1
  526. else:#elif target != self._base_value:
  527. try:
  528. target = float(target)
  529. self._flash = Fade(self._last_val,target,ftime=ftime,clock=clock,delay=delay)
  530. self._flash = Fade(self._last_val,target,ftime=0,clock=clock,delay=delay)
  531. except Exception as e:
  532. print( "Except:flash",target,ftime,clock,__name__,e,)
  533. self.next(clock)
  534. #print("init flush",self)
  535. def flash_fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="",clock=0,master=None):
  536. if str(xtype).lower() == "off":
  537. fx_value = self._fx_value
  538. self._flash_fx = None
  539. self._flash_fx_value = 0
  540. else:
  541. self._flash_fx = FX(xtype=xtype,size=size,speed=speed,invert=invert
  542. ,width=width,start=start,offset=offset,base=base
  543. ,clock=clock,master=master,master_id=0)
  544. self._flash_fx.exec_id(self._exec_ids[3])
  545. self.next(clock)
  546. #print("init flash_fx",self)
  547. def fx_ctl(self,cmd=""): #start,stop,off
  548. pass
  549. def __str__(self):
  550. return self.__repr__()
  551. def exec_ids(self,_id=None):
  552. #if type(_id) is not type(None):
  553. # #self._exec_id = _id
  554. # #print("set exec_id",_id)
  555. return self._exec_ids
  556. def __repr__(self):
  557. v = self._last_val
  558. if type(self._last_val) in [int,float]:
  559. v = round(self._last_val,2)
  560. return "<BUFFER DMX:{} FINE:{} VAL:{} EXEC:{}\n fd:{}\n fx:{}\n fx_flash:{}\n".format(
  561. self._dmx,self._dmx_fine
  562. ,v,str(self._exec_ids)
  563. ,self._fade
  564. ,self._fx
  565. ,self._flash_fx)
  566. def fade_ctl(self,cmd=""): #start,stop,backw,fwd,bounce
  567. pass
  568. def next(self,clock=0):
  569. try:
  570. self._next(clock)
  571. except Exception as e:
  572. cprint("Exception DMXCH.next()" ,e)
  573. out = self._last_val
  574. return out
  575. def _next(self,clock=0):
  576. value = self._base_value
  577. #self._last_val = value
  578. #return value
  579. #if self._dmx == 1024:
  580. # print(self)
  581. if self._last_val is None:
  582. self._last_val = value
  583. fx_value = self._fx_value
  584. if self._flash is not None:
  585. value = self._flash.next(clock)
  586. #flicker bug ?!
  587. value = self._flash.next(clock)
  588. if self._flash.end == 1 and self._flash.off == 1:
  589. self._flash = None
  590. fx_value = 0
  591. elif self._fade is not None:#is Fade:# is Fade:
  592. self._base_value = self._fade.next(clock)
  593. self._base_value = self._fade.next(clock) #flicker bug ?!
  594. value = self._base_value
  595. if self._flash_fx is not None:# is FX:
  596. fx_value = self._flash_fx.next(clock)
  597. else:
  598. self._fx_value = 0
  599. if self._fx[-1] is not None and self._flash is None:# is FX:
  600. self._fx_value += self._fx[-1].next(clock)
  601. fx_value = self._fx_value
  602. self._last_val = value + fx_value
  603. #self._last_val *= v_master.val(self._fix_id)
  604. if self._v_master_id in V_MASTER:
  605. vm = V_MASTER[self._v_master_id].next(clock)
  606. #print("V_MASTER is ", V_MASTER[self._v_master_id])
  607. vm = vm/256
  608. self._last_val *= vm # v_master.val(self._v_master_id)
  609. #out = self._last_val * htp_master.master_by_dmx(self._dmx)
  610. out = self._last_val
  611. return out
  612. V_MASTER = {} #DMXCH
  613. Bdmx = []
  614. for i in range(512*7+1):
  615. Bdmx.append( DMXCH(i) )
  616. #print(type(dmx[i]))
  617. _id = 1
  618. def split_cmd(data):
  619. if "cmd" in data:
  620. cmd = data["cmd"]
  621. #print("cmd",cmd)
  622. if "," in cmd:
  623. cmds = cmd.split(",")
  624. else:
  625. cmds = [cmd]
  626. return cmds
  627. class VDMX():
  628. """functional implementation as class for namespace encapsulation
  629. """
  630. def __init__(self):
  631. self.data = OrderedDict()
  632. self.data[4] = {"DMX":[21,22,23],"VALUE":255, "LIMIT":255} #,"DMXCH":DMXCH("V4")}
  633. for k,v in self.data.items():
  634. pass
  635. #dmxch = v["DMXCH"]
  636. #dmxch.fade(10,0)
  637. #dmxch.fx(size=200,speed=200,base="-") #self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="", clock=0,master=None):
  638. def _list_by_dmx(self,_dmx=0):
  639. data = OrderedDict()
  640. for i,link in self.data.items(): # enumerate(self.data):
  641. if _dmx in link["DMX"]:
  642. #print( "_list_by_dmx",i,link)
  643. data[i] = link
  644. return data
  645. def dmx_by_id(self,_id=0):
  646. #print("dmx by master-id:",_id)
  647. if _id in self.data:
  648. for i,link in self.data[_id].items():
  649. #print("dmx_by_id", i,link)
  650. return (i,link)
  651. return 0,{}
  652. def by_dmx(self,clock,dmx):
  653. #print("master of dmx:",dmx)
  654. val=0
  655. flag = 0
  656. data = self._list_by_dmx(dmx)
  657. for i,row in data.items():
  658. if "DMXCH" not in row:
  659. row["DMXCH"] = DMXCH("V{}".format(i))
  660. row["DMXCH"].fade(255,0)
  661. v = row["DMXCH"].next(clock)
  662. #row["DMXCH"].fade(200,20)
  663. if v >= val:
  664. val = v
  665. flag = 1
  666. out = 1.
  667. if val > 255:
  668. val = 255
  669. if flag:
  670. out = val/255.
  671. else:
  672. out = 1.
  673. return out
  674. vdmx = VDMX()
  675. class HTP_MASTER():
  676. """functional implementation as class for namespace encapsulation
  677. """
  678. def __init__(self):
  679. self.data = OrderedDict()
  680. #self.data[1] = {"DMX":[1,2,3],"VALUE":80, "LIMIT":255}
  681. #self.data[2] = {"DMX":[12,13,22],"VALUE":70, "LIMIT":255}
  682. #self.data[3] = {"DMX":[22,23,24],"VALUE":99, "LIMIT":255}
  683. self.data[4] = {"DMX":[22,23,24],"VALUE":99, "LIMIT":255,"DMXCH":DMXCH(4)}
  684. def _list_by_dmx(self,_dmx=0):
  685. data = OrderedDict()
  686. for i,link in self.data.items(): # enumerate(self.data):
  687. if _dmx in link["DMX"]:
  688. #print( "_list_by_dmx",i,link)
  689. data[i] = link
  690. return data
  691. def dmx_by_id(self,_id=0):
  692. #print("dmx by master-id:",_id)
  693. if _id in self.data:
  694. for i,link in self.data[_id].items():
  695. #print("dmx_by_id", i,link)
  696. return (i,link)
  697. return 0,{}
  698. def val_by_dmx(self,dmx=0):
  699. #print("master of dmx:",dmx)
  700. val=0
  701. flag = 0
  702. data = self._list_by_dmx(dmx)
  703. for i,link in data.items():
  704. #print("master_by_dmx", i,link)
  705. if link["VALUE"] > val:
  706. #print("master_by_dmx", i,link)
  707. val = link["VALUE"]
  708. flag=1
  709. out = 1.
  710. if flag:
  711. out = val/255.
  712. return out
  713. htp_master = HTP_MASTER()
  714. #htp_master.data[_id] = {"DMX":[1,2,3],"VALUE":80, "LIMIT":255,"DMXCH":DMXCH()}
  715. class Main():
  716. def __init__(self):
  717. self.artnet = {}
  718. self.fx = {} # key is dmx address
  719. self.lock = thread.allocate_lock()
  720. def loop(self):
  721. xx = [0]*512
  722. ii = 0
  723. old_univ = -1
  724. xx = [0]*512
  725. for ii,dmxch in enumerate(Bdmx):
  726. i = ii%512
  727. univ = ii//512
  728. if str(univ) not in self.artnet:
  729. print("add uiv",univ)
  730. self.artnet[str(univ)] = ANN.ArtNetNode(to="10.10.10.255",univ=univ)
  731. if univ != old_univ:
  732. old_univ = univ
  733. try:
  734. artnet.next()
  735. except:pass
  736. artnet = self.artnet[str(univ)]
  737. artnet.dmx = [0]*512
  738. fps_start = time.time()
  739. fps = 0
  740. dbg= 0#1
  741. while 1:
  742. self.lock.acquire_lock()
  743. start = time.time()
  744. _t=0
  745. t = clock.time()
  746. ii = 0
  747. old_univ = -1
  748. xx = [0]*512
  749. for ii,dmxch in enumerate(Bdmx):
  750. i = ii%512
  751. univ = ii//512
  752. s_univ = str(univ)
  753. if s_univ not in self.artnet:
  754. print("add uiv",univ)
  755. self.artnet[s_univ] = ANN.ArtNetNode(to="10.10.10.255",univ=univ)
  756. if dbg:
  757. end = time.time()
  758. print(" t",_t,ii,round(end-start,4))
  759. start = time.time()
  760. _t+=1
  761. old_univ = -1
  762. xx = [0]*512
  763. for ii,dmxch in enumerate(Bdmx):
  764. i = ii%512
  765. univ = ii//512
  766. if univ != old_univ:
  767. old_univ = univ
  768. artnet = self.artnet[str(univ)]
  769. xx = artnet.dmx
  770. v = dmxch.next(t)
  771. xx[i] = int(v)
  772. if dbg:
  773. end = time.time()
  774. print(" t",_t,ii,round(end-start,4))
  775. start = time.time()
  776. _t+=1
  777. old_univ = -1
  778. xx = [0]*512
  779. for ii,dmxch in enumerate(Bdmx): #fine loop
  780. dmx_fine = dmxch._dmx_fine
  781. if dmx_fine > 0:
  782. i = ii%512
  783. univ = ii//512
  784. if univ != old_univ:
  785. artnet = self.artnet[str(univ)]
  786. xx = artnet.dmx# = xx
  787. v = dmxch.next(t)
  788. vv = vdmx.by_dmx(clock=i,dmx=ii+1)
  789. try:
  790. v = v*vv # disable v-master
  791. except Exception as e:
  792. cprint("Exception v*vv",[v,vv],e)
  793. continue
  794. vf = int(v%1*255)
  795. dmx_fine = dmx_fine%512
  796. try:
  797. if v >= 255:
  798. xx[dmx_fine-1] = 255
  799. elif v < 0:
  800. xx[dmx_fine-1] = 0
  801. else:
  802. xx[dmx_fine-1] = int(v%1*255)
  803. except Exception as e:
  804. print("E dmx_fine",e,dmx_fine)
  805. if dbg:
  806. end = time.time()
  807. print(" t",_t,ii,round(end-start,4))
  808. print()
  809. start = time.time()
  810. _t+=1
  811. self.lock.release_lock()
  812. for k,artnet in self.artnet.items():
  813. artnet.next()
  814. fps += 1
  815. stop_fps = 50
  816. time.sleep(1/30)
  817. if fps >= stop_fps:
  818. fps_t = time.time()
  819. print(round(stop_fps/(fps_t-fps_start),2),"core/fps")
  820. fps = 0
  821. fps_start = time.time()
  822. main = Main()
  823. if __run_main:
  824. thread.start_new_thread(main.loop,())
  825. def _init_action(row):#Bdmx,out,DMX):
  826. Admx = row["DMXCH"]
  827. line_sub_count = 0
  828. if row["fx"]:
  829. x = row["fx"]
  830. Admx.fx(xtype=x["xtype"]
  831. ,size=x["size"]
  832. ,speed=x["speed"]
  833. ,invert=x["invert"]
  834. ,width=x["width"]
  835. ,start=x["start"]
  836. ,offset=x["offset"]
  837. ,base=x["base"]
  838. ,clock=x["clock"]
  839. ,master=x["master"])
  840. line_sub_count += 1
  841. if row["flash_fx"]:
  842. x = row["flash_fx"]
  843. Admx.flash_fx(xtype=x["xtype"]
  844. ,size=x["size"]
  845. ,speed=x["speed"]
  846. ,invert=x["invert"]
  847. ,width=x["width"]
  848. ,start=x["start"]
  849. ,offset=x["offset"]
  850. ,base=x["base"]
  851. ,clock=x["clock"]
  852. ,master=x["master"])
  853. line_sub_count += 1
  854. if row["flash"]:
  855. x = row["flash"]
  856. Admx.flash(target=x["target"]
  857. ,ftime=x["ftime"]
  858. ,clock=x["clock"]
  859. ,delay=x["delay"])
  860. line_sub_count += 1
  861. if row["fade"]:
  862. x = row["fade"]
  863. Admx.fade(target=x["target"]
  864. ,ftime=x["ftime"]
  865. ,clock=x["clock"]
  866. ,delay=x["delay"])
  867. line_sub_count += 1
  868. return line_sub_count
  869. def set_dmx_fine_ch(Admx,dmx_fine_nr):
  870. try:
  871. if int(dmx_fine_nr) > 0:
  872. Admx._dmx_fine = int(dmx_fine_nr)
  873. except Exception as e:
  874. cprint(x,color="red")
  875. cprint("except 3455",e,color="red")
  876. def _parse_cmds(cmds,clock=0,master_fx=None):
  877. c=clock
  878. out = {}
  879. for x in cmds:
  880. Admx = DMXCH() #dummy
  881. _fix_id=0
  882. _attr = ""
  883. if "CMD" in x:
  884. print("CMD:",x)
  885. if "EXEC-SPEED-MASTER" == x["CMD"]:
  886. exec_speed_master.val(x["NR"],x["VALUE"])
  887. if "EXEC-SIZE-MASTER" == x["CMD"]:
  888. exec_size_master.val(x["NR"],x["VALUE"])
  889. if "EXEC-OFFSET-MASTER" == x["CMD"]:
  890. exec_offset_master.val(x["NR"],x["VALUE"])
  891. if "SPEED-MASTER" == x["CMD"]:
  892. speed_master.val(x["NR"],x["VALUE"])
  893. if "SIZE-MASTER" == x["CMD"]:
  894. size_master.val(x["NR"],x["VALUE"])
  895. else:
  896. #print("x",x)
  897. if "DMX" in x:
  898. DMX = int(x["DMX"])
  899. else:
  900. continue
  901. if "VALUE" in x:
  902. v = x["VALUE"]
  903. else:
  904. continue
  905. _inc = 0
  906. _fix_id = 0
  907. _val = -1
  908. _clock = 0
  909. exec_id = None
  910. if "VALUE" in x:
  911. _val = x["VALUE"]
  912. if "INC" in x:
  913. _inc = x["INC"]
  914. if "FIX" in x:
  915. _fix_id = x["FIX"]
  916. if "clock" in x:
  917. _clock=x["clock"]
  918. if "ATTR" in x:
  919. _attr = x["ATTR"]
  920. if DMX <= 0: # VIRTUAL
  921. DMX = "FIX"+str(_fix_id)
  922. ok = 0
  923. if "ATTR" in x:
  924. _attr = x["ATTR"]
  925. if "DIM" == x["ATTR"]:
  926. if _fix_id not in V_MASTER:
  927. V_MASTER[_fix_id] = DMXCH()
  928. #print("_val",_val)
  929. #V_MASTER[_fix_id].fade(_val,ftime=0,clock=0,delay=0)
  930. #print(" V-MASTER",_fix_id,_val,_inc)
  931. ok = 1
  932. if _fix_id in V_MASTER:
  933. Admx = V_MASTER[_fix_id]
  934. if not ok:
  935. continue
  936. else:
  937. if DMX < len(Bdmx):
  938. Admx = Bdmx[DMX-1]
  939. else:
  940. print("DMX ADDRESS too BIG",DMX)
  941. continue
  942. if "DMX-FINE" in x and DMX > 0:
  943. set_dmx_fine_ch(Admx, x["DMX-FINE"])
  944. #print("-")
  945. if "EXEC" in x:
  946. exec_id = x["EXEC"]
  947. if "ATTR" in x:
  948. _attr = x["ATTR"]
  949. if "FIX" in x:
  950. _fix_id = x["FIX"]
  951. fx=""
  952. fx2={}
  953. ftime=0
  954. delay=0
  955. if "FX" in x:
  956. fx = x["FX"]
  957. if "FX2" in x:
  958. fx2 = x["FX2"]
  959. if "FADE" in x:
  960. ftime = x["FADE"]
  961. if "DELAY" in x:
  962. delay = x["DELAY"]
  963. #print("DO",[exec_id],x)
  964. # ids = [401,402,304,103]
  965. # exec-id, exec-fx-id, flush-id, flush-fx-id
  966. if v != "off":
  967. if "FLASH" in x:
  968. ids = Admx.exec_ids()
  969. if type(v) is int:
  970. ids[2] = exec_id
  971. if fx2:
  972. ids[3] = exec_id
  973. #print(" ",[ids, exec_id],"FL")
  974. else: # GO or ON
  975. ids = Admx.exec_ids()
  976. if type(v) is int:
  977. ids[0] = exec_id
  978. if fx2:
  979. ids[1] = exec_id
  980. #print(" ",[ids, exec_id],"GO")
  981. if v == "off":
  982. if "FLASH" in x:
  983. ids = Admx.exec_ids()
  984. stop = 0
  985. #print(" ",[ids, exec_id])
  986. if ids[2] != exec_id:
  987. stop = 1
  988. else:
  989. ids[2] = None
  990. if fx2:
  991. if ids[3] != exec_id:
  992. stop = 1
  993. else:
  994. ids[3] = None
  995. stop = 0
  996. if stop:
  997. # this FLASH cmd OFF/RELEASE is not valid anymore
  998. continue
  999. #aprint("OK")
  1000. #ids = Admx.exec_ids()
  1001. #print("OK ",[ids, exec_id])
  1002. #Bdmx[DMX].exec_id(exec_id)
  1003. out[DMX] = {"flash":{},"fade":{},"fx":{},"flash_fx":{},"fix_id":_fix_id,"attr":_attr,"DMXCH":Admx}
  1004. if v is not None:
  1005. if "FLASH" in x:
  1006. out[DMX]["flash"] = {"target":v,"ftime":ftime, "clock":c,"delay":delay,"DMXCH":Admx}
  1007. else:
  1008. out[DMX]["fade"] = {"target":v,"ftime":ftime, "clock":c,"delay":delay,"DMXCH":Admx}
  1009. if type(fx2) is dict and fx2:
  1010. xtype="fade"
  1011. size = 10
  1012. speed = 10
  1013. start = 0
  1014. offset= 0
  1015. width=100
  1016. invert=0
  1017. base = "-"
  1018. if "TYPE" in fx2:
  1019. xtype = fx2["TYPE"]
  1020. if "SIZE" in fx2:
  1021. size = fx2["SIZE"]
  1022. if "SPEED" in fx2:
  1023. speed = fx2["SPEED"]
  1024. if "OFFSET" in fx2:
  1025. offset = fx2["OFFSET"]
  1026. if "BASE" in fx2:
  1027. base = fx2["BASE"]
  1028. if "INVERT" in fx2:
  1029. invert = fx2["INVERT"]
  1030. if "WIDTH" in fx2:
  1031. width = fx2["WIDTH"]
  1032. if "off" == x["VALUE"]: #fix fx flash off
  1033. xtype= "off"
  1034. if "alloff" == xtype.lower():
  1035. for dmxch in Bdmx:
  1036. if dmxch is not None:
  1037. dmxch.flash_fx(xtype="off",clock=c)
  1038. dmxch.fx(xtype="off",clock=c)
  1039. for j in V_MASTER:
  1040. dmxch = V_MASTER[j]
  1041. if j is not None:
  1042. dmxch.flash_fx(xtype="off",clock=c)
  1043. dmxch.fx(xtype="off",clock=c)
  1044. if "FLASH" in x:
  1045. out[DMX]["flash_fx"] = {"xtype":xtype,"size":size,"speed":speed,
  1046. "invert":invert,"width":width,"start":start
  1047. ,"offset":offset,"base":base,"clock":c,"master":master_fx}
  1048. else:
  1049. out[DMX]["fx"] = {"xtype":xtype,"size":size,"speed":speed
  1050. ,"invert":invert,"width":width,"start":start
  1051. ,"offset":offset,"base":base,"clock":c,"master":master_fx}
  1052. elif type(fx) is str and fx:
  1053. # old fx like sinus:200:12:244
  1054. ccm = str(DMX+1)+":"+fx
  1055. print("fx",ccm)
  1056. if "FLASH" in x:
  1057. pass#CB({"cmd":"fxf"+ccm})
  1058. else:
  1059. pass#CB({"cmd":"fx"+ccm})
  1060. return out
  1061. import hashlib
  1062. JCB_GLOB_BUF = {}
  1063. def JCB(data,sock=None): #json client input
  1064. t_start = time.time()
  1065. s = time.time()
  1066. e = time.time()
  1067. ct = int(e*100)/100
  1068. print()
  1069. msg = "{} JCB START: {:0.02f} sizeof:{}"
  1070. msg = msg.format(ct,e-s,sys.getsizeof(data) )
  1071. print(msg)
  1072. jdatas = []
  1073. l2 = 0
  1074. for line in data:
  1075. data2 = json.loads(line)
  1076. l2 += len(data2)
  1077. #print("line:",line)
  1078. jdatas.append(data2) #["CMD"])
  1079. print("INPUT JCB =>",len(data),":",l2)
  1080. c = clock.time()
  1081. c = float(c)
  1082. ftime = 0
  1083. delay = 0
  1084. out = {}
  1085. line=""
  1086. for cmds in jdatas:
  1087. for line in cmds: # run first
  1088. #print(line)
  1089. if "FLASH" in line:
  1090. cprint("FLUSH",end=" ",color="CYAN")
  1091. if "VALUE" in line:
  1092. if line["VALUE"] == "off":
  1093. cprint("OFF",end=" ",color="red")
  1094. else:
  1095. cprint("ON",end=" ",color="green")
  1096. print("")
  1097. else:
  1098. cprint("FADE",color="CYAN")
  1099. break
  1100. for cmds in jdatas:
  1101. for line in cmds:
  1102. if "time" in line:
  1103. jt_start = line["time"]
  1104. latenz = round(t_start-jt_start,4)
  1105. if latenz > 0.5:
  1106. cprint("latenz 0.5 >",latenz,color="red")
  1107. break
  1108. for cmds in jdatas:
  1109. #line = json.dumps(cmds)
  1110. #md5 = hashlib.md5.hexdigest(line)
  1111. master_fx = MASTER_FX()
  1112. if not cmds:
  1113. continue
  1114. try:
  1115. out = _parse_cmds(cmds,clock=c,master_fx=master_fx)
  1116. #cprint("-","{:0.04} sec.".format(time.time()-t_start),color="yellow")
  1117. # ------- ----------------------------------------------------
  1118. except Exception as e:
  1119. cprint("EXCEPTION JCB",e,color="red")
  1120. cprint("----",str(cmds)[:150],"...",color="red")
  1121. cprint("Error on line {}".format(sys.exc_info()[-1].tb_lineno),color="red")
  1122. raise e
  1123. line_count = 0
  1124. line_count_sub = 0
  1125. line_size = 0
  1126. attr_count = {}
  1127. attr_count2 = 0
  1128. if out:
  1129. try:
  1130. try: # second loop to sync-start all dmxch's
  1131. main.lock.acquire_lock()
  1132. for _id in out:
  1133. row = out[_id]
  1134. #print(row)
  1135. line_size += sys.getsizeof(row)
  1136. #print("_id",_id)
  1137. Admx = row["DMXCH"]
  1138. #print("Admx",Admx)
  1139. if "attr" in row:
  1140. if row["attr"] not in attr_count:
  1141. attr_count[row["attr"]] = 0
  1142. attr_count[row["attr"]] += 1
  1143. attr_count2 +=1
  1144. if row["fix_id"]:
  1145. _fix_id = row["fix_id"]
  1146. Admx._fix_id = _fix_id
  1147. if "attr" in row:
  1148. if row["attr"] in ["RED","GREEN","BLUE","WHITE","AMBER"]: #CYAN,MAGENTA,YELLOW
  1149. Admx._v_master_id = _fix_id
  1150. #print("SET V_MASTER",row)
  1151. line_count_sub += _init_action(row)
  1152. line_count += 1
  1153. e = time.time()
  1154. print(" sub-JCB TIME:","{:0.02f}".format(e-s),int(e*100)/100)
  1155. finally:
  1156. main.lock.release_lock()
  1157. #time.sleep(1/30)
  1158. except Exception as e:
  1159. cprint("EXCEPTION JCB",e,color="red")
  1160. cprint("----",str(cmds)[:150],"...",color="red")
  1161. cprint("Error on line {}".format(sys.exc_info()[-1].tb_lineno),color="red")
  1162. raise e
  1163. #cprint(" ","{:0.04} sec.".format(time.time()-t_start),color="yellow")
  1164. print("attr_count:",attr_count)
  1165. #print(line_count,line_size)
  1166. e = time.time()
  1167. ct = int(e*100)/100
  1168. msg = "{} JCB: END {:0.02f} sizeof:{} fix-count:{} attr-count:{}"
  1169. msg = msg.format(ct,e-s,line_size,line_count,line_count_sub )
  1170. print(msg)
  1171. time.sleep(1/60)
  1172. if __run_main:
  1173. s = chat.Server(cb=JCB)
  1174. while 1:
  1175. s.poll()
  1176. time.sleep(0.001)