_console.py 41 KB

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