console.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. #! /usr/bin/python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. This file is part of grandPA.
  5. grandPA 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, either version 2 of the License, or
  8. (at your option) any later version.
  9. grandPA is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with grandPA. If not, see <http://www.gnu.org/licenses/>.
  15. (c) 2012 micha.rathfelder@gmail.com
  16. """
  17. import time
  18. import socket
  19. import struct
  20. import sys
  21. import random
  22. import math
  23. from collections import OrderedDict
  24. import lib.chat as chat
  25. import lib.ArtNetNode as ANN
  26. import _thread as thread
  27. #thread.start_new_thread
  28. import lib.motion as motion
  29. #idmx = [0]*512 # incremental dmx
  30. dmx = [0]*512 # absolute dmx data
  31. def artnet_loop():
  32. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=12)
  33. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=0)
  34. artnet = ANN.ArtNetNode(to="10.10.10.255",univ=0)
  35. #artnet = ANN.ArtNetNode(to="2.0.0.255",univ=0)
  36. #artnet = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  37. dmx[205] = 255 #205 BLUE
  38. artnet.dmx= dmx #[0]*512
  39. artnet.send()
  40. while 1:
  41. #artnet._test_frame()
  42. artnet.next()
  43. time.sleep(0.01)
  44. class Main():
  45. def __init__(self):
  46. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=12)
  47. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=0)
  48. #artnet = ANN.ArtNetNode(to="2.0.0.255",univ=0)
  49. #artnet = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  50. self.artnet = ANN.ArtNetNode(to="10.10.10.255",univ=0)
  51. self.fx = {} # key is dmx address
  52. def loop(self):
  53. #dmx[205] = 255 #205 BLUE
  54. self.artnet.send()
  55. xx = [0]*512
  56. self.artnet.dmx = xx# [:] #dmx #[0]*512
  57. while 1:
  58. t = clock.time()
  59. for i,dmxch in enumerate(Bdmx):
  60. v = dmxch.next(t)
  61. if i == 0:
  62. if int(xx[i]*100) != int( v*100):
  63. #print("----v",x[i],v,t)
  64. pass
  65. #print("i:{:0.2f} xx:{:0.2f} v:{:0.2f} {:0.2f}----v {}".format(i,xx[i],v,t+100,dmxch))
  66. #print("i:{:0.2f} xx:{:0.2f} v:{:0.2f} {:0.2f}----v {}".format(i,xx[i],v,t+100,dmxch))
  67. xx[i] = int(v)
  68. #artnet._test_frame()
  69. self.artnet.next()
  70. #self.artnet.send()
  71. time.sleep(0.01)
  72. main = Main()
  73. #thread.start_new_thread(artnet_loop,())
  74. thread.start_new_thread(main.loop,())
  75. class CLOCK():
  76. def __init__(self):
  77. self.__time = 0
  78. self.__start = time.time() # only for debugging
  79. self.__tick = 0.01 # incremental timer drift's on highe cpu load ?
  80. def time(self):
  81. return self.__time
  82. def get_drift(self):
  83. run_time = time.time() - self.__start
  84. tick_time = self.__time # * self.__tick
  85. print( "runtime:{:0.2f} tick_timer:{:0.2f} drift:{:0.2f}".format(run_time,tick_time,run_time-tick_time))
  86. def loop(self):
  87. while 1:
  88. self.__time +=self.__tick
  89. #if int(self.__time*100)/10. % 10 == 0:# self.__time % 2 == 0:
  90. # print( self.get_drift())
  91. #print(self.__time)
  92. #for i in range(10):
  93. time.sleep(self.__tick)
  94. clock = CLOCK()
  95. thread.start_new_thread(clock.loop,())
  96. class Fade():
  97. def __init__(self,start,target,time,clock,delay=0):
  98. #print("init Fade ",start,target,time,clock)
  99. if delay < 0:
  100. delay = 0
  101. if time <= 0:
  102. time = 0.0001
  103. clock += delay
  104. self.__delay = delay
  105. self.__clock = clock
  106. self.__clock_curr = clock
  107. self.__time = time
  108. self.__start = start
  109. self.__last = start
  110. self.__target = target
  111. self.run = 1
  112. print("INIT", str(self) )
  113. def __str__(self):
  114. return self.__repr__()
  115. def __repr__(self):
  116. return "<Fade Next:{:0.2f} Start:{:0.2f} Target:{:0.2f} T{:0.2f} Clock:{:0.2f} run:{} delay:{:0.2f}>".format(
  117. self.__last, self.__start,self.__target,self.__time,self.__clock_curr,self.run,self.__delay )
  118. def next(self,clock=None):
  119. if self.__time <= 0 and self.__delay <= 0:
  120. self.__last = self.__target
  121. self.run = 0
  122. if type(clock) is float or type(clock) is int:#not None:
  123. self.__clock_curr = clock
  124. if self.__target > self.__start:
  125. if self.__last >= self.__target:
  126. self.run = 0
  127. return self.__target
  128. else:
  129. if self.__last <= self.__target:
  130. self.run = 0
  131. return self.__target
  132. current = (self.__clock - self.__clock_curr) / self.__time
  133. length = self.__start - self.__target
  134. self.__last = self.__start+ length*current
  135. #if self.__last < 0:
  136. # self.__last = 0
  137. #if self.__last > 255:
  138. # self.__last = 255
  139. self.run = 1
  140. return self.__last
  141. def ctl(self,cmd="",value=None): # if x-fade cmd="%" value=50
  142. # start,stop,fwd,bwd,revers
  143. pass
  144. class FX():
  145. def __init__(self,xtype="sinus",size=10,speed=10,offset=0,clock=0):
  146. self.__xtype=xtype
  147. self.__size = size
  148. self.__speed = speed
  149. self.__offset = offset
  150. self.__clock = clock
  151. self.__clock_curr = clock
  152. self.run = 1
  153. def __str__(self):
  154. return self.__repr__()
  155. def __repr__(self):
  156. return "<FX Next:{:0.2f} xtype:{} Size:{:0.2f} Speed:{:0.2f} Clock:{:0.2f} run:{}>".format(
  157. self.next(),self.__xtype, self.__size,self.__speed,self.__clock_curr,self.run )
  158. def next(self,clock=None):
  159. if type(clock) is float or type(clock) is int:#not None:
  160. self.__clock_curr = clock
  161. t = self.__clock_curr * self.__speed / 255
  162. t += self.__offset / 255
  163. if self.__xtype == "sinus":
  164. return math.sin( t ) * self.__size
  165. elif self.__xtype == "cosinus":
  166. return math.cos( t ) * self.__size
  167. else:
  168. return 0
  169. class DMXCH(object):
  170. def __init__(self):
  171. self._base_value = 0
  172. self._fade = None
  173. self._fx = None
  174. self._fx_value = 0
  175. self._flush = None
  176. self._flush_fx = None
  177. self._flush_fx_value = 0
  178. self._last_val = 0
  179. def fade(self,target,time=0,clock=0,delay=0):
  180. if target != self._base_value:
  181. try:
  182. target = float(target)
  183. self._fade = Fade(self._base_value,target,time=time,clock=clock,delay=delay)
  184. except Exception as e:
  185. print( "Except:",e)
  186. def fx(self,xtype="sinus",size=40,speed=40,offset=0,clock=0):
  187. if str(xtype).lower() == "off":
  188. #self._fx = Fade(self._fx_value,target=0,time=2,clock=clock)
  189. self._fx = None
  190. self._fx_value = 0
  191. else:
  192. self._fx = FX(xtype=xtype,size=size,speed=speed,offset=offset,clock=clock)
  193. def flush(self,target,time=0,clock=0,delay=0):
  194. if str(target).lower() == "off":
  195. self._flush = None
  196. else:#elif target != self._base_value:
  197. try:
  198. target = float(target)
  199. self._flush = Fade(self._last_val,target,time=time,clock=clock,delay=delay)
  200. except Exception as e:
  201. print( "Except:",e)
  202. def flush_fx(self,xtype="sinus",size=40,speed=40,offset=0,clock=0):
  203. if str(xtype).lower() == "off":
  204. #self._fx = Fade(self._fx_value,target=0,time=2,clock=clock)
  205. self._flush_fx = None
  206. self._flush_fx_value = 0
  207. else:
  208. self._flush_fx = FX(xtype=xtype,size=size,speed=speed,offset=offset,clock=clock)
  209. def fx_ctl(self,cmd=""):#start,stop,off
  210. pass
  211. def __str__(self):
  212. return self.__repr__()
  213. def __repr__(self):
  214. return "< DMXCH {:0.2f} > \n{}\n {}".format( self._last_val,self._fx,self._fade)
  215. def fade_ctl(self,cmd=""):#start,stop,backw,fwd,bounce
  216. pass
  217. def next(self,clock=0):
  218. value = self._base_value
  219. fx_value = self._fx_value
  220. if self._flush is not None:
  221. value = self._flush.next(clock)
  222. fx_value = 0
  223. elif self._fade is not None:#is Fade:# is Fade:
  224. self._base_value = self._fade.next(clock)
  225. value = self._base_value
  226. if self._flush_fx is not None:# is FX:
  227. fx_value = self._flush_fx.next(clock)
  228. elif self._fx is not None and self._flush is None:# is FX:
  229. self._fx_value = self._fx.next(clock)
  230. fx_value = self._fx_value
  231. self._last_val = value+fx_value
  232. return self._last_val
  233. Bdmx = []
  234. for i in range(512):
  235. Bdmx.append( DMXCH() )
  236. #print(type(dmx[i]))
  237. def split_cmd(data):
  238. if "cmd" in data:
  239. cmd = data["cmd"]
  240. #print("cmd",cmd)
  241. if "," in cmd:
  242. cmds = cmd.split(",")
  243. else:
  244. cmds = [cmd]
  245. return cmds
  246. def CB(data):
  247. print("CB",data)
  248. cmds = split_cmd(data)
  249. c = clock.time()
  250. time = 2
  251. delay = 0
  252. for xcmd in cmds:
  253. if xcmd.startswith("df"):
  254. xxcmd=xcmd[2:].split(":")
  255. #print("DMX:",xxcmd)
  256. if "alloff" == xxcmd[1].lower():
  257. for i in Bdmx:
  258. if i is not None:
  259. i.flush(target="off",clock=c)
  260. continue
  261. l = xxcmd
  262. try:
  263. k=int(l[0])-1
  264. v=l[1]
  265. if len(l) >= 3:
  266. time=float(l[2])
  267. #if v > 255:
  268. # v = 255
  269. if len(l) >= 3:
  270. try:time=float(l[2])
  271. except:pass
  272. if len(l) >= 4:
  273. try:delay=float(l[3])
  274. except:pass
  275. if len(Bdmx) > k:
  276. Bdmx[k].flush(target=v,time=time, clock=c,delay=delay)
  277. except Exception as e:
  278. print("EXCEPTION IN FADE",e)
  279. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  280. elif xcmd.startswith("d"):
  281. xxcmd=xcmd[1:].split(":")
  282. #print("DMX:",xxcmd)
  283. l = xxcmd
  284. try:
  285. k=int(l[0])-1
  286. v=l[1]
  287. if len(l) >= 3:
  288. time=float(l[2])
  289. #if v > 255:
  290. # v = 255
  291. if len(l) >= 3:
  292. try:time=float(l[2])
  293. except:pass
  294. if len(l) >= 4:
  295. try:delay=float(l[3])
  296. except:pass
  297. if len(Bdmx) > k:
  298. Bdmx[k].fade(target=v,time=time, clock=c,delay=delay)
  299. except Exception as e:
  300. print("EXCEPTION IN FADE",e)
  301. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  302. elif xcmd.startswith("fxf"):
  303. xxcmd=xcmd[3:].split(":")
  304. print("fxf:",xxcmd)
  305. if "alloff" == xxcmd[1].lower():
  306. for i in Bdmx:
  307. if i is not None:
  308. i.flush_fx(xtype="off",clock=c)
  309. l = xxcmd
  310. try:
  311. xtype=""
  312. size=40
  313. speed=100
  314. offset=0
  315. k=int(l[0])-1
  316. xtype=l[1]
  317. if len(l) >= 3:
  318. try:size=int(l[2])
  319. except:pass
  320. if len(l) >= 4:
  321. try:speed=int(l[3])
  322. except:pass
  323. if len(l) >= 5:
  324. try:offset=int(l[4])
  325. except:pass
  326. if len(Bdmx) > k:
  327. #Bdmx[k].fade(target=v,time=t, clock=c)
  328. Bdmx[k].flush_fx(xtype=xtype,size=size,speed=speed,offset=offset,clock=c)
  329. except Exception as e:
  330. print("EXCEPTION IN FX",e)
  331. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  332. elif xcmd.startswith("fx"):
  333. xxcmd=xcmd[2:].split(":")
  334. #print("DMX:",xxcmd)
  335. if "alloff" == xxcmd[1].lower():
  336. for i in Bdmx:
  337. i.fx(xtype="off",clock=c)
  338. l = xxcmd
  339. try:
  340. xtype=""
  341. size=40
  342. speed=100
  343. offset=0
  344. k=int(l[0])-1
  345. xtype=l[1]
  346. if len(l) >= 3:
  347. try:size=int(l[2])
  348. except:pass
  349. if len(l) >= 4:
  350. try:speed=int(l[3])
  351. except:pass
  352. if len(l) >= 5:
  353. try:offset=int(l[4])
  354. except:pass
  355. if len(Bdmx) > k:
  356. #Bdmx[k].fade(target=v,time=t, clock=c)
  357. Bdmx[k].fx(xtype=xtype,size=size,speed=speed,offset=offset,clock=c)
  358. except Exception as e:
  359. print("EXCEPTION IN FX",e)
  360. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  361. chat.cmd(CB) # server listener
  362. input("END")