console.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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):
  98. #print("init Fade ",start,target,time,clock)
  99. self.__clock = clock
  100. self.__clock_curr = clock
  101. self.__time = time
  102. self.__start = start
  103. self.__last = start
  104. self.__target = target
  105. self.run = 1
  106. print("INIT", str(self) )
  107. def __str__(self):
  108. return self.__repr__()
  109. def __repr__(self):
  110. return "<Fade Next:{:0.2f} Start:{:0.2f} Target:{:0.2f} Clock:{:0.2f} run:{}>".format(
  111. self.__last, self.__start,self.__target,self.__clock_curr,self.run )
  112. def next(self,clock=None):
  113. if self.__time <= 0:
  114. self.__last = self.__target
  115. self.run = 0
  116. if type(clock) is float or type(clock) is int:#not None:
  117. self.__clock_curr = clock
  118. if self.__target > self.__start:
  119. if self.__last >= self.__target:
  120. self.run = 0
  121. return self.__target
  122. else:
  123. if self.__last <= self.__target:
  124. self.run = 0
  125. return self.__target
  126. current = (self.__clock - self.__clock_curr) / self.__time
  127. length = self.__start - self.__target
  128. self.__last = self.__start+ length*current
  129. #if self.__last < 0:
  130. # self.__last = 0
  131. #if self.__last > 255:
  132. # self.__last = 255
  133. self.run = 1
  134. return self.__last
  135. def ctl(self,cmd="",value=None): # if x-fade cmd="%" value=50
  136. # start,stop,fwd,bwd,revers
  137. pass
  138. class FX():
  139. def __init__(self,xtype="sinus",size=10,speed=10,offset=0,clock=0):
  140. self.__xtype=xtype
  141. self.__size = size
  142. self.__speed = speed
  143. self.__offset = offset
  144. self.__clock = clock
  145. self.__clock_curr = clock
  146. self.run = 1
  147. def __str__(self):
  148. return self.__repr__()
  149. def __repr__(self):
  150. return "<FX Next:{:0.2f} xtype:{} Size:{:0.2f} Speed:{:0.2f} Clock:{:0.2f} run:{}>".format(
  151. self.next(),self.__xtype, self.__size,self.__speed,self.__clock_curr,self.run )
  152. def next(self,clock=None):
  153. if type(clock) is float or type(clock) is int:#not None:
  154. self.__clock_curr = clock
  155. t = self.__clock_curr * self.__speed / 255
  156. t += self.__offset / 255
  157. if self.__xtype == "sinus":
  158. return math.sin( t ) * self.__size
  159. elif self.__xtype == "cosinus":
  160. return math.cos( t ) * self.__size
  161. else:
  162. return 0
  163. class DMXCH(object):
  164. def __init__(self):
  165. self._base_value = 0
  166. self._fx_value = 0
  167. self._fade = None
  168. self._fx = None
  169. self._last_val = 0
  170. def fade(self,target,time=0,clock=0):
  171. if target != self._base_value:
  172. self._fade = Fade(self._base_value,target,time=time,clock=clock)
  173. def fx(self,xtype="sinus",size=40,speed=40,offset=0,clock=0):
  174. if xtype.lower() == "off":
  175. #self._fx = Fade(self._fx_value,target=0,time=2,clock=clock)
  176. self._fx = None
  177. self._fx_value = 0
  178. else:
  179. self._fx = FX(xtype=xtype,size=size,speed=speed,offset=offset,clock=clock)
  180. def fx_ctl(self,cmd=""):#start,stop,off
  181. pass
  182. def __str__(self):
  183. return self.__repr__()
  184. def __repr__(self):
  185. return "< DMXCH {:0.2f} > \n{}\n {}".format( self._last_val,self._fx,self._fade)
  186. def fade_ctl(self,cmd=""):#start,stop,backw,fwd,bounce
  187. pass
  188. def next(self,clock=0):
  189. if type(self._fade) is Fade:# is Fade:
  190. self._base_value = self._fade.next(clock)
  191. if type(self._fx) is FX:
  192. self._fx_value = self._fx.next(clock)
  193. self._last_val = self._base_value+self._fx_value
  194. return self._last_val
  195. Bdmx = []
  196. for i in range(512):
  197. Bdmx.append( DMXCH() )
  198. #print(type(dmx[i]))
  199. def split_cmd(data):
  200. if "cmd" in data:
  201. cmd = data["cmd"]
  202. #print("cmd",cmd)
  203. if "," in cmd:
  204. cmds = cmd.split(",")
  205. else:
  206. cmds = [cmd]
  207. return cmds
  208. def CB(data):
  209. print("CB",data)
  210. cmds = split_cmd(data)
  211. c = clock.time()
  212. for xcmd in cmds:
  213. if xcmd.startswith("d"):
  214. xxcmd=xcmd[1:].split(":")
  215. #print("DMX:",xxcmd)
  216. l = xxcmd
  217. t = 2
  218. try:
  219. k=int(l[0])-1
  220. v=float(l[1])
  221. if len(l) >= 3:
  222. t=float(l[2])
  223. if v > 255:
  224. v = 255
  225. if len(Bdmx) > k:
  226. Bdmx[k].fade(target=v,time=t, clock=c)
  227. except Exception as e:
  228. print("EXCEPTION IN FADE",e)
  229. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  230. elif xcmd.startswith("fx"):
  231. xxcmd=xcmd[2:].split(":")
  232. #print("DMX:",xxcmd)
  233. if "alloff" == xxcmd[1].lower():
  234. for i in Bdmx:
  235. i.fx(xtype="off",clock=c)
  236. l = xxcmd
  237. t = 2
  238. try:
  239. xtype=""
  240. size=40
  241. speed=100
  242. offset=0
  243. k=int(l[0])-1
  244. xtype=l[1]
  245. if len(l) >= 3:
  246. try:size=int(l[2])
  247. except:pass
  248. if len(l) >= 4:
  249. try:speed=int(l[3])
  250. except:pass
  251. if len(l) >= 5:
  252. try:offset=int(l[4])
  253. except:pass
  254. if len(Bdmx) > k:
  255. #Bdmx[k].fade(target=v,time=t, clock=c)
  256. Bdmx[k].fx(xtype=xtype,size=size,speed=speed,offset=offset,clock=c)
  257. except Exception as e:
  258. print("EXCEPTION IN FX",e)
  259. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  260. chat.cmd(CB) # server listener
  261. input("END")