| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242 |
- ##############################################
- # $Id: 32_WifiLight.pm 15907 2018-01-16 20:58:44Z 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}) && ($defs{$key}{PORT} eq $hash->{PORT}) && ($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) = @_;
- Log3 ($ledDevice, 4, "$ledDevice->{NAME} high level cmd queue clear");
- RemoveInternalTimer($ledDevice, 'WifiLight_HighLevelCmdQueue_Exec');
- $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
|