| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249 |
- ##############################################
- # $Id: 32_WifiLight.pm 14607 2017-06-30 21:16:09Z herrmannj $
- # TODO
- # versions
- # 00 POC
- # ..
- # 50 Stable
- # 51 new milight color converter
- # 52 timing for transitions: drop frames if required
- # 53 transition names and events
- # 54 drop frames ll add-on / lock ll queue
- # 55 add ll queue lock count
- # 56 RGB in
- # 57 bridge v2
- # 58 gamma correction
- # 59 fix "off" with ramp
- # 60 add dimup/dimdown
- # 61 introduce dimSteps
- # 62 introduce defaultColor
- # 63 LW12 define if lw12 is unavailable at startup
- # 64 transition with ramp 0 fixed
- # 65 some typos with impact to RGBW1 and RGBW2
- # 66 readings: lower camelCase and limited trigger
- # 67 restore state after startup
- # 68 LW12 reconnect after timeout
- # 69 RGBW1 timing improved
- # 70 colorpicker
- # 71 default ramp attrib
- # 72 add LD316
- # 73 add LD382
- # 74 add color calibration (hue intersections) for RGB type controller
- # 75 add white point adjustment for RGB type controller
- # 76 add LW12 HX001
- # 77 milight RGBW2: critical cmds sendout repeatly
- # 78 add attrib for color managment (rgb types)
- # 79 add LD382 RGB ony mode
- # 80 HSV2fourChannel bug fixed (thnx to lexorius)
- # 81 LW12FC added
- # 82 LD382A (FW 1.0.6)
- # 83 fixed ramp handling (thnx to henryk)
- # 84 sengled boost added (thnx to scooty)
- # 85 milight white, improved reliability
- # 86 milight white, improved reliability / mark II
- # 87 milight rgbw2, dim bug
- # 88 readingFnAttributes
- # 89 add LD316A
- # 90 Sunricher poc
- # 91 milight colorcast fixed, more robust tcp re-connect
- # verbose level
- # 0: quit
- # 1: error
- # 2: warning
- # 3: user command
- # 4: 1st technical level (detailed internal reporting)
- # 5: 2nd technical level (full internal reporting)
- package main;
- use strict;
- use warnings;
- use IO::Handle;
- use IO::Socket;
- use IO::Select;
- use Time::HiRes;
- use Data::Dumper;
- use Color;
- sub
- WifiLight_Initialize(@)
- {
- my ($hash) = @_;
- FHEM_colorpickerInit();
- $hash->{DefFn} = "WifiLight_Define";
- $hash->{UndefFn} = "WifiLight_Undef";
- $hash->{ShutdownFn} = "WifiLight_Undef";
- $hash->{SetFn} = "WifiLight_Set";
- $hash->{GetFn} = "WifiLight_Get";
- $hash->{AttrFn} = "WifiLight_Attr";
- $hash->{NotifyFn} = "WifiLight_Notify";
- $hash->{AttrList} = "gamma dimStep defaultColor defaultRamp colorCast whitePoint"
- ." $readingFnAttributes";
-
- return undef;
- }
- sub
- WifiLight_Define($$)
- {
- my ($hash, $def) = @_;
- my @a = split("[ \t][ \t]*", $def);
- my $name = $a[0];
- my $key;
- return "wrong syntax: define <name> WifiLight <type> <connection>" if(@a != 4);
- # return "unknown LED type ($a[2]): choose one of RGB, RGBW, RGBW1, RGBW2, White" unless (grep /$a[2]/, ('RGB', 'RGBW', 'RGBW1', 'RGBW2', 'White'));
-
- $hash->{LEDTYPE} = $a[2];
- my $otherLights;
- if ($a[3] =~ m/(bridge-V2):([^:]+):*(\d+)*/g)
- {
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:50000;
- $hash->{PROTO} = 0;
- #my @hlCmdQueue = [];
- @{$hash->{helper}->{hlCmdQueue}} = (); #\@hlCmdQueue;
- # $hash->{SERVICE} = 48899; unkown for v2
- # search if this bridge is already defined
- # if so, we need a shared buffer (llCmdQueue), shared socket and we need to check if the requied slot is free
- foreach $key (keys %defs)
- {
- if (($defs{$key}{TYPE} eq 'WifiLight') && ($defs{$key}{IP} eq $hash->{IP}) && ($key ne $name))
- {
- #bridge is in use
- Log3 (undef, 3, "WifiLight: requested bridge $hash->{CONNECTION} at $hash->{IP} already in use by $key, copy llCmdQueue");
- $hash->{helper}->{llCmdQueue} = $defs{$key}{helper}{llCmdQueue};
- $hash->{helper}->{llLock} = 0;
- $hash->{helper}->{SOCKET} = $defs{$key}{helper}{SOCKET};
- $hash->{helper}->{SELECT} = $defs{$key}{helper}{SELECT};
- my $slotInUse = $defs{$key}{SLOT};
- $otherLights->{$slotInUse} = $defs{$key};
- }
- }
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => 48899,
- Blocking => 0,
- Proto => 'udp',
- Broadcast => 1) or return "can't bind: $@";
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = {};
- $hash->{helper}->{llLock} = 0;
- }
- }
- if ($a[3] =~ m/(bridge-V3):([^:]+):*(\d+)*/g)
- {
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:8899;
- $hash->{PROTO} = 0;
- #my @hlCmdQueue = [];
- @{$hash->{helper}->{hlCmdQueue}} = (); #\@hlCmdQueue;
- # $hash->{SERVICE} = 48899;
- # search if this bridge is already defined
- # if so, we need a shared buffer (llCmdQueue), shared socket and we need to check if the requied slot is free
- foreach $key (keys %defs)
- {
- if (($defs{$key}{TYPE} eq 'WifiLight') && ($defs{$key}{IP} eq $hash->{IP}) && ($key ne $name))
- {
- #bridge is in use
- Log3 (undef, 3, "WifiLight: requested bridge $hash->{CONNECTION} at $hash->{IP} already in use by $key, copy llCmdQueue");
- $hash->{helper}->{llCmdQueue} = $defs{$key}{helper}{llCmdQueue};
- $hash->{helper}->{llLock} = 0;
- $hash->{helper}->{SOCKET} = $defs{$key}{helper}{SOCKET};
- $hash->{helper}->{SELECT} = $defs{$key}{helper}{SELECT};
- my $slotInUse = $defs{$key}{SLOT};
- $otherLights->{$slotInUse} = $defs{$key};
- }
- }
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => 48899,
- Blocking => 0,
- Proto => 'udp',
- Broadcast => 1) or return "can't bind: $@";
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
-
- if ($a[3] =~ m/(LW12):([^:]+):*(\d+)*/g)
- {
- return "only RGB supported by LW12" if ($a[2] ne "RGB");
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5577;
- $hash->{PROTO} = 1;
- #$hash->{SERVICE} = 48899;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
- if ($a[3] =~ m/(LW12HX):([^:]+):*(\d+)*/g)
- {
- return "only RGB supported by LW12HX" if ($a[2] ne "RGB");
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5000;
- $hash->{PROTO} = 1;
- #$hash->{SERVICE} = 48899;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
- if ($a[3] =~ m/(LW12FC):([^:]+):*(\d+)*/g)
- {
- return "only RGB supported by LW12FC" if ($a[2] ne "RGB");
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5000;
- #$hash->{PROTO} = 1;
- #$hash->{SERVICE} = 48899;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Blocking => 0,
- Proto => 'udp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
- if ($a[3] =~ m/(LD316):([^:]+):*(\d+)*/g)
- {
- return "only RGBW supported by LD316" if ($a[2] ne "RGBW");
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5577;
- $hash->{PROTO} = 1;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
-
- if ($a[3] =~ m/(LD316A):([^:]+):*(\d+)*/g)
- {
- return "only RGBW supported by LD316A" if ($a[2] ne "RGBW");
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5577;
- $hash->{PROTO} = 1;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
- if ($a[3] =~ m/(LD382):([^:]+):*(\d+)*/g)
- {
- return "only RGB and RGBW supported by LD382" if (($a[2] ne "RGB") && ($a[2] ne "RGBW"));
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5577;
- $hash->{PROTO} = 1;
- #$hash->{SERVICE} = 48899;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
- if ($a[3] =~ m/(LD382A):([^:]+):*(\d+)*/g)
- {
- return "only RGB and RGBW supported by LD382A" if (($a[2] ne "RGB") && ($a[2] ne "RGBW"));
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:5577;
- $hash->{PROTO} = 1;
- #$hash->{SERVICE} = 48899;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
-
- if ($a[3] =~ m/(SENGLED):([^:]+):*(\d+)*/g)
- {
- return "only White supported by SENGLED" if ($a[2] ne "White");
- $hash->{CONNECTION} = $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:9060;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Blocking => 0,
- Proto => 'udp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
-
- if ($a[3] =~ m/(SUNRICHER):([^:]+):*(\d+)*/gi)
- {
- # return "only White, DualWhite, RGB, RGBW supported by Sunricher" if ($a[2] ne 'RGBW');
- $hash->{CONNECTION} = uc $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:8899;
- $hash->{PROTO} = 1;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- }
- }
- if ($a[3] =~ m/(SUNRICHERA):([^:]+):*(\d+)*/gi)
- {
- # return "only White, DualWhite, RGB, RGBW supported by Sunricher" if ($a[2] ne 'RGBW');
- $hash->{CONNECTION} = uc $1;
- $hash->{IP} = $2;
- $hash->{PORT} = $3?$3:8899;
- $hash->{PROTO} = 1;
- $hash->{SLOT} = 0;
- @{$hash->{helper}->{hlCmdQueue}} = ();
- if (!defined($hash->{helper}->{SOCKET}))
- {
- my $sock = IO::Socket::INET-> new (
- PeerPort => $hash->{PORT},
- PeerAddr => $hash->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($hash, 3, "define $hash->{NAME}: can't reach ($@)");
- my $select = IO::Select->new($sock);
- $hash->{helper}->{SOCKET} = $sock;
- $hash->{helper}->{SELECT} = $select;
- @{$hash->{helper}->{llCmdQueue}} = ();
- $hash->{helper}->{llLock} = 0;
- }
- }
-
- return "unknown connection type, see documentation" if !(defined($hash->{CONNECTION}));
- Log3 ($hash, 4, "define $a[0] $a[1] $a[2] $a[3]");
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} =~ 'LW12'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 0.75, 0.25';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} =~ 'LW12HX'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 0.75, 0.25';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} =~ 'LW12FC'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.85);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 0.85, 0.55';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGBW') && ($hash->{CONNECTION} =~ 'LD316'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -25, -15, -25, 0, -20';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1.0, 0.6, 0.065';
- return undef;
- }
-
- if (($hash->{LEDTYPE} eq 'RGBW') && ($hash->{CONNECTION} =~ 'LD316A'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -25, -15, -25, 0, -20';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1.0, 0.6, 0.065';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGBW') && ($hash->{CONNECTION} =~ 'LD382'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 1, 1';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} =~ 'LD382'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 0.75, 0.25';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGBW') && ($hash->{CONNECTION} =~ 'LD382A'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 1, 1';
- return undef;
- }
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} =~ 'LD382A'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10';
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 0.75, 0.25';
- return undef;
- }
- if ((($hash->{LEDTYPE} eq 'RGB') || ($hash->{LEDTYPE} eq 'RGBW1')) && ($hash->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- return "no free slot at $hash->{CONNECTION} ($hash->{IP}) for $hash->{LEDTYPE}" if (defined($otherLights->{0}));
- $hash->{SLOT} = 0;
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 1);
- $hash->{helper}->{COLORMAP} = WifiLight_Milight_ColorConverter($hash);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB sync pair unpair";
- #if we are allready paired: sync to get a defined state
- return WifiLight_RGB_Sync($hash) if ($hash->{LEDTYPE} eq 'RGB');
- return WifiLight_RGBW1_Sync($hash) if ($hash->{LEDTYPE} eq 'RGBW1');
- }
- elsif (($hash->{LEDTYPE} eq 'RGBW2') && ($hash->{CONNECTION} =~ 'bridge-V3'))
- {
- # find a free slot
- my $i = 5;
- while (defined($otherLights->{$i}))
- {
- $i++;
- }
- if ( grep { $i == $_ } 5..8 )
- {
- $hash->{SLOT} = $i;
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.73);
- $hash->{helper}->{COLORMAP} = WifiLight_Milight_ColorConverter($hash);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB sync pair unpair";
- return WifiLight_RGBW2_Sync($hash);
- }
- else
- {
- return "no free slot at $hash->{CONNECTION} ($hash->{IP}) for $hash->{LEDTYPE}";
- }
- }
- elsif (($hash->{LEDTYPE} eq 'White') && ($hash->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- # find a free slot
- my $i = 1;
- while (defined($otherLights->{$i}))
- {
- $i++;
- }
- if ( grep { $i == $_ } 1..4 )
- {
- $hash->{SLOT} = $i;
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.8);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown sync pair unpair";
- return WifiLight_White_Sync($hash);
- }
- else
- {
- return "no free slot at $hash->{CONNECTION} ($hash->{IP}) for $hash->{LEDTYPE}";
- }
- }
-
- if (($hash->{LEDTYPE} eq 'White') && ($hash->{CONNECTION} =~ 'SENGLED'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 1);
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown";
- return undef;
- }
-
- if (($hash->{LEDTYPE} eq 'DualWhite') && ($hash->{CONNECTION} eq 'SUNRICHER'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65); # TODO CHECK VALUES
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown";
- $hash->{helper}->{wLevel} = 0;
- # color cast defaults in r,y, g, c, b, m: +/-30°
- # my $cc = '0, -20, -20, -25, 0, -10'; # TODO CHECK VALUES
- # $attr{$name}{"colorCast"} = $cc;
- # WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- # $attr{$name}{"whitePoint"} = '1, 1, 1';
- return undef;
- }
-
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} eq 'SUNRICHER'))
- {
- $hash->{helper}->{COMMANDSET} = 'on off dim dimup dimdown HSV HSVK CT RGB';
- # init helper
- $hash->{helper}->{rLevel} = 0;
- $hash->{helper}->{gLevel} = 0;
- $hash->{helper}->{bLevel} = 0;
- # init converter
- $hash->{helper}->{cmd_pwr} = 'RGBSunricher_setPWR';
- $hash->{helper}->{cmd_hsv} = 'RGBSunricher_setHSV';
- # defaults
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65); # TODO CHECK VALUES
- # color cast defaults
- my $cc = '0, -20, -20, -25, 0, -10'; # TODO CHECK VALUES
- $attr{$name}{"colorCast"} = '0, -20, -20, -25, 0, -10';
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 1, 1';
- # TODO init readings
- return undef;
- }
-
- if (($hash->{LEDTYPE} eq 'RGB') && ($hash->{CONNECTION} eq 'SUNRICHERA'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65); # TODO CHECK VALUES
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- $hash->{helper}->{rLevel} = 0;
- $hash->{helper}->{gLevel} = 0;
- $hash->{helper}->{bLevel} = 0;
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10'; # TODO CHECK VALUES
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 1, 1';
- return undef;
- }
-
- if (($hash->{LEDTYPE} eq 'RGBW') && ($hash->{CONNECTION} eq 'SUNRICHER'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65); # TODO CHECK VALUES
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- $hash->{helper}->{rLevel} = 0;
- $hash->{helper}->{gLevel} = 0;
- $hash->{helper}->{bLevel} = 0;
- $hash->{helper}->{wLevel} = 0;
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10'; # TODO CHECK VALUES
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 1, 1';
- return undef;
- }
-
- if (($hash->{LEDTYPE} eq 'RGBW') && ($hash->{CONNECTION} eq 'SUNRICHERA'))
- {
- $hash->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($hash, 0.65); # TODO CHECK VALUES
- $hash->{helper}->{COMMANDSET} = "on off dim dimup dimdown HSV RGB";
- $hash->{helper}->{rLevel} = 0;
- $hash->{helper}->{gLevel} = 0;
- $hash->{helper}->{bLevel} = 0;
- $hash->{helper}->{wLevel} = 0;
- # color cast defaults in r,y, g, c, b, m: +/-30°
- my $cc = '0, -20, -20, -25, 0, -10'; # TODO CHECK VALUES
- $attr{$name}{"colorCast"} = $cc;
- WifiLight_RGB_ColorConverter($hash, split(',', $cc));
- # white point defaults in r,g,b
- $attr{$name}{"whitePoint"} = '1, 1, 1';
- return undef;
- }
-
- return "$hash->{LEDTYPE} is not supported at $hash->{CONNECTION} ($hash->{IP})";
- }
- sub
- WifiLight_Undef(@)
- {
- return undef;
- }
- sub
- WifiLight_Set(@)
- {
- my ($ledDevice, $name, $cmd, @args) = @_;
- my $descriptor = '';
-
- # remove descriptor from @args
- for (my $i = $#args; $i >= 0; --$i )
- {
- if ($args[$i] =~ /\/d\:(.*)/)
- {
- $descriptor = $1;
- splice (@args, $i, 1);
- }
- }
-
- my $cnt = @args;
- my $ramp = 0;
- my $flags = "";
- my $event = undef;
- my $cmdSet = $ledDevice->{helper}->{COMMANDSET};
- return "unknown command ($cmd): choose one of ".join(", ", $cmdSet) if ($cmd eq "?");
- return "unknown command ($cmd): choose one of ".$ledDevice->{helper}->{COMMANDSET} if ($cmd ne 'RGB') and not ( grep { $cmd eq $_ } split(" ", $ledDevice->{helper}->{COMMANDSET} ));
- if ($cmd eq 'pair')
- {
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- if (defined($args[0]))
- {
- return "usage: set $name pair [seconds]" if ($args[0] !~ /^\d+$/);
- $ramp = $args[0];
- }
- return WifiLight_RGB_Pair($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_Pair($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_Pair($ledDevice, $ramp) if ($ledDevice->{LEDTYPE} eq 'RGBW2');
- return WifiLight_White_Pair($ledDevice, $ramp) if ($ledDevice->{LEDTYPE} eq 'White');
- }
- if ($cmd eq 'unpair')
- {
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- if (defined($args[0]))
- {
- return "usage: set $name unpair [seconds]" if ($args[0] !~ /^\d+$/);
- $ramp = $args[0];
- }
- return WifiLight_RGB_UnPair($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_UnPair($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_UnPair($ledDevice, $ramp) if ($ledDevice->{LEDTYPE} eq 'RGBW2');
- return WifiLight_White_UnPair($ledDevice, $ramp) if ($ledDevice->{LEDTYPE} eq 'White');
- }
- if ($cmd eq 'sync')
- {
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- return WifiLight_RGB_Sync($ledDevice) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_Sync($ledDevice) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_Sync($ledDevice) if ($ledDevice->{LEDTYPE} eq 'RGBW2');
- return WifiLight_White_Sync($ledDevice) if ($ledDevice->{LEDTYPE} eq 'White');
- }
-
- if (($cmd eq 'HSV') || ($cmd eq 'RGB') || ($cmd eq 'dim'))
- {
- $args[1] = AttrVal($ledDevice->{NAME}, "defaultRamp", 0) if !defined($args[1]);
- }
- else
- {
- $args[0] = AttrVal($ledDevice->{NAME}, "defaultRamp", 0) if !defined($args[0]);
- }
- if ($cmd eq 'on')
- {
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- if (defined($args[0]))
- {
- return "usage: set $name on [seconds]" if ($args[0] !~ /^\d?.?\d+$/);
- $ramp = $args[0];
- }
- return WifiLight_RGBWLD316_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316'));
- return WifiLight_RGBWLD316A_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316A'));
- return WifiLight_RGBWLD382_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBLD382_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBWLD382A_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLD382A_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLW12_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12'));
- return WifiLight_RGBLW12HX_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12HX'));
- return WifiLight_RGBLW12FC_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12FC'));
- return WifiLight_WhiteSENGLED_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'));
- return WifiLight_RGB_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} eq 'bridge-V3'));
- return WifiLight_White_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_DualWhiteSunricher_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'DualWhite') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricher_On($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- }
- if ($cmd eq 'off')
- {
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- if (defined($args[0]))
- {
- return "usage: set $name off [seconds]" if ($args[0] !~ /^\d?.?\d+$/);
- $ramp = $args[0];
- }
- return WifiLight_RGBWLD316_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316'));
- return WifiLight_RGBWLD316A_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316A'));
- return WifiLight_RGBWLD382_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBLD382_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBWLD382A_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLD382A_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLW12_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12'));
- return WifiLight_RGBLW12HX_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12HX'));
- return WifiLight_RGBLW12FC_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12FC'));
- return WifiLight_WhiteSENGLED_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'));
- return WifiLight_RGB_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} eq 'bridge-V3'));
- return WifiLight_White_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_DualWhiteSunricher_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} eq 'DualWhite') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricher_Off($ledDevice, $ramp) if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- }
- if ($cmd eq 'dimup')
- {
- return "usage: set $name dimup" if (defined($args[1]));
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- my $v = ReadingsVal($ledDevice->{NAME}, "brightness", 0) + AttrVal($ledDevice->{NAME}, "dimStep", 7);
- $v = 100 if $v > 100;
- return WifiLight_RGBWLD316_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316'));
- return WifiLight_RGBWLD316A_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316A'));
- return WifiLight_RGBWLD382_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBLD382_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBWLD382A_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLD382A_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLW12_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12'));
- return WifiLight_RGBLW12HX_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12HX'));
- return WifiLight_RGBLW12FC_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12FC'));
- return WifiLight_WhiteSENGLED_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'));
- return WifiLight_RGB_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} eq 'bridge-V3'));
- return WifiLight_White_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_DualWhiteSunricher_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'DualWhite') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricher_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- }
- if ($cmd eq 'dimdown')
- {
- return "usage: set $name dimdown" if (defined($args[1]));
- WifiLight_HighLevelCmdQueue_Clear($ledDevice);
- my $v = ReadingsVal($ledDevice->{NAME}, "brightness", 0) - AttrVal($ledDevice->{NAME}, "dimStep", 7);
- $v = 0 if $v < 0;
- return WifiLight_RGBWLD316_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316'));
- return WifiLight_RGBWLD316A_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316A'));
- return WifiLight_RGBWLD382_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBLD382_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBWLD382A_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLD382A_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLW12_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12'));
- return WifiLight_RGBLW12HX_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12HX'));
- return WifiLight_RGBLW12FC_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12FC'));
- return WifiLight_WhiteSENGLED_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'));
- return WifiLight_RGB_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} eq 'bridge-V3'));
- return WifiLight_White_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_DualWhiteSunricher_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} eq 'DualWhite') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricher_Dim($ledDevice, $v, 0, '') if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- }
- if ($cmd eq 'dim')
- {
- return "usage: set $name dim level [seconds]" if ($args[0] !~ /^\d+$/);
- return "usage: set $name dim level [seconds]" if (($args[0] < 0) || ($args[0] > 100));
- if (defined($args[1]))
- {
- return "usage: set $name dim level [seconds] [q]" if ($args[1] !~ /^\d?.?\d+$/);
- $ramp = $args[1];
- }
- if (defined($args[2]))
- {
- return "usage: set $name dim level seconds [q]" if ($args[2] !~ m/.*[qQ].*/);
- $flags = $args[2];
- }
- WifiLight_HighLevelCmdQueue_Clear($ledDevice) if ($flags !~ m/.*[qQ].*/);
- return WifiLight_RGBWLD316_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316'));
- return WifiLight_RGBWLD316A_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316A'));
- return WifiLight_RGBWLD382_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBLD382_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBWLD382A_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLD382A_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLW12_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12'));
- return WifiLight_RGBLW12HX_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12HX'));
- return WifiLight_RGBLW12FC_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LW12FC'));
- return WifiLight_WhiteSENGLED_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'));
- return WifiLight_RGB_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} eq 'bridge-V3'));
- return WifiLight_White_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_DualWhiteSunricher_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} eq 'DualWhite') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricher_Dim($ledDevice, $args[0], $ramp, $flags) if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- }
- if (($cmd eq 'HSV') || ($cmd eq 'RGB'))
- {
- my ($hue, $sat, $val);
-
- if ($cmd eq 'HSV')
- {
- return "HSV is required as h,s,v" if (defined($args[0]) && $args[0] !~ /^\d{1,3},\d{1,3},\d{1,3}$/);
- ($hue, $sat, $val) = split(',', $args[0]);
- return "wrong hue ($hue): valid range 0..360" if !(($hue >= 0) && ($hue <= 360));
- return "wrong saturation ($sat): valid range 0..100" if !(($sat >= 0) && ($sat <= 100));
- return "wrong brightness ($val): valid range 0..100" if !(($val >= 0) && ($val <= 100));
- }
- elsif ($cmd eq 'RGB')
- {
- return "RGB is required hex RRGGBB" if (defined($args[0]) && $args[0] !~ /^[0-9A-Fa-f]{6}$/);
- ($hue, $sat, $val) = WifiLight_RGB2HSV($ledDevice, $args[0]);
- }
-
- if (defined($args[1]))
- {
- return "usage: set $name HSV H,S,V seconds flags programm" if ($args[1] !~ /^\d?.?\d+$/);
- $ramp = $args[1];
- }
- if (defined($args[2]))
- {
- return "usage: set $name HSV H,S,V seconds [slq] programm" if ($args[2] !~ m/.*[sSlLqQ].*/);
- $flags = $args[2];
- }
- if (defined($args[3]))
- {
- return "usage: set $name HSV H,S,V seconds flags programm=[A-Za-z_0-9]" if ($args[3] !~ m/[A-Za-z_0-9]*/);
- $event = $args[3];
- }
- WifiLight_HighLevelCmdQueue_Clear($ledDevice) if ($flags !~ m/.*[qQ].*/);
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LD316');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LD316A');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LD382');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LD382A');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LW12');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LW12HX');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if ($ledDevice->{CONNECTION} eq 'LW12FC');
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 500, $event) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 1000, $event) if (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 200, $event) if (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- WifiLight_HSV_Transition($ledDevice, $hue, $sat, $val, $ramp, $flags, 100, $event) if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- return WifiLight_SetHSV_Target($ledDevice, $hue, $sat, $val);
- }
- }
- sub
- WifiLight_Get(@)
- {
- my ($ledDevice, $name, $cmd, @args) = @_;
- my $cnt = @args;
-
- return undef;
- }
- sub
- WifiLight_Attr(@)
- {
- my ($cmd, $device, $attribName, $attribVal) = @_;
- my $ledDevice = $defs{$device};
- if ($cmd eq 'set' && $attribName eq 'gamma')
- {
- return "gamma is required as numerical value (eg. 0.5 or 2.2)" if ($attribVal !~ /^\d*\.\d*$/);
- $ledDevice->{helper}->{GAMMAMAP} = WifiLight_CreateGammaMapping($ledDevice, $attribVal);
- }
- if ($cmd eq 'set' && $attribName eq 'dimStep')
- {
- return "dimStep is required as numerical value [1..100]" if ($attribVal !~ /^\d*$/) || (($attribVal < 1) || ($attribVal > 100));
- }
- if ($cmd eq 'set' && $attribName eq 'defaultColor')
- {
- return "defaultColor is required as HSV" if ($attribVal !~ /^\d{1,3},\d{1,3},\d{1,3}$/);
- my ($hue, $sat, $val) = split(',', $attribVal);
- return "defaultColor: wrong hue ($hue): valid range 0..360" if !(($hue >= 0) && ($hue <= 360));
- return "defaultColor: wrong saturation ($sat): valid range 0..100" if !(($sat >= 0) && ($sat <= 100));
- return "defaultColor: wrong brightness ($val): valid range 0..100" if !(($val >= 0) && ($val <= 100));
- }
- my @a = ();
- if ($cmd eq 'set' && $attribName eq 'colorCast')
- {
- @a = split(',', $attribVal);
- my $msg = "colorCast: correction require red, yellow, green ,cyan, blue, magenta (each in a range of -29 .. 29)";
- return $msg unless (@a == 6);
- foreach my $tc (@a)
- {
- return $msg unless ($tc =~ m/^\s*[\-]{0,1}[0-9]+[\.]{0,1}[0-9]*\s*$/g);
- return $msg if (abs($tc) >= 30);
- }
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LD316');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LD316A');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LD382');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LD382A');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LW12');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LW12HX');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} eq 'LW12FC');
- WifiLight_Milight_ColorConverter($ledDevice, @a) if ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]');
- WifiLight_RGB_ColorConverter($ledDevice, @a) if (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/));
- if ($init_done && !(@{$ledDevice->{helper}->{hlCmdQueue}}))
- {
- my $hue = $ledDevice->{READINGS}->{hue}->{VAL};
- my $sat = $ledDevice->{READINGS}->{saturation}->{VAL};
- my $val = $ledDevice->{READINGS}->{brightness}->{VAL};
- WifiLight_setHSV($ledDevice, $hue, $sat, $val, 1);
- }
- }
- if ($cmd eq 'set' && $attribName eq 'whitePoint')
- {
- @a = split(',', $attribVal);
- my $msg = "whitePoint: correction require red, green, blue (each in a range of 0.0 ..1.0)";
- return $msg unless (@a == 3);
- foreach my $tc (@a)
- {
- return $msg unless ($tc =~ m/^\s*[0-9]+?[\.]{0,1}[0-9]*\s*$/g);
- return $msg if (($tc < 0) || ($tc > 1));
- }
- if ($init_done && !(@{$ledDevice->{helper}->{hlCmdQueue}}))
- {
- $attr{$device}{"whitePoint"} = $attribVal;
- my $hue = $ledDevice->{READINGS}->{hue}->{VAL};
- my $sat = $ledDevice->{READINGS}->{saturation}->{VAL};
- my $val = $ledDevice->{READINGS}->{brightness}->{VAL};
- WifiLight_setHSV($ledDevice, $hue, $sat, $val, 1);
- }
- }
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} attrib $attribName $cmd $attribVal") if $attribVal;
- return undef;
- }
- # restore previous settings (as set statefile)
- sub
- WifiLight_Notify(@)
- {
- my ($ledDevice, $eventSrc) = @_;
- my $events = deviceEvents($eventSrc, 1);
- my ($hue, $sat, $val);
- # wait for global: INITIALIZED after start up
- if ($eventSrc->{NAME} eq 'global' && @{$events}[0] eq 'INITIALIZED')
- {
- #######################################################
- # TODO remove in a few weeks. its here for convenience
- delete($ledDevice->{READINGS}->{HUE});
- delete($ledDevice->{READINGS}->{SATURATION});
- delete($ledDevice->{READINGS}->{BRIGHTNESS});
- #######################################################
- if ($ledDevice->{CONNECTION} eq 'LW12')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBLW12_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif ($ledDevice->{CONNECTION} eq 'LW12HX')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBLW12HX_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif ($ledDevice->{CONNECTION} eq 'LW12FC')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBLW12FC_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif ($ledDevice->{CONNECTION} eq 'LD316')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBWLD316_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif ($ledDevice->{CONNECTION} eq 'LD316A')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBWLD316A_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif ($ledDevice->{CONNECTION} eq 'LD382')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBWLD382_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif ($ledDevice->{CONNECTION} eq 'LD382A')
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBWLD382A_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:60;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:100;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:100;
- return WifiLight_RGB_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif (($ledDevice->{LEDTYPE} eq 'RGBW1') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:50;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:100;
- return WifiLight_RGBW1_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif (($ledDevice->{LEDTYPE} eq 'RGBW2') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:0;
- return WifiLight_RGBW2_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:100;
- return WifiLight_White_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'))
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:100;
- return WifiLight_WhiteSENGLED_setHSV($ledDevice, $hue, $sat, $val);
- }
- elsif (($ledDevice->{LEDTYPE} =~ /^RGB.?$/) && ($ledDevice->{CONNECTION} =~ /^SUNRICHER.?$/))
- {
- $hue = defined($ledDevice->{READINGS}->{hue}->{VAL})?$ledDevice->{READINGS}->{hue}->{VAL}:0;
- $sat = defined($ledDevice->{READINGS}->{saturation}->{VAL})?$ledDevice->{READINGS}->{saturation}->{VAL}:0;
- $val = defined($ledDevice->{READINGS}->{brightness}->{VAL})?$ledDevice->{READINGS}->{brightness}->{VAL}:100;
- return WifiLight_RGBSunricher_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricherA_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'SUNRICHERA'));
- return WifiLight_RGBWSunricher_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBWSunricherA_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'SUNRICHERA'));
- }
- #
- else
- {
- }
- return
- }
- }
- ###############################################################################
- #
- # generic device types
- # RGB device
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBDevice_On(@)
- {
- my ($ledDevice, $ramp) = @_;
-
- my $delay = 50;
- my $on = pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x02, 0x12, 0xAB, 0x00, 0xAA, 0xAA );
- my $receiver;
-
- $on = WifiLight_Sunricher_Checksum($ledDevice, $on);
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
-
- # TODO device specific on
-
- my ($h, $s, $v, $k) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100, 3200"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} $ledDevice->{LEDTYPE} $ledDevice->{CONNECTION} set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBDevice_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} $ledDevice->{LEDTYPE} $ledDevice->{CONNECTION} set off $ramp");
- return WifiLight_RGBDevice_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBDevice_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} $ledDevice->{LEDTYPE} $ledDevice->{CONNECTION} dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- ###############################################################################
- #
- # device specific controller functions DualWhite SUNRICHER
- #
- #
- #
- ###############################################################################
- sub
- WifiLight_DualWhiteSunricher_On(@)
- {
- my ($ledDevice, $ramp) = @_;
-
- my $delay = 50;
- my $on = pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x02, 0x12, 0xAB, 0x00, 0xAA, 0xAA );
- my $receiver;
-
- $on = WifiLight_Sunricher_Checksum($ledDevice, $on);
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
-
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} DualWhite Sunricher set on ($v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_DualWhiteSunricher_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} DualWhite Sunricher set off $ramp");
- return WifiLight_DualWhiteSunricher_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_DualWhiteSunricher_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} DualWhite Sunricher dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_DualWhiteSunricher_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val, $ct) = @_;
- my $receiver; # = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 0;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} DualWhite Sunricher set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
-
- my $wt = int($gammaVal * 0x40 / 100);
-
- my $msg;
- # Me$msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x36, 0x10, 0x00, 0xAA, 0xAA));
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x33, $wt, 0x00, 0xAA, 0xAA));
-
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions RGBW SUNRICHER
- # device range 0x00 0xff
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBSunricher_On(@)
- {
- my ($ledDevice, $ramp) = @_;
-
- my $delay = 50;
- my $on = pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x02, 0x12, 0xAB, 0x00, 0xAA, 0xAA );
- my $receiver;
-
- $on = WifiLight_Sunricher_Checksum($ledDevice, $on);
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
-
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} $ledDevice->{LEDTYPE} $ledDevice->{CONNECTION} set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBSunricher_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} $ledDevice->{LEDTYPE} $ledDevice->{CONNECTION} set off $ramp");
- return WifiLight_RGBWLD382_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBSunricher_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} $ledDevice->{LEDTYPE} $ledDevice->{CONNECTION} dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- ###############################################################################
- #
- # SUNRICHER Color conversation functions
- #
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBSunricher_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver; # = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 0;
- my $msg = '';
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW Sunricher set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
-
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
-
- $rr = int( $rr * 0x80 / 0xFF );
- $rg = int( $rg * 0x80 / 0xFF );
- $rb = int( $rb * 0x80 / 0xFF );
- $white = int( $white * 0x80 / 0xFF );
-
- # TODO CT and white point correction
- $rr += $white;
- $rg += $white;
- $rb += $white;
-
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x18, $rr, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{rLevel} != $rr);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x19, $rg, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{gLevel} != $rg);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x20, $rb, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{bLevel} != $rb);
-
- $ledDevice->{helper}->{rLevel} = $rr;
- $ledDevice->{helper}->{rLevel} = $rg;
- $ledDevice->{helper}->{rLevel} = $rb;
-
- # leave here if nothing to tell
- return unless $msg;
-
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- sub
- WifiLight_RGBSunricherA_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver; # = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 0;
- my $msg = '';
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW Sunricher set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
-
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
-
- # TODO CT and white point correction
- $rr += $white;
- $rg += $white;
- $rb += $white;
-
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x18, $rr, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{rLevel} != $rr);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x19, $rg, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{gLevel} != $rg);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x20, $rb, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{bLevel} != $rb);
-
- $ledDevice->{helper}->{rLevel} = $rr;
- $ledDevice->{helper}->{rLevel} = $rg;
- $ledDevice->{helper}->{rLevel} = $rb;
-
- # leave here if nothing to tell
- return unless $msg;
-
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- sub
- WifiLight_RGBWSunricher_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver; # = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 0;
- my $msg = '';
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW Sunricher set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
-
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
-
- $rr = int( $rr * 0x80 / 0xFF );
- $rg = int( $rg * 0x80 / 0xFF );
- $rb = int( $rb * 0x80 / 0xFF );
- $white = int( $white * 0x80 / 0xFF );
-
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x18, $rr, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{rLevel} != $rr);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x19, $rg, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{gLevel} != $rg);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x20, $rb, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{bLevel} != $rb);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x21, $white, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{wLevel} != $white);
-
- $ledDevice->{helper}->{rLevel} = $rr;
- $ledDevice->{helper}->{rLevel} = $rg;
- $ledDevice->{helper}->{rLevel} = $rb;
- $ledDevice->{helper}->{rLevel} = $white;
-
- # leave here if nothing to tell
- return unless $msg;
-
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- sub
- WifiLight_RGBWSunricherA_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver; # = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 0;
- my $msg = '';
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW Sunricher set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
-
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
-
- $rr *= 0x80 / 0xFF;
-
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x18, $rr, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{rLevel} != $rr);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x19, $rg, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{gLevel} != $rg);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x20, $rb, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{bLevel} != $rb);
- $msg .= WifiLight_Sunricher_Checksum($ledDevice, pack('C*', 0x55, 0x00, 0x00, 0x00, 0x02, 0xFF, 0x08, 0x21, $white, 0x00, 0xAA, 0xAA)) if ($ledDevice->{helper}->{wLevel} != $white);
-
- $ledDevice->{helper}->{rLevel} = $rr;
- $ledDevice->{helper}->{rLevel} = $rg;
- $ledDevice->{helper}->{rLevel} = $rb;
- $ledDevice->{helper}->{rLevel} = $white;
-
- # leave here if nothing to tell
- return unless $msg;
-
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # SUNRICHER helper functions
- #
- #
- ###############################################################################
- sub
- WifiLight_Sunricher_Checksum(@)
- {
- my ($ledDevice, $msg) = @_;
-
- my @byteStream = unpack('C*', $msg);
- my $l = @byteStream;
- my $c = 0;
-
- for (my $i=4; $i<($l-3); $i++) {
- $c += $byteStream[$i];
- }
- $c %= 0x100;
- $byteStream[$l -3] = $c;
- $msg = pack('C*', @byteStream);
- return $msg;
- }
- ###############################################################################
- #
- # device specific controller functions RGBW LD316
- # aka XScource
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBWLD316_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c", 0xCC, 0x23, 0x33);
- my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD316 set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBWLD316_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD316 set off $ramp");
- return WifiLight_RGBWLD316_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBWLD316_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD316 dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBWLD316_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val, $k) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW LD316 set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction, may be doing it after wb more ok
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- ##########################################
- # sat is spread by 10% so there is room
- # for a smoth switch to white and adapt to
- # higher brightness of white led
- ##########################################
- $sat = ($sat * 1.1) -10;
- my $wl = ($sat<0)?$sat * -1:0;
- $sat = ($sat<0)?0:$sat;
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my $msg;
- ##########################################
- # experimental white temp adjustment
- # G - 50%
- # B - 04%
- # sat is spread by 10% so there is room
- # for a smoth switch to white and adapt to
- # higher brightness of whte led
- ##########################################
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- # rgb mode
- if (($val > 0) && ($wl == 0))
- {
- #replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- #new proto 0x56, r, g, b, white level, f0 (color) || 0f (white), 0xaa (terminator)
- $msg = sprintf("%c%c%c%c%c%c%c", 0x56, $rr, $rg, $rb, 0x00, 0xF0, 0xAA);
- }
- elsif ($wl > 0)
- {
- #smoth brightness adaption of white led
- my $wo = $gammaVal - ($gammaVal * (10-$wl) * 0.08); #0.07
- $wo = int(0.5 + ($wo * 2.55));
- $msg = sprintf("%c%c%c%c%c%c%c", 0x56, 0, 0, 0, $wo, 0x0F, 0xAA);
- }
- else
- {
- $msg = sprintf("%c%c%c%c%c%c%c", 0x56, 0, 0, 0, 0x00, 0xF0, 0xAA);
- }
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions RGBW LD316A - new fw.
- # thnx raspklaus
- #
- ###############################################################################
- sub
- WifiLight_RGBWLD316A_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c%c", 0x71, 0x23, 0x0F, 0xA3);
- my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD316A set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBWLD316A_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD316A set off $ramp");
- return WifiLight_RGBWLD316_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBWLD316A_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD316A dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBWLD316A_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW LD316A set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction, may be doing it after wb more ok
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- ##########################################
- # sat is spread by 10% so there is room
- # for a smoth switch to white and adapt to
- # higher brightness of white led
- ##########################################
- $sat = ($sat * 1.1) -10;
- my $wl = ($sat<0)?$sat * -1:0;
- $sat = ($sat<0)?0:$sat;
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my $msg;
- ##########################################
- # experimental white temp adjustment
- # G - 50%
- # B - 04%
- # sat is spread by 10% so there is room
- # for a smoth switch to white and adapt to
- # higher brightness of whte led
- ##########################################
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- # rgb mode
- if (($val > 0) && ($wl == 0))
- {
- #replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- #new proto 0x56, r, g, b, white level, f0 (color) || 0f (white), 0xaa (terminator)
- $msg = sprintf("%c%c%c%c%c%c%c", 0x31, $rr, $rg, $rb, 0x00, 0xF0, 0x0F);
- }
- elsif ($wl > 0)
- {
- #smoth brightness adaption of white led
- my $wo = $gammaVal - ($gammaVal * (10-$wl) * 0.08); #0.07
- $wo = int(0.5 + ($wo * 2.55));
- $msg = sprintf("%c%c%c%c%c%c%c", 0x31, 0, 0, 0, $wo, 0x0F, 0x0F);
- }
- else
- {
- $msg = sprintf("%c%c%c%c%c%c%c", 0x31, 0, 0, 0, 0x00, 0xF0, 0x0F);
- }
- #add checksum
- $msg = WifiLight_RGBWLD382_Checksum($ledDevice, $msg);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions LD382 aka Magic UFO
- # with RGBW stripe (RGB and white)
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBWLD382_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c", 0x71, 0x23, 0x94);
- my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD382 set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBWLD382_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD382 set off $ramp");
- return WifiLight_RGBWLD382_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBWLD382_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD382 dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBWLD382_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW LD382 set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my $msg = sprintf("%c%c%c%c%c%c%c", 0x31, $rr, $rg, $rb, $white, 0x00, 0x00);
- #add checksum
- $msg = WifiLight_RGBWLD382_Checksum($ledDevice, $msg);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- sub
- WifiLight_RGBWLD382_Checksum(@)
- {
- my ($ledDevice, $msg) = @_;
- my $c = 0;
- foreach my $w (split //, $msg)
- {
- $c += ord($w);
- }
- $c %= 0x100;
- $msg .= sprintf("%c", $c);
- return $msg;
- }
- ###############################################################################
- #
- # device specific controller functions LD382 aka Magic UFO
- # with RGB stripe (mixed white)
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBLD382_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c", 0x71, 0x23, 0x94);
- my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LD382 set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBLD382_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LD382 set off $ramp");
- return WifiLight_RGBLD382_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBLD382_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LD382 dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBLD382_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB LD382 set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- #replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- my $msg = sprintf("%c%c%c%c%c%c%c", 0x31, $rr, $rg, $rb, 0x00, 0x00, 0x00);
- #add checksum
- $msg = WifiLight_RGBWLD382_Checksum($ledDevice, $msg);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions LD382A aka Magic UFO
- # with RGBW stripe (RGB and white)
- # LD382A is a LD382 with fw 1.0.6
- #
- ###############################################################################
- sub
- WifiLight_RGBWLD382A_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c%c", 0x71, 0x23, 0x0F, 0xA3);
- # my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD382A set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBWLD382A_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD382A set off $ramp");
- return WifiLight_RGBWLD382A_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBWLD382A_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW LD382A dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBWLD382A_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW LD382A set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my $msg = sprintf("%c%c%c%c%c%c%c", 0x31, $rr, $rg, $rb, $white, 0x00, 0x0F);
- #add checksum
- $msg = WifiLight_RGBWLD382_Checksum($ledDevice, $msg);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions LD382A aka Magic UFO
- # with RGB stripe (mixed white)
- # LD382A is a LD382 with fw 1.0.6
- #
- ###############################################################################
- sub
- WifiLight_RGBLD382A_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c%c", 0x71, 0x23, 0x0F, 0xA3);
- # my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LD382A set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBLD382A_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LD382A set off $ramp");
- return WifiLight_RGBLD382A_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBLD382A_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LD382A dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBLD382A_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB LD382A set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # convert to device 4 channels (remaining r,g,b after substract white, white, rgb)
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- #replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- my $msg = sprintf("%c%c%c%c%c%c%c", 0x31, $rr, $rg, $rb, 0x00, 0x00, 0x0F);
- #add checksum
- $msg = WifiLight_RGBWLD382_Checksum($ledDevice, $msg);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions RGB LW12
- # LED Stripe controller LW12
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBLW12_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c", 0xCC, 0x23, 0x33);
- my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- my $receiver;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- # WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12 set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- #TODO set physical off: my $off = sprintf("%c%c%c", 0xCC, 0x24, 0x33);
- sub
- WifiLight_RGBLW12_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12 set off $ramp");
- return WifiLight_RGBLW12_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBLW12_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12 dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBLW12_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB LW12 set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- #new style converter with white point correction
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- #replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- my $msg = sprintf("%c%c%c%c%c", 0x56, $rr, $rg, $rb, 0xAA);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions RGB LW12 HX001 Version
- # LED Stripe controller LW12
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBLW12HX_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- # my $delay = 50;
- # my $on = sprintf("%c%c%c", 0xCC, 0x23, 0x33);
- # my $msg = sprintf("%c%c%c%c%c", 0x56, 0, 0, 0, 0xAA);
- # my $receiver;
- # WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
- # WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12HX set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBLW12HX_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12HX set off $ramp");
- return WifiLight_RGBLW12HX_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBLW12HX_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBHX LW12 dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBLW12HX_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB LW12 set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- #new style converter with white point correction
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- #replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- my $on = ($gammaVal > 0)?1:0;
- my $dim = 100;
- # supported by ichichich
- my @sendData = (0x9D, 0x62, 0x00, 0x01, 0x01, $on, $dim, $rr, $rg, $rb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
- my $chkSum = 0xFF;
- $chkSum += $_ for @sendData[3, 5..9];
- unless ($chkSum == 0)
- {
- $chkSum %= 0xFF;
- $chkSum = 0xFF if ($chkSum == 0);
- }
- push (@sendData, $chkSum);
- for (my $i=2; $i<11; $i++)
- {
- my $h = ($sendData[$i] & 0xF0) + ($sendData[21-$i] >> 4);
- my $l = (($sendData[$i] & 0x0F) << 4) + ($sendData[21-$i] & 0x0F);
- $sendData[$i] = $h;
- $sendData[21-$i] = $l;
- }
- my $msg = pack('C*', @sendData);
- # $dbgStr = unpack("H*", $msg);
- # print "lw12HX $dbgStr \n";
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions RGB LW12 FC Version
- # LED Stripe controller LW12
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBLW12FC_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my $delay = 50;
- my $on = sprintf("%c%c%c%c%c%c%c%c%c", 0x7E, 0x04, 0x04, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0xEF);
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
-
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12FC set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_RGBLW12FC_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12FC set off $ramp");
- return WifiLight_RGBLW12FC_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBLW12FC_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LW12FC dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_RGBLW12FC_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB LW12FC set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # color cast correction
- my $h = $ledDevice->{helper}->{COLORMAP}[$hue];
- # new style converter with white point correction
- my ($rr, $rg, $rb, $white) = WifiLight_HSV2fourChannel($h, $sat, $gammaVal);
- my ($wr, $wg, $wb) = split(',', AttrVal($ledDevice->{NAME}, 'whitePoint', '1, 1, 1'));
- # replace the removed part of white light and apply white balance
- $rr += int(($white * $wr) + 0.5);
- $rg += int(($white * $wg) + 0.5);
- $rb += int(($white * $wb) + 0.5);
- my $on = ($gammaVal > 0)?1:0;
- my $dim = 100;
- my $msg = sprintf("%c%c%c%c%c%c%c%c%c", 0x7E, 0x07, 0x05, 0x03, $rr, $rg, $rb, 0x00, 0xEF);
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue
- return WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- ###############################################################################
- #
- # device specific controller functions White SENGLED
- # E27 LED Bulb with
- #
- #
- ###############################################################################
- sub
- WifiLight_WhiteSENGLED_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- # my $delay = 50;
- # my $on = sprintf("%c%c%c%c%c%c%c%c%c", 0x7E, 0x04, 0x04, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0xEF);
- # my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- # WifiLight_LowLevelCmdQueue_Add($ledDevice, $on, $receiver, $delay);
-
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} White SENGLED set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 100, undef);
- }
- sub
- WifiLight_WhiteSENGLED_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} White SENGLED set off $ramp");
- return WifiLight_WhiteSENGLED_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_WhiteSENGLED_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- # my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- # my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} White SENGLED dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, 0, 0, $level, $ramp, $flags, 100, undef);
- }
- sub
- WifiLight_WhiteSENGLED_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val, $isLast) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 50;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} White SENGLED set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
-
- my @remote = split(/\./, $ledDevice->{helper}->{SOCKET}->peerhost());
- # intro
- my $msg = sprintf("%c%c%c%c%c", 0x0d, 0x00, 0x02, 0x00, 0x01);
- # sender, lazy 0x00
- $msg .= sprintf("%c%c%c%c", 0x00, 0x00, 0x00, 0x00);
- # destinations
- $msg .= sprintf("%c%c%c%c", $remote[0], $remote[1], $remote[2], $remote[3] );
- # sender, lazy 0x00
- $msg .= sprintf("%c%c%c%c", 0x00, 0x00, 0x00, 0x00);
- # destinations
- $msg .= sprintf("%c%c%c%c", $remote[0], $remote[1], $remote[2], $remote[3] );
- # intro 2
- $msg .= sprintf("%c%c%c%c%c%c", 0x01, 0x00, 0x01, 0x00, 0x00, 0x00);
- # cmd level
- $msg .= sprintf("%c%c", $gammaVal, 0x64);
-
- # for safety of tranmission (udp): repeat cmd if its stand-alone or first or last in transition
- my $repeat = ($isLast)?3:1;
- for (my $i=0; $i<$repeat; $i++)
- {
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $msg, $receiver, $delay);
- # unlock ll queue after complete cmd is send
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
-
- return undef;
- }
- ###############################################################################
- #
- # device specific controller functions RGB
- # LED Stripe or bulb, no white, controller V2
- #
- ###############################################################################
- sub
- WifiLight_RGB_Pair(@)
- {
- my ($ledDevice, $numSeconds) = @_;
- $numSeconds = 3 if (($numSeconds || 0) == 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LED slot $ledDevice->{SLOT} pair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = "\x25\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_RGB_UnPair(@)
- {
- my ($ledDevice) = @_;
- my $numSeconds = 8;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB LED slot $ledDevice->{SLOT} unpair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = "\x25\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_RGB_Sync(@)
- {
- my ($ledDevice) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- $ledDevice->{helper}->{whiteLevel} =9;
- $ledDevice->{helper}->{colorLevel} =9;
- $ledDevice->{helper}->{colorValue} =127;
- $ledDevice->{helper}->{mode} =2; # mode 0: off, 1: mixed "white", 2: color
-
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x22\x00\x55", $receiver, 500); # on
- for (my $i = 0; $i < 22; $i++) {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode up (to "pure white" ;-)
- }
- for (my $i = 0; $i < 10; $i++) {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up (to "pure white" ;-)
- }
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20\x7F\x55", $receiver, $delay); # color yellow (auto jump to mode 2)
- for (my $i = 0; $i < 10; $i++) {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up (yellow max brightness)
- }
- WifiLight_setHSV_Readings($ledDevice, 60, 100, 100) if $init_done;
- return undef;
- }
- sub
- WifiLight_RGB_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "40,100,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB slot $ledDevice->{SLOT} set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 500, undef);
- }
- sub
- WifiLight_RGB_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB slot $ledDevice->{SLOT} set off $ramp");
- return WifiLight_RGB_Dim($ledDevice, 0, $ramp, '');
- #TODO remove if tested
- #return WifiLight_HSV_Transition($ledDevice, 0, 100, 0, $ramp, undef, 500, undef);
- }
- sub
- WifiLight_RGB_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGB slot $ledDevice->{SLOT} dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 500, undef);
- }
- sub
- WifiLight_RGB_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB slot $ledDevice->{SLOT} set h:$hue, s:$sat, v:$val");
- $sat = 100;
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # convert to device specs
- my ($cv, $cl, $wl) = WifiLight_RGBW1_ColorConverter($ledDevice, $hue, $sat, $val);
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGB slot $ledDevice->{SLOT} set levels: $cv, $cl, $wl");
- return WifiLight_RGB_setLevels($ledDevice, $cv, $cl, $wl);
- }
- sub
- WifiLight_RGB_setLevels(@)
- {
- my ($ledDevice, $cv, $cl, $wl) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- my $lock = 0;
- # mode 0: off, 1: mixed "white", 2: color
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- if ((($ledDevice->{helper}->{colorValue} != $cv) && ($cl > 0)) || ($ledDevice->{helper}->{colorLevel} != $cl) || ($ledDevice->{helper}->{whiteLevel} != $wl))
- {
- $ledDevice->{helper}->{llLock} += 1;
- $lock = 1;
- }
- # need to touch color value (only if visible) or color level ?
- if ((($ledDevice->{helper}->{colorValue} != $cv) && ($cl > 0)) || $ledDevice->{helper}->{colorLevel} != $cl)
- {
- # if color all off switch on
- if ($ledDevice->{helper}->{mode} == 0)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x22\x00\x55", $receiver, $delay); # switch on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20".chr($cv)."\x55", $receiver, $delay); # set color
- $ledDevice->{helper}->{colorValue} = $cv;
- $ledDevice->{helper}->{colorLevel} = 1;
- $ledDevice->{helper}->{mode} = 2;
- }
- elsif ($ledDevice->{helper}->{mode} == 1)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20".chr($cv)."\x55", $receiver, $delay); # set color
- $ledDevice->{helper}->{colorValue} = $cv;
- $ledDevice->{helper}->{mode} = 2;
- }
- else
- {
- $ledDevice->{helper}->{colorValue} = $cv;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20".chr($cv)."\x55", $receiver, $delay); # set color
- }
- # cl decrease
- if ($ledDevice->{helper}->{colorLevel} > $cl)
- {
- for (my $i=$ledDevice->{helper}->{colorLevel}; $i > $cl; $i--)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x24\x00\x55", $receiver, $delay); # brightness down
- $ledDevice->{helper}->{colorLevel} = $i - 1;
- }
- if ($cl == 0)
- {
- # need to switch off color
- # if no white is required and no white is active we can must entirely switch off
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x21\x00\x55", $receiver, $delay); # switch off
- $ledDevice->{helper}->{colorLevel} = 0;
- $ledDevice->{helper}->{mode} = 0;
- }
- }
- # cl inrease
- if ($ledDevice->{helper}->{colorLevel} < $cl)
- {
- for (my $i=$ledDevice->{helper}->{colorLevel}; $i < $cl; $i++)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # brightness up
- $ledDevice->{helper}->{colorLevel} = $i + 1;
- }
- }
- }
- # unlock ll queue
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1) if $lock;
- return undef;
- }
- ###############################################################################
- #
- # device specific controller functions RGBW1
- # LED Stripe with extra white led, controller V2, bridge V2|bridge V3
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBW1_Pair(@)
- {
- my ($ledDevice, $numSeconds) = @_;
- $numSeconds = 3 if (($numSeconds || 0) == 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW1 LED slot $ledDevice->{SLOT} pair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = "\x25\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_RGBW1_UnPair(@)
- {
- my ($ledDevice) = @_;
- my $numSeconds = 8;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW1 LED slot $ledDevice->{SLOT} unpair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = "\x25\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_RGBW1_Sync(@)
- {
- my ($ledDevice) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 250;
- $ledDevice->{helper}->{whiteLevel} =9;
- $ledDevice->{helper}->{colorLevel} =9;
- $ledDevice->{helper}->{colorValue} =170;
- $ledDevice->{helper}->{mode} =3; # mode 0: c:off, w:off; 1: c:on, w:off; 2: c:off, w:on; 3: c:on, w:on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x22\x00\x55", $receiver, 500); # on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x22\x00\x55", $receiver, $delay); # on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20\xAA\x55", $receiver, $delay); # color red (auto jump to mode 1 except we are mode 3)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down (now we are for sure in mode 1)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #1
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #2
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #3
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #4
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #5
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #6
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #7
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #8
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #9 (highest dim-level color red)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay); # mode up (pure white)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #1
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #2
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #3
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #4
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #5
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #6
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #7
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #8
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # dim up #9 (highest dim-level white)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay); # mode up (white and red at highest level: bright warm light)
- WifiLight_setHSV_Readings($ledDevice, 0, 50, 100) if $init_done;
- return undef;
- }
- sub
- WifiLight_RGBW1_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW1 slot $ledDevice->{SLOT} set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 1000, undef);
- }
- sub
- WifiLight_RGBW1_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW1 slot $ledDevice->{SLOT} set off $ramp");
- return WifiLight_RGBW1_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_RGBW1_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW1 slot $ledDevice->{SLOT} dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 1000, undef);
- }
- sub
- WifiLight_RGBW1_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW1 slot $ledDevice->{SLOT} set h:$hue, s:$sat, v:$val");
- WifiLight_setHSV_Readings($ledDevice, $hue, $sat, $val);
- # convert to device specs
- my ($cv, $cl, $wl) = WifiLight_RGBW1_ColorConverter($ledDevice, $hue, $sat, $val);
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW1 slot $ledDevice->{SLOT} set levels: $cv, $cl, $wl");
- return WifiLight_RGBW1_setLevels($ledDevice, $cv, $cl, $wl);
- }
- sub
- WifiLight_RGBW1_setLevels(@)
- {
- my ($ledDevice, $cv, $cl, $wl) = @_;
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 250;
- my $lock = 0;
- # need to touch color value or color level?
- # yes
- # is color visible ? (we are in mode 1 or 3)
- # yes: adjust color!, requ level = 1 if cl = 0; new level 0 ? yes: mode 0 if wl == 0 else Mode = 1 (if coming from 0 or 1 then wl =1)
- # no:
- # will we need color ?
- # yes: go into mode #1, (cl jumps to 1)
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- if ((($ledDevice->{helper}->{colorValue} != $cv) && ($cl > 0)) || ($ledDevice->{helper}->{colorLevel} != $cl) || ($ledDevice->{helper}->{whiteLevel} != $wl))
- {
- $ledDevice->{helper}->{llLock} += 1;
- $lock = 1;
- }
- # need to touch color value (only if visible) or color level ?
- if ((($ledDevice->{helper}->{colorValue} != $cv) && ($cl > 0)) || $ledDevice->{helper}->{colorLevel} != $cl)
- {
- # if color all off switch on
- if ($ledDevice->{helper}->{mode} == 0)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x22\x00\x55", $receiver, $delay); # switch on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down: 3 > 2 || 2 > 1
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down: 2 > 1 || 1 > 1
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20".chr($cv)."\x55", $receiver, $delay); # set color
- $ledDevice->{helper}->{colorValue} = $cv;
- $ledDevice->{helper}->{colorLevel} = 1;
- $ledDevice->{helper}->{mode} = 1;
- }
- elsif ($ledDevice->{helper}->{mode} == 2)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay); # mode up: 2 > 3
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20".chr($cv)."\x55", $receiver, $delay); # set color
- $ledDevice->{helper}->{colorValue} = $cv;
- $ledDevice->{helper}->{colorLevel} = 1;
- $ledDevice->{helper}->{mode} = 3;
- }
- else
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x20".chr($cv)."\x55", $receiver, $delay); # set color
- $ledDevice->{helper}->{colorValue} = $cv;
- }
- # color level decrease
- if ($ledDevice->{helper}->{colorLevel} > $cl)
- {
- for (my $i=$ledDevice->{helper}->{colorLevel}; $i > $cl; $i--)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x24\x00\x55", $receiver, $delay); # brightness down
- $ledDevice->{helper}->{colorLevel} = $i - 1;
- }
- if ($cl == 0)
- {
- # need to switch off color
- # if no white is required and no white is active switch off
- if (($wl == 0) && ($ledDevice->{helper}->{mode} == 1))
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x21\x00\x55", $receiver, $delay); # switch off
- $ledDevice->{helper}->{colorLevel} = 0;
- $ledDevice->{helper}->{mode} = 0;
- }
- # if white is required, goto mode 2: pure white
- if (($wl > 0) || ($ledDevice->{helper}->{mode} == 2) || ($ledDevice->{helper}->{mode} == 3))
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay) if ($ledDevice->{helper}->{mode} == 1) ; # mode up
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay) if ($ledDevice->{helper}->{mode} == 3) ; # mode down
- $ledDevice->{helper}->{colorLevel} = 0;
- $ledDevice->{helper}->{whiteLevel} = 1 if ($ledDevice->{helper}->{mode} == 1);
- $ledDevice->{helper}->{mode} = 2;
- }
- }
- }
- if ($ledDevice->{helper}->{colorLevel} < $cl)
- {
- for (my $i=$ledDevice->{helper}->{colorLevel}; $i < $cl; $i++)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # brightness up
- $ledDevice->{helper}->{colorLevel} = $i + 1;
- }
- }
- }
- # need to adjust white level ?
- if ($ledDevice->{helper}->{whiteLevel} != $wl)
- {
- # white off but need adjustment ? set it on..
- # color processing is finished, so if we are in mode 0, no color required. go to mode 2: pure white
- if ($ledDevice->{helper}->{mode} == 0)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x22\x00\x55", $receiver, $delay); # switch on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down (3 -> 2 || 2 -> 1)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down (2 -> 1 || 1 -> 1)
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay); # mode up (1 -> 2)
- $ledDevice->{helper}->{whiteLevel} = 1;
- $ledDevice->{helper}->{mode} = 2;
- }
- # color processing is finished, so if we are at mode 1 color is required. go to mode 2
- if ($ledDevice->{helper}->{mode} == 1)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay); # mode up (1 -> 2)
- $ledDevice->{helper}->{whiteLevel} = 1;
- $ledDevice->{helper}->{mode} = 2;
- }
- # temporary go to mode 2 while maintain white level
- if ($ledDevice->{helper}->{mode} == 3)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down (3 -> 2)
- $ledDevice->{helper}->{mode} = 2;
- }
- # white level inrease
- for (my $i=$ledDevice->{helper}->{whiteLevel}; $i < $wl; $i++)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x23\x00\x55", $receiver, $delay); # brightness up
- $ledDevice->{helper}->{whiteLevel} = $i + 1;
- }
- # white level decrease
- if ($ledDevice->{helper}->{whiteLevel} > $wl)
- {
- for (my $i=$ledDevice->{helper}->{whiteLevel}; $i > $wl; $i--)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x24\x00\x55", $receiver, $delay); # brightness down
- $ledDevice->{helper}->{whiteLevel} = $i - 1;
- }
- }
- # assume we are at mode 2, finishing to correct mode
- if (($wl == 0) && ($cl == 0))
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x21\x00\x55", $receiver, $delay); # switch off
- $ledDevice->{helper}->{whiteLevel} = 0;
- $ledDevice->{helper}->{mode} = 0;
- }
- if (($wl == 0) && ($cl > 0))
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x28\x00\x55", $receiver, $delay); # mode down (2 -> 1)
- $ledDevice->{helper}->{whiteLevel} = 0;
- $ledDevice->{helper}->{mode} = 1;
- }
- if (($wl > 0) && ($cl > 0))
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x27\x00\x55", $receiver, $delay); # mode up (2 -> 3)
- $ledDevice->{helper}->{mode} = 3;
- }
- }
- # unlock ll queue
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1) if $lock;
- return undef;
- }
- sub
- WifiLight_RGBW1_ColorConverter(@)
- {
- my ($ledDevice, $h, $s, $v) = @_;
- my $color = $ledDevice->{helper}->{COLORMAP}[$h % 360];
-
- # there are 0..9 dim level, setup correction
- my $valueSpread = 100/9;
- my $totalVal = int(($v / $valueSpread) +0.5);
- # saturation 100..50: color full, white increase. 50..0 white full, color decrease
- my $colorVal = ($s >= 50) ? $totalVal : int(($s / 50 * $totalVal) +0.5);
- my $whiteVal = ($s >= 50) ? int(((100-$s) / 50 * $totalVal) +0.5) : $totalVal;
- return ($color, $colorVal, $whiteVal);
- }
- ###############################################################################
- #
- # device specific functions RGBW2 bulb
- # RGB white, only bridge V3
- #
- #
- ###############################################################################
- sub
- WifiLight_RGBW2_Pair(@)
- {
- my ($ledDevice, $numSeconds) = @_;
- $numSeconds = 3 if (($numSeconds || 0) == 0);
- my @bulbCmdsOn = ("\x45", "\x47", "\x49", "\x4B");
- Log3 ($ledDevice, 3, "$ledDevice->{NAME}, $ledDevice->{LEDTYPE} at $ledDevice->{CONNECTION}, slot $ledDevice->{SLOT}: pair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_RGBW2_UnPair(@)
- {
- my ($ledDevice, $numSeconds, $releaseFromSlot) = @_;
- $numSeconds = 5;
- my @bulbCmdsOn = ("\x45", "\x47", "\x49", "\x4B");
- Log3 ($ledDevice, 3, "$ledDevice->{NAME}, $ledDevice->{LEDTYPE} at $ledDevice->{CONNECTION}, slot $ledDevice->{SLOT}: unpair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_RGBW2_Sync(@)
- {
- my ($ledDevice) = @_;
- # force new settings
- $ledDevice->{helper}->{mode} = -1;
- $ledDevice->{helper}->{colorValue} = -1;
- $ledDevice->{helper}->{colorLevel} = -1;
- $ledDevice->{helper}->{whiteLevel} = -1;
- return undef;
- }
- sub
- WifiLight_RGBW2_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- my ($h, $s, $v) = split(',', AttrVal($ledDevice->{NAME}, "defaultColor", "0,0,100"));
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW2 slot $ledDevice->{SLOT} set on ($h, $s, $v) $ramp");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $v, $ramp, '', 200, undef);
- }
- sub
- WifiLight_RGBW2_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW2 slot $ledDevice->{SLOT} set off $ramp");
- return WifiLight_RGBW2_Dim($ledDevice, 0, $ramp, '');
- #TODO remove if tested
- #return WifiLight_HSV_Transition($ledDevice, 0, 0, 0, $ramp, undef, 500, undef);
- }
- sub
- WifiLight_RGBW2_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} RGBW2 slot $ledDevice->{SLOT} dim $level $ramp ". $flags || '');
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 200, undef);
- }
- sub
- WifiLight_RGBW2_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val, $isLast) = @_;
- my ($cl, $wl);
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- my $cv = $ledDevice->{helper}->{COLORMAP}[$hue % 360];
- # apply gamma correction
- my $gammaVal = $ledDevice->{helper}->{GAMMAMAP}[$val];
- # mode 0 = off, 1 = color, 2 = white
- # brightness 2..27 (x02..x1b) | 25
- my $cf = 100 / 26;
- my $cb = int(($gammaVal / $cf) + 0.5);
- $cb += ($cb > 0)?1:0;
- if ($sat < 20)
- {
- $wl = $cb;
- $cl = 0;
- WifiLight_setHSV_Readings($ledDevice, $hue, 0, $val);
- }
- else
- {
- $cl = $cb;
- $wl = 0;
- WifiLight_setHSV_Readings($ledDevice, $hue, 100, $val);
- }
- return WifiLight_RGBW2_setLevelsFast($ledDevice, $receiver, $cv, $cl, $wl) unless ($isLast);
- return WifiLight_RGBW2_setLevelsSafe($ledDevice, $receiver, $cv, $cl, $wl);
- }
- # repeatly send out a full size cmd
- # the last cmd in a transition or if it is stand alone
- sub
- WifiLight_RGBW2_setLevelsSafe(@)
- {
- my ($ledDevice, $receiver, $cv, $cl, $wl) = @_;
- my $delay = 100;
- my @bulbCmdsOn = ("\x45", "\x47", "\x49", "\x4B");
- my @bulbCmdsOff = ("\x46", "\x48", "\x4A", "\x4C");
- my @bulbCmdsWT = ("\xC5", "\xC7", "\xC9", "\xCB");
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} RGBW2 slot $ledDevice->{SLOT} set safe levels");
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} RGBW2 slot $ledDevice->{SLOT} lock queue ".$ledDevice->{helper}->{llLock});
- my @cmd = ();
-
- # about switching off. dim to prevent a flash if switched on again
-
- if (($wl == 0) && ($cl == 0) && ($ledDevice->{helper}->{mode} != 0))
- {
- $ledDevice->{helper}->{llLock} += 1; # lock ...
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55", $receiver, $delay); # group on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x4E\x02\x55", $receiver, $delay); # brightness
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1); # ... unlock
- }
- if (($wl == 0) && ($cl == 0))
- {
- push (@cmd, @bulbCmdsOff[$ledDevice->{SLOT} -5]."\x00\x55");
- $ledDevice->{helper}->{whiteLevel} = 0;
- $ledDevice->{helper}->{colorLevel} = 0;
- $ledDevice->{helper}->{mode} = 0; # group off
- }
- elsif ($wl > 0)
- {
- push (@cmd, @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55");
- push (@cmd, @bulbCmdsWT[$ledDevice->{SLOT} -5]."\x00\x55");
- push (@cmd, "\x4E".chr($wl)."\x55");
- $ledDevice->{helper}->{whiteLevel} = $wl;
- $ledDevice->{helper}->{colorLevel} = 0;
- $ledDevice->{helper}->{mode} = 2; # white
- }
- elsif ($cl > 0)
- {
- push (@cmd, @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55");
- push (@cmd, "\x40".chr($cv)."\x55"); # color
- push (@cmd, "\x4E".chr($cl)."\x55"); # brightness
- $ledDevice->{helper}->{whiteLevel} = 0;
- $ledDevice->{helper}->{colorLevel} = $cl;
- $ledDevice->{helper}->{colorValue} = $cv;
- $ledDevice->{helper}->{mode} = 1; # color
- }
- # repeat it three times
- for (my $i=0; $i<3; $i++)
- {
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $_, $receiver, $delay) foreach (@cmd);
- # unlock ll queue after complete cmd is send
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- }
- return undef;
- }
- # classic optimized version, used by fast color transitions
- sub
- WifiLight_RGBW2_setLevelsFast(@)
- {
- my ($ledDevice, $receiver, $cv, $cl, $wl) = @_;
- my $delay = 100;
- my @bulbCmdsOn = ("\x45", "\x47", "\x49", "\x4B");
- my @bulbCmdsOff = ("\x46", "\x48", "\x4A", "\x4C");
- my @bulbCmdsWT = ("\xC5", "\xC7", "\xC9", "\xCB");
- return if (($ledDevice->{helper}->{colorValue} == $cv) && ($ledDevice->{helper}->{colorLevel} == $cl) && ($ledDevice->{helper}->{whiteLevel} == $wl));
- # lock ll queue to prevent a bottleneck within llqueue
- # in cases where the high level queue fills the low level queue (which should not be interrupted) faster then it is processed (send out)
- # this lock will cause the hlexec intentionally drop frames which can safely be done because there are further frames for processing avialable
- $ledDevice->{helper}->{llLock} += 1;
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} RGBW2 slot $ledDevice->{SLOT} lock queue ".$ledDevice->{helper}->{llLock});
- if (($wl == 0) && ($cl == 0) && ($ledDevice->{helper}->{mode} != 0))
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOff[$ledDevice->{SLOT} -5]."\x00\x55", $receiver, $delay);
- $ledDevice->{helper}->{whiteLevel} = 0;
- $ledDevice->{helper}->{colorLevel} = 0;
- $ledDevice->{helper}->{mode} = 0; # group off
- }
- else
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55", $receiver, $delay); # group on
- # WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -5]."\x00\x55", $receiver, $delay) if (($wl > 0) || ($cl > 0)); # group on
- if (($wl > 0) && ($ledDevice->{helper}->{mode} == 2)) # already white
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x4E".chr($wl)."\x55", $receiver, $delay) if ($ledDevice->{helper}->{whiteLevel} != $wl); # brightness
- }
- elsif (($wl > 0) && ($ledDevice->{helper}->{mode} != 2)) # not white
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsWT[$ledDevice->{SLOT} -5]."\x00\x55", $receiver, $delay); # white
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x4E".chr($wl)."\x55", $receiver, $delay); # brightness
- $ledDevice->{helper}->{mode} = 2; # white
- }
- elsif (($cl > 0) && ($ledDevice->{helper}->{mode} == 1)) # already color
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x4E".chr($cl)."\x55", $receiver, $delay) if ($ledDevice->{helper}->{colorLevel} != $cl); # brightness
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x40".chr($cv)."\x55", $receiver, $delay) if ($ledDevice->{helper}->{colorValue} != $cv); # color
- }
- elsif (($cl > 0) && ($ledDevice->{helper}->{mode} != 1)) # not color
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x40".chr($cv)."\x55", $receiver, $delay); # color
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x4E".chr($cl)."\x55", $receiver, $delay); # brightness
- $ledDevice->{helper}->{mode} = 1; # color
- }
- $ledDevice->{helper}->{colorValue} = $cv;
- $ledDevice->{helper}->{colorLevel} = $cl;
- $ledDevice->{helper}->{whiteLevel} = $wl;
- }
- # unlock ll queue after complete cmd is send
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x00", $receiver, 0, 1);
- return undef;
- }
- ###############################################################################
- #
- # device specific functions white bulb
- # warm white / cold white with dim, bridge V2|bridge V3
- #
- #
- ###############################################################################
- sub
- WifiLight_White_Pair(@)
- {
- my ($ledDevice, $numSeconds) = @_;
- $numSeconds = 1 if !(defined($numSeconds));
- my @bulbCmdsOn = ("\x38", "\x3D", "\x37", "\x32");
- Log3 ($ledDevice, 3, "$ledDevice->{NAME}, $ledDevice->{LEDTYPE} at $ledDevice->{CONNECTION}, slot $ledDevice->{SLOT}: pair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 500, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_White_UnPair(@)
- {
- my ($ledDevice, $numSeconds, $releaseFromSlot) = @_;
- $numSeconds = 5;
- my @bulbCmdsOn = ("\x38", "\x3D", "\x37", "\x32");
- Log3 ($ledDevice, 3, "$ledDevice->{NAME}, $ledDevice->{LEDTYPE} at $ledDevice->{CONNECTION}, slot $ledDevice->{SLOT}: unpair $numSeconds");
- # find my slot and get my group-all-on cmd
- my $ctrl = @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55";
- for (my $i = 0; $i < $numSeconds; $i++)
- {
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- WifiLight_HighLevelCmdQueue_Add($ledDevice, undef, undef, undef, $ctrl, 250, undef, undef);
- }
- return undef;
- }
- sub
- WifiLight_White_Sync(@)
- {
- my ($ledDevice) = @_;
- my @bulbCmdsOn = ("\x38", "\x3D", "\x37", "\x32");
- my @bulbCmdsFB = ("\xB8", "\xBD", "\xB7", "\xB2");
-
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- $ledDevice->{helper}->{whiteLevel} =11;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME}, $ledDevice->{LEDTYPE} at $ledDevice->{CONNECTION}, slot $ledDevice->{SLOT}: sync");
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay); # group on
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsFB[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay); # full brightness
- WifiLight_setHSV_Readings($ledDevice, 0, 0, 100) if $init_done;
- return undef;
- }
- sub
- WifiLight_White_On(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} white slot $ledDevice->{SLOT} set on $ramp");
- return WifiLight_HSV_Transition($ledDevice, 0, 0, 100, $ramp, '', 500, undef);
- }
- sub
- WifiLight_White_Off(@)
- {
- my ($ledDevice, $ramp) = @_;
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} white slot $ledDevice->{SLOT} set off $ramp");
- return WifiLight_RGBW2_Dim($ledDevice, 0, $ramp, '');
- }
- sub
- WifiLight_White_Dim(@)
- {
- my ($ledDevice, $level, $ramp, $flags) = @_;
- my $h = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- my $s = ReadingsVal($ledDevice->{NAME}, "saturation", 0);
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} white slot $ledDevice->{SLOT} dim $level $ramp $flags");
- return WifiLight_HSV_Transition($ledDevice, $h, $s, $level, $ramp, $flags, 300, undef);
- }
- # only val supported,
- # TODO hue will become colortemp
- sub
- WifiLight_White_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my $wlStep = (100 / 11);
- WifiLight_setHSV_Readings($ledDevice, 0, 0, $val);
- $val = int(($val / $wlStep) +0.5);
- WifiLight_White_setLevels($ledDevice, undef, $val);
-
- return undef;
- }
- sub
- WifiLight_White_setLevels(@)
- {
- my ($ledDevice, $cv, $wl) = @_;
- my @bulbCmdsOn = ("\x38", "\x3D", "\x37", "\x32");
- my @bulbCmdsOff = ("\x3B", "\x33", "\x3A", "\x36");
- my @bulbCmdsFull = ("\xB8", "\xBD", "\xB7", "\xB2");
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 80;
- # alert that dump receiver, give it a extra wake up call
- if ($ledDevice->{helper}->{whiteLevel} != $wl)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay);
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay);
- }
-
- if ($ledDevice->{helper}->{whiteLevel} > $wl)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay); # group on
- for (my $i=$ledDevice->{helper}->{whiteLevel}; $i > $wl; $i--)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x34\x00\x55", $receiver, $delay); # brightness down
- $ledDevice->{helper}->{whiteLevel} = $i - 1;
- }
- if ($wl == 0)
- {
- # special precaution, giving extra downsteps to do a sync each time you switch off
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x34\x00\x55", $receiver, $delay); # brightness down
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x34\x00\x55", $receiver, $delay); # brightness down
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x34\x00\x55", $receiver, $delay); # brightness down
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOff[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay); # group off
- #WifiLight_LowLevelCmdqueue_Add($ledDevice, @bulbCmdsOff[$ledDevice->{SLOT}-1]."\x00\x55", $receiver, $delay);
- }
- }
-
- if ($ledDevice->{helper}->{whiteLevel} < $wl)
- {
- $ledDevice->{helper}->{whiteLevel} = 1 if ($ledDevice->{helper}->{whiteLevel} == 0);
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsOn[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay); # group on
- for (my $i=$ledDevice->{helper}->{whiteLevel}; $i < $wl; $i++)
- {
- WifiLight_LowLevelCmdQueue_Add($ledDevice, "\x3C\x00\x55", $receiver, $delay); # brightness up
- $ledDevice->{helper}->{whiteLevel} = $i + 1;
- }
- WifiLight_LowLevelCmdQueue_Add($ledDevice, @bulbCmdsFull[$ledDevice->{SLOT} -1]."\x00\x55", $receiver, $delay) if ($ledDevice->{helper}->{whiteLevel} == 11);
- }
- return undef;
- }
- ###############################################################################
- #
- # device indepenent routines
- #
- ###############################################################################
- # dispatcher
- sub
- WifiLight_setHSV(@)
- {
- my ($ledDevice, $hue, $sat, $val, $isLast) = @_;
- return WifiLight_RGBWLD316_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316'));
- return WifiLight_RGBWLD316A_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD316A'));
- return WifiLight_RGBWLD382_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBLD382_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382'));
- return WifiLight_RGBWLD382A_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLD382A_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'LD382A'));
- return WifiLight_RGBLW12_setHSV($ledDevice, $hue, $sat, $val) if ($ledDevice->{CONNECTION} eq 'LW12');
- return WifiLight_RGBLW12HX_setHSV($ledDevice, $hue, $sat, $val) if ($ledDevice->{CONNECTION} eq 'LW12HX');
- return WifiLight_RGBLW12FC_setHSV($ledDevice, $hue, $sat, $val) if ($ledDevice->{CONNECTION} eq 'LW12FC');
- return WifiLight_WhiteSENGLED_setHSV($ledDevice, $hue, $sat, $val, $isLast) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} eq 'SENGLED'));
- return WifiLight_RGB_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW1_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq "RGBW1") && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_RGBW2_setHSV($ledDevice, $hue, $sat, $val, $isLast) if ($ledDevice->{LEDTYPE} eq "RGBW2");
- return WifiLight_White_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'White') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'));
- return WifiLight_DualWhiteSunricher_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'DualWhite') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricher_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBSunricherA_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} eq 'SUNRICHERA'));
- return WifiLight_RGBWSunricher_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'SUNRICHER'));
- return WifiLight_RGBWSunricherA_setHSV($ledDevice, $hue, $sat, $val) if (($ledDevice->{LEDTYPE} eq 'RGBW') && ($ledDevice->{CONNECTION} eq 'SUNRICHERA'));
- return undef;
- }
- # dispatcher
- sub
- WifiLight_processEvent(@)
- {
- my ($ledDevice, $event, $progress) = @_;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} processEvent: $event, progress: $progress") if defined($event);
- DoTrigger($ledDevice->{NAME}, "programm: $event $progress",0) if defined($event);
- return undef;
- }
- sub
- WifiLight_HSV_Transition(@)
- {
- my ($ledDevice, $hue, $sat, $val, $ramp, $flags, $delay, $event) = @_;
- my ($hueFrom, $satFrom, $valFrom, $timeFrom);
-
- # minimum stepwide
- my $defaultDelay = $delay;
- # if queue in progess set start vals to last cached hsv target, else set start to actual hsv
- if (@{$ledDevice->{helper}->{hlCmdQueue}} > 0)
- {
- $hueFrom = $ledDevice->{helper}->{targetHue};
- $satFrom = $ledDevice->{helper}->{targetSat};
- $valFrom = $ledDevice->{helper}->{targetVal};
- $timeFrom = $ledDevice->{helper}->{targetTime};
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} prepare start hsv transition (is cached) hsv $hueFrom, $satFrom, $valFrom, $timeFrom");
- }
- else
- {
- $hueFrom = $ledDevice->{READINGS}->{hue}->{VAL} || 0;
- $satFrom = $ledDevice->{READINGS}->{saturation}->{VAL} || 0;
- $valFrom = $ledDevice->{READINGS}->{brightness}->{VAL} || 0;
- $timeFrom = gettimeofday();
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} prepare start hsv transition (is actual) hsv $hueFrom, $satFrom, $valFrom, $timeFrom");
- }
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} current HSV $hueFrom, $satFrom, $valFrom");
- Log3 ($ledDevice, 3, "$ledDevice->{NAME} set HSV $hue, $sat, $val with ramp: $ramp, flags: ". $flags);
- # if there is no ramp we dont need transition
- if (($ramp || 0) == 0)
- {
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} hsv transition without ramp routed to direct settings, hsv $hue, $sat, $val");
- $ledDevice->{helper}->{targetTime} = $timeFrom;
- return WifiLight_HighLevelCmdQueue_Add($ledDevice, $hue, $sat, $val, undef, $delay, 100, $event, $timeFrom);
- }
- # calculate the left and right turn length based
- # startAngle +360 -endAngle % 360 = counter clock
- # endAngle +360 -startAngle % 360 = clockwise
- my $fadeLeft = ($hueFrom + 360 - $hue) % 360;
- my $fadeRight = ($hue + 360 - $hueFrom) % 360;
- my $direction = ($fadeLeft <=> $fadeRight); # -1 = counterclock, +1 = clockwise
- $direction = ($direction == 0)?1:$direction; # in dupt cw
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} color rotation dev cc:$fadeLeft, cw:$fadeRight, shortest:$direction");
- $direction *= -1 if ($flags =~ m/.*[lL].*/); # reverse if long path desired (flag l or L is set)
- my $rotation = ($direction == 1)?$fadeRight:$fadeLeft; # angle of hue rotation in based on flags
- my $sFade = abs($sat - $satFrom);
- my $vFade = abs($val - $valFrom);
-
- my ($stepWide, $steps, $hueToSet, $hueStep, $satToSet, $satStep, $valToSet, $valStep);
-
- # fix if there is in fact no transition, blocks queue for given ramp time with actual hsv values
- if ($rotation == 0 && $sFade == 0 && $vFade == 0)
- {
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} hsv transition with unchaned settings, hsv $hue, $sat, $val, ramp $ramp");
- #TODO remove if tested
- #WifiLight_HighLevelCmdQueue_Add($ledDevice, $hue, $sat, $val, undef, $ramp * 1000, 0, $event, $timeFrom);
-
- $ledDevice->{helper}->{targetTime} = $timeFrom + $ramp;
- return WifiLight_HighLevelCmdQueue_Add($ledDevice, $hue, $sat, $val, undef, $delay, 100, $event, $timeFrom + $ramp);
- }
- if (($rotation >= $sFade) && ($rotation >= $vFade))
- {
- $stepWide = ($ramp * 1000 / $rotation); # how long is one step (set hsv) in ms based on hue
- $stepWide = $defaultDelay if ($stepWide < $defaultDelay);
- $steps = int($ramp * 1000 / $stepWide); # how many steps will we need ?
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} transit (H>S||V) steps: $steps stepwide: $stepWide");
- }
- elsif (($sFade >= $rotation) && ($sFade >= $vFade))
- {
- $stepWide = ($ramp * 1000 / $sFade); # how long is one step (set hsv) in ms based on sat
- $stepWide = $defaultDelay if ($stepWide < $defaultDelay);
- $steps = int($ramp * 1000 / $stepWide); # how many steps will we need ?
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} transit (S>H||V) steps: $steps stepwide: $stepWide");
- }
- else
- {
- $stepWide = ($ramp * 1000 / $vFade); # how long is one step (set hsv) in ms based on val
- $stepWide = $defaultDelay if ($stepWide < $defaultDelay);
- $steps = int($ramp * 1000 / $stepWide); # how many steps will we need ?
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} transit (V>H||S) steps: $steps stepwide: $stepWide");
- }
-
- $hueToSet = $hueFrom; # prepare tmp working hue
- $hueStep = $rotation / $steps * $direction; # how big is one hue step base on timing choosen
-
- $satToSet = $satFrom; # prepare workin sat
- $satStep = ($sat - $satFrom) / $steps;
-
- $valToSet = $valFrom;
- $valStep = ($val - $valFrom) / $steps;
- #TODO do something more flexible
- #TODO remove if tested
- # $timeFrom += 1;
- for (my $i=1; $i <= $steps; $i++)
- {
- $hueToSet += $hueStep;
- $hueToSet -= 360 if ($hueToSet > 360); #handle turn over zero
- $hueToSet += 360 if ($hueToSet < 0);
- $satToSet += $satStep;
- $valToSet += $valStep;
- my $progress = 100 / $steps * $i;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} add to hl queue h:".($hueToSet).", s:".($satToSet).", v:".($valToSet)." ($i/$steps)");
- WifiLight_HighLevelCmdQueue_Add($ledDevice, int($hueToSet +0.5), int($satToSet +0.5), int($valToSet +0.5), undef, $stepWide, int($progress +0.5), $event, $timeFrom + (($i-1) * $stepWide / 1000) );
- }
- $ledDevice->{helper}->{targetTime} = $timeFrom + $ramp;
- return undef;
- }
- sub
- WifiLight_SetHSV_Target(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- $ledDevice->{helper}->{targetHue} = $hue;
- $ledDevice->{helper}->{targetSat} = $sat;
- $ledDevice->{helper}->{targetVal} = $val;
- return undef;
- }
- sub
- WifiLight_setHSV_Readings(@)
- {
- my ($ledDevice, $hue, $sat, $val) = @_;
- my ($r, $g, $b) = WifiLight_HSV2RGB($hue, $sat, $val);
- readingsBeginUpdate($ledDevice);
- readingsBulkUpdate($ledDevice, "hue", $hue % 360);
- readingsBulkUpdate($ledDevice, "saturation", $sat);
- readingsBulkUpdate($ledDevice, "brightness", $val);
- readingsBulkUpdate($ledDevice, "RGB", sprintf("%02X%02X%02X",$r,$g,$b));
- readingsBulkUpdate($ledDevice, "state", "on") if ($val > 0);
- readingsBulkUpdate($ledDevice, "state", "off") if ($val == 0);
- readingsEndUpdate($ledDevice, 1);
- }
- sub
- WifiLight_HSV2RGB(@)
- {
- my ($hue, $sat, $val) = @_;
- if ($sat == 0)
- {
- return int(($val * 2.55) +0.5), int(($val * 2.55) +0.5), int(($val * 2.55) +0.5);
- }
- $hue %= 360;
- $hue /= 60;
- $sat /= 100;
- $val /= 100;
- my $i = int($hue);
- my $f = $hue - $i;
- my $p = $val * (1 - $sat);
- my $q = $val * (1 - $sat * $f);
- my $t = $val * (1 - $sat * (1 - $f));
- my ($r, $g, $b);
- if ( $i == 0 )
- {
- ($r, $g, $b) = ($val, $t, $p);
- }
- elsif ( $i == 1 )
- {
- ($r, $g, $b) = ($q, $val, $p);
- }
- elsif ( $i == 2 )
- {
- ($r, $g, $b) = ($p, $val, $t);
- }
- elsif ( $i == 3 )
- {
- ($r, $g, $b) = ($p, $q, $val);
- }
- elsif ( $i == 4 )
- {
- ($r, $g, $b) = ($t, $p, $val);
- }
- else
- {
- ($r, $g, $b) = ($val, $p, $q);
- }
- return (int(($r * 255) +0.5), int(($g * 255) +0.5), int(($b * 255) + 0.5));
- }
- sub
- WifiLight_RGB2HSV(@)
- {
- my ($ledDevice, $in) = @_;
- my $r = hex substr($in, 0, 2);
- my $g = hex substr($in, 2, 2);
- my $b = hex substr($in, 4, 2);
- my ($max, $min, $delta);
- my ($h, $s, $v);
- $max = $r if (($r >= $g) && ($r >= $b));
- $max = $g if (($g >= $r) && ($g >= $b));
- $max = $b if (($b >= $r) && ($b >= $g));
- $min = $r if (($r <= $g) && ($r <= $b));
- $min = $g if (($g <= $r) && ($g <= $b));
- $min = $b if (($b <= $r) && ($b <= $g));
- $v = int(($max / 2.55) + 0.5);
- $delta = $max - $min;
- my $currentHue = ReadingsVal($ledDevice->{NAME}, "hue", 0);
- return ($currentHue, 0, $v) if (($max == 0) || ($delta == 0));
- $s = int((($delta / $max) *100) + 0.5);
- $h = ($g - $b) / $delta if ($r == $max);
- $h = 2 + ($b - $r) / $delta if ($g == $max);
- $h = 4 + ($r - $g) / $delta if ($b == $max);
- $h = int(($h * 60) + 0.5);
- $h += 360 if ($h < 0);
- return $h, $s, $v;
- }
- sub
- WifiLight_HSV2fourChannel(@)
- {
- my ($h, $s, $v) = @_;
- my ($r, $g, $b) = WifiLight_HSV2RGB($h, $s, $v);
- #white part, base 255
- my $white = 255;
- foreach ($r, $g, $b) { $white = $_ if ($_ < $white); }
- #remaining color part
- my ($rr, $rg, $rb);
- $rr = $r - $white;
- $rg = $g - $white;
- $rb = $b - $white;
- return ($rr, $rg, $rb, $white);
- }
- sub
- WifiLight_Milight_ColorConverter(@)
- {
- my ($ledDevice, $cr, $cy, $cg, $cc, $cb, $cm) = @_;
- #my ($ledDevice) = @_;
- my @colorMap;
-
- #my $hueRed = 0;
- my $adjRed = 0 - ($cr || 0);
- #my $hueYellow = 60;
- my $adjYellow = 60 - ($cy || 0);
- #my $hueGreen = 120;
- my $adjGreen = 120 - ($cg || 0);
- #my $hueCyan = 180;
- my $adjCyan = 180 - ($cc || 0);
- #my $hueBlue = 240;
- my $adjBlue = 240 - ($cb || 0);
- #my $hueLilac = 300;
- my $adjLilac = 300 - ($cm || 0);
- #st34
- my $devRed = 168;
- #my $devRed = 176;
- my $devYellow = 134;
- #my $devYellow = 144;
- my $devGreen = 88;
- #my $devCyan = 48;
- my $devCyan = 56;
- my $devBlue = 8;
- my $devLilac = 208; #224
- my $i= 360;
- # red to yellow
- $adjRed += 360 if ($adjRed < 0); # in case of negative adjustment
- $devRed += 256 if ($devRed < $devYellow);
- $adjYellow += 360 if ($adjYellow < $adjRed);
- for ($i = $adjRed; $i <= $adjYellow; $i++)
- {
- $colorMap[$i % 360] = ($devRed - int((($devRed - $devYellow) / ($adjYellow - $adjRed) * ($i - $adjRed)) +0.5)) % 255;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} create colormap h: ".($i % 360)." d: ".$colorMap[$i % 360]);
- }
- #yellow to green
- $devYellow += 256 if ($devYellow < $devGreen);
- $adjGreen += 360 if ($adjGreen < $adjYellow);
- for ($i = $adjYellow; $i <= $adjGreen; $i++)
- {
- $colorMap[$i % 360] = ($devYellow - int((($devYellow - $devGreen) / ($adjGreen - $adjYellow) * ($i - $adjYellow)) +0.5)) % 255;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} create colormap h: ".($i % 360)." d: ".$colorMap[$i % 360]);
- }
- #green to cyan
- $devGreen += 256 if ($devGreen < $devCyan);
- $adjCyan += 360 if ($adjCyan < $adjGreen);
- for ($i = $adjGreen; $i <= $adjCyan; $i++)
- {
- $colorMap[$i % 360] = ($devGreen - int((($devGreen - $devCyan) / ($adjCyan - $adjGreen) * ($i - $adjGreen)) +0.5)) % 255;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} create colormap h: ".($i % 360)." d: ".$colorMap[$i % 360]);
- }
- #cyan to blue
- $devCyan += 256 if ($devCyan < $devCyan);
- $adjBlue += 360 if ($adjBlue < $adjCyan);
- for ($i = $adjCyan; $i <= $adjBlue; $i++)
- {
- $colorMap[$i % 360] = ($devCyan - int((($devCyan - $devBlue) / ($adjBlue - $adjCyan) * ($i - $adjCyan)) +0.5)) % 255;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} create colormap h: ".($i % 360)." d: ".$colorMap[$i % 360]);
- }
- #blue to lilac
- $devBlue += 256 if ($devBlue < $devLilac);
- $adjLilac += 360 if ($adjLilac < $adjBlue);
- for ($i = $adjBlue; $i <= $adjLilac; $i++)
- {
- $colorMap[$i % 360] = ($devBlue - int((($devBlue - $devLilac) / ($adjLilac - $adjBlue) * ($i- $adjBlue)) +0.5)) % 255;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} create colormap h: ".($i % 360)." d: ".$colorMap[$i % 360]);
- }
- #lilac to red
- $devLilac += 256 if ($devLilac < $devRed);
- $adjRed += 360 if ($adjRed < $adjLilac);
- for ($i = $adjLilac; $i <= $adjRed; $i++)
- {
- $colorMap[$i % 360] = ($devLilac - int((($devLilac - $devRed) / ($adjRed - $adjLilac) * ($i - $adjLilac)) +0.5)) % 255;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} create colormap h: ".($i % 360)." d: ".$colorMap[$i % 360]);
- }
- @{$ledDevice->{helper}->{COLORMAP}} = @colorMap;
- return \@colorMap;
- }
- sub
- WifiLight_RGB_ColorConverter(@)
- {
- # default correction +/- 29°
- my ($ledDevice, $cr, $cy, $cg, $cc, $cb, $cm) = @_;
- #my ($cr, $cy, $cg, $cc, $cb, $cm) = (0, -30, -10, -30, 0, -10);
- my @colorMap;
- for (my $i = 0; $i <= 360; $i++)
- {
- my $toR = WifiLight_HueDistance(0, $i);
- my $toY = WifiLight_HueDistance(60, $i);
- my $toG = WifiLight_HueDistance(120, $i);
- my $toC = WifiLight_HueDistance(180, $i);
- my $toB = WifiLight_HueDistance(240, $i);
- my $toM = WifiLight_HueDistance(300, $i);
-
- my $c = 0; # $i;
- $c += $cr - ($cr * $toR / 60) if (abs($toR) <= 60);
- $c += $cy - ($cy * $toY / 60) if (abs($toY) <= 60);
- $c += $cg - ($cg * $toG / 60) if (abs($toG) <= 60);
- $c += $cc - ($cc * $toC / 60) if (abs($toC) <= 60);
- $c += $cb - ($cb * $toB / 60) if (abs($toB) <= 60);
- $c += $cm - ($cm * $toM / 60) if (abs($toM) <= 60);
- $colorMap[$i] = int($i + $c + 0.5) % 360;
- #$colorMap[$i] = (int($colorMap[$i] + ($cr - ($cr * $toR / 45)) + 0.5) + 360) % 360 if (abs($toR) <= 45);
- #$colorMap[$i] = (int($colorMap[$i] + ($cy - ($cy * $toY / 45)) + 0.5) + 360) % 360 if (abs($toY) <= 45);
- #$colorMap[$i] = (int($colorMap[$i] + ($cg - ($cg * $toG / 45)) + 0.5) + 360) % 360 if (abs($toG) <= 45);
- }
- @{$ledDevice->{helper}->{COLORMAP}} = @colorMap;
- return \@colorMap;
- }
- # calculate the distance of two given hue
- sub
- WifiLight_HueDistance(@)
- {
- my ($hue, $testHue) = @_;
- my $a = (360 + $hue - $testHue) % 360;
- my $b = (360 + $testHue - $hue) % 360;
- return ($a, $b)[$a > $b];
- }
- # helper for easying access to attrib
- sub
- WifiLight_ccAttribVal(@)
- {
- my ($ledDevice, $dr, $dy, $dg, $dc, $db, $dm) = @_;
- my $a = AttrVal($ledDevice->{NAME}, 'colorCast', undef);
- if ($a)
- {
- my ($cr, $cy, $cg, $cc, $cb, $cm) = split (',', $a);
- }
- else
- {
- my ($cr, $cy, $cg, $cc, $cb, $cm) = ($dr, $dy, $dg, $dc, $db, $dm);
- }
- return ($dr, $dy, $dg, $dc, $db, $dm);
- }
- sub
- WifiLight_CreateGammaMapping(@)
- {
- my ($ledDevice, $gamma) = @_;
- my @gammaMap;
- for (my $i = 0; $i <= 100; $i += 1)
- {
- my $correction = ($i / 100) ** (1 / $gamma);
- $gammaMap[$i] = $correction * 100;
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} create gammamap v-in: ".$i.", v-out: $gammaMap[$i]");
- }
- return \@gammaMap;
- }
- ###############################################################################
- #
- # high level queue, long running color transitions
- #
- ###############################################################################
- sub
- WifiLight_HighLevelCmdQueue_Add(@)
- {
- my ($ledDevice, $hue, $sat, $val, $ctrl, $delay, $progress, $event, $targetTime) = @_;
- my $cmd;
- $cmd->{hue} = $hue;
- $cmd->{sat} = $sat;
- $cmd->{val} = $val;
- # $cmd->{k} = $k;
- $cmd->{ctrl} = $ctrl;
- $cmd->{delay} = $delay;
- $cmd->{progress} = $progress;
- $cmd->{event} = $event;
- $cmd->{targetTime} = $targetTime;
- $cmd->{inProgess} = 0;
- push @{$ledDevice->{helper}->{hlCmdQueue}}, $cmd;
- my $dbgStr = unpack("H*", $cmd->{ctrl} || '');
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue add hsv/ctrl $cmd->{hue}, $cmd->{sat}, $cmd->{val}, ctrl $dbgStr, targetTime $cmd->{targetTime}, qlen ".@{$ledDevice->{helper}->{hlCmdQueue}});
- my $actualCmd = @{$ledDevice->{helper}->{hlCmdQueue}}[0];
- # sender busy ?
- return undef if (($actualCmd->{inProgess} || 0) == 1);
- return WifiLight_HighLevelCmdQueue_Exec($ledDevice);
- }
- sub
- WifiLight_HighLevelCmdQueue_Exec(@)
- {
- my ($ledDevice) = @_;
- my $actualCmd = @{$ledDevice->{helper}->{hlCmdQueue}}[0];
- # transmission complete, remove
- shift @{$ledDevice->{helper}->{hlCmdQueue}} if ($actualCmd->{inProgess});
- # next in queue
- $actualCmd = @{$ledDevice->{helper}->{hlCmdQueue}}[0];
- my $nextCmd = @{$ledDevice->{helper}->{hlCmdQueue}}[1];
- # return if no more elements in queue
- return undef if (!defined($actualCmd->{inProgess}));
- # drop frames if next frame is already sceduled for given time. do not drop if it is the last frame or if it is a command
- while (defined($nextCmd->{targetTime}) && ($nextCmd->{targetTime} < gettimeofday()) && !$actualCmd->{ctrl})
- {
- shift @{$ledDevice->{helper}->{hlCmdQueue}};
- $actualCmd = @{$ledDevice->{helper}->{hlCmdQueue}}[0];
- $nextCmd = @{$ledDevice->{helper}->{hlCmdQueue}}[1];
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue exec drop frame at hlQueue level. hl qlen: ".@{$ledDevice->{helper}->{hlCmdQueue}});
- }
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} high level cmd queue exec dropper delay: ".($actualCmd->{targetTime} - gettimeofday()) );
- # set hsv or if a device ctrl command is sceduled: send it and ignore hsv
- if ($actualCmd->{ctrl})
- {
- my $dbgStr = unpack("H*", $actualCmd->{ctrl});
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue exec ctrl $dbgStr, qlen ".@{$ledDevice->{helper}->{hlCmdQueue}});
- WifiLight_sendCtrl($ledDevice, $actualCmd->{ctrl});
- }
- else
- {
- my $isLast = (@{$ledDevice->{helper}->{hlCmdQueue}} == 1)?1:undef;
- if (($ledDevice->{helper}->{llLock} == 0) || $isLast)
- {
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue exec hsv $actualCmd->{hue}, $actualCmd->{sat}, $actualCmd->{val}, delay $actualCmd->{delay}, hl qlen ".@{$ledDevice->{helper}->{hlCmdQueue}}.", ll qlen ".@{$ledDevice->{helper}->{llCmdQueue}}.", lock ".$ledDevice->{helper}->{llLock});
- WifiLight_setHSV($ledDevice, $actualCmd->{hue}, $actualCmd->{sat}, $actualCmd->{val}, $isLast);
- }
- else
- {
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} high level cmd queue exec drop frame at llQueue level. ll qlen: ".@{$ledDevice->{helper}->{llCmdQueue}}.", lock ".$ledDevice->{helper}->{llLock});
- }
- }
- $actualCmd->{inProgess} = 1;
- my $next = defined($nextCmd->{targetTime})?$nextCmd->{targetTime}:gettimeofday() + ($actualCmd->{delay} / 1000);
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue ask next $next");
- InternalTimer($next, "WifiLight_HighLevelCmdQueue_Exec", $ledDevice, 0);
- WifiLight_processEvent($ledDevice, $actualCmd->{event}, $actualCmd->{progress});
- return undef;
- }
- sub
- WifiLight_HighLevelCmdQueue_Clear(@)
- {
- my ($ledDevice) = @_;
- foreach my $a (keys %intAt)
- {
- if (($intAt{$a}{ARG} eq $ledDevice) && ($intAt{$a}{FN} eq 'WifiLight_HighLevelCmdQueue_Exec'))
- {
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue clear, remove timer at ".$intAt{$a}{TRIGGERTIME} );
- delete($intAt{$a}) ;
- }
- }
- $ledDevice->{helper}->{hlCmdQueue} = [];
- }
- # dispatcher for ctrl cmd
- sub
- WifiLight_sendCtrl(@)
- {
- my ($ledDevice, $ctrl) = @_;
- # TODO adjust for all bridge types
- if (($ledDevice->{LEDTYPE} eq 'RGB') && ($ledDevice->{CONNECTION} =~ 'bridge-V[2|3]'))
- {
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $ctrl, $receiver, $delay);
- }
- if ($ledDevice->{LEDTYPE} eq 'RGBW1')
- {
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $ctrl, $receiver, $delay);
- }
- if ($ledDevice->{LEDTYPE} eq 'RGBW2')
- {
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 100;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $ctrl, $receiver, $delay);
- }
- if ($ledDevice->{LEDTYPE} eq 'White')
- {
- my $receiver = sockaddr_in($ledDevice->{PORT}, inet_aton($ledDevice->{IP}));
- my $delay = 10;
- WifiLight_LowLevelCmdQueue_Add($ledDevice, $ctrl, $receiver, $delay);
- }
- }
- ###############################################################################
- #
- # atomic low level udp communication to device
- # required because there are timing requirements, mostly limitaions in processing speed of the bridge
- # the commands should never be interrupted or canceled because some fhem readings are set in advance
- #
- ###############################################################################
- sub
- WifiLight_LowLevelCmdQueue_Add(@)
- {
- my ($ledDevice, $command, $receiver, $delay, $unlock) = @_;
- my $cmd;
- $cmd->{command} = $command;
- $cmd->{sender} = $ledDevice;
- $cmd->{receiver} = $receiver;
- $cmd->{delay} = $delay;
- $cmd->{unlock} = $unlock;
- $cmd->{inProgess} = 0;
- # push cmd into queue
- push @{$ledDevice->{helper}->{llCmdQueue}}, $cmd;
- my $dbgStr = unpack("H*", $cmd->{command});
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} low level cmd queue add $dbgStr, qlen ".@{$ledDevice->{helper}->{llCmdQueue}});
- my $actualCmd = @{$ledDevice->{helper}->{llCmdQueue}}[0];
-
- # sender busy ?
- return undef if ($actualCmd->{inProgess});
- return WifiLight_LowLevelCmdQueue_Send($ledDevice);
- }
- sub
- WifiLight_LowLevelCmdQueue_Send(@)
- {
- my ($ledDevice) = @_;
- my $actualCmd = @{$ledDevice->{helper}->{llCmdQueue}}[0];
- # transmission complete, remove
- shift @{$ledDevice->{helper}->{llCmdQueue}} if ($actualCmd->{inProgess});
- # next in queue
- $actualCmd = @{$ledDevice->{helper}->{llCmdQueue}}[0];
-
- # remove a low level queue lock if present and get next
- while (($actualCmd->{unlock} || 0) == 1)
- {
- $actualCmd->{sender}->{helper}->{llLock} -= 1;
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} | $actualCmd->{sender}->{NAME} unlock queue ".$actualCmd->{sender}->{helper}->{llLock});
- shift @{$ledDevice->{helper}->{llCmdQueue}};
- $actualCmd = @{$ledDevice->{helper}->{llCmdQueue}}[0];
- }
- # return if no more elements in queue
- return undef if (!defined($actualCmd->{command}));
- my $dbgStr = unpack("H*", $actualCmd->{command});
- Log3 ($ledDevice, 5, "$ledDevice->{NAME} low level cmd queue qlen ".@{$ledDevice->{helper}->{llCmdQueue}}.", send $dbgStr");
- # TCP
- if ($ledDevice->{PROTO})
- {
- if (!$ledDevice->{helper}->{SOCKET} || ($ledDevice->{helper}->{SELECT}->can_read(0) && !$ledDevice->{helper}->{SOCKET}->recv(my $data, 512)))
- {
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} low level cmd queue send $dbgStr, qlen ".@{$ledDevice->{helper}->{llCmdQueue}}." connection refused: trying to reconnect");
- if ($ledDevice->{helper}->{SOCKET}) {
- $ledDevice->{helper}->{SOCKET}->shutdown(2);
- $ledDevice->{helper}->{SOCKET}->close();
- }
- $ledDevice->{helper}->{SOCKET} = IO::Socket::INET-> new (
- PeerPort => $ledDevice->{PORT},
- PeerAddr => $ledDevice->{IP},
- Timeout => 1,
- Blocking => 0,
- Proto => 'tcp') or Log3 ($ledDevice, 3, "$ledDevice->{NAME} low level cmd queue send ERROR $dbgStr, qlen ".@{$ledDevice->{helper}->{llCmdQueue}}." (reconnect giving up)");
- $ledDevice->{helper}->{SELECT} = IO::Select->new($ledDevice->{helper}->{SOCKET}) if $ledDevice->{helper}->{SOCKET};
- }
- $ledDevice->{helper}->{SOCKET}->send($actualCmd->{command}) if $ledDevice->{helper}->{SOCKET};
- }
- else
- {
- # print "send: $ledDevice->{NAME} $dbgStr \n";
- send($ledDevice->{helper}->{SOCKET}, $actualCmd->{command}, 0, $actualCmd->{receiver}) or Log3 ($ledDevice, 1, "$ledDevice->{NAME} low level cmd queue send ERROR $@ $dbgStr, qlen ".@{$ledDevice->{helper}->{llCmdQueue}});
- }
- $actualCmd->{inProgess} = 1;
- my $msec = $actualCmd->{delay} / 1000;
- InternalTimer(gettimeofday()+$msec, "WifiLight_LowLevelCmdQueue_Send", $ledDevice, 0);
- return undef;
- }
- 1;
- =pod
- =item device
- =item summary controls a large number of different LED types
- =item summary_DE steuert eine große Anzahl unterschiedlicher LED Typen
- =begin html
- <a name="WifiLight"></a>
- <h3>WifiLight</h3>
- <ul>
- <p>The module controls a large number of different "no name" LED types and provide a consistent interface.</p>
- <p>Following types will be supported:</p>
- <!-- <table rules="all" cellpadding="6" style="border:solid 1px;"> -->
- <table>
- <thead align="left">
- <tr>
- <th>
- type / bridge
- </th>
- <th>
- type
- </th>
- <th>
- note
- </th>
- <th>
- define signature
- </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- Milight RGB first generation
- </td>
- <td>
- E27, stripe controller
- </td>
- <td>
- *(1,2,a,C)
- </td>
- <td>
- RGB bridge-V2|3
- </td>
- </tr>
- <tr>
- <td>
- Milight RGBW1 first generation
- </td>
- <td>
- RGBW stripe controller
- </td>
- <td>
- *(1,2,a)
- </td>
- <td>
- RGBW1 bridge-V2|3
- </td>
- </tr>
- <tr>
- <td>
- Milight Dual White
- </td>
- <td>
- E14, E27, GU10, stripe controller, Downlight
- </td>
- <td>
- *(1,2,b,W,nK)
- </td>
- <td>
- White bridge-V2|3
- </td>
- </tr>
- <tr>
- <td>
- Milight RGBW2 second generation
- </td>
- <td>
- E14, E27, GU10, stripe controller, Downlight
- </td>
- <td>
- *(2,b,CW,S20)
- </td>
- <td>
- RGBW2 bridge-V3
- </td>
- </tr>
- <tr>
- <td>
- LW12 first generation (SSID LEDNet...)
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LW12
- </td>
- </tr>
- <tr>
- <td>
- LW12HX (SSID HX...)
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LW12HX
- </td>
- </tr>
- <tr>
- <td>
- LW12FC (SSID FC...)
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LW12FC
- </td>
- </tr>
- <tr>
- <td>
- LD316 in RGB mode
- </td>
- <td>
- E27
- </td>
- <td>
-
- </td>
- <td>
- RGB LD316
- </td>
- </tr>
- <tr>
- <td>
- LD316 in RGBW mode
- </td>
- <td>
- E27
- </td>
- <td>
- *(S20)
- </td>
- <td>
- RGBW LD316
- </td>
- </tr>
- <tr>
- <td>
- LD316A in RGBW mode
- </td>
- <td>
- E27
- </td>
- <td>
- *(S20)
- </td>
- <td>
- RGBW LD316A
- </td>
- </tr>
- <tr>
- <td>
- LD382 in RGB mode
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LD382
- </td>
- </tr>
- <tr>
- <td>
- LD382 in RGBW mode
- </td>
- <td>
- RGBW stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGBW LD382
- </td>
- </tr>
- <tr>
- <td>
- LD382A (FW 1.0.6+) in RGB mode
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LD382
- </td>
- </tr>
- <tr>
- <td>
- LD382A (FW 1.0.6+) in RGBW mode
- </td>
- <td>
- RGBW stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGBW LD382
- </td>
- </tr>
- <tr>
- <td>
- SENGLED
- </td>
- <td>
- E27 bulb with build-in WLAN repeater
- </td>
- <td>
-
- </td>
- <td>
- White Sengled
- </td>
- </tr>
- <tr>
- <td>
- SUNRICHER with RGBW
- </td>
- <td>
- Controller
- </td>
- <td>
- *(!!!)
- </td>
- <td>
- RGBW Sunricher
- </td>
- </tr>
- </tbody>
- </table>
- <p>
- <small>
- (1) milght brigbe V2, V3, V4<br />
- (2) milight bridge V3, V4<br />
- (a) one group per bridge<br />
- (b) four independent group per bridge<br />
- (nK) no color temp support (Kelvin)<br />
- (C) pure color<br />
- (W) pure white<br />
- (CW) pure Color or pure white<br />
- (S20) Saturation <20: switch to pure white channel<br />
- (!!!) EXPERIMENTAL<br />
- </p>
- </small>
- <p>
- <table>
- <tr>
- <td>
- <p><b>Color</b></p>
- <p>Colors can be specified in RGB or HSV color space.</p>
- <p>Color in <a name="WifiLight_Farbraum_HSV"><b>color space "HSV"</b></a> are completely and generally more intuitive than RGB.</p>
- <p><b>H</b> (HUE: 0..360) are the basic color in a color wheel.
- <ul>
- <li>Red is at 0 °</li>
- <li>Green at 120 °</li>
- <li> Blue at 240 °</li>
- </ul>
- </p>
- <p><b>S</b> (Saturation: 0..100) stands for the saturation of the color. A saturation of 100 means the color is "pure" or completely saturated. Blue, for example, with 100% saturation corresponds to RGB # 0000FF.</p>
- <p><b>V</b> (Value: 0..100) indicates the brightness. A value of 50 states that "half brightness".</p>
- </td>
- <td>
- <a name="WifiLight_Farbkreis">
- <svg style="width:450px; height:320px;" viewBox="-100 -30 500 320">
- <linearGradient id="linearColors1" x1="0" y1="0" x2="1" y2="1">
- <stop offset="0%" stop-color="#FF0000"></stop>
- <stop offset="100%" stop-color="#FFFF00"></stop>
- </linearGradient>
- <linearGradient id="linearColors2" x1="0.5" y1="0" x2="0.5" y2="1">
- <stop offset="0%" stop-color="#FFFF00"></stop>
- <stop offset="100%" stop-color="#00FF00"></stop>
- </linearGradient>
- <linearGradient id="linearColors3" x1="1" y1="0" x2="0" y2="1">
- <stop offset="0%" stop-color="#00FF00"></stop>
- <stop offset="100%" stop-color="#00FFFF"></stop>
- </linearGradient>
- <linearGradient id="linearColors4" x1="1" y1="1" x2="0" y2="0">
- <stop offset="0%" stop-color="#00FFFF"></stop>
- <stop offset="100%" stop-color="#0000FF"></stop>
- </linearGradient>
- <linearGradient id="linearColors5" x1="0.5" y1="1" x2="0.5" y2="0">
- <stop offset="0%" stop-color="#0000FF"></stop>
- <stop offset="100%" stop-color="#FF00FF"></stop>
- </linearGradient>
- <linearGradient id="linearColors6" x1="0" y1="1" x2="1" y2="0">
- <stop offset="0%" stop-color="#FF00FF"></stop>
- <stop offset="100%" stop-color="#FF0000"></stop>
- </linearGradient>
- <linearGradient id="linearColors7" x1="152" y1="130" x2="152" y2="35" gradientUnits="userSpaceOnUse">
- <stop offset="0.2" stop-color="#FFFFFF"></stop>
- <stop offset="1" stop-color="#FF0000"></stop>
- </linearGradient>
- <linearGradient id="linearColors8" x1="152" y1="130" x2="230" y2="190" gradientUnits="userSpaceOnUse">
- <stop offset="0.2" stop-color="#FFFFFF"></stop>
- <stop offset="1" stop-color="#00FF00"></stop>
- </linearGradient>
- <linearGradient id="linearColors9" x1="152" y1="130" x2="70" y2="190" gradientUnits="userSpaceOnUse">
- <stop offset="0.2" stop-color="#FFFFFF"></stop>
- <stop offset="1" stop-color="#0000FF"></stop>
- </linearGradient>
- <marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">
- <path d="M2,2 L2,11 L10,6 L2,2" style="fill:grey;" />
- </marker>
- <path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="url(#linearColors1)" stroke-width="20" />
- <path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="url(#linearColors2)" stroke-width="20" />
- <path d="M253.9230 190 a120 120 0 0 1 -103.9230 60" fill="none" stroke="url(#linearColors3)" stroke-width="20" />
- <path d="M150 250 a120 120 0 0 1 -103.9230 -60" fill="none" stroke="url(#linearColors4)" stroke-width="20" />
- <path d="M46.077 190 a120 120 0 0 1 0 -120" fill="none" stroke="url(#linearColors5)" stroke-width="20" />
- <path d="M46.077 70 a120 120 0 0 1 103.9230 -60" fill="none" stroke="url(#linearColors6)" stroke-width="20" />
- <path d="M150,50 C250,50 250,180 180,200" fill="none" stroke="grey" stroke-width="2" marker-end="url(#markerArrow)" />
- <text class="Label" x="126" y="208">HUE</text>
- <line x1="152" y1="130" x2="152" y2="35" stroke="url(#linearColors7)" stroke-width="4" />
- <line x1="136" y1="120" x2="136" y2="45" stroke="grey" stroke-width="2" marker-end="url(#markerArrow)" />
- <text class="Label" x="96" y="96">SAT</text>
- <line x1="152" y1="130" x2="230" y2="190" stroke="url(#linearColors8)" stroke-width="4" />
- <line x1="152" y1="130" x2="70" y2="190" stroke="url(#linearColors9)" stroke-width="4" />
- <text x="120" y="-10">0° (Red)</text>
- <text x="270" y="60">60° (Yellow)</text>
- <text x="270" y="220">120° (Green)</text>
- <text x="110" y="285">180° (Cyan)</text>
- <text x="-60" y="220">240° (Blue)</text>
- <text x="-90" y="60">300° (Magenta)</text>
- </svg>
- </a>
- </td>
- </tr>
- </table>
- </p>
- <p>
- <b>Color: HSV compared to RGB</b>
- <p>
- Normally, a color may be expressed in the HSV color space as well as in RGB color space.
- <p>
- Colors in the HSV color space usually seem more understandable.
- To move a Green in the HSV color space a little more toward CYAN, simply increase the HUE value (angle) slightly.
- In RGB color space, the same task is less intuitive to achieve by increasing blue.
- <p>
- Differences become clear in Transitions however.
- In order to dim BLUE up the HSV Transitions 240,100,0 -> 240,100,100 would be used.
- To slowly dim RED (brightness 0) to BLUE the Transition in the HSV color space is 0,100,0 -> 240,100,100.
- In RGB color space (# 000000 -> # 0000FF) can not distinguish between the two versions.
- Here (correctly, but probably differently than intended) would appear in both cases, a white (brightness 0) as an initial value.
- </p>
- <p><b>Define</b></p>
- <ul>
- <li>
- <p><code>define <name> WifiLight <LED type> <bridgetype>:<IP|FQDN></code></p>
- <p>
- <i><u>example</u></i>
- <ul>
- <p>
- <i>defines a milight RGBW2 (bulb or LED stripe controller) on a milight bridge version 3 or 4.
- The LED is allocated to a maximum of 4 groups available per bridge in order of definition:</i>
- <br/>
- <code>define wz.licht.decke WifiLight RGBW2 bridge-V3:192.168.178.142</code>
- </ul>
- <ul>
- <p>
- <i>defines a LD382A Controller with RGBW stripe:</i>
- <br/>
- <code>define wz.licht.decke WifiLight RGBW LD382A:192.168.178.142</code>
- </ul>
- <ul>
- <p>
- <i>defines a LD382A Controller with RGB stripe:</i>
- <br/>
- <code>define wz.licht.decke WifiLight RGB LD382A:192.168.178.142</code>
- </ul>
- <p>WifiLight has a <a href="#WifiLight_Farbkalibrierung">"color calibration"</a>. Ideally, a calibration should be performed every time after a lamp change or after definition.</p>
- </ul>
- </li>
- <p><b>Set</b></p>
- <ul>
- <li>
- <p><code>set <name> <b>on</b> [ramp]</code></p>
- <p>Turns on the device. It is either chosen 100% White or the color defined by the attribute "default color".
- <p>Advanced options:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>off</b> [ramp]</code></p>
- <p>Turns of the device.
- <p>Advanced options:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>dimup</b></code></p>
- <p>Increases the brightness by a fixed amount. The attribute "dimStep" or the default "7" is applied.<br />
- This command is useful to increase particularly the brightness by a wall switch or a remote control.
- <p>Advanced options:
- <ul>
- <li>none</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>dimdown</b></code></p>
- <p>Decreases the brightness by a fixed amount. The attribute "dimStep" or the default "7" is applied.<br />
- This command is useful to reduce particularly the brightness by a wall switch or a remote control.
- <p>Advanced options:
- <ul>
- <li>none</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>dim</b> level [ramp] [q]</code></p>
- <p>Sets the brightness to the specified level (0..100).
- This command also maintains the preset color even with "dim 0" (off) and then "dim xx" (turned on) at.
- Therefore, it represents an alternative form to "off" / "on". The latter would always choose the "default color".
- <p>Advanced options:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- <p>Flags:
- <ul>
- <li>q</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>HSV</b> H,S,V [ramp] [s|l|q] [event]</code></p>
- <p>Sets the color in the <a href="#WifiLight_Farbraum_HSV">HSV color space</a>. If the ramp is specified (as a time in seconds), the module calculates a soft color transition from the current color to the newly set.
- <ul><i>For example, sets a saturated blue with half brightness:</i><br /><code>set wz.licht.decke HSV 240,100,50</code></ul>
- <p>Advanced options:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- <p>Flags:
- <ul>
- <li>s l q event</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>RGB</b> RRGGBB [ramp] [l|s|q] [event]</code></p>
- <p>Sets the color in the RGB color space.
- <p>Advanced options:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- <p>Flags:
- <ul>
- <li>s l q event</li>
- </ul>
- </p>
- </ul>
- </li>
- <p><b>Meaning of Flags</b></p>
- Certain commands (set) can be marked with special flags.
- <p>
- <ul>
- <li>ramp:
- <ul>
- Time in seconds for a soft color or brightness transition. The soft transition starts at the currently visible color and is calculated for the specified.
- </ul>
- </li>
- <li>s:
- <ul>
- (short, default). A smooth transition to another color is carried out in the <a href="#WifiLight_Farbkreis">"color wheel"</a> on the shortest path.
- A transition from red to green lead by the shortest route through yellow.
- </ul>
- </li>
- <li>l:
- <ul>
- (long). A smooth transition to another color is carried out in the <a href="#WifiLight_Farbkreis">"color wheel"</a> on the "long" way.
- A transition from red to green then leads across magenta, blue, and cyan.
- </ul>
- </li>
- <li>q:
- <ul>
- (queue). Commands with this flag are cached in an internal queue and will not run before the currently running soft transitions have been processed.
- Commands without the flag will be processed immediately. In this case all running transitions are stopped immediately and the queue will be cleared.
- </ul>
- </li>
- <li>event:
- <ul>
- designator ([A-Za-z_0-9])
- <p>
- WifiLight creates, when using this flag, during transitions to another color messages (events) in the form:
- <p>
- <code>WifiLight <NAME> programm: <EVENT> <XX></code>.
- <p>
- <EVENT> is the designator as specified in the flag.<br/>
- <XX> is the progress (percentage) of the transition.<br/>
- <p>
- Depending on the total duration of the transition, the values from 0 to 100 will not completely go through but for 0% and 100% is guaranteed always a event.
- To these events can then be reacted within a notify or DOIF to (for example):
- <ul>
- <li>increase the volume of a radio when a lamp is turned on in the morning slowly</li>
- <li>A color transition can be restarted in a notify if it is complete (loop it, even complex transitions)</li>
- <li>Other light sources can be synchronized by individually created color transitions.</li>
- </ul>
- </ul>
- </li>
- </ul>
- <p><b><a name="WifiLight_Farbkalibrierung"></a>color calibration</b></p>
- WifiLight supports two different types of color calibrations:
- <ul>
- <p>
- <b>Correction of saturated colors</b>
- <p>
- background:
- <p>
- YELLOW, for example, is defined as a mixture of red and green light in equal parts.
- Depending on the LED and control used the green channel may be much more luminous.
- If the red and green LEDs are each fully driven, GREEN predominates in this mixture and the desired YELLOW would get a distinct green tint.
- In this example, no yellow would be generated (corresponding to 60 ° in the <a href="#WifiLight_Farbkreis">"color wheel"</a>) for HSV 60,100,100.
- Instead GREEN would be generated with yellow tinge, perhaps corresponding to an estimated color angle of 80 °.
- The required correction for yellow would therefore minus 20° (60° target - 80° result = -20° correction).
- YELLOW may have to be corrected as to -20 °. Possible values per correction point are +/- 29 °.
- <p>
- procedure:
- <p>
- The correction of the full color is controlled by the attribute "color cast".
- Here 6 (comma separated) values are specified in the range from -29 to 29.
- These values are in accordance with the angle correction for red (0 °), yellow (60 °), green (120 °), cyan (180 °), blue (240 °) and magenta (300 °).
- First, the deviation of the mixed colors (60 ° / 180 ° / 300 °) should be determined as in the above example, and stored in the attribute.
- Following the primary colors (0 ° / 120 ° / 240 °) should be corrected so that the smooth transitions between adjacent pure colors appear as linear as possible.
- This process may need to be repeated iteratively multiple times until the result is harmonious.
- <p>
- <b>White Balance</b>
- <p>
- background:
- <p>
- Some bulbs produce white light by mixing the RGB channels (for example, LW12).
- Depending on the light intensity of the RGB channels of the LED strips used, the result is different.
- One or two colors dominate.
- In addition, there are various types of white light.
- Cold light has a higher proportion of blue.
- In Central Europe mostly warm white light is used for light sources.
- This has a high red and low blue component.
- <p>
- WifiLight offers the possibility for mixed RGB white to adapt the composition.
- The adjustment is carried out via the attribute "white point".
- The attribute expects a value between 0 and 1 (decimal point with) and the three colors are separated by a comma for each of the three RGB channels.
- <p>
- procedure:
- <p>
- A value of "1,1,1" sets all the three channels to 100% each.
- Assuming that the blue component of the white light should be reduced, a value of "1,1,0.5" sets the third channel (BLUE) in white on 0.5 according to 50%.
- Before doing a white balance correction the adjusment of the saturated color should be completed.
- </ul>
- <p><b>Attribute</b></p>
- <ul>
- <li>
- <code>attr <name> <b>colorCast</b> <R,Y,G,C,B,M></code>
- <p>
- <a href="#WifiLight_Farbkalibrierung">color calibration</a> of saturated colors.
- R(ed), Y(ellow), G(reen), C(yan), B(lue), M(agenta) in the range of +/- 29 (degrees)
- </li>
- <li>
- <code>attr <name> <b>defaultColor</b> <H,S,V></code>
- <p>
- Specify the light color in HSV which is selected at "on". Default is white.
- </li>
- <li>
- <code>attr <name> <b>defaultRamp</b> <0 bis X></code>
- <p>
- Time in seconds. If this attribute is set, a smooth transition is always implicitly generated if no ramp in the set is indicated.
- </li>
- <li>
- <code>attr <name> <b>dimStep</b> <0 bis 100></code>
- <p>
- Value by which the brightness at dim up and dim-down is changed. Default is "7"
- </li>
- <li>
- <code>attr <name> <b>gamma</b> <X.X></code>
- <p>
- The human eye perceives brightness changes very differently to (logarithmic).
- At low output brightness even a small change in brightness is perceived as very strong and on the other side strong changes are needed at high luminance.
- Therefore, a logarithmic correction of brightness increase of lamps is necessary so that the increase is found to be uniform.
- Some controllers perform this correction internally.
- In other cases it is necessary to store this correction in the module.
- A gamma value of 1.0 (default) results in a linear output values.
- Values less than 1.0 lead to a logarithmic correction.
- </li>
- <li>
- <code>attr <name> <b>whitePoint</b> <R,G,B></code>
- <p>
- <a href="#WifiLight_Farbkalibrierung">color calibration</a> for mixed RGB white light.
- </li>
- <li>
- <code>attr <name> <b><a href="#readingFnAttributes">readingFnAttributes</a></b></code>
- </li>
- </ul>
- <p><b>Colored device-icon for FhemWeb</b>
- <ul>
- <p>
- To activate a colored icon for <a href="#FHEMWEB">FhemWeb</a> the following attribute must be set:
- <p>
- <li>
- <code>attr <name> <b>devStateIcon</b> {Color_devStateIcon(ReadingsVal($name,"RGB","000000"))}</code>
- </li>
- </ul>
- <p><b>Colorpicker for FhemWeb</b>
- <ul>
- <p>
- In order for the Color Picker can be used in <a href="#FHEMWEB">FhemWeb</a> following attributes need to be set:
- <p>
- <li>
- <code>attr <name> <b>webCmd</b> RGB</code>
- </li>
- <li>
- <code>attr <name> <b>widgetOverride</b> RGB:colorpicker,RGB</code>
- </li>
- </ul>
- </ul>
- =end html
- =begin html_DE
- <a name="WifiLight"></a>
- <h3>WifiLight</h3>
- <ul>
- <p>Das Modul steuert eine große Anzahl unterschiedlicher "no name" LED Typen und stellt Ihnen einheitliches Interface zur Verfügung.</p>
- <p>Folgende Typen werden unterstützt:</p>
- <!-- <table rules="all" cellpadding="6" style="border:solid 1px;"> -->
- <table>
- <thead align="left">
- <tr>
- <th>
- Leuchtmitteltyp / bridge
- </th>
- <th>
- Type
- </th>
- <th>
- Notiz
- </th>
- <th>
- Signatur im define
- </th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>
- Milight RGB erste Generation
- </td>
- <td>
- E27, stripe controller
- </td>
- <td>
- *(1,2,a,C)
- </td>
- <td>
- RGB bridge-V2|3
- </td>
- </tr>
- <tr>
- <td>
- Milight RGBW1 erste Generation
- </td>
- <td>
- RGBW stripe controller
- </td>
- <td>
- *(1,2,a)
- </td>
- <td>
- RGBW1 bridge-V2|3
- </td>
- </tr>
- <tr>
- <td>
- Milight White
- </td>
- <td>
- E14, E27, GU10, stripe controller, Downlight
- </td>
- <td>
- *(1,2,b,W,nK)
- </td>
- <td>
- White bridge-V2|3
- </td>
- </tr>
- <tr>
- <td>
- Milight RGBW2 zweite Generation
- </td>
- <td>
- E14, E27, GU10, stripe controller, Downlight
- </td>
- <td>
- *(2,b,CW,S20)
- </td>
- <td>
- RGBW2 bridge-V3
- </td>
- </tr>
- <tr>
- <td>
- LW12 erste Generation (SSID LEDNet...)
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LW12
- </td>
- </tr>
- <tr>
- <td>
- LW12HX (SSID HX...)
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LW12HX
- </td>
- </tr>
- <tr>
- <td>
- LW12FC (SSID FC...)
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LW12FC
- </td>
- </tr>
- <tr>
- <td>
- LD316 im RGB mode
- </td>
- <td>
- E27
- </td>
- <td>
-
- </td>
- <td>
- RGB LD316
- </td>
- </tr>
- <tr>
- <td>
- LD316 im RGBW mode
- </td>
- <td>
- E27
- </td>
- <td>
- *(S20)
- </td>
- <td>
- RGBW LD316
- </td>
- </tr>
- <tr>
- <td>
- LD316A im RGBW mode
- </td>
- <td>
- E27
- </td>
- <td>
- *(S20)
- </td>
- <td>
- RGBW LD316A
- </td>
- </tr>
- <tr>
- <td>
- LD382 im RGB mode
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LD382
- </td>
- </tr>
- <tr>
- <td>
- LD382 im RGBW mode
- </td>
- <td>
- RGBW stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGBW LD382
- </td>
- </tr>
- <tr>
- <td>
- LD382A (FW 1.0.6) im RGB mode
- </td>
- <td>
- RGB stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGB LD382
- </td>
- </tr>
- <tr>
- <td>
- LD382A (FW 1.0.6) im RGBW mode
- </td>
- <td>
- RGBW stripe controller
- </td>
- <td>
-
- </td>
- <td>
- RGBW LD382
- </td>
- </tr>
- <tr>
- <td>
- SENGLED
- </td>
- <td>
- E27 mit WLAN repeater
- </td>
- <td>
-
- </td>
- <td>
- White Sengled
- </td>
- </tr>
- <tr>
- <td>
- SUNRICHER mit RGBW
- </td>
- <td>
- Controller
- </td>
- <td>
- *(!!!)
- </td>
- <td>
- RGBW Sunricher
- </td>
- </tr>
- </tbody>
- </table>
- <p>
- <small>
- (1) milght brigbe V2, V3, V4<br />
- (2) milight bridge V3, V4<br />
- (a) eine Gruppe pro bridge<br />
- (b) vier unabhängige Gruppen pro bridge<br />
- (nK) kein Temperatursupport, Kelvin<br />
- (C) rein Color<br />
- (W) rein White<br />
- (CW) rein Color oder White<br />
- (S20) Saturation <20: umschalten white Channel<br />
- (!!!) EXPERIMENTAL<br />
- </p>
- </small>
- <p>
- <table>
- <tr>
- <td>
- <p><b>Farbangaben</b></p>
- <p>Farben können im RGB oder im HSV Farbraum angegeben werden.</p>
- <p>Farbangaben im <a name="WifiLight_Farbraum_HSV"><b>Farbraum "HSV"</b></a> sind vollständig und in der Regel intuitiver als RGB.</p>
- <p><b>H</b> (HUE: 0..360) gibt die Grundfarbe in einem Farbkreis an.
- <ul>
- <li>Rot liegt bei 0°</li>
- <li>Grün bei 120°</li>
- <li>Blau bei 240°</li>
- </ul>
- </p>
- <p><b>S</b> (Saturation/Sättigung: 0..100) steht für die Sättigung der Farbe. Eine Sättigung von 100 bedeutet die Farbe ist "rein" oder komplett gesättigt. Blau zum Beispiel mit 100% Sättigung entspricht RGB #0000FF.</p>
- <p><b>V</b> (Value: 0..100) gibt die Helligkeit an. Ein V von 50 heißt: "halbe Helligkeit".</p>
- </td>
- <td>
- <a name="WifiLight_Farbkreis">
- <svg style="width:450px; height:320px;" viewBox="-100 -30 500 320">
- <linearGradient id="linearColors1" x1="0" y1="0" x2="1" y2="1">
- <stop offset="0%" stop-color="#FF0000"></stop>
- <stop offset="100%" stop-color="#FFFF00"></stop>
- </linearGradient>
- <linearGradient id="linearColors2" x1="0.5" y1="0" x2="0.5" y2="1">
- <stop offset="0%" stop-color="#FFFF00"></stop>
- <stop offset="100%" stop-color="#00FF00"></stop>
- </linearGradient>
- <linearGradient id="linearColors3" x1="1" y1="0" x2="0" y2="1">
- <stop offset="0%" stop-color="#00FF00"></stop>
- <stop offset="100%" stop-color="#00FFFF"></stop>
- </linearGradient>
- <linearGradient id="linearColors4" x1="1" y1="1" x2="0" y2="0">
- <stop offset="0%" stop-color="#00FFFF"></stop>
- <stop offset="100%" stop-color="#0000FF"></stop>
- </linearGradient>
- <linearGradient id="linearColors5" x1="0.5" y1="1" x2="0.5" y2="0">
- <stop offset="0%" stop-color="#0000FF"></stop>
- <stop offset="100%" stop-color="#FF00FF"></stop>
- </linearGradient>
- <linearGradient id="linearColors6" x1="0" y1="1" x2="1" y2="0">
- <stop offset="0%" stop-color="#FF00FF"></stop>
- <stop offset="100%" stop-color="#FF0000"></stop>
- </linearGradient>
- <linearGradient id="linearColors7" x1="152" y1="130" x2="152" y2="35" gradientUnits="userSpaceOnUse">
- <stop offset="0.2" stop-color="#FFFFFF"></stop>
- <stop offset="1" stop-color="#FF0000"></stop>
- </linearGradient>
- <linearGradient id="linearColors8" x1="152" y1="130" x2="230" y2="190" gradientUnits="userSpaceOnUse">
- <stop offset="0.2" stop-color="#FFFFFF"></stop>
- <stop offset="1" stop-color="#00FF00"></stop>
- </linearGradient>
- <linearGradient id="linearColors9" x1="152" y1="130" x2="70" y2="190" gradientUnits="userSpaceOnUse">
- <stop offset="0.2" stop-color="#FFFFFF"></stop>
- <stop offset="1" stop-color="#0000FF"></stop>
- </linearGradient>
- <marker id="markerArrow" markerWidth="13" markerHeight="13" refX="2" refY="6" orient="auto">
- <path d="M2,2 L2,11 L10,6 L2,2" style="fill:grey;" />
- </marker>
- <path d="M150 10 a120 120 0 0 1 103.9230 60" fill="none" stroke="url(#linearColors1)" stroke-width="20" />
- <path d="M253.9230 70 a120 120 0 0 1 0 120" fill="none" stroke="url(#linearColors2)" stroke-width="20" />
- <path d="M253.9230 190 a120 120 0 0 1 -103.9230 60" fill="none" stroke="url(#linearColors3)" stroke-width="20" />
- <path d="M150 250 a120 120 0 0 1 -103.9230 -60" fill="none" stroke="url(#linearColors4)" stroke-width="20" />
- <path d="M46.077 190 a120 120 0 0 1 0 -120" fill="none" stroke="url(#linearColors5)" stroke-width="20" />
- <path d="M46.077 70 a120 120 0 0 1 103.9230 -60" fill="none" stroke="url(#linearColors6)" stroke-width="20" />
- <path d="M150,50 C250,50 250,180 180,200" fill="none" stroke="grey" stroke-width="2" marker-end="url(#markerArrow)" />
- <text class="Label" x="126" y="208">HUE</text>
- <line x1="152" y1="130" x2="152" y2="35" stroke="url(#linearColors7)" stroke-width="4" />
- <line x1="136" y1="120" x2="136" y2="45" stroke="grey" stroke-width="2" marker-end="url(#markerArrow)" />
- <text class="Label" x="96" y="96">SAT</text>
- <line x1="152" y1="130" x2="230" y2="190" stroke="url(#linearColors8)" stroke-width="4" />
- <line x1="152" y1="130" x2="70" y2="190" stroke="url(#linearColors9)" stroke-width="4" />
- <text x="120" y="-10">0° (Rot)</text>
- <text x="270" y="60">60° (Gelb)</text>
- <text x="270" y="220">120° (Grün)</text>
- <text x="110" y="285">180° (Cyan)</text>
- <text x="-60" y="220">240° (Blau)</text>
- <text x="-90" y="60">300° (Magenta)</text>
- </svg>
- </a>
- </td>
- </tr>
- </table>
- </p>
- <p><b>Farbangaben: HSV gegenüber RGB</b><p>
- <p>
- Im Normalfall kann eine Farbe im HSV Farbraum genauso wie im RGB Farbraum dargestellt werden.
- <p>
- Farben im HSV Farbraum wirken meist verständlicher.
- Um ein Grün im HSV Farbraum etwas mehr in Richtung CYAN zu bewegen wird einfach der HUE Wert (Winkel) etwas erhöht.
- Im RGB Farbraum ist die gleiche Aufgabe weniger intuitiv durch eine Erhöhung von BLAU zu erreichen.
- <p>
- Unterschiede werden jedoch bei Transitions deutlich.
- Um BLAU langsam auf zu dimmen lauten die HSV Transitions 240,100,0 -> 240,100,100.
- Um von ROT (Helligkeit 0) langsam auf BLAU zu dimmen wird im HSV Farbraum 0,100,0 -> 240,100,100 verwendet.
- Im RGB Farbraum (#000000 -> #0000FF) kann nicht zwischen den beiden Varianten unterschieden werden.
- Hier würde (richtiger weise, vermutlich jedoch anders als beabsichtigt) in beiden Fällen ein Weiß (Helligkeit 0) als Startwert erscheinen.
- </p>
- <p><b>Define</b></p>
- <ul>
- <li>
- <p><code>define <name> WifiLight <Leuchtmitteltyp> <bridgetyp>:<IP|FQDN></code></p>
- <p>
- <i><u>Beispiele</u></i>
- <ul>
- <p>
- <i>definiert einen milight RGBW2 Leuchtmittel (Bulb oder LED stripe controller) an einer milight bridge Version 3 oder 4.
- Die LED wird den maximal 4 verfügbaren Gruppen pro bridge in der Reihenfolge der Definition zugeordnet:</i>
- <br/>
- <code>define wz.licht.decke WifiLight RGBW2 bridge-V3:192.168.178.142</code>
- </ul>
- <ul>
- <p>
- <i>definiert einen LD382A Controller mit RGBW Stripe:</i>
- <br/>
- <code>define wz.licht.decke WifiLight RGBW LD382A:192.168.178.142</code>
- </ul>
- <ul>
- <p>
- <i>definiert einen LD382A Controller mit RGB Stripe:</i>
- <br/>
- <code>define wz.licht.decke WifiLight RGB LD382A:192.168.178.142</code>
- </ul>
- <p>WifiLight verfügt über eine <a href="#WifiLight_Farbkalibrierung">"Farbkalibrierung"</a>. Sinnvollerweise sollte nach einem Leuchtmitteltausch oder einem define eine Kalibrierung vorgenommen werden.</p>
- </ul>
- </li>
- <p><b>Set</b></p>
- <ul>
- <li>
- <p><code>set <name> <b>on</b> [ramp]</code></p>
- <p>Schaltet das device ein. Dabei wird entweder 100% Weiß oder die im Attribut "defaultColor" definierte Farbe gewählt.
- <p>Erweiterte Parameter:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>off</b> [ramp]</code></p>
- <p>Schaltet das device aus.
- <p>Erweiterte Parameter:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>dimup</b></code></p>
- <p>Erhöht die Helligkeit um einen festen Betrag. Dabei wird der im Attribut "dimStep" definierte Wert oder der Default "7" angewendet.<br>Dieser Befehl eignet sich besonders um die Helligkeit über einen Wandschalter oder eine Fernbedienung zu erhöhen.
- <p>Erweiterte Parameter:
- <ul>
- <li>keine</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>dimdown</b></code></p>
- <p>Verringert die Helligkeit um einen festen Betrag. Dabei wird der im Attribut "dimStep" definierte Wert oder der Default "7" angewendet.<br>Dieser Befehl eignet sich besonders um die Helligkeit über einen Wandschalter oder eine Fernbedienung zu verringern
- <p>Erweiterte Parameter:
- <ul>
- <li>keine</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>dim</b> level [ramp] [q]</code></p>
- <p>Setzt die Helligkeit auf den angegebenen level (0..100).<br>Dieser Befehl behält außerdem die eingestellte Farbe auch bei "dim 0" (ausgeschaltet) und nachfolgendem "dim xx" (eingeschaltet) bei. Daher stellt er eine alternative Form zu "off" / "on" dar. Letzteres würde immer die "defaultColor" wählen.
- <p>Erweiterte Parameter:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- <p>Flags:
- <ul>
- <li>q</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>HSV</b> H,S,V [ramp] [s|l|q] [event]</code></p>
- <p>Setzt die Farbe im <a href="#WifiLight_Farbraum_HSV">HSV Farbraum</a>. Wenn die ramp (als Zeit in Sekunden) angegeben ist, berechnet das modul einen weichen Farbübergang von der aktuellen Farbe zur neu gesetzten.
- <ul><i>Beispiel, setzt ein gesättigtes Blau mit halber Helligkeit:</i><br /><code>set wz.licht.decke HSV 240,100,50</code></ul>
- <p>Erweiterte Parameter:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- <p>Flags:
- <ul>
- <li>s l q event</li>
- </ul>
- </p>
- </li>
- <li>
- <p><code>set <name> <b>RGB</b> RRGGBB [ramp] [l|s|q] [event]</code></p>
- <p>Setzt die Farbe im RGB Farbraum.
- <p>Erweiterte Parameter:
- <ul>
- <li>ramp</li>
- </ul>
- </p>
- <p>Flags:
- <ul>
- <li>s l q event</li>
- </ul>
- </p>
- </ul>
- </li>
- <p><b>Bedeutung der Flags</b></p>
- Bestimmte Befehle (set) können mit speziellen Flags versehen werden.
- <p>
- <ul>
- <li>ramp:
- <ul>
- Zeit in Sekunden für einen weichen Farb- oder Helligkeitsübergang. Der weiche Übergang startet bei der aktuell sichtbaren Farbe und wird zur angegeben berechnet.
- </ul>
- </li>
- <li>s:
- <ul>
- (short, default). Ein weicher Übergang zu einer anderen Farbe wird im <a href="#WifiLight_Farbkreis">"Farbkreis"</a> auf dem kürzesten Weg durchgeführt.</br>
- Eine Transition von ROT nach GRÜN führt auf dem kürzesten Weg über GELB.
- </ul>
- </li>
- <li>l:
- <ul>
- (long). Ein weicher Übergang zu einer anderen Farbe wird im <a href="#WifiLight_Farbkreis">"Farbkreis"</a> auf dem "langen" Weg durchgeführt.</br>
- Eine Transition von ROT nach GRÜN führt dann über MAGENTA, BLAU, und CYAN.
- </ul>
- </li>
- <li>q:
- <ul>
- (queue). Kommandos mit diesem Flag werden in einer internen Warteschlange zwischengespeichert und erst ausgeführt nachdem die aktuell laufenden weichen Übergänge
- abgearbeitet wurden. Kommandos ohne das Flag werden sofort abgearbeitet. Dabei werden alle laufenden Übergänge sofort abgebrochen und die Warteschlange wird gelöscht.
- </ul>
- </li>
- <li>event:
- <ul>
- Beliebige Bezeichnung ([A-Za-z_0-9])
- <p>
- WifiLight erzeugt bei Verwendung dieses Flags im Verlauf weicher Übergange zu einer anderen Farbe Nachrichten (events) in der Form:
- <p>
- <code>WifiLight <NAME> programm: <EVENT> <XX></code>.
- <p>
- <EVENT> entspricht dem Namen so wie im Flag angegeben.<br/>
- <XX> ist der prozentuale Fortschritt des Übergangs.<br/>
- <p>
- Je nach Gesamtdauer des Übergangs werden die Werte von 0 bis 100 nicht komplett durchlaufen wobei jedoch für 0% und 100% immer ein event garantiert ist. Auf diese events kann dann innerhalb von notify oder DOIF reagiert werden um zum Beispiel:
- <ul>
- <li>die Lautstärke eines Radios anzupassen wenn eine LED morgens langsam hochgedimmt wird</li>
- <li>ein Farbübergang kann in einem notify neu gestartet werden wenn er komplett ist (loop)</li>
- <li>andere Leuchtmittel können mit erstellten Farbübergängen synchronisiert werden</li>
- </ul>
- </ul>
- </li>
- </ul>
- <p><b><a name="WifiLight_Farbkalibrierung"></a>Farbkalibrierung</b></p>
- WifiLight unterstützt zwei unterschiedliche Formen der Farbkalibrierungen:
- <ul>
- <p>
- <b>Korrektur gesättigter Farben</b>
- <p>
- Hintergrund:
- <p>
- GELB, zum Beispiel, ist definiert als Mischung aus ROTEM und GRÜNEM Licht zu gleichen Teilen.
- Je nach verwendeter LED und Ansteuerung ist der GRÜNE Kanal nun möglicherweise viel leuchtstärker.
- Wenn jetzt also die ROTE und GRÜNE LED jeweils voll angesteuert werden überwiegt GRÜN in dieser Mischung und das gewünschte GELB bekäme einen deutlichen Grünstich.
- In diesem Beispiel würde jetzt für HSV 60,100,100 kein Gelb (entsprechend 60° im <a href="#WifiLight_Farbkreis">"Farbkreis"</a>) erzeugt.
- Stattdessen würde GRÜN mit GELBSTICH erzeugt das vielleicht einem geschätzten Farbwinkel von 80° entspricht.
- Die erforderliche Korrektur für GELB würde also minus 20° betragen (60° SOLL - 80° IST = -20° Korrektur).
- GELB müsste als um -20° korrigiert werden. Mögliche Werte pro Korrektur-Punkt sind +/- 29°.
- <p>
- Vorgehen:
- <p>
- Die Korrektur der Vollfarben wird über das Attribut "colorCast" gesteuert. Dabei werden 6 (Komma getrennte) Werte im Bereich -29 bis 29 angegeben.
- Diese Werte stehen entsprechen der Winkelkorrektur für ROT (0°), GELB (60°), GRÜN (120°), CYAN (180°), BLAU (240°) und MAGENTA (300°).
- Zuerst sollte die Abweichung für 60°/180°/300° (die Mischfarben) so wie in obigem Beispiel ermittelt und im Attribut hinterlegt werden.
- Im Anschluss sollten die Primärfarben (0°/120°/240°) so korrigiert werden das die weichen Übergänge zwischen benachbarten reinen Farben möglichst linear erscheinen.
- Dieser Vorgang muss eventuell iterativ mehrfach wiederholt werden bis das Ergebniss stimmig ist.
- <p>
- <b>Weißabgleich</b>
- <p>
- Hintergrund:
- <p>
- Einige Leuchtmittel erzeugen weißes Licht durch Mischung der RGB Kanäle (zum Beispiel LW12).
- Je nach Leuchtstärke der RGB Kanäle der verwendeten LED Streifen unterscheidet sich das Ergebnis und eine oder zwei Farben dominieren.
- Zusätzlich gibt es verschiedene Formen weißen Lichtes. Kaltes Licht hat einen höheren Blauanteil.
- Dagegen wird in Mitteleuropa für Leuchtmittel meist warm-weiß verwendet welches einen hohen ROT- und geringen BLAU Anteil hat.
- <p>
- WifiLight bietet die Möglichkeit bei RGB gemischtem Weiß die Zusammensetzung anzupassen. Die Anpassung erfolgt über das Attribut "whitePoint".
- Dieses erwartet für jeden der drei RGB Kanäle einen Wert zwischen 0 und 1 (ein Komma wird als Punkt angegeben). Die drei Werte werden mit einem normalen Komma getrennt.
- <p>
- Vorgehen:
- <p>
- Eine Angabe von "1,1,1" setzt alle die drei Kanäle auf jeweils 100%. Angenommen der BLAU Anteil des weißen Lichtes soll nun verringert werden.
- Ein Wert von "1,1,0.5" setzt den dritten Kanal (BLAU) bei Weiß auf 0.5 entsprechend 50%. Vor einem Weißabgleich sollte die Korrektur der Vollfarben abgeschlossen sein.
- </ul>
- <p><b>Attribute</b></p>
- <ul>
- <li>
- <code>attr <name> <b>colorCast</b> <R,Y,G,C,B,M></code>
- <p>
- <a href="#WifiLight_Farbkalibrierung">Farbkalibrierung</a> der voll gesättigten Farben.
- R(ed), Y(ellow), G(reen), C(yan), B(lue), M(agenta) im Bereich +/- 29
- </li>
- <li>
- <code>attr <name> <b>defaultColor</b> <H,S,V></code>
- <p>
- HSV Angabe der Lichtfarbe die bei "on" gewählt wird. Default ist Weiß.
- </li>
- <li>
- <code>attr <name> <b>defaultRamp</b> <0 bis X></code>
- <p>
- Zeit in Sekunden. Wenn dieses Attribut gesetzt ist wird implizit immer ein weicher Übergang erzeugt wenn keine Ramp im set angegeben ist.
- </li>
- <li>
- <code>attr <name> <b>dimStep</b> <0 bis 100></code>
- <p>
- Wert um den die Helligkeit bei dimUp und dimDown verändert wird. Default 7.
- </li>
- <li>
- <code>attr <name> <b>gamma</b> <X.X></code>
- <p>
- Das menschliche Auge nimmt Helligkeitsänderungen sehr unterschiedlich wahr (logarithmisch).
- Bei geringer Ausgangshelligkeit wird schon eine kleine Helligkeitsänderung als sehr stark empfunden und auf der anderen Seite sind bei großer Helligkeit starke Änderungen notwendig.
- Daher ist eine logarithmische Korrektur des Helligkeitsanstiegs der Leuchtmittel erforderlich damit der Anstieg als gleichmäßig empfunden wird.
- Einige controller führen diese Korrektur intern durch. In anderen Fällen ist es notwendig diese Korrektur im Modul zu hinterlegen.
- Ein gamma Wert von 1.0 (default) führt zu einer linearen Ausgabe der Werte. Werte kleiner als 1.0 führen zu einer logarithmischem Korrektur.
- </li>
- <li>
- <code>attr <name> <b>whitePoint</b> <R,G,B></code>
- <p>
- <a href="#WifiLight_Farbkalibrierung">Farbkalibrierung</a> für RGB gemischtes weißes Licht.
- </li>
- <li>
- <code>attr <name> <b><a href="#readingFnAttributes">readingFnAttributes</a></b></code>
- </li>
- </ul>
- <p><b>Farbiges Icon für FhemWeb</b>
- <ul>
- <p>
- Um ein farbiges Icon für <a href="#FHEMWEB">FhemWeb</a> zu aktivieren muss das folgende Attribut gesetzt sein:
- <p>
- <li>
- <code>attr <name> <b>devStateIcon</b> {Color_devStateIcon(ReadingsVal($name,"RGB","000000"))}</code>
- </li>
- </ul>
- <p><b>Colorpicker für FhemWeb</b>
- <ul>
- <p>
- Um den Color-Picker für <a href="#FHEMWEB">FhemWeb</a> zu aktivieren müssen folgende Attribute gesetzt werden:
- <p>
- <li>
- <code>attr <name> <b>webCmd</b> RGB</code>
- </li>
- <li>
- <code>attr <name> <b>widgetOverride</b> RGB:colorpicker,RGB</code>
- </li>
- </ul>
- </ul>
- =end html_DE
|