console.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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. rnd_id = ""
  18. rnd_id += " Beta 22.02 "
  19. import subprocess
  20. rnd_id += subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).decode('ascii').strip()
  21. if "__file__" in dir():
  22. sys.stdout.write("\x1b]2;"+str(__file__)+" "+rnd_id+"\x07") # terminal title
  23. else:
  24. sys.stdout.write("\x1b]2;"+str("__file__")+" "+rnd_if+"\x07") # terminal title
  25. import time
  26. import socket
  27. import struct
  28. import sys
  29. import random
  30. import math
  31. from collections import OrderedDict
  32. import lib.chat as chat
  33. import lib.ArtNetNode as ANN
  34. import _thread as thread
  35. #thread.start_new_thread
  36. import lib.motion as motion
  37. #idmx = [0]*512 # incremental dmx
  38. dmx = [0]*512 # absolute dmx data
  39. gcolor = 1
  40. def cprint(*text,color="blue",space=" ",end="\n"):
  41. #return 0 #disable print dbg
  42. if not gcolor:
  43. print(text)
  44. return 0
  45. if color == "green":
  46. txt = '\033[92m'
  47. elif color == "red":
  48. txt = '\033[0;31m\033[1m'
  49. elif color == "yellow":
  50. txt = '\033[93m\033[1m'
  51. elif color == "cyan":
  52. txt = '\033[96m'
  53. else:
  54. txt = '\033[94m'
  55. for t in text:
  56. txt += str(t ) +" "
  57. #HEADER = '\033[95m'
  58. #OKBLUE = '\033[94m'
  59. #OKCYAN = '\033[96m'
  60. #OKGREEN = '\033[92m'
  61. #WARNING = '\033[93m'
  62. #FAIL = '\033[91m'
  63. #ENDC = '\033[0m'
  64. #BOLD = '\033[1m'
  65. #UNDERLINE = '\033[4m'
  66. txt += '\033[0m'
  67. print(txt,end=end)
  68. #return txt
  69. def artnet_loop():
  70. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=12)
  71. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=0)
  72. artnet = ANN.ArtNetNode(to="10.10.10.255",univ=0)
  73. #artnet = ANN.ArtNetNode(to="2.0.0.255",univ=0)
  74. #artnet = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  75. #dmx[205] = 255 #205 BLUE
  76. artnet.dmx= dmx #[0]*512
  77. artnet.send()
  78. while 1:
  79. #artnet._test_frame()
  80. artnet.next()
  81. time.sleep(0.01)
  82. class Main():
  83. def __init__(self):
  84. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=12)
  85. #artnet = ANN.ArtNetNode(to="127.0.0.1",port=6555,univ=0)
  86. #artnet = ANN.ArtNetNode(to="2.0.0.255",univ=0)
  87. #artnet = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  88. self.artnet = {}
  89. #self.artnet["0"] = ANN.ArtNetNode(to="10.10.10.255",univ=0)
  90. #self.artnet["0"].dmx[512-1] = 10
  91. #self.artnet["1"] = ANN.ArtNetNode(to="10.10.10.255",univ=1)
  92. #self.artnet["1"].dmx[512-1] = 11
  93. self.fx = {} # key is dmx address
  94. def loop(self):
  95. #dmx[205] = 255 #205 BLUE
  96. #self.artnet.send()
  97. xx = [0]*512
  98. #artnet = self.artnet["0"]
  99. #artnet.dmx = xx# [:] #dmx #[0]*512
  100. old_univ = -1
  101. while 1:
  102. t = clock.time()
  103. ii = 0
  104. for ii,dmxch in enumerate(Bdmx):
  105. i = ii%512
  106. univ = ii//512
  107. if str(univ) not in self.artnet:
  108. print("add uiv",univ)
  109. self.artnet[str(univ)] = ANN.ArtNetNode(to="10.10.10.255",univ=univ)
  110. self.artnet[str(univ)].dmx[512-1] = 100+univ
  111. if univ != old_univ:
  112. old_univ = univ
  113. #print("UNIV",ii/512)
  114. try:
  115. artnet.next()
  116. except:pass
  117. artnet = self.artnet[str(univ)]
  118. artnet.dmx = xx
  119. v = dmxch.next(t)
  120. if i == 0:
  121. #print(dmxch)
  122. if int(xx[i]*100) != int( v*100):
  123. #print("----v",x[i],v,t)
  124. pass
  125. #print("i:{:0.2f} xx:{:0.2f} v:{:0.2f} {:0.2f}----v {}".format(i,xx[i],v,t+100,dmxch))
  126. #print("i:{:0.2f} xx:{:0.2f} v:{:0.2f} {:0.2f}----v {}".format(i,xx[i],v,t+100,dmxch))
  127. xx[i] = int(v)
  128. try:
  129. artnet.next()
  130. except:pass
  131. time.sleep(0.01)
  132. main = Main()
  133. #thread.start_new_thread(artnet_loop,())
  134. thread.start_new_thread(main.loop,())
  135. class CLOCK():
  136. def __init__(self):
  137. self.__time = 0
  138. self.__start = time.time() # only for debugging
  139. self.__tick = 0.01 # incremental timer drift's on highe cpu load ?
  140. def time(self):
  141. return self.__time
  142. def get_drift(self):
  143. run_time = time.time() - self.__start
  144. tick_time = self.__time # * self.__tick
  145. print( "runtime:{:0.2f} tick_timer:{:0.2f} drift:{:0.2f}".format(run_time,tick_time,run_time-tick_time))
  146. def loop(self):
  147. while 1:
  148. self.__time +=self.__tick
  149. #if int(self.__time*100)/10. % 10 == 0:# self.__time % 2 == 0:
  150. # print( self.get_drift())
  151. #print(self.__time)
  152. #for i in range(10):
  153. time.sleep(self.__tick)
  154. clock = CLOCK()
  155. thread.start_new_thread(clock.loop,())
  156. class Fade():
  157. def __init__(self,start,target,ftime,clock,delay=0):
  158. #print("init Fade ",start,target,ftime,clock)
  159. if delay < 0:
  160. delay = 0.0001
  161. if ftime <= 0:
  162. ftime = 0.0001
  163. clock += delay
  164. self.__delay = delay
  165. self.__clock = clock
  166. self.__clock_curr = clock
  167. self.__ftime = ftime
  168. self.__start = start
  169. self.__last = start
  170. self.__target = target
  171. self.run = 1
  172. #print("INIT", str(self) )
  173. def __str__(self):
  174. return self.__repr__()
  175. def __repr__(self):
  176. return "<Fade Next:{:0.2f} Start:{:0.2f} Target:{:0.2f} T{:0.2f} Clock:{:0.2f} run:{} delay:{:0.2f}>".format(
  177. self.__last, self.__start,self.__target,self.__ftime,self.__clock_curr,self.run,self.__delay )
  178. def next(self,clock=None):
  179. if self.__ftime <= 0 and self.__delay <= 0:
  180. self.__last = self.__target
  181. self.run = 0
  182. if type(clock) is float or type(clock) is int:#not None:
  183. self.__clock_curr = clock
  184. if self.__target > self.__start:
  185. if self.__last >= self.__target:
  186. self.run = 0
  187. return self.__target
  188. else:
  189. if self.__last <= self.__target:
  190. self.run = 0
  191. return self.__target
  192. current = (self.__clock - self.__clock_curr) / self.__ftime
  193. length = self.__start - self.__target
  194. self.__last = self.__start+ length*current
  195. #if self.__last < 0:
  196. # self.__last = 0
  197. #if self.__last > 255:
  198. # self.__last = 255
  199. self.run = 1
  200. return self.__last
  201. def ctl(self,cmd="",value=None): # if x-fade cmd="%" value=50
  202. # start,stop,fwd,bwd,revers
  203. pass
  204. class FX():
  205. def __init__(self,xtype="sinus",size=10,speed=10,invert=0,width=100,start=0,offset=0,base="",clock=0):
  206. self.__xtype=xtype
  207. self.__size = size
  208. self.__start = start
  209. if width > 200:
  210. width = 200
  211. self.__width = width
  212. self.__invert = invert
  213. self.__base = base
  214. self.__speed = speed
  215. self.__offset = offset
  216. self.__clock = clock
  217. self.__clock_curr = clock
  218. self.out = 0
  219. self.run = 1
  220. self.__angel = self.__clock_curr*360%360
  221. def __str__(self):
  222. return self.__repr__()
  223. def __repr__(self):
  224. return "<FX Next:{:0.2f} xtype:{} Size:{:0.2f} Speed:{:0.2f} ang:{:0.2f} base:{} Clock:{:0.2f} run:{}>".format(
  225. self.next(),self.__xtype, self.__size,self.__speed,self.__angel, self.__base,self.__clock_curr,self.run )
  226. def next(self,clock=None):
  227. if type(clock) is float or type(clock) is int:#not None:
  228. self.__clock_curr = clock
  229. t = self.__clock_curr * self.__speed / 255
  230. t += self.__offset / 1024 #255
  231. t += self.__start / 1024 #255
  232. tw = t%1
  233. if tw > self.__width/100:
  234. return self.out
  235. t = t * (100/self.__width)
  236. self.__angel = t%1*360 #self.__clock_curr%1 #*360%360
  237. t = t%1
  238. rad = math.radians(self.__angel)
  239. base = 0
  240. if self.__base == "+": # add
  241. base = self.__size
  242. elif self.__base == "-": # sub
  243. base = self.__size*-1
  244. # todo start angle 20°
  245. # todo width angle 90°
  246. #print("{:0.2f} {:0.2f} {:0.2f} {:0.2f}".format(self.__angel ,self.__clock_curr,self.__angel ,math.sin(rad) ) )
  247. out = 0
  248. if self.__xtype == "sinus":
  249. out = math.sin( rad ) * self.__size/2 + base/2
  250. elif self.__xtype == "cosinus":
  251. out = math.cos( rad ) * self.__size/2 + base/2
  252. elif self.__xtype == "on2":
  253. out = self.__size/2
  254. if self.__angel > 90 and self.__angel <=270:
  255. out *=-1
  256. out += base/2
  257. print("ON {:0.2f} {:0.2f} {:0.2f} {:0.2f}".format(out,t,0,self.__angel, base))
  258. #return out
  259. elif self.__xtype == "on":
  260. out = self.__size/2
  261. if self.__angel > 90 and self.__angel <=270:
  262. pass
  263. else:
  264. out *=-1
  265. out += base/2
  266. #return out
  267. elif self.__xtype == "bump":
  268. out = 0
  269. if self.__base == "-": # sub
  270. out = (t%1-1) * self.__size
  271. elif self.__base == "+": # sub
  272. out = (t%1) * self.__size
  273. else:
  274. out = (t%1-0.5) * self.__size
  275. #print("bump",out)
  276. #return out
  277. elif self.__xtype == "bump2":
  278. out = 0
  279. if self.__base == "+": # sub
  280. out = (t%1-1) * (self.__size *-1)
  281. elif self.__base == "-": # sub
  282. out = (t%1) * (self.__size *-1)
  283. else:
  284. out = (t%1-0.5) * (self.__size *-1)
  285. #print("bump",out)
  286. #return out
  287. elif self.__xtype == "fade":
  288. x = t * 2
  289. if x > 1:
  290. x = 2-x
  291. x -= 0.5
  292. out = x * self.__size + base/2
  293. #print("FADE {:0.2f} {:0.2f} {:0.2f} {:0.2f}".format(out,t,x,self.__angel, base))
  294. #return out
  295. if not self.__invert:
  296. out = self.__size*-1 -out
  297. self.out = out
  298. return out
  299. class DMXCH(object):
  300. def __init__(self):
  301. self._base_value = 0
  302. self._fade = None
  303. self._fx = None
  304. self._fx_value = 0
  305. self._flush = None
  306. self._flush_fx = None
  307. self._flush_fx_value = 0
  308. self._last_val = None
  309. def fade(self,target,ftime=0,clock=0,delay=0):
  310. if target != self._base_value:
  311. try:
  312. target = float(target)
  313. self._fade = Fade(self._base_value,target,ftime=ftime,clock=clock,delay=delay)
  314. #self._fade.next()
  315. #self._fade.next()
  316. except Exception as e:
  317. print( "Except:fade",e,target,ftime,clock)
  318. def fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="", clock=0):
  319. print([self,xtype,size,speed,start,offset,base, clock])
  320. if str(xtype).lower() == "off":
  321. #self._fx = Fade(self._fx_value,target=0,ftime=2,clock=clock)
  322. self._fx = None
  323. self._fx_value = 0
  324. else:
  325. self._fx = FX(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=clock)
  326. def flush(self,target,ftime=0,clock=0,delay=0):
  327. if str(target).lower() == "off":
  328. self._flush = None
  329. else:#elif target != self._base_value:
  330. try:
  331. target = float(target)
  332. self._flush = Fade(self._last_val,target,ftime=ftime,clock=clock,delay=delay)
  333. except Exception as e:
  334. print( "Except:flush",target,ftime,clock,__name__,e,)
  335. def flush_fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="",clock=0):
  336. if str(xtype).lower() == "off":
  337. #self._fx = Fade(self._fx_value,target=0,ftime=2,clock=clock)
  338. self._flush_fx = None
  339. self._flush_fx_value = 0
  340. else:
  341. self._flush_fx = FX(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=clock)
  342. def fx_ctl(self,cmd=""):#start,stop,off
  343. pass
  344. def __str__(self):
  345. return self.__repr__()
  346. def __repr__(self):
  347. return "< DMXCH {:0.2f} > {} {}".format( self._last_val,self._fx,self._fade)
  348. def fade_ctl(self,cmd=""):#start,stop,backw,fwd,bounce
  349. pass
  350. def next(self,clock=0):
  351. value = self._base_value
  352. if self._last_val is None:
  353. self._last_val = value
  354. fx_value = self._fx_value
  355. if self._flush is not None:
  356. value = self._flush.next(clock)
  357. #flicker bug ?!
  358. value = self._flush.next(clock)
  359. fx_value = 0
  360. elif self._fade is not None:#is Fade:# is Fade:
  361. self._base_value = self._fade.next(clock)
  362. #flicker bug ?!
  363. self._base_value = self._fade.next(clock)
  364. value = self._base_value
  365. if self._flush_fx is not None:# is FX:
  366. fx_value = self._flush_fx.next(clock)
  367. elif self._fx is not None and self._flush is None:# is FX:
  368. self._fx_value = self._fx.next(clock)
  369. fx_value = self._fx_value
  370. self._last_val = value+fx_value
  371. return self._last_val
  372. Bdmx = []
  373. for i in range(512*3):
  374. Bdmx.append( DMXCH() )
  375. #print(type(dmx[i]))
  376. def split_cmd(data):
  377. if "cmd" in data:
  378. cmd = data["cmd"]
  379. #print("cmd",cmd)
  380. if "," in cmd:
  381. cmds = cmd.split(",")
  382. else:
  383. cmds = [cmd]
  384. return cmds
  385. import time
  386. import json
  387. import zlib
  388. def JCB(data): #json client input
  389. t_start = time.time()
  390. #jdatas = data["cmd"].split("\x00")
  391. jdatas = [data["cmd"]]
  392. c = clock.time()
  393. c = float(c)
  394. print("JCB",round(c,2))
  395. ftime = 0
  396. delay = 0
  397. for j in jdatas:
  398. if not j:
  399. continue
  400. try:
  401. jdata = j #jdatas[j]
  402. jtxt = jdata
  403. #jtxt = zlib.decompress(jtxt) #jtxt.decode())
  404. jtxt = str(jtxt,"UTF-8")
  405. cmds = json.loads(jtxt)
  406. for x in cmds:
  407. #cprint(int(clock.time()*1000)/1000,end=" ",color="yellow")#time.time())
  408. #cprint("json", x,type(x),color="yellow")#,cmds[x])
  409. if "DMX" in x:
  410. DMX = int(x["DMX"])
  411. else:continue
  412. if DMX > 0:
  413. DMX -=1
  414. else:continue
  415. if "VALUE" in x:# and x["VALUE"] is not None:
  416. v = x["VALUE"]
  417. else:continue
  418. if "FX" in x:# and x["VALUE"] is not None:
  419. fx = x["FX"]
  420. else:fx=""
  421. if "FX2" in x:# and x["VALUE"] is not None:
  422. fx2 = x["FX2"]
  423. else:fx2={}
  424. if "FADE" in x:
  425. ftime = x["FADE"]
  426. else:ftime=0
  427. if "DELAY" in x:
  428. delay = x["DELAY"]
  429. else:delay=0
  430. if len(Bdmx) < DMX:
  431. continue
  432. if v is not None:
  433. if "FLASH" in x:
  434. #print("FLASH")
  435. Bdmx[DMX].flush(target=v,ftime=ftime, clock=c,delay=delay)
  436. else:
  437. #print("FADE")
  438. Bdmx[DMX].fade(target=v,ftime=ftime, clock=c,delay=delay)
  439. if type(fx2) is dict and fx2:
  440. #cprint("FX2",DMX,fx2,color="green")
  441. xtype="fade"
  442. size = 10
  443. speed = 10
  444. start = 0
  445. offset= 0
  446. width=100
  447. invert=0
  448. base = "-"
  449. if "TYPE" in fx2:
  450. xtype = fx2["TYPE"]
  451. if "SIZE" in fx2:
  452. size = fx2["SIZE"]
  453. if "SPEED" in fx2:
  454. speed = fx2["SPEED"]
  455. if "OFFSET" in fx2:
  456. offset = fx2["OFFSET"]
  457. if "BASE" in fx2:
  458. base = fx2["BASE"]
  459. if "INVERT" in fx2:
  460. invert = fx2["INVERT"]
  461. if "WIDTH" in fx2:
  462. width = fx2["WIDTH"]
  463. if "alloff" == xtype.lower():
  464. for i in Bdmx:
  465. if i is not None:
  466. i.flush_fx(xtype="off",clock=c)
  467. i.fx(xtype="off",clock=c)
  468. if "FLASH" in x:
  469. Bdmx[DMX].flush_fx(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=c)
  470. else:
  471. Bdmx[DMX].fx(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=c)
  472. elif type(fx) is str and fx: # old fx like sinus:200:12:244
  473. ccm = str(DMX+1)+":"+fx
  474. print("fx",ccm)
  475. if "FLASH" in x:
  476. CB({"cmd":"fxf"+ccm})
  477. else:
  478. CB({"cmd":"fx"+ccm})
  479. print(time.time()-t_start)
  480. print(time.time())
  481. return
  482. except Exception as e:
  483. cprint("EXCEPTION JCB",e,color="red")
  484. cprint("----",jdata,color="red")
  485. cprint("Error on line {}".format(sys.exc_info()[-1].tb_lineno),color="red")
  486. def CB(data): # raw/text client input
  487. #print("CB",data)
  488. cmds = split_cmd(data)
  489. c = clock.time()
  490. c = float(c)
  491. ftime = 0
  492. delay = 0
  493. for xcmd in cmds:
  494. if xcmd:
  495. cprint("CB",xcmd,end=" ")
  496. pass
  497. else:
  498. continue
  499. if xcmd.startswith("fxf"):
  500. xxcmd=xcmd[3:].split(":")
  501. #print("fxf:",xxcmd)
  502. if "alloff" == xxcmd[1].lower():
  503. for i in Bdmx:
  504. if i is not None:
  505. i.flush_fx(xtype="off",clock=c)
  506. l = xxcmd
  507. try:
  508. xtype=""
  509. size=40
  510. speed=100
  511. start=0
  512. offset=0
  513. base=""
  514. k=int(l[0])-1
  515. xtype=l[1]
  516. if len(l) >= 3:
  517. try:size=int(l[2])
  518. except:pass
  519. if len(l) >= 4:
  520. try:speed=int(l[3])
  521. except:pass
  522. if len(l) >= 5:
  523. try:start=int(l[4])
  524. except:pass
  525. if len(l) >= 6:
  526. try:offset=int(l[5])
  527. except:pass
  528. if len(l) >= 7:
  529. try:base=l[6]
  530. except:pass
  531. if len(Bdmx) > k:
  532. #Bdmx[k].fade(target=v,ftime=t, clock=c)
  533. Bdmx[k].flush_fx(xtype=xtype,size=size,speed=speed,start=start,offset=offset,base=base,clock=c)
  534. except Exception as e:
  535. print("EXCEPTION IN FX",e)
  536. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  537. elif xcmd.startswith("fx"):
  538. xxcmd=xcmd[2:].split(":")
  539. print("DMX:",xxcmd)
  540. if len(xxcmd) < 2:
  541. print("xxcmd err",xxcmd,xcmd)
  542. continue
  543. if "alloff" == xxcmd[1].lower():
  544. for i in Bdmx:
  545. i.fx(xtype="off",clock=c)
  546. l = xxcmd
  547. try:
  548. xtype=""
  549. size=40
  550. speed=100
  551. start=0
  552. offset=0
  553. base=""
  554. k=int(l[0])-1
  555. xtype=l[1]
  556. if len(l) >= 3:
  557. try:size=int(l[2])
  558. except:pass
  559. if len(l) >= 4:
  560. try:speed=int(l[3])
  561. except:pass
  562. if len(l) >= 5:
  563. try:start=int(l[4])
  564. except:pass
  565. if len(l) >= 6:
  566. try:offset=int(l[5])
  567. except:pass
  568. if len(l) >= 7:
  569. try:base=l[6]
  570. except:pass
  571. if len(Bdmx) > k:
  572. #Bdmx[k].fade(target=v,ftime=t, clock=c)
  573. Bdmx[k].fx(xtype=xtype,size=size,speed=speed,start=start,offset=offset,base=base,clock=c)
  574. except Exception as e:
  575. print("EXCEPTION IN FX",xcmd,e)
  576. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  577. #jchat = chat.CMD(CB,port=50001) # server listener
  578. #thread.start_new_thread(jchat.poll,())
  579. chat.cmd(JCB) # server listener
  580. #chat.cmd(JCB,port=50001) # server listener
  581. #input("END")