_console.py 39 KB

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