_console.py 41 KB

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