console.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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._fx_value = 0
  173. self._fade = None
  174. self._fx = None
  175. self._last_val = 0
  176. def fade(self,target,time=0,clock=0,delay=0):
  177. if target != self._base_value:
  178. self._fade = Fade(self._base_value,target,time=time,clock=clock,delay=delay)
  179. def fx(self,xtype="sinus",size=40,speed=40,offset=0,clock=0):
  180. if xtype.lower() == "off":
  181. #self._fx = Fade(self._fx_value,target=0,time=2,clock=clock)
  182. self._fx = None
  183. self._fx_value = 0
  184. else:
  185. self._fx = FX(xtype=xtype,size=size,speed=speed,offset=offset,clock=clock)
  186. def fx_ctl(self,cmd=""):#start,stop,off
  187. pass
  188. def __str__(self):
  189. return self.__repr__()
  190. def __repr__(self):
  191. return "< DMXCH {:0.2f} > \n{}\n {}".format( self._last_val,self._fx,self._fade)
  192. def fade_ctl(self,cmd=""):#start,stop,backw,fwd,bounce
  193. pass
  194. def next(self,clock=0):
  195. if type(self._fade) is Fade:# is Fade:
  196. self._base_value = self._fade.next(clock)
  197. if type(self._fx) is FX:
  198. self._fx_value = self._fx.next(clock)
  199. self._last_val = self._base_value+self._fx_value
  200. return self._last_val
  201. Bdmx = []
  202. for i in range(512):
  203. Bdmx.append( DMXCH() )
  204. #print(type(dmx[i]))
  205. def split_cmd(data):
  206. if "cmd" in data:
  207. cmd = data["cmd"]
  208. #print("cmd",cmd)
  209. if "," in cmd:
  210. cmds = cmd.split(",")
  211. else:
  212. cmds = [cmd]
  213. return cmds
  214. def CB(data):
  215. print("CB",data)
  216. cmds = split_cmd(data)
  217. c = clock.time()
  218. time = 2
  219. delay = 0
  220. for xcmd in cmds:
  221. if xcmd.startswith("d"):
  222. xxcmd=xcmd[1:].split(":")
  223. #print("DMX:",xxcmd)
  224. l = xxcmd
  225. try:
  226. k=int(l[0])-1
  227. v=float(l[1])
  228. if len(l) >= 3:
  229. time=float(l[2])
  230. if v > 255:
  231. v = 255
  232. if len(l) >= 3:
  233. try:time=float(l[2])
  234. except:pass
  235. if len(l) >= 4:
  236. try:delay=float(l[3])
  237. except:pass
  238. if len(Bdmx) > k:
  239. Bdmx[k].fade(target=v,time=time, clock=c,delay=delay)
  240. except Exception as e:
  241. print("EXCEPTION IN FADE",e)
  242. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  243. elif xcmd.startswith("fx"):
  244. xxcmd=xcmd[2:].split(":")
  245. #print("DMX:",xxcmd)
  246. if "alloff" == xxcmd[1].lower():
  247. for i in Bdmx:
  248. i.fx(xtype="off",clock=c)
  249. l = xxcmd
  250. try:
  251. xtype=""
  252. size=40
  253. speed=100
  254. offset=0
  255. k=int(l[0])-1
  256. xtype=l[1]
  257. if len(l) >= 3:
  258. try:size=int(l[2])
  259. except:pass
  260. if len(l) >= 4:
  261. try:speed=int(l[3])
  262. except:pass
  263. if len(l) >= 5:
  264. try:offset=int(l[4])
  265. except:pass
  266. if len(Bdmx) > k:
  267. #Bdmx[k].fade(target=v,time=t, clock=c)
  268. Bdmx[k].fx(xtype=xtype,size=size,speed=speed,offset=offset,clock=c)
  269. except Exception as e:
  270. print("EXCEPTION IN FX",e)
  271. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  272. chat.cmd(CB) # server listener
  273. input("END")