console.py 22 KB

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