console.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  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.run = 1
  219. self.__angel = self.__clock_curr*360%360
  220. def __str__(self):
  221. return self.__repr__()
  222. def __repr__(self):
  223. return "<FX Next:{:0.2f} xtype:{} Size:{:0.2f} Speed:{:0.2f} ang:{:0.2f} base:{} Clock:{:0.2f} run:{}>".format(
  224. self.next(),self.__xtype, self.__size,self.__speed,self.__angel, self.__base,self.__clock_curr,self.run )
  225. def next(self,clock=None):
  226. if type(clock) is float or type(clock) is int:#not None:
  227. self.__clock_curr = clock
  228. t = self.__clock_curr * self.__speed / 255
  229. t += self.__offset / 1024 #255
  230. t += self.__start / 1024 #255
  231. tw = t%1
  232. if tw > self.__width/100:
  233. if self.__invert:
  234. return 0
  235. else:
  236. return self.__size*-1
  237. t = t * (100/self.__width)
  238. self.__angel = t%1*360 #self.__clock_curr%1 #*360%360
  239. t = t%1
  240. rad = math.radians(self.__angel)
  241. base = 0
  242. if self.__base == "+": # add
  243. base = self.__size
  244. elif self.__base == "-": # sub
  245. base = self.__size*-1
  246. # todo start angle 20°
  247. # todo width angle 90°
  248. #print("{:0.2f} {:0.2f} {:0.2f} {:0.2f}".format(self.__angel ,self.__clock_curr,self.__angel ,math.sin(rad) ) )
  249. out = 0
  250. if self.__xtype == "sinus":
  251. out = math.sin( rad ) * self.__size/2 + base/2
  252. elif self.__xtype == "cosinus":
  253. out = math.cos( rad ) * self.__size/2 + base/2
  254. elif self.__xtype == "on2":
  255. out = self.__size/2
  256. if self.__angel > 90 and self.__angel <=270:
  257. out *=-1
  258. out += base/2
  259. print("ON {:0.2f} {:0.2f} {:0.2f} {:0.2f}".format(out,t,0,self.__angel, base))
  260. #return out
  261. elif self.__xtype == "on":
  262. out = self.__size/2
  263. if self.__angel > 90 and self.__angel <=270:
  264. pass
  265. else:
  266. out *=-1
  267. out += base/2
  268. #return out
  269. elif self.__xtype == "bump":
  270. out = 0
  271. if self.__base == "-": # sub
  272. out = (t%1-1) * self.__size
  273. elif self.__base == "+": # sub
  274. out = (t%1) * self.__size
  275. else:
  276. out = (t%1-0.5) * self.__size
  277. #print("bump",out)
  278. #return out
  279. elif self.__xtype == "bump2":
  280. out = 0
  281. if self.__base == "+": # sub
  282. out = (t%1-1) * (self.__size *-1)
  283. elif self.__base == "-": # sub
  284. out = (t%1) * (self.__size *-1)
  285. else:
  286. out = (t%1-0.5) * (self.__size *-1)
  287. #print("bump",out)
  288. #return out
  289. elif self.__xtype == "fade":
  290. x = t * 2
  291. if x > 1:
  292. x = 2-x
  293. x -= 0.5
  294. out = x * self.__size + base/2
  295. #print("FADE {:0.2f} {:0.2f} {:0.2f} {:0.2f}".format(out,t,x,self.__angel, base))
  296. #return out
  297. if self.__invert:
  298. return out
  299. else:
  300. return self.__size*-1 -out
  301. return out
  302. class DMXCH(object):
  303. def __init__(self):
  304. self._base_value = 0
  305. self._fade = None
  306. self._fx = None
  307. self._fx_value = 0
  308. self._flush = None
  309. self._flush_fx = None
  310. self._flush_fx_value = 0
  311. self._last_val = None
  312. def fade(self,target,ftime=0,clock=0,delay=0):
  313. if target != self._base_value:
  314. try:
  315. target = float(target)
  316. self._fade = Fade(self._base_value,target,ftime=ftime,clock=clock,delay=delay)
  317. #self._fade.next()
  318. #self._fade.next()
  319. except Exception as e:
  320. print( "Except:fade",e,target,ftime,clock)
  321. def fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="", clock=0):
  322. print([self,xtype,size,speed,start,offset,base, clock])
  323. if str(xtype).lower() == "off":
  324. #self._fx = Fade(self._fx_value,target=0,ftime=2,clock=clock)
  325. self._fx = None
  326. self._fx_value = 0
  327. else:
  328. self._fx = FX(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=clock)
  329. def flush(self,target,ftime=0,clock=0,delay=0):
  330. if str(target).lower() == "off":
  331. self._flush = None
  332. else:#elif target != self._base_value:
  333. try:
  334. target = float(target)
  335. self._flush = Fade(self._last_val,target,ftime=ftime,clock=clock,delay=delay)
  336. except Exception as e:
  337. print( "Except:flush",target,ftime,clock,__name__,e,)
  338. def flush_fx(self,xtype="sinus",size=40,speed=40,invert=0,width=100,start=0,offset=0,base="",clock=0):
  339. if str(xtype).lower() == "off":
  340. #self._fx = Fade(self._fx_value,target=0,ftime=2,clock=clock)
  341. self._flush_fx = None
  342. self._flush_fx_value = 0
  343. else:
  344. self._flush_fx = FX(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=clock)
  345. def fx_ctl(self,cmd=""):#start,stop,off
  346. pass
  347. def __str__(self):
  348. return self.__repr__()
  349. def __repr__(self):
  350. return "< DMXCH {:0.2f} > {} {}".format( self._last_val,self._fx,self._fade)
  351. def fade_ctl(self,cmd=""):#start,stop,backw,fwd,bounce
  352. pass
  353. def next(self,clock=0):
  354. value = self._base_value
  355. if self._last_val is None:
  356. self._last_val = value
  357. fx_value = self._fx_value
  358. if self._flush is not None:
  359. value = self._flush.next(clock)
  360. #flicker bug ?!
  361. value = self._flush.next(clock)
  362. fx_value = 0
  363. elif self._fade is not None:#is Fade:# is Fade:
  364. self._base_value = self._fade.next(clock)
  365. #flicker bug ?!
  366. self._base_value = self._fade.next(clock)
  367. value = self._base_value
  368. if self._flush_fx is not None:# is FX:
  369. fx_value = self._flush_fx.next(clock)
  370. elif self._fx is not None and self._flush is None:# is FX:
  371. self._fx_value = self._fx.next(clock)
  372. fx_value = self._fx_value
  373. self._last_val = value+fx_value
  374. return self._last_val
  375. Bdmx = []
  376. for i in range(512*3):
  377. Bdmx.append( DMXCH() )
  378. #print(type(dmx[i]))
  379. def split_cmd(data):
  380. if "cmd" in data:
  381. cmd = data["cmd"]
  382. #print("cmd",cmd)
  383. if "," in cmd:
  384. cmds = cmd.split(",")
  385. else:
  386. cmds = [cmd]
  387. return cmds
  388. import time
  389. import json
  390. def JCB(data):
  391. t_start = time.time()
  392. #jdatas = data["cmd"].split("\x00")
  393. jdatas = [data["cmd"]]
  394. c = clock.time()
  395. c = float(c)
  396. print("JCB",round(c,2))
  397. ftime = 0
  398. delay = 0
  399. for j in jdatas:
  400. if not j:
  401. continue
  402. try:
  403. jdata = j #jdatas[j]
  404. jtxt = jdata
  405. #jtxt = zlib.decompress(jtxt) #jtxt.decode())
  406. jtxt = str(jtxt,"UTF-8")
  407. cmds = json.loads(jtxt)
  408. for x in cmds:
  409. #cprint(int(clock.time()*1000)/1000,end=" ",color="yellow")#time.time())
  410. #cprint("json", x,type(x),color="yellow")#,cmds[x])
  411. if "DMX" in x:
  412. DMX = int(x["DMX"])
  413. else:continue
  414. if DMX > 0:
  415. DMX -=1
  416. else:continue
  417. if "VALUE" in x:# and x["VALUE"] is not None:
  418. v = x["VALUE"]
  419. else:continue
  420. if "FX" in x:# and x["VALUE"] is not None:
  421. fx = x["FX"]
  422. else:fx=""
  423. if "FX2" in x:# and x["VALUE"] is not None:
  424. fx2 = x["FX2"]
  425. else:fx2={}
  426. if "FADE" in x:
  427. ftime = x["FADE"]
  428. else:ftime=0
  429. if "DELAY" in x:
  430. delay = x["DELAY"]
  431. else:delay=0
  432. if len(Bdmx) < DMX:
  433. continue
  434. if v is not None:
  435. if "FLASH" in x:
  436. #print("FLASH")
  437. Bdmx[DMX].flush(target=v,ftime=ftime, clock=c,delay=delay)
  438. else:
  439. #print("FADE")
  440. Bdmx[DMX].fade(target=v,ftime=ftime, clock=c,delay=delay)
  441. if type(fx2) is dict and fx2:
  442. #cprint("FX2",DMX,fx2,color="green")
  443. xtype="fade"
  444. size = 10
  445. speed = 10
  446. start = 0
  447. offset= 0
  448. width=100
  449. invert=0
  450. base = "-"
  451. if "TYPE" in fx2:
  452. xtype = fx2["TYPE"]
  453. if "SIZE" in fx2:
  454. size = fx2["SIZE"]
  455. if "SPEED" in fx2:
  456. speed = fx2["SPEED"]
  457. if "OFFSET" in fx2:
  458. offset = fx2["OFFSET"]
  459. if "BASE" in fx2:
  460. base = fx2["BASE"]
  461. if "INVERT" in fx2:
  462. invert = fx2["INVERT"]
  463. if "WIDTH" in fx2:
  464. width = fx2["WIDTH"]
  465. if "alloff" == xtype.lower():
  466. for i in Bdmx:
  467. if i is not None:
  468. i.flush_fx(xtype="off",clock=c)
  469. i.fx(xtype="off",clock=c)
  470. if "FLASH" in x:
  471. Bdmx[DMX].flush_fx(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=c)
  472. else:
  473. Bdmx[DMX].fx(xtype=xtype,size=size,speed=speed,invert=invert,width=width,start=start,offset=offset,base=base,clock=c)
  474. elif type(fx) is str and fx: # old fx like sinus:200:12:244
  475. ccm = str(DMX+1)+":"+fx
  476. print("fx",ccm)
  477. if "FLASH" in x:
  478. CB({"cmd":"fxf"+ccm})
  479. else:
  480. CB({"cmd":"fx"+ccm})
  481. print(time.time()-t_start)
  482. print(time.time())
  483. return
  484. except Exception as e:
  485. cprint("EXCEPTION JCB",e,color="red")
  486. cprint("----",jdata,color="red")
  487. cprint("Error on line {}".format(sys.exc_info()[-1].tb_lineno),color="red")
  488. def CB(data):
  489. #print("CB",data)
  490. cmds = split_cmd(data)
  491. c = clock.time()
  492. c = float(c)
  493. ftime = 0
  494. delay = 0
  495. for xcmd in cmds:
  496. if xcmd:
  497. cprint("CB",xcmd,end=" ")
  498. pass
  499. else:
  500. continue
  501. if xcmd.startswith("fxf"):
  502. xxcmd=xcmd[3:].split(":")
  503. #print("fxf:",xxcmd)
  504. if "alloff" == xxcmd[1].lower():
  505. for i in Bdmx:
  506. if i is not None:
  507. i.flush_fx(xtype="off",clock=c)
  508. l = xxcmd
  509. try:
  510. xtype=""
  511. size=40
  512. speed=100
  513. start=0
  514. offset=0
  515. base=""
  516. k=int(l[0])-1
  517. xtype=l[1]
  518. if len(l) >= 3:
  519. try:size=int(l[2])
  520. except:pass
  521. if len(l) >= 4:
  522. try:speed=int(l[3])
  523. except:pass
  524. if len(l) >= 5:
  525. try:start=int(l[4])
  526. except:pass
  527. if len(l) >= 6:
  528. try:offset=int(l[5])
  529. except:pass
  530. if len(l) >= 7:
  531. try:base=l[6]
  532. except:pass
  533. if len(Bdmx) > k:
  534. #Bdmx[k].fade(target=v,ftime=t, clock=c)
  535. Bdmx[k].flush_fx(xtype=xtype,size=size,speed=speed,start=start,offset=offset,base=base,clock=c)
  536. except Exception as e:
  537. print("EXCEPTION IN FX",e)
  538. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  539. elif xcmd.startswith("fx"):
  540. xxcmd=xcmd[2:].split(":")
  541. print("DMX:",xxcmd)
  542. if len(xxcmd) < 2:
  543. print("xxcmd err",xxcmd,xcmd)
  544. continue
  545. if "alloff" == xxcmd[1].lower():
  546. for i in Bdmx:
  547. i.fx(xtype="off",clock=c)
  548. l = xxcmd
  549. try:
  550. xtype=""
  551. size=40
  552. speed=100
  553. start=0
  554. offset=0
  555. base=""
  556. k=int(l[0])-1
  557. xtype=l[1]
  558. if len(l) >= 3:
  559. try:size=int(l[2])
  560. except:pass
  561. if len(l) >= 4:
  562. try:speed=int(l[3])
  563. except:pass
  564. if len(l) >= 5:
  565. try:start=int(l[4])
  566. except:pass
  567. if len(l) >= 6:
  568. try:offset=int(l[5])
  569. except:pass
  570. if len(l) >= 7:
  571. try:base=l[6]
  572. except:pass
  573. if len(Bdmx) > k:
  574. #Bdmx[k].fade(target=v,ftime=t, clock=c)
  575. Bdmx[k].fx(xtype=xtype,size=size,speed=speed,start=start,offset=offset,base=base,clock=c)
  576. except Exception as e:
  577. print("EXCEPTION IN FX",xcmd,e)
  578. print("Error on line {}".format(sys.exc_info()[-1].tb_lineno))
  579. #jchat = chat.CMD(CB,port=50001) # server listener
  580. #thread.start_new_thread(jchat.poll,())
  581. chat.cmd(JCB) # server listener
  582. #chat.cmd(JCB,port=50001) # server listener
  583. #input("END")