fixlib.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750
  1. #!/usr/bin/python3
  2. import os
  3. import json
  4. import time
  5. import __main__ as MAIN
  6. from collections import OrderedDict
  7. from lib.cprint import *
  8. from pathlib import Path
  9. home_dir = str(Path.home())
  10. def _fixture_decode_sav_line(line):
  11. out = None
  12. out = [0,"none",{}]
  13. if line.count("\t") < 2:
  14. cprint("Error line.count('\\t') < 2 (is:{})".format(line.count("\t")),color="red",end=" ")
  15. cprint("file:{}".format(line),color="red")
  16. else:
  17. key,label,rdata = line.split("\t",2)
  18. jdata = json.loads(rdata,object_pairs_hook=OrderedDict)
  19. key = int(key)
  20. #label += " dsav"
  21. #label = label.replace(" dsav","")
  22. out = [key,label,jdata]
  23. #if not out:
  24. #print(line)
  25. #sys.exit()
  26. return out
  27. def _fixture_repair_nr0(jdata):
  28. nrnull = 0
  29. if "ATTRIBUT" in jdata: # translate old Fixtures.fixtures start with 0 to 1
  30. if nrnull:
  31. cprint("DMX NR IS NULL",attr,"CHANGE +1")
  32. for attr in jdata["ATTRIBUT"]:
  33. if "NR" in jdata["ATTRIBUT"][attr]:
  34. nr = jdata["ATTRIBUT"][attr]["NR"]
  35. if nr >= 0:
  36. jdata["ATTRIBUT"][attr]["NR"] +=1
  37. #return jdata
  38. def FIXTURE_CHECK_SDATA(ID,sdata):
  39. #print("FIXTURE_CHECK_SDATA",ID)
  40. new_f = OrderedDict()
  41. #print("++++")
  42. for k,j in sdata.items():
  43. overide=0 # only for repair
  44. if overide:
  45. if k in ["TYPE","VENDOR"]: #ignor
  46. continue
  47. new_f[k] = j
  48. if k =="NAME":
  49. #print("AAAADDDDDD")
  50. if "TYPE" not in sdata and not overide:
  51. if len( sdata["ATTRIBUT"]) == 1:
  52. new_f["TYPE"] = "DIMMER"
  53. elif "PAN" in sdata["ATTRIBUT"]:
  54. new_f["TYPE"] = "MOVER"
  55. elif "RED" in sdata["ATTRIBUT"] and len(sdata["ATTRIBUT"]) == 3:
  56. new_f["TYPE"] = "RGB"
  57. elif "RED" in sdata["ATTRIBUT"]:
  58. new_f["TYPE"] = "LED"
  59. elif "CYAN" in sdata["ATTRIBUT"]:
  60. new_f["TYPE"] = "COLOR"
  61. else:
  62. new_f["TYPE"] = ""
  63. if "VENDOR" not in sdata and not overide:
  64. new_f["VENDOR"] = ""
  65. #print(k,j)#,sdata)
  66. sdata = new_f
  67. if "ACTIVE" not in sdata:
  68. sdata["ACTIVE"] = 0
  69. sdata["ATTRIBUT"]["_ACTIVE"] = OrderedDict()
  70. sdata["ATTRIBUT"]["_ACTIVE"]["NR"] = 0
  71. sdata["ATTRIBUT"]["_ACTIVE"]["ACTIVE"] = 1
  72. sdata["ATTRIBUT"]["_ACTIVE"]["VALUE"] = 0
  73. sdata["ATTRIBUT"]["_ACTIVE"]["FX2"] = {}
  74. sdata["ATTRIBUT"]["_ACTIVE"]["FX"] = ""
  75. DEL = []
  76. for ATTR in list(sdata["ATTRIBUT"].keys()):
  77. if ATTR.startswith("_"):
  78. continue
  79. if ATTR.endswith(" FINE"):
  80. ATTR2 = ATTR.replace(" FINE","-FINE")
  81. ATTR2 = ATTR2.replace(" -","-")
  82. ATTR2 = ATTR2.replace(" "," ")
  83. ATTR2 = ATTR2.replace(" "," ")
  84. ATTR2 = ATTR2.replace(" "," ")
  85. if ATTR2 not in sdata["ATTRIBUT"]:
  86. print(" CHECK_SDATA REPAIR",[ATTR,ATTR2])
  87. sdata["ATTRIBUT"][ATTR2] = sdata["ATTRIBUT"][ATTR]
  88. DEL.append(ATTR)
  89. for d in DEL:
  90. if d in sdata["ATTRIBUT"]:
  91. print(" CHECK_SDATA DEL ",[d],"!")
  92. del sdata["ATTRIBUT"][d]
  93. if "DIM" not in sdata["ATTRIBUT"]:
  94. _tmp = None
  95. #print(sdata)
  96. vdim_count = 0
  97. for a in ["RED","GREEN","BLUE"]:#,"WHITE","AMBER"]:
  98. if a in sdata["ATTRIBUT"]:
  99. vdim_count +=1
  100. if vdim_count == 3:
  101. _tmp = {"NR": 0, "MASTER": "0", "MODE": "F", "VALUE": 255, "ACTIVE": 0, "FX": "", "FX2": {}}
  102. _tmp = OrderedDict(_tmp)
  103. sdata["ATTRIBUT"]["DIM"] =_tmp
  104. print(" ADD ---- VDIM",vdim_count,_tmp)
  105. #input("STOP")
  106. for attr in sdata["ATTRIBUT"]:
  107. row = sdata["ATTRIBUT"][attr]
  108. row["ACTIVE"] = 0
  109. if "FX" not in row:
  110. row["FX"] =""
  111. if "FX2" not in row:
  112. row["FX2"] = {}
  113. if "MASTER" not in row:
  114. row["MASTER"] = 0
  115. if "ID" not in sdata:
  116. sdata["ID"] = str(ID)
  117. return sdata
  118. def _parse_fixture_name(name):
  119. out = []
  120. #{"FIX","MAN","CH","PATH":""}
  121. if name.count(".") == 2:
  122. m,n,e = name.split(".")
  123. #out = [n,m,"0",name]
  124. out = {"name":n,"manufactor":m,"fname":name}
  125. elif name.count("_") == 2:
  126. name,e = name.split(".")
  127. m,n,c = name.split("_")
  128. out = {"name":n,"ch":c,"manufactor":m,"name":name}
  129. #out = [n,m,c,name]
  130. else:
  131. out = {"name":name}
  132. return out
  133. def index_fixtures():
  134. p="/opt/LibreLight/Xdesk/fixtures/"
  135. ls = os.listdir(p )
  136. ls.sort()
  137. blist = []
  138. for l in ls:
  139. b = _parse_fixture_name(l)
  140. b.append(p)
  141. b.insert(0,"base")
  142. blist.append(b)
  143. return blist
  144. #def _fixture_create_import_list(path=None):
  145. def _fixture_load_import_list(path=None):
  146. if not path:
  147. path = home_dir+"/LibreLight/show"
  148. blist = []
  149. lsd = os.listdir(path)
  150. lsd.sort()
  151. fname_buffer = []
  152. for sname in lsd:
  153. #print(" ",sname)
  154. ok = 0
  155. try:
  156. fname = path+"/"+sname+"/patch.sav"
  157. if os.path.isfile(fname):
  158. ok = 1
  159. else:
  160. fname = path+"/"+sname
  161. if os.path.isfile(fname):
  162. ok = 1
  163. #fname_buffer = []
  164. if not ok:
  165. continue
  166. f = open(fname)
  167. lines = f.readlines()
  168. f.close()
  169. for line in lines:
  170. ok2 = 0
  171. _key = ""
  172. line = line.split("\t")
  173. if len(line) < 2:
  174. continue
  175. jdata = json.loads(line[2])
  176. fixture = jdata
  177. _len = str(fixture_get_ch_count(fixture))
  178. if "ATTRIBUT" in jdata:
  179. #_len = len(jdata["ATTRIBUT"])
  180. #if "_ACTIVE" in jdata["ATTRIBUT"]:
  181. # _len -= 1
  182. _key = list(jdata["ATTRIBUT"].keys())
  183. _key.sort()
  184. _key = str(_key)
  185. if _key not in fname_buffer:
  186. fname_buffer.append(_key) # group same fixtures by ATTR
  187. ok2 = 1
  188. if ok2:
  189. name = jdata["NAME"]
  190. #row = [name,fname+":"+name,path])
  191. xfname = fname.replace(path,"")
  192. row = {"xfname":xfname ,"name":name,"ch":_len, "xpath":path,"d":_key} #,"b":jdata}
  193. blist.append(row)
  194. except Exception as e:
  195. print("exception",e)
  196. raise e
  197. return blist
  198. def fixture_get_ch_count(fixture):
  199. _len = [0,0]
  200. if "ATTRIBUT" not in fixture:
  201. return [-1,-1]
  202. for at in fixture["ATTRIBUT"]:
  203. #print(at,_len)
  204. #print(" ",fixture["ATTRIBUT"][at])
  205. if not at.startswith("_") and not at.startswith("EMPTY"):
  206. _len[1] += 1
  207. if "NR" in fixture["ATTRIBUT"][at]:
  208. NR = fixture["ATTRIBUT"][at]["NR"]
  209. if NR > _len[0]:
  210. _len[0] = NR
  211. #print("-",at,_len)
  212. return _len
  213. def fixture_get_attr_data(fixture,attr):
  214. if "ATTRIBUT" in fixture:
  215. if attr in fixture["ATTRIBUT"]:
  216. return fixture["ATTRIBUT"][attr]
  217. if "NAME" in fixture:
  218. print(" NO fixture_get_attr_data A",fixture["NAME"],attr)
  219. else:
  220. print(" NO fixture_get_attr_data B",fixture,attr)
  221. def fixture_order_attr_by_nr(fixture):
  222. out1 = []
  223. max_nr = 0
  224. if "ATTRIBUT" not in fixture:
  225. return []
  226. nrs = {}
  227. for at in fixture["ATTRIBUT"]:
  228. #print("+ ",at)
  229. atd = fixture_get_attr_data(fixture,at)
  230. #print("+ ",atd)
  231. if not atd:
  232. continue
  233. k = atd["NR"]
  234. v = at
  235. nrs[k] = v
  236. if k > max_nr:
  237. max_nr = k
  238. for i in range(1,max_nr+1):
  239. if i not in nrs:
  240. v = "EMPTY" #-{}".format(i)
  241. nrs[i] = v
  242. #print("-: ",v)
  243. nrs_key = list(nrs.keys())
  244. nrs_key.sort()
  245. #print(nrs_key)
  246. for k in nrs_key:
  247. v = nrs[k]
  248. #print("-: ",k,v)
  249. out1.append(v)
  250. #print()
  251. return out1
  252. def _load_fixture_list(mode="None"):
  253. blist = []
  254. if mode == "USER":
  255. path = home_dir+"/LibreLight/fixtures/"
  256. elif mode == "GLOBAL":
  257. path="/opt/LibreLight/Xdesk/fixtures/"
  258. elif mode == "IMPORT":
  259. path=None
  260. _r = _fixture_load_import_list(path=path)
  261. blist.extend( _r )
  262. return blist
  263. def get_attr(fixtures,fix,attr):
  264. if fix in fixtures:
  265. data = fixtures[fix]
  266. if "ATTRIBUT" in data:
  267. if attr in data["ATTRIBUT"]:
  268. return data["ATTRIBUT"][attr]
  269. def get_dmx(fixtures,fix,attr):
  270. #cprint("get_dmx",[fix,attr], fix in self.fixtures)
  271. DMX = -99
  272. if attr.startswith("_"):
  273. return -88
  274. if fix in fixtures:
  275. data = fixtures[fix]
  276. if "DMX" in data:
  277. DMX = int(data["DMX"])
  278. if DMX <= 0:
  279. return DMX # VIRTUAL FIX
  280. if "UNIVERS" in data:
  281. DMX += int(data["UNIVERS"])*512
  282. #adata = self.get_attr(fix,attr)
  283. adata = get_attr(fixtures,fix,attr)
  284. if adata:
  285. if "NR" in adata:
  286. NR = adata["NR"]
  287. if NR <= 0:
  288. return -12 # not a VIRTUAL ATTR
  289. else:
  290. DMX+=NR-1
  291. return DMX
  292. return -199
  293. def get_active(fixtures,_filter=""): #_filter only-fx
  294. cprint("fixlib.get_active",_filter)
  295. CFG = OrderedDict()
  296. sdata = OrderedDict()
  297. sdata["CFG"] = CFG # OrderedDict()
  298. sdata["CFG"]["FADE"] = MAIN.meta.FADE.val()
  299. sdata["CFG"]["DEALY"] = 0
  300. for fix in fixtures:
  301. data = fixtures[fix]
  302. for attr in data["ATTRIBUT"]:
  303. if not data["ATTRIBUT"][attr]["ACTIVE"]:
  304. continue
  305. if fix not in sdata:
  306. sdata[fix] = {}
  307. if attr not in sdata[fix]:
  308. sdata[fix][attr] = OrderedDict()
  309. if "ONLY-FX" in _filter:
  310. #cprint( " ONLY FX !!! -------------------- ")
  311. sdata[fix][attr]["VALUE"] = None
  312. else:
  313. sdata[fix][attr]["VALUE"] = data["ATTRIBUT"][attr]["VALUE"]
  314. if "FX" not in data["ATTRIBUT"][attr]:
  315. data["ATTRIBUT"][attr]["FX"] = ""
  316. if "FX2" not in data["ATTRIBUT"][attr]:
  317. data["ATTRIBUT"][attr]["FX2"] = {}
  318. sdata[fix][attr]["FX"] = data["ATTRIBUT"][attr]["FX"]
  319. sdata[fix][attr]["FX2"] = data["ATTRIBUT"][attr]["FX2"]
  320. return sdata
  321. def _deselect_all(fixtures,fix=None):
  322. cprint("fixlib._deselect_all()",fix,"ALL",color="yellow")
  323. c=0
  324. if fix in fixtures:
  325. data = fixtures[fix]
  326. for attr in data["ATTRIBUT"]:
  327. #print("SELECT ALL",fix,attr)
  328. if "-FINE" in attr.upper():
  329. pass
  330. else:
  331. c+=select(fixtures,fix,attr,mode="off",mute=1)
  332. return c
  333. def _select_all(fixtures,fix=None,mode="toggle",mute=0):
  334. if not mute:
  335. cprint("fixlib._select_all()",fix,"ALL",mode,color="yellow")
  336. c=0
  337. if fix in fixtures:
  338. data = fixtures[fix]
  339. for attr in data["ATTRIBUT"]:
  340. #print("SELECT ALL",fix,attr)
  341. if "-FINE" in attr.upper():
  342. continue
  343. if mode == "toggle":
  344. c+=select(fixtures,fix,attr,mode="on",mute=mute)
  345. elif mode == "swap":
  346. if not attr.startswith("_"):
  347. c+=select(fixtures,fix,attr,mode="toggle",mute=mute)
  348. if not c and mode == "toggle": # unselect all
  349. c= _deselect_all(fixtures,fix=fix)
  350. return c
  351. def select(fixtures,fix=None,attr=None,mode="on",mute=0):
  352. if not mute:
  353. cprint("fixlib.select() >>",fix,attr,mode,color="yellow")
  354. out = 0
  355. if fix == "SEL":
  356. if attr.upper() == "INV-ATTR":
  357. fixs = get_active(fixtures)
  358. cprint("selected:",len(fixs))
  359. for fix in fixs:
  360. x=_select_all(fixtures,fix=fix,mode=mode,mute=1)
  361. return None
  362. if fix in fixtures:
  363. if attr.upper() == "ALL":
  364. x=_select_all(fixtures,fix=fix,mode=mode)
  365. return x
  366. data = fixtures[fix]
  367. if attr in data["ATTRIBUT"]:
  368. if mode == "on":
  369. if not data["ATTRIBUT"][attr]["ACTIVE"]:
  370. data["ATTRIBUT"][attr]["ACTIVE"] = 1
  371. data["ATTRIBUT"]["_ACTIVE"]["ACTIVE"] = 1
  372. out = 1
  373. elif mode == "off":
  374. if data["ATTRIBUT"][attr]["ACTIVE"]:
  375. data["ATTRIBUT"][attr]["ACTIVE"] = 0
  376. out = 1
  377. elif mode == "toggle":
  378. if data["ATTRIBUT"][attr]["ACTIVE"]:
  379. data["ATTRIBUT"][attr]["ACTIVE"] = 0
  380. else:
  381. data["ATTRIBUT"][attr]["ACTIVE"] = 1
  382. data["ATTRIBUT"]["_ACTIVE"]["ACTIVE"] = 1
  383. out = 1
  384. return out
  385. def clear(fixtures):
  386. out = 0
  387. for fix in fixtures:
  388. data = fixtures[fix]
  389. for attr in data["ATTRIBUT"]:
  390. #if attr.endswith("-FINE"):
  391. # continue
  392. if data["ATTRIBUT"][attr]["ACTIVE"]:
  393. out +=1
  394. data["ATTRIBUT"][attr]["ACTIVE"] = 0
  395. return out
  396. def encoder(fixtures,fix,attr,xval="",xfade=0,xdelay=0,blind=0):
  397. _blind = 0
  398. if MAIN.modes.val("BLIND"):
  399. _blind = 1
  400. if blind:
  401. _blind = 1
  402. if not _blind:
  403. cprint("fixlib.encoder",fix,attr,xval,xfade,color="yellow")
  404. if attr == "CLEAR":
  405. clear(fixtures)
  406. return 0
  407. if attr == "ALL":
  408. x=select(fixtures,fix,attr,mode="toggle")
  409. return x
  410. if attr == "INV-ATTR":
  411. cprint("-x-x-x-x-x-x-x-X-")
  412. x=select(fixtures,fix,attr,mode="swap")
  413. MAIN.master.refresh_fix()
  414. return x
  415. if attr == "INV-FIX":
  416. cprint("-x-x-x-x-x-x-x-x-")
  417. x=select(fixtures,fix,attr,mode="swap")
  418. return x
  419. out = []
  420. if fix not in fixtures:
  421. ii =0
  422. delay=0
  423. sstart = time.time()
  424. sub_data = []
  425. for _fix in fixtures:
  426. ii+=1
  427. data = fixtures[_fix]
  428. if "-FINE" in attr.upper():
  429. continue
  430. elif (attr in data["ATTRIBUT"] ) and "-FINE" not in attr.upper() :
  431. if xval == "click":
  432. select(fixtures,_fix,attr,mode="on")
  433. elif data["ATTRIBUT"][attr]["ACTIVE"]:
  434. if _fix:
  435. sub_data.append([_fix,attr,xval,xfade,delay])
  436. if MAIN.meta.DELAY._is():
  437. pass #delay += MAIN.meta.DELAY.val()/100
  438. sub_jdata = []
  439. for dd in sub_data:
  440. _x123 = encoder(fixtures,dd[0],dd[1],dd[2],dd[3],dd[4],1)
  441. sub_jdata.append(_x123)
  442. if sub_jdata:
  443. cprint(" SEND MASTER ENCODER:",len(sub_data),sub_data[0],"... _blind:",_blind)#,end="")
  444. if not _blind:
  445. MAIN.jclient_send(sub_jdata)
  446. #for ia in sub_jdata:
  447. # print("SOND:",ia)
  448. jdata=[{"MODE":ii}]
  449. if not _blind:
  450. MAIN.jclient_send(jdata)
  451. return sub_jdata #len(sub_data)
  452. data = fixtures[fix]
  453. if xval == "click":
  454. return select(fixtures,fix,attr,mode="toggle")
  455. v2=data["ATTRIBUT"][attr]["VALUE"]
  456. change=0
  457. increment = 5 #4.11
  458. jdata = {"MODE":"ENC"}
  459. if xval == "++":
  460. v2+= increment
  461. jdata["INC"] = increment
  462. change=1
  463. elif xval == "--":
  464. jdata["INC"] = increment*-1
  465. v2-= increment
  466. change=1
  467. elif xval == "+":
  468. increment = 0.25 #.5
  469. v2+= increment
  470. jdata["INC"] = increment
  471. change=1
  472. elif xval == "-":
  473. increment = 0.25 #.5
  474. jdata["INC"] = increment*-1
  475. v2-= increment
  476. change=1
  477. elif type(xval) is int or type(xval) is float:
  478. v2 = xval
  479. change=1
  480. if v2 < 0:
  481. v2=0
  482. elif v2 > 256:
  483. v2=256
  484. jdata["VALUE"] = round(v2,4)
  485. jdata["FIX"] = fix
  486. jdata["FADE"] = 0
  487. jdata["DELAY"] = 0
  488. jdata["ATTR"] = attr
  489. dmx = get_dmx(fixtures,fix,attr)
  490. jdata["DMX"] = dmx
  491. dmx_fine = get_dmx(fixtures,fix,attr+"-FINE")
  492. if dmx_fine != jdata["DMX"] and dmx > 0:
  493. jdata["DMX-FINE"] = dmx_fine
  494. out = {}
  495. if 1: #change:
  496. data["ATTRIBUT"][attr]["ACTIVE"] = 1
  497. data["ATTRIBUT"]["_ACTIVE"]["ACTIVE"] = 1
  498. data["ATTRIBUT"][attr]["VALUE"] = round(v2,4)
  499. if xfade:
  500. jdata["FADE"] = xfade
  501. if xdelay:
  502. #if attr not in ["PAN","TILT"] and 1:
  503. jdata["DELAY"] = xdelay
  504. if not _blind:
  505. jdata = [jdata]
  506. MAIN.jclient_send(jdata)
  507. time.sleep(0.001)
  508. return jdata
  509. import lib.showlib as showlib
  510. class Fixtures():
  511. def __init__(self):
  512. #super().__init__()
  513. self.base=showlib.Base()
  514. #self.load()
  515. self.fixtures = OrderedDict()
  516. def load_patch(self):
  517. cprint("Fixtures.load_patch ..")
  518. filename="patch"
  519. d,l = self.base._load(filename)
  520. self.fixtures = OrderedDict()
  521. for i in l:
  522. sdata = d[i]
  523. #sdata = self._repair_sdata(sdata)
  524. sdata = FIXTURE_CHECK_SDATA(i,sdata)
  525. self.fixtures[str(i)] = sdata
  526. self._re_sort()
  527. self.fx_off("all")
  528. def _re_sort(self):
  529. keys = list(self.fixtures.keys())
  530. keys2=[]
  531. for k in keys:
  532. #k = "{:0>5}".format(k)
  533. k = int(k)
  534. keys2.append(k)
  535. keys2.sort()
  536. fixtures2 = OrderedDict()
  537. for k in keys2:
  538. k = str(k)
  539. fixtures2[k] = self.fixtures[k]
  540. self.fixtures = fixtures2
  541. def backup_patch(self,save_as="",new=0):
  542. filename = "patch"
  543. #self.fx_off("all")
  544. data = self.fixtures
  545. labels = {}
  546. for k in data:
  547. labels[k] = k
  548. if new:
  549. data = []
  550. labels = {}
  551. return self.base._backup(filename,data,labels,save_as)
  552. def fx_get(self,fix=None):
  553. out={}
  554. if not fix or fix == "all":
  555. for fix in self.fixtures:
  556. data = self.fixtures[fix]
  557. for attr in data["ATTRIBUT"]:
  558. out[str(fix)+"."+str(attr)+".fx"] = data["ATTRIBUT"][attr]["FX"]
  559. out[str(fix)+"."+str(attr)+".fx"] = data["ATTRIBUT"][attr]["FX2"]
  560. return out
  561. def fx_off(self,fix=None):
  562. if not fix or fix == "all":
  563. for fix in self.fixtures:
  564. data = self.fixtures[fix]
  565. for attr in data["ATTRIBUT"]:
  566. data["ATTRIBUT"][attr]["FX"] = ""
  567. data["ATTRIBUT"][attr]["FX2"] = OrderedDict()
  568. def get_max_dmx_nr(self,fix):
  569. max_dmx = 0
  570. used_dmx = 0
  571. if fix not in self.fixtures:
  572. return (used_dmx,max_dmx)
  573. data = self.fixtures[fix]
  574. used_dmx = len(data["ATTRIBUT"])
  575. for a in data["ATTRIBUT"]:
  576. attr = data["ATTRIBUT"][a]
  577. if "NR" in attr:
  578. try:
  579. _n = int(attr["NR"])
  580. if _n > max_dmx:
  581. max_dmx=_n
  582. except ValueError:pass
  583. return (used_dmx,max_dmx)
  584. def update_raw(self,rdata,update=1):
  585. #cprint("update_raw",len(rdata))
  586. cmd = []
  587. for i,d in enumerate(rdata):
  588. xcmd = {"DMX":""}
  589. fix = d["FIX"]
  590. attr = d["ATTR"]
  591. v2 = d["VALUE"]
  592. v2_fx = d["FX"]
  593. if fix not in self.fixtures:
  594. continue
  595. sdata = self.fixtures[fix] #shortcat
  596. ATTR = sdata["ATTRIBUT"]
  597. if attr not in ATTR:
  598. continue
  599. sDMX = get_dmx(self.fixtures,fix,attr)
  600. #print(sDMX)
  601. xcmd["DMX"] = str(sDMX)
  602. cmd.append(xcmd)
  603. v=ATTR[attr]["VALUE"]
  604. if v2 is not None and update:
  605. ATTR[attr]["VALUE"] = v2
  606. if d["FX2"] and update:
  607. ATTR[attr]["FX2"] = d["FX2"]
  608. text = str(attr)+' '+str(round(v,2))
  609. return cmd