_console.py 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091
  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@uxsrv.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. size_master = _MASTER("SIZE")
  197. speed_master = _MASTER("SPEED")
  198. exe_master = []
  199. exe_master.append({"SIZE":100,"SPEED":100,"id":12,"link-ids":[2]})
  200. class MASTER_FX():
  201. def __init__(self):
  202. #cprint(self,"MASTER_FX INIT !",color="green")
  203. self.__data = []
  204. self.__ok = []
  205. self.i=0
  206. self.old_offsets = []
  207. self.offsets = []
  208. self.count = -1
  209. self.init = 10
  210. def add(self,fx):
  211. if fx not in self.__data:
  212. #cprint(self,"ADD TO MASTER !",color="green")
  213. self.__data.append(fx)
  214. info = fx._get_info()
  215. #cprint(self,"ADD" ,info,color="green")
  216. offset = 0
  217. if "offset" in info:
  218. offset = info["offset"]
  219. self.old_offsets.append(offset)
  220. self.offsets.append(offset)
  221. if "xtype" in info:
  222. if info["xtype"] == "rnd":
  223. self._shuffle()
  224. #self.init += 1
  225. def _shuffle(self):
  226. #cprint(self,"REORDER RANDOM !",color="green")
  227. #self.init = 0
  228. #cprint(self.old_offsets)
  229. random.shuffle(self.old_offsets)
  230. #cprint(self.old_offsets)
  231. def _init(self):
  232. self._shuffle()
  233. #self.offsets = []
  234. for i,v in enumerate(self.old_offsets):
  235. offset = self.old_offsets[i]
  236. self.offsets[i] = offset
  237. self.init = 0
  238. def next(self,child):
  239. i = self.__data.index(child)
  240. offset = self.old_offsets[i]
  241. self.offsets[i] = offset
  242. return offset
  243. #for i,v in enumerate(self.old_offsets):
  244. # offset = self.old_offsets[i]
  245. # self.offsets[i] = offset
  246. def get(self,child,count):
  247. offset = 0
  248. if child not in self.__data:
  249. return offset
  250. if self.init:
  251. self._init()
  252. idx = self.__data.index(child)
  253. if (self.count != count and idx == 0 ) or self.init == 0:
  254. self.init = 1
  255. self._shuffle()
  256. #print( count)
  257. self.count=count
  258. idx = self.__data.index(child)
  259. offset = self.offsets[idx]
  260. return offset
  261. class FX():
  262. 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):
  263. self.__xtype=xtype
  264. self.__size = size
  265. self.__start = start
  266. self.__master_id = master_id
  267. if width > 200:
  268. width = 200
  269. if width <= 0:
  270. width = 1
  271. self.__fade_in_master = 0
  272. self.__width = width
  273. self.__invert = invert
  274. self.__base = base
  275. self.__speed = speed
  276. self.__offset = offset
  277. self.__clock = clock
  278. self.__clock_curr = clock
  279. self.__clock_delta = 0
  280. self.__clock_old = self.__clock_curr
  281. self.out = 0
  282. self.old_v = -1
  283. self.run = 1
  284. self.count = -1
  285. self.__angel = self.__clock_curr*360%360
  286. if master is None:
  287. cprint(master, "MASTER_FX ERR",master,color="red")
  288. self.__master = MASTER_FX()
  289. self.__master.add(self)
  290. else:
  291. #cprint( "MASTER_FX OK",master,color="red")
  292. self.__master = master
  293. self.__master.add(self)
  294. if self.__xtype == "rnd":
  295. self.__offset = self.__master.get(self,-2)
  296. self.__offset = self.__master.next(self)#,count)
  297. self._exec_id = None
  298. self.next()
  299. #print("init FX",self)
  300. def exec_id(self,_id=None):
  301. if type(_id) is not type(None):
  302. self._exec_id = str(_id)
  303. return self._exec_id
  304. def _get_info(self):
  305. print(self.__offset)
  306. return {"offset":self.__offset,"xtype":self.__xtype}
  307. #return self.next(),self.__xtype, self.__size,self.__speed,self.__angel, self.__base,self.__clock_curr,self.run
  308. def __str__(self):
  309. return self.__repr__()
  310. def __repr__(self):
  311. return "<FX Next:{:0.2f} xtype:{} Size:{:0.2f} Speed:{:0.2f} ang:{:0.2f} base:{} Clock:{:0.2f} run:{} EXEC:{}>".format(
  312. self.next(),self.__xtype, self.__size,self.__speed,self.__angel, self.__base,self.__clock_curr,self.run,self._exec_id )
  313. def next(self,clock=None):
  314. if type(clock) is float or type(clock) is int:#not None:
  315. self.__clock_curr = clock
  316. d = (self.__clock_curr - self.__clock_old)
  317. #print()
  318. #print("A",d)
  319. m1 = ( speed_master.val(self.__master_id)) # global speed-master
  320. #print("B {:0.4}".format(m1))
  321. m2 = ( exec_speed_master.val(self._exec_id)) # exec start by 0
  322. #print("C {:0.4}".format(m2))
  323. shift = 0
  324. m = (m1 * m2) -1
  325. shift += d * m
  326. #print("D",shift)
  327. self.__clock_delta += shift
  328. #print(self.__clock_delta )
  329. self.__clock_old = self.__clock_curr
  330. t = self.__clock_curr
  331. t += self.__clock_delta
  332. t *= self.__speed / 60
  333. t += self.__offset / 100 #255 #1024 #255
  334. t += self.__start / 1024 #255
  335. #t = t*speed_master.val(self.__master_id)
  336. tw = t%1
  337. count = t//1
  338. t = t * (100/self.__width)
  339. if tw > self.__width/100:
  340. t = 1
  341. self.__angel = t%1*360
  342. t = t%1
  343. rad = math.radians(self.__angel)
  344. v=0
  345. out = 0
  346. base = 0
  347. size = self.__size
  348. if self.__base == "+": # add
  349. base = size/2
  350. elif self.__base == "-": # sub
  351. base = size/2*-1
  352. if self.__xtype == "sinus":
  353. v = math.sin( rad )
  354. v/=2
  355. elif self.__xtype == "cosinus":
  356. v = math.cos( rad )
  357. if self.__base == "+": # add
  358. size *= -1
  359. v/=2
  360. elif self.__xtype == "rnd":
  361. #base = 0
  362. if self.__angel > 90 and self.__angel <=270:
  363. v=1
  364. else:
  365. v=0
  366. #if count != self.count and v: # % 2 == 0:#!= self.count:
  367. # #self.__offset = random.randint(0,1024)# /1024
  368. # self.__master._shuffle()
  369. if count != self.count and v == 0: # and v: # % 2 == 0:#!= self.count:
  370. self.__master.next(self)#,count)
  371. #self.__master.next(self)#,count)
  372. self.__offset = self.__master.get(self,count)
  373. base = 0
  374. if self.__base == "-": # sub
  375. if self.__invert:
  376. v = 1-v
  377. #base = -size
  378. size *=-1
  379. v *=-1
  380. elif self.__base == "+": # sub
  381. if self.__invert:
  382. v = v-1
  383. else:
  384. v = (t%1-0.5)
  385. elif self.__xtype == "on":
  386. #base = 0
  387. if self.__angel > 90 and self.__angel <=270:
  388. v=1
  389. else:
  390. v=0
  391. base = 0
  392. if self.__base == "-": # sub
  393. if self.__invert:
  394. v = 1-v
  395. #base = -size
  396. size *=-1
  397. v *=-1
  398. elif self.__base == "+": # sub
  399. if self.__invert:
  400. v = v-1
  401. else:
  402. v = (t%1-0.5)
  403. elif self.__xtype == "ramp" or self.__xtype == "ramp":
  404. v = (t%1)
  405. base = 0
  406. if self.__base == "-": # sub
  407. if self.__invert:
  408. v = 1-v
  409. #base = -size
  410. size *=-1
  411. v *=-1
  412. elif self.__base == "+": # sub
  413. if self.__invert:
  414. v = v-1
  415. else:
  416. v = (t%1-0.5)
  417. elif self.__xtype == "ramp2" or self.__xtype == "bump2":
  418. v = (t%1)
  419. v = 1-v
  420. if v == 1:
  421. v=0
  422. base = 0
  423. if self.__base == "-": # sub
  424. if self.__invert:
  425. v = 1-v
  426. #base = -size
  427. size *=-1
  428. v *=-1
  429. elif self.__base == "+": # sub
  430. if self.__invert:
  431. v = v-1
  432. else:
  433. v = (t%1-0.5)
  434. elif self.__xtype == "fade":
  435. x = t * 2
  436. if x > 1:
  437. x = 2-x
  438. x -= 0.5
  439. v = x*2
  440. #base /= 2
  441. #base *=2
  442. if self.__base == "+": # add
  443. pass#base /= 2
  444. else:
  445. v *= -1
  446. v/=2
  447. if self.__invert:
  448. v *=-1
  449. #if self.__fade_in_master < 255:
  450. # self.__fade_in_master += v*size
  451. out = v *size +base
  452. self.out = out
  453. self.count = count
  454. out = out * size_master.val(self.__master_id) # master
  455. out = out * exec_size_master.val(self._exec_id) # master
  456. #* (self.__fade_in_master /255.)
  457. return out
  458. class DMXCH(object):
  459. def __init__(self,dmx=-1):
  460. self._base_value = 0
  461. self._fade = None
  462. self._fx = [None,None] # None
  463. self._fx_value = 0
  464. self._dmx = dmx
  465. self._flash = None
  466. self._flash_fx = None
  467. self._flash_fx_value = 0
  468. self._last_val = None
  469. self._exec_id = None
  470. #self.next(clock)
  471. #print("init",self)
  472. def fade(self,target,ftime=0,clock=0,delay=0):
  473. if target != self._base_value:
  474. try:
  475. target = float(target)
  476. self._fade = Fade(self._base_value,target,ftime=ftime,clock=clock,delay=delay)
  477. #self._fade.next()
  478. #self._fade.next()
  479. except Exception as e:
  480. print( "Except:fade",e,target,ftime,clock)
  481. self.next(clock)
  482. print("init",self)
  483. def fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="", clock=0,master=None):
  484. print([self,xtype,size,speed,start,offset,base, clock])
  485. self._fx[0] = self._fx[1]
  486. if str(xtype).lower() == "off":
  487. fx_value = self._fx_value
  488. if fx_value != 0:
  489. cprint("???????______ FX OFF AS FADE",fx_value,0,255)
  490. self._fx[1] = Fade(fx_value,0,ftime=0.5,clock=clock)
  491. else:
  492. self._fx[1] = None
  493. self._fx_value = 0
  494. else:
  495. 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)
  496. self._fx[1].exec_id(self._exec_id)
  497. self.next(clock)
  498. print("init",self)
  499. def flash(self,target,ftime=0,clock=0,delay=0):
  500. if str(target).lower() == "off":
  501. self._flash = None
  502. else:#elif target != self._base_value:
  503. try:
  504. target = float(target)
  505. self._flash = Fade(self._last_val,target,ftime=ftime,clock=clock,delay=delay)
  506. except Exception as e:
  507. print( "Except:flash",target,ftime,clock,__name__,e,)
  508. self.next(clock)
  509. print("init",self)
  510. def flash_fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="",clock=0,master=None):
  511. if str(xtype).lower() == "off":
  512. fx_value = self._fx_value
  513. self._flash_fx = None
  514. self._flash_fx_value = 0
  515. else:
  516. 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)
  517. self._flash_fx.exec_id(self._exec_id)
  518. self.next(clock)
  519. print("init",self)
  520. def fx_ctl(self,cmd=""): #start,stop,off
  521. pass
  522. def __str__(self):
  523. return self.__repr__()
  524. def exec_id(self,_id=None):
  525. if type(id) is not type(None):
  526. self._exec_id = _id
  527. return self._exec_id
  528. def __repr__(self):
  529. return "<BUFFER {} v:{:0.2f} EXEC:{}> fx:[{}] fd:{}".format(self._dmx, self._last_val,self._exec_id,self._fx,self._fade)
  530. def fade_ctl(self,cmd=""): #start,stop,backw,fwd,bounce
  531. pass
  532. def next(self,clock=0):
  533. value = self._base_value
  534. if self._last_val is None:
  535. self._last_val = value
  536. fx_value = self._fx_value
  537. if self._flash is not None:
  538. value = self._flash.next(clock)
  539. #flicker bug ?!
  540. value = self._flash.next(clock)
  541. fx_value = 0
  542. elif self._fade is not None:#is Fade:# is Fade:
  543. self._base_value = self._fade.next(clock)
  544. self._base_value = self._fade.next(clock) #flicker bug ?!
  545. value = self._base_value
  546. if self._flash_fx is not None:# is FX:
  547. fx_value = self._flash_fx.next(clock)
  548. else:
  549. self._fx_value = 0
  550. if self._fx[-1] is not None and self._flash is None:# is FX:
  551. self._fx_value += self._fx[-1].next(clock)
  552. fx_value = self._fx_value
  553. self._last_val = value + fx_value
  554. #out = self._last_val * htp_master.master_by_dmx(self._dmx)
  555. out = self._last_val
  556. return out
  557. Bdmx = []
  558. for i in range(512*3):
  559. Bdmx.append( DMXCH(i) )
  560. #print(type(dmx[i]))
  561. _id = 1
  562. def split_cmd(data):
  563. if "cmd" in data:
  564. cmd = data["cmd"]
  565. #print("cmd",cmd)
  566. if "," in cmd:
  567. cmds = cmd.split(",")
  568. else:
  569. cmds = [cmd]
  570. return cmds
  571. class VDMX():
  572. """functional implementation as class for namespace encapsulation
  573. """
  574. def __init__(self):
  575. self.data = OrderedDict()
  576. self.data[4] = {"DMX":[21,22,23],"VALUE":255, "LIMIT":255} #,"DMXCH":DMXCH("V4")}
  577. for k,v in self.data.items():
  578. pass
  579. #dmxch = v["DMXCH"]
  580. #dmxch.fade(10,0)
  581. #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):
  582. def _list_by_dmx(self,_dmx=0):
  583. data = OrderedDict()
  584. for i,link in self.data.items(): # enumerate(self.data):
  585. if _dmx in link["DMX"]:
  586. #print( "_list_by_dmx",i,link)
  587. data[i] = link
  588. return data
  589. def dmx_by_id(self,_id=0):
  590. #print("dmx by master-id:",_id)
  591. if _id in self.data:
  592. for i,link in self.data[_id].items():
  593. #print("dmx_by_id", i,link)
  594. return (i,link)
  595. return 0,{}
  596. def by_dmx(self,clock,dmx):
  597. #print("master of dmx:",dmx)
  598. val=0
  599. flag = 0
  600. data = self._list_by_dmx(dmx)
  601. for i,row in data.items():
  602. if "DMXCH" not in row:
  603. row["DMXCH"] = DMXCH("V{}".format(i))
  604. row["DMXCH"].fade(255,0)
  605. v = row["DMXCH"].next(clock)
  606. #row["DMXCH"].fade(200,20)
  607. if v >= val:
  608. val = v
  609. flag = 1
  610. out = 1.
  611. if val > 255:
  612. val = 255
  613. if flag:
  614. out = val/255.
  615. else:
  616. out = 1.
  617. return out
  618. vdmx = VDMX()
  619. class HTP_MASTER():
  620. """functional implementation as class for namespace encapsulation
  621. """
  622. def __init__(self):
  623. self.data = OrderedDict()
  624. #self.data[1] = {"DMX":[1,2,3],"VALUE":80, "LIMIT":255}
  625. #self.data[2] = {"DMX":[12,13,22],"VALUE":70, "LIMIT":255}
  626. #self.data[3] = {"DMX":[22,23,24],"VALUE":99, "LIMIT":255}
  627. self.data[4] = {"DMX":[22,23,24],"VALUE":99, "LIMIT":255,"DMXCH":DMXCH(4)}
  628. def _list_by_dmx(self,_dmx=0):
  629. data = OrderedDict()
  630. for i,link in self.data.items(): # enumerate(self.data):
  631. if _dmx in link["DMX"]:
  632. #print( "_list_by_dmx",i,link)
  633. data[i] = link
  634. return data
  635. def dmx_by_id(self,_id=0):
  636. #print("dmx by master-id:",_id)
  637. if _id in self.data:
  638. for i,link in self.data[_id].items():
  639. #print("dmx_by_id", i,link)
  640. return (i,link)
  641. return 0,{}
  642. def val_by_dmx(self,dmx=0):
  643. #print("master of dmx:",dmx)
  644. val=0
  645. flag = 0
  646. data = self._list_by_dmx(dmx)
  647. for i,link in data.items():
  648. #print("master_by_dmx", i,link)
  649. if link["VALUE"] > val:
  650. #print("master_by_dmx", i,link)
  651. val = link["VALUE"]
  652. flag=1
  653. out = 1.
  654. if flag:
  655. out = val/255.
  656. return out
  657. htp_master = HTP_MASTER()
  658. #htp_master.data[_id] = {"DMX":[1,2,3],"VALUE":80, "LIMIT":255,"DMXCH":DMXCH()}
  659. class Main():
  660. def __init__(self):
  661. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=12)
  662. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=0)
  663. #artnet = ANN.ArtNetNode(to="2.0.0.255",univ=0)
  664. #artnet = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  665. self.artnet = {}
  666. #self.artnet["0"] = ANN.ArtNetNode(to="10.10.10.255",univ=0)
  667. #self.artnet["0"].dmx[512-1] = 10
  668. #self.artnet["1"] = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  669. #self.artnet["1"].dmx[512-1] = 11
  670. self.fx = {} # key is dmx address
  671. def loop(self):
  672. #dmx[205] = 255 #205 BLUE
  673. #self.artnet.send()
  674. xx = [0]*512
  675. #artnet = self.artnet["0"]
  676. #artnet.dmx = xx# [:] #dmx #[0]*512
  677. old_univ = -1
  678. while 1:
  679. t = clock.time()
  680. ii = 0
  681. for ii,dmxch in enumerate(Bdmx):
  682. i = ii%512
  683. univ = ii//512
  684. if str(univ) not in self.artnet:
  685. print("add uiv",univ)
  686. self.artnet[str(univ)] = ANN.ArtNetNode(to="10.10.10.255",univ=univ)
  687. self.artnet[str(univ)].dmx[512-1] = 100+univ
  688. if univ != old_univ:
  689. old_univ = univ
  690. #print("UNIV",ii/512)
  691. try:
  692. artnet.next()
  693. except:pass
  694. artnet = self.artnet[str(univ)]
  695. artnet.dmx = xx
  696. v = dmxch.next(t)
  697. vv = vdmx.by_dmx(clock=i,dmx=ii+1)
  698. v = v*vv # disable v-master
  699. xx[i] = int(v)
  700. try:
  701. artnet.next()
  702. except:pass
  703. time.sleep(0.01)
  704. main = Main()
  705. if __run_main:
  706. #thread.start_new_thread(artnet_loop,())
  707. thread.start_new_thread(main.loop,())
  708. def JCB(data): #json client input
  709. t_start = time.time()
  710. #jdatas = data["cmd"].split("\x00")
  711. jdatas = [data["cmd"]]
  712. c = clock.time()
  713. c = float(c)
  714. print("JCB",round(c,2))
  715. ftime = 0
  716. delay = 0
  717. for j in jdatas:
  718. master_fx = MASTER_FX()
  719. if not j:
  720. continue
  721. try:
  722. cprint("JCB::")#,j)
  723. jdata = j #jdatas[j]
  724. jtxt = jdata
  725. #jtxt = zlib.decompress(jtxt) #jtxt.decode())
  726. jtxt = str(jtxt,"UTF-8")
  727. cmds = json.loads(jtxt)
  728. for x in cmds:
  729. #cprint(int(clock.time()*1000)/1000,end=" ",color="yellow")#time.time())
  730. #cprint("json", x,type(x),color="yellow")#,cmds[x])
  731. if "CMD" in x:
  732. print("CMD:",x)
  733. if "EXEC-SPEED-MASTER" == x["CMD"]:
  734. exec_speed_master.val(x["NR"],x["VALUE"])
  735. if "EXEC-SIZE-MASTER" == x["CMD"]:
  736. exec_size_master.val(x["NR"],x["VALUE"])
  737. if "SPEED-MASTER" == x["CMD"]:
  738. speed_master.val(x["NR"],x["VALUE"])
  739. if x["NR"] == 2:
  740. pass
  741. #vdmx.data[4]["DMXCH"].fade(x["VALUE"],3)#,clock=clock.time())
  742. if x["NR"] == 3:
  743. pass
  744. #vdmx.data[4]["DMXCH"].fx(size=255,speed=x["VALUE"],base="-",offset=0)#xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=c,master=master_fx)
  745. if "SIZE-MASTER" == x["CMD"]:
  746. size_master.val(x["NR"],x["VALUE"])
  747. else:
  748. if "DMX" in x:
  749. DMX = int(x["DMX"])
  750. else:continue
  751. if DMX > 0:
  752. DMX -=1
  753. else:continue
  754. exec_id = None
  755. if "EXEC" in x:
  756. exec_id = x["EXEC"]
  757. if "VALUE" in x:# and x["VALUE"] is not None:
  758. v = x["VALUE"]
  759. else:continue
  760. if "FX" in x:# and x["VALUE"] is not None:
  761. fx = x["FX"]
  762. else:fx=""
  763. if "FX2" in x:# and x["VALUE"] is not None:
  764. fx2 = x["FX2"]
  765. else:fx2={}
  766. if "FADE" in x:
  767. ftime = x["FADE"]
  768. else:ftime=0
  769. if "DELAY" in x:
  770. delay = x["DELAY"]
  771. else:delay=0
  772. if len(Bdmx) < DMX:
  773. continue
  774. Bdmx[DMX].exec_id(exec_id)
  775. if v is not None:
  776. if "FLASH" in x:
  777. #print("FLASH")
  778. Bdmx[DMX].flash(target=v,ftime=ftime, clock=c,delay=delay)
  779. else:
  780. #print("FADE")
  781. Bdmx[DMX].fade(target=v,ftime=ftime, clock=c,delay=delay)
  782. if type(fx2) is dict and fx2:
  783. #cprint("FX2",DMX,fx2,color="green")
  784. xtype="fade"
  785. size = 10
  786. speed = 10
  787. start = 0
  788. offset= 0
  789. width=100
  790. invert=0
  791. base = "-"
  792. if "TYPE" in fx2:
  793. xtype = fx2["TYPE"]
  794. if "SIZE" in fx2:
  795. size = fx2["SIZE"]
  796. if "SPEED" in fx2:
  797. speed = fx2["SPEED"]
  798. if "OFFSET" in fx2:
  799. offset = fx2["OFFSET"]
  800. if "BASE" in fx2:
  801. base = fx2["BASE"]
  802. if "INVERT" in fx2:
  803. invert = fx2["INVERT"]
  804. if "WIDTH" in fx2:
  805. width = fx2["WIDTH"]
  806. if "off" == x["VALUE"]: #fix fx flash off
  807. xtype= "off"
  808. if "alloff" == xtype.lower():
  809. for i in Bdmx:
  810. if i is not None:
  811. i.flash_fx(xtype="off",clock=c)
  812. i.fx(xtype="off",clock=c)
  813. if "FLASH" in x:
  814. 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)
  815. else:
  816. Bdmx[DMX].fx(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=c,master=master_fx)
  817. elif type(fx) is str and fx: # old fx like sinus:200:12:244
  818. ccm = str(DMX+1)+":"+fx
  819. print("fx",ccm)
  820. if "FLASH" in x:
  821. CB({"cmd":"fxf"+ccm})
  822. else:
  823. CB({"cmd":"fx"+ccm})
  824. cprint("{:0.04} sec.".format(time.time()-t_start),color="yellow")
  825. cprint("{:0.04} t.".format(time.time()),color="yellow")
  826. except Exception as e:
  827. cprint("EXCEPTION JCB",e,color="red")
  828. cprint("----",str(jdata)[:150],"...",color="red")
  829. cprint("Error on line {}".format(sys.exc_info()[-1].tb_lineno),color="red")
  830. cprint()
  831. cprint("{:0.04} sec.".format(time.time()-t_start),color="yellow")
  832. cprint("{:0.04} t.".format(time.time()),color="yellow")
  833. def CB(data): # raw/text client input
  834. #print("CB",data)
  835. cmds = split_cmd(data)
  836. c = clock.time()
  837. c = float(c)
  838. ftime = 0
  839. delay = 0
  840. for xcmd in cmds:
  841. if xcmd:
  842. cprint("CB",xcmd,end=" ")
  843. pass
  844. else:
  845. continue
  846. if xcmd.startswith("fxf"):
  847. xxcmd=xcmd[3:].split(":")
  848. #print("fxf:",xxcmd)
  849. if "alloff" == xxcmd[1].lower():
  850. for i in Bdmx:
  851. if i is not None:
  852. i.flash_fx(xtype="off",clock=c)
  853. l = xxcmd
  854. try:
  855. xtype=""
  856. size=40
  857. speed=100
  858. start=0
  859. offset=0
  860. base=""
  861. k=int(l[0])-1
  862. xtype=l[1]
  863. if len(l) >= 3:
  864. try:size=int(l[2])
  865. except:pass
  866. if len(l) >= 4:
  867. try:speed=int(l[3])
  868. except:pass
  869. if len(l) >= 5:
  870. try:start=int(l[4])
  871. except:pass
  872. if len(l) >= 6:
  873. try:offset=int(l[5])
  874. except:pass
  875. if len(l) >= 7:
  876. try:base=l[6]
  877. except:pass
  878. if len(Bdmx) > k:
  879. #Bdmx[k].fade(target=v,ftime=t, clock=c)
  880. Bdmx[k].flash_fx(xtype=xtype,size=size,speed=speed,start=start,offset=offset,base=base,clock=c)
  881. except Exception as e:
  882. print("EXCEPTION IN FX",e)
  883. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  884. elif xcmd.startswith("fx"):
  885. xxcmd=xcmd[2:].split(":")
  886. print("DMX:",xxcmd)
  887. if len(xxcmd) < 2:
  888. print("xxcmd err",xxcmd,xcmd)
  889. continue
  890. if "alloff" == xxcmd[1].lower():
  891. for i in Bdmx:
  892. i.fx(xtype="off",clock=c)
  893. l = xxcmd
  894. try:
  895. xtype=""
  896. size=40
  897. speed=100
  898. start=0
  899. offset=0
  900. base=""
  901. k=int(l[0])-1
  902. xtype=l[1]
  903. if len(l) >= 3:
  904. try:size=int(l[2])
  905. except:pass
  906. if len(l) >= 4:
  907. try:speed=int(l[3])
  908. except:pass
  909. if len(l) >= 5:
  910. try:start=int(l[4])
  911. except:pass
  912. if len(l) >= 6:
  913. try:offset=int(l[5])
  914. except:pass
  915. if len(l) >= 7:
  916. try:base=l[6]
  917. except:pass
  918. if len(Bdmx) > k:
  919. #Bdmx[k].fade(target=v,ftime=t, clock=c)
  920. Bdmx[k].fx(xtype=xtype,size=size,speed=speed,start=start,offset=offset,base=base,clock=c)
  921. except Exception as e:
  922. print("EXCEPTION IN FX",xcmd,e)
  923. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  924. if __run_main:
  925. #jchat = chat.CMD(CB,port=50001) # server listener
  926. #thread.start_new_thread(jchat.poll,())
  927. chat.cmd(JCB) # server listener
  928. #chat.cmd(JCB,port=50001) # server listener
  929. #input("END")