_console.py 42 KB

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