fixlib.py 20 KB

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