_console.py 38 KB

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