_console.py 41 KB

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