49_SSCam.pm 447 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978
  1. ########################################################################################################################
  2. # $Id: 49_SSCam.pm 17256 2018-09-02 17:38:12Z DS_Starter $
  3. #########################################################################################################################
  4. # 49_SSCam.pm
  5. #
  6. # (c) 2015-2018 by Heiko Maaz
  7. # e-mail: Heiko dot Maaz at t-online dot de
  8. #
  9. # This Module can be used to operate Cameras defined in Synology Surveillance Station 7.0 or higher.
  10. # It's based on and uses Synology Surveillance Station API.
  11. #
  12. # This script is part of fhem.
  13. #
  14. # Fhem is free software: you can redistribute it and/or modify
  15. # it under the terms of the GNU General Public License as published by
  16. # the Free Software Foundation, either version 2 of the License, or
  17. # (at your option) any later version.
  18. #
  19. # Fhem is distributed in the hope that it will be useful,
  20. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. # GNU General Public License for more details.
  23. #
  24. # You should have received a copy of the GNU General Public License
  25. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  26. #
  27. #########################################################################################################################
  28. # Versions History:
  29. #
  30. # 7.1.0 02.09.2018 PIR Sensor enable/disable, SSCam_Set/SSCam_Get optimized
  31. # 7.0.1 27.08.2018 enable/disable issue (https://forum.fhem.de/index.php/topic,45671.msg830869.html#msg830869)
  32. # 7.0.0 27.07.2018 compatibility to API v2.8
  33. # 6.0.1 04.07.2018 Reading CamFirmware
  34. # 6.0.0 03.07.2018 HTTPS Support, buttons for refresh SSCamSTRM-devices
  35. # 5.3.0 29.06.2018 changes regarding to "createStreamDev ... generic", refresh reading parentState of all
  36. # SSCamSTRM devices with PARENT=SSCam-device, control elements for runView within fhemweb,
  37. # new CamLive.*-Readings, minor fixes
  38. # 5.2.7 26.06.2018 fix state turns to "off" even though cam is disabled
  39. # 5.2.6 20.06.2018 running stream as human readable entry for SSCamSTRM-Device, goAbsPTZ fix set-entry für non-PTZ
  40. # 5.2.5 18.06.2018 trigger lastsnap_fw to SSCamSTRM-Device only if snap was done by it.
  41. # 5.2.4 17.06.2018 SSCam_composegallery added and write warning if old composegallery-weblink device is used
  42. # 5.2.3 16.06.2018 no SSCamSTRM refresh when snapgetinfo was running without taken a snap by SSCamSTRM-Device
  43. # 5.2.2 16.06.2018 compatibility to SSCamSTRM V 1.1.0
  44. # 5.2.1 14.06.2018 design change of SSCam_StreamDev, change in event generation for SSCam_StreamDev, fix global vars
  45. # 5.2.0 14.06.2018 support longpoll refresh of SSCamSTRM-Devices
  46. # 5.1.0 13.06.2018 more control elements (Start/Stop Recording, Take Snapshot) in func SSCam_StreamDev
  47. # control of detaillink is moved to SSCamSTRM-device
  48. # 5.0.1 12.06.2018 control of page refresh improved (for e.g. Floorplan,Dashboard)
  49. # 5.0.0 11.06.2018 HLS Streaming, Buttons for Streaming-Devices, use of module SSCamSTRM for Streaming-Devices,
  50. # deletion of Streaming-devices if SSCam-device is deleted, some more improvements, minor bugfixes
  51. # 4.3.0 27.05.2018 HLS preparation changed
  52. # 4.2.0 22.05.2018 PTZ-Panel integrated to created StreamDevice
  53. # 4.1.0 05.05.2018 use SYNO.SurveillanceStation.VideoStream instead of SYNO.SurveillanceStation.VideoStreaming,
  54. # preparation for hls
  55. # 4.0.0 01.05.2018 AudioStream possibility added
  56. # 3.10.0 24.04.2018 createStreamDev added, new features lastrec_fw_MJPEG, lastrec_fw_MPEG4/H.264 added to
  57. # playback MPEG4/H.264 videos
  58. # 3.9.2 21.04.2018 minor fixes
  59. # 3.9.1 20.04.2018 Attribute ptzPanel_use, initial webcommands in DeviceOverview changed, minor fixes ptzPanel
  60. # 3.9.0 17.04.2018 control panel & PTZcontrol weblink device for PTZ cams
  61. # 3.8.4 06.04.2018 Internal MODEL changed to SVS or "CamVendor - CamModel" for Cams
  62. # 3.8.3 05.04.2018 bugfix V3.8.2, $OpMode "Start" changed, composegallery changed
  63. # 3.8.2 04.04.2018 $attr replaced by AttrVal, SSCam_wdpollcaminfo redesigned
  64. # 3.8.1 04.04.2018 some codereview like new sub SSCam_jboolmap
  65. # 3.8.0 03.04.2018 new reading PresetHome, setHome command, minor fixes
  66. # 3.7.0 26.03.2018 minor details of setPreset changed, new command delPreset
  67. # 3.6.0 25.03.2018 setPreset command, changed SSCam_wdpollcaminfo, SSCam_getcaminfoall
  68. # 3.5.0 22.03.2018 new get command listPresets
  69. # 3.4.0 21.03.2018 new commands startTracking, stopTracking
  70. # 3.3.1 20.03.2018 new readings CapPTZObjTracking, CapPTZPresetNumber
  71. # 3.3.0 25.02.2018 code review, API bug fix of runview lastrec, commandref revised (forum:#84953)
  72. # 3.2.4 18.11.2017 fix bug don't retrieve SSCam_getptzlistpreset if cam is disabled
  73. # 3.2.3 08.10.2017 set optimizeParams, get caminfo (simple), minor bugfix, commandref revised
  74. # 3.2.2 03.10.2017 make functions ready to use "SYNO.SurveillanceStation.PTZ" version 5, minor fixes, commandref
  75. # revised
  76. # 3.2.1 02.10.2017 change some "SYNO.SurveillanceStation.Camera" methods to version 9
  77. # 3.2.0 27.09.2017 new command get listLog, change to $hash->{HELPER}{".SNAPHASH"} for avoid huge "list"-report
  78. # 3.1.0 26.09.2017 move extevent from CAM to SVS model, Reading PollState enhanced for CAM-Model, minor fixes
  79. # 3.0.0 23.09.2017 Internal MODEL SVS or CAM -> distinguish/support Cams and SVS in different devices
  80. # new comand get storedCredentials, commandref revised
  81. # 2.9.0 20.09.2017 new function get homeModeState, minor fixes at simu_SVSversion, commandref revised
  82. # 2.8.2 19.09.2017 some preparations for version 9 of API "SYNO.SurveillanceStation.Camera", SSCam_logout added to function
  83. # get scanVirginirgin
  84. # 2.8.1 17.09.2017 attr simu_SVSversion changed, $mjpegHttp quotes dependend if noQuotesForSID set, commandref revised
  85. # 2.8.0 07.09.2017 Home Mode, commandref revised
  86. # 2.7.1 28.08.2017 minor fixes
  87. # 2.7.0 20.08.2017 bugfix if credentials not set, set maximum password lenth to 20
  88. # 2.6.3 12.08.2017 get snapGallery can also be triggered by at or notify (better use than "set"), commandref revised
  89. # 2.6.2 11.08.2017 set snapGallery can be triggered by at or notify
  90. # 2.6.1 07.08.2017 some changes in composegallery if createSnapGallery used, room Snapshots changed to SnapGalllery
  91. # commandref revised
  92. # 2.6.0 06.08.2017 new command createSnapGallery
  93. # 2.5.4 05.08.2017 analyze $hash->{CL} in SetFn bzw. GetFn, set snapGallery only if snapGalleryBoost=1 is set,
  94. # some snapGallery improvements and fixes
  95. # 2.5.3 02.08.2017 implement snapGallery as set-command
  96. # 2.5.2 01.08.2017 get snapGallery with or without snapGalleryBoost (some more attributes for snapGallery)
  97. # 2.5.1 31.07.2017 sub composegallery (no polling necessary)
  98. # 2.5.0 31.07.2017 logtext revised, new get snapGallery command
  99. # 2.4.1 29.07.2017 fix behavior of state when starting lastsnap_fw, fix "uninitialized value in pattern match (m//)
  100. # at ./FHEM/49_SSCam.pm line 2895"
  101. # 2.4.0 28.07.2017 new set command runView lastsnap_fw, commandref revised, minor fixes
  102. # 2.3.2 28.07.2017 code change of SSCam_getcaminfo (params of Internaltimer)
  103. # 2.3.1 28.07.2017 code review creating log entries when pollnologging is set/unset
  104. # 2.3.0 27.07.2017 new "get snapinfo" command, minor fixes
  105. # 2.2.4 25.07.2017 avoid error "Operation Getptzlistpreset of Camera ... was not successful" if cam is disabled
  106. # 2.2.3 30.06.2017 fix if SVSversion small "0", create events for "snap"
  107. # 2.2.2 11.06.2017 bugfix SSCam_login, SSCam_login_return,
  108. # Forum: https://forum.fhem.de/index.php/topic,45671.msg646701.html#msg646701
  109. # 2.2.1 15.05.2017 avoid FW_detailFn because of FW_deviceOverview is active (double streams in detailview if on)
  110. # 2.2.0 10.05.2017 check if JSON module has been loaded successfully, DeviceOverview available, options of
  111. # runView changed image->live_fw, link->live_link, link_open->live_open, lastrec ->lastrec_fw,
  112. # commandref revised
  113. # 2.1.4 08.05.2017 commandref changed
  114. # 2.1.3 05.05.2017 issue of operation error if CAMID is set and SID isn't valid, more login-errorcodes evaluation
  115. # 2.1.2 04.05.2017 default login retries increased to 3
  116. # 2.1.1 17.04.2017 SSCam_runliveview routine changed, {HELPER}{SID_STRM} deleted
  117. # 2.1.0 12.04.2017 some codereview, getapisites cached, CAMID cached, rewrite logs from verbose 4 to 5,
  118. # get scanVirgin, commandref replenished
  119. # 2.0.0 10.04.2017 redesign login procedure, fix Reading SVSversion use SMALL version, new attr loginRetries
  120. # 1.42 15.03.2017 SSCam_camop changed to get all cam id's and names
  121. # 1.41 15.03.2017 minor bugfix of blank character in state "disabled" (row 3383)
  122. # 1.40 21.01.2017 downgrade of API apicammaxver in SVS 8.0.0
  123. # 1.39 20.01.2017 compatibility to SVS 8.0.0, Version in Internals, execute SSCam_getsvsinfo after set credentials
  124. # 1.37 10.10.2016 bugfix Experimental keys on scalar is now forbidden (Perl >= 5.23)
  125. # (Forum: #msg501709)
  126. # 1.36 18.09.2016 bugfix of get presets, get patrols of zoom-cams without pan/tilt
  127. # 1.35 17.09.2016 internal timer of start-routines optimized
  128. # 1.34 15.09.2016 simu_SVSversion changed, added 407 errorcode message, external recording changed
  129. # for SVS 7.2
  130. # 1.33 21.08.2016 function get stmUrlPath added, fit to new commandref style, attribute showStmInfoFull added
  131. # 1.32.1 18.08.2016 empty event LastSnapId fixed
  132. # 1.32 17.08.2016 Logging of verbose 4 changed
  133. # 1.31 15.08.2016 Attr "noQuotesForSID" added, avoid possible 402 - permission denied problems
  134. # in some SVS/DS-combinations
  135. # 1.30 15.08.2016 commandref revised, more v4 logging in special case
  136. # 1.29 02.07.2016 add regex for adaption SVS version, url call for "snap" changed
  137. # 1.28 30.06.2016 Attr "showPassInLog" added, per default no password will be shown in log
  138. # 1.27 29.06.2016 Attr "simu_SVSversion" added, sub login_nonbl changed,
  139. # sub camret_nonbl changed (getlistptzpreset) due to 7.2 problem
  140. # 1.26.3 28.06.2016 Time::HiRes added
  141. # 1.26.2 05.05.2016 change: get "snapfileinfo" will get back an Infomessage if Reading "LastSnapId"
  142. # isn't available
  143. # 1.26.1 27.04.2016 bugfix module will not load due to Unknown warnings category 'experimental'
  144. # when using an older perl version
  145. # 1.26 22.04.2016 Attribute "disable" to deactivate the module added
  146. # 1.25 18.04.2016 motion detection parameters can be entered if
  147. # motion detection by camera or SVS is used
  148. # 1.24 16.04.2016 behavior of "set ... on" changed, Attr "recextend" added
  149. # please have a look at commandref and Wiki
  150. # bugfix: setstate-warning if FHEM will restarted and SVS is not reachable
  151. # (Forum: #308)
  152. # 1.23.2 12.04.2016 code review, no functional changes
  153. # 1.23.1 07.04.2016 command check for set cmd's don't work completely
  154. # 1.23 02.04.2016 change to RemoveInternalTimer for functions
  155. # 1.22 27.03.2016 bugfix "link_open" doesn't work after last update
  156. # 1.21 23.03.2016 added "lastrec"," lastrec_open" to playback last recording
  157. # 1.20.3 19.03.2016 change: delay of InternalTimer(s) changed
  158. # "ptzlistpresets" - "id" changed to "position" according to Synology-ticket
  159. # run "SSCam_geteventlist" automatically after recording-stop
  160. # 1.20.2 14.03.2016 change: routine "SSCam_initonboot" changed
  161. # 1.20.1 12.03.2016 bugfix: default recordtime 15 s is used if attribute "rectime" is set to "0"
  162. # 1.20 09.03.2016 command "extevent" added
  163. # 1.19.3 07.03.2016 bugfix "uninitialized value $lastrecstarttime",
  164. # "uninitialized value $lastrecstoptime",
  165. # new attribute "videofolderMap"
  166. # 1.19.2 06.03.2016 Reading "CamLastRec" added which contains Path/name
  167. # of last recording
  168. # 1.19.1 28.02.2016 enhanced command runView by option "link_open" to
  169. # open a streamlink immediately
  170. # 1.19 25.02.2016 functions for cam-livestream added
  171. # 1.18.1 21.02.2016 fixed a problem that the state is "disable" instead of
  172. # "disabled" if a camera is disabled and FHEM will be restarted
  173. # 1.18 20.02.2016 function "get ... eventlist" added,
  174. # Reading "CamEventNum" added which containes total number of
  175. # camera events,
  176. # change usage of reading "LastUpdateTime"
  177. # 1.17 19.02.2016 function "runPatrol" added that starts predefined patrols
  178. # of PTZ-cameras,
  179. # Reading "CamDetMotSc" added
  180. # 1.16.1 17.02.2016 Reading "CamExposureControl" added
  181. # 1.16 16.02.2016 set up of motion detection source now possible
  182. # 1.15 15.02.2016 control of exposure mode day, night & auto is possible now
  183. # 1.14 14.02.2016 The port in DEF-String is optional now,
  184. # if not given, default port 5000 is used
  185. # 1.13.2 13.02.2016 fixed a problem that manual updates using "getcaminfoall" are
  186. # leading to additional pollingloops if polling is used,
  187. # attribute "debugactivetoken" added for debugging-use
  188. # 1.13.1 12.02.2016 fixed a problem that a usersession won't be destroyed if a
  189. # function couldn't be executed successfully
  190. # 1.13 feature for retrieval snapfilename added
  191. # 1.12.1 09.02.2016 bugfix: "goAbsPTZ" may be unavailable on Windows-systems
  192. # 1.12 08.02.2016 added function "move" for continuous PTZ action
  193. # 1.11.1 07.02.2016 entries with loglevel "2" reviewed, changed to loglevel "3"
  194. # 1.11 05.02.2016 added function "goPreset" and "goAbsPTZ" to control the move of PTZ lense
  195. # to absolute positions
  196. # refere to commandref or have a look in forum at:
  197. # http://forum.fhem.de/index.php/topic,45671.msg404275.html#msg404275 ,
  198. # http://forum.fhem.de/index.php/topic,45671.msg404892.html#msg404892
  199. # 1.10 02.02.2016 added function "svsinfo" to get informations about installed SVS-package,
  200. # if Availability = " disconnected" then "state"-value will be "disconnected" too,
  201. # saved Credentials were deleted from file if a device will be deleted
  202. # 1.9.1 31.01.2016 a little bit code optimization
  203. # 1.9 28.01.2016 fixed the problem a recording may still stay active if fhem
  204. # will be restarted after a recording was triggered and
  205. # the recordingtime wasn't be over,
  206. # Enhancement of readings.
  207. # 1.8 25.01.2016 changed define in order to remove credentials from string,
  208. # added "set credentials" command to save username/password,
  209. # added Attribute "session" to make login-session selectable,
  210. # Note: You have to adapt your define-strings !!
  211. # Refere to commandref or look in forum at:
  212. # http://forum.fhem.de/index.php/topic,45671.msg397449.html#msg397449
  213. # 1.7 18.01.2016 Attribute "httptimeout" added
  214. # 1.6 16.01.2016 Change the define-string related to rectime.
  215. # Note: See all changes to rectime usage in commandref or here:
  216. # http://forum.fhem.de/index.php/topic,45671.msg391664.html#msg391664
  217. # 1.5.1 11.01.2016 Vars "USERNAME" and "RECTIME" removed from internals,
  218. # Var (Internals) "SERVERNAME" changed to "SERVERADDR",
  219. # minor change of Log messages,
  220. # Note: use rereadcfg in order to activate the changes
  221. # 1.5 04.01.2016 Function "Get" for creating Camera-Readings integrated,
  222. # Attributs pollcaminfoall, pollnologging added,
  223. # Function for Polling Cam-Infos added.
  224. # 1.4 23.12.2015 function "enable" and "disable" for SS-Cams added,
  225. # changed timout of Http-calls to a higher value
  226. # 1.3 19.12.2015 function "snap" for taking snapshots added,
  227. # fixed a bug that functions may impact each other
  228. # 1.2 14.12.2015 improve usage of verbose-modes
  229. # 1.1 13.12.2015 use of InternalTimer instead of fhem(sleep)
  230. # 1.0 12.12.2015 changed completly to HttpUtils_NonblockingGet for calling websites nonblocking,
  231. # LWP is not needed anymore
  232. #
  233. #
  234. # Definition: define <name> SSCam <camname> <ServerAddr> [ServerPort]
  235. #
  236. # Example of defining a Cam-device: define CamCP1 SSCAM Carport 192.168.2.20 [5000] [HTTP(S)]
  237. # Example of defining a SVS-device: define SDS1 SSCAM SVS 192.168.2.20 [5000] [HTTP(S)]
  238. #
  239. package main;
  240. eval "use JSON qw( decode_json );1;" or my $SScamMMDBI = "JSON"; # Debian: apt-get install libjson-perl
  241. use Data::Dumper; # Perl Core module
  242. use strict;
  243. use warnings;
  244. use MIME::Base64;
  245. use Time::HiRes;
  246. use HttpUtils;
  247. # no if $] >= 5.017011, warnings => 'experimental';
  248. # Version und getestete SVS-Version
  249. my $SSCamVersion = "7.1.0";
  250. my $compstat = "8.2.0";
  251. # Aufbau Errorcode-Hashes (siehe Surveillance Station Web API)
  252. my %SSCam_errauthlist = (
  253. 100 => "Unknown error",
  254. 101 => "The account parameter is not specified",
  255. 102 => "API does not exist",
  256. 400 => "Invalid user or password",
  257. 401 => "Guest or disabled account",
  258. 402 => "Permission denied - DSM-Session: make sure user is member of Admin-group, SVS-Session: make sure SVS package is started, make sure FHEM-Server IP won't be blocked in DSM automated blocking list",
  259. 403 => "One time password not specified",
  260. 404 => "One time password authenticate failed",
  261. 405 => "method not allowd - maybe the password is too long",
  262. 407 => "Permission denied - make sure FHEM-Server IP won't be blocked in DSM automated blocking list",
  263. );
  264. my %SSCam_errlist = (
  265. 100 => "Unknown error",
  266. 101 => "Invalid parameters",
  267. 102 => "API does not exist",
  268. 103 => "Method does not exist",
  269. 104 => "This API version is not supported",
  270. 105 => "Insufficient user privilege",
  271. 106 => "Connection time out",
  272. 107 => "Multiple login detected",
  273. 117 => "need manager rights in SurveillanceStation for operation",
  274. 400 => "Execution failed",
  275. 401 => "Parameter invalid",
  276. 402 => "Camera disabled",
  277. 403 => "Insufficient license",
  278. 404 => "Codec activation failed",
  279. 405 => "CMS server connection failed",
  280. 407 => "CMS closed",
  281. 410 => "Service is not enabled",
  282. 412 => "Need to add license",
  283. 413 => "Reach the maximum of platform",
  284. 414 => "Some events not exist",
  285. 415 => "message connect failed",
  286. 417 => "Test Connection Error",
  287. 418 => "Object is not exist",
  288. 419 => "Visualstation name repetition",
  289. 439 => "Too many items selected",
  290. 502 => "Camera disconnected",
  291. 600 => "Presetname and PresetID not found in Hash",
  292. );
  293. # Standardvariablen
  294. my $SSCam_slim = 3; # default Anzahl der abzurufenden Schnappschüsse mit snapGallery
  295. my $SSCAM_snum = "1,2,3,4,5,6,7,8,9,10"; # mögliche Anzahl der abzurufenden Schnappschüsse mit snapGallery
  296. use vars qw($FW_ME); # webname (default is fhem), used by 97_GROUP/weblink
  297. use vars qw($FW_subdir); # Sub-path in URL, used by FLOORPLAN/weblink
  298. use vars qw($FW_room); # currently selected room
  299. use vars qw($FW_detail); # currently selected device for detail view
  300. sub SSCam_Initialize($) {
  301. my ($hash) = @_;
  302. $hash->{DefFn} = "SSCam_Define";
  303. $hash->{UndefFn} = "SSCam_Undef";
  304. $hash->{DeleteFn} = "SSCam_Delete";
  305. $hash->{SetFn} = "SSCam_Set";
  306. $hash->{GetFn} = "SSCam_Get";
  307. $hash->{AttrFn} = "SSCam_Attr";
  308. # Aufrufe aus FHEMWEB
  309. $hash->{FW_summaryFn} = "SSCam_FWsummaryFn";
  310. $hash->{FW_detailFn} = "SSCam_FWdetailFn";
  311. $hash->{FW_deviceOverview} = 1;
  312. $hash->{AttrList} =
  313. "disable:1,0 ".
  314. "genericStrmHtmlTag ".
  315. "httptimeout ".
  316. "htmlattr ".
  317. "livestreamprefix ".
  318. "loginRetries:1,2,3,4,5,6,7,8,9,10 ".
  319. "videofolderMap ".
  320. "pollcaminfoall ".
  321. "snapGalleryBoost:0,1 ".
  322. "snapGallerySize:Icon,Full ".
  323. "snapGalleryNumber:$SSCAM_snum ".
  324. "snapGalleryColumns ".
  325. "snapGalleryHtmlAttr ".
  326. "pollnologging:1,0 ".
  327. "debugactivetoken:1,0 ".
  328. "rectime ".
  329. "recextend:1,0 ".
  330. "noQuotesForSID:1,0 ".
  331. "session:SurveillanceStation,DSM ".
  332. "showPassInLog:1,0 ".
  333. "showStmInfoFull:1,0 ".
  334. "simu_SVSversion:7.2-xxxx,7.1-xxxx,8.0.0-xxxx,8.1.5-xxxx,8.2.0-xxxx ".
  335. "webCmd ".
  336. $readingFnAttributes;
  337. return undef;
  338. }
  339. ################################################################
  340. sub SSCam_Define($@) {
  341. # Die Define-Funktion eines Moduls wird von Fhem aufgerufen wenn der Define-Befehl für ein Gerät ausgeführt wird
  342. # Welche und wie viele Parameter akzeptiert werden ist Sache dieser Funktion. Die Werte werden nach dem übergebenen Hash in ein Array aufgeteilt
  343. # define CamCP1 SSCAM Carport 192.168.2.20 [5000]
  344. # ($hash) [1] [2] [3] [4]
  345. #
  346. my ($hash, $def) = @_;
  347. my $name = $hash->{NAME};
  348. return "Error: Perl module ".$SScamMMDBI." is missing. Install it on Debian with: sudo apt-get install libjson-perl" if($SScamMMDBI);
  349. my @a = split("[ \t][ \t]*", $def);
  350. if(int(@a) < 4) {
  351. return "You need to specify more parameters.\n". "Format: define <name> SSCAM <Cameraname> <ServerAddress> [Port]";
  352. }
  353. my $camname = $a[2];
  354. my $serveraddr = $a[3];
  355. my $serverport = $a[4] ? $a[4] : 5000;
  356. my $proto = $a[5] ? lc($a[5]) : "http";
  357. $hash->{SERVERADDR} = $serveraddr;
  358. $hash->{SERVERPORT} = $serverport;
  359. $hash->{CAMNAME} = $camname;
  360. $hash->{VERSION} = $SSCamVersion;
  361. $hash->{MODEL} = ($camname =~ m/^SVS$/i)?"SVS":"CAM"; # initial, CAM wird später ersetzt durch CamModel
  362. $hash->{PROTOCOL} = $proto;
  363. $hash->{COMPATIBILITY} = $compstat; # getestete SVS-version Kompatibilität
  364. # benötigte API's in $hash einfügen
  365. $hash->{HELPER}{APIINFO} = "SYNO.API.Info"; # Info-Seite für alle API's, einzige statische Seite !
  366. $hash->{HELPER}{APIAUTH} = "SYNO.API.Auth"; # API used to perform session login and logout
  367. $hash->{HELPER}{APISVSINFO} = "SYNO.SurveillanceStation.Info";
  368. $hash->{HELPER}{APIEVENT} = "SYNO.SurveillanceStation.Event";
  369. $hash->{HELPER}{APIEXTREC} = "SYNO.SurveillanceStation.ExternalRecording";
  370. $hash->{HELPER}{APIEXTEVT} = "SYNO.SurveillanceStation.ExternalEvent";
  371. $hash->{HELPER}{APICAM} = "SYNO.SurveillanceStation.Camera"; # stark geändert ab API v2.8
  372. $hash->{HELPER}{APISNAPSHOT} = "SYNO.SurveillanceStation.SnapShot";
  373. $hash->{HELPER}{APIPTZ} = "SYNO.SurveillanceStation.PTZ";
  374. $hash->{HELPER}{APIPRESET} = "SYNO.SurveillanceStation.PTZ.Preset";
  375. $hash->{HELPER}{APICAMEVENT} = "SYNO.SurveillanceStation.Camera.Event";
  376. $hash->{HELPER}{APIVIDEOSTM} = "SYNO.SurveillanceStation.VideoStreaming"; # verwendet in Response von "SYNO.SurveillanceStation.Camera: GetLiveViewPath" -> StreamKey-Methode
  377. # $hash->{HELPER}{APISTM} = "SYNO.SurveillanceStation.Streaming"; # provides methods to get Live View or Event video stream, removed in API v2.8
  378. $hash->{HELPER}{APISTM} = "SYNO.SurveillanceStation.Stream"; # Beschreibung ist falsch und entspricht "SYNO.SurveillanceStation.Streaming" auch noch ab v2.8
  379. $hash->{HELPER}{APIHM} = "SYNO.SurveillanceStation.HomeMode";
  380. $hash->{HELPER}{APILOG} = "SYNO.SurveillanceStation.Log";
  381. $hash->{HELPER}{APIAUDIOSTM} = "SYNO.SurveillanceStation.AudioStream"; # Audiostream mit SID, removed in API v2.8
  382. $hash->{HELPER}{APIVIDEOSTMS} = "SYNO.SurveillanceStation.VideoStream"; # Videostream mit SID, removed in API v2.8
  383. # Startwerte setzen
  384. if(SSCam_IsModelCam($hash)) {
  385. $attr{$name}{webCmd} = "on:off:snap:enable:disable:runView:stopView"; # initiale Webkommandos setzen
  386. } else {
  387. $attr{$name}{webCmd} = "homeMode";
  388. $attr{$name}{webCmdLabel} = "HomeMode";
  389. }
  390. $hash->{HELPER}{ACTIVE} = "off"; # Funktionstoken "off", Funktionen können sofort starten
  391. $hash->{HELPER}{OLDVALPOLLNOLOGGING} = "0"; # Loggingfunktion für Polling ist an
  392. $hash->{HELPER}{OLDVALPOLL} = "0";
  393. $hash->{HELPER}{RECTIME_DEF} = "15"; # Standard für rectime setzen, überschreibbar durch Attribut "rectime" bzw. beim "set .. on-for-time"
  394. $hash->{HELPER}{OLDPTZHOME} = "";
  395. $hash->{".ptzhtml"} = "";
  396. $hash->{HELPER}{HLSSTREAM} = "inactive"; # Aktivitätsstatus HLS-Streaming
  397. $hash->{HELPER}{SNAPLIMIT} = 0; # abgerufene Anzahl Snaps
  398. $hash->{HELPER}{TOTALCNT} = 0; # totale Anzahl Snaps
  399. readingsBeginUpdate($hash);
  400. readingsBulkUpdate($hash,"PollState","Inactive"); # es ist keine Gerätepolling aktiv
  401. if(SSCam_IsModelCam($hash)) {
  402. readingsBulkUpdate($hash,"Availability", "???"); # Verfügbarkeit ist unbekannt
  403. readingsBulkUpdate($hash,"state", "off"); # Init für "state" , Problemlösung für setstate, Forum #308
  404. } else {
  405. readingsBulkUpdate($hash,"state", "Initialized"); # Init für "state" wenn SVS
  406. }
  407. readingsEndUpdate($hash,1);
  408. SSCam_getcredentials($hash,1); # Credentials lesen und in RAM laden ($boot=1)
  409. # initiale Routinen nach Restart ausführen , verzögerter zufälliger Start
  410. RemoveInternalTimer($hash, "SSCam_initonboot");
  411. InternalTimer(gettimeofday()+int(rand(30)), "SSCam_initonboot", $hash, 0);
  412. return undef;
  413. }
  414. ################################################################
  415. sub SSCam_Undef($$) {
  416. my ($hash, $arg) = @_;
  417. SSCam_logout($hash);
  418. RemoveInternalTimer($hash);
  419. return undef;
  420. }
  421. ################################################################
  422. sub SSCam_Delete($$) {
  423. my ($hash, $arg) = @_;
  424. my $index = $hash->{TYPE}."_".$hash->{NAME}."_credentials";
  425. my $name = $hash->{NAME};
  426. # gespeicherte Credentials löschen
  427. setKeyValue($index, undef);
  428. # löschen snapGallerie-Device falls vorhanden
  429. my $sgdev = "SSCam.$hash->{NAME}.snapgallery";
  430. CommandDelete($hash->{CL},"$sgdev");
  431. # alle Streaming-Devices löschen falls vorhanden
  432. CommandDelete($hash->{CL},"TYPE=SSCamSTRM:FILTER=PARENT=$name");
  433. return undef;
  434. }
  435. ################################################################
  436. sub SSCam_Attr($$$$) {
  437. my ($cmd,$name,$aName,$aVal) = @_;
  438. my $hash = $defs{$name};
  439. my ($do,$val);
  440. # $cmd can be "del" or "set"
  441. # $name is device name
  442. # aName and aVal are Attribute name and value
  443. # dynamisch PTZ-Attribute setzen (wichtig beim Start wenn Reading "DeviceType" nicht gesetzt ist)
  444. if ($cmd eq "set" && ($aName =~ m/ptzPanel_.*/)) {
  445. foreach my $n (0..9) {
  446. $n = sprintf("%2.2d",$n);
  447. addToDevAttrList($name, "ptzPanel_row$n");
  448. }
  449. addToDevAttrList($name, "ptzPanel_iconPrefix");
  450. addToDevAttrList($name, "ptzPanel_iconPath");
  451. }
  452. if($aName =~ m/ptzPanel_row.*|ptzPanel_Home|ptzPanel_use/) {
  453. InternalTimer(gettimeofday()+0.7, "SSCam_addptzattr", "$name", 0);
  454. }
  455. if ($aName eq "disable") {
  456. if($cmd eq "set") {
  457. $do = ($aVal) ? 1 : 0;
  458. }
  459. $do = 0 if($cmd eq "del");
  460. if(SSCam_IsModelCam($hash)) {
  461. $val = ($do == 1 ? "inactive" : "off");
  462. } else {
  463. $val = ($do == 1 ? "disabled" : "initialized");
  464. }
  465. readingsSingleUpdate($hash, "state", $val, 1);
  466. readingsSingleUpdate($hash, "PollState", "Inactive", 1) if($do == 1);
  467. readingsSingleUpdate($hash, "Availability", "???", 1) if($do == 1 && SSCam_IsModelCam($hash));
  468. }
  469. if ($aName eq "showStmInfoFull") {
  470. if($cmd eq "set") {
  471. $do = ($aVal) ? 1 : 0;
  472. }
  473. $do = 0 if($cmd eq "del");
  474. if ($do == 0) {
  475. delete($defs{$name}{READINGS}{StmKeymjpegHttp});
  476. delete($defs{$name}{READINGS}{LiveStreamUrl});
  477. delete($defs{$name}{READINGS}{StmKeyUnicst});
  478. delete($defs{$name}{READINGS}{StmKeyUnicstOverHttp});
  479. delete($defs{$name}{READINGS}{StmKeymxpegHttp});
  480. }
  481. }
  482. if ($aName eq "snapGallerySize") {
  483. if($cmd eq "set") {
  484. $do = ($aVal eq "Icon")?1:2;
  485. }
  486. $do = 0 if($cmd eq "del");
  487. if ($do == 0) {
  488. delete($hash->{HELPER}{".SNAPHASH"}) if(AttrVal($name,"snapGalleryBoost",0)); # Snaphash nur löschen wenn Snaps gepollt werden
  489. Log3($name, 4, "$name - Snapshot hash deleted");
  490. } elsif (AttrVal($name,"snapGalleryBoost",0)) {
  491. # snap-Infos abhängig ermitteln wenn gepollt werden soll
  492. my ($slim,$ssize);
  493. $hash->{HELPER}{GETSNAPGALLERY} = 1;
  494. $slim = AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snaps
  495. $ssize = $do;
  496. RemoveInternalTimer("SSCam_getsnapinfo");
  497. InternalTimer(gettimeofday()+0.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  498. }
  499. }
  500. if ($aName eq "snapGalleryBoost") {
  501. if($cmd eq "set") {
  502. $do = ($aVal == 1)?1:0;
  503. }
  504. $do = 0 if($cmd eq "del");
  505. if ($do == 0) {
  506. delete($hash->{HELPER}{".SNAPHASH"}); # Snaphash löschen
  507. Log3($name, 4, "$name - Snapshot hash deleted");
  508. } else {
  509. # snapgallery regelmäßig neu einlesen wenn Polling ein
  510. return "When you want activate \"snapGalleryBoost\", you have to set the attribute \"pollcaminfoall\" first because the functionality depends on retrieving snapshots periodical."
  511. if(!AttrVal($name,"pollcaminfoall",0));
  512. my ($slim,$ssize);
  513. $hash->{HELPER}{GETSNAPGALLERY} = 1;
  514. $slim = AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snaps
  515. my $sg = AttrVal($name,"snapGallerySize","Icon"); # Auflösung Image
  516. $ssize = ($sg eq "Icon")?1:2;
  517. RemoveInternalTimer("SSCam_getsnapinfo");
  518. InternalTimer(gettimeofday()+0.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  519. }
  520. }
  521. if ($aName eq "snapGalleryNumber" && AttrVal($name,"snapGalleryBoost",0)) {
  522. my ($slim,$ssize);
  523. if($cmd eq "set") {
  524. $do = ($aVal != 0)?1:0;
  525. }
  526. $do = 0 if($cmd eq "del");
  527. if ($do == 0) {
  528. $slim = 3;
  529. } else {
  530. $slim = $aVal;
  531. }
  532. $hash->{HELPER}{GETSNAPGALLERY} = 1;
  533. my $sg = AttrVal($name,"snapGallerySize","Icon"); # Auflösung Image
  534. $ssize = ($sg eq "Icon")?1:2;
  535. RemoveInternalTimer("SSCam_getsnapinfo");
  536. InternalTimer(gettimeofday()+0.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  537. }
  538. if ($aName eq "simu_SVSversion") {
  539. delete $hash->{HELPER}{APIPARSET};
  540. delete $hash->{HELPER}{SID};
  541. delete $hash->{CAMID};
  542. RemoveInternalTimer($hash, "SSCam_getcaminfoall");
  543. InternalTimer(gettimeofday()+0.5, "SSCam_getcaminfoall", $hash, 0);
  544. }
  545. if($aName =~ m/pollcaminfoall/ && $init_done == 1) {
  546. RemoveInternalTimer($hash, "SSCam_getcaminfoall");
  547. InternalTimer(gettimeofday()+1.0, "SSCam_getcaminfoall", $hash, 0);
  548. RemoveInternalTimer($hash, "SSCam_wdpollcaminfo");
  549. InternalTimer(gettimeofday()+1.5, "SSCam_wdpollcaminfo", $hash, 0);
  550. }
  551. if($aName =~ m/pollnologging/ && $init_done == 1) {
  552. RemoveInternalTimer($hash, "SSCam_wdpollcaminfo");
  553. InternalTimer(gettimeofday()+1.0, "SSCam_wdpollcaminfo", $hash, 0);
  554. }
  555. if ($cmd eq "set") {
  556. if ($aName =~ m/httptimeout|snapGalleryColumns|rectime|pollcaminfoall/) {
  557. unless ($aVal =~ /^\d+$/) { return " The Value for $aName is not valid. Use only figures 1-9 !";}
  558. }
  559. if($aName =~ m/pollcaminfoall/) {
  560. return "The value of \"$aName\" has to be greater than 10 seconds." if($aVal <= 10);
  561. }
  562. }
  563. if ($cmd eq "del") {
  564. if ($aName =~ m/pollcaminfoall/ ) {
  565. # Polling nicht ausschalten wenn snapGalleryBoost ein (regelmäßig neu einlesen)
  566. return "Please switch off \"snapGalleryBoost\" first if you want to deactivate \"pollcaminfoall\" because the functionality of \"snapGalleryBoost\" depends on retrieving snapshots periodical."
  567. if(AttrVal($name,"snapGalleryBoost",0));
  568. }
  569. }
  570. return undef;
  571. }
  572. ################################################################
  573. sub SSCam_Set($@) {
  574. my ($hash, @a) = @_;
  575. return "\"set X\" needs at least an argument" if ( @a < 2 );
  576. my $name = $a[0];
  577. my $opt = $a[1];
  578. my $prop = $a[2];
  579. my $prop1 = $a[3];
  580. my $prop2 = $a[4];
  581. my $prop3 = $a[5];
  582. my $camname = $hash->{CAMNAME};
  583. my $success;
  584. my $setlist;
  585. my @prop;
  586. return if(IsDisabled($name));
  587. if(!$hash->{CREDENTIALS}) {
  588. # initiale setlist für neue Devices
  589. $setlist = "Unknown argument $opt, choose one of ".
  590. "credentials "
  591. ;
  592. } elsif(SSCam_IsModelCam($hash)) {
  593. # selist für Cams
  594. my $hlslfw = SSCam_IsHLSCap($hash)?",live_fw_hls,":",";
  595. $setlist = "Unknown argument $opt, choose one of ".
  596. "credentials ".
  597. ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "delPreset:".ReadingsVal("$name","Presets","")." " : "").
  598. "expmode:auto,day,night ".
  599. "on ".
  600. "off:noArg ".
  601. "motdetsc:disable,camera,SVS ".
  602. "snap:noArg ".
  603. (AttrVal($name, "snapGalleryBoost",0)?(AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ":" ").
  604. "createSnapGallery:noArg ".
  605. "createStreamDev:generic,mjpeg,switched ".
  606. ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "createPTZcontrol:noArg ": "").
  607. "enable:noArg ".
  608. "disable:noArg ".
  609. "optimizeParams ".
  610. ((ReadingsVal("$name", "CapPIR", "false") ne "false") ? "pirSensor:activate,deactivate ": "").
  611. "runView:live_fw".$hlslfw."live_link,live_open,lastrec_fw,lastrec_fw_MJPEG,lastrec_fw_MPEG4/H.264,lastrec_open,lastsnap_fw ".
  612. ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "setPreset ": "").
  613. ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "setHome:---currentPosition---,".ReadingsVal("$name","Presets","")." " : "").
  614. "stopView:noArg ".
  615. ((ReadingsVal("$name", "CapPTZObjTracking", "false") ne "false") ? "startTracking:noArg " : "").
  616. ((ReadingsVal("$name", "CapPTZObjTracking", "false") ne "false") ? "stopTracking:noArg " : "").
  617. ((ReadingsVal("$name", "CapPTZDirections", 0) > 0) ? "move"." " : "").
  618. ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "runPatrol:".ReadingsVal("$name", "Patrols", "")." " : "").
  619. ((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "goPreset:".ReadingsVal("$name", "Presets", "")." " : "").
  620. ((ReadingsVal("$name", "CapPTZAbs", "false") ne "false") ? "goAbsPTZ"." " : "").
  621. ((ReadingsVal("$name", "CapPTZDirections", 0) > 0) ? "move"." " : "");
  622. } else {
  623. # setlist für SVS Devices
  624. $setlist = "Unknown argument $opt, choose one of ".
  625. "credentials ".
  626. "extevent:1,2,3,4,5,6,7,8,9,10 ".
  627. ($hash->{HELPER}{APIHMMAXVER}?"homeMode:on,off ": "");
  628. }
  629. if ($opt eq "credentials") {
  630. return "Credentials are incomplete, use username password" if (!$prop || !$prop1);
  631. return "Password is too long. It is limited up to and including 20 characters." if (length $prop1 > 20);
  632. delete $hash->{HELPER}{SID} if($hash->{HELPER}{SID});
  633. ($success) = SSCam_setcredentials($hash,$prop,$prop1);
  634. $hash->{HELPER}{ACTIVE} = "off";
  635. if($success) {
  636. SSCam_getcaminfoall($hash,0);
  637. RemoveInternalTimer($hash, "SSCam_getptzlistpreset");
  638. InternalTimer(gettimeofday()+11, "SSCam_getptzlistpreset", $hash, 0);
  639. RemoveInternalTimer($hash, "SSCam_getptzlistpatrol");
  640. InternalTimer(gettimeofday()+12, "SSCam_getptzlistpatrol", $hash, 0);
  641. return "Username and Password saved successfully";
  642. } else {
  643. return "Error while saving Username / Password - see logfile for details";
  644. }
  645. }
  646. if ($opt eq "on" && SSCam_IsModelCam($hash)) {
  647. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  648. if (defined($prop)) {
  649. unless ($prop =~ /^\d+$/) { return " The Value for \"$opt\" is not valid. Use only figures 0-9 without decimal places !";}
  650. $hash->{HELPER}{RECTIME_TEMP} = $prop;
  651. }
  652. SSCam_camstartrec($hash);
  653. } elsif ($opt eq "off" && SSCam_IsModelCam($hash)) {
  654. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  655. SSCam_camstoprec($hash);
  656. } elsif ($opt eq "snap" && SSCam_IsModelCam($hash)) {
  657. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  658. $hash->{HELPER}{SNAPBYSTRMDEV} = 1 if ($prop); # $prop wird mitgegeben durch Snap by SSCamSTRM-Device
  659. SSCam_camsnap($hash);
  660. } elsif ($opt eq "startTracking" && SSCam_IsModelCam($hash)) {
  661. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  662. if ($hash->{HELPER}{APIPTZMAXVER} < 5) {return "Function \"$opt\" needs a higher version of Surveillance Station";}
  663. SSCam_starttrack($hash);
  664. } elsif ($opt eq "stopTracking" && SSCam_IsModelCam($hash)) {
  665. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  666. if ($hash->{HELPER}{APIPTZMAXVER} < 5) {return "Function \"$opt\" needs a higher version of Surveillance Station";}
  667. SSCam_stoptrack($hash);
  668. } elsif ($opt eq "snapGallery" && SSCam_IsModelCam($hash)) {
  669. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  670. my $ret = SSCam_getclhash($hash);
  671. return $ret if($ret);
  672. if(!AttrVal($name, "snapGalleryBoost",0)) {
  673. # Snaphash ist nicht vorhanden und wird neu abgerufen und ausgegeben
  674. $hash->{HELPER}{GETSNAPGALLERY} = 1;
  675. # snap-Infos für Gallerie abrufen
  676. my ($sg,$slim,$ssize);
  677. $slim = $prop?AttrVal($name,"snapGalleryNumber",$prop):AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snapshots
  678. $ssize = (AttrVal($name,"snapGallerySize","Icon") eq "Icon")?1:2; # Image Size 1-Icon, 2-Full
  679. SSCam_getsnapinfo("$name:$slim:$ssize");
  680. } else {
  681. # Snaphash ist vorhanden und wird zur Ausgabe aufbereitet (Polling ist aktiv)
  682. my $htmlCode = SSCam_composegallery($name);
  683. for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
  684. if ($hash->{HELPER}{CL}{$k}->{COMP}) {
  685. # CL zusammengestellt (Auslösung durch Notify)
  686. asyncOutput($hash->{HELPER}{CL}{$k}, "$htmlCode");
  687. } else {
  688. # Output wurde über FHEMWEB ausgelöst
  689. return $htmlCode;
  690. }
  691. }
  692. delete($hash->{HELPER}{CL});
  693. }
  694. } elsif ($opt eq "createSnapGallery" && SSCam_IsModelCam($hash)) {
  695. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  696. my ($ret,$sgdev);
  697. return "Before use \"$opt\" you have to set the attribute \"snapGalleryBoost\" first due to the technology of retrieving snapshots automatically is needed."
  698. if(!AttrVal($name,"snapGalleryBoost",0));
  699. $sgdev = "SSCamSTRM.$name.snapgallery";
  700. $ret = CommandDefine($hash->{CL},"$sgdev SSCamSTRM {SSCam_composegallery('$name','$sgdev','snapgallery')}");
  701. return $ret if($ret);
  702. my $room = "SnapGallery";
  703. $attr{$sgdev}{room} = $room;
  704. return "Snapgallery device \"$sgdev\" created and assigned to room \"$room\".";
  705. } elsif ($opt eq "createPTZcontrol" && SSCam_IsModelCam($hash)) {
  706. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  707. my $ptzcdev = "SSCamSTRM.$name.PTZcontrol";
  708. my $ret = CommandDefine($hash->{CL},"$ptzcdev SSCamSTRM {SSCam_ptzpanel('$name','$ptzcdev','ptzcontrol')}");
  709. return $ret if($ret);
  710. my $room = AttrVal($name,"room","PTZcontrol");
  711. $attr{$ptzcdev}{room} = $room;
  712. $attr{$ptzcdev}{group} = $name."_PTZcontrol";
  713. return "PTZ control device \"$ptzcdev\" created and assigned to room \"$room\".";
  714. } elsif ($opt eq "createStreamDev" && SSCam_IsModelCam($hash)) {
  715. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  716. my ($livedev,$ret);
  717. if($prop =~ /mjpeg/) {
  718. $livedev = "SSCamSTRM.$name.mjpeg";
  719. $ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','mjpeg')}");
  720. return $ret if($ret);
  721. }
  722. if($prop =~ /generic/) {
  723. $livedev = "SSCamSTRM.$name.generic";
  724. $ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','generic')}");
  725. return $ret if($ret);
  726. }
  727. if($prop =~ /switched/) {
  728. $livedev = "SSCamSTRM.$name.switched";
  729. $ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','switched')}");
  730. return $ret if($ret);
  731. }
  732. my $room = AttrVal($name,"room","Livestream");
  733. $attr{$livedev}{room} = $room;
  734. return "Livestream device \"$livedev\" created and assigned to room \"$room\".";
  735. } elsif ($opt eq "enable" && SSCam_IsModelCam($hash)) {
  736. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  737. SSCam_camenable($hash);
  738. } elsif ($opt eq "disable" && SSCam_IsModelCam($hash)) {
  739. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  740. SSCam_camdisable($hash);
  741. } elsif ($opt eq "motdetsc" && SSCam_IsModelCam($hash)) {
  742. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  743. if (!$prop || $prop !~ /^(disable|camera|SVS)$/) { return " \"$opt\" needs one of those arguments: disable, camera, SVS !";}
  744. $hash->{HELPER}{MOTDETSC} = $prop;
  745. if ($prop1) {
  746. # check ob Zahl zwischen 1 und 99
  747. return "invalid value for sensitivity (SVS or camera) - use number between 1 - 99" if ($prop1 !~ /^([1-9]|[1-9][0-9])*$/);
  748. $hash->{HELPER}{MOTDETSC_PROP1} = $prop1;
  749. }
  750. if ($prop2) {
  751. # check ob Zahl zwischen 1 und 99
  752. return "invalid value for threshold (SVS) / object size (camera) - use number between 1 - 99" if ($prop2 !~ /^([1-9]|[1-9][0-9])*$/);
  753. $hash->{HELPER}{MOTDETSC_PROP2} = $prop2;
  754. }
  755. if ($prop3) {
  756. # check ob Zahl zwischen 1 und 99
  757. return "invalid value for threshold (SVS) / object size (camera) - use number between 1 - 99" if ($prop3 !~ /^([1-9]|[1-9][0-9])*$/);
  758. $hash->{HELPER}{MOTDETSC_PROP3} = $prop3;
  759. }
  760. SSCam_cammotdetsc($hash);
  761. } elsif ($opt eq "expmode" && SSCam_IsModelCam($hash)) {
  762. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  763. unless ($prop) { return " \"$opt\" needs one of those arguments: auto, day, night !";}
  764. $hash->{HELPER}{EXPMODE} = $prop;
  765. SSCam_camexpmode($hash);
  766. } elsif ($opt eq "homeMode" && !SSCam_IsModelCam($hash)) {
  767. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  768. unless ($prop) { return " \"$opt\" needs one of those arguments: on, off !";}
  769. $hash->{HELPER}{HOMEMODE} = $prop;
  770. SSCam_sethomemode($hash);
  771. } elsif ($opt eq "goPreset" && SSCam_IsModelCam($hash)) {
  772. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  773. if (!$prop) {return "Function \"goPreset\" needs a \"Presetname\" as an argument";}
  774. $hash->{HELPER}{GOPRESETNAME} = $prop;
  775. $hash->{HELPER}{PTZACTION} = "gopreset";
  776. SSCam_doptzaction($hash);
  777. } elsif ($opt eq "optimizeParams" && SSCam_IsModelCam($hash)) {
  778. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  779. my %cpcl = (ntp => 1, mirror => 2, flip => 4, rotate => 8);
  780. SSCam_extoptpar($hash,$prop,\%cpcl) if($prop);
  781. SSCam_extoptpar($hash,$prop1,\%cpcl) if($prop1);
  782. SSCam_extoptpar($hash,$prop2,\%cpcl) if($prop2);
  783. SSCam_setoptpar($hash);
  784. } elsif ($opt eq "pirSensor" && SSCam_IsModelCam($hash)) {
  785. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  786. if(ReadingsVal("$name", "CapPIR", "false") eq "false") {return "Function \"$opt\" not possible. Camera \"$name\" don't have a PIR sensor."}
  787. if(!$prop) {return "Function \"$opt\" needs an argument";}
  788. $hash->{HELPER}{PIRACT} = ($prop eq "activate")?0:($prop eq "deactivate")?-1:5;
  789. if($hash->{HELPER}{PIRACT} == 5) {return " Illegal argument for \"$opt\" detected, use \"activate\" or \"activate\" !";}
  790. SSCam_piract($hash);
  791. } elsif ($opt eq "runPatrol" && SSCam_IsModelCam($hash)) {
  792. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  793. if (!$prop) {return "Function \"$opt\" needs a \"Patrolname\" as an argument";}
  794. $hash->{HELPER}{GOPATROLNAME} = $prop;
  795. $hash->{HELPER}{PTZACTION} = "runpatrol";
  796. SSCam_doptzaction($hash);
  797. } elsif ($opt eq "goAbsPTZ" && SSCam_IsModelCam($hash)) {
  798. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  799. if ($prop eq "up" || $prop eq "down" || $prop eq "left" || $prop eq "right") {
  800. if ($prop eq "up") {$hash->{HELPER}{GOPTZPOSX} = 320; $hash->{HELPER}{GOPTZPOSY} = 480;}
  801. if ($prop eq "down") {$hash->{HELPER}{GOPTZPOSX} = 320; $hash->{HELPER}{GOPTZPOSY} = 0;}
  802. if ($prop eq "left") {$hash->{HELPER}{GOPTZPOSX} = 0; $hash->{HELPER}{GOPTZPOSY} = 240;}
  803. if ($prop eq "right") {$hash->{HELPER}{GOPTZPOSX} = 640; $hash->{HELPER}{GOPTZPOSY} = 240;}
  804. $hash->{HELPER}{PTZACTION} = "goabsptz";
  805. SSCam_doptzaction($hash);
  806. return undef;
  807. } else {
  808. if ($prop !~ /\d+/ || $prop1 !~ /\d+/ || abs($prop) > 640 || abs($prop1) > 480) {
  809. return "Function \"goAbsPTZ\" needs two coordinates, posX=0-640 and posY=0-480, as arguments or use up, down, left, right instead";
  810. }
  811. $hash->{HELPER}{GOPTZPOSX} = abs($prop);
  812. $hash->{HELPER}{GOPTZPOSY} = abs($prop1);
  813. $hash->{HELPER}{PTZACTION} = "goabsptz";
  814. SSCam_doptzaction($hash);
  815. return undef;
  816. }
  817. return "Function \"goAbsPTZ\" needs two coordinates, posX=0-640 and posY=0-480, as arguments or use up, down, left, right instead";
  818. } elsif ($opt eq "move" && SSCam_IsModelCam($hash)) {
  819. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  820. return "PTZ version of Synology API isn't set. Use \"get $name scanVirgin\" first." if(!$hash->{HELPER}{APIPTZMAXVER});
  821. if($hash->{HELPER}{APIPTZMAXVER} <= 4) {
  822. if (!defined($prop) || ($prop !~ /^up$|^down$|^left$|^right$|^dir_\d$/)) {return "Function \"move\" needs an argument like up, down, left, right or dir_X (X = 0 to CapPTZDirections-1)";}
  823. $hash->{HELPER}{GOMOVEDIR} = $prop;
  824. } elsif ($hash->{HELPER}{APIPTZMAXVER} >= 5) {
  825. if (!defined($prop) || ($prop !~ /^right$|^upright$|^up$|^upleft$|^left$|^downleft$|^down$|^downright$/)) {return "Function \"move\" needs an argument like right, upright, up, upleft, left, downleft, down, downright ";}
  826. my %dirs = (
  827. right => 0,
  828. upright => 4,
  829. up => 8,
  830. upleft => 12,
  831. left => 16,
  832. downleft => 20,
  833. down => 24,
  834. downright => 28,
  835. );
  836. $hash->{HELPER}{GOMOVEDIR} = $dirs{$prop};
  837. }
  838. $hash->{HELPER}{GOMOVETIME} = defined($prop1) ? $prop1 : 1;
  839. $hash->{HELPER}{PTZACTION} = "movestart";
  840. SSCam_doptzaction($hash);
  841. } elsif ($opt eq "runView" && SSCam_IsModelCam($hash)) {
  842. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  843. if ($prop eq "live_open") {
  844. if ($prop1) {$hash->{HELPER}{VIEWOPENROOM} = $prop1;} else {delete $hash->{HELPER}{VIEWOPENROOM};}
  845. $hash->{HELPER}{OPENWINDOW} = 1;
  846. $hash->{HELPER}{WLTYPE} = "link";
  847. $hash->{HELPER}{ALIAS} = "LiveView";
  848. $hash->{HELPER}{RUNVIEW} = "live_open";
  849. $hash->{HELPER}{ACTSTRM} = ""; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  850. } elsif ($prop eq "live_link") {
  851. $hash->{HELPER}{OPENWINDOW} = 0;
  852. $hash->{HELPER}{WLTYPE} = "link";
  853. $hash->{HELPER}{ALIAS} = "LiveView";
  854. $hash->{HELPER}{RUNVIEW} = "live_link";
  855. $hash->{HELPER}{ACTSTRM} = ""; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  856. } elsif ($prop eq "lastrec_open") {
  857. if ($prop1) {$hash->{HELPER}{VIEWOPENROOM} = $prop1;} else {delete $hash->{HELPER}{VIEWOPENROOM};}
  858. $hash->{HELPER}{OPENWINDOW} = 1;
  859. $hash->{HELPER}{WLTYPE} = "link";
  860. $hash->{HELPER}{ALIAS} = "LastRecording";
  861. $hash->{HELPER}{RUNVIEW} = "lastrec_open";
  862. $hash->{HELPER}{ACTSTRM} = ""; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  863. } elsif ($prop eq "lastrec_fw") { # Video in iFrame eingebettet
  864. $hash->{HELPER}{OPENWINDOW} = 0;
  865. $hash->{HELPER}{WLTYPE} = "iframe";
  866. $hash->{HELPER}{ALIAS} = " ";
  867. $hash->{HELPER}{RUNVIEW} = "lastrec";
  868. $hash->{HELPER}{ACTSTRM} = "last Recording"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  869. } elsif ($prop eq "lastrec_fw_MJPEG") { # “video/avi” – MJPEG format event
  870. $hash->{HELPER}{OPENWINDOW} = 0;
  871. $hash->{HELPER}{WLTYPE} = "image";
  872. $hash->{HELPER}{ALIAS} = " ";
  873. $hash->{HELPER}{RUNVIEW} = "lastrec";
  874. $hash->{HELPER}{ACTSTRM} = "last Recording"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  875. } elsif ($prop eq "lastrec_fw_MPEG4/H.264") { # “video/mp4” – MPEG4/H.264 format event
  876. $hash->{HELPER}{OPENWINDOW} = 0;
  877. $hash->{HELPER}{WLTYPE} = "video";
  878. $hash->{HELPER}{ALIAS} = " ";
  879. $hash->{HELPER}{RUNVIEW} = "lastrec";
  880. $hash->{HELPER}{ACTSTRM} = "last Recording"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  881. } elsif ($prop eq "live_fw") {
  882. $hash->{HELPER}{OPENWINDOW} = 0;
  883. $hash->{HELPER}{WLTYPE} = "image";
  884. $hash->{HELPER}{ALIAS} = " ";
  885. $hash->{HELPER}{RUNVIEW} = "live_fw";
  886. $hash->{HELPER}{ACTSTRM} = "MJPEG Livestream"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  887. } elsif ($prop eq "live_fw_hls") {
  888. return "API \"SYNO.SurveillanceStation.VideoStream\" is not available or Reading \"CamStreamFormat\" is not \"HLS\". May be your API version is 2.8 or higher." if(!SSCam_IsHLSCap($hash));
  889. $hash->{HELPER}{OPENWINDOW} = 0;
  890. $hash->{HELPER}{WLTYPE} = "hls";
  891. $hash->{HELPER}{ALIAS} = "View only on compatible browsers";
  892. $hash->{HELPER}{RUNVIEW} = "live_fw_hls";
  893. $hash->{HELPER}{ACTSTRM} = "HLS Livestream"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  894. } elsif ($prop eq "lastsnap_fw") {
  895. $hash->{HELPER}{LSNAPBYSTRMDEV} = 1 if($prop1); # Anzeige durch SSCamSTRM-Device ausgelöst
  896. $hash->{HELPER}{LSNAPBYDEV} = 1 if(!$prop1); # Anzeige durch SSCam ausgelöst
  897. $hash->{HELPER}{OPENWINDOW} = 0;
  898. $hash->{HELPER}{WLTYPE} = "base64img";
  899. $hash->{HELPER}{ALIAS} = " ";
  900. $hash->{HELPER}{RUNVIEW} = "lastsnap_fw";
  901. $hash->{HELPER}{ACTSTRM} = "last Snapshot"; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  902. } else {
  903. return "$prop isn't a valid option of runview, use one of live_fw, live_link, live_open, lastrec_fw, lastrec_open, lastsnap_fw";
  904. }
  905. SSCam_runliveview($hash);
  906. } elsif ($opt eq "hlsreactivate" && SSCam_IsModelCam($hash)) {
  907. # ohne SET-Menüeintrag
  908. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  909. SSCam_hlsreactivate($hash);
  910. } elsif ($opt eq "hlsactivate" && SSCam_IsModelCam($hash)) {
  911. # ohne SET-Menüeintrag
  912. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  913. SSCam_hlsactivate($hash);
  914. } elsif ($opt eq "refresh" && SSCam_IsModelCam($hash)) {
  915. # ohne SET-Menüeintrag
  916. if($prop =~ /STRM/) {
  917. # Event in allen SSCamSTRM-Devices erzeugen um Contentwiedergabe aufzufrischen
  918. SSCam_refresh($hash,0,0,1); # kein Room-Refresh, kein SSCam-state-Event, SSCamSTRM-Event
  919. }
  920. } elsif ($opt eq "extevent" && !SSCam_IsModelCam($hash)) {
  921. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  922. $hash->{HELPER}{EVENTID} = $prop;
  923. SSCam_extevent($hash);
  924. } elsif ($opt eq "stopView" && SSCam_IsModelCam($hash)) {
  925. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  926. SSCam_stopliveview($hash);
  927. } elsif ($opt eq "setPreset" && SSCam_IsModelCam($hash)) {
  928. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  929. if (!$prop) {return "Syntax of function \"$opt\" was wrong. Please use \"set $name setPreset <PresetNumber> <PresetName> [<Speed>]\" ";}
  930. $hash->{HELPER}{PNUMBER} = $prop;
  931. $hash->{HELPER}{PNAME} = $prop1?$prop1:$prop; # wenn keine Presetname angegeben -> Presetnummer als Name verwenden
  932. $hash->{HELPER}{PSPEED} = $prop2 if($prop2);
  933. SSCam_setPreset($hash);
  934. } elsif ($opt eq "setHome" && SSCam_IsModelCam($hash)) {
  935. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  936. if (!$prop) {return "Function \"$opt\" needs a \"Presetname\" as argument";}
  937. $hash->{HELPER}{SETHOME} = $prop;
  938. SSCam_setHome($hash);
  939. } elsif ($opt eq "delPreset" && SSCam_IsModelCam($hash)) {
  940. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  941. if (!$prop) {return "Function \"$opt\" needs a \"Presetname\" as argument";}
  942. $hash->{HELPER}{DELPRESETNAME} = $prop;
  943. SSCam_delPreset($hash);
  944. } else {
  945. return "$setlist";
  946. }
  947. return;
  948. }
  949. ################################################################
  950. sub SSCam_Get($@) {
  951. my ($hash, @a) = @_;
  952. return "\"get X\" needs at least an argument" if ( @a < 2 );
  953. my $name = shift @a;
  954. my $opt = shift @a;
  955. my $arg = shift @a;
  956. my $arg1 = shift @a;
  957. my $arg2 = shift @a;
  958. my $ret = "";
  959. my $getlist;
  960. if(!$hash->{CREDENTIALS}) {
  961. return;
  962. } elsif(SSCam_IsModelCam($hash)) {
  963. # getlist für Cams
  964. $getlist = "Unknown argument $opt, choose one of ".
  965. "caminfoall:noArg ".
  966. "caminfo:noArg ".
  967. ((AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))
  968. ?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ").
  969. ((ReadingsVal("$name", "CapPTZPresetNumber", 0) != 0) ? "listPresets:noArg " : "").
  970. "snapinfo:noArg ".
  971. "svsinfo:noArg ".
  972. "snapfileinfo:noArg ".
  973. "eventlist:noArg ".
  974. "stmUrlPath:noArg ".
  975. "storedCredentials:noArg ".
  976. "scanVirgin:noArg "
  977. ;
  978. } else {
  979. # getlist für SVS Devices
  980. $getlist = "Unknown argument $opt, choose one of ".
  981. "caminfoall:noArg ".
  982. ($hash->{HELPER}{APIHMMAXVER}?"homeModeState:noArg ": "").
  983. "svsinfo:noArg ".
  984. "listLog ".
  985. "storedCredentials:noArg ".
  986. "scanVirgin:noArg "
  987. ;
  988. }
  989. return if(IsDisabled($name));
  990. if ($opt eq "caminfo") {
  991. # "1" ist Statusbit für manuelle Abfrage, kein Einstieg in Pollingroutine
  992. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  993. SSCam_getcaminfo($hash);
  994. } elsif ($opt eq "caminfoall") {
  995. # "1" ist Statusbit für manuelle Abfrage, kein Einstieg in Pollingroutine
  996. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  997. SSCam_getcaminfoall($hash,1);
  998. } elsif ($opt eq "homeModeState" && !SSCam_IsModelCam($hash)) {
  999. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1000. SSCam_gethomemodestate($hash);
  1001. } elsif ($opt eq "listLog" && !SSCam_IsModelCam($hash)) {
  1002. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1003. # übergebenen CL-Hash (FHEMWEB) in Helper eintragen
  1004. SSCam_getclhash($hash,1);
  1005. SSCam_extlogargs($hash,$arg) if($arg);
  1006. SSCam_extlogargs($hash,$arg1) if($arg1);
  1007. SSCam_extlogargs($hash,$arg2) if($arg2);
  1008. SSCam_getsvslog($hash);
  1009. } elsif ($opt eq "listPresets" && SSCam_IsModelCam($hash)) {
  1010. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1011. # übergebenen CL-Hash (FHEMWEB) in Helper eintragen
  1012. SSCam_getclhash($hash,1);
  1013. SSCam_getpresets($hash);
  1014. } elsif ($opt eq "svsinfo") {
  1015. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1016. SSCam_getsvsinfo($hash);
  1017. } elsif ($opt eq "storedCredentials") {
  1018. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1019. # Credentials abrufen
  1020. my ($success, $username, $password) = SSCam_getcredentials($hash,0);
  1021. unless ($success) {return "Credentials couldn't be retrieved successfully - see logfile"};
  1022. return "Stored Credentials for $name - Username: $username, Password: $password";
  1023. } elsif ($opt eq "snapGallery" && SSCam_IsModelCam($hash)) {
  1024. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1025. my $txt = SSCam_getclhash($hash);
  1026. return $txt if($txt);
  1027. if(!AttrVal($name, "snapGalleryBoost",0)) {
  1028. # Snaphash ist nicht vorhanden und wird abgerufen
  1029. $hash->{HELPER}{GETSNAPGALLERY} = 1;
  1030. # snap-Infos für Gallerie abrufen
  1031. my ($sg,$slim,$ssize);
  1032. $slim = $arg?AttrVal($name,"snapGalleryNumber",$arg):AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snapshots
  1033. $ssize = (AttrVal($name,"snapGallerySize","Icon") eq "Icon")?1:2; # Image Size 1-Icon, 2-Full
  1034. SSCam_getsnapinfo("$name:$slim:$ssize");
  1035. } else {
  1036. # Snaphash ist vorhanden und wird zur Ausgabe aufbereitet
  1037. my $htmlCode = SSCam_composegallery($name);
  1038. for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
  1039. if ($hash->{HELPER}{CL}{$k}->{COMP}) {
  1040. # CL zusammengestellt (Auslösung durch Notify)
  1041. asyncOutput($hash->{HELPER}{CL}{$k}, "$htmlCode");
  1042. } else {
  1043. # Output wurde über FHEMWEB ausgelöst
  1044. return $htmlCode;
  1045. }
  1046. }
  1047. delete($hash->{HELPER}{CL});
  1048. }
  1049. } elsif ($opt eq "snapinfo" && SSCam_IsModelCam($hash)) {
  1050. # Schnappschußgalerie abrufen (snapGalleryBoost) oder nur Info des letzten Snaps
  1051. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1052. my ($slim,$ssize) = SSCam_snaplimsize($hash);
  1053. SSCam_getsnapinfo("$name:$slim:$ssize");
  1054. } elsif ($opt eq "snapfileinfo" && SSCam_IsModelCam($hash)) {
  1055. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1056. if (!ReadingsVal("$name", "LastSnapId", undef)) {return "Reading LastSnapId is empty - please take a snapshot before !"}
  1057. SSCam_getsnapfilename($hash);
  1058. } elsif ($opt eq "eventlist" && SSCam_IsModelCam($hash)) {
  1059. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1060. SSCam_geteventlist ($hash);
  1061. } elsif ($opt eq "stmUrlPath" && SSCam_IsModelCam($hash)) {
  1062. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1063. SSCam_getStmUrlPath ($hash);
  1064. } elsif ($opt eq "scanVirgin") {
  1065. if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";}
  1066. SSCam_sessionoff($hash);
  1067. delete $hash->{HELPER}{APIPARSET};
  1068. delete $hash->{CAMID};
  1069. # alte Readings außer state löschen
  1070. my @allrds = keys%{$defs{$name}{READINGS}};
  1071. foreach my $key(@allrds) {
  1072. # Log3 ($name, 1, "DbRep $name - Reading Schlüssel: $key");
  1073. delete($defs{$name}{READINGS}{$key}) if($key ne "state");
  1074. }
  1075. # "1" ist Statusbit für manuelle Abfrage, kein Einstieg in Pollingroutine
  1076. SSCam_getcaminfoall($hash,1);
  1077. } else {
  1078. return "$getlist";
  1079. }
  1080. return $ret; # not generate trigger out of command
  1081. }
  1082. ######################################################################################
  1083. # Kamera Liveview Anzeige in FHEMWEB
  1084. ######################################################################################
  1085. # wird von FW aufgerufen. $FW_wname = aufrufende Webinstanz, $d = aufrufendes
  1086. # Device (z.B. CamCP1)
  1087. sub SSCam_FWsummaryFn ($$$$) {
  1088. my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn in FHEMWEB
  1089. my $hash = $defs{$d};
  1090. my $name = $hash->{NAME};
  1091. my $link = $hash->{HELPER}{LINK};
  1092. my $wltype = $hash->{HELPER}{WLTYPE};
  1093. my $ret;
  1094. my $alias;
  1095. return if(!$hash->{HELPER}{LINK} || ReadingsVal($d, "state", "") =~ /^dis.*/ || IsDisabled($name));
  1096. # Definition Tasten
  1097. my $imgblank = "<img src=\"$FW_ME/www/images/sscam/black_btn_CAMBLANK.png\">"; # nicht sichtbare Leertaste
  1098. my $cmdstop = "cmd=set $d stopView"; # Stream deaktivieren
  1099. my $imgstop = "<img src=\"$FW_ME/www/images/default/remotecontrol/black_btn_POWEROFF3.png\">";
  1100. my $cmdhlsreact = "cmd=set $d hlsreactivate"; # HLS Stream reaktivieren
  1101. my $imghlsreact = "<img src=\"$FW_ME/www/images/default/remotecontrol/black_btn_BACKDroid.png\">";
  1102. my $cmdmjpegrun = "cmd=set $d runView live_fw"; # MJPEG Stream aktivieren
  1103. my $imgmjpegrun = "<img src=\"$FW_ME/www/images/sscam/black_btn_MJPEG.png\">";
  1104. my $cmdhlsrun = "cmd=set $d runView live_fw_hls"; # HLS Stream aktivieren
  1105. my $imghlsrun = "<img src=\"$FW_ME/www/images/sscam/black_btn_HLS.png\">";
  1106. my $cmdlrirun = "cmd=set $d runView lastrec_fw"; # Last Record IFrame
  1107. my $imglrirun = "<img src=\"$FW_ME/www/images/sscam/black_btn_LASTRECIFRAME.png\">";
  1108. my $cmdlh264run = "cmd=set $d runView lastrec_fw_MPEG4/H.264"; # Last Record H.264
  1109. my $imglh264run = "<img src=\"$FW_ME/www/images/sscam/black_btn_LRECH264.png\">";
  1110. my $cmdlmjpegrun = "cmd=set $d runView lastrec_fw_MJPEG"; # Last Record MJPEG
  1111. my $imglmjpegrun = "<img src=\"$FW_ME/www/images/sscam/black_btn_LRECMJPEG.png\">";
  1112. my $cmdlsnaprun = "cmd=set $d runView lastsnap_fw STRM"; # Last SNAP
  1113. my $imglsnaprun = "<img src=\"$FW_ME/www/images/sscam/black_btn_LSNAP.png\">";
  1114. my $cmdrecendless = "cmd=set $d on 0"; # Endlosaufnahme Start
  1115. my $imgrecendless = "<img src=\"$FW_ME/www/images/sscam/black_btn_RECSTART.png\">";
  1116. my $cmdrecstop = "cmd=set $d off"; # Aufnahme Stop
  1117. my $imgrecstop = "<img src=\"$FW_ME/www/images/sscam/black_btn_RECSTOP.png\">";
  1118. my $cmddosnap = "cmd=set $d snap STRM"; # Snapshot auslösen mit Kennzeichnung "by STRM-Device"
  1119. my $imgdosnap = "<img src=\"$FW_ME/www/images/sscam/black_btn_DOSNAP.png\">";
  1120. my $attr = AttrVal($d, "htmlattr", " ");
  1121. Log3($name, 4, "$name - SSCam_FWsummaryFn called - FW_wname: $FW_wname, device: $d, room: $room, attributes: $attr");
  1122. if($wltype eq "image") {
  1123. $ret = "<img src=$link $attr><br>";
  1124. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  1125. $ret .= $imgblank;
  1126. if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
  1127. if(ReadingsVal($d, "Record", "Stop") eq "Stop") {
  1128. # Aufnahmebutton endlos Start
  1129. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>";
  1130. } else {
  1131. # Aufnahmebutton Stop
  1132. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
  1133. }
  1134. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>";
  1135. }
  1136. $ret .= "<br>";
  1137. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($d, "CamAudioType", "Unknown") !~ /Unknown/) {
  1138. $ret .= "<audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  1139. Your browser does not support the audio element.
  1140. </audio>";
  1141. }
  1142. } elsif($wltype eq "iframe") {
  1143. $ret = "<iframe src=$link $attr controls autoplay>
  1144. Iframes disabled
  1145. </iframe>";
  1146. $ret .= "<br>";
  1147. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  1148. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($d, "CamAudioType", "Unknown") !~ /Unknown/) {
  1149. $ret .= "<audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  1150. Your browser does not support the audio element.
  1151. </audio>";
  1152. }
  1153. } elsif($wltype eq "embed") {
  1154. $ret = "<embed src=$link $attr>";
  1155. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($d, "CamAudioType", "Unknown") !~ /Unknown/) {
  1156. $ret .= "<audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  1157. Your browser does not support the audio element.
  1158. </audio>";
  1159. }
  1160. } elsif($wltype eq "link") {
  1161. $alias = $hash->{HELPER}{ALIAS};
  1162. $ret = "<a href=$link $attr>$alias</a><br>";
  1163. } elsif($wltype eq "base64img") {
  1164. $alias = $hash->{HELPER}{ALIAS};
  1165. $ret = "<img $attr alt='$alias' src='data:image/jpeg;base64,$link'><br>";
  1166. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  1167. } elsif($wltype eq "hls") {
  1168. $alias = $hash->{HELPER}{ALIAS};
  1169. $ret = "<video $attr controls autoplay>
  1170. <source src=$link type=\"application/x-mpegURL\">
  1171. <source src=$link type=\"video/MP2T\">
  1172. Your browser does not support the video tag
  1173. </video>";
  1174. $ret .= "<br>";
  1175. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  1176. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsreact')\">$imghlsreact </a>";
  1177. $ret .= $imgblank;
  1178. if(ReadingsVal($d, "Record", "Stop") eq "Stop") {
  1179. # Aufnahmebutton endlos Start
  1180. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>";
  1181. } else {
  1182. # Aufnahmebutton Stop
  1183. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
  1184. }
  1185. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>";
  1186. } elsif($wltype eq "video") {
  1187. $ret = "<video $attr controls autoplay>
  1188. <source src=$link type=\"video/mp4\">
  1189. <source src=$link type=\"video/ogg\">
  1190. <source src=$link type=\"video/webm\">
  1191. Your browser does not support the video tag.
  1192. </video>";
  1193. $ret .= "<br>";
  1194. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  1195. $ret .= "<br>";
  1196. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($d, "CamAudioType", "Unknown") !~ /Unknown/) {
  1197. $ret .= "<audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  1198. Your browser does not support the audio element.
  1199. </audio>";
  1200. }
  1201. }
  1202. return $ret;
  1203. }
  1204. ######################################################################################
  1205. # PTZ-Steuerpanel in Detailanzeige darstellen
  1206. ######################################################################################
  1207. sub SSCam_FWdetailFn ($$$$) {
  1208. my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
  1209. my $hash = $defs{$d};
  1210. return undef if(!AttrVal($d,"ptzPanel_use",1));
  1211. $hash->{".ptzhtml"} = SSCam_ptzpanel($d) if($hash->{".ptzhtml"} eq "");
  1212. if($hash->{".ptzhtml"} ne "") {
  1213. return $hash->{".ptzhtml"};
  1214. } else {
  1215. return undef;
  1216. }
  1217. }
  1218. ######################################################################################
  1219. # initiale Startroutinen nach Restart FHEM
  1220. ######################################################################################
  1221. sub SSCam_initonboot ($) {
  1222. my ($hash) = @_;
  1223. my $name = $hash->{NAME};
  1224. RemoveInternalTimer($hash, "SSCam_initonboot");
  1225. if ($init_done == 1) {
  1226. RemoveInternalTimer($hash); # alle Timer löschen
  1227. delete($defs{$name}{READINGS}{LiveStreamUrl}) if($defs{$name}{READINGS}{LiveStreamUrl}); # LiveStream URL zurücksetzen
  1228. # check ob alle Recordings = "Stop" nach Reboot -> sonst stoppen
  1229. if (ReadingsVal($hash->{NAME}, "Record", "Stop") eq "Start") {
  1230. Log3($name, 2, "$name - Recording of $hash->{CAMNAME} seems to be still active after FHEM restart - try to stop it now");
  1231. SSCam_camstoprec($hash);
  1232. }
  1233. # Konfiguration der Synology Surveillance Station abrufen
  1234. if (!$hash->{CREDENTIALS}) {
  1235. Log3($name, 2, "$name - Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"");
  1236. } else {
  1237. # allg. SVS-Eigenschaften abrufen
  1238. SSCam_getsvsinfo($hash);
  1239. if(SSCam_IsModelCam($hash)) {
  1240. # Kameraspezifische Infos holen
  1241. SSCam_getcaminfo($hash);
  1242. SSCam_getcapabilities($hash);
  1243. # Preset/Patrollisten in Hash einlesen zur PTZ-Steuerung
  1244. SSCam_getptzlistpreset($hash);
  1245. SSCam_getptzlistpatrol($hash);
  1246. # Schnappschußgalerie abrufen (snapGalleryBoost) oder nur Info des letzten Snaps
  1247. my ($slim,$ssize) = SSCam_snaplimsize($hash);
  1248. RemoveInternalTimer("SSCam_getsnapinfo");
  1249. InternalTimer(gettimeofday()+0.9, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  1250. }
  1251. }
  1252. # Subroutine Watchdog-Timer starten (sollen Cam-Infos regelmäßig abgerufen werden ?), verzögerter zufälliger Start 0-30s
  1253. RemoveInternalTimer($hash, "SSCam_wdpollcaminfo");
  1254. InternalTimer(gettimeofday()+int(rand(30)), "SSCam_wdpollcaminfo", $hash, 0);
  1255. } else {
  1256. InternalTimer(gettimeofday()+1, "SSCam_initonboot", $hash, 0);
  1257. }
  1258. return;
  1259. }
  1260. ######################################################################################
  1261. # Username / Paßwort speichern
  1262. ######################################################################################
  1263. sub SSCam_setcredentials ($@) {
  1264. my ($hash, @credentials) = @_;
  1265. my $name = $hash->{NAME};
  1266. my $success;
  1267. my $credstr;
  1268. my $index;
  1269. my $retcode;
  1270. my (@key,$len,$i);
  1271. $credstr = encode_base64(join(':', @credentials));
  1272. # Beginn Scramble-Routine
  1273. @key = qw(1 3 4 5 6 3 2 1 9);
  1274. $len = scalar @key;
  1275. $i = 0;
  1276. $credstr = join "",
  1277. map { $i = ($i + 1) % $len;
  1278. chr((ord($_) + $key[$i]) % 256) } split //, $credstr;
  1279. # End Scramble-Routine
  1280. $index = $hash->{TYPE}."_".$hash->{NAME}."_credentials";
  1281. $retcode = setKeyValue($index, $credstr);
  1282. if ($retcode) {
  1283. Log3($name, 2, "$name - Error while saving the Credentials - $retcode");
  1284. $success = 0;
  1285. } else {
  1286. SSCam_getcredentials($hash,1); # Credentials nach Speicherung lesen und in RAM laden ($boot=1)
  1287. $success = 1;
  1288. }
  1289. return ($success);
  1290. }
  1291. ######################################################################################
  1292. # Username / Paßwort abrufen
  1293. ######################################################################################
  1294. sub SSCam_getcredentials ($$) {
  1295. my ($hash,$boot) = @_;
  1296. my $name = $hash->{NAME};
  1297. my $success;
  1298. my $username;
  1299. my $passwd;
  1300. my $index;
  1301. my ($retcode, $credstr);
  1302. my (@key,$len,$i);
  1303. if ($boot eq 1) {
  1304. # mit $boot=1 Credentials von Platte lesen und als scrambled-String in RAM legen
  1305. $index = $hash->{TYPE}."_".$hash->{NAME}."_credentials";
  1306. ($retcode, $credstr) = getKeyValue($index);
  1307. if ($retcode) {
  1308. Log3($name, 2, "$name - Unable to read password from file: $retcode");
  1309. $success = 0;
  1310. }
  1311. if ($credstr) {
  1312. # beim Boot scrambled Credentials in den RAM laden
  1313. $hash->{HELPER}{CREDENTIALS} = $credstr;
  1314. # "Credentials" wird als Statusbit ausgewertet. Wenn nicht gesetzt -> Warnmeldung und keine weitere Verarbeitung
  1315. $hash->{CREDENTIALS} = "Set";
  1316. $success = 1;
  1317. }
  1318. } else {
  1319. # boot = 0 -> Credentials aus RAM lesen, decoden und zurückgeben
  1320. $credstr = $hash->{HELPER}{CREDENTIALS};
  1321. # Beginn Descramble-Routine
  1322. @key = qw(1 3 4 5 6 3 2 1 9);
  1323. $len = scalar @key;
  1324. $i = 0;
  1325. $credstr = join "",
  1326. map { $i = ($i + 1) % $len;
  1327. chr((ord($_) - $key[$i] + 256) % 256) }
  1328. split //, $credstr;
  1329. # Ende Descramble-Routine
  1330. ($username, $passwd) = split(":",decode_base64($credstr));
  1331. my $logpw = AttrVal($name, "showPassInLog", "0") == 1 ? $passwd : "********";
  1332. Log3($name, 4, "$name - Credentials read from RAM: $username $logpw");
  1333. $success = (defined($passwd)) ? 1 : 0;
  1334. }
  1335. return ($success, $username, $passwd);
  1336. }
  1337. ######################################################################################
  1338. # Polling Überwachung
  1339. ######################################################################################
  1340. sub SSCam_wdpollcaminfo ($) {
  1341. # Überwacht die Wert von Attribut "pollcaminfoall" und Reading "PollState"
  1342. # wenn Attribut "pollcaminfoall" > 10 und "PollState"=Inactive -> start Polling
  1343. my ($hash) = @_;
  1344. my $name = $hash->{NAME};
  1345. my $camname = $hash->{CAMNAME};
  1346. my $pcia = AttrVal($name,"pollcaminfoall",0);
  1347. my $pnl = AttrVal($name,"pollnologging",0);
  1348. my $watchdogtimer = 90;
  1349. RemoveInternalTimer($hash, "SSCam_wdpollcaminfo");
  1350. # Poll-Logging prüfen
  1351. if ($hash->{HELPER}{OLDVALPOLLNOLOGGING} != $pnl) {
  1352. $hash->{HELPER}{OLDVALPOLLNOLOGGING} = $pnl; # aktuellen pollnologging-Wert in $hash eintragen für späteren Vergleich
  1353. if ($pnl) {
  1354. Log3($name, 3, "$name - Polling-Log of $camname is deactivated");
  1355. } else {
  1356. Log3($name, 3, "$name - Polling-Log of $camname is activated");
  1357. }
  1358. }
  1359. # Polling prüfen
  1360. if ($pcia && !IsDisabled($name)) {
  1361. if(ReadingsVal($name, "PollState", "Active") eq "Inactive") {
  1362. readingsSingleUpdate($hash,"PollState","Active",1); # Polling ist jetzt aktiv
  1363. readingsSingleUpdate($hash,"state","polling",1) if(!SSCam_IsModelCam($hash)); # Polling-state bei einem SVS-Device setzten
  1364. Log3($name, 3, "$name - Polling of $camname is activated - Pollinginterval: $pcia s");
  1365. $hash->{HELPER}{OLDVALPOLL} = $pcia; # in $hash eintragen für späteren Vergleich (Changes von pollcaminfoall)
  1366. SSCam_getcaminfoall($hash,0);
  1367. }
  1368. my $lupd = ReadingsVal($name, "LastUpdateTime", 0);
  1369. if ($lupd) {
  1370. my ($year, $month, $mday, $hour, $min, $sec) = ($lupd =~ /(\d+)\.(\d+)\.(\d+) \/ (\d+):(\d+):(\d+)/);
  1371. $lupd = fhemTimeGm($sec, $min, $hour, $mday, $month, $year);
  1372. }
  1373. if( gettimeofday() < ($lupd + $pcia + 20) ) {
  1374. SSCam_getcaminfoall($hash,0);
  1375. }
  1376. }
  1377. if (defined($hash->{HELPER}{OLDVALPOLL}) && $pcia) {
  1378. if ($hash->{HELPER}{OLDVALPOLL} != $pcia) {
  1379. Log3($name, 3, "$name - Pollinginterval of $camname has been changed to: $pcia s");
  1380. $hash->{HELPER}{OLDVALPOLL} = $pcia;
  1381. }
  1382. }
  1383. InternalTimer(gettimeofday()+$watchdogtimer, "SSCam_wdpollcaminfo", $hash, 0);
  1384. return undef;
  1385. }
  1386. ############################################################################################################
  1387. # OpMode-Startroutinen #
  1388. # $hash->{HELPER}{ACTIVE} = Funktionstoken #
  1389. # $hash->{HELPER}{ACTIVE} = "on" -> eine Routine läuft, Start anderer Routine erst wenn "off". #
  1390. # $hash->{HELPER}{ACTIVE} = "off" -> keine andere Routine läuft, sofortiger Start möglich #
  1391. ############################################################################################################
  1392. ###############################################################################
  1393. # Kamera Aufnahme starten
  1394. ###############################################################################
  1395. sub SSCam_camstartrec ($) {
  1396. my ($hash) = @_;
  1397. my $camname = $hash->{CAMNAME};
  1398. my $name = $hash->{NAME};
  1399. my $errorcode;
  1400. my $error;
  1401. RemoveInternalTimer($hash, "SSCam_camstartrec");
  1402. return if(IsDisabled($name));
  1403. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1404. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1405. $errorcode = "402";
  1406. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1407. $errorcode = "502";
  1408. }
  1409. # Fehlertext zum Errorcode ermitteln
  1410. $error = SSCam_experror($hash,$errorcode);
  1411. # Setreading
  1412. readingsBeginUpdate($hash);
  1413. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1414. readingsBulkUpdate($hash,"Error",$error);
  1415. readingsEndUpdate($hash, 1);
  1416. Log3($name, 2, "$name - ERROR - Start Recording of Camera $camname can't be executed - $error");
  1417. return;
  1418. }
  1419. if (ReadingsVal("$name", "Record", undef) eq "Start" and !AttrVal($name, "recextend", undef)) {
  1420. Log3($name, 3, "$name - another recording is already running - new start-command will be ignored");
  1421. return;
  1422. }
  1423. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1424. # Aufnahme starten
  1425. $hash->{OPMODE} = "Start";
  1426. $hash->{HELPER}{ACTIVE} = "on";
  1427. $hash->{HELPER}{LOGINRETRIES} = 0;
  1428. if (AttrVal($name,"debugactivetoken",0)) {
  1429. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1430. }
  1431. SSCam_getapisites($hash);
  1432. } else {
  1433. InternalTimer(gettimeofday()+0.3, "SSCam_camstartrec", $hash);
  1434. }
  1435. }
  1436. ###############################################################################
  1437. # Kamera Aufnahme stoppen
  1438. ###############################################################################
  1439. sub SSCam_camstoprec ($) {
  1440. my ($hash) = @_;
  1441. my $camname = $hash->{CAMNAME};
  1442. my $name = $hash->{NAME};
  1443. my $errorcode;
  1444. my $error;
  1445. RemoveInternalTimer($hash, "SSCam_camstoprec");
  1446. return if(IsDisabled($name));
  1447. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1448. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1449. $errorcode = "402";
  1450. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1451. $errorcode = "502";
  1452. }
  1453. # Fehlertext zum Errorcode ermitteln
  1454. $error = SSCam_experror($hash,$errorcode);
  1455. # Setreading
  1456. readingsBeginUpdate($hash);
  1457. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1458. readingsBulkUpdate($hash,"Error",$error);
  1459. readingsEndUpdate($hash, 1);
  1460. Log3($name, 2, "$name - ERROR - Stop Recording of Camera $camname can't be executed - $error");
  1461. return;
  1462. }
  1463. if (ReadingsVal("$name", "Record", undef) eq "Stop") {
  1464. Log3($name, 3, "$name - recording is already stopped - new stop-command will be ignored");
  1465. return;
  1466. }
  1467. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1468. $hash->{OPMODE} = "Stop";
  1469. $hash->{HELPER}{ACTIVE} = "on";
  1470. $hash->{HELPER}{LOGINRETRIES} = 0;
  1471. if (AttrVal($name,"debugactivetoken",0)) {
  1472. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1473. }
  1474. SSCam_getapisites($hash);
  1475. } else {
  1476. InternalTimer(gettimeofday()+0.3, "SSCam_camstoprec", $hash, 0);
  1477. }
  1478. }
  1479. ###############################################################################
  1480. # Kamera Auto / Day / Nightmode setzen
  1481. ###############################################################################
  1482. sub SSCam_camexpmode($) {
  1483. my ($hash) = @_;
  1484. my $camname = $hash->{CAMNAME};
  1485. my $name = $hash->{NAME};
  1486. my $errorcode;
  1487. my $error;
  1488. RemoveInternalTimer($hash, "SSCam_camexpmode");
  1489. return if(IsDisabled($name));
  1490. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1491. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1492. $errorcode = "402";
  1493. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1494. $errorcode = "502";
  1495. }
  1496. # Fehlertext zum Errorcode ermitteln
  1497. $error = SSCam_experror($hash,$errorcode);
  1498. # Setreading
  1499. readingsBeginUpdate($hash);
  1500. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1501. readingsBulkUpdate($hash,"Error",$error);
  1502. readingsEndUpdate($hash, 1);
  1503. Log3($name, 2, "$name - ERROR - Setting exposure mode of Camera $camname can't be executed - $error");
  1504. return;
  1505. }
  1506. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1507. $hash->{OPMODE} = "ExpMode";
  1508. $hash->{HELPER}{ACTIVE} = "on";
  1509. $hash->{HELPER}{LOGINRETRIES} = 0;
  1510. if (AttrVal($name,"debugactivetoken",0)) {
  1511. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1512. }
  1513. SSCam_getapisites($hash);
  1514. } else {
  1515. InternalTimer(gettimeofday()+0.5, "SSCam_camexpmode", $hash, 0);
  1516. }
  1517. }
  1518. ###############################################################################
  1519. # Art der Bewegungserkennung setzen
  1520. ###############################################################################
  1521. sub SSCam_cammotdetsc($) {
  1522. my ($hash) = @_;
  1523. my $camname = $hash->{CAMNAME};
  1524. my $name = $hash->{NAME};
  1525. my $errorcode;
  1526. my $error;
  1527. RemoveInternalTimer($hash, "SSCam_cammotdetsc");
  1528. return if(IsDisabled($name));
  1529. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1530. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1531. $errorcode = "402";
  1532. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1533. $errorcode = "502";
  1534. }
  1535. # Fehlertext zum Errorcode ermitteln
  1536. $error = SSCam_experror($hash,$errorcode);
  1537. # Setreading
  1538. readingsBeginUpdate($hash);
  1539. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1540. readingsBulkUpdate($hash,"Error",$error);
  1541. readingsEndUpdate($hash, 1);
  1542. Log3($name, 2, "$name - ERROR - Setting of motion detection source of Camera $camname can't be executed - $error");
  1543. return;
  1544. }
  1545. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1546. $hash->{OPMODE} = "MotDetSc";
  1547. $hash->{HELPER}{ACTIVE} = "on";
  1548. $hash->{HELPER}{LOGINRETRIES} = 0;
  1549. if (AttrVal($name,"debugactivetoken",0)) {
  1550. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1551. }
  1552. SSCam_getapisites($hash);
  1553. } else {
  1554. InternalTimer(gettimeofday()+0.5, "SSCam_cammotdetsc", $hash, 0);
  1555. }
  1556. }
  1557. ###############################################################################
  1558. # Kamera Schappschuß aufnehmen
  1559. ###############################################################################
  1560. sub SSCam_camsnap($) {
  1561. my ($hash) = @_;
  1562. my $camname = $hash->{CAMNAME};
  1563. my $name = $hash->{NAME};
  1564. my $errorcode;
  1565. my $error;
  1566. RemoveInternalTimer($hash, "SSCam_camsnap");
  1567. return if(IsDisabled($name));
  1568. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1569. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1570. $errorcode = "402";
  1571. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1572. $errorcode = "502";
  1573. }
  1574. # Fehlertext zum Errorcode ermitteln
  1575. $error = SSCam_experror($hash,$errorcode);
  1576. # Setreading
  1577. readingsBeginUpdate($hash);
  1578. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1579. readingsBulkUpdate($hash,"Error",$error);
  1580. readingsEndUpdate($hash, 1);
  1581. Log3($name, 2, "$name - ERROR - Snapshot of Camera $camname can't be executed - $error");
  1582. return;
  1583. }
  1584. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1585. # einen Schnappschuß aufnehmen
  1586. $hash->{OPMODE} = "Snap";
  1587. $hash->{HELPER}{ACTIVE} = "on";
  1588. $hash->{HELPER}{LOGINRETRIES} = 0;
  1589. if (AttrVal($name,"debugactivetoken",0)) {
  1590. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1591. }
  1592. SSCam_getapisites($hash);
  1593. } else {
  1594. InternalTimer(gettimeofday()+0.3, "SSCam_camsnap", $hash, 0);
  1595. }
  1596. }
  1597. ###############################################################################
  1598. # Start Object Tracking
  1599. ###############################################################################
  1600. sub SSCam_starttrack($) {
  1601. my ($hash) = @_;
  1602. my $camname = $hash->{CAMNAME};
  1603. my $name = $hash->{NAME};
  1604. my $errorcode;
  1605. my $error;
  1606. RemoveInternalTimer($hash, "SSCam_starttrack");
  1607. return if(IsDisabled($name));
  1608. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1609. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1610. $errorcode = "402";
  1611. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1612. $errorcode = "502";
  1613. }
  1614. # Fehlertext zum Errorcode ermitteln
  1615. $error = SSCam_experror($hash,$errorcode);
  1616. readingsBeginUpdate($hash);
  1617. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1618. readingsBulkUpdate($hash,"Error",$error);
  1619. readingsEndUpdate($hash, 1);
  1620. Log3($name, 2, "$name - ERROR - Object Tracking of Camera $camname can't switched on - $error");
  1621. return;
  1622. }
  1623. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1624. $hash->{OPMODE} = "startTrack";
  1625. $hash->{HELPER}{ACTIVE} = "on";
  1626. $hash->{HELPER}{LOGINRETRIES} = 0;
  1627. if (AttrVal($name,"debugactivetoken",0)) {
  1628. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1629. }
  1630. SSCam_getapisites($hash);
  1631. } else {
  1632. InternalTimer(gettimeofday()+0.9, "SSCam_starttrack", $hash, 0);
  1633. }
  1634. }
  1635. ###############################################################################
  1636. # Stopp Object Tracking
  1637. ###############################################################################
  1638. sub SSCam_stoptrack($) {
  1639. my ($hash) = @_;
  1640. my $camname = $hash->{CAMNAME};
  1641. my $name = $hash->{NAME};
  1642. my $errorcode;
  1643. my $error;
  1644. RemoveInternalTimer($hash, "SSCam_stoptrack");
  1645. return if(IsDisabled($name));
  1646. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1647. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1648. $errorcode = "402";
  1649. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1650. $errorcode = "502";
  1651. }
  1652. # Fehlertext zum Errorcode ermitteln
  1653. $error = SSCam_experror($hash,$errorcode);
  1654. readingsBeginUpdate($hash);
  1655. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1656. readingsBulkUpdate($hash,"Error",$error);
  1657. readingsEndUpdate($hash, 1);
  1658. Log3($name, 2, "$name - ERROR - Object Tracking of Camera $camname can't switched off - $error");
  1659. return;
  1660. }
  1661. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1662. $hash->{OPMODE} = "stopTrack";
  1663. $hash->{HELPER}{ACTIVE} = "on";
  1664. $hash->{HELPER}{LOGINRETRIES} = 0;
  1665. if (AttrVal($name,"debugactivetoken",0)) {
  1666. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1667. }
  1668. SSCam_getapisites($hash);
  1669. } else {
  1670. InternalTimer(gettimeofday()+0.9, "SSCam_stoptrack", $hash, 0);
  1671. }
  1672. }
  1673. ###############################################################################
  1674. # Preset-Array abrufen
  1675. ###############################################################################
  1676. sub SSCam_getpresets($) {
  1677. my ($hash) = @_;
  1678. my $camname = $hash->{CAMNAME};
  1679. my $name = $hash->{NAME};
  1680. my $errorcode;
  1681. my $error;
  1682. RemoveInternalTimer($hash, "SSCam_getpresets");
  1683. return if(IsDisabled($name));
  1684. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1685. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1686. $errorcode = "402";
  1687. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1688. $errorcode = "502";
  1689. }
  1690. # Fehlertext zum Errorcode ermitteln
  1691. $error = SSCam_experror($hash,$errorcode);
  1692. readingsBeginUpdate($hash);
  1693. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1694. readingsBulkUpdate($hash,"Error",$error);
  1695. readingsEndUpdate($hash, 1);
  1696. Log3($name, 2, "$name - ERROR - Preset list of Camera $camname can't be get - $error");
  1697. return;
  1698. }
  1699. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1700. $hash->{OPMODE} = "getPresets";
  1701. $hash->{HELPER}{ACTIVE} = "on";
  1702. $hash->{HELPER}{LOGINRETRIES} = 0;
  1703. if (AttrVal($name,"debugactivetoken",0)) {
  1704. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1705. }
  1706. SSCam_getapisites($hash);
  1707. } else {
  1708. InternalTimer(gettimeofday()+1.2, "SSCam_getpresets", $hash, 0);
  1709. }
  1710. }
  1711. ###############################################################################
  1712. # einen Preset setzen
  1713. ###############################################################################
  1714. sub SSCam_setPreset($) {
  1715. my ($hash) = @_;
  1716. my $camname = $hash->{CAMNAME};
  1717. my $name = $hash->{NAME};
  1718. my $errorcode;
  1719. my $error;
  1720. RemoveInternalTimer($hash, "SSCam_setPreset");
  1721. return if(IsDisabled($name));
  1722. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1723. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1724. $errorcode = "402";
  1725. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1726. $errorcode = "502";
  1727. }
  1728. # Fehlertext zum Errorcode ermitteln
  1729. $error = SSCam_experror($hash,$errorcode);
  1730. readingsBeginUpdate($hash);
  1731. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1732. readingsBulkUpdate($hash,"Error",$error);
  1733. readingsEndUpdate($hash, 1);
  1734. Log3($name, 2, "$name - ERROR - Preset of Camera $camname can't be set - $error");
  1735. return;
  1736. }
  1737. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1738. $hash->{OPMODE} = "setPreset";
  1739. $hash->{HELPER}{ACTIVE} = "on";
  1740. $hash->{HELPER}{LOGINRETRIES} = 0;
  1741. if (AttrVal($name,"debugactivetoken",0)) {
  1742. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1743. }
  1744. SSCam_getapisites($hash);
  1745. } else {
  1746. InternalTimer(gettimeofday()+1.2, "SSCam_setPreset", $hash, 0);
  1747. }
  1748. }
  1749. ###############################################################################
  1750. # einen Preset löschen
  1751. ###############################################################################
  1752. sub SSCam_delPreset($) {
  1753. my ($hash) = @_;
  1754. my $camname = $hash->{CAMNAME};
  1755. my $name = $hash->{NAME};
  1756. my $errorcode;
  1757. my $error;
  1758. RemoveInternalTimer($hash, "SSCam_delPreset");
  1759. return if(IsDisabled($name));
  1760. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1761. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1762. $errorcode = "402";
  1763. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1764. $errorcode = "502";
  1765. }
  1766. # Fehlertext zum Errorcode ermitteln
  1767. $error = SSCam_experror($hash,$errorcode);
  1768. readingsBeginUpdate($hash);
  1769. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1770. readingsBulkUpdate($hash,"Error",$error);
  1771. readingsEndUpdate($hash, 1);
  1772. Log3($name, 2, "$name - ERROR - Preset of Camera $camname can't be deleted - $error");
  1773. return;
  1774. }
  1775. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1776. $hash->{OPMODE} = "delPreset";
  1777. $hash->{HELPER}{ACTIVE} = "on";
  1778. $hash->{HELPER}{LOGINRETRIES} = 0;
  1779. if (AttrVal($name,"debugactivetoken",0)) {
  1780. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1781. }
  1782. SSCam_getapisites($hash);
  1783. } else {
  1784. InternalTimer(gettimeofday()+1.4, "SSCam_delPreset", $hash, 0);
  1785. }
  1786. }
  1787. ###############################################################################
  1788. # Preset Home setzen
  1789. ###############################################################################
  1790. sub SSCam_setHome($) {
  1791. my ($hash) = @_;
  1792. my $camname = $hash->{CAMNAME};
  1793. my $name = $hash->{NAME};
  1794. my $errorcode;
  1795. my $error;
  1796. RemoveInternalTimer($hash, "SSCam_setHome");
  1797. return if(IsDisabled($name));
  1798. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1799. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1800. $errorcode = "402";
  1801. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1802. $errorcode = "502";
  1803. }
  1804. # Fehlertext zum Errorcode ermitteln
  1805. $error = SSCam_experror($hash,$errorcode);
  1806. readingsBeginUpdate($hash);
  1807. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1808. readingsBulkUpdate($hash,"Error",$error);
  1809. readingsEndUpdate($hash, 1);
  1810. Log3($name, 2, "$name - ERROR - Home preset of Camera $camname can't be set - $error");
  1811. return;
  1812. }
  1813. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1814. $hash->{OPMODE} = "setHome";
  1815. $hash->{HELPER}{ACTIVE} = "on";
  1816. $hash->{HELPER}{LOGINRETRIES} = 0;
  1817. if (AttrVal($name,"debugactivetoken",0)) {
  1818. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1819. }
  1820. SSCam_getapisites($hash);
  1821. } else {
  1822. InternalTimer(gettimeofday()+1.2, "SSCam_setHome", $hash, 0);
  1823. }
  1824. }
  1825. ###############################################################################
  1826. # PIR Sensor aktivieren/deaktivieren
  1827. ###############################################################################
  1828. sub SSCam_piract($) {
  1829. my ($hash) = @_;
  1830. my $camname = $hash->{CAMNAME};
  1831. my $name = $hash->{NAME};
  1832. my $errorcode;
  1833. my $error;
  1834. RemoveInternalTimer($hash, "SSCam_piract");
  1835. return if(IsDisabled($name));
  1836. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1837. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1838. $errorcode = "402";
  1839. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1840. $errorcode = "502";
  1841. }
  1842. # Fehlertext zum Errorcode ermitteln
  1843. $error = SSCam_experror($hash,$errorcode);
  1844. readingsBeginUpdate($hash);
  1845. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1846. readingsBulkUpdate($hash,"Error",$error);
  1847. readingsEndUpdate($hash, 1);
  1848. Log3($name, 2, "$name - ERROR - Home preset of Camera $camname can't be set - $error");
  1849. return;
  1850. }
  1851. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1852. $hash->{OPMODE} = "piract";
  1853. $hash->{HELPER}{ACTIVE} = "on";
  1854. $hash->{HELPER}{LOGINRETRIES} = 0;
  1855. if (AttrVal($name,"debugactivetoken",0)) {
  1856. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1857. }
  1858. SSCam_getapisites($hash);
  1859. } else {
  1860. InternalTimer(gettimeofday()+1.2, "SSCam_piract", $hash, 0);
  1861. }
  1862. }
  1863. ###############################################################################
  1864. # Kamera Liveview starten
  1865. ###############################################################################
  1866. sub SSCam_runliveview($) {
  1867. my ($hash) = @_;
  1868. my $camname = $hash->{CAMNAME};
  1869. my $name = $hash->{NAME};
  1870. my $errorcode;
  1871. my $error;
  1872. RemoveInternalTimer($hash, "SSCam_runliveview");
  1873. return if(IsDisabled($name));
  1874. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1875. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1876. $errorcode = "402";
  1877. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1878. $errorcode = "502";
  1879. }
  1880. # Fehlertext zum Errorcode ermitteln
  1881. $error = &SSCam_experror($hash,$errorcode);
  1882. readingsBeginUpdate($hash);
  1883. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1884. readingsBulkUpdate($hash,"Error",$error);
  1885. readingsEndUpdate($hash, 1);
  1886. Log3($name, 2, "$name - ERROR - Liveview of Camera $camname can't be started - $error");
  1887. return;
  1888. }
  1889. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1890. # Liveview starten
  1891. $hash->{OPMODE} = "runliveview";
  1892. $hash->{HELPER}{ACTIVE} = "on";
  1893. $hash->{HELPER}{LOGINRETRIES} = 0;
  1894. # erzwingen die Camid zu ermitteln und bei login-Fehler neue SID zu holen
  1895. delete $hash->{CAMID};
  1896. if (AttrVal($name,"debugactivetoken",0)) {
  1897. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1898. }
  1899. readingsSingleUpdate($hash,"state","runView ".$hash->{HELPER}{RUNVIEW},1);
  1900. SSCam_getapisites($hash);
  1901. } else {
  1902. InternalTimer(gettimeofday()+0.5, "SSCam_runliveview", $hash, 0);
  1903. }
  1904. }
  1905. ###############################################################################
  1906. # Kamera HLS-Stream aktivieren
  1907. ###############################################################################
  1908. sub SSCam_hlsactivate($) {
  1909. my ($hash) = @_;
  1910. my $camname = $hash->{CAMNAME};
  1911. my $name = $hash->{NAME};
  1912. my $errorcode;
  1913. my $error;
  1914. RemoveInternalTimer($hash, "SSCam_hlsactivate");
  1915. return if(IsDisabled($name));
  1916. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1917. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1918. $errorcode = "402";
  1919. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1920. $errorcode = "502";
  1921. }
  1922. # Fehlertext zum Errorcode ermitteln
  1923. $error = &SSCam_experror($hash,$errorcode);
  1924. readingsBeginUpdate($hash);
  1925. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1926. readingsBulkUpdate($hash,"Error",$error);
  1927. readingsEndUpdate($hash, 1);
  1928. Log3($name, 2, "$name - ERROR - HLS-Stream of Camera $camname can't be activated - $error");
  1929. return;
  1930. }
  1931. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1932. # Aktivierung starten
  1933. $hash->{OPMODE} = "activate_hls";
  1934. $hash->{HELPER}{ACTIVE} = "on";
  1935. $hash->{HELPER}{LOGINRETRIES} = 0;
  1936. if (AttrVal($name,"debugactivetoken",0)) {
  1937. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1938. }
  1939. SSCam_getapisites($hash);
  1940. } else {
  1941. InternalTimer(gettimeofday()+0.3, "SSCam_hlsactivate", $hash, 0);
  1942. }
  1943. }
  1944. ###############################################################################
  1945. # HLS-Stream reaktivieren (stoppen & starten)
  1946. ###############################################################################
  1947. sub SSCam_hlsreactivate($) {
  1948. my ($hash) = @_;
  1949. my $camname = $hash->{CAMNAME};
  1950. my $name = $hash->{NAME};
  1951. my $errorcode;
  1952. my $error;
  1953. RemoveInternalTimer($hash, "SSCam_hlsreactivate");
  1954. return if(IsDisabled($name));
  1955. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  1956. if (ReadingsVal("$name", "state", "") eq "disabled") {
  1957. $errorcode = "402";
  1958. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  1959. $errorcode = "502";
  1960. }
  1961. # Fehlertext zum Errorcode ermitteln
  1962. $error = &SSCam_experror($hash,$errorcode);
  1963. readingsBeginUpdate($hash);
  1964. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  1965. readingsBulkUpdate($hash,"Error",$error);
  1966. readingsEndUpdate($hash, 1);
  1967. Log3($name, 2, "$name - ERROR - HLS-Stream of Camera $camname can't be activated - $error");
  1968. return;
  1969. }
  1970. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1971. # Aktivierung starten
  1972. $hash->{OPMODE} = "reactivate_hls";
  1973. $hash->{HELPER}{ACTIVE} = "on";
  1974. $hash->{HELPER}{LOGINRETRIES} = 0;
  1975. if (AttrVal($name,"debugactivetoken",0)) {
  1976. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  1977. }
  1978. SSCam_getapisites($hash);
  1979. } else {
  1980. InternalTimer(gettimeofday()+0.4, "SSCam_hlsreactivate", $hash, 0);
  1981. }
  1982. }
  1983. ###############################################################################
  1984. # Kamera Liveview stoppen
  1985. ###############################################################################
  1986. sub SSCam_stopliveview ($) {
  1987. my ($hash) = @_;
  1988. my $camname = $hash->{CAMNAME};
  1989. my $name = $hash->{NAME};
  1990. my $errorcode;
  1991. my $error;
  1992. RemoveInternalTimer($hash, "SSCam_stopliveview");
  1993. return if(IsDisabled($name));
  1994. if ($hash->{HELPER}{ACTIVE} eq "off") {
  1995. # Liveview stoppen
  1996. $hash->{OPMODE} = "stopliveview";
  1997. $hash->{HELPER}{ACTIVE} = "on";
  1998. $hash->{HELPER}{LOGINRETRIES} = 0;
  1999. if (AttrVal($name,"debugactivetoken",0)) {
  2000. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2001. }
  2002. # Link aus Helper-hash löschen
  2003. delete $hash->{HELPER}{LINK};
  2004. delete $hash->{HELPER}{AUDIOLINK};
  2005. delete $hash->{HELPER}{ACTSTRM}; # sprechender Name des laufenden Streamtyps für SSCamSTRM
  2006. # Reading LiveStreamUrl löschen
  2007. delete($defs{$name}{READINGS}{LiveStreamUrl}) if ($defs{$name}{READINGS}{LiveStreamUrl});
  2008. readingsSingleUpdate($hash,"state","stopview",1);
  2009. if($hash->{HELPER}{WLTYPE} eq "hls") {
  2010. # HLS Stream war aktiv, Streaming beenden
  2011. $hash->{OPMODE} = "stopliveview_hls";
  2012. SSCam_getapisites($hash);
  2013. } else {
  2014. # kein HLS Stream
  2015. SSCam_refresh($hash,0,1,1); # kein Room-Refresh, SSCam-state-Event, SSCamSTRM-Event
  2016. $hash->{HELPER}{ACTIVE} = "off";
  2017. if (AttrVal($name,"debugactivetoken",0)) {
  2018. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  2019. }
  2020. }
  2021. } else {
  2022. InternalTimer(gettimeofday()+0.5, "SSCam_stopliveview", $hash, 0);
  2023. }
  2024. }
  2025. ###############################################################################
  2026. # external Event 1-10 auslösen
  2027. ###############################################################################
  2028. sub SSCam_extevent ($) {
  2029. my ($hash) = @_;
  2030. my $name = $hash->{NAME};
  2031. RemoveInternalTimer($hash, "SSCam_extevent");
  2032. return if(IsDisabled($name));
  2033. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2034. $hash->{OPMODE} = "extevent";
  2035. $hash->{HELPER}{ACTIVE} = "on";
  2036. $hash->{HELPER}{LOGINRETRIES} = 0;
  2037. if (AttrVal($name,"debugactivetoken",0)) {
  2038. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2039. }
  2040. SSCam_getapisites($hash);
  2041. } else {
  2042. InternalTimer(gettimeofday()+0.5, "SSCam_extevent", $hash, 0);
  2043. }
  2044. }
  2045. ###############################################################################
  2046. # PTZ-Kamera auf Position fahren
  2047. ###############################################################################
  2048. sub SSCam_doptzaction ($) {
  2049. my ($hash) = @_;
  2050. my $camname = $hash->{CAMNAME};
  2051. my $name = $hash->{NAME};
  2052. my $errorcode;
  2053. my $error;
  2054. RemoveInternalTimer($hash, "SSCam_doptzaction");
  2055. return if(IsDisabled($name));
  2056. if (ReadingsVal("$name", "DeviceType", "Camera") ne "PTZ") {
  2057. Log3($name, 2, "$name - ERROR - Operation \"$hash->{HELPER}{PTZACTION}\" is only possible for cameras of DeviceType \"PTZ\" - please compare with device Readings");
  2058. return;
  2059. }
  2060. if ($hash->{HELPER}{PTZACTION} eq "goabsptz" && !ReadingsVal("$name", "CapPTZAbs", "false")) {
  2061. Log3($name, 2, "$name - ERROR - Operation \"$hash->{HELPER}{PTZACTION}\" is only possible if camera supports absolute PTZ action - please compare with device Reading \"CapPTZAbs\"");
  2062. return;
  2063. }
  2064. if ( $hash->{HELPER}{PTZACTION} eq "movestart" && ReadingsVal("$name", "CapPTZDirections", "0") < 1) {
  2065. Log3($name, 2, "$name - ERROR - Operation \"$hash->{HELPER}{PTZACTION}\" is only possible if camera supports \"Tilt\" and \"Pan\" operations - please compare with device Reading \"CapPTZDirections\"");
  2066. return;
  2067. }
  2068. if ($hash->{HELPER}{PTZACTION} eq "gopreset") {
  2069. if (!defined($hash->{HELPER}{ALLPRESETS}{$hash->{HELPER}{GOPRESETNAME}})) {
  2070. $errorcode = "600";
  2071. # Fehlertext zum Errorcode ermitteln
  2072. $error = SSCam_experror($hash,$errorcode);
  2073. # Setreading
  2074. readingsBeginUpdate($hash);
  2075. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  2076. readingsBulkUpdate($hash,"Error",$error);
  2077. readingsEndUpdate($hash, 1);
  2078. Log3($name, 2, "$name - ERROR - goPreset to position \"$hash->{HELPER}{GOPRESETNAME}\" of Camera $camname can't be executed - $error");
  2079. return;
  2080. }
  2081. }
  2082. if ($hash->{HELPER}{PTZACTION} eq "runpatrol") {
  2083. if (!defined($hash->{HELPER}{ALLPATROLS}{$hash->{HELPER}{GOPATROLNAME}})) {
  2084. $errorcode = "600";
  2085. # Fehlertext zum Errorcode ermitteln
  2086. $error = SSCam_experror($hash,$errorcode);
  2087. # Setreading
  2088. readingsBeginUpdate($hash);
  2089. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  2090. readingsBulkUpdate($hash,"Error",$error);
  2091. readingsEndUpdate($hash, 1);
  2092. Log3($name, 2, "$name - ERROR - runPatrol to patrol \"$hash->{HELPER}{GOPATROLNAME}\" of Camera $camname can't be executed - $error");
  2093. return;
  2094. }
  2095. }
  2096. if (ReadingsVal("$name", "state", "") =~ /^dis.*/) {
  2097. if (ReadingsVal("$name", "state", "") eq "disabled") {
  2098. $errorcode = "402";
  2099. } elsif (ReadingsVal("$name", "state", "") eq "disconnected") {
  2100. $errorcode = "502";
  2101. }
  2102. # Fehlertext zum Errorcode ermitteln
  2103. $error = SSCam_experror($hash,$errorcode);
  2104. # Setreading
  2105. readingsBeginUpdate($hash);
  2106. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  2107. readingsBulkUpdate($hash,"Error",$error);
  2108. readingsEndUpdate($hash, 1);
  2109. Log3($name, 2, "$name - ERROR - $hash->{HELPER}{PTZACTION} of Camera $camname can't be executed - $error");
  2110. return;
  2111. }
  2112. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2113. if ($hash->{HELPER}{PTZACTION} eq "gopreset") {
  2114. Log3($name, 4, "$name - Move Camera $camname to position \"$hash->{HELPER}{GOPRESETNAME}\" with ID \"$hash->{HELPER}{ALLPRESETS}{$hash->{HELPER}{GOPRESETNAME}}\" now");
  2115. } elsif ($hash->{HELPER}{PTZACTION} eq "runpatrol") {
  2116. Log3($name, 4, "$name - Start patrol \"$hash->{HELPER}{GOPATROLNAME}\" with ID \"$hash->{HELPER}{ALLPATROLS}{$hash->{HELPER}{GOPATROLNAME}}\" of Camera $camname now");
  2117. } elsif ($hash->{HELPER}{PTZACTION} eq "goabsptz") {
  2118. Log3($name, 4, "$name - Start move Camera $camname to position posX=\"$hash->{HELPER}{GOPTZPOSX}\" and posY=\"$hash->{HELPER}{GOPTZPOSY}\" now");
  2119. } elsif ($hash->{HELPER}{PTZACTION} eq "movestart") {
  2120. Log3($name, 4, "$name - Start move Camera $camname to direction \"$hash->{HELPER}{GOMOVEDIR}\" with duration of $hash->{HELPER}{GOMOVETIME} s");
  2121. }
  2122. if (AttrVal($name,"debugactivetoken",0)) {
  2123. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2124. }
  2125. $hash->{OPMODE} = $hash->{HELPER}{PTZACTION};
  2126. $hash->{HELPER}{ACTIVE} = "on";
  2127. $hash->{HELPER}{LOGINRETRIES} = 0;
  2128. SSCam_getapisites($hash);
  2129. } else {
  2130. InternalTimer(gettimeofday()+0.5, "SSCam_doptzaction", $hash, 0);
  2131. }
  2132. }
  2133. ###############################################################################
  2134. # stoppen continoues move
  2135. ###############################################################################
  2136. sub SSCam_movestop ($) {
  2137. my ($hash) = @_;
  2138. my $camname = $hash->{CAMNAME};
  2139. my $name = $hash->{NAME};
  2140. RemoveInternalTimer($hash, "SSCam_movestop");
  2141. return if(IsDisabled($name));
  2142. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2143. $hash->{OPMODE} = "movestop";
  2144. $hash->{HELPER}{ACTIVE} = "on";
  2145. $hash->{HELPER}{LOGINRETRIES} = 0;
  2146. if (AttrVal($name,"debugactivetoken",0)) {
  2147. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");;
  2148. }
  2149. SSCam_getapisites($hash);
  2150. } else {
  2151. InternalTimer(gettimeofday()+0.3, "SSCam_movestop", $hash, 0);
  2152. }
  2153. }
  2154. ###############################################################################
  2155. # Kamera aktivieren
  2156. ###############################################################################
  2157. sub SSCam_camenable ($) {
  2158. my ($hash) = @_;
  2159. my $camname = $hash->{CAMNAME};
  2160. my $name = $hash->{NAME};
  2161. RemoveInternalTimer($hash, "SSCam_camenable");
  2162. return if(IsDisabled($name));
  2163. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2164. # eine Kamera aktivieren
  2165. Log3($name, 4, "$name - Enable Camera $camname");
  2166. $hash->{OPMODE} = "Enable";
  2167. $hash->{HELPER}{ACTIVE} = "on";
  2168. $hash->{HELPER}{LOGINRETRIES} = 0;
  2169. if (AttrVal($name,"debugactivetoken",0)) {
  2170. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2171. }
  2172. SSCam_getapisites($hash);
  2173. } else {
  2174. InternalTimer(gettimeofday()+0.5, "SSCam_camenable", $hash, 0);
  2175. }
  2176. }
  2177. ###############################################################################
  2178. # Kamera deaktivieren
  2179. ###############################################################################
  2180. sub SSCam_camdisable ($) {
  2181. my ($hash) = @_;
  2182. my $camname = $hash->{CAMNAME};
  2183. my $name = $hash->{NAME};
  2184. RemoveInternalTimer($hash, "SSCam_camdisable");
  2185. return if(IsDisabled($name));
  2186. if ($hash->{HELPER}{ACTIVE} eq "off" and ReadingsVal("$name", "Record", "Start") ne "Start") {
  2187. # eine Kamera deaktivieren
  2188. Log3($name, 4, "$name - Disable Camera $camname");
  2189. $hash->{OPMODE} = "Disable";
  2190. $hash->{HELPER}{ACTIVE} = "on";
  2191. $hash->{HELPER}{LOGINRETRIES} = 0;
  2192. if (AttrVal($name,"debugactivetoken",0)) {
  2193. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2194. }
  2195. SSCam_getapisites($hash);
  2196. } else {
  2197. InternalTimer(gettimeofday()+0.5, "SSCam_camdisable", $hash, 0);
  2198. }
  2199. }
  2200. ###############################################################################
  2201. # Kamera alle Informationen abrufen (Get) bzw. Einstieg Polling
  2202. ###############################################################################
  2203. sub SSCam_getcaminfoall ($$) {
  2204. my ($hash,$mode) = @_;
  2205. my $camname = $hash->{CAMNAME};
  2206. my $name = $hash->{NAME};
  2207. my ($now,$new);
  2208. RemoveInternalTimer($hash, "SSCam_getcaminfoall");
  2209. return if(IsDisabled($name));
  2210. RemoveInternalTimer($hash, "SSCam_getsvsinfo");
  2211. InternalTimer(gettimeofday()+1, "SSCam_getsvsinfo", $hash, 0);
  2212. if(SSCam_IsModelCam($hash)) {
  2213. # Model ist CAM
  2214. RemoveInternalTimer($hash, "SSCam_geteventlist");
  2215. InternalTimer(gettimeofday()+0.5, "SSCam_geteventlist", $hash, 0);
  2216. RemoveInternalTimer($hash, "SSCam_getmotionenum");
  2217. InternalTimer(gettimeofday()+0.6, "SSCam_getmotionenum", $hash, 0);
  2218. RemoveInternalTimer($hash, "SSCam_getcaminfo");
  2219. InternalTimer(gettimeofday()+0.9, "SSCam_getcaminfo", $hash, 0);
  2220. RemoveInternalTimer($hash, "SSCam_getcapabilities");
  2221. InternalTimer(gettimeofday()+1.3, "SSCam_getcapabilities", $hash, 0);
  2222. RemoveInternalTimer($hash, "SSCam_getstreamformat");
  2223. InternalTimer(gettimeofday()+1.4, "SSCam_getstreamformat", $hash, 0);
  2224. # Schnappschußgalerie abrufen (snapGalleryBoost) oder nur Info des letzten Snaps
  2225. my ($slim,$ssize) = SSCam_snaplimsize($hash);
  2226. RemoveInternalTimer("SSCam_getsnapinfo");
  2227. InternalTimer(gettimeofday()+1.5, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  2228. RemoveInternalTimer($hash, "SSCam_getptzlistpreset");
  2229. InternalTimer(gettimeofday()+1.6, "SSCam_getptzlistpreset", $hash, 0);
  2230. RemoveInternalTimer($hash, "SSCam_getptzlistpatrol");
  2231. InternalTimer(gettimeofday()+1.9, "SSCam_getptzlistpatrol", $hash, 0);
  2232. RemoveInternalTimer($hash, "SSCam_getStmUrlPath");
  2233. InternalTimer(gettimeofday()+2.1, "SSCam_getStmUrlPath", $hash, 0);
  2234. } else {
  2235. # Model ist SVS
  2236. RemoveInternalTimer($hash, "SSCam_gethomemodestate");
  2237. InternalTimer(gettimeofday()+0.7, "SSCam_gethomemodestate", $hash, 0);
  2238. RemoveInternalTimer($hash, "SSCam_getsvslog");
  2239. InternalTimer(gettimeofday()+0.8, "SSCam_getsvslog", $hash, 0);
  2240. }
  2241. # wenn gesetzt = manuelle Abfrage
  2242. # return if ($mode); # 24.03.2018 geänd.
  2243. my $pcia = AttrVal($name,"pollcaminfoall",0);
  2244. my $pnl = AttrVal($name,"pollnologging",0);
  2245. if ($pcia) {
  2246. $new = gettimeofday()+$pcia;
  2247. InternalTimer($new, "SSCam_getcaminfoall", $hash, 0);
  2248. $now = FmtTime(gettimeofday());
  2249. $new = FmtTime(gettimeofday()+$pcia);
  2250. readingsSingleUpdate($hash,"state","polling",1) if(!SSCam_IsModelCam($hash)); # state für SVS-Device setzen
  2251. readingsSingleUpdate($hash,"PollState","Active - next time: $new",1);
  2252. if (!$pnl) {
  2253. Log3($name, 3, "$name - Polling now: $now , next Polling: $new");
  2254. }
  2255. } else {
  2256. # Beenden Polling aller Caminfos
  2257. readingsSingleUpdate($hash,"PollState","Inactive",1);
  2258. readingsSingleUpdate($hash,"state","initialized",1) if(!SSCam_IsModelCam($hash)); # state für SVS-Device setzen
  2259. Log3($name, 3, "$name - Polling of $camname is deactivated");
  2260. }
  2261. return;
  2262. }
  2263. ###########################################################################
  2264. # Infos zu Snaps abfragen (z.B. weil nicht über SSCam ausgelöst)
  2265. ###########################################################################
  2266. sub SSCam_getsnapinfo ($) {
  2267. my ($str) = @_;
  2268. my ($name,$slim,$ssize) = split(":",$str);
  2269. my $hash = $defs{$name};
  2270. my $camname = $hash->{CAMNAME};
  2271. RemoveInternalTimer("SSCam_getsnapinfo");
  2272. return if(IsDisabled($name));
  2273. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2274. $hash->{OPMODE} = "getsnapinfo";
  2275. $hash->{OPMODE} = "getsnapgallery" if(exists($hash->{HELPER}{GETSNAPGALLERY}));
  2276. $hash->{HELPER}{ACTIVE} = "on";
  2277. $hash->{HELPER}{LOGINRETRIES} = 0;
  2278. $hash->{HELPER}{SNAPLIMIT} = $slim; # 0-alle Snapshots werden abgerufen und ausgewertet, sonst $slim
  2279. $hash->{HELPER}{SNAPIMGSIZE} = $ssize; # 0-Do not append image, 1-Icon size, 2-Full size
  2280. $hash->{HELPER}{KEYWORD} = $camname;
  2281. if (AttrVal($name,"debugactivetoken",0)) {
  2282. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2283. }
  2284. SSCam_getapisites($hash);
  2285. } else {
  2286. InternalTimer(gettimeofday()+1.7, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  2287. }
  2288. }
  2289. ###############################################################################
  2290. # Filename zu Schappschuß ermitteln
  2291. ###############################################################################
  2292. sub SSCam_getsnapfilename ($) {
  2293. my ($hash) = @_;
  2294. my $name = $hash->{NAME};
  2295. RemoveInternalTimer($hash, "SSCam_getsnapfilename");
  2296. return if(IsDisabled($name));
  2297. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2298. $hash->{OPMODE} = "getsnapfilename";
  2299. $hash->{HELPER}{ACTIVE} = "on";
  2300. $hash->{HELPER}{LOGINRETRIES} = 0;
  2301. if (AttrVal($name,"debugactivetoken",0)) {
  2302. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2303. }
  2304. SSCam_getapisites($hash);
  2305. } else {
  2306. InternalTimer(gettimeofday()+0.5, "SSCam_getsnapfilename", $hash, 0);
  2307. }
  2308. }
  2309. ###########################################################################
  2310. # allgemeine Infos über Synology Surveillance Station
  2311. ###########################################################################
  2312. sub SSCam_getsvsinfo ($) {
  2313. my ($hash) = @_;
  2314. my $camname = $hash->{CAMNAME};
  2315. my $name = $hash->{NAME};
  2316. RemoveInternalTimer($hash, "SSCam_getsvsinfo");
  2317. return if(IsDisabled($name));
  2318. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2319. $hash->{OPMODE} = "getsvsinfo";
  2320. $hash->{HELPER}{ACTIVE} = "on";
  2321. $hash->{HELPER}{LOGINRETRIES} = 0;
  2322. if (AttrVal($name,"debugactivetoken",0)) {
  2323. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2324. }
  2325. SSCam_getapisites($hash);
  2326. } else {
  2327. InternalTimer(gettimeofday()+1, "SSCam_getsvsinfo", $hash, 0);
  2328. }
  2329. }
  2330. ###########################################################################
  2331. # HomeMode setzen
  2332. ###########################################################################
  2333. sub SSCam_sethomemode ($) {
  2334. my ($hash) = @_;
  2335. my $camname = $hash->{CAMNAME};
  2336. my $name = $hash->{NAME};
  2337. RemoveInternalTimer($hash, "SSCam_sethomemode");
  2338. return if(IsDisabled($name) || !defined($hash->{HELPER}{APIHMMAXVER}));
  2339. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2340. $hash->{OPMODE} = "sethomemode";
  2341. $hash->{HELPER}{ACTIVE} = "on";
  2342. $hash->{HELPER}{LOGINRETRIES} = 0;
  2343. if (AttrVal($name,"debugactivetoken",0)) {
  2344. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2345. }
  2346. SSCam_getapisites($hash);
  2347. } else {
  2348. InternalTimer(gettimeofday()+0.6, "SSCam_sethomemode", $hash, 0);
  2349. }
  2350. }
  2351. ###########################################################################
  2352. # Optimierparameter setzen
  2353. ###########################################################################
  2354. sub SSCam_setoptpar ($) {
  2355. my ($hash) = @_;
  2356. my $camname = $hash->{CAMNAME};
  2357. my $name = $hash->{NAME};
  2358. RemoveInternalTimer($hash, "SSCam_setoptpar");
  2359. return if(IsDisabled($name));
  2360. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2361. $hash->{OPMODE} = "setoptpar";
  2362. $hash->{HELPER}{ACTIVE} = "on";
  2363. $hash->{HELPER}{LOGINRETRIES} = 0;
  2364. if (AttrVal($name,"debugactivetoken",0)) {
  2365. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2366. }
  2367. SSCam_getapisites($hash);
  2368. } else {
  2369. InternalTimer(gettimeofday()+0.6, "SSCam_setoptpar", $hash, 0);
  2370. }
  2371. }
  2372. ###########################################################################
  2373. # HomeMode Status abfragen
  2374. ###########################################################################
  2375. sub SSCam_gethomemodestate ($) {
  2376. my ($hash) = @_;
  2377. my $camname = $hash->{CAMNAME};
  2378. my $name = $hash->{NAME};
  2379. RemoveInternalTimer($hash, "SSCam_gethomemodestate");
  2380. return if(IsDisabled($name) || !defined($hash->{HELPER}{APIHMMAXVER}));
  2381. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2382. $hash->{OPMODE} = "gethomemodestate";
  2383. $hash->{HELPER}{ACTIVE} = "on";
  2384. $hash->{HELPER}{LOGINRETRIES} = 0;
  2385. if (AttrVal($name,"debugactivetoken",0)) {
  2386. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2387. }
  2388. SSCam_getapisites($hash);
  2389. } else {
  2390. InternalTimer(gettimeofday()+0.7, "SSCam_gethomemodestate", $hash, 0);
  2391. }
  2392. }
  2393. ###########################################################################
  2394. # SVS Log abrufen
  2395. ###########################################################################
  2396. sub SSCam_getsvslog ($) {
  2397. my ($hash) = @_;
  2398. my $camname = $hash->{CAMNAME};
  2399. my $name = $hash->{NAME};
  2400. RemoveInternalTimer($hash, "SSCam_getsvslog");
  2401. return if(IsDisabled($name));
  2402. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2403. $hash->{OPMODE} = "getsvslog";
  2404. $hash->{HELPER}{ACTIVE} = "on";
  2405. $hash->{HELPER}{LOGINRETRIES} = 0;
  2406. if (AttrVal($name,"debugactivetoken",0)) {
  2407. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2408. }
  2409. SSCam_getapisites($hash);
  2410. } else {
  2411. InternalTimer(gettimeofday()+0.9, "SSCam_getsvslog", $hash, 0);
  2412. }
  2413. }
  2414. ###########################################################################
  2415. # Session SSCam_logout
  2416. ###########################################################################
  2417. sub SSCam_sessionoff ($) {
  2418. my ($hash) = @_;
  2419. my $camname = $hash->{CAMNAME};
  2420. my $name = $hash->{NAME};
  2421. RemoveInternalTimer($hash, "SSCam_sessionoff");
  2422. return if(IsDisabled($name));
  2423. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2424. $hash->{OPMODE} = "logout";
  2425. $hash->{HELPER}{ACTIVE} = "on";
  2426. if (AttrVal($name,"debugactivetoken",0)) {
  2427. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2428. }
  2429. SSCam_logout($hash);
  2430. } else {
  2431. InternalTimer(gettimeofday()+1.1, "SSCam_sessionoff", $hash, 0);
  2432. }
  2433. }
  2434. ###########################################################################
  2435. # Kamera allgemeine Informationen abrufen (Get)
  2436. ###########################################################################
  2437. sub SSCam_getcaminfo($) {
  2438. my ($hash) = @_;
  2439. my $camname = $hash->{CAMNAME};
  2440. my $name = $hash->{NAME};
  2441. RemoveInternalTimer($hash, "SSCam_getcaminfo");
  2442. return if(IsDisabled($name));
  2443. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2444. $hash->{OPMODE} = "Getcaminfo";
  2445. $hash->{HELPER}{ACTIVE} = "on";
  2446. $hash->{HELPER}{LOGINRETRIES} = 0;
  2447. if (AttrVal($name,"debugactivetoken",0)) {
  2448. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2449. }
  2450. SSCam_getapisites($hash);
  2451. } else {
  2452. InternalTimer(gettimeofday()+2, "SSCam_getcaminfo", $hash, 0);
  2453. }
  2454. }
  2455. ###########################################################################
  2456. # SYNO.SurveillanceStation.VideoStream query aktuelles Streamformat
  2457. ###########################################################################
  2458. sub SSCam_getstreamformat ($) {
  2459. my ($hash) = @_;
  2460. my $camname = $hash->{CAMNAME};
  2461. my $name = $hash->{NAME};
  2462. RemoveInternalTimer($hash, "SSCam_getstreamformat");
  2463. my $apivideostmsmaxver = $hash->{HELPER}{APIVIDEOSTMSMAXVER};
  2464. return if(IsDisabled($name));
  2465. if(!$apivideostmsmaxver) {
  2466. # keine API "SYNO.SurveillanceStation.VideoStream" mehr ab API v2.8
  2467. readingsSingleUpdate($hash,"CamStreamFormat", "no API", 1);
  2468. return;
  2469. }
  2470. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2471. $hash->{OPMODE} = "getstreamformat";
  2472. $hash->{HELPER}{ACTIVE} = "on";
  2473. $hash->{HELPER}{LOGINRETRIES} = 0;
  2474. if (AttrVal($name,"debugactivetoken",0)) {
  2475. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2476. }
  2477. SSCam_getapisites($hash);
  2478. } else {
  2479. InternalTimer(gettimeofday()+1.4, "SSCam_getstreamformat", $hash, 0);
  2480. }
  2481. }
  2482. ################################################################################
  2483. # Kamera Stream Urls abrufen (Get)
  2484. ################################################################################
  2485. sub SSCam_getStmUrlPath ($) {
  2486. my ($hash) = @_;
  2487. my $camname = $hash->{CAMNAME};
  2488. my $name = $hash->{NAME};
  2489. RemoveInternalTimer($hash, "SSCam_getStmUrlPath");
  2490. return if(IsDisabled($name));
  2491. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2492. # Stream-Urls abrufen
  2493. $hash->{OPMODE} = "getStmUrlPath";
  2494. $hash->{HELPER}{ACTIVE} = "on";
  2495. $hash->{HELPER}{LOGINRETRIES} = 0;
  2496. if (AttrVal($name,"debugactivetoken",0)) {
  2497. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2498. }
  2499. SSCam_getapisites($hash);
  2500. } else {
  2501. InternalTimer(gettimeofday()+2, "SSCam_getStmUrlPath", $hash, 0);
  2502. }
  2503. }
  2504. ###########################################################################
  2505. # query SVS-Event information
  2506. ###########################################################################
  2507. sub SSCam_geteventlist ($) {
  2508. my ($hash) = @_;
  2509. my $camname = $hash->{CAMNAME};
  2510. my $name = $hash->{NAME};
  2511. RemoveInternalTimer($hash, "SSCam_geteventlist");
  2512. return if(IsDisabled($name));
  2513. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2514. $hash->{OPMODE} = "geteventlist";
  2515. $hash->{HELPER}{ACTIVE} = "on";
  2516. $hash->{HELPER}{LOGINRETRIES} = 0;
  2517. if (AttrVal($name,"debugactivetoken",0)) {
  2518. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2519. }
  2520. SSCam_getapisites($hash);
  2521. } else {
  2522. InternalTimer(gettimeofday()+2, "SSCam_geteventlist", $hash, 0);
  2523. }
  2524. }
  2525. ###########################################################################
  2526. # Enumerate motion detection parameters
  2527. ###########################################################################
  2528. sub SSCam_getmotionenum ($) {
  2529. my ($hash) = @_;
  2530. my $camname = $hash->{CAMNAME};
  2531. my $name = $hash->{NAME};
  2532. RemoveInternalTimer($hash, "SSCam_getmotionenum");
  2533. return if(IsDisabled($name));
  2534. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2535. $hash->{OPMODE} = "getmotionenum";
  2536. $hash->{HELPER}{ACTIVE} = "on";
  2537. $hash->{HELPER}{LOGINRETRIES} = 0;
  2538. if (AttrVal($name,"debugactivetoken",0)) {
  2539. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2540. }
  2541. SSCam_getapisites($hash);
  2542. } else {
  2543. InternalTimer(gettimeofday()+2, "SSCam_getmotionenum", $hash, 0);
  2544. }
  2545. }
  2546. ##########################################################################
  2547. # Capabilities von Kamera abrufen (Get)
  2548. ##########################################################################
  2549. sub SSCam_getcapabilities ($) {
  2550. my ($hash) = @_;
  2551. my $camname = $hash->{CAMNAME};
  2552. my $name = $hash->{NAME};
  2553. RemoveInternalTimer($hash, "SSCam_getcapabilities");
  2554. return if(IsDisabled($name));
  2555. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2556. $hash->{OPMODE} = "Getcapabilities";
  2557. $hash->{HELPER}{ACTIVE} = "on";
  2558. $hash->{HELPER}{LOGINRETRIES} = 0;
  2559. if (AttrVal($name,"debugactivetoken",0)) {
  2560. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2561. }
  2562. SSCam_getapisites($hash);
  2563. } else {
  2564. InternalTimer(gettimeofday()+2, "SSCam_getcapabilities", $hash, 0);
  2565. }
  2566. }
  2567. ##########################################################################
  2568. # PTZ Presets abrufen (Get)
  2569. ##########################################################################
  2570. sub SSCam_getptzlistpreset ($) {
  2571. my ($hash) = @_;
  2572. my $camname = $hash->{CAMNAME};
  2573. my $name = $hash->{NAME};
  2574. RemoveInternalTimer($hash, "SSCam_getptzlistpreset");
  2575. return if(IsDisabled($name));
  2576. if (ReadingsVal("$name", "DeviceType", "") ne "PTZ") {
  2577. Log3($name, 4, "$name - Retrieval of Presets for $camname can't be executed - $camname is not a PTZ-Camera");
  2578. return;
  2579. }
  2580. if (ReadingsVal("$name", "CapPTZTilt", "") eq "false" | ReadingsVal("$name", "CapPTZPan", "") eq "false") {
  2581. Log3($name, 4, "$name - Retrieval of Presets for $camname can't be executed - $camname has no capability to tilt/pan");
  2582. return;
  2583. }
  2584. if ($hash->{HELPER}{ACTIVE} eq "off") {
  2585. $hash->{OPMODE} = "Getptzlistpreset";
  2586. $hash->{HELPER}{ACTIVE} = "on";
  2587. $hash->{HELPER}{LOGINRETRIES} = 0;
  2588. if (AttrVal($name,"debugactivetoken",0)) {
  2589. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2590. }
  2591. SSCam_getapisites($hash);
  2592. } else {
  2593. InternalTimer(gettimeofday()+2, "SSCam_getptzlistpreset", $hash, 0);
  2594. }
  2595. }
  2596. ##########################################################################
  2597. # PTZ Patrols abrufen (Get)
  2598. ##########################################################################
  2599. sub SSCam_getptzlistpatrol ($) {
  2600. my ($hash) = @_;
  2601. my $camname = $hash->{CAMNAME};
  2602. my $name = $hash->{NAME};
  2603. RemoveInternalTimer($hash, "SSCam_getptzlistpatrol");
  2604. return if(IsDisabled($name));
  2605. if (ReadingsVal("$name", "DeviceType", "") ne "PTZ") {
  2606. Log3($name, 4, "$name - Retrieval of Patrols for $camname can't be executed - $camname is not a PTZ-Camera");
  2607. return;
  2608. }
  2609. if (ReadingsVal("$name", "CapPTZTilt", "") eq "false" | ReadingsVal("$name", "CapPTZPan", "") eq "false") {
  2610. Log3($name, 4, "$name - Retrieval of Patrols for $camname can't be executed - $camname has no capability to tilt/pan");
  2611. return;
  2612. }
  2613. if ($hash->{HELPER}{ACTIVE} ne "on") {
  2614. $hash->{OPMODE} = "Getptzlistpatrol";
  2615. $hash->{HELPER}{ACTIVE} = "on";
  2616. $hash->{HELPER}{LOGINRETRIES} = 0;
  2617. if (AttrVal($name,"debugactivetoken",0)) {
  2618. Log3($name, 3, "$name - Active-Token was set by OPMODE: $hash->{OPMODE}");
  2619. }
  2620. SSCam_getapisites($hash);
  2621. } else {
  2622. InternalTimer(gettimeofday()+2, "SSCam_getptzlistpatrol", $hash, 0);
  2623. }
  2624. }
  2625. #############################################################################################################################
  2626. ####### Begin Kameraoperationen mit NonblockingGet (nicht blockierender HTTP-Call) #######
  2627. #############################################################################################################################
  2628. sub SSCam_getapisites($) {
  2629. my ($hash) = @_;
  2630. my $serveraddr = $hash->{SERVERADDR};
  2631. my $serverport = $hash->{SERVERPORT};
  2632. my $name = $hash->{NAME};
  2633. my $apiinfo = $hash->{HELPER}{APIINFO}; # Info-Seite für alle API's, einzige statische Seite !
  2634. my $apiauth = $hash->{HELPER}{APIAUTH};
  2635. my $apiextrec = $hash->{HELPER}{APIEXTREC};
  2636. my $apiextevt = $hash->{HELPER}{APIEXTEVT};
  2637. my $apicam = $hash->{HELPER}{APICAM};
  2638. my $apitakesnap = $hash->{HELPER}{APISNAPSHOT};
  2639. my $apiptz = $hash->{HELPER}{APIPTZ};
  2640. my $apipreset = $hash->{HELPER}{APIPRESET};
  2641. my $apisvsinfo = $hash->{HELPER}{APISVSINFO};
  2642. my $apicamevent = $hash->{HELPER}{APICAMEVENT};
  2643. my $apievent = $hash->{HELPER}{APIEVENT};
  2644. my $apivideostm = $hash->{HELPER}{APIVIDEOSTM};
  2645. my $apiaudiostm = $hash->{HELPER}{APIAUDIOSTM};
  2646. my $apivideostms = $hash->{HELPER}{APIVIDEOSTMS};
  2647. my $apistm = $hash->{HELPER}{APISTM};
  2648. my $apihm = $hash->{HELPER}{APIHM};
  2649. my $apilog = $hash->{HELPER}{APILOG};
  2650. my $proto = $hash->{PROTOCOL};
  2651. my $url;
  2652. my $param;
  2653. # API-Pfade und MaxVersions ermitteln
  2654. Log3($name, 4, "$name - ####################################################");
  2655. Log3($name, 4, "$name - ### start cam operation $hash->{OPMODE} ");
  2656. Log3($name, 4, "$name - ####################################################");
  2657. Log3($name, 4, "$name - --- Begin Function SSCam_getapisites nonblocking ---");
  2658. if ($hash->{HELPER}{APIPARSET}) {
  2659. # API-Hashwerte sind bereits gesetzt -> Abruf überspringen
  2660. Log3($name, 4, "$name - API hashvalues already set - ignore get apisites");
  2661. return SSCam_checksid($hash);
  2662. }
  2663. my $httptimeout = AttrVal($name,"httptimeout",4);
  2664. Log3($name, 5, "$name - HTTP-Call will be done with httptimeout-Value: $httptimeout s");
  2665. # URL zur Abfrage der Eigenschaften der API's
  2666. $url = "$proto://$serveraddr:$serverport/webapi/query.cgi?api=$apiinfo&method=Query&version=1&query=$apiauth,$apiextrec,$apicam,$apitakesnap,$apiptz,$apipreset,$apisvsinfo,$apicamevent,$apievent,$apivideostm,$apiextevt,$apistm,$apihm,$apilog,$apiaudiostm,$apivideostms";
  2667. Log3($name, 4, "$name - Call-Out now: $url");
  2668. $param = {
  2669. url => $url,
  2670. timeout => $httptimeout,
  2671. hash => $hash,
  2672. method => "GET",
  2673. header => "Accept: application/json",
  2674. callback => \&SSCam_getapisites_parse
  2675. };
  2676. HttpUtils_NonblockingGet ($param);
  2677. }
  2678. ####################################################################################
  2679. # Auswertung Abruf apisites
  2680. ####################################################################################
  2681. sub SSCam_getapisites_parse ($) {
  2682. my ($param, $err, $myjson) = @_;
  2683. my $hash = $param->{hash};
  2684. my $name = $hash->{NAME};
  2685. my $serveraddr = $hash->{SERVERADDR};
  2686. my $serverport = $hash->{SERVERPORT};
  2687. my $apiauth = $hash->{HELPER}{APIAUTH};
  2688. my $apiextrec = $hash->{HELPER}{APIEXTREC};
  2689. my $apiextevt = $hash->{HELPER}{APIEXTEVT};
  2690. my $apicam = $hash->{HELPER}{APICAM};
  2691. my $apitakesnap = $hash->{HELPER}{APISNAPSHOT};
  2692. my $apiptz = $hash->{HELPER}{APIPTZ};
  2693. my $apipreset = $hash->{HELPER}{APIPRESET};
  2694. my $apisvsinfo = $hash->{HELPER}{APISVSINFO};
  2695. my $apicamevent = $hash->{HELPER}{APICAMEVENT};
  2696. my $apievent = $hash->{HELPER}{APIEVENT};
  2697. my $apivideostm = $hash->{HELPER}{APIVIDEOSTM};
  2698. my $apiaudiostm = $hash->{HELPER}{APIAUDIOSTM};
  2699. my $apivideostms = $hash->{HELPER}{APIVIDEOSTMS};
  2700. my $apistm = $hash->{HELPER}{APISTM};
  2701. my $apihm = $hash->{HELPER}{APIHM};
  2702. my $apilog = $hash->{HELPER}{APILOG};
  2703. my ($apicammaxver,$apicampath);
  2704. if ($err ne "") {
  2705. # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
  2706. Log3($name, 2, "$name - error while requesting ".$param->{url}." - $err");
  2707. readingsSingleUpdate($hash, "Error", $err, 1);
  2708. # ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
  2709. $hash->{HELPER}{ACTIVE} = "off";
  2710. if (AttrVal($name,"debugactivetoken",0)) {
  2711. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  2712. }
  2713. return;
  2714. } elsif ($myjson ne "") {
  2715. # Evaluiere ob Daten im JSON-Format empfangen wurden
  2716. ($hash, my $success) = SSCam_evaljson($hash,$myjson);
  2717. unless ($success) {
  2718. Log3($name, 4, "$name - Data returned: $myjson");
  2719. $hash->{HELPER}{ACTIVE} = "off";
  2720. if (AttrVal($name,"debugactivetoken",0)) {
  2721. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  2722. }
  2723. return;
  2724. }
  2725. my $data = decode_json($myjson);
  2726. # Logausgabe decodierte JSON Daten
  2727. Log3($name, 5, "$name - JSON returned: ". Dumper $data);
  2728. $success = $data->{'success'};
  2729. if ($success) {
  2730. my $logstr;
  2731. # Pfad und Maxversion von "SYNO.API.Auth" ermitteln
  2732. my $apiauthpath = $data->{'data'}->{$apiauth}->{'path'};
  2733. $apiauthpath =~ tr/_//d if (defined($apiauthpath));
  2734. my $apiauthmaxver = $data->{'data'}->{$apiauth}->{'maxVersion'};
  2735. $logstr = defined($apiauthpath) ? "Path of $apiauth selected: $apiauthpath" : "Path of $apiauth undefined - Surveillance Station may be stopped";
  2736. Log3($name, 4, "$name - $logstr");
  2737. $logstr = defined($apiauthmaxver) ? "MaxVersion of $apiauth selected: $apiauthmaxver" : "MaxVersion of $apiauth undefined - Surveillance Station may be stopped";
  2738. Log3($name, 4, "$name - $logstr");
  2739. # Pfad und Maxversion von "SYNO.SurveillanceStation.ExternalRecording" ermitteln
  2740. my $apiextrecpath = $data->{'data'}->{$apiextrec}->{'path'};
  2741. $apiextrecpath =~ tr/_//d if (defined($apiextrecpath));
  2742. my $apiextrecmaxver = $data->{'data'}->{$apiextrec}->{'maxVersion'};
  2743. $logstr = defined($apiextrecpath) ? "Path of $apiextrec selected: $apiextrecpath" : "Path of $apiextrec undefined - Surveillance Station may be stopped";
  2744. Log3($name, 4, "$name - $logstr");
  2745. $logstr = defined($apiextrecmaxver) ? "MaxVersion of $apiextrec selected: $apiextrecmaxver" : "MaxVersion of $apiextrec undefined - Surveillance Station may be stopped";
  2746. Log3($name, 4, "$name - $logstr");
  2747. # Pfad und Maxversion von "SYNO.SurveillanceStation.Camera" ermitteln
  2748. $apicampath = $data->{'data'}->{$apicam}->{'path'};
  2749. $apicampath =~ tr/_//d if (defined($apicampath));
  2750. $apicammaxver = $data->{'data'}->{$apicam}->{'maxVersion'};
  2751. $logstr = defined($apicampath) ? "Path of $apicam selected: $apicampath" : "Path of $apicam undefined - Surveillance Station may be stopped";
  2752. Log3($name, 4, "$name - $logstr");
  2753. $logstr = defined($apiextrecmaxver) ? "MaxVersion of $apicam: $apicammaxver" : "MaxVersion of $apicam undefined - Surveillance Station may be stopped";
  2754. Log3($name, 4, "$name - $logstr");
  2755. # Pfad und Maxversion von "SYNO.SurveillanceStation.SnapShot" ermitteln
  2756. my $apitakesnappath = $data->{'data'}->{$apitakesnap}->{'path'};
  2757. $apitakesnappath =~ tr/_//d if (defined($apitakesnappath));
  2758. my $apitakesnapmaxver = $data->{'data'}->{$apitakesnap}->{'maxVersion'};
  2759. $logstr = defined($apitakesnappath) ? "Path of $apitakesnap selected: $apitakesnappath" : "Path of $apitakesnap undefined - Surveillance Station may be stopped";
  2760. Log3($name, 4, "$name - $logstr");
  2761. $logstr = defined($apitakesnapmaxver) ? "MaxVersion of $apitakesnap: $apitakesnapmaxver" : "MaxVersion of $apitakesnap undefined - Surveillance Station may be stopped";
  2762. Log3($name, 4, "$name - $logstr");
  2763. # Pfad und Maxversion von "SYNO.SurveillanceStation.PTZ" ermitteln
  2764. my $apiptzpath = $data->{'data'}->{$apiptz}->{'path'};
  2765. $apiptzpath =~ tr/_//d if (defined($apiptzpath));
  2766. my $apiptzmaxver = $data->{'data'}->{$apiptz}->{'maxVersion'};
  2767. $logstr = defined($apiptzpath) ? "Path of $apiptz selected: $apiptzpath" : "Path of $apiptz undefined - Surveillance Station may be stopped";
  2768. Log3($name, 4, "$name - $logstr");
  2769. $logstr = defined($apiptzmaxver) ? "MaxVersion of $apiptz: $apiptzmaxver" : "MaxVersion of $apiptz undefined - Surveillance Station may be stopped";
  2770. Log3($name, 4, "$name - $logstr");
  2771. # Pfad und Maxversion von "SYNO.SurveillanceStation.PTZ.Preset" ermitteln
  2772. my $apipresetpath = $data->{'data'}->{$apipreset}->{'path'};
  2773. $apipresetpath =~ tr/_//d if (defined($apipresetpath));
  2774. my $apipresetmaxver = $data->{'data'}->{$apipreset}->{'maxVersion'};
  2775. $logstr = defined($apipresetpath) ? "Path of $apipreset selected: $apipresetpath" : "Path of $apipreset undefined - Surveillance Station may be stopped";
  2776. Log3($name, 4, "$name - $logstr");
  2777. $logstr = defined($apipresetmaxver) ? "MaxVersion of $apipreset: $apipresetmaxver" : "MaxVersion of $apipreset undefined - Surveillance Station may be stopped";
  2778. Log3($name, 4, "$name - $logstr");
  2779. # Pfad und Maxversion von "SYNO.SurveillanceStation.Info" ermitteln
  2780. my $apisvsinfopath = $data->{'data'}->{$apisvsinfo}->{'path'};
  2781. $apisvsinfopath =~ tr/_//d if (defined($apisvsinfopath));
  2782. my $apisvsinfomaxver = $data->{'data'}->{$apisvsinfo}->{'maxVersion'};
  2783. $logstr = defined($apisvsinfopath) ? "Path of $apisvsinfo selected: $apisvsinfopath" : "Path of $apisvsinfo undefined - Surveillance Station may be stopped";
  2784. Log3($name, 4, "$name - $logstr");
  2785. $logstr = defined($apisvsinfomaxver) ? "MaxVersion of $apisvsinfo: $apisvsinfomaxver" : "MaxVersion of $apisvsinfo undefined - Surveillance Station may be stopped";
  2786. Log3($name, 4, "$name - $logstr");
  2787. # Pfad und Maxversion von "SYNO.Surveillance.Camera.Event" ermitteln
  2788. my $apicameventpath = $data->{'data'}->{$apicamevent}->{'path'};
  2789. $apicameventpath =~ tr/_//d if (defined($apicameventpath));
  2790. my $apicameventmaxver = $data->{'data'}->{$apicamevent}->{'maxVersion'};
  2791. $logstr = defined($apicameventpath) ? "Path of $apicamevent selected: $apicameventpath" : "Path of $apicamevent undefined - Surveillance Station may be stopped";
  2792. Log3($name, 4, "$name - $logstr");
  2793. $logstr = defined($apicameventmaxver) ? "MaxVersion of $apicamevent: $apicameventmaxver" : "MaxVersion of $apicamevent undefined - Surveillance Station may be stopped";
  2794. Log3($name, 4, "$name - $logstr");
  2795. # Pfad und Maxversion von "SYNO.Surveillance.Event" ermitteln
  2796. my $apieventpath = $data->{'data'}->{$apievent}->{'path'};
  2797. $apieventpath =~ tr/_//d if (defined($apieventpath));
  2798. my $apieventmaxver = $data->{'data'}->{$apievent}->{'maxVersion'};
  2799. $logstr = defined($apieventpath) ? "Path of $apievent selected: $apieventpath" : "Path of $apievent undefined - Surveillance Station may be stopped";
  2800. Log3($name, 4, "$name - $logstr");
  2801. $logstr = defined($apieventmaxver) ? "MaxVersion of $apievent: $apieventmaxver" : "MaxVersion of $apievent undefined - Surveillance Station may be stopped";
  2802. Log3($name, 4, "$name - $logstr");
  2803. # Pfad und Maxversion von "SYNO.Surveillance.VideoStream" ermitteln
  2804. my $apivideostmpath = $data->{'data'}->{$apivideostm}->{'path'};
  2805. $apivideostmpath =~ tr/_//d if (defined($apivideostmpath));
  2806. my $apivideostmmaxver = $data->{'data'}->{$apivideostm}->{'maxVersion'};
  2807. $logstr = defined($apivideostmpath) ? "Path of $apivideostm selected: $apivideostmpath" : "Path of $apivideostm undefined - Surveillance Station may be stopped";
  2808. Log3($name, 4, "$name - $logstr");
  2809. $logstr = defined($apivideostmmaxver) ? "MaxVersion of $apivideostm: $apivideostmmaxver" : "MaxVersion of $apivideostm undefined - Surveillance Station may be stopped";
  2810. Log3($name, 4, "$name - $logstr");
  2811. # Pfad und Maxversion von "SYNO.SurveillanceStation.ExternalEvent" ermitteln
  2812. my $apiextevtpath = $data->{'data'}->{$apiextevt}->{'path'};
  2813. $apiextevtpath =~ tr/_//d if (defined($apiextevtpath));
  2814. my $apiextevtmaxver = $data->{'data'}->{$apiextevt}->{'maxVersion'};
  2815. $logstr = defined($apiextevtpath) ? "Path of $apiextevt selected: $apiextevtpath" : "Path of $apiextevt undefined - Surveillance Station may be stopped";
  2816. Log3($name, 4, "$name - $logstr");
  2817. $logstr = defined($apiextevtmaxver) ? "MaxVersion of $apiextevt selected: $apiextevtmaxver" : "MaxVersion of $apiextevt undefined - Surveillance Station may be stopped";
  2818. Log3($name, 4, "$name - $logstr");
  2819. # Pfad und Maxversion von "SYNO.SurveillanceStation.Streaming" ermitteln
  2820. my $apistmpath = $data->{'data'}->{$apistm}->{'path'};
  2821. $apistmpath =~ tr/_//d if (defined($apistmpath));
  2822. my $apistmmaxver = $data->{'data'}->{$apistm}->{'maxVersion'};
  2823. $logstr = defined($apistmpath) ? "Path of $apistm selected: $apistmpath" : "Path of $apistm undefined - Surveillance Station may be stopped";
  2824. Log3($name, 4, "$name - $logstr");
  2825. $logstr = defined($apistmmaxver) ? "MaxVersion of $apistm selected: $apistmmaxver" : "MaxVersion of $apistm undefined - Surveillance Station may be stopped";
  2826. Log3($name, 4, "$name - $logstr");
  2827. # Pfad und Maxversion von "SYNO.SurveillanceStation.HomeMode" ermitteln
  2828. my $apihmpath = $data->{'data'}->{$apihm}->{'path'};
  2829. $apihmpath =~ tr/_//d if (defined($apihmpath));
  2830. my $apihmmaxver = $data->{'data'}->{$apihm}->{'maxVersion'};
  2831. $logstr = defined($apihmpath) ? "Path of $apihm selected: $apihmpath" : "Path of $apihm undefined - Surveillance Station may be stopped";
  2832. Log3($name, 4, "$name - $logstr");
  2833. $logstr = defined($apihmmaxver) ? "MaxVersion of $apihm selected: $apihmmaxver" : "MaxVersion of $apihm undefined - Surveillance Station may be stopped";
  2834. Log3($name, 4, "$name - $logstr");
  2835. # Pfad und Maxversion von "SYNO.SurveillanceStation.Log" ermitteln
  2836. my $apilogpath = $data->{'data'}->{$apilog}->{'path'};
  2837. $apilogpath =~ tr/_//d if (defined($apilogpath));
  2838. my $apilogmaxver = $data->{'data'}->{$apilog}->{'maxVersion'};
  2839. $logstr = defined($apilogpath) ? "Path of $apilog selected: $apilogpath" : "Path of $apilog undefined - Surveillance Station may be stopped";
  2840. Log3($name, 4, "$name - $logstr");
  2841. $logstr = defined($apilogmaxver) ? "MaxVersion of $apilog selected: $apilogmaxver" : "MaxVersion of $apilog undefined - Surveillance Station may be stopped";
  2842. Log3($name, 4, "$name - $logstr");
  2843. # Pfad und Maxversion von "SYNO.SurveillanceStation.AudioStream" ermitteln
  2844. my $apiaudiostmpath = $data->{'data'}->{$apiaudiostm}->{'path'};
  2845. $apiaudiostmpath =~ tr/_//d if (defined($apiaudiostmpath));
  2846. my $apiaudiostmmaxver = $data->{'data'}->{$apiaudiostm}->{'maxVersion'};
  2847. $logstr = defined($apiaudiostmpath) ? "Path of $apiaudiostm selected: $apiaudiostmpath" : "Path of $apiaudiostm undefined - Surveillance Station may be stopped";
  2848. Log3($name, 4, "$name - $logstr");
  2849. $logstr = defined($apiaudiostmmaxver) ? "MaxVersion of $apiaudiostm selected: $apiaudiostmmaxver" : "MaxVersion of $apiaudiostm undefined - Surveillance Station may be stopped";
  2850. Log3($name, 4, "$name - $logstr");
  2851. # Pfad und Maxversion von "SYNO.SurveillanceStation.VideoStream" ermitteln
  2852. my $apivideostmspath = $data->{'data'}->{$apivideostms}->{'path'};
  2853. $apivideostmspath =~ tr/_//d if (defined($apivideostmspath));
  2854. my $apivideostmsmaxver = $data->{'data'}->{$apivideostms}->{'maxVersion'};
  2855. $logstr = defined($apivideostmspath) ? "Path of $apivideostms selected: $apivideostmspath" : "Path of $apivideostms undefined - Surveillance Station may be stopped";
  2856. Log3($name, 4, "$name - $logstr");
  2857. $logstr = defined($apivideostmsmaxver) ? "MaxVersion of $apivideostms selected: $apivideostmsmaxver" : "MaxVersion of $apivideostms undefined - Surveillance Station may be stopped";
  2858. Log3($name, 4, "$name - $logstr");
  2859. # aktuelle oder simulierte SVS-Version für Fallentscheidung setzen
  2860. no warnings 'uninitialized';
  2861. my $major = $hash->{HELPER}{SVSVERSION}{MAJOR};
  2862. my $minor = $hash->{HELPER}{SVSVERSION}{MINOR};
  2863. my $small = $hash->{HELPER}{SVSVERSION}{SMALL};
  2864. my $build = $hash->{HELPER}{SVSVERSION}{BUILD};
  2865. my $actvs = $major.$minor.$small.$build;
  2866. my $avsc = $major.$minor.$small; # Variable zum Version Kompatibilitätscheck
  2867. Log3($name, 4, "$name - installed SVS version is: $actvs");
  2868. use warnings;
  2869. if(AttrVal($name,"simu_SVSversion",0)) {
  2870. my @vl = split (/\.|-/,AttrVal($name, "simu_SVSversion", ""));
  2871. $actvs = $vl[0];
  2872. $actvs .= $vl[1];
  2873. $actvs .= ($vl[2] =~ /\d/)?$vl[2]."xxxx":$vl[2];
  2874. $actvs .= "-simu";
  2875. }
  2876. # Downgrades für nicht kompatible API-Versionen
  2877. # hier nur nutzen wenn API zentral downgraded werden soll
  2878. # In den neueren API-Upgrades werden nur einzelne Funktionen auf eine höhere API-Version gezogen
  2879. # -> diese Steuerung erfolgt in den einzelnen Funktionsaufrufen in SSCam_camop
  2880. Log3($name, 4, "$name - ------- Begin of adaption section -------");
  2881. #$apiptzmaxver = 4;
  2882. #Log3($name, 4, "$name - MaxVersion of $apiptz adapted to: $apiptzmaxver");
  2883. #$apicammaxver = 8;
  2884. #Log3($name, 4, "$name - MaxVersion of $apicam adapted to: $apicammaxver");
  2885. Log3($name, 4, "$name - ------- End of adaption section -------");
  2886. # Simulation anderer SVS-Versionen
  2887. Log3($name, 4, "$name - ------- Begin of simulation section -------");
  2888. if (AttrVal($name, "simu_SVSversion", undef)) {
  2889. Log3($name, 4, "$name - SVS version $actvs will be simulated");
  2890. if ($actvs =~ /^71/) {
  2891. $apicammaxver = 8;
  2892. Log3($name, 4, "$name - MaxVersion of $apicam adapted to: $apicammaxver");
  2893. $apiauthmaxver = 4;
  2894. Log3($name, 4, "$name - MaxVersion of $apiauth adapted to: $apiauthmaxver");
  2895. $apiextrecmaxver = 2;
  2896. Log3($name, 4, "$name - MaxVersion of $apiextrec adapted to: $apiextrecmaxver");
  2897. $apiptzmaxver = 4;
  2898. Log3($name, 4, "$name - MaxVersion of $apiptz adapted to: $apiptzmaxver");
  2899. } elsif ($actvs =~ /^72/) {
  2900. $apicammaxver = 8;
  2901. Log3($name, 4, "$name - MaxVersion of $apicam adapted to: $apicammaxver");
  2902. $apiauthmaxver = 6;
  2903. Log3($name, 4, "$name - MaxVersion of $apiauth adapted to: $apiauthmaxver");
  2904. $apiextrecmaxver = 3;
  2905. Log3($name, 4, "$name - MaxVersion of $apiextrec adapted to: $apiextrecmaxver");
  2906. $apiptzmaxver = 5;
  2907. Log3($name, 4, "$name - MaxVersion of $apiptz adapted to: $apiptzmaxver");
  2908. } elsif ($actvs =~ /^800/) {
  2909. $apicammaxver = 9;
  2910. Log3($name, 4, "$name - MaxVersion of $apicam adapted to: $apicammaxver");
  2911. $apiauthmaxver = 6;
  2912. Log3($name, 4, "$name - MaxVersion of $apiauth adapted to: $apiauthmaxver");
  2913. $apiextrecmaxver = 3;
  2914. Log3($name, 4, "$name - MaxVersion of $apiextrec adapted to: $apiextrecmaxver");
  2915. $apiptzmaxver = 5;
  2916. Log3($name, 4, "$name - MaxVersion of $apiptz adapted to: $apiptzmaxver");
  2917. } elsif ($actvs =~ /^815/) {
  2918. $apicammaxver = 9;
  2919. Log3($name, 4, "$name - MaxVersion of $apicam adapted to: $apicammaxver");
  2920. $apiauthmaxver = 6;
  2921. Log3($name, 4, "$name - MaxVersion of $apiauth adapted to: $apiauthmaxver");
  2922. $apiextrecmaxver = 3;
  2923. Log3($name, 4, "$name - MaxVersion of $apiextrec adapted to: $apiextrecmaxver");
  2924. $apiptzmaxver = 5;
  2925. Log3($name, 4, "$name - MaxVersion of $apiptz adapted to: $apiptzmaxver");
  2926. } elsif ($actvs =~ /^820/) {
  2927. # ab API v2.8 kein "SYNO.SurveillanceStation.VideoStream", "SYNO.SurveillanceStation.AudioStream",
  2928. # "SYNO.SurveillanceStation.Streaming" mehr enthalten
  2929. $apivideostmsmaxver = 0;
  2930. Log3($name, 4, "$name - MaxVersion of $apivideostms adapted to: $apivideostmsmaxver");
  2931. $apiaudiostmmaxver = 0;
  2932. Log3($name, 4, "$name - MaxVersion of $apiaudiostm adapted to: $apiaudiostmmaxver");
  2933. }
  2934. } else {
  2935. Log3($name, 4, "$name - no simulations done !");
  2936. }
  2937. Log3($name, 4, "$name - ------- End of simulation section -------");
  2938. # ermittelte Werte in $hash einfügen
  2939. $hash->{HELPER}{APIAUTHPATH} = $apiauthpath;
  2940. $hash->{HELPER}{APIAUTHMAXVER} = $apiauthmaxver;
  2941. $hash->{HELPER}{APIEXTRECPATH} = $apiextrecpath;
  2942. $hash->{HELPER}{APIEXTRECMAXVER} = $apiextrecmaxver;
  2943. $hash->{HELPER}{APICAMPATH} = $apicampath;
  2944. $hash->{HELPER}{APICAMMAXVER} = $apicammaxver;
  2945. $hash->{HELPER}{APITAKESNAPPATH} = $apitakesnappath;
  2946. $hash->{HELPER}{APITAKESNAPMAXVER} = $apitakesnapmaxver;
  2947. $hash->{HELPER}{APIPTZPATH} = $apiptzpath;
  2948. $hash->{HELPER}{APIPTZMAXVER} = $apiptzmaxver;
  2949. $hash->{HELPER}{APIPRESETPATH} = $apipresetpath;
  2950. $hash->{HELPER}{APIPRESETMAXVER} = $apipresetmaxver;
  2951. $hash->{HELPER}{APISVSINFOPATH} = $apisvsinfopath;
  2952. $hash->{HELPER}{APISVSINFOMAXVER} = $apisvsinfomaxver;
  2953. $hash->{HELPER}{APICAMEVENTPATH} = $apicameventpath;
  2954. $hash->{HELPER}{APICAMEVENTMAXVER} = $apicameventmaxver;
  2955. $hash->{HELPER}{APIEVENTPATH} = $apieventpath;
  2956. $hash->{HELPER}{APIEVENTMAXVER} = $apieventmaxver;
  2957. $hash->{HELPER}{APIVIDEOSTMPATH} = $apivideostmpath;
  2958. $hash->{HELPER}{APIVIDEOSTMMAXVER} = $apivideostmmaxver;
  2959. $hash->{HELPER}{APIAUDIOSTMPATH} = $apiaudiostmpath?$apiaudiostmpath:"undefinded";
  2960. $hash->{HELPER}{APIAUDIOSTMMAXVER} = $apiaudiostmmaxver?$apiaudiostmmaxver:0;
  2961. $hash->{HELPER}{APIEXTEVTPATH} = $apiextevtpath;
  2962. $hash->{HELPER}{APIEXTEVTMAXVER} = $apiextevtmaxver;
  2963. $hash->{HELPER}{APISTMPATH} = $apistmpath;
  2964. $hash->{HELPER}{APISTMMAXVER} = $apistmmaxver;
  2965. $hash->{HELPER}{APIHMPATH} = $apihmpath;
  2966. $hash->{HELPER}{APIHMMAXVER} = $apihmmaxver;
  2967. $hash->{HELPER}{APILOGPATH} = $apilogpath;
  2968. $hash->{HELPER}{APILOGMAXVER} = $apilogmaxver;
  2969. $hash->{HELPER}{APIVIDEOSTMSPATH} = $apivideostmspath?$apivideostmspath:"undefinded";
  2970. $hash->{HELPER}{APIVIDEOSTMSMAXVER} = $apivideostmsmaxver?$apivideostmsmaxver:0;
  2971. readingsBeginUpdate($hash);
  2972. readingsBulkUpdate($hash,"Errorcode","none");
  2973. readingsBulkUpdate($hash,"Error","none");
  2974. readingsEndUpdate($hash,1);
  2975. # API Hash values sind gesetzt
  2976. $hash->{HELPER}{APIPARSET} = 1;
  2977. } else {
  2978. my $error = "couldn't call API-Infosite";
  2979. readingsBeginUpdate($hash);
  2980. readingsBulkUpdate($hash,"Errorcode","none");
  2981. readingsBulkUpdate($hash,"Error",$error);
  2982. readingsEndUpdate($hash, 1);
  2983. Log3($name, 2, "$name - ERROR - the API-Query couldn't be executed successfully");
  2984. # ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
  2985. $hash->{HELPER}{ACTIVE} = "off";
  2986. if (AttrVal($name,"debugactivetoken",0)) {
  2987. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  2988. }
  2989. return;
  2990. }
  2991. }
  2992. return SSCam_checksid($hash);
  2993. }
  2994. #############################################################################################
  2995. # Check ob Session ID gesetzt ist - ggf. login
  2996. #############################################################################################
  2997. sub SSCam_checksid ($) {
  2998. my ($hash) = @_;
  2999. my $name = $hash->{NAME};
  3000. my $subref;
  3001. if(SSCam_IsModelCam($hash)) {
  3002. # Folgefunktion wenn Cam-Device
  3003. $subref = "SSCam_getcamid";
  3004. } else {
  3005. # Folgefunktion wenn SVS-Device
  3006. $subref = "SSCam_camop";
  3007. }
  3008. # SID holen bzw. login
  3009. my $sid = $hash->{HELPER}{SID};
  3010. if(!$sid) {
  3011. Log3($name, 3, "$name - no session ID found - get new one");
  3012. SSCam_login($hash,$subref);
  3013. return;
  3014. }
  3015. if(SSCam_IsModelCam($hash)) {
  3016. # Normalverarbeitung für Cams
  3017. return SSCam_getcamid($hash);
  3018. } else {
  3019. # Sprung zu SSCam_camop wenn SVS Device
  3020. return SSCam_camop($hash);
  3021. }
  3022. }
  3023. #############################################################################################
  3024. # Abruf der installierten Cams
  3025. #############################################################################################
  3026. sub SSCam_getcamid ($) {
  3027. my ($hash) = @_;
  3028. my $name = $hash->{NAME};
  3029. my $serveraddr = $hash->{SERVERADDR};
  3030. my $serverport = $hash->{SERVERPORT};
  3031. my $apicam = $hash->{HELPER}{APICAM};
  3032. my $apicampath = $hash->{HELPER}{APICAMPATH};
  3033. my $apicammaxver = $hash->{HELPER}{APICAMMAXVER};
  3034. my $sid = $hash->{HELPER}{SID};
  3035. my $proto = $hash->{PROTOCOL};
  3036. my $url;
  3037. # die Kamera-Id wird aus dem Kameranamen (Surveillance Station) ermittelt
  3038. Log3($name, 4, "$name - --- Begin Function SSCam_getcamid nonblocking ---");
  3039. if ($hash->{CAMID}) {
  3040. # Camid ist bereits ermittelt -> Abruf überspringen
  3041. Log3($name, 4, "$name - CAMID already set - ignore get camid");
  3042. return SSCam_camop($hash);
  3043. }
  3044. my $httptimeout = AttrVal($name,"httptimeout", 4);
  3045. Log3($name, 5, "$name - HTTP-Call will be done with httptimeout-Value: $httptimeout s");
  3046. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=List&basic=true&streamInfo=true&camStm=true&_sid=\"$sid\"";
  3047. if ($apicammaxver >= 9) {
  3048. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=\"List\"&basic=true&streamInfo=true&camStm=0&_sid=\"$sid\"";
  3049. }
  3050. Log3($name, 4, "$name - Call-Out now: $url");
  3051. my $param = {
  3052. url => $url,
  3053. timeout => $httptimeout,
  3054. hash => $hash,
  3055. method => "GET",
  3056. header => "Accept: application/json",
  3057. callback => \&SSCam_getcamid_parse
  3058. };
  3059. HttpUtils_NonblockingGet($param);
  3060. }
  3061. #############################################################################################
  3062. # Auswertung installierte Cams, Selektion Cam , Ausführung Operation
  3063. #############################################################################################
  3064. sub SSCam_getcamid_parse ($) {
  3065. my ($param, $err, $myjson) = @_;
  3066. my $hash = $param->{hash};
  3067. my $name = $hash->{NAME};
  3068. my $camname = $hash->{CAMNAME};
  3069. my $apicammaxver = $hash->{HELPER}{APICAMMAXVER};
  3070. my ($data,$success,$error,$errorcode,$camid);
  3071. my ($i,$n,$id);
  3072. my %allcams;
  3073. if ($err ne "") {
  3074. # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
  3075. Log3($name, 2, "$name - error while requesting ".$param->{url}." - $err");
  3076. readingsSingleUpdate($hash, "Error", $err, 1);
  3077. return SSCam_login($hash,'SSCam_getapisites');
  3078. } elsif ($myjson ne "") {
  3079. # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
  3080. # evaluiere ob Daten im JSON-Format empfangen wurden, Achtung: sehr viele Daten mit verbose=5
  3081. ($hash, $success) = SSCam_evaljson($hash,$myjson);
  3082. unless ($success) {
  3083. Log3($name, 4, "$name - Data returned: ".$myjson);
  3084. $hash->{HELPER}{ACTIVE} = "off";
  3085. if (AttrVal($name,"debugactivetoken",0)) {
  3086. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  3087. }
  3088. return;
  3089. }
  3090. $data = decode_json($myjson);
  3091. # lesbare Ausgabe der decodierten JSON-Daten
  3092. Log3($name, 5, "$name - JSON returned: ". Dumper $data);
  3093. $success = $data->{'success'};
  3094. if ($success) {
  3095. # die Liste aller Kameras konnte ausgelesen werden
  3096. $i = 0;
  3097. # Namen aller installierten Kameras mit Id's in Assoziatives Array einlesen
  3098. %allcams = ();
  3099. while ($data->{'data'}->{'cameras'}->[$i]) {
  3100. if ($apicammaxver <= 8) {
  3101. $n = $data->{'data'}->{'cameras'}->[$i]->{'name'};
  3102. } else {
  3103. $n = $data->{'data'}->{'cameras'}->[$i]->{'newName'}; # Änderung ab SVS 8.0.0
  3104. }
  3105. $id = $data->{'data'}->{'cameras'}->[$i]->{'id'};
  3106. $allcams{"$n"} = "$id";
  3107. $i += 1;
  3108. }
  3109. # Ist der gesuchte Kameraname im Hash enhalten (in SVS eingerichtet ?)
  3110. if (exists($allcams{$camname})) {
  3111. $camid = $allcams{$camname};
  3112. # in hash eintragen
  3113. $hash->{CAMID} = $camid;
  3114. # Logausgabe
  3115. Log3($name, 4, "$name - Detection Camid successful - $camname ID: $camid");
  3116. } else {
  3117. # Kameraname nicht gefunden, id = ""
  3118. # Setreading
  3119. readingsBeginUpdate($hash);
  3120. readingsBulkUpdate($hash,"Errorcode","none");
  3121. readingsBulkUpdate($hash,"Error","Camera(ID) not found in Surveillance Station");
  3122. readingsEndUpdate($hash, 1);
  3123. # Logausgabe
  3124. Log3($name, 2, "$name - ERROR - Cameraname $camname wasn't found in Surveillance Station. Check Userrights, Cameraname and Spelling");
  3125. $hash->{HELPER}{ACTIVE} = "off";
  3126. if (AttrVal($name,"debugactivetoken",0)) {
  3127. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  3128. }
  3129. return;
  3130. }
  3131. } else {
  3132. # Errorcode aus JSON ermitteln
  3133. $errorcode = $data->{'error'}->{'code'};
  3134. # Fehlertext zum Errorcode ermitteln
  3135. $error = SSCam_experror($hash,$errorcode);
  3136. readingsBeginUpdate($hash);
  3137. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  3138. readingsBulkUpdate($hash,"Error",$error);
  3139. readingsEndUpdate($hash, 1);
  3140. if ($errorcode =~ /(105|401)/) {
  3141. # neue Login-Versuche
  3142. Log3($name, 2, "$name - ERROR - $errorcode - $error -> try new login");
  3143. return SSCam_login($hash,'SSCam_getapisites');
  3144. } else {
  3145. # ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
  3146. $hash->{HELPER}{ACTIVE} = "off";
  3147. if (AttrVal($name,"debugactivetoken",0)) {
  3148. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  3149. }
  3150. Log3($name, 2, "$name - ERROR - ID of Camera $camname couldn't be selected. Errorcode: $errorcode - $error");
  3151. return;
  3152. }
  3153. }
  3154. }
  3155. return SSCam_camop($hash);
  3156. }
  3157. #############################################################################################
  3158. # Ausführung Operation
  3159. #############################################################################################
  3160. sub SSCam_camop ($) {
  3161. my ($hash) = @_;
  3162. my $name = $hash->{NAME};
  3163. my $serveraddr = $hash->{SERVERADDR};
  3164. my $serverport = $hash->{SERVERPORT};
  3165. my $apicam = $hash->{HELPER}{APICAM};
  3166. my $apicampath = $hash->{HELPER}{APICAMPATH};
  3167. my $apicammaxver = $hash->{HELPER}{APICAMMAXVER};
  3168. my $apiextrec = $hash->{HELPER}{APIEXTREC};
  3169. my $apiextrecpath = $hash->{HELPER}{APIEXTRECPATH};
  3170. my $apiextrecmaxver = $hash->{HELPER}{APIEXTRECMAXVER};
  3171. my $apiextevt = $hash->{HELPER}{APIEXTEVT};
  3172. my $apiextevtpath = $hash->{HELPER}{APIEXTEVTPATH};
  3173. my $apiextevtmaxver = $hash->{HELPER}{APIEXTEVTMAXVER};
  3174. my $apitakesnap = $hash->{HELPER}{APISNAPSHOT};
  3175. my $apitakesnappath = $hash->{HELPER}{APITAKESNAPPATH};
  3176. my $apitakesnapmaxver = $hash->{HELPER}{APITAKESNAPMAXVER};
  3177. my $apiptz = $hash->{HELPER}{APIPTZ};
  3178. my $apiptzpath = $hash->{HELPER}{APIPTZPATH};
  3179. my $apiptzmaxver = $hash->{HELPER}{APIPTZMAXVER};
  3180. my $apipreset = $hash->{HELPER}{APIPRESET};
  3181. my $apipresetpath = $hash->{HELPER}{APIPRESETPATH};
  3182. my $apipresetmaxver = $hash->{HELPER}{APIPRESETMAXVER};
  3183. my $apisvsinfo = $hash->{HELPER}{APISVSINFO};
  3184. my $apisvsinfopath = $hash->{HELPER}{APISVSINFOPATH};
  3185. my $apisvsinfomaxver = $hash->{HELPER}{APISVSINFOMAXVER};
  3186. my $apicamevent = $hash->{HELPER}{APICAMEVENT};
  3187. my $apicameventpath = $hash->{HELPER}{APICAMEVENTPATH};
  3188. my $apicameventmaxver = $hash->{HELPER}{APICAMEVENTMAXVER};
  3189. my $apievent = $hash->{HELPER}{APIEVENT};
  3190. my $apieventpath = $hash->{HELPER}{APIEVENTPATH};
  3191. my $apieventmaxver = $hash->{HELPER}{APIEVENTMAXVER};
  3192. my $apivideostm = $hash->{HELPER}{APIVIDEOSTM};
  3193. my $apivideostmpath = $hash->{HELPER}{APIVIDEOSTMPATH};
  3194. my $apivideostmmaxver = $hash->{HELPER}{APIVIDEOSTMMAXVER};
  3195. my $apiaudiostm = $hash->{HELPER}{APIAUDIOSTM};
  3196. my $apiaudiostmpath = $hash->{HELPER}{APIAUDIOSTMPATH};
  3197. my $apiaudiostmmaxver = $hash->{HELPER}{APIAUDIOSTMMAXVER};
  3198. my $apistm = $hash->{HELPER}{APISTM};
  3199. my $apistmpath = $hash->{HELPER}{APISTMPATH};
  3200. my $apistmmaxver = $hash->{HELPER}{APISTMMAXVER};
  3201. my $apihm = $hash->{HELPER}{APIHM};
  3202. my $apihmpath = $hash->{HELPER}{APIHMPATH};
  3203. my $apihmmaxver = $hash->{HELPER}{APIHMMAXVER};
  3204. my $apilog = $hash->{HELPER}{APILOG};
  3205. my $apilogpath = $hash->{HELPER}{APILOGPATH};
  3206. my $apilogmaxver = $hash->{HELPER}{APILOGMAXVER};
  3207. my $apivideostms = $hash->{HELPER}{APIVIDEOSTMS};
  3208. my $apivideostmspath = $hash->{HELPER}{APIVIDEOSTMSPATH};
  3209. my $apivideostmsmaxver = $hash->{HELPER}{APIVIDEOSTMSMAXVER};
  3210. my $sid = $hash->{HELPER}{SID};
  3211. my $OpMode = $hash->{OPMODE};
  3212. my $camid = $hash->{CAMID};
  3213. my $proto = $hash->{PROTOCOL};
  3214. my ($exturl,$winname,$attr,$room,$param);
  3215. my ($url,$snapid,$httptimeout,$expmode,$motdetsc);
  3216. Log3($name, 4, "$name - --- Begin Function $OpMode nonblocking ---");
  3217. $httptimeout = AttrVal($name, "httptimeout", 4);
  3218. $httptimeout = $httptimeout+90 if($OpMode =~ /setoptpar|Disable/); # setzen der Optimierungsparameter/Disable dauert lange !
  3219. Log3($name, 5, "$name - HTTP-Call will be done with httptimeout-Value: $httptimeout s");
  3220. if ($OpMode eq "Start") {
  3221. $url = "$proto://$serveraddr:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=start&_sid=\"$sid\"";
  3222. if($apiextrecmaxver >= 3) {
  3223. $url = "$proto://$serveraddr:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraIds=$camid&action=start&_sid=\"$sid\"";
  3224. }
  3225. } elsif ($OpMode eq "Stop") {
  3226. $url = "$proto://$serveraddr:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=stop&_sid=\"$sid\"";
  3227. if($apiextrecmaxver >= 3) {
  3228. $url = "$proto://$serveraddr:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraIds=$camid&action=stop&_sid=\"$sid\"";
  3229. }
  3230. } elsif ($OpMode eq "Snap") {
  3231. # ein Schnappschuß wird ausgelöst
  3232. $url = "$proto://$serveraddr:$serverport/webapi/$apitakesnappath?api=\"$apitakesnap\"&dsId=\"0\"&method=\"TakeSnapshot\"&version=\"$apitakesnapmaxver\"&camId=\"$camid\"&blSave=\"true\"&_sid=\"$sid\"";
  3233. readingsSingleUpdate($hash,"state", "snap", 1);
  3234. readingsSingleUpdate($hash, "LastSnapId", "", 0);
  3235. } elsif ($OpMode eq "getsnapinfo" || $OpMode eq "getsnapgallery") {
  3236. # Informationen über den letzten oder mehrere Schnappschüsse ermitteln
  3237. my $limit = $hash->{HELPER}{SNAPLIMIT};
  3238. my $imgsize = $hash->{HELPER}{SNAPIMGSIZE};
  3239. my $keyword = $hash->{HELPER}{KEYWORD};
  3240. Log3($name,4, "$name - Call getsnapinfo with params: Image numbers => $limit, Image size => $imgsize, Keyword => $keyword");
  3241. $url = "$proto://$serveraddr:$serverport/webapi/$apitakesnappath?api=\"$apitakesnap\"&method=\"List\"&version=\"$apitakesnapmaxver\"&keyword=\"$keyword\"&imgSize=\"$imgsize\"&limit=\"$limit\"&_sid=\"$sid\"";
  3242. } elsif ($OpMode eq "getsnapfilename") {
  3243. # der Filename der aktuellen Schnappschuß-ID wird ermittelt
  3244. $snapid = ReadingsVal("$name", "LastSnapId", " ");
  3245. Log3($name, 4, "$name - Get filename of present Snap-ID $snapid");
  3246. $url = "$proto://$serveraddr:$serverport/webapi/$apitakesnappath?api=\"$apitakesnap\"&method=\"List\"&version=\"$apitakesnapmaxver\"&imgSize=\"0\"&idList=\"$snapid\"&_sid=\"$sid\"";
  3247. } elsif ($OpMode eq "gopreset") {
  3248. # Preset wird angefahren
  3249. $apiptzmaxver = ($apiptzmaxver >= 5)?4:$apiptzmaxver;
  3250. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"GoPreset\"&position=\"$hash->{HELPER}{ALLPRESETS}{$hash->{HELPER}{GOPRESETNAME}}\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3251. } elsif ($OpMode eq "getPresets") {
  3252. # Liste der Presets abrufen
  3253. $url = "$proto://$serveraddr:$serverport/webapi/$apipresetpath?api=\"$apipreset\"&version=\"$apipresetmaxver\"&method=\"Enum\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3254. } elsif ($OpMode eq "piract") {
  3255. # PIR Sensor aktivieren/deaktivieren
  3256. my $piract = $hash->{HELPER}{PIRACT};
  3257. $url = "$proto://$serveraddr:$serverport/webapi/$apicameventpath?api=\"$apicamevent\"&version=\"$apicameventmaxver\"&method=\"PDParamSave\"&keep=true&source=$piract&camId=\"$camid\"&_sid=\"$sid\"";
  3258. } elsif ($OpMode eq "setPreset") {
  3259. # einen Preset setzen
  3260. my $pnumber = $hash->{HELPER}{PNUMBER};
  3261. my $pname = $hash->{HELPER}{PNAME};
  3262. my $pspeed = $hash->{HELPER}{PSPEED};
  3263. if ($pspeed) {
  3264. $url = "$proto://$serveraddr:$serverport/webapi/$apipresetpath?api=\"$apipreset\"&version=\"$apipresetmaxver\"&method=\"SetPreset\"&position=$pnumber&name=\"$pname\"&speed=\"$pspeed\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3265. } else {
  3266. $url = "$proto://$serveraddr:$serverport/webapi/$apipresetpath?api=\"$apipreset\"&version=\"$apipresetmaxver\"&method=\"SetPreset\"&position=$pnumber&name=\"$pname\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3267. }
  3268. } elsif ($OpMode eq "delPreset") {
  3269. # einen Preset löschen
  3270. $url = "$proto://$serveraddr:$serverport/webapi/$apipresetpath?api=\"$apipreset\"&version=\"$apipresetmaxver\"&method=\"DelPreset\"&position=\"$hash->{HELPER}{ALLPRESETS}{$hash->{HELPER}{DELPRESETNAME}}\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3271. } elsif ($OpMode eq "setHome") {
  3272. # aktuelle Position als Home setzen
  3273. if($hash->{HELPER}{SETHOME} eq "---currentPosition---") {
  3274. $url = "$proto://$serveraddr:$serverport/webapi/$apipresetpath?api=\"$apipreset\"&version=\"$apipresetmaxver\"&method=\"SetHome\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3275. } else {
  3276. my $bindpos = $hash->{HELPER}{ALLPRESETS}{$hash->{HELPER}{SETHOME}};
  3277. $url = "$proto://$serveraddr:$serverport/webapi/$apipresetpath?api=\"$apipreset\"&version=\"$apipresetmaxver\"&method=\"SetHome\"&bindPosition=\"$bindpos\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3278. }
  3279. } elsif ($OpMode eq "startTrack") {
  3280. # Object Tracking einschalten
  3281. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"ObjTracking\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3282. } elsif ($OpMode eq "stopTrack") {
  3283. # Object Tracking stoppen
  3284. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"ObjTracking\"&moveType=\"Stop\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3285. } elsif ($OpMode eq "runpatrol") {
  3286. # eine Überwachungstour starten
  3287. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"RunPatrol\"&patrolId=\"$hash->{HELPER}{ALLPATROLS}{$hash->{HELPER}{GOPATROLNAME}}\"&cameraId=\"$camid\"&_sid=\"$sid\"";
  3288. } elsif ($OpMode eq "goabsptz") {
  3289. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"AbsPtz\"&cameraId=\"$camid\"&posX=\"$hash->{HELPER}{GOPTZPOSX}\"&posY=\"$hash->{HELPER}{GOPTZPOSY}\"&_sid=\"$sid\"";
  3290. } elsif ($OpMode eq "movestart") {
  3291. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"Move\"&cameraId=\"$camid\"&direction=\"$hash->{HELPER}{GOMOVEDIR}\"&speed=\"3\"&moveType=\"Start\"&_sid=\"$sid\"";
  3292. } elsif ($OpMode eq "movestop") {
  3293. Log3($name, 4, "$name - Stop Camera $hash->{CAMNAME} moving to direction \"$hash->{HELPER}{GOMOVEDIR}\" now");
  3294. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=\"$apiptz\"&version=\"$apiptzmaxver\"&method=\"Move\"&cameraId=\"$camid\"&direction=\"$hash->{HELPER}{GOMOVEDIR}\"&moveType=\"Stop\"&_sid=\"$sid\"";
  3295. } elsif ($OpMode eq "Enable") {
  3296. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=Enable&cameraIds=$camid&_sid=\"$sid\"";
  3297. if($apicammaxver >= 9) {
  3298. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&version=$apicammaxver&method=\"Enable\"&idList=\"$camid\"&_sid=\"$sid\"";
  3299. }
  3300. } elsif ($OpMode eq "Disable") {
  3301. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=Disable&cameraIds=$camid&_sid=\"$sid\"";
  3302. if($apicammaxver >= 9) {
  3303. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&version=$apicammaxver&method=\"Disable\"&idList=\"$camid\"&_sid=\"$sid\"";
  3304. }
  3305. } elsif ($OpMode eq "sethomemode") {
  3306. my $sw = $hash->{HELPER}{HOMEMODE}; # HomeMode on,off
  3307. $sw = ($sw eq "on")?"true":"false";
  3308. $url = "$proto://$serveraddr:$serverport/webapi/$apihmpath?on=$sw&api=$apihm&method=Switch&version=$apihmmaxver&_sid=\"$sid\"";
  3309. } elsif ($OpMode eq "gethomemodestate") {
  3310. $url = "$proto://$serveraddr:$serverport/webapi/$apihmpath?api=$apihm&method=GetInfo&version=$apihmmaxver&_sid=\"$sid\"";
  3311. } elsif ($OpMode eq "getsvslog") {
  3312. my $sev = $hash->{HELPER}{LISTLOGSEVERITY}?$hash->{HELPER}{LISTLOGSEVERITY}:"";
  3313. my $lim = $hash->{HELPER}{LISTLOGLIMIT}?$hash->{HELPER}{LISTLOGLIMIT}:0;
  3314. my $mco = $hash->{HELPER}{LISTLOGMATCH}?$hash->{HELPER}{LISTLOGMATCH}:"";
  3315. $mco = SSCam_IsModelCam($hash)?$hash->{CAMNAME}:$mco;
  3316. $lim = 1 if(!$hash->{HELPER}{CL}{1}); # Datenabruf im Hintergrund
  3317. $sev = (lc($sev) =~ /error/)?3:(lc($sev) =~ /warning/)?2:(lc($sev) =~ /info/)?1:"";
  3318. no warnings 'uninitialized';
  3319. Log3($name,4, "$name - get logList with params: severity => $hash->{HELPER}{LISTLOGSEVERITY}, limit => $lim, matchcode => $hash->{HELPER}{LISTLOGMATCH}");
  3320. use warnings;
  3321. $url = "$proto://$serveraddr:$serverport/webapi/$apilogpath?api=$apilog&version=\"2\"&method=\"List\"&time2String=\"no\"&level=\"$sev\"&limit=\"$lim\"&keyword=\"$mco\"&_sid=\"$sid\"";
  3322. delete($hash->{HELPER}{LISTLOGSEVERITY});
  3323. delete($hash->{HELPER}{LISTLOGLIMIT});
  3324. delete($hash->{HELPER}{LISTLOGMATCH});
  3325. } elsif ($OpMode eq "getsvsinfo") {
  3326. $url = "$proto://$serveraddr:$serverport/webapi/$apisvsinfopath?api=\"$apisvsinfo\"&version=\"$apisvsinfomaxver\"&method=\"GetInfo\"&_sid=\"$sid\"";
  3327. } elsif ($OpMode eq "setoptpar") {
  3328. my $mirr = $hash->{HELPER}{MIRROR}?$hash->{HELPER}{MIRROR}:ReadingsVal("$name","CamVideoMirror","");
  3329. my $flip = $hash->{HELPER}{FLIP}?$hash->{HELPER}{FLIP}:ReadingsVal("$name","CamVideoFlip","");
  3330. my $rot = $hash->{HELPER}{ROTATE}?$hash->{HELPER}{ROTATE}:ReadingsVal("$name","CamVideoRotate","");
  3331. my $ntp = $hash->{HELPER}{NTPSERV}?$hash->{HELPER}{NTPSERV}:ReadingsVal("$name","CamNTPServer","");
  3332. my $clst = $hash->{HELPER}{CHKLIST}?$hash->{HELPER}{CHKLIST}:"";
  3333. $apicammaxver = ($apicammaxver >= 9)?8:$apicammaxver;
  3334. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&version=\"$apicammaxver\"&method=\"SaveOptimizeParam\"&vdoMirror=$mirr&vdoRotation=$rot&vdoFlip=$flip&timeServer=\"$ntp\"&camParamChkList=$clst&cameraIds=\"$camid\"&_sid=\"$sid\"";
  3335. } elsif ($OpMode eq "Getcaminfo") {
  3336. $apicammaxver = ($apicammaxver >= 9)?8:$apicammaxver;
  3337. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&version=\"$apicammaxver\"&method=\"GetInfo\"&cameraIds=\"$camid\"&deviceOutCap=\"true\"&streamInfo=\"true\"&ptz=\"true\"&basic=\"true\"&camAppInfo=\"true\"&optimize=\"true\"&fisheye=\"true\"&eventDetection=\"true\"&_sid=\"$sid\"";
  3338. } elsif ($OpMode eq "getStmUrlPath") {
  3339. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&version=\"$apicammaxver\"&method=\"GetStmUrlPath\"&cameraIds=\"$camid\"&_sid=\"$sid\"";
  3340. if($apicammaxver >= 9) {
  3341. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&method=\"GetLiveViewPath\"&version=$apicammaxver&idList=\"$camid\"&_sid=\"$sid\"";
  3342. }
  3343. } elsif ($OpMode eq "geteventlist") {
  3344. # Abruf der Events einer Kamera
  3345. $url = "$proto://$serveraddr:$serverport/webapi/$apieventpath?api=\"$apievent\"&version=\"$apieventmaxver\"&method=\"List\"&cameraIds=\"$camid\"&locked=\"0\"&blIncludeSnapshot=\"false\"&reason=\"\"&limit=\"2\"&includeAllCam=\"false\"&_sid=\"$sid\"";
  3346. } elsif ($OpMode eq "Getptzlistpreset") {
  3347. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=$apiptz&version=$apiptzmaxver&method=ListPreset&cameraId=$camid&_sid=\"$sid\"";
  3348. } elsif ($OpMode eq "Getcapabilities") {
  3349. # Capabilities einer Cam werden abgerufen
  3350. $apicammaxver = ($apicammaxver >= 9)?8:$apicammaxver;
  3351. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=\"GetCapabilityByCamId\"&cameraId=$camid&_sid=\"$sid\"";
  3352. } elsif ($OpMode eq "Getptzlistpatrol") {
  3353. # PTZ-ListPatrol werden abgerufen
  3354. $url = "$proto://$serveraddr:$serverport/webapi/$apiptzpath?api=$apiptz&version=$apiptzmaxver&method=ListPatrol&cameraId=$camid&_sid=\"$sid\"";
  3355. } elsif ($OpMode eq "ExpMode") {
  3356. if ($hash->{HELPER}{EXPMODE} eq "auto") {
  3357. $expmode = "0";
  3358. }
  3359. elsif ($hash->{HELPER}{EXPMODE} eq "day") {
  3360. $expmode = "1";
  3361. }
  3362. elsif ($hash->{HELPER}{EXPMODE} eq "night") {
  3363. $expmode = "2";
  3364. }
  3365. $apicammaxver = ($apicammaxver >= 9)?8:$apicammaxver;
  3366. $url = "$proto://$serveraddr:$serverport/webapi/$apicampath?api=\"$apicam\"&version=\"$apicammaxver\"&method=\"SaveOptimizeParam\"&cameraIds=\"$camid\"&expMode=\"$expmode\"&camParamChkList=32&_sid=\"$sid\"";
  3367. } elsif ($OpMode eq "MotDetSc") {
  3368. # Hash für Optionswerte sichern für Logausgabe in Befehlsauswertung
  3369. my %motdetoptions = ();
  3370. if ($hash->{HELPER}{MOTDETSC} eq "disable") {
  3371. $motdetsc = "-1";
  3372. $url = "$proto://$serveraddr:$serverport/webapi/$apicameventpath?api=\"$apicamevent\"&version=\"$apicameventmaxver\"&method=\"MDParamSave\"&camId=\"$camid\"&source=$motdetsc&keep=true&_sid=\"$sid\"";
  3373. } elsif ($hash->{HELPER}{MOTDETSC} eq "camera") {
  3374. $motdetsc = "0";
  3375. $motdetoptions{SENSITIVITY} = $hash->{'HELPER'}{'MOTDETSC_PROP1'} if ($hash->{'HELPER'}{'MOTDETSC_PROP1'});
  3376. $motdetoptions{OBJECTSIZE} = $hash->{'HELPER'}{'MOTDETSC_PROP2'} if ($hash->{'HELPER'}{'MOTDETSC_PROP2'});
  3377. $motdetoptions{PERCENTAGE} = $hash->{'HELPER'}{'MOTDETSC_PROP3'} if ($hash->{'HELPER'}{'MOTDETSC_PROP3'});
  3378. $url = "$proto://$serveraddr:$serverport/webapi/$apicameventpath?api=\"$apicamevent\"&version=\"$apicameventmaxver\"&method=\"MDParamSave\"&camId=\"$camid\"&source=$motdetsc&_sid=\"$sid\"";
  3379. if ($hash->{HELPER}{MOTDETSC_PROP1} || $hash->{HELPER}{MOTDETSC_PROP2} || $hash->{HELPER}{MOTDETSC_PROP13}) {
  3380. # umschalten und neue Werte setzen
  3381. $url .= "&keep=false";
  3382. } else {
  3383. # nur Umschaltung, alte Werte beibehalten
  3384. $url .= "&keep=true";
  3385. }
  3386. if ($hash->{HELPER}{MOTDETSC_PROP1}) {
  3387. # der Wert für Bewegungserkennung Kamera -> Empfindlichkeit ist gesetzt
  3388. my $sensitivity = delete $hash->{HELPER}{MOTDETSC_PROP1};
  3389. $url .= "&sensitivity=\"$sensitivity\"";
  3390. }
  3391. if ($hash->{HELPER}{MOTDETSC_PROP2}) {
  3392. # der Wert für Bewegungserkennung Kamera -> Objektgröße ist gesetzt
  3393. my $objectsize = delete $hash->{HELPER}{MOTDETSC_PROP2};
  3394. $url .= "&objectSize=\"$objectsize\"";
  3395. }
  3396. if ($hash->{HELPER}{MOTDETSC_PROP3}) {
  3397. # der Wert für Bewegungserkennung Kamera -> Prozentsatz für Auslösung ist gesetzt
  3398. my $percentage = delete $hash->{HELPER}{MOTDETSC_PROP3};
  3399. $url .= "&percentage=\"$percentage\"";
  3400. }
  3401. } elsif ($hash->{HELPER}{MOTDETSC} eq "SVS") {
  3402. $motdetsc = "1";
  3403. $motdetoptions{SENSITIVITY} = $hash->{'HELPER'}{'MOTDETSC_PROP1'} if ($hash->{'HELPER'}{'MOTDETSC_PROP1'});
  3404. $motdetoptions{THRESHOLD} = $hash->{'HELPER'}{'MOTDETSC_PROP2'} if ($hash->{'HELPER'}{'MOTDETSC_PROP2'});
  3405. # nur Umschaltung, alte Werte beibehalten
  3406. $url = "$proto://$serveraddr:$serverport/webapi/$apicameventpath?api=\"$apicamevent\"&version=\"$apicameventmaxver\"&method=\"MDParamSave\"&camId=\"$camid\"&source=$motdetsc&keep=true&_sid=\"$sid\"";
  3407. if ($hash->{HELPER}{MOTDETSC_PROP1}) {
  3408. # der Wert für Bewegungserkennung SVS -> Empfindlichkeit ist gesetzt
  3409. my $sensitivity = delete $hash->{HELPER}{MOTDETSC_PROP1};
  3410. $url .= "&sensitivity=\"$sensitivity\"";
  3411. }
  3412. if ($hash->{HELPER}{MOTDETSC_PROP2}) {
  3413. # der Wert für Bewegungserkennung SVS -> Schwellwert ist gesetzt
  3414. my $threshold = delete $hash->{HELPER}{MOTDETSC_PROP2};
  3415. $url .= "&threshold=\"$threshold\"";
  3416. }
  3417. }
  3418. # Optionswerte in Hash sichern für Logausgabe in Befehlsauswertung
  3419. $hash->{HELPER}{MOTDETOPTIONS} = \%motdetoptions;
  3420. } elsif ($OpMode eq "getmotionenum") {
  3421. $url = "$proto://$serveraddr:$serverport/webapi/$apicameventpath?api=\"$apicamevent\"&version=\"$apicameventmaxver\"&method=\"MotionEnum\"&camId=\"$camid\"&_sid=\"$sid\"";
  3422. } elsif ($OpMode eq "extevent") {
  3423. Log3($name, 4, "$name - trigger external event \"$hash->{HELPER}{EVENTID}\"");
  3424. $url = "$proto://$serveraddr:$serverport/webapi/$apiextevtpath?api=$apiextevt&version=$apiextevtmaxver&method=Trigger&eventId=$hash->{HELPER}{EVENTID}&eventName=$hash->{HELPER}{EVENTID}&_sid=\"$sid\"";
  3425. } elsif ($OpMode eq "runliveview" && $hash->{HELPER}{RUNVIEW} !~ m/snap|^live_.*hls$/) {
  3426. if ($hash->{HELPER}{RUNVIEW} =~ m/live/) {
  3427. if($apiaudiostmmaxver) { # API "SYNO.SurveillanceStation.AudioStream" vorhanden ? (removed ab API v2.8)
  3428. $hash->{HELPER}{AUDIOLINK} = "$proto://$serveraddr:$serverport/webapi/$apiaudiostmpath?api=$apiaudiostm&version=$apiaudiostmmaxver&method=Stream&cameraId=$camid&_sid=$sid";
  3429. } else {
  3430. delete $hash->{HELPER}{AUDIOLINK} if($hash->{HELPER}{AUDIOLINK});
  3431. }
  3432. $exturl = AttrVal($name, "livestreamprefix", "$proto://$serveraddr:$serverport");
  3433. if($apivideostmsmaxver) { # API "SYNO.SurveillanceStation.VideoStream" vorhanden ? (removed ab API v2.8)
  3434. # externe URL in Reading setzen
  3435. $exturl .= "/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=mjpeg&_sid=$sid";
  3436. # interne URL
  3437. $url = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=mjpeg&_sid=$sid";
  3438. } elsif ($hash->{HELPER}{STMKEYMJPEGHTTP}) {
  3439. $url = $hash->{HELPER}{STMKEYMJPEGHTTP};
  3440. }
  3441. readingsSingleUpdate($hash,"LiveStreamUrl", $exturl, 1) if(AttrVal($name, "showStmInfoFull", undef));
  3442. } else {
  3443. # Abspielen der letzten Aufnahme (EventId)
  3444. $exturl = AttrVal($name, "livestreamprefix", "$proto://$serveraddr:$serverport");
  3445. # externe URL in Reading setzen
  3446. $exturl .= "/webapi/$apistmpath?api=$apistm&version=$apistmmaxver&method=EventStream&eventId=$hash->{HELPER}{CAMLASTRECID}&timestamp=1&_sid=$sid";
  3447. # interne URL
  3448. $url = "$proto://$serveraddr:$serverport/webapi/$apistmpath?api=$apistm&version=$apistmmaxver&method=EventStream&eventId=$hash->{HELPER}{CAMLASTRECID}&timestamp=1&_sid=$sid";
  3449. readingsSingleUpdate($hash,"LiveStreamUrl", $exturl, 1) if(AttrVal($name, "showStmInfoFull", undef));
  3450. }
  3451. # Liveview-Link in Hash speichern
  3452. $hash->{HELPER}{LINK} = $url;
  3453. Log3($name, 4, "$name - Set Streaming-URL: $url");
  3454. # livestream sofort in neuem Browsertab öffnen
  3455. if ($hash->{HELPER}{OPENWINDOW}) {
  3456. $winname = $name."_view";
  3457. $attr = AttrVal($name, "htmlattr", "");
  3458. # öffnen streamwindow für die Instanz die "VIEWOPENROOM" oder Attr "room" aktuell geöffnet hat
  3459. if ($hash->{HELPER}{VIEWOPENROOM}) {
  3460. $room = $hash->{HELPER}{VIEWOPENROOM};
  3461. map {FW_directNotify("FILTER=room=$room", "#FHEMWEB:$_", "window.open ('$url','$winname','$attr')", "")} devspec2array("WEB.*");
  3462. } else {
  3463. map {FW_directNotify("#FHEMWEB:$_", "window.open ('$url','$winname','$attr')", "")} devspec2array("WEB.*");
  3464. }
  3465. }
  3466. SSCam_refresh($hash,0,1,1); # kein Room-Refresh, SSCam-state-Event, SSCamSTRM-Event
  3467. $hash->{HELPER}{ACTIVE} = "off";
  3468. if (AttrVal($name,"debugactivetoken",0)) {
  3469. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  3470. }
  3471. return;
  3472. } elsif ($OpMode eq "runliveview" && $hash->{HELPER}{RUNVIEW} =~ /snap/) {
  3473. # den letzten Schnappschuß live anzeigen
  3474. my $limit = 1; # nur 1 Snap laden, für lastsnap_fw
  3475. my $imgsize = 2; # full size image, für lastsnap_fw
  3476. my $keyword = $hash->{CAMNAME}; # nur Snaps von $camname selektieren, für lastsnap_fw
  3477. $url = "$proto://$serveraddr:$serverport/webapi/$apitakesnappath?api=\"$apitakesnap\"&method=\"List\"&version=\"$apitakesnapmaxver\"&keyword=\"$keyword\"&imgSize=\"$imgsize\"&limit=\"$limit\"&_sid=\"$sid\"";
  3478. } elsif (($OpMode eq "runliveview" && $hash->{HELPER}{RUNVIEW} =~ m/^live_.*hls$/) || $OpMode eq "activate_hls") {
  3479. # HLS Livestreaming aktivieren
  3480. $httptimeout = $httptimeout+90; # aktivieren HLS dauert lange !
  3481. $url = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Open&cameraId=$camid&format=hls&_sid=$sid";
  3482. } elsif ($OpMode eq "stopliveview_hls" || $OpMode eq "reactivate_hls") {
  3483. # HLS Livestreaming deaktivieren
  3484. $url = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Close&cameraId=$camid&format=hls&_sid=$sid";
  3485. } elsif ($OpMode eq "getstreamformat") {
  3486. # aktuelles Streamformat abfragen
  3487. $url = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Query&cameraId=$camid&_sid=$sid";
  3488. }
  3489. Log3($name, 4, "$name - Call-Out now: $url");
  3490. $param = {
  3491. url => $url,
  3492. timeout => $httptimeout,
  3493. hash => $hash,
  3494. method => "GET",
  3495. header => "Accept: application/json",
  3496. callback => \&SSCam_camop_parse
  3497. };
  3498. HttpUtils_NonblockingGet ($param);
  3499. }
  3500. ###################################################################################
  3501. # Check ob Kameraoperation erfolgreich wie in "OpMOde" definiert
  3502. ###################################################################################
  3503. sub SSCam_camop_parse ($) {
  3504. my ($param, $err, $myjson) = @_;
  3505. my $hash = $param->{hash};
  3506. my $name = $hash->{NAME};
  3507. my $camname = $hash->{CAMNAME};
  3508. my $OpMode = $hash->{OPMODE};
  3509. my $serveraddr = $hash->{SERVERADDR};
  3510. my $serverport = $hash->{SERVERPORT};
  3511. my $camid = $hash->{CAMID};
  3512. my $apivideostms = $hash->{HELPER}{APIVIDEOSTMS};
  3513. my $apivideostmspath = $hash->{HELPER}{APIVIDEOSTMSPATH};
  3514. my $apivideostmsmaxver = $hash->{HELPER}{APIVIDEOSTMSMAXVER};
  3515. my $apicammaxver = $hash->{HELPER}{APICAMMAXVER};
  3516. my $sid = $hash->{HELPER}{SID};
  3517. my $proto = $hash->{PROTOCOL};
  3518. my ($rectime,$data,$success);
  3519. my ($error,$errorcode);
  3520. my ($snapid,$camLiveMode,$update_time);
  3521. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
  3522. my ($deviceType,$camStatus);
  3523. my ($patrolcnt,$patrolid,$patrolname,@patrolkeys,$patrollist);
  3524. my ($recStatus,$exposuremode,$exposurecontrol);
  3525. my ($userPriv,$verbose,$motdetsc);
  3526. my ($sensitivity_camCap,$sensitivity_value,$sensitivity_ssCap);
  3527. my ($threshold_camCap,$threshold_value,$threshold_ssCap);
  3528. my ($percentage_camCap,$percentage_value,$percentage_ssCap);
  3529. my ($objectSize_camCap,$objectSize_value,$objectSize_ssCap);
  3530. # Einstellung für Logausgabe Pollinginfos
  3531. # wenn "pollnologging" = 1 -> logging nur bei Verbose=4, sonst 3
  3532. if (AttrVal($name, "pollnologging", 0) == 1) {
  3533. $verbose = 4;
  3534. } else {
  3535. $verbose = 3;
  3536. }
  3537. if ($err ne "") {
  3538. # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
  3539. Log3($name, 2, "$name - error while requesting ".$param->{url}." - $err");
  3540. readingsSingleUpdate($hash, "Error", $err, 1);
  3541. # ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
  3542. $hash->{HELPER}{ACTIVE} = "off";
  3543. if (AttrVal($name,"debugactivetoken",0)) {
  3544. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  3545. }
  3546. return;
  3547. } elsif ($myjson ne "") {
  3548. # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
  3549. # Evaluiere ob Daten im JSON-Format empfangen wurden
  3550. ($hash,$success,$myjson) = SSCam_evaljson($hash,$myjson);
  3551. unless ($success) {
  3552. Log3($name, 4, "$name - Data returned: ".$myjson);
  3553. # ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
  3554. $hash->{HELPER}{ACTIVE} = "off";
  3555. if (AttrVal($name,"debugactivetoken",0)) {
  3556. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  3557. }
  3558. return;
  3559. }
  3560. $data = decode_json($myjson);
  3561. # Logausgabe decodierte JSON Daten
  3562. Log3($name, 5, "$name - JSON returned: ". Dumper $data);
  3563. $success = $data->{'success'};
  3564. if ($success) {
  3565. # Kameraoperation entsprechend "OpMode" war erfolgreich
  3566. if ($OpMode eq "Start") {
  3567. # Die Aufnahmezeit setzen
  3568. # wird "set <name> on [rectime]" verwendet -> dann [rectime] nutzen,
  3569. # sonst Attribut "rectime" wenn es gesetzt ist, falls nicht -> "RECTIME_DEF"
  3570. if (defined($hash->{HELPER}{RECTIME_TEMP})) {
  3571. $rectime = delete $hash->{HELPER}{RECTIME_TEMP};
  3572. } else {
  3573. $rectime = AttrVal($name, "rectime", $hash->{HELPER}{RECTIME_DEF});
  3574. }
  3575. if ($rectime == "0") {
  3576. Log3($name, 3, "$name - Camera $camname endless Recording started - stop it by stop-command !");
  3577. } else {
  3578. if (ReadingsVal("$name", "Record", "Stop") eq "Start") {
  3579. # Aufnahme läuft schon und wird verlängert
  3580. Log3($name, 3, "$name - running recording renewed to $rectime s");
  3581. } else {
  3582. Log3($name, 3, "$name - Camera $camname Recording with Recordtime $rectime s started");
  3583. }
  3584. }
  3585. readingsBeginUpdate($hash);
  3586. readingsBulkUpdate($hash,"Record","Start");
  3587. readingsBulkUpdate($hash,"state","on");
  3588. readingsBulkUpdate($hash,"Errorcode","none");
  3589. readingsBulkUpdate($hash,"Error","none");
  3590. readingsEndUpdate($hash, 1);
  3591. if ($rectime != 0) {
  3592. # Stop der Aufnahme nach Ablauf $rectime, wenn rectime = 0 -> endlose Aufnahme
  3593. RemoveInternalTimer($hash, "SSCam_camstoprec");
  3594. InternalTimer(gettimeofday()+$rectime, "SSCam_camstoprec", $hash);
  3595. }
  3596. SSCam_refresh($hash,0,0,1); # kein Room-Refresh, kein SSCam-state-Event, SSCamSTRM-Event
  3597. } elsif ($OpMode eq "Stop") {
  3598. readingsBeginUpdate($hash);
  3599. readingsBulkUpdate($hash,"Record","Stop");
  3600. readingsBulkUpdate($hash,"state","off");
  3601. readingsBulkUpdate($hash,"Errorcode","none");
  3602. readingsBulkUpdate($hash,"Error","none");
  3603. readingsEndUpdate($hash, 1);
  3604. # Logausgabe
  3605. Log3($name, 3, "$name - Camera $camname Recording stopped");
  3606. SSCam_refresh($hash,0,0,1); # kein Room-Refresh, kein SSCam-state-Event, SSCamSTRM-Event
  3607. # Aktualisierung Eventlist der letzten Aufnahme
  3608. SSCam_geteventlist($hash);
  3609. } elsif ($OpMode eq "ExpMode") {
  3610. readingsBeginUpdate($hash);
  3611. readingsBulkUpdate($hash,"Errorcode","none");
  3612. readingsBulkUpdate($hash,"Error","none");
  3613. readingsEndUpdate($hash, 1);
  3614. # Logausgabe
  3615. Log3($name, 3, "$name - Camera $camname exposure mode was set to \"$hash->{HELPER}{EXPMODE}\"");
  3616. } elsif ($OpMode eq "sethomemode") {
  3617. readingsBeginUpdate($hash);
  3618. readingsBulkUpdate($hash,"Errorcode","none");
  3619. readingsBulkUpdate($hash,"Error","none");
  3620. readingsEndUpdate($hash, 1);
  3621. Log3($name, 3, "$name - HomeMode was set to \"$hash->{HELPER}{HOMEMODE}\" ");
  3622. # Token freigeben vor nächstem Kommando
  3623. $hash->{HELPER}{ACTIVE} = "off";
  3624. # neuen HomeModeState abrufen
  3625. SSCam_gethomemodestate($hash);
  3626. } elsif ($OpMode eq "gethomemodestate") {
  3627. my $hmst = $data->{'data'}{'on'};
  3628. my $hmststr = ($hmst == 1)?"on":"off";
  3629. readingsBeginUpdate($hash);
  3630. readingsBulkUpdate($hash,"HomeModeState",$hmststr);
  3631. readingsBulkUpdate($hash,"Errorcode","none");
  3632. readingsBulkUpdate($hash,"Error","none");
  3633. readingsEndUpdate($hash, 1);
  3634. } elsif ($OpMode eq "getsvslog") {
  3635. my $lec = $data->{'data'}{'total'}; # abgerufene Anzahl von Log-Einträgen
  3636. my $log = '<html>';
  3637. my $log0 = "";
  3638. my $i = 0;
  3639. while ($data->{'data'}->{'log'}->[$i]) {
  3640. my $id = $data->{'data'}->{'log'}->[$i]{'id'};
  3641. my $un = $data->{'data'}->{'log'}->[$i]{'user_name'};
  3642. my $desc = $data->{'data'}->{'log'}->[$i]{'desc'};
  3643. my $level = $data->{'data'}->{'log'}->[$i]{'type'};
  3644. $level = ($level == 3)?"Error":($level == 2)?"Warning":"Information";
  3645. my $time = $data->{'data'}->{'log'}->[$i]{'time'};
  3646. $time = FmtDateTime($time);
  3647. $log0 = $time." - ".$level." - ".$desc if($i == 0);
  3648. $log .= "$time - $level - $desc<br>";
  3649. $i++;
  3650. }
  3651. $log = "<html><b>Surveillance Station Server \"$hash->{SERVERADDR}\" Log</b> ( $i/$lec entries are displayed )<br><br>$log</html>";
  3652. # asyncOutput kann normalerweise etwa 100k uebertragen (siehe fhem.pl/addToWritebuffer() fuer Details)
  3653. # bzw. https://forum.fhem.de/index.php/topic,77310.0.html
  3654. # $log = "Too much log data were selected. Please reduce amount of data by specifying all or one of 'severity', 'limit', 'match'" if (length($log) >= 102400);
  3655. readingsBeginUpdate($hash);
  3656. readingsBulkUpdate($hash,"LastLogEntry",$log0) if(!$hash->{HELPER}{CL}{1}); # Datenabruf im Hintergrund;
  3657. readingsBulkUpdate($hash,"Errorcode","none");
  3658. readingsBulkUpdate($hash,"Error","none");
  3659. readingsEndUpdate($hash, 1);
  3660. # Ausgabe Popup der Log-Daten (nach readingsEndUpdate positionieren sonst "Connection lost, trying reconnect every 5 seconds" wenn > 102400 Zeichen)
  3661. asyncOutput($hash->{HELPER}{CL}{1},"$log");
  3662. delete($hash->{HELPER}{CL});
  3663. } elsif ($OpMode eq "getPresets") {
  3664. my %ap = ();
  3665. my $i = 0;
  3666. while ($data->{'data'}->{'preset'}->[$i]) {
  3667. my $pname = $data->{'data'}->{'preset'}->[$i]{'name'};
  3668. my $ptype = $data->{'data'}->{'preset'}->[$i]{'type'};
  3669. my $ppos = $data->{'data'}->{'preset'}->[$i]{'position'};
  3670. my $pspeed = $data->{'data'}->{'preset'}->[$i]{'speed'};
  3671. my $pextra = $data->{'data'}->{'preset'}->[$i]{'extra'};
  3672. $ptype = ($ptype == 1)?"Home":"Normal";
  3673. $ap{$ppos} = "Name: $pname, Speed: $pspeed, Type: $ptype";
  3674. $i++;
  3675. }
  3676. my $enum;
  3677. foreach my $key (sort{$a <=>$b}keys%ap) {
  3678. $enum .= $key." => ".$ap{$key}."<br>";
  3679. }
  3680. $enum = "<html><b>Preset positions saved of camera \"$hash->{CAMNAME}\" </b> ".
  3681. "(PresetNumber => Name: ..., Speed: ..., Type: ...) <br><br>$enum</html>";
  3682. # asyncOutput kann normalerweise etwa 100k uebertragen (siehe fhem.pl/addToWritebuffer() fuer Details)
  3683. # bzw. https://forum.fhem.de/index.php/topic,77310.0.html
  3684. readingsBeginUpdate($hash);
  3685. readingsBulkUpdate($hash,"Errorcode","none");
  3686. readingsBulkUpdate($hash,"Error","none");
  3687. readingsEndUpdate($hash, 1);
  3688. # Ausgabe Popup der Daten (nach readingsEndUpdate positionieren sonst
  3689. # "Connection lost, trying reconnect every 5 seconds" wenn > 102400 Zeichen)
  3690. asyncOutput($hash->{HELPER}{CL}{1},"$enum");
  3691. delete($hash->{HELPER}{CL});
  3692. } elsif ($OpMode eq "setPreset") {
  3693. readingsBeginUpdate($hash);
  3694. readingsBulkUpdate($hash,"Errorcode","none");
  3695. readingsBulkUpdate($hash,"Error","none");
  3696. readingsEndUpdate($hash, 1);
  3697. my $pnumber = delete($hash->{HELPER}{PNUMBER});
  3698. my $pname = delete($hash->{HELPER}{PNAME});
  3699. my $pspeed = delete($hash->{HELPER}{PSPEED});
  3700. $pspeed = $pspeed?$pspeed:"not set";
  3701. # Logausgabe
  3702. Log3($name, 3, "$name - Camera \"$camname\" preset \"$pname\" was saved to number $pnumber with speed $pspeed");
  3703. SSCam_getptzlistpreset($hash);
  3704. } elsif ($OpMode eq "delPreset") {
  3705. readingsBeginUpdate($hash);
  3706. readingsBulkUpdate($hash,"Errorcode","none");
  3707. readingsBulkUpdate($hash,"Error","none");
  3708. readingsEndUpdate($hash, 1);
  3709. my $dp = $hash->{HELPER}{DELPRESETNAME};
  3710. Log3($name, 3, "$name - Preset \"$dp\" of camera \"$camname\" was deleted successfully");
  3711. SSCam_getptzlistpreset($hash);
  3712. } elsif ($OpMode eq "piract") {
  3713. readingsBeginUpdate($hash);
  3714. readingsBulkUpdate($hash,"Errorcode","none");
  3715. readingsBulkUpdate($hash,"Error","none");
  3716. readingsEndUpdate($hash, 1);
  3717. # Logausgabe
  3718. my $piract = ($hash->{HELPER}{PIRACT} == 0)?"activated":"deactivated";
  3719. Log3($name, 3, "$name - PIR sensor $piract");
  3720. } elsif ($OpMode eq "setHome") {
  3721. readingsBeginUpdate($hash);
  3722. readingsBulkUpdate($hash,"Errorcode","none");
  3723. readingsBulkUpdate($hash,"Error","none");
  3724. readingsEndUpdate($hash, 1);
  3725. my $sh = $hash->{HELPER}{SETHOME};
  3726. Log3($name, 3, "$name - Preset \"$sh\" of camera \"$camname\" was set as Home position");
  3727. SSCam_getptzlistpreset($hash);
  3728. } elsif ($OpMode eq "setoptpar") {
  3729. my $rid = $data->{'data'}{'id'}; # Cam ID return wenn i.O.
  3730. my $ropt = $rid == $hash->{CAMID}?"none":"error in operation";
  3731. delete($hash->{HELPER}{NTPSERV});
  3732. delete($hash->{HELPER}{MIRROR});
  3733. delete($hash->{HELPER}{FLIP});
  3734. delete($hash->{HELPER}{ROTATE});
  3735. delete($hash->{HELPER}{CHKLIST});
  3736. readingsBeginUpdate($hash);
  3737. readingsBulkUpdate($hash,"Errorcode","none");
  3738. readingsBulkUpdate($hash,"Error",$ropt);
  3739. readingsEndUpdate($hash, 1);
  3740. # Token freigeben vor Abruf caminfo
  3741. $hash->{HELPER}{ACTIVE} = "off";
  3742. RemoveInternalTimer($hash, "SSCam_getcaminfo");
  3743. InternalTimer(gettimeofday()+0.5, "SSCam_getcaminfo", $hash, 0);
  3744. } elsif ($OpMode eq "MotDetSc") {
  3745. readingsBeginUpdate($hash);
  3746. readingsBulkUpdate($hash,"Errorcode","none");
  3747. readingsBulkUpdate($hash,"Error","none");
  3748. readingsEndUpdate($hash, 1);
  3749. # Logausgabe
  3750. my $sensitivity;
  3751. if ($hash->{HELPER}{MOTDETSC} eq "SVS" && keys %{$hash->{HELPER}{MOTDETOPTIONS}}) {
  3752. # Optionen für "SVS" sind gesetzt
  3753. $sensitivity = ($hash->{HELPER}{MOTDETOPTIONS}{SENSITIVITY}) ? ($hash->{HELPER}{MOTDETOPTIONS}{SENSITIVITY}) : "-";
  3754. my $threshold = ($hash->{HELPER}{MOTDETOPTIONS}{THRESHOLD}) ? ($hash->{HELPER}{MOTDETOPTIONS}{THRESHOLD}) : "-";
  3755. Log3($name, 3, "$name - Camera $camname motion detection source set to \"$hash->{HELPER}{MOTDETSC}\" with options sensitivity: $sensitivity, threshold: $threshold");
  3756. } elsif ($hash->{HELPER}{MOTDETSC} eq "camera" && keys %{$hash->{HELPER}{MOTDETOPTIONS}}) {
  3757. # Optionen für "camera" sind gesetzt
  3758. $sensitivity = ($hash->{HELPER}{MOTDETOPTIONS}{SENSITIVITY}) ? ($hash->{HELPER}{MOTDETOPTIONS}{SENSITIVITY}) : "-";
  3759. my $objectSize = ($hash->{HELPER}{MOTDETOPTIONS}{OBJECTSIZE}) ? ($hash->{HELPER}{MOTDETOPTIONS}{OBJECTSIZE}) : "-";
  3760. my $percentage = ($hash->{HELPER}{MOTDETOPTIONS}{PERCENTAGE}) ? ($hash->{HELPER}{MOTDETOPTIONS}{PERCENTAGE}) : "-";
  3761. Log3($name, 3, "$name - Camera $camname motion detection source set to \"$hash->{HELPER}{MOTDETSC}\" with options sensitivity: $sensitivity, objectSize: $objectSize, percentage: $percentage");
  3762. } else {
  3763. # keine Optionen Bewegungserkennung wurden gesetzt
  3764. Log3($name, 3, "$name - Camera $camname motion detection source set to \"$hash->{HELPER}{MOTDETSC}\" ");
  3765. }
  3766. } elsif ($OpMode eq "Snap") {
  3767. # ein Schnapschuß wurde aufgenommen
  3768. # falls Aufnahme noch läuft -> state = on setzen
  3769. SSCam_refresh($hash,0,0,0); # kein Room-Refresh, kein SSCam-state-Event, kein SSCamSTRM-Event
  3770. $snapid = $data->{data}{'id'};
  3771. readingsBeginUpdate($hash);
  3772. readingsBulkUpdate($hash,"Errorcode","none");
  3773. readingsBulkUpdate($hash,"Error","none");
  3774. readingsEndUpdate($hash, 1);
  3775. # Logausgabe
  3776. Log3($name, 3, "$name - Snapshot of Camera $camname has been done successfully");
  3777. # Token freigeben vor nächstem Kommando
  3778. $hash->{HELPER}{ACTIVE} = "off";
  3779. # Schnappschußgalerie abrufen (snapGalleryBoost) oder nur Info des letzten Snaps
  3780. my ($slim,$ssize) = SSCam_snaplimsize($hash);
  3781. RemoveInternalTimer("SSCam_getsnapinfo");
  3782. InternalTimer(gettimeofday()+0.6, "SSCam_getsnapinfo", "$name:$slim:$ssize", 0);
  3783. } elsif ($OpMode eq "getsnapinfo" || $OpMode eq "getsnapgallery" || ($OpMode eq "runliveview" && $hash->{HELPER}{RUNVIEW} =~ /snap/)) {
  3784. # Informationen zu einem oder mehreren Schnapschüssen wurde abgerufen bzw. Lifeanzeige Schappschuß
  3785. my $lsid = exists($data->{data}{data}[0]{id})?$data->{data}{data}[0]{id}:"n.a.";
  3786. my $lfname = exists($data->{data}{data}[0]{fileName})?$data->{data}{data}[0]{fileName}:"n.a.";
  3787. my $lstime;
  3788. if(exists($data->{data}{data}[0]{createdTm})) {
  3789. $lstime = $data->{data}{data}[0]{createdTm};
  3790. my @t = split(" ", FmtDateTime($lstime));
  3791. my @d = split("-", $t[0]);
  3792. $lstime = "$d[2].$d[1].$d[0] / $t[1]";
  3793. } else {
  3794. $lstime = "n.a.";
  3795. }
  3796. Log3($name,4, "$name - Snap [0]: ID => $lsid, File => $lfname, Created => $lstime");
  3797. readingsBeginUpdate($hash);
  3798. readingsBulkUpdate($hash,"Errorcode","none");
  3799. readingsBulkUpdate($hash,"Error","none");
  3800. readingsBulkUpdate($hash,"LastSnapId",$lsid);
  3801. readingsBulkUpdate($hash,"LastSnapFilename", $lfname);
  3802. readingsBulkUpdate($hash,"LastSnapTime", $lstime);
  3803. readingsEndUpdate($hash, 1);
  3804. # Schnapschuss soll als liveView angezeigt werden (mindestens 1 Bild vorhanden)
  3805. Log3($name, 3, "$name - There is no snapshot of camera $camname to display ! Take one snapshot before.")
  3806. if(exists($hash->{HELPER}{RUNVIEW}) && $hash->{HELPER}{RUNVIEW} =~ /snap/ && !exists($data->{'data'}{'data'}[0]{imageData}));
  3807. if (exists($hash->{HELPER}{RUNVIEW}) && $hash->{HELPER}{RUNVIEW} =~ /snap/ && exists($data->{'data'}{'data'}[0]{imageData})) {
  3808. delete $hash->{HELPER}{RUNVIEW};
  3809. $hash->{HELPER}{LINK} = $data->{data}{data}[0]{imageData};
  3810. }
  3811. if($OpMode eq "getsnapgallery") {
  3812. # es soll eine Schnappschußgallerie bereitgestellt (Attr snapGalleryBoost=1) bzw. gleich angezeigt werden (Attr snapGalleryBoost=0)
  3813. my $i = 0;
  3814. my $sn = 0;
  3815. my %allsnaps = (); # Schnappschuss Hash wird leer erstellt
  3816. $hash->{HELPER}{TOTALCNT} = $data->{data}{total}; # total Anzahl Schnappschüsse
  3817. while ($data->{'data'}{'data'}[$i]) {
  3818. if($data->{'data'}{'data'}[$i]{'camName'} ne $camname) {
  3819. $i += 1;
  3820. next;
  3821. }
  3822. $snapid = $data->{data}{data}[$i]{id};
  3823. my $createdTm = $data->{data}{data}[$i]{createdTm};
  3824. my $fileName = $data->{data}{data}[$i]{fileName};
  3825. my $imageData = $data->{data}{data}[$i]{imageData}; # Image data of snapshot in base64 format
  3826. $allsnaps{$sn}{snapid} = $snapid;
  3827. my @t = split(" ", FmtDateTime($createdTm));
  3828. my @d = split("-", $t[0]);
  3829. $createdTm = "$d[2].$d[1].$d[0] / $t[1]";
  3830. $allsnaps{$sn}{createdTm} = $createdTm;
  3831. $allsnaps{$sn}{fileName} = $fileName;
  3832. $allsnaps{$sn}{imageData} = $imageData;
  3833. Log3($name,4, "$name - Snap '$sn' added to gallery hash: ID => $allsnaps{$sn}{snapid}, File => $allsnaps{$sn}{fileName}, Created => $allsnaps{$sn}{createdTm}");
  3834. $sn += 1;
  3835. $i += 1;
  3836. }
  3837. # Hash der Schnapschüsse erstellen
  3838. $hash->{HELPER}{".SNAPHASH"} = \%allsnaps;
  3839. # Direktausgabe Snaphash wenn nicht gepollt wird
  3840. if(!AttrVal($name, "snapGalleryBoost",0)) {
  3841. my $htmlCode = SSCam_composegallery($name);
  3842. for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
  3843. asyncOutput($hash->{HELPER}{CL}{$k},"$htmlCode");
  3844. }
  3845. delete($hash->{HELPER}{".SNAPHASH"}); # Snaphash löschen wenn nicht gepollt wird
  3846. delete($hash->{HELPER}{CL});
  3847. }
  3848. delete($hash->{HELPER}{GETSNAPGALLERY}); # Steuerbit getsnapgallery statt getsnapinfo
  3849. }
  3850. if ($hash->{HELPER}{SNAPBYSTRMDEV} || $hash->{HELPER}{LSNAPBYSTRMDEV}) {
  3851. # Snap durch SSCamSTRM-Device ausgelöst
  3852. SSCam_refresh($hash,0,0,1); # kein Room-Refresh, kein SSCam-state-Event, SSCamSTRM-Event
  3853. delete $hash->{HELPER}{SNAPBYSTRMDEV};
  3854. delete $hash->{HELPER}{LSNAPBYSTRMDEV};
  3855. } elsif ($hash->{HELPER}{LSNAPBYDEV}) {
  3856. SSCam_refresh($hash,0,1,0); # kein Room-Refresh, SSCam-state-Event, kein SSCamSTRM-Event
  3857. delete $hash->{HELPER}{LSNAPBYDEV};
  3858. } else {
  3859. SSCam_refresh($hash,0,0,0); # kein Room-Refresh, SSCam-state-Event, SSCamSTRM-Event
  3860. }
  3861. Log3($name, $verbose, "$name - Snapinfos of camera $camname retrieved");
  3862. } elsif ($OpMode eq "runliveview" && $hash->{HELPER}{RUNVIEW} =~ m/^live_.*hls$/) {
  3863. # HLS Streaming wurde aktiviert
  3864. $hash->{HELPER}{HLSSTREAM} = "active";
  3865. # externe LivestreamURL setzen
  3866. my $exturl = AttrVal($name, "livestreamprefix", "$proto://$serveraddr:$serverport");
  3867. $exturl .= "/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=hls&_sid=$sid";
  3868. readingsSingleUpdate($hash,"LiveStreamUrl", $exturl, 1) if(AttrVal($name, "showStmInfoFull", undef));
  3869. my $url = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=hls&_sid=$sid";
  3870. # Liveview-Link in Hash speichern und Aktivitätsstatus speichern
  3871. $hash->{HELPER}{LINK} = $url;
  3872. Log3($name, 4, "$name - HLS Streaming of camera \"$name\" activated, Streaming-URL: $url") if(AttrVal($name,"verbose",3) == 4);
  3873. Log3($name, 3, "$name - HLS Streaming of camera \"$name\" activated") if(AttrVal($name,"verbose",3) == 3);
  3874. SSCam_refresh($hash,0,1,1); # kein Room-Refresh, SSCam-state-Event, SSCamSTRM-Event
  3875. } elsif ($OpMode eq "stopliveview_hls") {
  3876. # HLS Streaming wurde deaktiviert, Aktivitätsstatus speichern
  3877. $hash->{HELPER}{HLSSTREAM} = "inactive";
  3878. Log3($name, 3, "$name - HLS Streaming of camera \"$name\" deactivated");
  3879. SSCam_refresh($hash,0,1,1); # kein Room-Refresh, SSCam-state-Event, SSCamSTRM-Event
  3880. } elsif ($OpMode eq "reactivate_hls") {
  3881. # HLS Streaming wurde deaktiviert, Aktivitätsstatus speichern
  3882. $hash->{HELPER}{HLSSTREAM} = "inactive";
  3883. Log3($name, 4, "$name - HLS Streaming of camera \"$name\" deactivated for streaming device");
  3884. # Token freigeben vor hlsactivate
  3885. $hash->{HELPER}{ACTIVE} = "off";
  3886. SSCam_hlsactivate($hash);
  3887. } elsif ($OpMode eq "activate_hls") {
  3888. # HLS Streaming wurde aktiviert, Aktivitätsstatus speichern
  3889. $hash->{HELPER}{HLSSTREAM} = "active";
  3890. Log3($name, 4, "$name - HLS Streaming of camera \"$name\" activated for streaming device");
  3891. SSCam_refresh($hash,0,1,1); # kein Room-Refresh, SSCam-state-Event, SSCamSTRM-Event
  3892. } elsif ($OpMode eq "getsnapfilename") {
  3893. # den Filenamen eines Schnapschusses ermitteln
  3894. $snapid = ReadingsVal("$name", "LastSnapId", " ");
  3895. readingsBeginUpdate($hash);
  3896. readingsBulkUpdate($hash,"Errorcode","none");
  3897. readingsBulkUpdate($hash,"Error","none");
  3898. readingsBulkUpdate($hash,"LastSnapFilename", $data->{'data'}{'data'}[0]{'fileName'});
  3899. readingsEndUpdate($hash, 1);
  3900. # Logausgabe
  3901. Log3($name, 4, "$name - Filename of Snap-ID $snapid is \"$data->{'data'}{'data'}[0]{'fileName'}\"") if($data->{'data'}{'data'}[0]{'fileName'});
  3902. } elsif ($OpMode eq "getstreamformat") {
  3903. # aktuelles Streamformat abgefragt
  3904. my $sformat = SSCam_jboolmap($data->{'data'}->{'format'});
  3905. readingsBeginUpdate($hash);
  3906. readingsBulkUpdate($hash,"Errorcode","none");
  3907. readingsBulkUpdate($hash,"Error","none");
  3908. readingsBulkUpdate($hash,"CamStreamFormat", uc($sformat)) if($sformat);
  3909. readingsEndUpdate($hash, 1);
  3910. } elsif ($OpMode eq "gopreset") {
  3911. # eine Presetposition wurde angefahren
  3912. # falls Aufnahme noch läuft -> state = on setzen
  3913. my $st = (ReadingsVal("$name", "Record", "Stop") eq "Start")?"on":"off";
  3914. readingsSingleUpdate($hash,"state", $st, 0);
  3915. DoTrigger($name,"move stop");
  3916. readingsBeginUpdate($hash);
  3917. readingsBulkUpdate($hash,"Errorcode","none");
  3918. readingsBulkUpdate($hash,"Error","none");
  3919. readingsEndUpdate($hash, 1);
  3920. # Logausgabe
  3921. Log3($name, 3, "$name - Camera $camname has been moved to position \"$hash->{HELPER}{GOPRESETNAME}\"");
  3922. } elsif ($OpMode eq "runpatrol") {
  3923. # eine Tour wurde gestartet
  3924. # falls Aufnahme noch läuft -> state = on setzen
  3925. my $st = (ReadingsVal("$name", "Record", "Stop") eq "Start")?"on":"off";
  3926. readingsSingleUpdate($hash,"state", $st, 0);
  3927. DoTrigger($name,"patrol started");
  3928. readingsBeginUpdate($hash);
  3929. readingsBulkUpdate($hash,"Errorcode","none");
  3930. readingsBulkUpdate($hash,"Error","none");
  3931. readingsEndUpdate($hash, 1);
  3932. # Logausgabe
  3933. Log3($name, 3, "$name - Patrol \"$hash->{HELPER}{GOPATROLNAME}\" of camera $camname has been started successfully");
  3934. } elsif ($OpMode eq "goabsptz") {
  3935. # eine absolute PTZ-Position wurde angefahren
  3936. # falls Aufnahme noch läuft -> state = on setzen
  3937. my $st = (ReadingsVal("$name", "Record", "Stop") eq "Start")?"on":"off";
  3938. readingsSingleUpdate($hash,"state", $st, 0);
  3939. DoTrigger($name,"move stop");
  3940. readingsBeginUpdate($hash);
  3941. readingsBulkUpdate($hash,"Errorcode","none");
  3942. readingsBulkUpdate($hash,"Error","none");
  3943. readingsEndUpdate($hash, 1);
  3944. # Logausgabe
  3945. Log3($name, 3, "$name - Camera $camname has been moved to absolute position \"posX=$hash->{HELPER}{GOPTZPOSX}\" and \"posY=$hash->{HELPER}{GOPTZPOSY}\"");
  3946. } elsif ($OpMode eq "startTrack") {
  3947. # Object Tracking wurde eingeschaltet
  3948. readingsBeginUpdate($hash);
  3949. readingsBulkUpdate($hash,"Errorcode","none");
  3950. readingsBulkUpdate($hash,"Error","none");
  3951. readingsEndUpdate($hash, 1);
  3952. # Logausgabe
  3953. Log3($name, 3, "$name - Object tracking of Camera $camname has been switched on");
  3954. } elsif ($OpMode eq "stopTrack") {
  3955. # Object Tracking wurde eingeschaltet
  3956. readingsBeginUpdate($hash);
  3957. readingsBulkUpdate($hash,"Errorcode","none");
  3958. readingsBulkUpdate($hash,"Error","none");
  3959. readingsEndUpdate($hash, 1);
  3960. # Logausgabe
  3961. Log3($name, 3, "$name - Object tracking of Camera $camname has been stopped");
  3962. } elsif ($OpMode eq "movestart") {
  3963. # ein "Move" in eine bestimmte Richtung wird durchgeführt
  3964. readingsBeginUpdate($hash);
  3965. readingsBulkUpdate($hash,"Errorcode","none");
  3966. readingsBulkUpdate($hash,"Error","none");
  3967. readingsEndUpdate($hash, 1);
  3968. # Logausgabe
  3969. Log3($name, 3, "$name - Camera $camname started move to direction \"$hash->{HELPER}{GOMOVEDIR}\" with duration of $hash->{HELPER}{GOMOVETIME} s");
  3970. RemoveInternalTimer($hash, "SSCam_movestop");
  3971. InternalTimer(gettimeofday()+($hash->{HELPER}{GOMOVETIME}), "SSCam_movestop", $hash);
  3972. } elsif ($OpMode eq "movestop") {
  3973. # ein "Move" in eine bestimmte Richtung wurde durchgeführt
  3974. # falls Aufnahme noch läuft -> state = on setzen
  3975. my $st = (ReadingsVal("$name", "Record", "Stop") eq "Start")?"on":"off";
  3976. readingsSingleUpdate($hash,"state", $st, 0);
  3977. DoTrigger($name,"move stop");
  3978. readingsBeginUpdate($hash);
  3979. readingsBulkUpdate($hash,"Errorcode","none");
  3980. readingsBulkUpdate($hash,"Error","none");
  3981. readingsEndUpdate($hash, 1);
  3982. Log3($name, 3, "$name - Camera $camname stopped move to direction \"$hash->{HELPER}{GOMOVEDIR}\"");
  3983. } elsif ($OpMode eq "Enable") {
  3984. # Kamera wurde aktiviert, sonst kann nichts laufen -> "off"
  3985. readingsBeginUpdate($hash);
  3986. readingsBulkUpdate($hash,"Availability","enabled");
  3987. readingsBulkUpdate($hash,"state","off");
  3988. readingsBulkUpdate($hash,"Errorcode","none");
  3989. readingsBulkUpdate($hash,"Error","none");
  3990. readingsEndUpdate($hash, 1);
  3991. # Logausgabe
  3992. Log3($name, 3, "$name - Camera $camname has been enabled successfully");
  3993. } elsif ($OpMode eq "Disable") {
  3994. # Kamera wurde deaktiviert
  3995. readingsBeginUpdate($hash);
  3996. readingsBulkUpdate($hash,"Availability","disabled");
  3997. readingsBulkUpdate($hash,"state","disabled");
  3998. readingsBulkUpdate($hash,"Errorcode","none");
  3999. readingsBulkUpdate($hash,"Error","none");
  4000. readingsEndUpdate($hash, 1);
  4001. # Logausgabe
  4002. Log3($name, 3, "$name - Camera $camname has been disabled successfully");
  4003. } elsif ($OpMode eq "getsvsinfo") {
  4004. # Parse SVS-Infos
  4005. $userPriv = $data->{'data'}{'userPriv'};
  4006. if (defined($userPriv)) {
  4007. if ($userPriv eq "0") {
  4008. $userPriv = "No Access";
  4009. } elsif ($userPriv eq "1") {
  4010. $userPriv = "Admin";
  4011. } elsif ($userPriv eq "2") {
  4012. $userPriv = "Manager";
  4013. } elsif ($userPriv eq "4") {
  4014. $userPriv = "Viewer";
  4015. }
  4016. }
  4017. # "my" nicht am Anfang deklarieren, sonst wird Hash %version wieder geleert !
  4018. my %version = (
  4019. MAJOR => $data->{'data'}{'version'}{'major'},
  4020. MINOR => $data->{'data'}{'version'}{'minor'},
  4021. SMALL => $data->{'data'}{'version'}{'small'},
  4022. BUILD => $data->{'data'}{'version'}{'build'}
  4023. );
  4024. # Werte in $hash zur späteren Auswertung einfügen
  4025. $hash->{HELPER}{SVSVERSION} = \%version;
  4026. my $major = $version{"MAJOR"};
  4027. my $minor = $version{"MINOR"};
  4028. my $small = $version{"SMALL"};
  4029. my $build = $version{"BUILD"};
  4030. # simulieren einer anderen SVS-Version
  4031. if (AttrVal($name, "simu_SVSversion", undef)) {
  4032. Log3($name, 4, "$name - another SVS-version ".AttrVal($name, "simu_SVSversion", undef)." will be simulated");
  4033. #delete $version{"SMALL"} if ($version{"SMALL"});
  4034. my @vl = split (/\.|-/,AttrVal($name, "simu_SVSversion", ""));
  4035. $major = $vl[0];
  4036. $minor = $vl[1];
  4037. $small = ($vl[2] =~ /\d/)?$vl[2]:undef;
  4038. $build = "xxxx-simu";
  4039. }
  4040. my $avsc = $major.$minor.(($small=~/\d/)?$small:0);
  4041. my $avcomp = $hash->{COMPATIBILITY};
  4042. $avcomp =~ s/\.//g;
  4043. if($avsc <= $avcomp) {
  4044. readingsSingleUpdate($hash, "compstate", "true", 1);
  4045. } else {
  4046. readingsSingleUpdate($hash, "compstate", "false", 1);
  4047. Log3($name, 2, "$name - WARNING - your current/simulated SVS-version may be incompatible to the SSCam version $hash->{VERSION}");
  4048. }
  4049. if (!exists($data->{'data'}{'customizedPortHttp'})) {
  4050. delete $defs{$name}{READINGS}{SVScustomPortHttp};
  4051. }
  4052. if (!exists($data->{'data'}{'customizedPortHttps'})) {
  4053. delete $defs{$name}{READINGS}{SVScustomPortHttps};
  4054. }
  4055. readingsBeginUpdate($hash);
  4056. readingsBulkUpdate($hash,"SVScustomPortHttp",$data->{'data'}{'customizedPortHttp'});
  4057. readingsBulkUpdate($hash,"SVScustomPortHttps",$data->{'data'}{'customizedPortHttps'});
  4058. readingsBulkUpdate($hash,"SVSlicenseNumber",$data->{'data'}{'liscenseNumber'});
  4059. readingsBulkUpdate($hash,"SVSuserPriv",$userPriv);
  4060. if(defined($small)) {
  4061. readingsBulkUpdate($hash,"SVSversion",$major.".".$minor.".".$small."-".$build);
  4062. } else {
  4063. readingsBulkUpdate($hash,"SVSversion",$major.".".$minor."-".$build);
  4064. }
  4065. readingsBulkUpdate($hash,"Errorcode","none");
  4066. readingsBulkUpdate($hash,"Error","none");
  4067. readingsEndUpdate($hash, 1);
  4068. Log3($name, $verbose, "$name - Informations related to Surveillance Station retrieved");
  4069. } elsif ($OpMode eq "getStmUrlPath") {
  4070. # Parse SVS-Infos
  4071. my($camforcemcast,$mjpegHttp,$multicst,$mxpegHttp,$unicastOverHttp,$unicastPath);
  4072. if($apicammaxver < 9) {
  4073. $camforcemcast = SSCam_jboolmap($data->{'data'}{'pathInfos'}[0]{'forceEnableMulticast'});
  4074. $mjpegHttp = $data->{'data'}{'pathInfos'}[0]{'mjpegHttpPath'};
  4075. $multicst = $data->{'data'}{'pathInfos'}[0]{'multicstPath'};
  4076. $mxpegHttp = $data->{'data'}{'pathInfos'}[0]{'mxpegHttpPath'};
  4077. $unicastOverHttp = $data->{'data'}{'pathInfos'}[0]{'unicastOverHttpPath'};
  4078. $unicastPath = $data->{'data'}{'pathInfos'}[0]{'unicastPath'};
  4079. }
  4080. if($apicammaxver >= 9) {
  4081. $mjpegHttp = $data->{'data'}[0]{'mjpegHttpPath'};
  4082. $multicst = $data->{'data'}[0]{'multicstPath'};
  4083. $mxpegHttp = $data->{'data'}[0]{'mxpegHttpPath'};
  4084. $unicastOverHttp = $data->{'data'}[0]{'rtspOverHttpPath'};
  4085. $unicastPath = $data->{'data'}[0]{'rtspPath'};
  4086. }
  4087. # Rewrite Url's falls livestreamprefix ist gesetzt
  4088. if (AttrVal($name, "livestreamprefix", undef)) {
  4089. my @mjh = split(/\//, $mjpegHttp, 4);
  4090. $mjpegHttp = AttrVal($name, "livestreamprefix", undef)."/".$mjh[3];
  4091. my @mxh = split(/\//, $mxpegHttp, 4);
  4092. $mxpegHttp = AttrVal($name, "livestreamprefix", undef)."/".$mxh[3];
  4093. if($unicastPath) {
  4094. my @ucp = split(/[@\|:]/, $unicastPath);
  4095. my @lspf = split(/[\/\/\|:]/, AttrVal($name, "livestreamprefix", undef));
  4096. $unicastPath = $ucp[0].":".$ucp[1].":".$ucp[2]."@".$lspf[3].":".$ucp[4];
  4097. }
  4098. }
  4099. # StmKey extrahieren
  4100. my @sk = split(/&StmKey=/, $mjpegHttp);
  4101. my $stmkey = $sk[1];
  4102. $stmkey =~ tr/"//d;
  4103. # Quotes in StmKey entfernen falls noQuotesForSID gesezt
  4104. $mjpegHttp =~ tr/"//d if(AttrVal($name, "noQuotesForSID",0));
  4105. # Readings löschen falls sie nicht angezeigt werden sollen (showStmInfoFull)
  4106. #if (!AttrVal($name,"showStmInfoFull",0)) {
  4107. # delete($defs{$name}{READINGS}{StmKeymjpegHttp});
  4108. #delete($defs{$name}{READINGS}{StmKeyUnicstOverHttp});
  4109. #}
  4110. # Streaminginfos in Helper speichern
  4111. $hash->{HELPER}{STMKEYMJPEGHTTP} = $mjpegHttp if($mjpegHttp);
  4112. $hash->{HELPER}{STMKEYMXPEGHTTP} = $mxpegHttp if($mxpegHttp);
  4113. $hash->{HELPER}{STMKEYUNICSTOVERHTTP} = $unicastOverHttp if($unicastOverHttp);
  4114. $hash->{HELPER}{STMKEYUNICST} = $unicastPath if($unicastPath);
  4115. readingsBeginUpdate($hash);
  4116. readingsBulkUpdate($hash,"CamForceEnableMulticast",$camforcemcast) if($camforcemcast);
  4117. readingsBulkUpdate($hash,"StmKey",$stmkey);
  4118. readingsBulkUpdate($hash,"StmKeymjpegHttp",$mjpegHttp) if(AttrVal($name,"showStmInfoFull",0));
  4119. readingsBulkUpdate($hash,"StmKeymxpegHttp",$mxpegHttp) if(AttrVal($name,"showStmInfoFull",0));
  4120. readingsBulkUpdate($hash,"StmKeyUnicstOverHttp",$unicastOverHttp) if(AttrVal($name,"showStmInfoFull",0) && $unicastOverHttp);
  4121. readingsBulkUpdate($hash,"StmKeyUnicst",$unicastPath) if(AttrVal($name,"showStmInfoFull",0) && $unicastPath);
  4122. readingsBulkUpdate($hash,"Errorcode","none");
  4123. readingsBulkUpdate($hash,"Error","none");
  4124. readingsEndUpdate($hash, 1);
  4125. # Logausgabe
  4126. Log3($name, $verbose, "$name - Stream-URLs of camera $camname retrieved");
  4127. } elsif ($OpMode eq "Getcaminfo") {
  4128. # Parse Caminfos
  4129. $camLiveMode = $data->{'data'}->{'cameras'}->[0]->{'camLiveMode'};
  4130. if ($camLiveMode eq "0") {$camLiveMode = "Liveview from DS";}elsif ($camLiveMode eq "1") {$camLiveMode = "Liveview from Camera";}
  4131. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime;
  4132. $update_time = sprintf "%02d.%02d.%04d / %02d:%02d:%02d" , $mday , $mon+=1 ,$year+=1900 , $hour , $min , $sec ;
  4133. $deviceType = $data->{'data'}->{'cameras'}->[0]->{'deviceType'};
  4134. if ($deviceType eq "1") {
  4135. $deviceType = "Camera";
  4136. } elsif ($deviceType eq "2") {
  4137. $deviceType = "Video_Server";
  4138. } elsif ($deviceType eq "4") {
  4139. $deviceType = "PTZ";
  4140. } elsif ($deviceType eq "8") {
  4141. $deviceType = "Fisheye";
  4142. }
  4143. $camStatus = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'camStatus'});
  4144. if ($camStatus eq "1") {
  4145. $camStatus = "enabled";
  4146. # falls Aufnahme noch läuft -> STATE = on setzen
  4147. if (ReadingsVal("$name", "Record", "Stop") eq "Start") {
  4148. readingsSingleUpdate($hash,"state", "on", 0);
  4149. } else {
  4150. readingsSingleUpdate($hash,"state", "off", 0);
  4151. }
  4152. } elsif ($camStatus eq "3") {
  4153. $camStatus = "disconnected";
  4154. readingsSingleUpdate($hash,"state", "disconnected", 0);
  4155. } elsif ($camStatus eq "7") {
  4156. $camStatus = "disabled";
  4157. readingsSingleUpdate($hash,"state", "disabled", 0);
  4158. } else {
  4159. $camStatus = "other";
  4160. }
  4161. $recStatus = $data->{'data'}->{'cameras'}->[0]->{'recStatus'};
  4162. if ($recStatus ne "0") {
  4163. $recStatus = "Start";
  4164. } else {
  4165. $recStatus = "Stop";
  4166. }
  4167. my $rotate = $data->{'data'}->{'cameras'}->[0]->{'video_rotation'};
  4168. $rotate = $rotate == 1?"true":"false";
  4169. $exposuremode = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'exposure_mode'});
  4170. if ($exposuremode == 0) {
  4171. $exposuremode = "Auto";
  4172. } elsif ($exposuremode == 1) {
  4173. $exposuremode = "Day";
  4174. } elsif ($exposuremode == 2) {
  4175. $exposuremode = "Night";
  4176. } elsif ($exposuremode == 3) {
  4177. $exposuremode = "Schedule";
  4178. } elsif ($exposuremode == 4) {
  4179. $exposuremode = "Unknown";
  4180. }
  4181. $exposurecontrol = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'exposure_control'});
  4182. if ($exposurecontrol == 0) {
  4183. $exposurecontrol = "Auto";
  4184. } elsif ($exposurecontrol == 1) {
  4185. $exposurecontrol = "50HZ";
  4186. } elsif ($exposurecontrol == 2) {
  4187. $exposurecontrol = "60HZ";
  4188. } elsif ($exposurecontrol == 3) {
  4189. $exposurecontrol = "Hold";
  4190. } elsif ($exposurecontrol == 4) {
  4191. $exposurecontrol = "Outdoor";
  4192. } elsif ($exposurecontrol == 5) {
  4193. $exposurecontrol = "None";
  4194. } elsif ($exposurecontrol == 6) {
  4195. $exposurecontrol = "Unknown";
  4196. }
  4197. my $camaudiotype = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camAudioType'});
  4198. if ($camaudiotype == 0) {
  4199. $camaudiotype = "Unknown";
  4200. } elsif ($camaudiotype == 1) {
  4201. $camaudiotype = "PCM";
  4202. } elsif ($camaudiotype == 2) {
  4203. $camaudiotype = "G711";
  4204. } elsif ($camaudiotype == 3) {
  4205. $camaudiotype = "G726";
  4206. } elsif ($camaudiotype == 4) {
  4207. $camaudiotype = "AAC";
  4208. } elsif ($camaudiotype == 5) {
  4209. $camaudiotype = "AMR";
  4210. }
  4211. my $pdcap = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'PDCap'});
  4212. if (!$pdcap || $pdcap == 0) {
  4213. $pdcap = "false";
  4214. } else {
  4215. $pdcap = "true";
  4216. }
  4217. $data->{'data'}->{'cameras'}->[0]->{'video_flip'} = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'video_flip'});
  4218. $data->{'data'}->{'cameras'}->[0]->{'video_mirror'} = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'video_mirror'});
  4219. $data->{'data'}->{'cameras'}->[0]->{'blPresetSpeed'} = SSCam_jboolmap($data->{'data'}->{'cameras'}->[0]->{'blPresetSpeed'});
  4220. my $clstrmno = $data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camLiveStreamNo'};
  4221. $clstrmno++ if($clstrmno == 0);
  4222. my $fw = $data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camFirmware'};
  4223. readingsBeginUpdate($hash);
  4224. readingsBulkUpdate($hash,"CamAudioType",$camaudiotype);
  4225. readingsBulkUpdate($hash,"CamFirmware",$fw) if($fw);
  4226. readingsBulkUpdate($hash,"CamLiveMode",$camLiveMode);
  4227. readingsBulkUpdate($hash,"CamLiveFps",$data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camLiveFps'});
  4228. readingsBulkUpdate($hash,"CamLiveResolution",$data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camLiveResolution'});
  4229. readingsBulkUpdate($hash,"CamLiveQuality",$data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camLiveQuality'});
  4230. readingsBulkUpdate($hash,"CamLiveStreamNo",$clstrmno);
  4231. readingsBulkUpdate($hash,"CamExposureMode",$exposuremode);
  4232. readingsBulkUpdate($hash,"CamExposureControl",$exposurecontrol);
  4233. readingsBulkUpdate($hash,"CamModel",$data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camModel'});
  4234. readingsBulkUpdate($hash,"CamRecShare",$data->{'data'}->{'cameras'}->[0]->{'camRecShare'});
  4235. readingsBulkUpdate($hash,"CamRecVolume",$data->{'data'}->{'cameras'}->[0]->{'camRecVolume'});
  4236. readingsBulkUpdate($hash,"CamIP",$data->{'data'}->{'cameras'}->[0]->{'host'});
  4237. readingsBulkUpdate($hash,"CamNTPServer",$data->{'data'}->{'cameras'}->[0]->{'time_server'}) if($data->{'data'}->{'cameras'}->[0]->{'time_server'});
  4238. readingsBulkUpdate($hash,"CamVendor",$data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camVendor'});
  4239. readingsBulkUpdate($hash,"CamVideoType",$data->{'data'}->{'cameras'}->[0]->{'camVideoType'});
  4240. readingsBulkUpdate($hash,"CamPreRecTime",$data->{'data'}->{'cameras'}->[0]->{'detailInfo'}{'camPreRecTime'});
  4241. readingsBulkUpdate($hash,"CamPort",$data->{'data'}->{'cameras'}->[0]->{'port'});
  4242. readingsBulkUpdate($hash,"CamPtSpeed",$data->{'data'}->{'cameras'}->[0]->{'ptSpeed'}) if($deviceType =~ /PTZ/);
  4243. readingsBulkUpdate($hash,"CamblPresetSpeed",$data->{'data'}->{'cameras'}->[0]->{'blPresetSpeed'});
  4244. readingsBulkUpdate($hash,"CamVideoMirror",$data->{'data'}->{'cameras'}->[0]->{'video_mirror'});
  4245. readingsBulkUpdate($hash,"CamVideoFlip",$data->{'data'}->{'cameras'}->[0]->{'video_flip'});
  4246. readingsBulkUpdate($hash,"CamVideoRotate",$rotate);
  4247. readingsBulkUpdate($hash,"CapPIR",$pdcap);
  4248. readingsBulkUpdate($hash,"Availability",$camStatus);
  4249. readingsBulkUpdate($hash,"DeviceType",$deviceType);
  4250. readingsBulkUpdate($hash,"LastUpdateTime",$update_time);
  4251. readingsBulkUpdate($hash,"Record",$recStatus);
  4252. readingsBulkUpdate($hash,"UsedSpaceMB",$data->{'data'}->{'cameras'}->[0]->{'volume_space'});
  4253. readingsBulkUpdate($hash,"VideoFolder",AttrVal($name, "videofolderMap", undef) ? AttrVal($name, "videofolderMap", undef) : $data->{'data'}->{'cameras'}->[0]->{'folder'});
  4254. readingsBulkUpdate($hash,"Errorcode","none");
  4255. readingsBulkUpdate($hash,"Error","none");
  4256. readingsEndUpdate($hash, 1);
  4257. $hash->{MODEL} = ReadingsVal($name,"CamVendor","")." - ".ReadingsVal($name,"CamModel","CAM") if(SSCam_IsModelCam($hash));
  4258. Log3($name, $verbose, "$name - Informations of camera $camname retrieved");
  4259. } elsif ($OpMode eq "geteventlist") {
  4260. my $eventnum = $data->{'data'}{'total'};
  4261. my $lastrecord = $data->{'data'}{'events'}[0]{name};
  4262. $hash->{HELPER}{CAMLASTRECID} = $data->{'data'}{'events'}[0]{'eventId'};
  4263. my ($lastrecstarttime,$lastrecstoptime);
  4264. if ($eventnum > 0) {
  4265. $lastrecstarttime = $data->{'data'}{'events'}[0]{startTime};
  4266. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($lastrecstarttime);
  4267. $lastrecstarttime = sprintf "%02d.%02d.%04d / %02d:%02d:%02d" , $mday , $mon+=1 ,$year+=1900 , $hour , $min , $sec ;
  4268. $lastrecstoptime = $data->{'data'}{'events'}[0]{stopTime};
  4269. ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($lastrecstoptime);
  4270. $lastrecstoptime = sprintf "%02d:%02d:%02d" , $hour , $min , $sec ;
  4271. }
  4272. readingsBeginUpdate($hash);
  4273. readingsBulkUpdate($hash,"CamEventNum",$eventnum);
  4274. readingsBulkUpdate($hash,"CamLastRec",$lastrecord);
  4275. if ($lastrecstarttime) {readingsBulkUpdate($hash,"CamLastRecTime",$lastrecstarttime." - ". $lastrecstoptime);}
  4276. readingsBulkUpdate($hash,"Errorcode","none");
  4277. readingsBulkUpdate($hash,"Error","none");
  4278. readingsEndUpdate($hash, 1);
  4279. # Logausgabe
  4280. Log3($name, $verbose, "$name - Query eventlist of camera $camname retrieved");
  4281. } elsif ($OpMode eq "getmotionenum") {
  4282. $motdetsc = $data->{'data'}{'MDParam'}{'source'};
  4283. $sensitivity_camCap = $data->{'data'}{'MDParam'}{'sensitivity'}{'camCap'};
  4284. $sensitivity_value = $data->{'data'}{'MDParam'}{'sensitivity'}{'value'};
  4285. $sensitivity_ssCap = $data->{'data'}{'MDParam'}{'sensitivity'}{'ssCap'};
  4286. $threshold_camCap = $data->{'data'}{'MDParam'}{'threshold'}{'camCap'};
  4287. $threshold_value = $data->{'data'}{'MDParam'}{'threshold'}{'value'};
  4288. $threshold_ssCap = $data->{'data'}{'MDParam'}{'threshold'}{'ssCap'};
  4289. $percentage_camCap = $data->{'data'}{'MDParam'}{'percentage'}{'camCap'};
  4290. $percentage_value = $data->{'data'}{'MDParam'}{'percentage'}{'value'};
  4291. $percentage_ssCap = $data->{'data'}{'MDParam'}{'percentage'}{'ssCap'};
  4292. $objectSize_camCap = $data->{'data'}{'MDParam'}{'objectSize'}{'camCap'};
  4293. $objectSize_value = $data->{'data'}{'MDParam'}{'objectSize'}{'value'};
  4294. $objectSize_ssCap = $data->{'data'}{'MDParam'}{'objectSize'}{'ssCap'};
  4295. if ($motdetsc == -1) {
  4296. $motdetsc = "disabled";
  4297. }
  4298. elsif ($motdetsc == 0) {
  4299. $motdetsc = "Camera";
  4300. if ($sensitivity_camCap) {
  4301. $motdetsc .= ", sensitivity: $sensitivity_value";
  4302. }
  4303. if ($threshold_camCap) {
  4304. $motdetsc .= ", threshold: $threshold_value";
  4305. }
  4306. if ($percentage_camCap) {
  4307. $motdetsc .= ", percentage: $percentage_value";
  4308. }
  4309. if ($objectSize_camCap) {
  4310. $motdetsc .= ", objectSize: $objectSize_value";
  4311. }
  4312. }
  4313. elsif ($motdetsc == 1) {
  4314. $motdetsc = "SVS";
  4315. if ($sensitivity_ssCap) {
  4316. $motdetsc .= ", sensitivity: $sensitivity_value";
  4317. }
  4318. if ($threshold_ssCap) {
  4319. $motdetsc .= ", threshold: $threshold_value";
  4320. }
  4321. if ($percentage_ssCap) {
  4322. $motdetsc .= ", percentage: $percentage_value";
  4323. }
  4324. if ($objectSize_ssCap) {
  4325. $motdetsc .= ", objectSize: $objectSize_value";
  4326. }
  4327. }
  4328. # Setreading
  4329. readingsBeginUpdate($hash);
  4330. readingsBulkUpdate($hash,"CamMotDetSc",$motdetsc);
  4331. readingsBulkUpdate($hash,"Errorcode","none");
  4332. readingsBulkUpdate($hash,"Error","none");
  4333. readingsEndUpdate($hash, 1);
  4334. # Logausgabe
  4335. Log3($name, $verbose, "$name - Enumerate motion detection parameters of camera $camname retrieved");
  4336. } elsif ($OpMode eq "Getcapabilities") {
  4337. # Parse Infos
  4338. my $ptzfocus = $data->{'data'}{'ptzFocus'};
  4339. if ($ptzfocus eq "0") {
  4340. $ptzfocus = "false";
  4341. }
  4342. elsif ($ptzfocus eq "1") {
  4343. $ptzfocus = "support step operation";
  4344. }
  4345. elsif ($ptzfocus eq "2") {
  4346. $ptzfocus = "support continuous operation";
  4347. }
  4348. my $ptztilt = $data->{'data'}{'ptzTilt'};
  4349. if ($ptztilt eq "0") {
  4350. $ptztilt = "false";
  4351. }
  4352. elsif ($ptztilt eq "1") {
  4353. $ptztilt = "support step operation";
  4354. }
  4355. elsif ($ptztilt eq "2") {
  4356. $ptztilt = "support continuous operation";
  4357. }
  4358. my $ptzzoom = $data->{'data'}{'ptzZoom'};
  4359. if ($ptzzoom eq "0") {
  4360. $ptzzoom = "false";
  4361. }
  4362. elsif ($ptzzoom eq "1") {
  4363. $ptzzoom = "support step operation";
  4364. }
  4365. elsif ($ptzzoom eq "2") {
  4366. $ptzzoom = "support continuous operation";
  4367. }
  4368. my $ptzpan = $data->{'data'}{'ptzPan'};
  4369. if ($ptzpan eq "0") {
  4370. $ptzpan = "false";
  4371. }
  4372. elsif ($ptzpan eq "1") {
  4373. $ptzpan = "support step operation";
  4374. }
  4375. elsif ($ptzpan eq "2") {
  4376. $ptzpan = "support continuous operation";
  4377. }
  4378. my $ptziris = $data->{'data'}{'ptzIris'};
  4379. if ($ptziris eq "0") {
  4380. $ptziris = "false";
  4381. }
  4382. elsif ($ptziris eq "1") {
  4383. $ptziris = "support step operation";
  4384. }
  4385. elsif ($ptziris eq "2") {
  4386. $ptziris = "support continuous operation";
  4387. }
  4388. $data->{'data'}{'ptzHasObjTracking'} = SSCam_jboolmap($data->{'data'}{'ptzHasObjTracking'});
  4389. $data->{'data'}{'audioOut'} = SSCam_jboolmap($data->{'data'}{'audioOut'});
  4390. $data->{'data'}{'ptzSpeed'} = SSCam_jboolmap($data->{'data'}{'ptzSpeed'});
  4391. $data->{'data'}{'ptzAbs'} = SSCam_jboolmap($data->{'data'}{'ptzAbs'});
  4392. $data->{'data'}{'ptzAutoFocus'} = SSCam_jboolmap($data->{'data'}{'ptzAutoFocus'});
  4393. $data->{'data'}{'ptzHome'} = SSCam_jboolmap($data->{'data'}{'ptzHome'});
  4394. # Setreading
  4395. readingsBeginUpdate($hash);
  4396. readingsBulkUpdate($hash,"CapPTZAutoFocus",$data->{'data'}{'ptzAutoFocus'});
  4397. readingsBulkUpdate($hash,"CapAudioOut",$data->{'data'}{'audioOut'});
  4398. readingsBulkUpdate($hash,"CapChangeSpeed",$data->{'data'}{'ptzSpeed'});
  4399. readingsBulkUpdate($hash,"CapPTZHome",$data->{'data'}{'ptzHome'});
  4400. readingsBulkUpdate($hash,"CapPTZAbs",$data->{'data'}{'ptzAbs'});
  4401. readingsBulkUpdate($hash,"CapPTZDirections",$data->{'data'}{'ptzDirection'});
  4402. readingsBulkUpdate($hash,"CapPTZFocus",$ptzfocus);
  4403. readingsBulkUpdate($hash,"CapPTZIris",$ptziris);
  4404. readingsBulkUpdate($hash,"CapPTZObjTracking",$data->{'data'}{'ptzHasObjTracking'});
  4405. readingsBulkUpdate($hash,"CapPTZPan",$ptzpan);
  4406. readingsBulkUpdate($hash,"CapPTZPresetNumber",$data->{'data'}{'ptzPresetNumber'});
  4407. readingsBulkUpdate($hash,"CapPTZTilt",$ptztilt);
  4408. readingsBulkUpdate($hash,"CapPTZZoom",$ptzzoom);
  4409. readingsBulkUpdate($hash,"Errorcode","none");
  4410. readingsBulkUpdate($hash,"Error","none");
  4411. readingsEndUpdate($hash, 1);
  4412. # Logausgabe
  4413. Log3($name, $verbose, "$name - Capabilities of camera $camname retrieved");
  4414. } elsif ($OpMode eq "Getptzlistpreset") {
  4415. # Parse PTZ-ListPresets
  4416. my $presetcnt = $data->{'data'}->{'total'};
  4417. my $cnt = 0;
  4418. # alle Presets der Kamera mit Id's in Assoziatives Array einlesen
  4419. # "my" nicht am Anfang deklarieren, sonst wird Hash %allpresets wieder geleert !
  4420. my %allpresets;
  4421. my $home = "not set";
  4422. while ($cnt < $presetcnt) {
  4423. # my $presid = $data->{'data'}->{'presets'}->[$cnt]->{'id'};
  4424. my $presid = $data->{'data'}->{'presets'}->[$cnt]->{'position'};
  4425. my $presname = $data->{'data'}->{'presets'}->[$cnt]->{'name'};
  4426. $allpresets{$presname} = "$presid";
  4427. my $ptype = $data->{'data'}->{'presets'}->[$cnt]->{'type'};
  4428. if ($ptype) {
  4429. $home = $presname;
  4430. }
  4431. $cnt += 1;
  4432. }
  4433. # Presethash in $hash einfügen
  4434. $hash->{HELPER}{ALLPRESETS} = \%allpresets;
  4435. my @preskeys = sort(keys(%allpresets));
  4436. my $presetlist = join(",",@preskeys);
  4437. # Setreading
  4438. readingsBeginUpdate($hash);
  4439. readingsBulkUpdate($hash,"Presets",$presetlist);
  4440. readingsBulkUpdate($hash,"PresetHome",$home);
  4441. readingsBulkUpdate($hash,"Errorcode","none");
  4442. readingsBulkUpdate($hash,"Error","none");
  4443. readingsEndUpdate($hash, 1);
  4444. # spezifische Attribute für PTZ-Cams verfügbar machen
  4445. SSCam_addptzattr($name);
  4446. # Logausgabe
  4447. Log3($name, $verbose, "$name - PTZ Presets of camera $camname retrieved");
  4448. } elsif ($OpMode eq "Getptzlistpatrol") {
  4449. # Parse PTZ-ListPatrols
  4450. $patrolcnt = $data->{'data'}->{'total'};
  4451. my $cnt = 0;
  4452. # alle Patrols der Kamera mit Id's in Assoziatives Array einlesen
  4453. # "my" nicht am Anfang deklarieren, sonst wird Hash %allpatrols wieder geleert !
  4454. my %allpatrols = ();
  4455. while ($cnt < $patrolcnt) {
  4456. $patrolid = $data->{'data'}->{'patrols'}->[$cnt]->{'id'};
  4457. $patrolname = $data->{'data'}->{'patrols'}->[$cnt]->{'name'};
  4458. $allpatrols{$patrolname} = $patrolid;
  4459. $cnt += 1;
  4460. }
  4461. # Presethash in $hash einfügen
  4462. $hash->{HELPER}{ALLPATROLS} = \%allpatrols;
  4463. @patrolkeys = sort(keys(%allpatrols));
  4464. $patrollist = join(",",@patrolkeys);
  4465. # print "ID von Tour1 ist : ". %allpatrols->{Tour1};
  4466. # print "aus Hash: ".$hash->{HELPER}{ALLPRESETS}{Tour1};
  4467. readingsBeginUpdate($hash);
  4468. readingsBulkUpdate($hash,"Patrols",$patrollist);
  4469. readingsBulkUpdate($hash,"Errorcode","none");
  4470. readingsBulkUpdate($hash,"Error","none");
  4471. readingsEndUpdate($hash, 1);
  4472. # Logausgabe
  4473. Log3($name, $verbose, "$name - PTZ Patrols of camera $camname retrieved");
  4474. }
  4475. } else {
  4476. # die API-Operation war fehlerhaft
  4477. # Errorcode aus JSON ermitteln
  4478. $errorcode = $data->{'error'}->{'code'};
  4479. # Fehlertext zum Errorcode ermitteln
  4480. $error = SSCam_experror($hash,$errorcode);
  4481. # Setreading
  4482. readingsBeginUpdate($hash);
  4483. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  4484. readingsBulkUpdate($hash,"Error",$error);
  4485. readingsEndUpdate($hash, 1);
  4486. if ($errorcode =~ /105/) {
  4487. Log3($name, 2, "$name - ERROR - $errorcode - $error in operation $OpMode -> try new login");
  4488. return SSCam_login($hash,'SSCam_getapisites');
  4489. }
  4490. # Logausgabe
  4491. Log3($name, 2, "$name - ERROR - Operation $OpMode of Camera $camname was not successful. Errorcode: $errorcode - $error");
  4492. }
  4493. }
  4494. # Token freigeben
  4495. $hash->{HELPER}{ACTIVE} = "off";
  4496. if (AttrVal($name,"debugactivetoken",0)) {
  4497. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  4498. }
  4499. return;
  4500. }
  4501. #############################################################################################################################
  4502. ######### Hilfsroutinen #############
  4503. #############################################################################################################################
  4504. ####################################################################################
  4505. # Login in SVS wenn kein oder ungültige Session-ID vorhanden ist
  4506. sub SSCam_login ($$) {
  4507. my ($hash,$fret) = @_;
  4508. my $name = $hash->{NAME};
  4509. my $serveraddr = $hash->{SERVERADDR};
  4510. my $serverport = $hash->{SERVERPORT};
  4511. my $apiauth = $hash->{HELPER}{APIAUTH};
  4512. my $apiauthpath = $hash->{HELPER}{APIAUTHPATH};
  4513. my $apiauthmaxver = $hash->{HELPER}{APIAUTHMAXVER};
  4514. my $proto = $hash->{PROTOCOL};
  4515. my $lrt = AttrVal($name,"loginRetries",3);
  4516. my ($url,$param);
  4517. delete $hash->{HELPER}{SID} if($hash->{HELPER}{SID});
  4518. # Login und SID ermitteln
  4519. Log3($name, 4, "$name - --- Begin Function SSCam_login ---");
  4520. # Credentials abrufen
  4521. my ($success, $username, $password) = SSCam_getcredentials($hash,0);
  4522. unless ($success) {
  4523. Log3($name, 2, "$name - Credentials couldn't be retrieved successfully - make sure you've set it with \"set $name credentials <username> <password>\"");
  4524. $hash->{HELPER}{ACTIVE} = "off";
  4525. if (AttrVal($name,"debugactivetoken",0)) {
  4526. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  4527. }
  4528. return;
  4529. }
  4530. if($hash->{HELPER}{LOGINRETRIES} >= $lrt) {
  4531. # login wird abgebrochen, Freigabe Funktionstoken
  4532. $hash->{HELPER}{ACTIVE} = "off";
  4533. if (AttrVal($name,"debugactivetoken",0)) {
  4534. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  4535. }
  4536. Log3($name, 2, "$name - ERROR - Login or privilege of user $username unsuccessful");
  4537. return;
  4538. }
  4539. my $httptimeout = AttrVal($name,"httptimeout",4);
  4540. Log3($name, 5, "$name - HTTP-Call login will be done with httptimeout-Value: $httptimeout s");
  4541. my $urlwopw; # nur zur Anzeige bei verbose >= 4 und "showPassInLog" == 0
  4542. # sid in Quotes einschliessen oder nicht -> bei Problemen mit 402 - Permission denied
  4543. my $sid = AttrVal($name, "noQuotesForSID", "0") == 1 ? "sid" : "\"sid\"";
  4544. if (AttrVal($name,"session","DSM") eq "SurveillanceStation") {
  4545. $url = "$proto://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Login&account=$username&passwd=$password&session=SurveillanceStation&format=$sid";
  4546. $urlwopw = "$proto://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Login&account=$username&passwd=*****&session=SurveillanceStation&format=$sid";
  4547. } else {
  4548. $url = "$proto://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Login&account=$username&passwd=$password&format=$sid";
  4549. $urlwopw = "$proto://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Login&account=$username&passwd=*****&format=$sid";
  4550. }
  4551. AttrVal($name, "showPassInLog", "0") == 1 ? Log3($name, 4, "$name - Call-Out now: $url") : Log3($name, 4, "$name - Call-Out now: $urlwopw");
  4552. $hash->{HELPER}{LOGINRETRIES}++;
  4553. $param = {
  4554. url => $url,
  4555. timeout => $httptimeout,
  4556. hash => $hash,
  4557. user => $username,
  4558. funcret => $fret,
  4559. method => "GET",
  4560. header => "Accept: application/json",
  4561. callback => \&SSCam_login_return
  4562. };
  4563. HttpUtils_NonblockingGet ($param);
  4564. }
  4565. sub SSCam_login_return ($) {
  4566. my ($param, $err, $myjson) = @_;
  4567. my $hash = $param->{hash};
  4568. my $name = $hash->{NAME};
  4569. my $username = $param->{user};
  4570. my $fret = $param->{funcret};
  4571. my $subref = \&$fret;
  4572. my $success;
  4573. # Verarbeitung der asynchronen Rückkehrdaten aus sub "login_nonbl"
  4574. if ($err ne "") {
  4575. # ein Fehler bei der HTTP Abfrage ist aufgetreten
  4576. Log3($name, 2, "$name - error while requesting ".$param->{url}." - $err");
  4577. readingsSingleUpdate($hash, "Error", $err, 1);
  4578. return SSCam_login($hash,$fret);
  4579. } elsif ($myjson ne "") {
  4580. # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
  4581. # Evaluiere ob Daten im JSON-Format empfangen wurden
  4582. ($hash, $success) = SSCam_evaljson($hash,$myjson);
  4583. unless ($success) {
  4584. Log3($name, 4, "$name - no JSON-Data returned: ".$myjson);
  4585. $hash->{HELPER}{ACTIVE} = "off";
  4586. if (AttrVal($name,"debugactivetoken",0)) {
  4587. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  4588. }
  4589. return;
  4590. }
  4591. my $data = decode_json($myjson);
  4592. # Logausgabe decodierte JSON Daten
  4593. Log3($name, 5, "$name - JSON decoded: ". Dumper $data);
  4594. $success = $data->{'success'};
  4595. if ($success) {
  4596. # login war erfolgreich
  4597. my $sid = $data->{'data'}->{'sid'};
  4598. # Session ID in hash eintragen
  4599. $hash->{HELPER}{SID} = $sid;
  4600. # Setreading
  4601. readingsBeginUpdate($hash);
  4602. readingsBulkUpdate($hash,"Errorcode","none");
  4603. readingsBulkUpdate($hash,"Error","none");
  4604. readingsEndUpdate($hash, 1);
  4605. # Logausgabe
  4606. Log3($name, 4, "$name - Login of User $username successful - SID: $sid");
  4607. return &$subref($hash);
  4608. } else {
  4609. # Errorcode aus JSON ermitteln
  4610. my $errorcode = $data->{'error'}->{'code'};
  4611. # Fehlertext zum Errorcode ermitteln
  4612. my $error = SSCam_experrorauth($hash,$errorcode);
  4613. # Setreading
  4614. readingsBeginUpdate($hash);
  4615. readingsBulkUpdate($hash,"Errorcode",$errorcode);
  4616. readingsBulkUpdate($hash,"Error",$error);
  4617. readingsEndUpdate($hash, 1);
  4618. # Logausgabe
  4619. Log3($name, 3, "$name - Login of User $username unsuccessful. Code: $errorcode - $error - try again");
  4620. return SSCam_login($hash,$fret);
  4621. }
  4622. }
  4623. return SSCam_login($hash,$fret);
  4624. }
  4625. ###################################################################################
  4626. # Funktion logout
  4627. ###################################################################################
  4628. sub SSCam_logout ($) {
  4629. my ($hash) = @_;
  4630. my $name = $hash->{NAME};
  4631. my $serveraddr = $hash->{SERVERADDR};
  4632. my $serverport = $hash->{SERVERPORT};
  4633. my $apiauth = $hash->{HELPER}{APIAUTH};
  4634. my $apiauthpath = $hash->{HELPER}{APIAUTHPATH};
  4635. my $apiauthmaxver = $hash->{HELPER}{APIAUTHMAXVER};
  4636. my $sid = $hash->{HELPER}{SID};
  4637. my $proto = $hash->{PROTOCOL};
  4638. my $url;
  4639. my $param;
  4640. my $httptimeout;
  4641. Log3($name, 4, "$name - ####################################################");
  4642. Log3($name, 4, "$name - ### start cam operation $hash->{OPMODE} ");
  4643. Log3($name, 4, "$name - ####################################################");
  4644. Log3($name, 4, "$name - --- Begin Function SSCam_logout nonblocking ---");
  4645. $httptimeout = AttrVal($name,"httptimeout",4);
  4646. Log3($name, 5, "$name - HTTP-Call will be done with httptimeout-Value: $httptimeout s");
  4647. if (AttrVal($name,"session","DSM") eq "SurveillanceStation") {
  4648. $url = "$proto://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Logout&session=SurveillanceStation&_sid=$sid";
  4649. } else {
  4650. $url = "$proto://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Logout&_sid=$sid";
  4651. }
  4652. $param = {
  4653. url => $url,
  4654. timeout => $httptimeout,
  4655. hash => $hash,
  4656. method => "GET",
  4657. header => "Accept: application/json",
  4658. callback => \&SSCam_logout_return
  4659. };
  4660. HttpUtils_NonblockingGet ($param);
  4661. }
  4662. sub SSCam_logout_return ($) {
  4663. my ($param, $err, $myjson) = @_;
  4664. my $hash = $param->{hash};
  4665. my $name = $hash->{NAME};
  4666. my $sid = $hash->{HELPER}{SID};
  4667. my ($success, $username) = SSCam_getcredentials($hash,0);
  4668. my $OpMode = $hash->{OPMODE};
  4669. my $data;
  4670. my $error;
  4671. my $errorcode;
  4672. if($err ne "") {
  4673. # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
  4674. Log3($name, 2, "$name - error while requesting ".$param->{url}." - $err");
  4675. readingsSingleUpdate($hash, "Error", $err, 1);
  4676. } elsif($myjson ne "") {
  4677. # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
  4678. Log3($name, 4, "$name - URL-Call: ".$param->{url});
  4679. # Evaluiere ob Daten im JSON-Format empfangen wurden
  4680. ($hash, $success) = SSCam_evaljson($hash,$myjson);
  4681. unless ($success) {
  4682. Log3($name, 4, "$name - Data returned: ".$myjson);
  4683. $hash->{HELPER}{ACTIVE} = "off";
  4684. if (AttrVal($name,"debugactivetoken",0)) {
  4685. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  4686. }
  4687. return;
  4688. }
  4689. $data = decode_json($myjson);
  4690. # Logausgabe decodierte JSON Daten
  4691. Log3($name, 4, "$name - JSON returned: ". Dumper $data);
  4692. $success = $data->{'success'};
  4693. if ($success) {
  4694. # die Logout-URL konnte erfolgreich aufgerufen werden
  4695. Log3($name, 4, "$name - Session of User $username has ended - SID: \"$sid\" has been deleted");
  4696. } else {
  4697. # Errorcode aus JSON ermitteln
  4698. $errorcode = $data->{'error'}->{'code'};
  4699. # Fehlertext zum Errorcode ermitteln
  4700. $error = &SSCam_experrorauth($hash,$errorcode);
  4701. Log3($name, 2, "$name - ERROR - Logout of User $username was not successful, however SID: \"$sid\" has been deleted. Errorcode: $errorcode - $error");
  4702. }
  4703. }
  4704. # Session-ID aus Helper-hash löschen
  4705. delete $hash->{HELPER}{SID};
  4706. # ausgeführte Funktion ist erledigt (auch wenn logout nicht erfolgreich), Freigabe Funktionstoken
  4707. $hash->{HELPER}{ACTIVE} = "off";
  4708. if (AttrVal($name,"debugactivetoken",0)) {
  4709. Log3($name, 3, "$name - Active-Token deleted by OPMODE: $hash->{OPMODE}");
  4710. }
  4711. return;
  4712. }
  4713. ###############################################################################
  4714. # Test ob JSON-String empfangen wurde
  4715. ###############################################################################
  4716. sub SSCam_evaljson($$) {
  4717. my ($hash,$myjson) = @_;
  4718. my $OpMode = $hash->{OPMODE};
  4719. my $name = $hash->{NAME};
  4720. my $success = 1;
  4721. eval {decode_json($myjson)} or do
  4722. {
  4723. if($hash->{HELPER}{RUNVIEW} =~ m/^live_.*hls$/ || $OpMode =~ m/^.*_hls$/) {
  4724. # HLS aktivate/deaktivate bringt kein JSON wenn bereits aktiviert/deaktiviert
  4725. Log3($name, 5, "$name - HLS-activation data return: $myjson");
  4726. if ($myjson =~ m/{"success":true}/) {
  4727. $success = 1;
  4728. $myjson = '{"success":true}';
  4729. }
  4730. } else {
  4731. $success = 0;
  4732. # Setreading
  4733. readingsBeginUpdate($hash);
  4734. readingsBulkUpdate($hash,"Errorcode","none");
  4735. readingsBulkUpdate($hash,"Error","malformed JSON string received");
  4736. readingsEndUpdate($hash, 1);
  4737. }
  4738. };
  4739. return($hash,$success,$myjson);
  4740. }
  4741. ######################################################################################################
  4742. # Refresh eines Raumes aus $hash->{HELPER}{STRMROOM}
  4743. # bzw. Longpoll von SSCam bzw. eines SSCamSTRM Devices wenn
  4744. # $hash->{HELPER}{STRMDEV} gefüllt
  4745. # $hash, $pload (1=Page reload), SSCam-state-Event(1=Event), SSCamSTRM-Event (1=Event)
  4746. ######################################################################################################
  4747. sub SSCam_refresh($$$$) {
  4748. my ($hash,$pload,$lpoll_scm,$lpoll_strm) = @_;
  4749. my $name;
  4750. if (ref $hash ne "HASH")
  4751. {
  4752. ($name,$pload,$lpoll_scm,$lpoll_strm) = split ",",$hash;
  4753. $hash = $defs{$name};
  4754. } else {
  4755. $name = $hash->{NAME};
  4756. }
  4757. my $fpr = 0;
  4758. # Kontext des SSCamSTRM-Devices speichern für Refresh
  4759. my $sd = $hash->{HELPER}{STRMDEV}?$hash->{HELPER}{STRMDEV}:"\"n.a.\""; # Name des aufrufenden SSCamSTRM-Devices
  4760. my $sr = $hash->{HELPER}{STRMROOM}?$hash->{HELPER}{STRMROOM}:"\"n.a.\""; # Raum aus dem das SSCamSTRM-Device die Funktion aufrief
  4761. my $sl = $hash->{HELPER}{STRMDETAIL}?$hash->{HELPER}{STRMDETAIL}:"\"n.a.\""; # Name des SSCamSTRM-Devices (wenn Detailansicht)
  4762. $fpr = AttrVal($hash->{HELPER}{STRMDEV},"forcePageRefresh",0) if($hash->{HELPER}{STRMDEV});
  4763. Log3($name, 4, "$name - SSCam_refresh - caller: $sd, callerroom: $sr, detail: $sl, pload: $pload, forcePageRefresh: $fpr");
  4764. # Page-Reload
  4765. if($pload && $hash->{HELPER}{STRMROOM} && $hash->{HELPER}{STRMDETAIL}) {
  4766. if($hash->{HELPER}{STRMROOM} && !$hash->{HELPER}{STRMDETAIL} && !$fpr) {
  4767. Log3($name, 4, "$name - SSCam_refresh jetzt");
  4768. # trifft zu wenn in einer Raumansicht
  4769. my @rooms = split(",",$hash->{HELPER}{STRMROOM});
  4770. foreach (@rooms) {
  4771. my $room = $_;
  4772. { map { FW_directNotify("FILTER=room=$room", "#FHEMWEB:$_", "location.reload('true')", "") } devspec2array("TYPE=FHEMWEB") }
  4773. }
  4774. } elsif ( !$hash->{HELPER}{STRMROOM} || $hash->{HELPER}{STRMDETAIL} || $fpr ) {
  4775. # trifft zu bei Detailansicht oder im FLOORPLAN bzw. Dashboard oder wenn Seitenrefresh mit dem
  4776. # SSCamSTRM-Attribut "forcePageRefresh" erzwungen wird
  4777. { map { FW_directNotify("#FHEMWEB:$_", "location.reload('true')", "") } devspec2array("TYPE=FHEMWEB") }
  4778. }
  4779. } elsif ($fpr) {
  4780. # Seitenrefresh durch SSCamSTRM-Attribut "forcePageRefresh" erzwungen
  4781. { map { FW_directNotify("#FHEMWEB:$_", "location.reload('true')", "") } devspec2array("TYPE=FHEMWEB") }
  4782. }
  4783. # Aufnahmestatus/Disabledstatus in state abbilden & SSCam-Device state setzen (mit/ohne Event)
  4784. my $st = (ReadingsVal($name, "Availability", "enabled") eq "disabled")?"disabled":(ReadingsVal($name, "Record", "") eq "Start")?"on":"off";
  4785. if($lpoll_scm) {
  4786. readingsSingleUpdate($hash,"state", $st, 1);
  4787. } else {
  4788. readingsSingleUpdate($hash,"state", $st, 0);
  4789. }
  4790. # parentState des SSCamSTRM-Device mit Opmode updaten (mit/ohne Event)
  4791. my @strmdvs = devspec2array("TYPE=SSCamSTRM:FILTER=PARENT=".$name);
  4792. if(@strmdvs) {
  4793. foreach (@strmdvs) {
  4794. my $strmhash = $defs{$_};
  4795. if($lpoll_strm) {
  4796. readingsSingleUpdate($strmhash,"parentState", $hash->{OPMODE}, 1);
  4797. } else {
  4798. readingsSingleUpdate($strmhash,"parentState", $hash->{OPMODE}, 0);
  4799. }
  4800. }
  4801. }
  4802. return;
  4803. }
  4804. ###############################################################################
  4805. # Test ob MODEL=SVS (sonst ist es eine Cam)
  4806. ###############################################################################
  4807. sub SSCam_IsModelCam($){
  4808. my ($hash)= @_;
  4809. my $m = ($hash->{MODEL} ne "SVS")?1:0;
  4810. return($m);
  4811. }
  4812. ###############################################################################
  4813. # JSON Boolean Test und Mapping
  4814. ###############################################################################
  4815. sub SSCam_jboolmap($){
  4816. my ($bool)= @_;
  4817. if(JSON::is_bool($bool)) {
  4818. $bool = $bool?"true":"false";
  4819. }
  4820. return $bool;
  4821. }
  4822. ###############################################################################
  4823. # Schnappschußgalerie abrufen (snapGalleryBoost) o. nur Info des letzten Snaps
  4824. ###############################################################################
  4825. sub SSCam_snaplimsize ($) {
  4826. my ($hash)= @_;
  4827. my $name = $hash->{NAME};
  4828. my ($slim,$ssize);
  4829. if(!AttrVal($name,"snapGalleryBoost",0)) {
  4830. $slim = 1;
  4831. $ssize = 0;
  4832. } else {
  4833. $hash->{HELPER}{GETSNAPGALLERY} = 1;
  4834. $slim = AttrVal($name,"snapGalleryNumber",$SSCam_slim); # Anzahl der abzurufenden Snaps
  4835. my $sg = AttrVal($name,"snapGallerySize","Icon"); # Auflösung Image
  4836. $ssize = ($sg eq "Icon")?1:2;
  4837. }
  4838. return ($slim,$ssize);
  4839. }
  4840. ###############################################################################
  4841. # Helper für listLog-Argumente extrahieren
  4842. ###############################################################################
  4843. sub SSCam_extlogargs ($$) {
  4844. my ($hash,$a) = @_;
  4845. $hash->{HELPER}{LISTLOGSEVERITY} = (split("severity:",$a))[1] if(lc($a) =~ m/^severity:.*/);
  4846. $hash->{HELPER}{LISTLOGLIMIT} = (split("limit:",$a))[1] if(lc($a) =~ m/^limit:.*/);
  4847. $hash->{HELPER}{LISTLOGMATCH} = (split("match:",$a))[1] if(lc($a) =~ m/^match:.*/);
  4848. return;
  4849. }
  4850. ###############################################################################
  4851. # Helper für optimizeParams-Argumente extrahieren
  4852. ###############################################################################
  4853. sub SSCam_extoptpar($$$) {
  4854. my ($hash,$a,$cpcl) = @_;
  4855. $hash->{HELPER}{MIRROR} = (split("mirror:",$a))[1] if(lc($a) =~ m/^mirror:.*/);
  4856. $hash->{HELPER}{FLIP} = (split("flip:",$a))[1] if(lc($a) =~ m/^flip:.*/);
  4857. $hash->{HELPER}{ROTATE} = (split("rotate:",$a))[1] if(lc($a) =~ m/^rotate:.*/);
  4858. $hash->{HELPER}{NTPSERV} = (split("ntp:",$a))[1] if(lc($a) =~ m/^ntp:.*/);
  4859. $hash->{HELPER}{CHKLIST} = ($hash->{HELPER}{NTPSERV}?$cpcl->{ntp}:0)+
  4860. ($hash->{HELPER}{MIRROR}?$cpcl->{mirror}:0)+
  4861. ($hash->{HELPER}{FLIP}?$cpcl->{flip}:0)+
  4862. ($hash->{HELPER}{ROTATE}?$cpcl->{rotate}:0);
  4863. return;
  4864. }
  4865. ###############################################################################
  4866. # Helper für HLS Lieferfähigkeit
  4867. # HLS kann geliefert werden wenn "SYNO.SurveillanceStation.VideoStream"
  4868. # existiert und Reading CamStreamFormat "HLS" ist
  4869. ###############################################################################
  4870. sub SSCam_IsHLSCap($) {
  4871. my ($hash) = @_;
  4872. my $name = $hash->{NAME};
  4873. my $ret = 0;
  4874. my $api = $hash->{HELPER}{APIVIDEOSTMSMAXVER};
  4875. my $csf = (ReadingsVal($name,"CamStreamFormat","MJPEG") eq "HLS")?1:0;
  4876. $ret = 1 if($api && $csf);
  4877. return $ret;
  4878. }
  4879. ###############################################################################
  4880. # Clienthash übernehmen oder zusammenstellen
  4881. # Identifikation ob über FHEMWEB ausgelöst oder nicht -> erstellen $hash->CL
  4882. sub SSCam_getclhash($;$$) {
  4883. my ($hash,$nobgd)= @_;
  4884. my $name = $hash->{NAME};
  4885. my $ret;
  4886. if($nobgd) {
  4887. # nur übergebenen CL-Hash speichern,
  4888. # keine Hintergrundverarbeitung bzw. synthetische Erstellung CL-Hash
  4889. $hash->{HELPER}{CL}{1} = $hash->{CL};
  4890. return undef;
  4891. }
  4892. if (!defined($hash->{CL})) {
  4893. # Clienthash wurde nicht übergeben und wird erstellt (FHEMWEB Instanzen mit canAsyncOutput=1 analysiert)
  4894. my $outdev;
  4895. my @webdvs = devspec2array("TYPE=FHEMWEB:FILTER=canAsyncOutput=1:FILTER=STATE=Connected");
  4896. my $i = 1;
  4897. foreach (@webdvs) {
  4898. $outdev = $_;
  4899. next if(!$defs{$outdev});
  4900. $hash->{HELPER}{CL}{$i}->{NAME} = $defs{$outdev}{NAME};
  4901. $hash->{HELPER}{CL}{$i}->{NR} = $defs{$outdev}{NR};
  4902. $hash->{HELPER}{CL}{$i}->{COMP} = 1;
  4903. $i++;
  4904. }
  4905. } else {
  4906. # übergebenen CL-Hash in Helper eintragen
  4907. $hash->{HELPER}{CL}{1} = $hash->{CL};
  4908. }
  4909. # Clienthash auflösen zur Fehlersuche (aufrufende FHEMWEB Instanz
  4910. if (defined($hash->{HELPER}{CL}{1})) {
  4911. for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
  4912. Log3($name, 4, "$name - Clienthash number: $k");
  4913. while (my ($key,$val) = each(%{$hash->{HELPER}{CL}{$k}})) {
  4914. $val = $val?$val:" ";
  4915. Log3($name, 4, "$name - Clienthash: $key -> $val");
  4916. }
  4917. }
  4918. } else {
  4919. Log3($name, 2, "$name - Clienthash was neither delivered nor created !");
  4920. $ret = "Clienthash was neither delivered nor created. Can't use asynchronous output for function.";
  4921. }
  4922. return ($ret);
  4923. }
  4924. ###############################################################################
  4925. # konvertiere alle ptzPanel_rowXX-attribute zu html-Code für
  4926. # das generierte Widget und das weblink-Device ptzpanel_$name
  4927. ###############################################################################
  4928. sub SSCam_ptzpanel($;$$) {
  4929. my ($name,$ptzcdev,$ptzcontrol) = @_;
  4930. my $hash = $defs{$name};
  4931. my $iconpath = AttrVal("$name","ptzPanel_iconPath","www/images/sscam");
  4932. my $iconprefix = AttrVal("$name","ptzPanel_iconPrefix","black_btn_");
  4933. my $rowisset = 0;
  4934. my $ptz_ret;
  4935. my $row;
  4936. my @vl = split (/\.|-/,ReadingsVal($name, "SVSversion", ""));
  4937. if(@vl) {
  4938. my $actvs = $vl[0];
  4939. $actvs .= $vl[1];
  4940. return "" if($actvs <= 71);
  4941. }
  4942. $ptz_ret = "<div class=\"ptzpanel\">";
  4943. $ptz_ret.= '<table class="rc_body">';
  4944. foreach my $rownr (0..9) {
  4945. $rownr = sprintf("%2.2d",$rownr);
  4946. $row = AttrVal("$name","ptzPanel_row$rownr",undef);
  4947. next if (!$row);
  4948. $rowisset = 1;
  4949. $ptz_ret .= "<tr>";
  4950. my @btn = split (",",$row); # die Anzahl Buttons in einer Reihe
  4951. foreach my $btnnr (0..$#btn) {
  4952. $ptz_ret .= '<td class="rc_button">';
  4953. if ($btn[$btnnr] ne "") {
  4954. my $cmd;
  4955. my $img;
  4956. if ($btn[$btnnr] =~ /(.*?):(.*)/) { # enthält Komando -> <command>:<image>
  4957. $cmd = $1;
  4958. $img = $2;
  4959. } else { # button has format <command> or is empty
  4960. $cmd = $btn[$btnnr];
  4961. $img = $btn[$btnnr];
  4962. }
  4963. if ($img =~ m/\.svg/) { # Verwendung für SVG's
  4964. $img = FW_makeImage($img, $cmd, "rc-button");
  4965. } else {
  4966. $img = "<img src=\"$FW_ME/$iconpath/$iconprefix$img\">"; # $FW_ME = URL-Pfad unter dem der FHEMWEB-Server via HTTP erreichbar ist, z.B. /fhem
  4967. }
  4968. if ($cmd || $cmd eq "0") {
  4969. $cmd = "cmd=set $name $cmd";
  4970. $ptz_ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmd')\">$img</a>"; # $FW_subdir = Sub-path in URL, used by FLOORPLAN/weblink
  4971. } else {
  4972. $ptz_ret .= $img;
  4973. }
  4974. }
  4975. $ptz_ret .= "</td>";
  4976. $ptz_ret .= "\n";
  4977. }
  4978. $ptz_ret .= "</tr>\n";
  4979. }
  4980. $ptz_ret .= "</table>";
  4981. $ptz_ret .= "</div>";
  4982. if ($rowisset) {
  4983. return $ptz_ret;
  4984. } else {
  4985. return "";
  4986. }
  4987. }
  4988. ###############################################################################
  4989. # spezielle Attribute für PTZ-ControlPanel verfügbar machen
  4990. ###############################################################################
  4991. sub SSCam_addptzattr($) {
  4992. my ($name) = @_;
  4993. my $hash = $defs{$name};
  4994. my $actvs;
  4995. my @vl = split (/\.|-/,ReadingsVal($name, "SVSversion", ""));
  4996. if(@vl) {
  4997. $actvs = $vl[0];
  4998. $actvs.= $vl[1];
  4999. }
  5000. return if(ReadingsVal($name,"DeviceType","Camera") ne "PTZ" || $actvs <= 71);
  5001. foreach my $n (0..9) {
  5002. $n = sprintf("%2.2d",$n);
  5003. addToDevAttrList($name, "ptzPanel_row$n");
  5004. }
  5005. if(ReadingsVal("$name","Presets","") ne "") {
  5006. $attr{$name}{userattr} =~ s/ptzPanel_Home:$hash->{HELPER}{OLDPRESETS}//g if($hash->{HELPER}{OLDPRESETS} && ReadingsVal("$name","Presets","") ne $hash->{HELPER}{OLDPRESETS});
  5007. $hash->{HELPER}{OLDPRESETS} = ReadingsVal("$name","Presets","");
  5008. addToDevAttrList($name, "ptzPanel_Home:".ReadingsVal("$name","Presets",""));
  5009. }
  5010. addToDevAttrList($name, "ptzPanel_iconPrefix");
  5011. addToDevAttrList($name, "ptzPanel_iconPath");
  5012. addToDevAttrList($name, "ptzPanel_use:0,1");
  5013. # PTZ Panel Widget initial generieren
  5014. my $upleftfast = "move upleft";
  5015. my $upfast = "move up";
  5016. my $uprightfast = "move upright";
  5017. my $upleft = "move upleft 0.5";
  5018. my $up = "move up 0.5";
  5019. my $upright = "move upright 0.5";
  5020. my $leftfast = "move left";
  5021. my $left = "move left 0.5";
  5022. my $home = "goPreset ".AttrVal($name,"ptzPanel_Home",ReadingsVal($name,"PresetHome",""));
  5023. my $right = "move right 0.5";
  5024. my $rightfast = "move right";
  5025. my $downleft = "move downleft 0.5";
  5026. my $down = "move down 0.5";
  5027. my $downright = "move downright 0.5";
  5028. my $downleftfast = "move downleft";
  5029. my $downfast = "move down";
  5030. my $downrightfast = "move downright";
  5031. $attr{$name}{ptzPanel_row00} = "$upleftfast:CAMUPLEFTFAST.png,:CAMBLANK.png,$upfast:CAMUPFAST.png,:CAMBLANK.png,$uprightfast:CAMUPRIGHTFAST.png"
  5032. if(!AttrVal($name,"ptzPanel_row00",undef));
  5033. $attr{$name}{ptzPanel_row01} = ":CAMBLANK.png,$upleft:CAMUPLEFT.png,$up:CAMUP.png,$upright:CAMUPRIGHT.png"
  5034. if(!AttrVal($name,"ptzPanel_row01",undef));
  5035. $attr{$name}{ptzPanel_row02} = "$leftfast:CAMLEFTFAST.png,$left:CAMLEFT.png,$home:CAMHOME.png,$right:CAMRIGHT.png,$rightfast:CAMRIGHTFAST.png"
  5036. if(!AttrVal($name,"ptzPanel_row02",undef) || $home ne $hash->{HELPER}{OLDPTZHOME});
  5037. $attr{$name}{ptzPanel_row03} = ":CAMBLANK.png,$downleft:CAMDOWNLEFT.png,$down:CAMDOWN.png,$downright:CAMDOWNRIGHT.png"
  5038. if(!AttrVal($name,"ptzPanel_row03",undef));
  5039. $attr{$name}{ptzPanel_row04} = "$downleftfast:CAMDOWNLEFTFAST.png,:CAMBLANK.png,$downfast:CAMDOWNFAST.png,:CAMBLANK.png,$downrightfast:CAMDOWNRIGHTFAST.png"
  5040. if(!AttrVal($name,"ptzPanel_row04",undef));
  5041. $hash->{HELPER}{OLDPTZHOME} = $home;
  5042. $hash->{".ptzhtml"} = ""; # SSCam_ptzpanel wird neu durchlaufen
  5043. return;
  5044. }
  5045. ######################################################################################
  5046. # Stream einer Kamera - Kamera Liveview weblink device
  5047. # API: SYNO.SurveillanceStation.VideoStreaming
  5048. # Methode: GetLiveViewPath
  5049. ######################################################################################
  5050. sub SSCam_StreamDev($$$) {
  5051. my ($camname,$strmdev,$fmt) = @_;
  5052. my $hash = $defs{$camname};
  5053. my $wltype = $hash->{HELPER}{WLTYPE};
  5054. my $serveraddr = $hash->{SERVERADDR};
  5055. my $serverport = $hash->{SERVERPORT};
  5056. my $apivideostm = $hash->{HELPER}{APIVIDEOSTM};
  5057. my $apivideostmpath = $hash->{HELPER}{APIVIDEOSTMPATH};
  5058. my $apivideostmmaxver = $hash->{HELPER}{APIVIDEOSTMMAXVER};
  5059. my $apiaudiostm = $hash->{HELPER}{APIAUDIOSTM};
  5060. my $apiaudiostmpath = $hash->{HELPER}{APIAUDIOSTMPATH};
  5061. my $apiaudiostmmaxver = $hash->{HELPER}{APIAUDIOSTMMAXVER};
  5062. my $apivideostms = $hash->{HELPER}{APIVIDEOSTMS};
  5063. my $apivideostmspath = $hash->{HELPER}{APIVIDEOSTMSPATH};
  5064. my $apivideostmsmaxver = $hash->{HELPER}{APIVIDEOSTMSMAXVER};
  5065. my $camid = $hash->{CAMID};
  5066. my $sid = $hash->{HELPER}{SID};
  5067. my $proto = $hash->{PROTOCOL};
  5068. my ($cause,$ret,$link,$audiolink,$devWlink,$wlhash,$alias,$wlalias);
  5069. # Kontext des SSCamSTRM-Devices speichern für SSCam_refresh
  5070. $hash->{HELPER}{STRMDEV} = $strmdev; # Name des aufrufenden SSCamSTRM-Devices
  5071. $hash->{HELPER}{STRMROOM} = $FW_room?$FW_room:""; # Raum aus dem das SSCamSTRM-Device die Funktion aufrief
  5072. $hash->{HELPER}{STRMDETAIL} = $FW_detail?$FW_detail:""; # Name des SSCamSTRM-Devices (wenn Detailansicht)
  5073. # Definition Tasten
  5074. my $imgblank = "<img src=\"$FW_ME/www/images/sscam/black_btn_CAMBLANK.png\">"; # nicht sichtbare Leertaste
  5075. my $cmdstop = "cmd=set $camname stopView"; # Stream deaktivieren
  5076. my $imgstop = "<img src=\"$FW_ME/www/images/default/remotecontrol/black_btn_POWEROFF3.png\">";
  5077. my $cmdhlsreact = "cmd=set $camname hlsreactivate"; # HLS Stream reaktivieren
  5078. my $imghlsreact = "<img src=\"$FW_ME/www/images/default/remotecontrol/black_btn_BACKDroid.png\">";
  5079. my $cmdmjpegrun = "cmd=set $camname runView live_fw"; # MJPEG Stream aktivieren
  5080. my $imgmjpegrun = "<img src=\"$FW_ME/www/images/sscam/black_btn_MJPEG.png\">";
  5081. my $cmdhlsrun = "cmd=set $camname runView live_fw_hls"; # HLS Stream aktivieren
  5082. my $imghlsrun = "<img src=\"$FW_ME/www/images/sscam/black_btn_HLS.png\">";
  5083. my $cmdlrirun = "cmd=set $camname runView lastrec_fw"; # Last Record IFrame
  5084. my $imglrirun = "<img src=\"$FW_ME/www/images/sscam/black_btn_LASTRECIFRAME.png\">";
  5085. my $cmdlh264run = "cmd=set $camname runView lastrec_fw_MPEG4/H.264"; # Last Record H.264
  5086. my $imglh264run = "<img src=\"$FW_ME/www/images/sscam/black_btn_LRECH264.png\">";
  5087. my $cmdlmjpegrun = "cmd=set $camname runView lastrec_fw_MJPEG"; # Last Record MJPEG
  5088. my $imglmjpegrun = "<img src=\"$FW_ME/www/images/sscam/black_btn_LRECMJPEG.png\">";
  5089. my $cmdlsnaprun = "cmd=set $camname runView lastsnap_fw STRM"; # Last SNAP
  5090. my $imglsnaprun = "<img src=\"$FW_ME/www/images/sscam/black_btn_LSNAP.png\">";
  5091. my $cmdrecendless = "cmd=set $camname on 0"; # Endlosaufnahme Start
  5092. my $imgrecendless = "<img src=\"$FW_ME/www/images/sscam/black_btn_RECSTART.png\">";
  5093. my $cmdrecstop = "cmd=set $camname off"; # Aufnahme Stop
  5094. my $imgrecstop = "<img src=\"$FW_ME/www/images/sscam/black_btn_RECSTOP.png\">";
  5095. my $cmddosnap = "cmd=set $camname snap STRM"; # Snapshot auslösen mit Kennzeichnung "by STRM-Device"
  5096. my $imgdosnap = "<img src=\"$FW_ME/www/images/sscam/black_btn_DOSNAP.png\">";
  5097. my $cmdrefresh = "cmd=set $camname refresh STRM"; # Refresh in SSCamSTRM-Devices
  5098. my $imgrefresh = "<img src=\"$FW_ME/www/images/default/Restart.png\">";
  5099. my $ha = AttrVal($camname, "htmlattr", 'width="500" height="325"'); # HTML Attribute der Cam
  5100. $ha = AttrVal($strmdev, "htmlattr", $ha); # htmlattr mit htmattr Streaming-Device übersteuern
  5101. my $StmKey = ReadingsVal($camname,"StmKey",undef);
  5102. $ret = "";
  5103. $ret .= '<table class="block wide internals">';
  5104. $ret .= '<tbody>';
  5105. $ret .= '<tr class="odd">';
  5106. if(!$StmKey || ReadingsVal($camname, "Availability", "") ne "enabled" || IsDisabled($camname)) {
  5107. # Ausgabe bei Fehler
  5108. my $cam = AttrVal($camname, "alias", $camname);
  5109. $cause = !$StmKey?"Cam $cam has no Reading \"StmKey\" set !":"Cam \"$cam\" is disabled";
  5110. $cause = "Cam \"$cam\" is disabled" if(IsDisabled($camname));
  5111. $ret .= "<td> <br> <b> $cause </b> <br><br></td>";
  5112. $ret .= '</tr>';
  5113. $ret .= '</tbody>';
  5114. $ret .= '</table>';
  5115. $ret .= '</div>';
  5116. return $ret;
  5117. }
  5118. if($fmt =~ /mjpeg/) {
  5119. if($apivideostmsmaxver) { # keine API "SYNO.SurveillanceStation.VideoStream" mehr ab API v2.8
  5120. $link = "$proto://$serveraddr:$serverport/webapi/$apivideostmspath?api=$apivideostms&version=$apivideostmsmaxver&method=Stream&cameraId=$camid&format=mjpeg&_sid=$sid";
  5121. } elsif ($hash->{HELPER}{STMKEYMJPEGHTTP}) {
  5122. $link = $hash->{HELPER}{STMKEYMJPEGHTTP};
  5123. }
  5124. if($apiaudiostmmaxver) { # keine API "SYNO.SurveillanceStation.AudioStream" mehr ab API v2.8
  5125. $audiolink = "$proto://$serveraddr:$serverport/webapi/$apiaudiostmpath?api=$apiaudiostm&version=$apiaudiostmmaxver&method=Stream&cameraId=$camid&_sid=$sid";
  5126. }
  5127. $ret .= "<td><img src=$link $ha><br>";
  5128. if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
  5129. # Aufnahmebutton endlos Start
  5130. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>";
  5131. } else {
  5132. # Aufnahmebutton Stop
  5133. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
  5134. }
  5135. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>";
  5136. $ret .= "</td>";
  5137. if(AttrVal($camname,"ptzPanel_use",1)) {
  5138. my $ptz_ret = SSCam_ptzpanel($camname);
  5139. if($ptz_ret) {
  5140. $ret .= "<td>$ptz_ret</td>";
  5141. }
  5142. }
  5143. if($audiolink && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) {
  5144. $ret .= '</tr>';
  5145. $ret .= '<tr class="odd">';
  5146. $ret .= "<td><audio src=$audiolink preload='none' volume='0.5' controls>
  5147. Your browser does not support the audio element.
  5148. </audio>";
  5149. $ret .= "</td>";
  5150. }
  5151. } elsif($fmt =~ /generic/) {
  5152. my $htag = AttrVal($camname,"genericStrmHtmlTag","");
  5153. if( $htag =~ m/^\s*(.*)\s*$/s ) {
  5154. $htag = $1;
  5155. $htag =~ s/\$NAME/$camname/g;
  5156. $htag =~ s/\$HTMLATTR/$ha/g;
  5157. }
  5158. if(!$htag) {
  5159. $ret .= "<td> <br> <b> Set attribute \"genericStrmHtmlTag\" in device <a href=\"/fhem?detail=$camname\">$camname</a></b> <br><br></td>";
  5160. $ret .= '</tr>';
  5161. $ret .= '</tbody>';
  5162. $ret .= '</table>';
  5163. $ret .= '</div>';
  5164. return $ret;
  5165. }
  5166. $ret .= "<td>";
  5167. $ret .= "$htag";
  5168. $ret .= "<br>";
  5169. Log3($strmdev, 4, "$strmdev - generic Stream params:\n$htag");
  5170. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\">$imgrefresh </a>";
  5171. $ret .= $imgblank;
  5172. if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
  5173. # Aufnahmebutton endlos Start
  5174. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>";
  5175. } else {
  5176. # Aufnahmebutton Stop
  5177. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
  5178. }
  5179. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>";
  5180. $ret .= "</td>";
  5181. if(AttrVal($camname,"ptzPanel_use",1)) {
  5182. my $ptz_ret = SSCam_ptzpanel($camname);
  5183. if($ptz_ret) {
  5184. $ret .= "<td>$ptz_ret</td>";
  5185. }
  5186. }
  5187. } elsif($fmt =~ /switched/) {
  5188. my $wltype = $hash->{HELPER}{WLTYPE};
  5189. $link = $hash->{HELPER}{LINK};
  5190. if($link && $wltype =~ /image|iframe|video|base64img|embed|hls/) {
  5191. if($wltype =~ /image/) {
  5192. $ret .= "<td><img src=$link $ha><br>";
  5193. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  5194. $ret .= $imgblank;
  5195. if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
  5196. if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
  5197. # Aufnahmebutton endlos Start
  5198. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>";
  5199. } else {
  5200. # Aufnahmebutton Stop
  5201. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
  5202. }
  5203. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>";
  5204. }
  5205. $ret .= "</td>";
  5206. if(AttrVal($camname,"ptzPanel_use",1) && $hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
  5207. my $ptz_ret = SSCam_ptzpanel($camname);
  5208. if($ptz_ret) {
  5209. $ret .= "<td>$ptz_ret</td>";
  5210. }
  5211. }
  5212. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) {
  5213. $ret .= "</tr>";
  5214. $ret .= '<tr class="odd">';
  5215. $ret .= "<td><audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  5216. Your browser does not support the audio element.
  5217. </audio>";
  5218. }
  5219. } elsif ($wltype =~ /iframe/) {
  5220. $ret .= "<td><iframe src=$link $ha controls autoplay>
  5221. Iframes disabled
  5222. </iframe><br>";
  5223. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  5224. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\">$imgrefresh </a>";
  5225. $ret .= "</td>";
  5226. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) {
  5227. $ret .= '</tr>';
  5228. $ret .= '<tr class="odd">';
  5229. $ret .= "<td><audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  5230. Your browser does not support the audio element.
  5231. </audio>";
  5232. $ret .= "</td>";
  5233. }
  5234. } elsif ($wltype =~ /video/) {
  5235. $ret .= "<td><video $ha controls autoplay>
  5236. <source src=$link type=\"video/mp4\">
  5237. <source src=$link type=\"video/ogg\">
  5238. <source src=$link type=\"video/webm\">
  5239. Your browser does not support the video tag
  5240. </video><br>";
  5241. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  5242. $ret .= "</td>";
  5243. if($hash->{HELPER}{AUDIOLINK} && ReadingsVal($camname, "CamAudioType", "Unknown") !~ /Unknown/) {
  5244. $ret .= '</tr>';
  5245. $ret .= '<tr class="odd">';
  5246. $ret .= "<td><audio src=$hash->{HELPER}{AUDIOLINK} preload='none' volume='0.5' controls>
  5247. Your browser does not support the audio element.
  5248. </audio>";
  5249. $ret .= "</td>";
  5250. }
  5251. } elsif($wltype =~ /base64img/) {
  5252. $ret .= "<td><img src='data:image/jpeg;base64,$link' $ha><br>";
  5253. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  5254. $ret .= "</td>";
  5255. } elsif($wltype =~ /embed/) {
  5256. $ret .= "<td><embed src=$link $ha></td>";
  5257. } elsif($wltype =~ /hls/) {
  5258. $ret .= "<td><video $ha controls autoplay>
  5259. <source src=$link type=\"application/x-mpegURL\">
  5260. <source src=$link type=\"video/MP2T\">
  5261. Your browser does not support the video tag
  5262. </video><br>";
  5263. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdstop')\">$imgstop </a>";
  5264. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrefresh')\">$imgrefresh </a>";
  5265. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsreact')\">$imghlsreact </a>";
  5266. $ret .= $imgblank;
  5267. if(ReadingsVal($camname, "Record", "Stop") eq "Stop") {
  5268. # Aufnahmebutton endlos Start
  5269. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecendless')\">$imgrecendless </a>";
  5270. } else {
  5271. # Aufnahmebutton Stop
  5272. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdrecstop')\">$imgrecstop </a>";
  5273. }
  5274. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>";
  5275. $ret .= "</td>";
  5276. if(AttrVal($camname,"ptzPanel_use",1)) {
  5277. my $ptz_ret = SSCam_ptzpanel($camname);
  5278. if($ptz_ret) {
  5279. $ret .= "<td>$ptz_ret</td>";
  5280. }
  5281. }
  5282. }
  5283. } else {
  5284. my $cam = AttrVal($camname, "alias", $camname);
  5285. $cause = "Playback cam \"$cam\" switched off";
  5286. $ret .= "<td> <br> <b> $cause </b> <br><br>";
  5287. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdmjpegrun')\">$imgmjpegrun </a>";
  5288. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdhlsrun')\">$imghlsrun </a>" if(SSCam_IsHLSCap($hash));
  5289. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlrirun')\">$imglrirun </a>";
  5290. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlh264run')\">$imglh264run </a>";
  5291. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlmjpegrun')\">$imglmjpegrun </a>";
  5292. $ret .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmdlsnaprun')\">$imglsnaprun </a>";
  5293. $ret .= "</td>";
  5294. }
  5295. } else {
  5296. $cause = "Videoformat not supported";
  5297. $ret .= "<td> <br> <b> $cause </b> <br><br></td>";
  5298. }
  5299. $ret .= '</tr>';
  5300. $ret .= '</tbody>';
  5301. $ret .= '</table>';
  5302. Log3($strmdev, 4, "$strmdev - Link called: $link") if($link);
  5303. return $ret;
  5304. }
  5305. ###############################################################################
  5306. # Schnappschußgalerie zusammenstellen
  5307. ###############################################################################
  5308. sub composegallery ($;$$) {
  5309. my ($name,$strmdev,$model) = @_;
  5310. Log3($name, 1, "$name - SSCam will change the internal Code soon. Please delete your old Snapgallery-Device and create a new one by \"set $name createSnapGallery\" ");
  5311. my $htmlCode = SSCam_composegallery($name,$strmdev,$model);
  5312. return $htmlCode;
  5313. }
  5314. ###############################################################################
  5315. # Schnappschußgalerie zusammenstellen
  5316. ###############################################################################
  5317. sub SSCam_composegallery ($;$$) {
  5318. my ($name,$strmdev,$model) = @_;
  5319. my $hash = $defs{$name};
  5320. my $camname = $hash->{CAMNAME};
  5321. my $allsnaps = $hash->{HELPER}{".SNAPHASH"}; # = \%allsnaps
  5322. my $sgc = AttrVal($name,"snapGalleryColumns",3); # Anzahl der Images in einer Tabellenzeile
  5323. my $lss = ReadingsVal($name, "LastSnapTime", " "); # Zeitpunkt neueste Aufnahme
  5324. my $lang = AttrVal("global","language","EN"); # Systemsprache
  5325. my $limit = $hash->{HELPER}{SNAPLIMIT}; # abgerufene Anzahl Snaps
  5326. my $totalcnt = $hash->{HELPER}{TOTALCNT}; # totale Anzahl Snaps
  5327. $limit = $totalcnt if ($limit > $totalcnt); # wenn weniger Snaps vorhanden sind als $limit -> Text in Anzeige korrigieren
  5328. my $lupt = ((ReadingsTimestamp($name,"LastSnapTime"," ") gt ReadingsTimestamp($name,"LastUpdateTime"," "))
  5329. ? ReadingsTimestamp($name,"LastSnapTime"," ")
  5330. : ReadingsTimestamp($name,"LastUpdateTime"," ")); # letzte Aktualisierung
  5331. $lupt =~ s/ / \/ /;
  5332. my $cmddosnap = "cmd=set $name snap STRM"; # Snapshot auslösen mit Kennzeichnung "by STRM-Device"
  5333. my $imgdosnap = "<img src=\"$FW_ME/www/images/sscam/black_btn_DOSNAP.png\">";
  5334. my $ha = AttrVal($name, "snapGalleryHtmlAttr", AttrVal($name, "htmlattr", 'width="500" height="325"'));
  5335. # falls "SSCam_composegallery" durch ein SSCamSTRM-Device aufgerufen wird
  5336. my $devWlink = "";
  5337. if ($strmdev) {
  5338. my $wlha = AttrVal($strmdev, "htmlattr", undef);
  5339. $ha = (defined($wlha))?$wlha:$ha; # htmlattr vom SSCamSTRM-Device übernehmen falls von SSCamSTRM-Device aufgerufen und gesetzt
  5340. }
  5341. # wenn SSCamSTRM-device genutzt wird und attr "snapGalleryBoost" nicht gesetzt ist -> Warnung in Gallerie ausgeben
  5342. my $sgbnote = " ";
  5343. if($strmdev && !AttrVal($name,"snapGalleryBoost",0)) {
  5344. $sgbnote = "<b>CAUTION</b> - No snapshots can be retrieved. Please set the attribute \"snapGalleryBoost=1\" in device <a href=\"/fhem?detail=$name\">$name</a>" if ($lang eq "EN");
  5345. $sgbnote = "<b>ACHTUNG</b> - Es können keine Schnappschüsse abgerufen werden. Bitte setzen sie das Attribut \"snapGalleryBoost=1\" im Device <a href=\"/fhem?detail=$name\">$name</a>" if ($lang eq "DE");
  5346. }
  5347. my $header;
  5348. if ($lang eq "EN") {
  5349. $header = "Snapshots ($limit/$totalcnt) of camera <b>$camname</b> - newest Snapshot: $lss<br>";
  5350. $header .= " (Possibly another snapshots are available. Last recall: $lupt)<br>" if(AttrVal($name,"snapGalleryBoost",0));
  5351. } else {
  5352. $header = "Schnappschüsse ($limit/$totalcnt) von Kamera <b>$camname</b> - neueste Aufnahme: $lss <br>";
  5353. $header .= " (Eventuell sind neuere Aufnahmen verfügbar. Letzter Abruf: $lupt)<br>" if(AttrVal($name,"snapGalleryBoost",0));
  5354. }
  5355. $header .= $sgbnote;
  5356. my $gattr = (AttrVal($name,"snapGallerySize","Icon") eq "Full")?$ha:" ";
  5357. my @as = sort{$a <=>$b}keys%{$allsnaps};
  5358. # Ausgabetabelle erstellen
  5359. my ($htmlCode,$ct);
  5360. $htmlCode = "<html>";
  5361. $htmlCode .= sprintf("$devWlink <div class=\"makeTable wide\"; style=\"text-align:center\"> $header <br>");
  5362. $htmlCode .= "<table class=\"block wide internals\">";
  5363. $htmlCode .= "<tbody>";
  5364. $htmlCode .= "<tr class=\"odd\">";
  5365. my $cell = 1;
  5366. foreach my $key (@as) {
  5367. $ct = $allsnaps->{$key}{createdTm};
  5368. my $html = sprintf("<td>$ct<br /> <img $gattr src=\"data:image/jpeg;base64,$allsnaps->{$key}{imageData}\" /> </td>" );
  5369. $cell++;
  5370. if ( $cell == $sgc+1 ) {
  5371. $htmlCode .= $html;
  5372. $htmlCode .= "</tr>";
  5373. $htmlCode .= "<tr class=\"odd\">";
  5374. $cell = 1;
  5375. } else {
  5376. $htmlCode .= $html;
  5377. }
  5378. }
  5379. if ( $cell == 2 ) {
  5380. $htmlCode .= "<td> </td>";
  5381. }
  5382. $htmlCode .= "</tr>";
  5383. $htmlCode .= "</tbody>";
  5384. $htmlCode .= "</table>";
  5385. $htmlCode .= "</div>";
  5386. $htmlCode .= "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$cmddosnap')\">$imgdosnap </a>" if($strmdev);
  5387. $htmlCode .= "</html>";
  5388. return $htmlCode;
  5389. }
  5390. ##############################################################################
  5391. # Auflösung Errorcodes bei Login / Logout
  5392. ##############################################################################
  5393. sub SSCam_experrorauth {
  5394. # Übernahmewerte sind $hash, $errorcode
  5395. my ($hash,@errorcode) = @_;
  5396. my $device = $hash->{NAME};
  5397. my $errorcode = shift @errorcode;
  5398. my $error;
  5399. unless (exists($SSCam_errauthlist{"$errorcode"})) {$error = "Message of errorcode \"$errorcode\" not found. Please turn to Synology Web API-Guide."; return ($error);}
  5400. # Fehlertext aus Hash-Tabelle %errorauthlist ermitteln
  5401. $error = $SSCam_errauthlist{"$errorcode"};
  5402. return ($error);
  5403. }
  5404. ##############################################################################
  5405. # Auflösung Errorcodes SVS API
  5406. sub SSCam_experror {
  5407. # Übernahmewerte sind $hash, $errorcode
  5408. my ($hash,@errorcode) = @_;
  5409. my $device = $hash->{NAME};
  5410. my $errorcode = shift @errorcode;
  5411. my $error;
  5412. unless (exists($SSCam_errlist{"$errorcode"})) {$error = "Message of errorcode $errorcode not found. Please turn to Synology Web API-Guide."; return ($error);}
  5413. # Fehlertext aus Hash-Tabelle %errorlist ermitteln
  5414. $error = $SSCam_errlist{"$errorcode"};
  5415. return ($error);
  5416. }
  5417. 1;
  5418. =pod
  5419. =item summary Camera module to control the Synology Surveillance Station
  5420. =item summary_DE Kamera-Modul für die Steuerung der Synology Surveillance Station
  5421. =begin html
  5422. <a name="SSCam"></a>
  5423. <h3>SSCam</h3>
  5424. <ul>
  5425. Using this Module you are able to operate cameras which are defined in Synology Surveillance Station (SVS) and execute
  5426. functions of the SVS. It is based on the SVS API and supports the SVS version 7 and above.<br>
  5427. At present the following functions are available: <br><br>
  5428. <ul>
  5429. <ul>
  5430. <li>Start a Recording</li>
  5431. <li>Stop a Recording (using command or automatically after the &lt;RecordTime&gt; period</li>
  5432. <li>Trigger a Snapshot </li>
  5433. <li>Deaktivate a Camera in Synology Surveillance Station</li>
  5434. <li>Activate a Camera in Synology Surveillance Station</li>
  5435. <li>Control of the exposure modes day, night and automatic </li>
  5436. <li>switchover the motion detection by camera, by SVS or deactivate it </li>
  5437. <li>control of motion detection parameters sensitivity, threshold, object size and percentage for release </li>
  5438. <li>Retrieval of Camera Properties (also by Polling) as well as informations about the installed SVS-package</li>
  5439. <li>Move to a predefined Preset-position (at PTZ-cameras) </li>
  5440. <li>Start a predefined Patrol (at PTZ-cameras) </li>
  5441. <li>Positioning of PTZ-cameras to absolute X/Y-coordinates </li>
  5442. <li>continuous moving of PTZ-camera lense </li>
  5443. <li>trigger of external events 1-10 (action rules in SVS) </li>
  5444. <li>start and stop of camera livestreams incl. audio replay, show the last recording and snapshot </li>
  5445. <li>fetch of livestream-Url's with key (login not needed in that case) </li>
  5446. <li>playback of last recording and playback the last snapshot </li>
  5447. <li>switch the Surveillance Station HomeMode on/off and retrieve the HomeModeState </li>
  5448. <li>show the stored credentials of a device </li>
  5449. <li>fetch the Surveillance Station Logs, exploit the newest entry as reading </li>
  5450. <li>create a gallery of the last 1-10 snapshots (as Popup or in a discrete device) </li>
  5451. <li>Start/Stop Object Tracking (only supported PTZ-Cams with this capability) </li>
  5452. <li>set/delete a Preset (at PTZ-cameras) </li>
  5453. <li>set a Preset or current position as Home Preset (at PTZ-cameras) </li>
  5454. <li>provides a panel for camera control (at PTZ-cameras) </li>
  5455. <li>create different types of discrete Streaming-Devices (createStreamDev) </li>
  5456. <li>Activation / Deactivation of a camera integrated PIR sensor </li>
  5457. </ul>
  5458. </ul>
  5459. <br>
  5460. The recordings and snapshots will be stored in Synology Surveillance Station (SVS) and are managed like the other (normal) recordings / snapshots defined by Surveillance Station rules.<br>
  5461. For example the recordings are stored for a defined time in Surveillance Station and will be deleted after that period.<br><br>
  5462. If you like to discuss or help to improve this module please use FHEM-Forum with link: <br>
  5463. <a href="http://forum.fhem.de/index.php/topic,45671.msg374390.html#msg374390">49_SSCam: Fragen, Hinweise, Neuigkeiten und mehr rund um dieses Modul</a>.<br><br>
  5464. <b> Prerequisites </b> <br><br>
  5465. This module uses the Perl-module JSON. <br>
  5466. On Debian-Linux based systems this module can be installed by: <br><br>
  5467. <code>sudo apt-get install libjson-perl</code> <br><br>
  5468. SSCam is completely using the nonblocking functions of HttpUtils respectively HttpUtils_NonblockingGet. <br>
  5469. In DSM respectively in Synology Surveillance Station an User has to be created. The login credentials are needed later when using a set-command to assign the login-data to a device. <br>
  5470. Further informations could be find among <a href="#SSCam_Credentials">Credentials</a>. <br><br>
  5471. Overview which Perl-modules SSCam is using: <br><br>
  5472. JSON <br>
  5473. Data::Dumper <br>
  5474. MIME::Base64 <br>
  5475. Time::HiRes <br>
  5476. HttpUtils (FHEM-module) <br><br>
  5477. <a name="SSCamdefine"></a>
  5478. <b>Define</b>
  5479. <ul>
  5480. <br>
  5481. There is a distinction between the definition of a camera-device and the definition of a Surveillance Station (SVS)
  5482. device, that means the application on the discstation itself.
  5483. Dependend on the type of defined device the internal MODEL will be set to "&lt;vendor&gt; - &lt;camera type&gt;"
  5484. or "SVS" and a proper subset of the described set/get-commands are assigned to the device. <br>
  5485. The scope of application of set/get-commands is denoted to every particular command (valid for CAM, SVS, CAM/SVS).
  5486. <br><br>
  5487. A <b>camera</b> is defined by: <br><br>
  5488. <ul>
  5489. <b><code>define &lt;Name&gt; SSCAM &lt;camera name in SVS&gt; &lt;ServerAddr&gt; [Port] [Protocol]</code></b> <br><br>
  5490. </ul>
  5491. At first the devices have to be set up and has to be operable in Synology Surveillance Station 7.0 and above. <br><br>
  5492. A <b>SVS-device</b> to control functions of the Surveillance Station (SVS) is defined by: <br><br>
  5493. <ul>
  5494. <b><code>define &lt;Name&gt; SSCAM SVS &lt;ServerAddr&gt; [Port] [Protocol] </code></b> <br><br>
  5495. </ul>
  5496. In that case the term &lt;camera name in SVS&gt; become replaced by <b>SVS</b> only. <br><br>
  5497. The Modul SSCam ist based on functions of Synology Surveillance Station API. <br><br>
  5498. The parameters are in detail:
  5499. <br>
  5500. <br>
  5501. <table>
  5502. <colgroup> <col width=15%> <col width=85%> </colgroup>
  5503. <tr><td><b>Name</b> </td><td>the name of the new device to use in FHEM</td></tr>
  5504. <tr><td><b>Cameraname</b> </td><td>camera name as defined in Synology Surveillance Station if camera-device, "SVS" if SVS-Device. Spaces are not allowed in camera name. </td></tr>
  5505. <tr><td><b>ServerAddr</b> </td><td>IP-address of Synology Surveillance Station Host. <b>Note:</b> avoid using hostnames because of DNS-Calls are not unblocking in FHEM </td></tr>
  5506. <tr><td><b>Port</b> </td><td>optional - the port of synology disc station. If not set, the default "5000" is used</td></tr>
  5507. <tr><td><b>Protocol</b> </td><td>optional - the protocol (http or https) to access the synology disc station. If not set, the default "http" is used</td></tr>
  5508. </table>
  5509. <br><br>
  5510. <b>Examples:</b>
  5511. <pre>
  5512. <code>define CamCP SSCAM Carport 192.168.2.20 [5000] [http]</code>
  5513. <code>define CamCP SSCAM Carport 192.168.2.20 [5001] [https]</code>
  5514. # creates a new camera device CamCP
  5515. <code>define DS1 SSCAM SVS 192.168.2.20 [5000] [http]</code>
  5516. <code>define DS1 SSCAM SVS 192.168.2.20 [5001] [https]</code>
  5517. # creares a new SVS device DS1
  5518. </pre>
  5519. When a new Camera is defined, as a start the recordingtime of 15 seconds will be assigned to the device.<br>
  5520. Using the <a href="#SSCamattr">attribute</a> "rectime" you can adapt the recordingtime for every camera individually.<br>
  5521. The value of "0" for rectime will lead to an endless recording which has to be stopped by a "set &lt;name&gt; off" command.<br>
  5522. Due to a Log-Entry with a hint to that circumstance will be written. <br><br>
  5523. If the <a href="#SSCamattr">attribute</a> "rectime" would be deleted again, the default-value for recording-time (15s) become active.<br><br>
  5524. With <a href="#SSCamset">command</a> <b>"set &lt;name&gt; on [rectime]"</b> a temporary recordingtime is determinded which would overwrite the dafault-value of recordingtime <br>
  5525. and the attribute "rectime" (if it is set) uniquely. <br><br>
  5526. In that case the command <b>"set &lt;name&gt; on 0"</b> leads also to an endless recording as well.<br><br>
  5527. If you have specified a pre-recording time in SVS it will be considered too. <br><br>
  5528. If the module recognizes the defined camera as a PTZ-device (Reading "DeviceType = PTZ"), then a control panel is
  5529. created automatically in the detal view. This panel requires SVS >= 7.1. The properties and the behave of the
  5530. panel can be affected by <a href="#SSCamattr">attributes</a> "ptzPanel_.*". <br>
  5531. Please see also <a href="#SSCamset">command</a> <b>"set &lt;name&gt; createPTZcontrol"</b> in this context.
  5532. <br><br><br>
  5533. </ul>
  5534. <a name="SSCam_Credentials"></a>
  5535. <b>Credentials </b><br><br>
  5536. <ul>
  5537. After a camera-device is defined, firstly it is needed to save the credentials. This will be done with command:
  5538. <pre>
  5539. set &lt;name&gt; credentials &lt;username&gt; &lt;password&gt;
  5540. </pre>
  5541. The password length has a maximum of 20 characters. <br>
  5542. The operator can, dependend on what functions are planned to execute, create an user in DSM respectively in Synology Surveillance Station as well. <br>
  5543. If the user is member of admin-group, he has access to all module functions. Without this membership the user can only execute functions with lower need of rights. <br>
  5544. The required minimum rights to execute functions are listed in a table further down. <br>
  5545. Alternatively to DSM-user a user created in SVS can be used. Also in that case a user of type "manager" has the right to execute all functions, <br>
  5546. whereat the access to particular cameras can be restricted by the privilege profile (please see help function in SVS for details). <br>
  5547. As best practice it is proposed to create an user in DSM as well as in SVS too: <br><br>
  5548. <ul>
  5549. <li>DSM-User as member of admin group: unrestricted test of all module functions -&gt; session: DSM </li>
  5550. <li>SVS-User as Manager or observer: adjusted privilege profile -&gt; session: SurveillanceStation </li>
  5551. </ul>
  5552. <br>
  5553. Using the <a href="#SSCamattr">Attribute</a> "session" can be selected, if the session should be established to DSM or the SVS instead. <br>
  5554. If the session will be established to DSM, SVS Web-API methods are available as well as further API methods of other API's what possibly needed for processing. <br><br>
  5555. After device definition the default is "login to DSM", that means credentials with admin rights can be used to test all camera-functions firstly. <br>
  5556. After this the credentials can be switched to a SVS-session with a restricted privilege profile as needed on dependency what module functions are want to be executed. <br><br>
  5557. The following list shows the minimum rights what the particular module function needs. <br><br>
  5558. <ul>
  5559. <table>
  5560. <colgroup> <col width=20%> <col width=80%> </colgroup>
  5561. <tr><td><li>set ... on </td><td> session: ServeillanceStation - observer with enhanced privilege "manual recording" </li></td></tr>
  5562. <tr><td><li>set ... off </td><td> session: ServeillanceStation - observer with enhanced privilege "manual recording" </li></td></tr>
  5563. <tr><td><li>set ... snap </td><td> session: ServeillanceStation - observer </li></td></tr>
  5564. <tr><td><li>set ... delPreset </td><td> session: ServeillanceStation - observer </li></td></tr>
  5565. <tr><td><li>set ... disable </td><td> session: ServeillanceStation - manager </li></td></tr>
  5566. <tr><td><li>set ... enable </td><td> session: ServeillanceStation - manager </li></td></tr>
  5567. <tr><td><li>set ... expmode </td><td> session: ServeillanceStation - manager </li></td></tr>
  5568. <tr><td><li>set ... extevent </td><td> session: DSM - user as member of admin-group </li></td></tr>
  5569. <tr><td><li>set ... goPreset </td><td> session: ServeillanceStation - observer with privilege objective control of camera </li></td></tr>
  5570. <tr><td><li>set ... homeMode </td><td> ssession: ServeillanceStation - observer with privilege Home Mode switch </li></td></tr>
  5571. <tr><td><li>set ... motdetsc </td><td> session: ServeillanceStation - manager </li></td></tr>
  5572. <tr><td><li>set ... runPatrol </td><td> session: ServeillanceStation - observer with privilege objective control of camera </li></td></tr>
  5573. <tr><td><li>set ... goAbsPTZ </td><td> session: ServeillanceStation - observer with privilege objective control of camera </li></td></tr>
  5574. <tr><td><li>set ... move </td><td> session: ServeillanceStation - observer with privilege objective control of camera </li></td></tr>
  5575. <tr><td><li>set ... runView </td><td> session: ServeillanceStation - observer with privilege liveview of camera </li></td></tr>
  5576. <tr><td><li>set ... setHome </td><td> session: ServeillanceStation - observer </li></td></tr>
  5577. <tr><td><li>set ... setPreset </td><td> session: ServeillanceStation - observer </li></td></tr>
  5578. <tr><td><li>set ... snap </td><td> session: ServeillanceStation - observer </li></td></tr>
  5579. <tr><td><li>set ... snapGallery </td><td> session: ServeillanceStation - observer </li></td></tr>
  5580. <tr><td><li>set ... stopView </td><td> - </li></td></tr>
  5581. <tr><td><li>set ... credentials </td><td> - </li></td></tr>
  5582. <tr><td><li>get ... caminfo[all] </td><td> session: ServeillanceStation - observer </li></td></tr>
  5583. <tr><td><li>get ... eventlist </td><td> session: ServeillanceStation - observer </li></td></tr>
  5584. <tr><td><li>get ... listLog </td><td> session: ServeillanceStation - observer </li></td></tr>
  5585. <tr><td><li>get ... listPresets </td><td> session: ServeillanceStation - observer </li></td></tr>
  5586. <tr><td><li>get ... scanVirgin </td><td> session: ServeillanceStation - observer </li></td></tr>
  5587. <tr><td><li>get ... svsinfo </td><td> session: ServeillanceStation - observer </li></td></tr>
  5588. <tr><td><li>get ... snapfileinfo </td><td> session: ServeillanceStation - observer </li></td></tr>
  5589. <tr><td><li>get ... snapinfo </td><td> session: ServeillanceStation - observer </li></td></tr>
  5590. <tr><td><li>get ... stmUrlPath </td><td> session: ServeillanceStation - observer </li></td></tr>
  5591. </table>
  5592. </ul>
  5593. <br><br>
  5594. <a name="SSCam_HTTPTimeout"></a>
  5595. <b>HTTP-Timeout Settings</b><br><br>
  5596. All functions of SSCam use HTTP-calls to SVS Web API. <br>
  5597. The default-value of HTTP-Timeout amounts 4 seconds. You can set the <a href="#SSCamattr">attribute</a> "httptimeout" > 0 to adjust the value as needed in your technical environment. <br>
  5598. </ul>
  5599. <br><br><br>
  5600. <a name="SSCamset"></a>
  5601. <b>Set </b>
  5602. <ul>
  5603. <br>
  5604. The specified set-commands are available for CAM/SVS-devices or only valid for CAM-devices or rather for SVS-Devices.
  5605. They can be selected in the drop-down-menu of the particular device. <br><br>
  5606. <ul>
  5607. <a name="SSCamcreateStreamDev"></a>
  5608. <li><b> set &lt;name&gt; createStreamDev [generic | mjpeg | switched] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5609. A separate Streaming-Device (type SSCamSTRM) will be created. This device can be used as a discrete device in a dashboard for example.
  5610. The current room of the parent camera device is assigned to the new device if it is set there.
  5611. <br><br>
  5612. <ul>
  5613. <table>
  5614. <colgroup> <col width=10%> <col width=90%> </colgroup>
  5615. <tr><td>generic </td><td>- the streaming device playback a content determined by attribute "genericStrmHtmlTag" </td></tr>
  5616. <tr><td>mjpeg </td><td>- the streaming device playback a permanent MJPEG video stream (Streamkey method) </td></tr>
  5617. <tr><td>switched </td><td>- playback of different streaming types. Buttons for mode control are provided. </td></tr>
  5618. </table>
  5619. </ul>
  5620. <br><br>
  5621. You can control the design with HTML tags in <a href="#SSCamattr">attribute</a> "htmlattr" of the camera device or by the
  5622. specific attributes of the SSCamSTRM-device itself. <br>
  5623. In "switched"-Devices are buttons provided for mode control. <br>
  5624. If HLS (HTTP Live Streaming) is used in Streaming-Device of type "switched", then the camera has to be set to video format
  5625. H.264 in the Synology Surveillance Station and the SVS-Version has to support the HLS format.
  5626. Therefore the selection button of HLS is only provided by the Streaming-Device if the Reading "CamStreamFormat" contains
  5627. "HLS". <br>
  5628. HTTP Live Streaming is currently only available on Mac Safari or modern mobile iOS/Android devices. <br>
  5629. In devices of type "switched" buttons for controlling the media type to start are provided. <br>
  5630. A Streaming-Device of type "generic" needs the complete definition of HTML-Tags by the attribute "genericStrmHtmlTag".
  5631. These tags specify the content to playback. <br><br>
  5632. <ul>
  5633. <b>Example:</b>
  5634. <pre>
  5635. attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
  5636. &lt;source src='http://192.168.2.10:32000/$NAME.m3u8' type='application/x-mpegURL'&gt;
  5637. &lt;/video&gt;
  5638. </pre>
  5639. The variables $HTMLATTR, $NAME are placeholder and absorb the attribute "htmlattr" (if set) respectively the SSCam-Devicename.
  5640. </ul>
  5641. </ul>
  5642. <br><br>
  5643. <ul>
  5644. <li><b> set &lt;name&gt; createPTZcontrol </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br>
  5645. A separate PTZ-control panel will be created (type SSCamSTRM). The current room of the parent camera device is
  5646. assigned if it is set there.
  5647. With the "ptzPanel_.*"-<a href="#SSCamattr">attributes</a> or respectively the specific attributes of the SSCamSTRM-device
  5648. the properties of the control panel can be affected. <br>
  5649. <br><br>
  5650. </ul>
  5651. <ul>
  5652. <li><b> set &lt;name&gt; createSnapGallery </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5653. A snapshot gallery will be created as a separate device (type SSCamSTRM). The device will be provided in
  5654. room "SnapGallery".
  5655. With the "snapGallery..."-<a href="#SSCamattr">attributes</a> respectively the specific attributes of the SSCamSTRM-device
  5656. you are able to manipulate the properties of the new snapshot gallery device. <br>
  5657. <br><br>
  5658. </ul>
  5659. <ul>
  5660. <li><b> set &lt;name&gt; credentials &lt;username&gt; &lt;password&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM/SVS)</li> <br>
  5661. set username / password combination for access the Synology Surveillance Station.
  5662. See <a href="#SSCam_Credentials">Credentials</a><br> for further informations.
  5663. <br><br>
  5664. </ul>
  5665. <ul>
  5666. <li><b> set &lt;name&gt; delPreset &lt;PresetName&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br>
  5667. Deletes a preset "&lt;PresetName&gt;". In FHEMWEB a drop-down list with current available presets is provieded.
  5668. </ul>
  5669. <br><br>
  5670. <ul>
  5671. <li><b> set &lt;name&gt; [enable|disable] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5672. For <b>deactivating / activating</b> a list of cameras or all cameras by Regex-expression, subsequent two
  5673. examples using "at":
  5674. <pre>
  5675. define a13 at 21:46 set CamCP1,CamFL,CamHE1,CamTER disable (enable)
  5676. define a14 at 21:46 set Cam.* disable (enable)
  5677. </pre>
  5678. A bit more convenient is it to use a dummy-device for enable/disable all available cameras in Surveillance Station.<br>
  5679. At first the Dummy will be created.
  5680. <pre>
  5681. define allcams dummy
  5682. attr allcams eventMap on:enable off:disable
  5683. attr allcams room Cams
  5684. attr allcams webCmd enable:disable
  5685. </pre>
  5686. With combination of two created notifies, respectively one for "enable" and one for "diasble", you are able to switch all cameras into "enable" or "disable" state at the same time if you set the dummy to "enable" or "disable".
  5687. <pre>
  5688. define all_cams_disable notify allcams:.*off set CamCP1,CamFL,CamHE1,CamTER disable
  5689. attr all_cams_disable room Cams
  5690. define all_cams_enable notify allcams:on set CamCP1,CamFL,CamHE1,CamTER enable
  5691. attr all_cams_enable room Cams
  5692. </pre>
  5693. </ul>
  5694. <br><br>
  5695. <ul>
  5696. <li><b> set &lt;name&gt; expmode [day|night|auto] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5697. With this command you are able to control the exposure mode and can set it to day, night or automatic mode.
  5698. Thereby, for example, the behavior of camera LED's will be suitable controlled.
  5699. The successful switch will be reported by the reading CamExposureMode (command "get ... caminfoall"). <br><br>
  5700. <b> Note: </b><br>
  5701. The successfully execution of this function depends on if SVS supports that functionality of the connected camera.
  5702. Is the field for the Day/Night-mode shown greyed in SVS -&gt; IP-camera -&gt; optimization -&gt; exposure mode, this function will be probably unsupported.
  5703. </ul>
  5704. <br><br>
  5705. <ul>
  5706. <li><b> set &lt;name&gt; extevent [ 1-10 ] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for SVS)</li> <br>
  5707. This command triggers an external event (1-10) in SVS.
  5708. The actions which will are used have to be defined in the actionrule editor of SVS at first. There are the events 1-10 possible.
  5709. In the message application of SVS you may select Email, SMS or Mobil (DS-Cam) messages to release if an external event has been triggerd.
  5710. Further informations can be found in the online help of the actionrule editor.
  5711. The used user needs to be a member of the admin-group and DSM-session is needed too.
  5712. </ul>
  5713. <br><br>
  5714. <ul>
  5715. <li><b> set &lt;name&gt; goAbsPTZ [ X Y | up | down | left | right ] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5716. This command can be used to move a PTZ-camera to an arbitrary absolute X/Y-coordinate, or to absolute position using up/down/left/right.
  5717. The option is only available for cameras which are having the Reading "CapPTZAbs=true". The property of a camera can be requested with "get &lt;name&gt; caminfoall" .
  5718. <br><br>
  5719. Example for a control to absolute X/Y-coordinates: <br>
  5720. <pre>
  5721. set &lt;name&gt; goAbsPTZ 120 450
  5722. </pre>
  5723. In this example the camera lense moves to position X=120 und Y=450. <br>
  5724. The valuation is:
  5725. <pre>
  5726. X = 0 - 640 (0 - 319 moves lense left, 321 - 640 moves lense right, 320 don't move lense)
  5727. Y = 0 - 480 (0 - 239 moves lense down, 241 - 480 moves lense up, 240 don't move lense)
  5728. </pre>
  5729. The lense can be moved in smallest steps to very large steps into the desired direction.
  5730. If necessary the procedure has to be repeated to bring the lense into the desired position. <br><br>
  5731. If the motion should be done with the largest possible increment the following command can be used for simplification:
  5732. <pre>
  5733. set &lt;name&gt; goAbsPTZ up [down|left|right]
  5734. </pre>
  5735. In this case the lense will be moved with largest possible increment into the given absolute position.
  5736. Also in this case the procedure has to be repeated to bring the lense into the desired position if necessary.
  5737. </ul>
  5738. <br><br>
  5739. <ul>
  5740. <li><b> set &lt;name&gt; goPreset &lt;Preset&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5741. Using this command you can move PTZ-cameras to a predefined position. <br>
  5742. The Preset-positions have to be defined first of all in the Synology Surveillance Station. This usually happens in the PTZ-control of IP-camera setup in SVS.
  5743. The Presets will be read ito FHEM with command "get &lt;name&gt; caminfoall" (happens automatically when FHEM restarts). The import process can be repeated regular by camera polling.
  5744. A long polling interval is recommendable in this case because of the Presets are only will be changed if the user change it in the IP-camera setup itself.
  5745. <br><br>
  5746. Here it is an example of a PTZ-control depended on IR-motiondetector event:
  5747. <pre>
  5748. define CamFL.Preset.Wandschrank notify MelderTER:on.* set CamFL goPreset Wandschrank, ;; define CamFL.Preset.record at +00:00:10 set CamFL on 5 ;;;; define s3 at +*{3}00:00:05 set CamFL snap ;; define CamFL.Preset.back at +00:00:30 set CamFL goPreset Home
  5749. </pre>
  5750. Operating Mode: <br>
  5751. The IR-motiondetector registers a motion. Hereupon the camera "CamFL" moves to Preset-posion "Wandschrank". A recording with the length of 5 seconds starts 10 seconds later.
  5752. Because of the prerecording time of the camera is set to 10 seconds (cf. Reading "CamPreRecTime"), the effectice recording starts when the camera move begins. <br>
  5753. When the recording starts 3 snapshots with an interval of 5 seconds will be taken as well. <br>
  5754. After a time of 30 seconds in position "Wandschrank" the camera moves back to postion "Home". <br><br>
  5755. An extract of the log illustrates the process:
  5756. <pre>
  5757. 2016.02.04 15:02:14 2: CamFL - Camera Flur_Vorderhaus has moved to position "Wandschrank"
  5758. 2016.02.04 15:02:24 2: CamFL - Camera Flur_Vorderhaus Recording with Recordtime 5s started
  5759. 2016.02.04 15:02:29 2: CamFL - Snapshot of Camera Flur_Vorderhaus has been done successfully
  5760. 2016.02.04 15:02:30 2: CamFL - Camera Flur_Vorderhaus Recording stopped
  5761. 2016.02.04 15:02:34 2: CamFL - Snapshot of Camera Flur_Vorderhaus has been done successfully
  5762. 2016.02.04 15:02:39 2: CamFL - Snapshot of Camera Flur_Vorderhaus has been done successfully
  5763. 2016.02.04 15:02:44 2: CamFL - Camera Flur_Vorderhaus has moved to position "Home"
  5764. </pre>
  5765. </ul>
  5766. <br><br>
  5767. <ul>
  5768. <li><b> set &lt;name&gt; homeMode [on|off] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for SVS)</li> <br>
  5769. Switch the HomeMode of the Surveillance Station on or off.
  5770. Further informations about HomeMode you can find in the <a href="https://www.synology.com/en-global/knowledgebase/Surveillance/help/SurveillanceStation/home_mode">Synology Onlinehelp</a>.
  5771. <br><br>
  5772. </ul>
  5773. <ul>
  5774. <li><b> set &lt;name&gt; motdetsc [camera|SVS|disable] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5775. The command "motdetsc" (stands for "motion detection source") switchover the motion detection to the desired mode.
  5776. If motion detection will be done by camera / SVS without any parameters, the original camera motion detection settings are kept.
  5777. The successful execution of that opreration one can retrace by the state in SVS -&gt; IP-camera -&gt; event detection -&gt; motion. <br><br>
  5778. For the motion detection further parameter can be specified. The available options for motion detection by SVS are "sensitivity" and "threshold". <br><br>
  5779. <ul>
  5780. <table>
  5781. <colgroup> <col width=50%> <col width=50%> </colgroup>
  5782. <tr><td>set &lt;name&gt; motdetsc SVS [sensitivity] [threshold] </td><td># command pattern </td></tr>
  5783. <tr><td>set &lt;name&gt; motdetsc SVS 91 30 </td><td># set the sensitivity to 91 and threshold to 30 </td></tr>
  5784. <tr><td>set &lt;name&gt; motdetsc SVS 0 40 </td><td># keep the old value of sensitivity, set threshold to 40 </td></tr>
  5785. <tr><td>set &lt;name&gt; motdetsc SVS 15 </td><td># set the sensitivity to 15, threshold keep unchanged </td></tr>
  5786. </table>
  5787. </ul>
  5788. <br><br>
  5789. If the motion detection is used by camera, there are the options "sensitivity", "object size", "percentage for release" available. <br><br>
  5790. <ul>
  5791. <table>
  5792. <colgroup> <col width=50%> <col width=50%> </colgroup>
  5793. <tr><td>set &lt;name&gt; motdetsc camera [sensitivity] [threshold] [percentage] </td><td># command pattern </td></tr>
  5794. <tr><td>set &lt;name&gt; motdetsc camera 89 0 20 </td><td># set the sensitivity to 89, percentage to 20 </td></tr>
  5795. <tr><td>set &lt;name&gt; motdetsc camera 0 40 10 </td><td># keep old value for sensitivity, set threshold to 40, percentage to 10 </td></tr>
  5796. <tr><td>set &lt;name&gt; motdetsc camera 30 </td><td># set the sensitivity to 30, other values keep unchanged </td></tr>
  5797. </table>
  5798. </ul>
  5799. <br><br>
  5800. Please consider always the sequence of parameters. Unwanted options have to be set to "0" if further options which have to be changed are follow (see example above).
  5801. The numerical values are between 1 - 99 (except special case "0"). <br><br>
  5802. The each available options are dependend of camera type respectively the supported functions by SVS. Only the options can be used they are available in
  5803. SVS -&gt; edit camera -&gt; motion detection. Further informations please read in SVS online help. <br><br>
  5804. With the command "get &lt;name&gt; caminfoall" the <a href="#SSCamreadings">Reading</a> "CamMotDetSc" also will be updated which documents the current setup of motion detection.
  5805. Only the parameters and parameter values supported by SVS at present will be shown. The camera itself may offer further options to adjust. <br><br>
  5806. Example:
  5807. <pre>
  5808. CamMotDetSc SVS, sensitivity: 76, threshold: 55
  5809. </pre>
  5810. </ul>
  5811. <br><br>
  5812. <ul>
  5813. <li><b> set &lt;name&gt; move [ right | up | down | left | dir_X ] [Sekunden] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM up to SVS version 7.1)</li>
  5814. <b> set &lt;name&gt; move [ right | upright | up | upleft | left | downleft | down | downright ] [Sekunden] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM and SVS Version 7.2 and above) <br><br>
  5815. With this command a continuous move of a PTZ-camera will be started. In addition to the four basic directions up/down/left/right is it possible to use angular dimensions
  5816. "dir_X". The grain size of graduation depends on properties of the camera and can be identified by the Reading "CapPTZDirections". <br><br>
  5817. The radian measure of 360 degrees will be devided by the value of "CapPTZDirections" and describes the move drections starting with "0=right" counterclockwise.
  5818. That means, if a camera Reading is "CapPTZDirections = 8" it starts with dir_0 = right, dir_2 = top, dir_4 = left, dir_6 = bottom and respectively dir_1, dir_3, dir_5 and dir_7
  5819. the appropriate directions between. The possible moving directions of cameras with "CapPTZDirections = 32" are correspondingly divided into smaller sections. <br><br>
  5820. In opposite to the "set &lt;name&gt; goAbsPTZ"-command starts "set &lt;name&gt; move" a continuous move until a stop-command will be received.
  5821. The stop-command will be generated after the optional assignable time of [seconds]. If that retention period wouldn't be set by the command, a time of 1 second will be set implicit. <br><br>
  5822. Examples: <br>
  5823. <pre>
  5824. set &lt;name&gt; move up 0.5 : moves PTZ 0,5 Sek. (plus processing time) to the top
  5825. set &lt;name&gt; move dir_1 1.5 : moves PTZ 1,5 Sek. (plus processing time) to top-right
  5826. set &lt;name&gt; move dir_20 0.7 : moves PTZ 1,5 Sek. (plus processing time) to left-bottom ("CapPTZDirections = 32)"
  5827. </pre>
  5828. </ul>
  5829. <br><br>
  5830. <ul>
  5831. <li><b>set &lt;name&gt; [on [&lt;rectime&gt;] | off] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5832. The command "set &lt;name&gt; on" starts a recording. The default recording time takes 15 seconds. It can be changed by
  5833. the <a href="#SSCamattr">attribute</a> "rectime" individualy.
  5834. With the <a href="#SSCamattr">attribute</a> (respectively the default value) provided recording time can be overwritten
  5835. once by "set &lt;name&gt; on &lt;rectime&gt;".
  5836. The recording will be stopped after processing time "rectime"automatically.<br>
  5837. A special case is start recording by "set &lt;name&gt; on 0" respectively the attribute value "rectime = 0". In that case
  5838. a endless-recording will be started. One have to stop this recording by command "set &lt;name&gt; off" explicitely.<br>
  5839. The recording behavior can be impacted with <a href="#SSCamattr">attribute</a> "recextend" furthermore as explained as follows.<br><br>
  5840. <b>Attribute "recextend = 0" or not set (default):</b><br><br>
  5841. <ul>
  5842. <li> if, for example, a recording with rectimeme=22 is started, no other startcommand (for a recording) will be accepted until this started recording is finished.
  5843. A hint will be logged in case of verboselevel = 3. </li>
  5844. </ul>
  5845. <br>
  5846. <b>Attribute "recextend = 1" is set:</b><br><br>
  5847. <ul>
  5848. <li> a before started recording will be extend by the recording time "rectime" if a new start command is received. That means, the timer for the automatic stop-command will be
  5849. renewed to "rectime" given bei the command, attribute or default value. This procedure will be repeated every time a new start command for recording is received.
  5850. Therefore a running recording will be extended until no start command will be get. </li>
  5851. <li> a before started endless-recording will be stopped after recordingtime 2rectime" if a new "set <name> on"-command is received (new set of timer). If it is unwanted make sure you
  5852. don't set the <a href="#SSCamattr">attribute</a> "recextend" in case of endless-recordings. </li>
  5853. </ul>
  5854. <br>
  5855. Examples for simple <b>Start/Stop a Recording</b>: <br><br>
  5856. <table>
  5857. <colgroup> <col width=20%> <col width=80%> </colgroup>
  5858. <tr><td>set &lt;name&gt; on [rectime] </td><td>starts a recording of camera &lt;name&gt;, stops automatically after [rectime] (default 15s or defined by <a href="#SSCamattr">attribute</a>) </td></tr>
  5859. <tr><td>set &lt;name&gt; off </td><td>stops the recording of camera &lt;name&gt;</td></tr>
  5860. </table>
  5861. </ul>
  5862. <br><br>
  5863. <ul>
  5864. <li><b> set &lt;name&gt; optimizeParams [mirror:&lt;value&gt;] [flip:&lt;value&gt;] [rotate:&lt;value&gt;] [ntp:&lt;value&gt;]</b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  5865. Set one or several properties of the camera. The video can be mirrored (mirror), turned upside down (flip) or
  5866. rotated (rotate). Specified properties must be supported by the camera type. With "ntp" you can set a time server the camera
  5867. use for time synchronization. <br><br>
  5868. &lt;value&gt; can be for: <br>
  5869. <ul>
  5870. <li> <b>mirror, flip, rotate: </b> true | false </li>
  5871. <li> <b>ntp: </b> the name or the IP-address of time server </li>
  5872. </ul>
  5873. <br><br>
  5874. <b>Examples:</b> <br>
  5875. <code> set &lt;name&gt; optimizeParams mirror:true flip:true ntp:time.windows.com </code><br>
  5876. # The video will be mirrored, turned upside down and the time server is set to "time.windows.com".<br>
  5877. <code> set &lt;name&gt; optimizeParams ntp:Surveillance%20Station </code><br>
  5878. # The Surveillance Station is set as time server. (NTP-service has to be activated in DSM) <br>
  5879. <code> set &lt;name&gt; optimizeParams mirror:true flip:false rotate:true </code><br>
  5880. # The video will be mirrored and rotated round 90 degrees. <br>
  5881. <br><br>
  5882. </ul>
  5883. <ul>
  5884. <li><b> set &lt;name&gt; pirSensor [activate | deactivate] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5885. Activates / deactivates the infrared sensor of the camera (only posible if the camera has got a PIR sensor).
  5886. </ul>
  5887. <br><br>
  5888. <ul>
  5889. <li><b> set &lt;name&gt; runPatrol &lt;Patrolname&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5890. This commans starts a predefined patrol (tour) of a PTZ-camera. <br>
  5891. At first the patrol has to be predefined in the Synology Surveillance Station. It can be done in the PTZ-control of IP-Kamera Setup -&gt; PTZ-control -&gt; patrol.
  5892. The patrol tours will be read with command "get &lt;name&gt; caminfoall" which is be executed automatically when FHEM restarts.
  5893. The import process can be repeated regular by camera polling. A long polling interval is recommendable in this case because of the patrols are only will be changed
  5894. if the user change it in the IP-camera setup itself.
  5895. Further informations for creating patrols you can get in the online-help of Surveillance Station.
  5896. </ul>
  5897. <br><br>
  5898. <ul>
  5899. <li><b> set &lt;name&gt; runView [live_fw | live_link | live_open [&lt;room&gt;] | lastrec_fw | lastrec_fw_MJPEG | lastrec_fw_MPEG4/H.264 | lastrec_open [&lt;room&gt;] | lastsnap_fw] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5900. <ul>
  5901. <table>
  5902. <colgroup> <col width=25%> <col width=75%> </colgroup>
  5903. <tr><td>live_fw </td><td>- MJPEG-Livestream. Audio playback is provided if possible. </td></tr>
  5904. <tr><td>live_fw_hls </td><td>- HLS-Livestream (currently only Mac Safari Browser and mobile iOS/Android-Devices) </td></tr>
  5905. <tr><td>live_link </td><td>- Link of a MJPEG-Livestream </td></tr>
  5906. <tr><td>live_open [&lt;room&gt;] </td><td>- opens MJPEG-Livestream in separate Browser window </td></tr>
  5907. <tr><td>lastrec_fw </td><td>- playback last recording as iFrame object </td></tr>
  5908. <tr><td>lastrec_fw_MJPEG </td><td>- usable if last recording has format MJPEG </td></tr>
  5909. <tr><td>lastrec_fw_MPEG4/H.264 </td><td>- usable if last recording has format MPEG4/H.264 </td></tr>
  5910. <tr><td>lastrec_open [&lt;room&gt;] </td><td>- playback last recording in a separate Browser window </td></tr>
  5911. <tr><td>lastsnap_fw </td><td>- playback last snapshot </td></tr>
  5912. </table>
  5913. </ul>
  5914. <br><br>
  5915. With <b>"live_fw, live_link"</b> a MJPEG-Livestream will be started, either as an embedded image
  5916. or as a generated link. <br>
  5917. The option <b>"live_open"</b> starts a new browser window with a MJPEG-Livestream. If the optional "&lt;room&gt;" is set, the
  5918. window will only be started if the specified room is currently opened in a FHEMWEB-session. <br>
  5919. If a HLS-Stream by <b>"live_fw_hls"</b> is requested, the camera has to be setup to video format H.264 (not MJPEG) in the
  5920. Synology Surveillance Station and the SVS-Version has to support the HLS format.
  5921. Therefore this possibility is only present if the Reading "CamStreamFormat" is set to "HLS".
  5922. <br><br>
  5923. Access to the last recording of a camera can be done using <b>"lastrec_fw.*"</b> respectively <b>"lastrec_open"</b>.
  5924. By <b>"lastrec_fw"</b> the recording will be opened in an iFrame. There are some control elements provided if available. <br>
  5925. The <b>"lastrec_open"</b> command can be extended optionally by a room. In this case the new window opens only, if the
  5926. room is the same as a FHEMWEB-session has currently opened. <br>
  5927. The command <b>"set &lt;name&gt; runView lastsnap_fw"</b> shows the last snapshot of the camera embedded. <br>
  5928. The Streaming-Device properties can be affected by HTML-tags in <a href="#SSCamattr">attribute</a> "htmlattr".
  5929. <br><br>
  5930. <b>Examples:</b><br>
  5931. <pre>
  5932. attr &lt;name&gt; htmlattr width="500" height="375"
  5933. attr &lt;name&gt; htmlattr width="700",height="525",top="200",left="300"
  5934. </pre>
  5935. The command <b>"set &lt;name&gt; runView live_open"</b> starts the stream immediately in a new browser window.
  5936. A browser window will be initiated to open for every FHEMWEB-session which is active. If you want to change this behavior,
  5937. you can use command <b>"set &lt;name&gt; runView live_open &lt;room&gt;"</b>. In this case the new window opens only, if the
  5938. room is the same as a FHEMWEB-session has currently opened. <br>
  5939. The settings of <a href="#SSCamattr">attribute</a> "livestreamprefix" overwrite the data for protocol, servername and
  5940. port in <a href="#SSCamreadings">reading</a> "LiveStreamUrl".
  5941. By "livestreamprefix" the LivestreamURL (is shown if <a href="#SSCamattr">attribute</a> "showStmInfoFull" is set) can
  5942. be modified and used for distribution and external access to the Livestream. <br><br>
  5943. <b>Example:</b><br>
  5944. <pre>
  5945. attr &lt;name&gt; livestreamprefix https://&lt;Servername&gt;:&lt;Port&gt;
  5946. </pre>
  5947. The livestream can be stopped again by command <b>"set &lt;name&gt; stopView"</b>.
  5948. The "runView" function also switches Streaming-Devices of type "switched" into the appropriate mode. <br><br>
  5949. Dependend of the content to playback, different control buttons are provided: <br><br>
  5950. <ul>
  5951. <table>
  5952. <colgroup> <col width=25%> <col width=75%> </colgroup>
  5953. <tr><td> Start Recording </td><td>- starts an endless recording </td></tr>
  5954. <tr><td> Stop Recording </td><td>- stopps the recording </td></tr>
  5955. <tr><td> Take Snapshot </td><td>- take a snapshot </td></tr>
  5956. <tr><td> Switch off </td><td>- stops a running playback </td></tr>
  5957. </table>
  5958. </ul>
  5959. <br>
  5960. <b>Note for HLS (HTTP Live Streaming):</b> <br>
  5961. The video starts with a technology caused delay. Every stream will be segemented into some little video files
  5962. (with a lenth of approximately 10 seconds) and is than delivered to the client.
  5963. The video format of the camera has to be set to H.264 in the Synology Surveillance Station and not every camera type is
  5964. a proper device for HLS-Streaming.
  5965. At the time only the Mac Safari Browser and modern mobile iOS/Android-Devices are able to playback HLS-Streams.
  5966. </ul>
  5967. <br><br>
  5968. <ul>
  5969. <li><b> set &lt;name&gt; setHome &lt;PresetName&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br>
  5970. Set the Home-preset to a predefined preset name "&lt;PresetName&gt;" or the current position of the camera.
  5971. </ul>
  5972. <br><br>
  5973. <ul>
  5974. <li><b> set &lt;name&gt; setPreset &lt;PresetNumber&gt; [&lt;PresetName&gt;] [&lt;Speed&gt;] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br>
  5975. Sets a Preset with name "&lt;PresetName&gt;" to the current postion of the camera. The speed can be defined
  5976. optionally (&lt;Speed&gt;). If no PresetName is specified, the PresetNummer is used as name.
  5977. For this reason &lt;PresetName&gt; is defined as optional, but should usually be set.
  5978. </ul>
  5979. <br><br>
  5980. <ul>
  5981. <li><b> set &lt;name&gt; snap </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  5982. A snapshot can be triggered with:
  5983. <pre>
  5984. set &lt;name&gt; snap
  5985. </pre>
  5986. Subsequent some Examples for <b>taking snapshots</b>: <br><br>
  5987. If a serial of snapshots should be released, it can be done using the following notify command.
  5988. For the example a serial of snapshots are to be triggerd if the recording of a camera starts. <br>
  5989. When the recording of camera "CamHE1" starts (Attribut event-on-change-reading -> "Record" has to be set), then 3 snapshots at intervals of 2 seconds are triggered.
  5990. <pre>
  5991. define he1_snap_3 notify CamHE1:Record.*on define h3 at +*{3}00:00:02 set CamHE1 snap
  5992. </pre>
  5993. Release of 2 Snapshots of camera "CamHE1" at intervals of 6 seconds after the motion sensor "MelderHE1" has sent an event, <br>
  5994. can be done e.g. with following notify-command:
  5995. <pre>
  5996. define he1_snap_2 notify MelderHE1:on.* define h2 at +*{2}00:00:06 set CamHE1 snap
  5997. </pre>
  5998. The ID and the filename of the last snapshot will be displayed as value of variable "LastSnapId" respectively "LastSnapFilename" in the device-Readings. <br><br>
  5999. </ul>
  6000. <br><br>
  6001. <ul>
  6002. <li><b> set &lt;name&gt; snapGallery [1-10] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  6003. The command is only available if the attribute "snapGalleryBoost=1" is set. <br>
  6004. It creates an output of the last [x] snapshots as well as "get ... snapGallery". But differing from "get" with
  6005. <a href="#SSCamattr">attribute</a> "snapGalleryBoost=1" no popup will be created. The snapshot gallery will be depicted as
  6006. an browserpage instead. All further functions and attributes are appropriate the <a href="#SSCamget">"get &lt;name&gt; snapGallery"</a>
  6007. command. <br>
  6008. If you want create a snapgallery output by triggering, e.g. with an "at" or "notify", you should use the
  6009. <a href="#SSCamget">"get &lt;name&gt; snapGallery"</a> command instead of "set".
  6010. </ul>
  6011. <br><br>
  6012. <ul>
  6013. <li><b> set &lt;name&gt; startTracking </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM with tracking capability)</li> <br>
  6014. Starts object tracking of camera.
  6015. The command is only available if surveillance station has recognised the object tracking capability of camera
  6016. (Reading "CapPTZObjTracking").
  6017. </ul>
  6018. <br><br>
  6019. <ul>
  6020. <li><b> set &lt;name&gt; stopTracking </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM with tracking capability)</li> <br>
  6021. Stops object tracking of camera.
  6022. The command is only available if surveillance station has recognised the object tracking capability of camera
  6023. (Reading "CapPTZObjTracking").
  6024. </ul>
  6025. <br><br>
  6026. </ul>
  6027. <br>
  6028. <a name="SSCamget"></a>
  6029. <b>Get</b>
  6030. <ul>
  6031. <br>
  6032. With SSCam the properties of SVS and defined Cameras could be retrieved. <br>
  6033. The specified get-commands are available for CAM/SVS-devices or only valid for CAM-devices or rather for SVS-Devices.
  6034. They can be selected in the drop-down-menu of the particular device. <br><br>
  6035. <ul>
  6036. <li><b> get &lt;name&gt; caminfoall </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM/SVS)</li>
  6037. <b> get &lt;name&gt; caminfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM) <br><br>
  6038. Dependend of the type of camera (e.g. Fix- or PTZ-Camera) the available properties are retrieved and provided as Readings.<br>
  6039. For example the Reading "Availability" will be set to "disconnected" if the camera would be disconnected from Synology
  6040. Surveillance Station and can't be used for further processing like creating events. <br>
  6041. "getcaminfo" retrieves a subset of "getcaminfoall".
  6042. </ul>
  6043. <br><br>
  6044. <ul>
  6045. <li><b> get &lt;name&gt; eventlist </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  6046. The <a href="#SSCamreadings">Reading</a> "CamEventNum" and "CamLastRecord" will be refreshed which containes the total number
  6047. of in SVS registered camera events and the path/name of the last recording.
  6048. This command will be implicit executed when "get &lt;name&gt; caminfoall" is running. <br>
  6049. The <a href="#SSCamattr">attribute</a> "videofolderMap" replaces the content of reading "VideoFolder". You can use it for
  6050. example if you have mounted the videofolder of SVS under another name or path and want to access by your local pc.
  6051. </ul>
  6052. <br><br>
  6053. <ul>
  6054. <li><b> get &lt;name&gt; homeModeState </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for SVS)</li> <br>
  6055. HomeMode-state of the Surveillance Station will be retrieved.
  6056. </ul>
  6057. <br><br>
  6058. <ul>
  6059. <li><b> get &lt;name&gt; listLog [severity:&lt;Loglevel&gt;] [limit:&lt;Number of lines&gt;] [match:&lt;Searchstring&gt;] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for SVS)</li> <br>
  6060. Fetches the Surveillance Station Log from Synology server. Without any further options the whole log will be retrieved. <br>
  6061. You can specify all or any of the following options: <br><br>
  6062. <ul>
  6063. <li> &lt;Loglevel&gt; - Information, Warning or Error. Only datasets having this severity are retrieved (default: all) </li>
  6064. <li> &lt;Number of lines&gt; - the specified number of lines (newest) of the log are retrieved (default: all) </li>
  6065. <li> &lt;Searchstring&gt; - only log entries containing the searchstring are retrieved (Note: no Regex possible, the searchstring will be given into the call to SVS) </li>
  6066. </ul>
  6067. <br>
  6068. <b>Examples</b> <br>
  6069. <ul>
  6070. <code>get &lt;name&gt; listLog severity:Error limit:5 </code> <br>
  6071. Reports the last 5 Log entries with severity "Error" <br>
  6072. <code>get &lt;name&gt; listLog severity:Information match:Carport </code> <br>
  6073. Reports all Log entries with severity "Information" and containing the string "Carport" <br>
  6074. <code>get &lt;name&gt; listLog severity:Warning </code> <br>
  6075. Reports all Log entries with severity "Warning" <br><br>
  6076. </ul>
  6077. If the polling of SVS is activated by setting the <a href="#SSCamattr">attribute</a> "pollcaminfoall", the <a href="#SSCamreadings">reading</a>
  6078. "LastLogEntry" will be created. <br>
  6079. In the protocol-setup of the SVS you can adjust what data you want to log. For further informations please have a look at
  6080. <a href="https://www.synology.com/en-uk/knowledgebase/Surveillance/help/SurveillanceStation/log_advanced">Synology Online-Help</a>.
  6081. </ul>
  6082. <br><br>
  6083. <ul>
  6084. <li><b> get &lt;name&gt; listPresets </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for PTZ-CAM)</li> <br>
  6085. Get a popup with a lists of presets saved for the camera.
  6086. </ul>
  6087. <br><br>
  6088. <ul>
  6089. <li><b> get &lt;name&gt; scanVirgin </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM/SVS)</li> <br>
  6090. This command is similar to get caminfoall, informations relating to SVS and the camera will be retrieved.
  6091. In difference to caminfoall in either case a new session ID will be generated (do a new login), the camera ID will be
  6092. new identified and all necessary API-parameters will be new investigated.
  6093. </ul>
  6094. <br><br>
  6095. <ul>
  6096. <li><b> get &lt;name&gt; snapGallery [1-10] </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  6097. A popup with the last [x] snapshots will be created. If the <a href="#SSCamattr">attribute</a> "snapGalleryBoost" is set,
  6098. the last snapshots (default 3) are requested by polling and they will be stored in the FHEM-servers main memory.
  6099. This method is helpful to speed up the output especially in case of full size images, but it can be possible
  6100. that NOT the newest snapshots are be shown if they have not be initialized by the SSCAm-module itself. <br>
  6101. The function can also be triggered, e.g. by an "at" or "notify". In that case the snapshotgallery will be displayed on all
  6102. connected FHEMWEB instances as a popup. <br><br>
  6103. To control this function behavior there are further <a href="#SSCamattr">attributes</a>: <br><br>
  6104. <ul>
  6105. <li>snapGalleryBoost </li>
  6106. <li>snapGalleryColumns </li>
  6107. <li>snapGalleryHtmlAttr </li>
  6108. <li>snapGalleryNumber </li>
  6109. <li>snapGallerySize </li>
  6110. </ul> <br>
  6111. available.
  6112. </ul> <br>
  6113. <ul>
  6114. <b>Note:</b><br>
  6115. Depended from quantity and resolution (quality) of the snapshot images adequate CPU and/or main memory
  6116. ressources are needed.
  6117. </ul>
  6118. <br><br>
  6119. <ul>
  6120. <li><b> get &lt;name&gt; snapfileinfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  6121. The filename of the last snapshot will be retrieved. This command will be executed with <b>"get &lt;name&gt; snap"</b>
  6122. automatically.
  6123. </ul>
  6124. <br><br>
  6125. <ul>
  6126. <li><b> get &lt;name&gt; snapinfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  6127. Informations about snapshots will be retrieved. Heplful if snapshots are not triggerd by SSCam, but by motion detection of the camera or surveillance
  6128. station instead.
  6129. </ul>
  6130. <br><br>
  6131. <ul>
  6132. <li><b> get &lt;name&gt; stmUrlPath </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM)</li> <br>
  6133. This command is to fetch the streamkey information and streamurl using that streamkey. The reading "StmKey" will be filled when this command will be executed and can be used
  6134. to send it and run by your own application like a browser (see example).
  6135. If the <a href="#SSCamattr">attribute</a> "showStmInfoFull" is set, additional stream readings like "StmKeyUnicst", "StmKeymjpegHttp" will be shown and can be used to run the
  6136. appropriate livestream without session id. Is the attribute "livestreamprefix" (usage: "http(s)://&lt;hostname&gt;&lt;port&gt;) used, the servername / port will be replaced if necessary.
  6137. The strUrlPath function will be included automatically if polling is used.
  6138. <br><br>
  6139. Example to create an http-call to a livestream using StmKey: <br>
  6140. <pre>
  6141. http(s)://&lt;hostname&gt;&lt;port&gt;/webapi/entry.cgi?api=SYNO.SurveillanceStation.VideoStreaming&version=1&method=Stream&format=mjpeg&cameraId=5&StmKey="31fd87279976d89bb98409728cced890"
  6142. </pre>
  6143. cameraId (Internal CAMID) and StmKey has to be replaced by valid values. <br><br>
  6144. <b>Note:</b> <br>
  6145. If you use the stream-call from external and replace hostname / port with valid values and open your router ip ports, please
  6146. make shure that no unauthorized person could get this sensible data !
  6147. </ul>
  6148. <br><br>
  6149. <ul>
  6150. <li><b> get &lt;name&gt; storedCredentials </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM/SVS)</li> <br>
  6151. Shows the stored login credentials in a popup as plain text.
  6152. </ul>
  6153. <br><br>
  6154. <ul>
  6155. <li><b> get &lt;name&gt; svsinfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(valid for CAM/SVS)</li> <br>
  6156. Determines common informations about the installed SVS-version and other properties. <br>
  6157. </ul>
  6158. <br><br>
  6159. <b>Polling of Camera/SVS-Properties</b><br><br>
  6160. <ul>
  6161. Retrieval of Camera-Properties can be done automatically if the attribute "pollcaminfoall" will be set to a value &gt; 10. <br>
  6162. As default that attribute "pollcaminfoall" isn't be set and the automatic polling isn't be active. <br>
  6163. The value of that attribute determines the interval of property-retrieval in seconds. If that attribute isn't be set or &lt; 10 the automatic polling won't be started <br>
  6164. respectively stopped when the value was set to &gt; 10 before. <br><br>
  6165. The attribute "pollcaminfoall" is monitored by a watchdog-timer. Changes of the attribute-value will be checked every 90 seconds and transact corresponding. <br>
  6166. Changes of the pollingstate and pollinginterval will be reported in FHEM-Logfile. The reporting can be switched off by setting the attribute "pollnologging=1". <br>
  6167. Thereby the needless growing of the logfile can be avoided. But if verbose level is set to 4 or above even though the attribute "pollnologging" is set as well, the polling <br>
  6168. will be actived due to analysis purposes. <br><br>
  6169. If FHEM will be restarted, the first data retrieval will be done within 60 seconds after start. <br><br>
  6170. The state of automatic polling will be displayed by reading "PollState": <br><br>
  6171. <ul>
  6172. <li><b> PollState = Active </b> - automatic polling will be executed with interval correspondig value of attribute "pollcaminfoall" </li>
  6173. <li><b> PollState = Inactive </b> - automatic polling won't be executed </li>
  6174. </ul>
  6175. <br>
  6176. The readings are described <a href="#SSCamreadings">here</a>. <br><br>
  6177. <b>Notes:</b> <br><br>
  6178. If polling is used, the interval should be adjusted only as short as needed due to the detected camera values are predominantly static. <br>
  6179. A feasible guide value for attribute "pollcaminfoall" could be between 600 - 1800 (s). <br>
  6180. Per polling call and camera approximately 10 - 20 Http-calls will are stepped against Surveillance Station. <br>
  6181. Because of that if HTTP-Timeout (pls. refer <a href="#SSCamattr">Attribut</a> "httptimeout") is set to 4 seconds, the theoretical processing time couldn't be higher than 80 seconds. <br>
  6182. Considering a safety margin, in that example you shouldn't set the polling interval lower than 160 seconds. <br><br>
  6183. If several Cameras are defined in SSCam, attribute "pollcaminfoall" of every Cameras shouldn't be set exactly to the same value to avoid processing bottlenecks <br>
  6184. and thereby caused potential source of errors during request Synology Surveillance Station. <br>
  6185. A marginal difference between the polling intervals of the defined cameras, e.g. 1 second, can already be faced as
  6186. sufficient value. <br><br>
  6187. </ul>
  6188. </ul>
  6189. <a name="SSCaminternals"></a>
  6190. <b>Internals</b> <br><br>
  6191. <ul>
  6192. The meaning of used Internals is depicted in following list: <br><br>
  6193. <ul>
  6194. <li><b>CAMID</b> - the ID of camera defined in SVS, the value will be retrieved automatically on the basis of SVS-cameraname </li>
  6195. <li><b>CAMNAME</b> - the name of the camera in SVS </li>
  6196. <li><b>COMPATIBILITY</b> - information up to which SVS-version the module version is currently released/tested (see also Reading "compstate") </li>
  6197. <li><b>CREDENTIALS</b> - the value is "Set" if Credentials are set </li>
  6198. <li><b>NAME</b> - the cameraname in FHEM </li>
  6199. <li><b>MODEL</b> - distinction between camera device (CAM) and Surveillance Station device (SVS) </li>
  6200. <li><b>OPMODE</b> - the last executed operation of the module </li>
  6201. <li><b>SERVERADDR</b> - IP-Address of SVS Host </li>
  6202. <li><b>SERVERPORT</b> - SVS-Port </li>
  6203. <br><br>
  6204. </ul>
  6205. </ul>
  6206. <a name="SSCamattr"></a>
  6207. <b>Attributes</b>
  6208. <br><br>
  6209. <ul>
  6210. <ul>
  6211. <li><b>debugactivetoken</b><br>
  6212. if set the state of active token will be logged - only for debugging, don't use it in normal operation ! </li><br>
  6213. <li><b>disable</b><br>
  6214. deactivates the device definition </li><br>
  6215. <li><b>genericStrmHtmlTag</b><br>
  6216. This attribute contains HTML-Tags for video-specification in a Streaming-Device of type "generic".
  6217. (see also "set &lt;name&gt; createStreamDev generic") <br><br>
  6218. <ul>
  6219. <b>Example:</b>
  6220. <pre>
  6221. attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
  6222. &lt;source src='http://192.168.2.10:32000/$NAME.m3u8' type='application/x-mpegURL'&gt;
  6223. &lt;/video&gt;
  6224. </pre>
  6225. The variables $HTMLATTR, $NAME are placeholder and absorb the attribute "htmlattr" (if set) respectively the SSCam-Devicename.
  6226. </ul>
  6227. <br><br>
  6228. </li>
  6229. <li><b>httptimeout</b><br>
  6230. Timeout-Value of HTTP-Calls to Synology Surveillance Station, Default: 4 seconds (if httptimeout = "0"
  6231. or not set) </li><br>
  6232. <li><b>htmlattr</b><br>
  6233. additional specifications to inline oictures to manipulate the behavior of stream, e.g. size of the image. </li><br>
  6234. <ul>
  6235. <b>Example:</b><br>
  6236. attr &lt;name&gt; htmlattr width="500" height="325" top="200" left="300"
  6237. </ul>
  6238. <br>
  6239. <li><b>livestreamprefix</b><br>
  6240. overwrites the specifications of protocol, servername and port for further use of the livestream address, e.g.
  6241. as an link to external use. It has to be specified as "http(s)://&lt;servername&gt;:&lt;port&gt;" </li><br>
  6242. <li><b>loginRetries</b><br>
  6243. set the amount of login-repetitions in case of failure (default = 1) </li><br>
  6244. <li><b>noQuotesForSID</b><br>
  6245. this attribute may be helpfull in some cases to avoid errormessage "402 - permission denied" and makes login
  6246. possible. </li><br>
  6247. <li><b>pollcaminfoall</b><br>
  6248. Interval of automatic polling the Camera properties (if <= 10: no polling, if &gt; 10: polling with interval) </li><br>
  6249. <li><b>pollnologging</b><br>
  6250. "0" resp. not set = Logging device polling active (default), "1" = Logging device polling inactive</li><br>
  6251. <li><b>ptzPanel_Home</b><br>
  6252. In the PTZ-control panel the Home-Icon (in attribute "ptzPanel_row02") is automatically assigned to the value of
  6253. Reading "PresetHome".
  6254. With "ptzPanel_Home" you can change the assignment to another preset from the available Preset list. </li><br>
  6255. <li><b>ptzPanel_iconPath</b><br>
  6256. Path for icons used in PTZ-control panel, default is "www/images/sscam".
  6257. The attribute value will be used for all icon-files except *.svg. </li><br>
  6258. <li><b>ptzPanel_iconPrefix</b><br>
  6259. Prefix for icons used in PTZ-control panel, default is "black_btn_".
  6260. The attribute value will be used for all icon-files except *.svg. <br>
  6261. If the used icon-files begin with e.g. "black_btn_" ("black_btn_CAMDOWN.png"), the icon needs to be defined in
  6262. attributes "ptzPanel_row[00-09]" just with the subsequent part of name, e.g. "CAMDOWN.png".
  6263. </li><br>
  6264. <li><b>ptzPanel_row[00-09] &lt;command&gt;:&lt;icon&gt;,&lt;command&gt;:&lt;icon&gt;,... </b><br>
  6265. For PTZ-cameras the attributes "ptzPanel_row00" to "ptzPanel_row04" are created automatically for usage by
  6266. the PTZ-control panel. <br>
  6267. The attributes contain a comma spareated list of command:icon-combinations (buttons) each panel line.
  6268. One panel line can contain a random number of buttons. The attributes "ptzPanel_row00" to "ptzPanel_row04" can't be
  6269. deleted because of they are created automatically again in that case.
  6270. The user can change or complement the attribute values. These changes are conserved. <br>
  6271. If needed the assignment for Home-button in "ptzPanel_row02" can be changed by attribute "ptzPanel_Home". <br>
  6272. The icons are searched in path "ptzPanel_iconPath". The value of "ptzPanel_iconPrefix" is prepend to the icon filename.
  6273. Own extensions of the PTZ-control panel can be done using the attributes "ptzPanel_row05" to "ptzPanel_row09".
  6274. For creation of own icons a template is provided in the SVN:
  6275. <a href="https://svn.fhem.de/trac/browser/trunk/fhem/contrib/sscam">contrib/sscam/black_btn_CAM_Template.pdn</a>. This
  6276. template can be edited by e.g. Paint.Net. <br><br>
  6277. <b>Note:</b> <br>
  6278. For an empty field please use ":CAMBLANK.png" respectively ":CAMBLANK.png,:CAMBLANK.png,:CAMBLANK.png,..." for an empty
  6279. line.
  6280. <br><br>
  6281. <ul>
  6282. <b>Example:</b><br>
  6283. attr &lt;name&gt; ptzPanel_row00 move upleft:CAMUPLEFTFAST.png,:CAMBLANK.png,move up:CAMUPFAST.png,:CAMBLANK.png,move upright:CAMUPRIGHTFAST.png <br>
  6284. # The command "move upleft" is transmitted to the camera by pressing the button(icon) "CAMUPLEFTFAST.png". <br>
  6285. </ul>
  6286. <br>
  6287. </li><br>
  6288. <li><b>ptzPanel_use</b><br>
  6289. Switch the usage of a PTZ-control panel in detail view respectively a created StreamDevice off or on
  6290. (default: on). </li><br>
  6291. <li><b>rectime</b><br>
  6292. determines the recordtime when a recording starts. If rectime = 0 an endless recording will be started. If
  6293. it isn't defined, the default recordtime of 15s is activated </li><br>
  6294. <li><b>recextend</b><br>
  6295. "rectime" of a started recording will be set new. Thereby the recording time of the running recording will be
  6296. extended </li><br>
  6297. <li><b>session</b><br>
  6298. selection of login-Session. Not set or set to "DSM" -&gt; session will be established to DSM (Sdefault).
  6299. "SurveillanceStation" -&gt; session will be established to SVS </li><br>
  6300. <li><b>simu_SVSversion</b><br>
  6301. simulates another SVS version. (only a lower version than the installed one is possible !) </li><br>
  6302. <li><b>snapGalleryBoost</b><br>
  6303. If set, the last snapshots (default 3) will be retrieved by Polling, will be stored in the FHEM-servers main memory
  6304. and can be displayed by the "set/get ... snapGallery" command. <br>
  6305. This mode is helpful if many or full size images shall be displayed.
  6306. If the attribute is set, you can't specify arguments in addition to the "set/get ... snapGallery" command.
  6307. (see also attribut "snapGalleryNumber") </li><br>
  6308. <li><b>snapGalleryColumns</b><br>
  6309. The number of snapshots which shall appear in one row of the gallery popup (default 3). </li><br>
  6310. <li><b>snapGalleryHtmlAttr</b><br>
  6311. the image parameter can be controlled by this attribute. <br>
  6312. If the attribute isn't set, the value of attribute "htmlattr" will be used. <br>
  6313. If "htmlattr" is also not set, default parameters are used instead (width="500" height="325"). <br><br>
  6314. <ul>
  6315. <b>Example:</b><br>
  6316. attr &lt;name&gt; snapGalleryHtmlAttr width="325" height="225"
  6317. </ul>
  6318. <br>
  6319. </li>
  6320. <li><b>snapGalleryNumber</b><br>
  6321. The number of snapshots to retrieve (default 3). </li><br>
  6322. <li><b>snapGallerySize</b><br>
  6323. By this attribute the quality of the snapshot images can be controlled (default "Icon"). <br>
  6324. If mode "Full" is set, the images are retrieved with their original available resolution. That requires more ressources
  6325. and may slow down the display. By setting attribute "snapGalleryBoost=1" the display may accelerated, because in that case
  6326. the images will be retrieved by continuous polling and need only bring to display. </li><br>
  6327. <li><b>showStmInfoFull</b><br>
  6328. additional stream informations like LiveStreamUrl, StmKeyUnicst, StmKeymjpegHttp will be created </li><br>
  6329. <li><b>showPassInLog</b><br>
  6330. if set the used password will be shown in logfile with verbose 4. (default = 0) </li><br>
  6331. <li><b>videofolderMap</b><br>
  6332. replaces the content of reading "VideoFolder", Usage if e.g. folders are mountet with different names than original
  6333. (SVS) </li><br>
  6334. <li><b>verbose</b></li><br>
  6335. <ul>
  6336. Different Verbose-Level are supported.<br>
  6337. Those are in detail:
  6338. <table>
  6339. <colgroup> <col width=5%> <col width=95%> </colgroup>
  6340. <tr><td> 0 </td><td>- Start/Stop-Event will be logged </td></tr>
  6341. <tr><td> 1 </td><td>- Error messages will be logged </td></tr>
  6342. <tr><td> 2 </td><td>- messages according to important events were logged </td></tr>
  6343. <tr><td> 3 </td><td>- sended commands will be logged </td></tr>
  6344. <tr><td> 4 </td><td>- sended and received informations will be logged </td></tr>
  6345. <tr><td> 5 </td><td>- all outputs will be logged for error-analyses. <b>Caution:</b> a lot of data could be written into logfile ! </td></tr>
  6346. </table>
  6347. </ul>
  6348. <br>
  6349. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  6350. </ul>
  6351. </ul>
  6352. <br><br>
  6353. <a name="SSCamreadings"></a>
  6354. <b>Readings</b>
  6355. <ul>
  6356. <br>
  6357. Using the polling mechanism or retrieval by "get"-call readings are provieded, The meaning of the readings are listed in subsequent table: <br>
  6358. The transfered Readings can be deversified dependend on the type of camera.<br><br>
  6359. <ul>
  6360. <table>
  6361. <colgroup> <col width=5%> <col width=95%> </colgroup>
  6362. <tr><td><li>CamAudioType</li> </td><td>- Indicating audio type </td></tr>
  6363. <tr><td><li>Availability</li> </td><td>- Availability of Camera (disabled, enabled, disconnected, other) </td></tr>
  6364. <tr><td><li>CamEventNum</li> </td><td>- delivers the total number of in SVS registered events of the camera </td></tr>
  6365. <tr><td><li>CamExposureControl</li> </td><td>- indicating type of exposure control </td></tr>
  6366. <tr><td><li>CamExposureMode</li> </td><td>- current exposure mode (Day, Night, Auto, Schedule, Unknown) </td></tr>
  6367. <tr><td><li>CamForceEnableMulticast</li> </td><td>- Is the camera forced to enable multicast. </td></tr>
  6368. <tr><td><li>CamIP</li> </td><td>- IP-Address of Camera </td></tr>
  6369. <tr><td><li>CamLastRec</li> </td><td>- Path / name of the last recording </td></tr>
  6370. <tr><td><li>CamLastRecTime</li> </td><td>- date / starttime / endtime of the last recording </td></tr>
  6371. <tr><td><li>CamLiveFps</li> </td><td>- Frames per second of Live-Stream </td></tr>
  6372. <tr><td><li>CamLiveMode</li> </td><td>- Source of Live-View (DS, Camera) </td></tr>
  6373. <tr><td><li>camLiveQuality</li> </td><td>- Live-Stream quality set in SVS </td></tr>
  6374. <tr><td><li>camLiveResolution</li> </td><td>- Live-Stream resolution set in SVS </td></tr>
  6375. <tr><td><li>camLiveStreamNo</li> </td><td>- used Stream-number for Live-Stream </td></tr>
  6376. <tr><td><li>CamModel</li> </td><td>- Model of camera </td></tr>
  6377. <tr><td><li>CamMotDetSc</li> </td><td>- state of motion detection source (disabled, by camera, by SVS) and their parameter </td></tr>
  6378. <tr><td><li>CamNTPServer</li> </td><td>- set time server </td></tr>
  6379. <tr><td><li>CamPort</li> </td><td>- IP-Port of Camera </td></tr>
  6380. <tr><td><li>CamPreRecTime</li> </td><td>- Duration of Pre-Recording (in seconds) adjusted in SVS </td></tr>
  6381. <tr><td><li>CamPtSpeed</li> </td><td>- adjusted value of Pan/Tilt-activities (setup in SVS) </td></tr>
  6382. <tr><td><li>CamRecShare</li> </td><td>- shared folder on disk station for recordings </td></tr>
  6383. <tr><td><li>CamRecVolume</li> </td><td>- Volume on disk station for recordings </td></tr>
  6384. <tr><td><li>CamStreamFormat</li> </td><td>- the current format of video streaming </td></tr>
  6385. <tr><td><li>CamVideoType</li> </td><td>- Indicating video type </td></tr>
  6386. <tr><td><li>CamVendor</li> </td><td>- Identifier of camera producer </td></tr>
  6387. <tr><td><li>CamVideoFlip</li> </td><td>- Is the video flip </td></tr>
  6388. <tr><td><li>CamVideoMirror</li> </td><td>- Is the video mirror </td></tr>
  6389. <tr><td><li>CamVideoRotate</li> </td><td>- Is the video rotate </td></tr>
  6390. <tr><td><li>CapAudioOut</li> </td><td>- Capability to Audio Out over Surveillance Station (false/true) </td></tr>
  6391. <tr><td><li>CapChangeSpeed</li> </td><td>- Capability to various motion speed </td></tr>
  6392. <tr><td><li>CapPIR</li> </td><td>- has the camera a PIR sensor feature </td></tr>
  6393. <tr><td><li>CapPTZAbs</li> </td><td>- Capability to perform absolute PTZ action </td></tr>
  6394. <tr><td><li>CapPTZAutoFocus</li> </td><td>- Capability to perform auto focus action </td></tr>
  6395. <tr><td><li>CapPTZDirections</li> </td><td>- the PTZ directions that camera support </td></tr>
  6396. <tr><td><li>CapPTZFocus</li> </td><td>- mode of support for focus action </td></tr>
  6397. <tr><td><li>CapPTZHome</li> </td><td>- Capability to perform home action </td></tr>
  6398. <tr><td><li>CapPTZIris</li> </td><td>- mode of support for iris action </td></tr>
  6399. <tr><td><li>CapPTZObjTracking</li> </td><td>- Capability to perform objekt-tracking </td></tr>
  6400. <tr><td><li>CapPTZPan</li> </td><td>- Capability to perform pan action </td></tr>
  6401. <tr><td><li>CapPTZPresetNumber</li> </td><td>- The maximum number of preset supported by the model. 0 stands for preset incapability </td></tr>
  6402. <tr><td><li>CapPTZTilt</li> </td><td>- mode of support for tilt action </td></tr>
  6403. <tr><td><li>CapPTZZoom</li> </td><td>- Capability to perform zoom action </td></tr>
  6404. <tr><td><li>DeviceType</li> </td><td>- device type (Camera, Video_Server, PTZ, Fisheye) </td></tr>
  6405. <tr><td><li>Error</li> </td><td>- message text of last error </td></tr>
  6406. <tr><td><li>Errorcode</li> </td><td>- error code of last error </td></tr>
  6407. <tr><td><li>HomeModeState</li> </td><td>- HomeMode-state (SVS-version 8.1.0 and above) </td></tr>
  6408. <tr><td><li>LastLogEntry</li> </td><td>- the neweset entry of Surveillance Station Log (only if SVS-device and if attribute pollcaminfoall is set) </td></tr>
  6409. <tr><td><li>LastSnapFilename</li> </td><td>- the filename of the last snapshot </td></tr>
  6410. <tr><td><li>LastSnapId</li> </td><td>- the ID of the last snapshot </td></tr>
  6411. <tr><td><li>LastSnapTime</li> </td><td>- timestamp of the last snapshot </td></tr>
  6412. <tr><td><li>LastUpdateTime</li> </td><td>- date / time the last update of readings by "caminfoall" </td></tr>
  6413. <tr><td><li>LiveStreamUrl </li> </td><td>- the livestream URL if stream is started (is shown if <a href="#SSCamattr">attribute</a> "showStmInfoFull" is set) </td></tr>
  6414. <tr><td><li>Patrols</li> </td><td>- in Synology Surveillance Station predefined patrols (at PTZ-Cameras) </td></tr>
  6415. <tr><td><li>PollState</li> </td><td>- shows the state of automatic polling </td></tr>
  6416. <tr><td><li>PresetHome</li> </td><td>- Name of Home-position (at PTZ-Cameras) </td></tr>
  6417. <tr><td><li>Presets</li> </td><td>- in Synology Surveillance Station predefined Presets (at PTZ-Cameras) </td></tr>
  6418. <tr><td><li>Record</li> </td><td>- if recording is running = Start, if no recording is running = Stop </td></tr>
  6419. <tr><td><li>StmKey</li> </td><td>- current streamkey. it can be used to open livestreams without session id </td></tr>
  6420. <tr><td><li>StmKeyUnicst</li> </td><td>- Uni-cast stream path of the camera. (<a href="#SSCamattr">attribute</a> "showStmInfoFull" has to be set) </td></tr>
  6421. <tr><td><li>StmKeymjpegHttp</li> </td><td>- Mjpeg stream path(over http) of the camera (<a href="#SSCamattr">attribute</a> "showStmInfoFull" has to be set) </td></tr>
  6422. <tr><td><li>SVScustomPortHttp</li> </td><td>- Customized port of Surveillance Station (HTTP) (to get with "svsinfo") </td></tr>
  6423. <tr><td><li>SVScustomPortHttps</li> </td><td>- Customized port of Surveillance Station (HTTPS) (to get with "svsinfo") </td></tr>
  6424. <tr><td><li>SVSlicenseNumber</li> </td><td>- The total number of installed licenses (to get with "svsinfo") </td></tr>
  6425. <tr><td><li>SVSuserPriv</li> </td><td>- The effective rights of the user used for log in (to get with "svsinfo") </td></tr>
  6426. <tr><td><li>SVSversion</li> </td><td>- package version of the installed Surveillance Station (to get with "svsinfo") </td></tr>
  6427. <tr><td><li>UsedSpaceMB</li> </td><td>- used disk space of recordings by Camera </td></tr>
  6428. <tr><td><li>VideoFolder</li> </td><td>- Path to the recorded video </td></tr>
  6429. <tr><td><li>compstate</li> </td><td>- state of compatibility (compares current/simulated SVS-version with Internal COMPATIBILITY) </td></tr>
  6430. </table>
  6431. </ul>
  6432. <br><br>
  6433. </ul>
  6434. </ul>
  6435. =end html
  6436. =begin html_DE
  6437. <a name="SSCam"></a>
  6438. <h3>SSCam</h3>
  6439. <ul>
  6440. Mit diesem Modul können Operationen von in der Synology Surveillance Station (SVS) definierten Kameras und Funktionen
  6441. der SVS ausgeführt werden. Es basiert auf der SVS API und unterstützt die SVS ab Version 7. <br>
  6442. Zur Zeit werden folgende Funktionen unterstützt: <br><br>
  6443. <ul>
  6444. <ul>
  6445. <li>Start einer Aufnahme</li>
  6446. <li>Stop einer Aufnahme (per Befehl bzw. automatisch nach Ablauf der Aufnahmedauer) </li>
  6447. <li>Aufnehmen eines Schnappschusses und Ablage in der Synology Surveillance Station </li>
  6448. <li>Deaktivieren einer Kamera in Synology Surveillance Station</li>
  6449. <li>Aktivieren einer Kamera in Synology Surveillance Station</li>
  6450. <li>Steuerung der Belichtungsmodi Tag, Nacht bzw. Automatisch </li>
  6451. <li>Umschaltung der Ereigniserkennung durch Kamera, durch SVS oder deaktiviert </li>
  6452. <li>steuern der Erkennungsparameterwerte Empfindlichkeit, Schwellwert, Objektgröße und Prozentsatz für Auslösung </li>
  6453. <li>Abfrage von Kameraeigenschaften (auch mit Polling) sowie den Eigenschaften des installierten SVS-Paketes</li>
  6454. <li>Bewegen an eine vordefinierte Preset-Position (bei PTZ-Kameras) </li>
  6455. <li>Start einer vordefinierten Überwachungstour (bei PTZ-Kameras) </li>
  6456. <li>Positionieren von PTZ-Kameras zu absoluten X/Y-Koordinaten </li>
  6457. <li>kontinuierliche Bewegung von PTZ-Kameras </li>
  6458. <li>auslösen externer Ereignisse 1-10 (Aktionsregel SVS) </li>
  6459. <li>starten und beenden von Kamera-Livestreams incl. Audiowiedergabe, anzeigen der letzten Aufnahme oder des letzten Schnappschusses </li>
  6460. <li>Abruf und Ausgabe der Kamera Streamkeys sowie Stream-Urls (Nutzung von Kamera-Livestreams ohne Session Id) </li>
  6461. <li>abspielen der letzten Aufnahme bzw. Anzeige des letzten Schnappschusses </li>
  6462. <li>anzeigen der gespeicherten Anmeldeinformationen (Credentials) </li>
  6463. <li>Ein- bzw. Ausschalten des Surveillance Station HomeMode und abfragen des HomeMode-Status </li>
  6464. <li>abrufen des Surveillance Station Logs, auswerten des neuesten Eintrags als Reading </li>
  6465. <li>erzeugen einer Gallerie der letzten 1-10 Schnappschüsse (als Popup oder permanentes Device) </li>
  6466. <li>Start bzw. Stop Objekt Tracking (nur unterstützte PTZ-Kameras mit dieser Fähigkeit) </li>
  6467. <li>Setzen/Löschen eines Presets (bei PTZ-Kameras) </li>
  6468. <li>Setzen der Home-Position (bei PTZ-Kameras) </li>
  6469. <li>erstellen eines Paneels zur Kamera-Steuerung. (bei PTZ-Kameras) </li>
  6470. <li>erzeugen unterschiedlicher Typen von separaten Streaming-Devices (createStreamDev) </li>
  6471. <li>Aktivierung / Deaktivierung eines kamerainternen PIR-Sensors </li>
  6472. </ul>
  6473. </ul>
  6474. <br>
  6475. Die Aufnahmen stehen in der Synology Surveillance Station (SVS) zur Verfügung und unterliegen, wie jede andere Aufnahme, den in der Synology Surveillance Station eingestellten Regeln. <br>
  6476. So werden zum Beispiel die Aufnahmen entsprechend ihrer Archivierungsfrist gespeichert und dann gelöscht. <br><br>
  6477. Wenn sie über dieses Modul diskutieren oder zur Verbesserung des Moduls beitragen möchten, ist im FHEM-Forum ein Sammelplatz unter:<br>
  6478. <a href="http://forum.fhem.de/index.php/topic,45671.msg374390.html#msg374390">49_SSCam: Fragen, Hinweise, Neuigkeiten und mehr rund um dieses Modul</a>.<br><br>
  6479. Weitere Infomationen zum Modul sind im FHEM-Wiki zu finden:<br>
  6480. <a href="http://www.fhemwiki.de/wiki/SSCAM_-_Steuerung_von_Kameras_in_Synology_Surveillance_Station">SSCAM - Steuerung von Kameras in Synology Surveillance Station</a>.<br><br>
  6481. <b>Vorbereitung </b> <br><br>
  6482. <ul>
  6483. Dieses Modul nutzt das Perl-Modul JSON. <br>
  6484. Auf Debian-Linux basierenden Systemen kann es installiert werden mit: <br><br>
  6485. <code>sudo apt-get install libjson-perl</code> <br><br>
  6486. Das Modul verwendet für HTTP-Calls die nichtblockierenden Funktionen von HttpUtils bzw. HttpUtils_NonblockingGet. <br>
  6487. Im DSM bzw. der Synology Surveillance Station muß ein Nutzer angelegt sein. Die Zugangsdaten werden später über ein Set-Kommando dem angelegten Gerät zugewiesen. <br>
  6488. Nähere Informationen dazu unter <a href="#SSCam_Credentials">Credentials</a><br><br>
  6489. Überblick über die Perl-Module welche von SSCam genutzt werden: <br><br>
  6490. JSON <br>
  6491. Data::Dumper <br>
  6492. MIME::Base64 <br>
  6493. Time::HiRes <br>
  6494. HttpUtils (FHEM-Modul) <br><br>
  6495. </ul>
  6496. <a name="SSCamdefine"></a>
  6497. <b>Definition</b>
  6498. <ul>
  6499. <br>
  6500. Bei der Definition wird zwischen einer Kamera-Definition und der Definition einer Surveillance Station (SVS), d.h.
  6501. der Applikation selbst auf der Diskstation, unterschieden.
  6502. Abhängig von der Art des definierten Devices wird das Internal MODEL auf "&lt;Hersteller&gt; - &lt;Kameramodell&gt;" oder
  6503. SVS gesetzt und eine passende Teilmenge der beschriebenen set/get-Befehle dem Device zugewiesen. <br>
  6504. Der Gültigkeitsbereich von set/get-Befehlen ist nach dem jeweiligen Befehl angegeben "gilt für CAM, SVS, CAM/SVS".
  6505. <br><br>
  6506. Eine <b>Kamera</b> wird definiert mit: <br><br>
  6507. <ul>
  6508. <b><code>define &lt;Name&gt; SSCAM &lt;Kameraname in SVS&gt; &lt;ServerAddr&gt; [Port] [Protocol]</code></b> <br><br>
  6509. </ul>
  6510. Zunächst muß diese Kamera in der Synology Surveillance Station 7.0 oder höher eingebunden sein und entsprechend
  6511. funktionieren. <br><br>
  6512. Ein <b>SVS-Device</b> zur Steuerung von Funktionen der Surveillance Station wird definiert mit: <br><br>
  6513. <ul>
  6514. <b><code>define &lt;Name&gt; SSCAM SVS &lt;ServerAddr&gt; [Port] [Protocol]</code></b> <br><br>
  6515. </ul>
  6516. In diesem Fall wird statt &lt;Kameraname in SVS&gt; nur <b>SVS</b> angegeben. <br><br>
  6517. Das Modul SSCam basiert auf Funktionen der Synology Surveillance Station API. <br><br>
  6518. Die Parameter beschreiben im Einzelnen:
  6519. <br>
  6520. <br>
  6521. <table>
  6522. <colgroup> <col width=15%> <col width=85%> </colgroup>
  6523. <tr><td><b>Name</b> </td><td>der Name des neuen Gerätes in FHEM</td></tr>
  6524. <tr><td><b>Kameraname</b> </td><td>Kameraname wie er in der Synology Surveillance Station angegeben ist für Kamera-Device, "SVS" für SVS-Device. Leerzeichen im Namen sind nicht erlaubt. </td></tr>
  6525. <tr><td><b>ServerAddr</b> </td><td>die IP-Addresse des Synology Surveillance Station Host. Hinweis: Es sollte kein Servername verwendet werden weil DNS-Aufrufe in FHEM blockierend sind.</td></tr>
  6526. <tr><td><b>Port</b> </td><td>optional - der Port der Synology Disc Station. Wenn nicht angegeben, wird der Default-Port "5000" genutzt </td></tr>
  6527. <tr><td><b>Protocol</b> </td><td>optional - das Protokoll (http oder https) zum Funktionsaufruf. Wenn nicht angegeben, wird der Default "http" genutzt </td></tr>
  6528. </table>
  6529. <br><br>
  6530. <b>Beispiel:</b>
  6531. <pre>
  6532. <code>define CamCP SSCAM Carport 192.168.2.20 [5000] [http] </code>
  6533. <code>define CamCP SSCAM Carport 192.168.2.20 [5001] [https]</code>
  6534. # erstellt ein neues Kamera-Device CamCP
  6535. <code>define DS1 SSCAM SVS 192.168.2.20 [5000] [http] </code>
  6536. <code>define DS1 SSCAM SVS 192.168.2.20 [5001] [https] </code>
  6537. # erstellt ein neues SVS-Device DS1
  6538. </pre>
  6539. Wird eine neue Kamera definiert, wird diesem Device zunächst eine Standardaufnahmedauer von 15 zugewiesen. <br>
  6540. Über das <a href="#SSCamattr">Attribut</a> "rectime" kann die Aufnahmedauer für jede Kamera individuell angepasst werden. Der Wert "0" für "rectime" führt zu einer Endlosaufnahme, die durch "set &lt;name&gt; off" wieder gestoppt werden muß. <br>
  6541. Ein Logeintrag mit einem entsprechenden Hinweis auf diesen Umstand wird geschrieben. <br><br>
  6542. Wird das <a href="#SSCamattr">Attribut</a> "rectime" gelöscht, greift wieder der Default-Wert (15s) für die Aufnahmedauer. <br><br>
  6543. Mit dem <a href="#SSCamset">Befehl</a> <b>"set &lt;name&gt; on [rectime]"</b> wird die Aufnahmedauer temporär festgelegt und überschreibt einmalig sowohl den Defaultwert als auch den Wert des gesetzten Attributs "rectime". <br>
  6544. Auch in diesem Fall führt <b>"set &lt;name&gt; on 0"</b> zu einer Daueraufnahme. <br><br>
  6545. Eine eventuell in der SVS eingestellte Dauer der Voraufzeichnung wird weiterhin berücksichtigt. <br><br>
  6546. Erkennt das Modul die definierte Kamera als PTZ-Device (Reading "DeviceType = PTZ"), wird automatisch ein
  6547. Steuerungspaneel in der Detailansicht erstellt. Dieses Paneel setzt SVS >= 7.1 voraus. Die Eigenschaften und das
  6548. Verhalten des Paneels können mit den <a href="#SSCamattr">Attributen</a> "ptzPanel_.*" beeinflusst werden. <br>
  6549. Siehe dazu auch den <a href="#SSCamset">Befehl</a> <b>"set &lt;name&gt; createPTZcontrol"</b>.
  6550. <br><br><br>
  6551. </ul>
  6552. <a name="SSCam_Credentials"></a>
  6553. <b>Credentials </b><br><br>
  6554. <ul>
  6555. Nach dem Definieren des Gerätes müssen zuerst die Zugangsparameter gespeichert werden. Das geschieht mit dem Befehl:
  6556. <pre>
  6557. set &lt;name&gt; credentials &lt;Username&gt; &lt;Passwort&gt;
  6558. </pre>
  6559. Die Passwortlänge beträgt maximal 20 Zeichen. <br>
  6560. Der Anwender kann in Abhängigkeit der beabsichtigten einzusetzenden Funktionen einen Nutzer im DSM bzw. in der Surveillance Station einrichten. <br>
  6561. Ist der DSM-Nutzer der Gruppe Administratoren zugeordnet, hat er auf alle Funktionen Zugriff. Ohne diese Gruppenzugehörigkeit können nur Funktionen mit niedrigeren <br>
  6562. Rechtebedarf ausgeführt werden. Die benötigten Mindestrechte der Funktionen sind in der Tabelle weiter unten aufgeführt. <br>
  6563. Alternativ zum DSM-Nutzer kann ein in der SVS angelegter Nutzer verwendet werden. Auch in diesem Fall hat ein Nutzer vom Typ Manager das Recht alle Funktionen <br>
  6564. auszuführen, wobei der Zugriff auf bestimmte Kameras/ im Privilegienprofil beschränkt werden kann (siehe Hilfefunktion in SVS). <br>
  6565. Als Best Practice wird vorgeschlagen jeweils einen User im DSM und einen in der SVS anzulegen: <br><br>
  6566. <ul>
  6567. <li>DSM-User als Mitglied der Admin-Gruppe: uneingeschränkter Test aller Modulfunktionen -> session:DSM </li>
  6568. <li>SVS-User als Manager oder Betrachter: angepasstes Privilegienprofil -> session: SurveillanceStation </li>
  6569. </ul>
  6570. <br>
  6571. Über das <a href="#SSCamattr">Attribut</a> "session" kann ausgewählt werden, ob die Session mit dem DSM oder der SVS augebaut werden soll. <br>
  6572. Erfolgt der Session-Aufbau mit dem DSM, stehen neben der SVS Web-API auch darüber hinaus gehende API-Zugriffe zur Verfügung die unter Umständen zur Verarbeitung benötigt werden. <br><br>
  6573. Nach der Gerätedefinition ist die Grundeinstellung "Login in das DSM", d.h. es können Credentials mit Admin-Berechtigungen genutzt werden um zunächst alle <br>
  6574. Funktionen der Kameras testen zu können. Danach können die Credentials z.B. in Abhängigkeit der benötigten Funktionen auf eine SVS-Session mit entsprechend beschränkten Privilegienprofil umgestellt werden. <br><br>
  6575. Die nachfolgende Aufstellung zeigt die Mindestanforderungen der jeweiligen Modulfunktionen an die Nutzerrechte. <br><br>
  6576. <ul>
  6577. <table>
  6578. <colgroup> <col width=20%> <col width=80%> </colgroup>
  6579. <tr><td><li>set ... credentials </td><td> - </li></td></tr>
  6580. <tr><td><li>set ... delPreset </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6581. <tr><td><li>set ... disable </td><td> session: ServeillanceStation - Manager </li></td></tr>
  6582. <tr><td><li>set ... enable </td><td> session: ServeillanceStation - Manager </li></td></tr>
  6583. <tr><td><li>set ... expmode </td><td> session: ServeillanceStation - Manager </li></td></tr>
  6584. <tr><td><li>set ... extevent </td><td> session: DSM - Nutzer Mitglied von Admin-Gruppe </li></td></tr>
  6585. <tr><td><li>set ... goPreset </td><td> session: ServeillanceStation - Betrachter mit Privileg Objektivsteuerung der Kamera </li></td></tr>
  6586. <tr><td><li>set ... homeMode </td><td> session: ServeillanceStation - Betrachter mit Privileg Home-Modus schalten </li></td></tr>
  6587. <tr><td><li>set ... goAbsPTZ </td><td> session: ServeillanceStation - Betrachter mit Privileg Objektivsteuerung der Kamera </li></td></tr>
  6588. <tr><td><li>set ... move </td><td> session: ServeillanceStation - Betrachter mit Privileg Objektivsteuerung der Kamera </li></td></tr>
  6589. <tr><td><li>set ... motdetsc </td><td> session: ServeillanceStation - Manager </li></td></tr>
  6590. <tr><td><li>set ... on </td><td> session: ServeillanceStation - Betrachter mit erweiterten Privileg "manuelle Aufnahme" </li></td></tr>
  6591. <tr><td><li>set ... off </td><td> session: ServeillanceStation - Betrachter mit erweiterten Privileg "manuelle Aufnahme" </li></td></tr>
  6592. <tr><td><li>set ... runView </td><td> session: ServeillanceStation - Betrachter mit Privileg Liveansicht für Kamera </li></td></tr>
  6593. <tr><td><li>set ... runPatrol </td><td> session: ServeillanceStation - Betrachter mit Privileg Objektivsteuerung der Kamera </li></td></tr>
  6594. <tr><td><li>set ... setHome </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6595. <tr><td><li>set ... setPreset </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6596. <tr><td><li>set ... snap </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6597. <tr><td><li>set ... snapGallery </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6598. <tr><td><li>set ... stopView </td><td> - </li></td></tr>
  6599. <tr><td><li>get ... caminfo[all] </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6600. <tr><td><li>get ... eventlist </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6601. <tr><td><li>get ... listLog </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6602. <tr><td><li>get ... listPresets </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6603. <tr><td><li>get ... scanVirgin </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6604. <tr><td><li>get ... svsinfo </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6605. <tr><td><li>get ... snapfileinfo </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6606. <tr><td><li>get ... snapGallery </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6607. <tr><td><li>get ... snapinfo </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6608. <tr><td><li>get ... stmUrlPath </td><td> session: ServeillanceStation - Betrachter </li></td></tr>
  6609. </table>
  6610. </ul>
  6611. <br><br>
  6612. <a name="SSCam_HTTPTimeout"></a>
  6613. <b>HTTP-Timeout setzen</b><br><br>
  6614. Alle Funktionen dieses Moduls verwenden HTTP-Aufrufe gegenüber der SVS Web API. <br>
  6615. Der Standardwert für den HTTP-Timeout beträgt 4 Sekunden. Durch Setzen des <a href="#SSCamattr">Attributes</a> "httptimeout" > 0 kann dieser Wert bei Bedarf entsprechend den technischen Gegebenheiten angepasst werden. <br>
  6616. </ul>
  6617. <br><br><br>
  6618. <a name="SSCamset"></a>
  6619. <b>Set </b>
  6620. <ul>
  6621. <br>
  6622. Die aufgeführten set-Befehle sind für CAM/SVS-Devices oder nur für CAM-Devices bzw. nur für SVS-Devices gültig. Sie stehen im
  6623. Drop-Down-Menü des jeweiligen Devices zur Auswahl zur Verfügung. <br><br>
  6624. <ul>
  6625. <a name="SSCamcreateStreamDev"></a>
  6626. <li><b> set &lt;name&gt; createStreamDev [generic | mjpeg | switched] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6627. Es wird ein separates Streaming-Device (Typ SSCamSTRM) erstellt. Dieses Device kann z.B. als separates Device
  6628. in einem Dashboard genutzt werden.
  6629. Dem Streaming-Device wird der aktuelle Raum des Kameradevice zugewiesen sofern dort gesetzt.
  6630. <br><br>
  6631. <ul>
  6632. <table>
  6633. <colgroup> <col width=10%> <col width=90%> </colgroup>
  6634. <tr><td>generic </td><td>- das Streaming-Device gibt einen durch das Attribut "genericStrmHtmlTag" bestimmten Content wieder </td></tr>
  6635. <tr><td>mjpeg </td><td>- das Streaming-Device gibt einen permanenten MJPEG Kamerastream wieder (Streamkey Methode) </td></tr>
  6636. <tr><td>switched </td><td>- Wiedergabe unterschiedlicher Streamtypen. Drucktasten zur Steuerung werden angeboten. </td></tr>
  6637. </table>
  6638. </ul>
  6639. <br><br>
  6640. Die Gestaltung kann durch HTML-Tags im <a href="#SSCamattr">Attribut</a> "htmlattr" im Kameradevice oder mit den
  6641. spezifischen Attributen im Streaming-Device beeinflusst werden. <br>
  6642. Soll ein HLS-Stream im Streaming-Device vom Typ "switched" gestartet werden, muss die Kamera in der Synology Surveillance Station
  6643. auf das Videoformat H.264 eingestellt und HLS von der eingesetzten SVS-Version unterstützt sein.
  6644. Diese Auswahltaste wird deshalb im nur im Streaming-Device angeboten wenn das Reading "CamStreamFormat = HLS" beinhaltet. <br>
  6645. HLS (HTTP Live Streaming) kann momentan nur auf Mac Safari oder mobilen iOS/Android-Geräten wiedergegeben werden. <br>
  6646. Im "switched"-Device werden Drucktasten zur Steuerung des zu startenden Medientyps angeboten. <br>
  6647. Ein Streaming-Device vom Typ "generic" benötigt die Angabe von HTML-Tags im Attribut "genericStrmHtmlTag". Diese Tags
  6648. spezifizieren den wiederzugebenden Content. <br><br>
  6649. <ul>
  6650. <b>Beispiel:</b>
  6651. <pre>
  6652. attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
  6653. &lt;source src='http://192.168.2.10:32000/$NAME.m3u8' type='application/x-mpegURL'&gt;
  6654. &lt;/video&gt;
  6655. </pre>
  6656. Die Variablen $HTMLATTR, $NAME sind Platzhalter und übernehmen ein gesetztes Attribut "htmlattr" bzw. den SSCam-Devicenamen.
  6657. </ul>
  6658. </ul>
  6659. <br><br>
  6660. <ul>
  6661. <li><b> set &lt;name&gt; createPTZcontrol </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br>
  6662. Es wird ein separates PTZ-Steuerungspaneel (Type SSCamSTRM) erstellt. Es wird der aktuelle Raum des Kameradevice
  6663. zugewiesen sofern dort gesetzt.
  6664. Mit den "ptzPanel_.*"-<a href="#SSCamattr">Attributen</a> bzw. den spezifischen Attributen des erzeugten
  6665. SSCamSTRM-Devices können die Eigenschaften des PTZ-Paneels beeinflusst werden. <br>
  6666. <br><br>
  6667. </ul>
  6668. <ul>
  6669. <li><b> set &lt;name&gt; createSnapGallery </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6670. Es wird eine Schnappschußgallerie als separates Device (Type SSCamSTRM) erzeugt. Das Device wird im Raum
  6671. "SnapGallery" erstellt.
  6672. Mit den "snapGallery..."-<a href="#SSCamattr">Attributen</a> bzw. den spezifischen Attributen des erzeugten SSCamSTRM-Devices
  6673. können die Eigenschaften der Schnappschußgallerie beeinflusst werden. <br>
  6674. <br><br>
  6675. </ul>
  6676. <ul>
  6677. <li><b> set &lt;name&gt; credentials &lt;username&gt; &lt;password&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM/SVS)</li> <br>
  6678. Setzt Username / Passwort für den Zugriff auf die Synology Surveillance Station.
  6679. Siehe <a href="#SSCam_Credentials">Credentials</a><br>
  6680. <br><br>
  6681. </ul>
  6682. <ul>
  6683. <li><b> set &lt;name&gt; delPreset &lt;PresetName&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br>
  6684. Löscht einen Preset "&lt;PresetName&gt;". Im FHEMWEB wird eine Drop-Down Liste der aktuell vorhandenen
  6685. Presets angeboten.
  6686. </ul>
  6687. <br><br>
  6688. <ul>
  6689. <li><b> set &lt;name&gt; [enable|disable] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6690. Aktviviert / deaktiviert eine Kamera. <br>
  6691. Um eine Liste von Kameras oder alle Kameras (mit Regex) zum Beispiel um 21:46 zu <b>deaktivieren</b> / zu <b>aktivieren</b> zwei Beispiele mit at:
  6692. <pre>
  6693. define a13 at 21:46 set CamCP1,CamFL,CamHE1,CamTER disable (enable)
  6694. define a14 at 21:46 set Cam.* disable (enable)
  6695. </pre>
  6696. Etwas komfortabler gelingt das Schalten aller Kameras über einen Dummy. Zunächst wird der Dummy angelegt:
  6697. <pre>
  6698. define allcams dummy
  6699. attr allcams eventMap on:enable off:disable
  6700. attr allcams room Cams
  6701. attr allcams webCmd enable:disable
  6702. </pre>
  6703. Durch Verknüpfung mit zwei angelegten notify, jeweils ein notify für "enable" und "disable", kann man durch Schalten des Dummys auf "enable" bzw. "disable" alle Kameras auf einmal aktivieren bzw. deaktivieren.
  6704. <pre>
  6705. define all_cams_disable notify allcams:.*off set CamCP1,CamFL,CamHE1,CamTER disable
  6706. attr all_cams_disable room Cams
  6707. define all_cams_enable notify allcams:on set CamCP1,CamFL,CamHE1,CamTER enable
  6708. attr all_cams_enable room Cams
  6709. </pre>
  6710. </ul>
  6711. <br>
  6712. <ul>
  6713. <li><b> set &lt;name&gt; expmode [day|night|auto] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6714. Mit diesem Befehl kann der Belichtungsmodus der Kameras gesetzt werden. Dadurch wird z.B. das Verhalten der Kamera-LED's entsprechend gesteuert.
  6715. Die erfolgreiche Umschaltung wird durch das Reading CamExposureMode ("get ... caminfoall") reportet. <br><br>
  6716. <b> Hinweis: </b> <br>
  6717. Die erfolgreiche Ausführung dieser Funktion ist davon abhängig ob die SVS diese Funktionalität der Kamera unterstützt.
  6718. Ist in SVS -&gt; IP-Kamera -&gt; Optimierung -&gt; Belichtungsmodus das Feld für den Tag/Nachtmodus grau hinterlegt, ist nicht von einer lauffähigen Unterstützung dieser
  6719. Funktion auszugehen.
  6720. <br><br>
  6721. </ul>
  6722. <ul>
  6723. <li><b> set &lt;name&gt; extevent [ 1-10 ] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für SVS)</li> <br>
  6724. Dieses Kommando triggert ein externes Ereignis (1-10) in der SVS.
  6725. Die Aktionen, die dieses Ereignis auslöst, sind zuvor in dem Aktionsregeleditor der SVS einzustellen. Es stehen die Ereignisse
  6726. 1-10 zur Verfügung.
  6727. In der Benachrichtigungs-App der SVS können auch Email, SMS oder Mobil (DS-Cam) Nachrichten ausgegeben werden wenn ein externes
  6728. Ereignis ausgelöst wurde.
  6729. Nähere Informationen dazu sind in der Hilfe zum Aktionsregeleditor zu finden.
  6730. Der verwendete User benötigt Admin-Rechte in einer DSM-Session.
  6731. </ul>
  6732. <br><br>
  6733. <ul>
  6734. <li><b> set &lt;name&gt; goAbsPTZ [ X Y | up | down | left | right ] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6735. Mit diesem Kommando wird eine PTZ-Kamera in Richtung einer wählbaren absoluten X/Y-Koordinate bewegt, oder zur maximalen Absolutposition in Richtung up/down/left/right.
  6736. Die Option ist nur für Kameras verfügbar die das Reading "CapPTZAbs=true" (die Fähigkeit für PTZAbs-Aktionen) besitzen. Die Eigenschaften der Kamera kann mit "get &lt;name&gt; caminfoall" abgefragt werden.
  6737. <br><br>
  6738. Beispiel für Ansteuerung absoluter X/Y-Koordinaten: <br>
  6739. <pre>
  6740. set &lt;name&gt; goAbsPTZ 120 450
  6741. </pre>
  6742. Dieses Beispiel bewegt die Kameralinse in die Position X=120 und Y=450. <br>
  6743. Der Wertebereich ist dabei:
  6744. <pre>
  6745. X = 0 - 640 (0 - 319 bewegt nach links, 321 - 640 bewegt nach rechts, 320 bewegt die Linse nicht)
  6746. Y = 0 - 480 (0 - 239 bewegt nach unten, 241 - 480 bewegt nach oben, 240 bewegt die Linse nicht)
  6747. </pre>
  6748. Die Linse kann damit in kleinsten bis sehr großen Schritten in die gewünschte Richtung bewegt werden.
  6749. Dieser Vorgang muß ggf. mehrfach wiederholt werden um die Kameralinse in die gewünschte Position zu bringen. <br><br>
  6750. Soll die Bewegung mit der maximalen Schrittweite erfolgen, kann zur Vereinfachung der Befehl:
  6751. <pre>
  6752. set &lt;name&gt; goAbsPTZ [up|down|left|right]
  6753. </pre>
  6754. verwendet werden. Die Optik wird in diesem Fall mit der größt möglichen Schrittweite zur Absolutposition in der angegebenen Richtung bewegt.
  6755. Auch in diesem Fall muß der Vorgang ggf. mehrfach wiederholt werden um die Kameralinse in die gewünschte Position zu bringen.
  6756. </ul>
  6757. <br><br>
  6758. <ul>
  6759. <li><b> set &lt;name&gt; goPreset &lt;Preset&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6760. Mit diesem Kommando können PTZ-Kameras in eine vordefininierte Position bewegt werden. <br>
  6761. Die Preset-Positionen müssen dazu zunächst in der Synology Surveillance Station angelegt worden sein. Das geschieht in der PTZ-Steuerung im IP-Kamera Setup.
  6762. Die Presets werden über das Kommando "get &lt;name&gt; caminfoall" eingelesen (geschieht bei restart von FHEM automatisch). Der Einlesevorgang kann durch ein Kamerapolling
  6763. regelmäßig wiederholt werden. Ein langes Pollingintervall ist in diesem Fall empfehlenswert, da sich die Presetpositionen nur im Fall der Neuanlage bzw. Änderung verändern werden.
  6764. <br><br>
  6765. Hier ein Beispiel einer PTZ-Steuerung in Abhängigkeit eines IR-Melder Events:
  6766. <pre>
  6767. define CamFL.Preset.Wandschrank notify MelderTER:on.* set CamFL goPreset Wandschrank, ;; define CamFL.Preset.record at +00:00:10 set CamFL on 5 ;;;; define s3 at +*{3}00:00:05 set CamFL snap ;; define CamFL.Preset.back at +00:00:30 set CamFL goPreset Home
  6768. </pre>
  6769. Funktionsweise: <br>
  6770. Der IR-Melder "MelderTER" registriert eine Bewegung. Daraufhin wird die Kamera CamFL in die Preset-Position "Wandschrank" gebracht. Eine Aufnahme mit Dauer von 5 Sekunden startet 10 Sekunden
  6771. später. Da die Voraufnahmezeit der Kamera 10s beträgt (vgl. Reading "CamPreRecTime"), startet die effektive Aufnahme wenn der Kameraschwenk beginnt. <br>
  6772. Mit dem Start der Aufnahme werden drei Schnappschüsse im Abstand von 5 Sekunden angefertigt. <br>
  6773. Nach einer Zeit von 30 Sekunden fährt die Kamera wieder zurück in die "Home"-Position. <br><br>
  6774. Ein Auszug aus dem Log verdeutlicht den Ablauf:
  6775. <pre>
  6776. 2016.02.04 15:02:14 2: CamFL - Camera Flur_Vorderhaus has moved to position "Wandschrank"
  6777. 2016.02.04 15:02:24 2: CamFL - Camera Flur_Vorderhaus Recording with Recordtime 5s started
  6778. 2016.02.04 15:02:29 2: CamFL - Snapshot of Camera Flur_Vorderhaus has been done successfully
  6779. 2016.02.04 15:02:30 2: CamFL - Camera Flur_Vorderhaus Recording stopped
  6780. 2016.02.04 15:02:34 2: CamFL - Snapshot of Camera Flur_Vorderhaus has been done successfully
  6781. 2016.02.04 15:02:39 2: CamFL - Snapshot of Camera Flur_Vorderhaus has been done successfully
  6782. 2016.02.04 15:02:44 2: CamFL - Camera Flur_Vorderhaus has moved to position "Home"
  6783. </pre>
  6784. </ul>
  6785. <br><br>
  6786. <ul>
  6787. <li><b> set &lt;name&gt; homeMode [on|off] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für SVS)</li> <br>
  6788. Schaltet den HomeMode der Surveillance Station ein bzw. aus.
  6789. Informationen zum HomeMode sind in der <a href="https://www.synology.com/de-de/knowledgebase/Surveillance/help/SurveillanceStation/home_mode">Synology Onlinehilfe</a>
  6790. enthalten.
  6791. <br><br>
  6792. </ul>
  6793. <ul>
  6794. <li><b> set &lt;name&gt; motdetsc [camera|SVS|disable] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6795. Der Befehl "motdetsc" (steht für motion detection source) schaltet die Bewegungserkennung in den gewünschten Modus.
  6796. Wird die Bewegungserkennung durch die Kamera / SVS ohne weitere Optionen eingestellt, werden die momentan gültigen Bewegungserkennungsparameter der
  6797. Kamera / SVS beibehalten. Die erfolgreiche Ausführung der Operation lässt sich u.a. anhand des Status von SVS -&gt; IP-Kamera -&gt; Ereigniserkennung -&gt;
  6798. Bewegung nachvollziehen. <br><br>
  6799. Für die Bewegungserkennung durch SVS bzw. durch Kamera können weitere Optionen angegeben werden. Die verfügbaren Optionen bezüglich der Bewegungserkennung
  6800. durch SVS sind "Empfindlichkeit" und "Schwellwert". <br><br>
  6801. <ul>
  6802. <table>
  6803. <colgroup> <col width=50%> <col width=50%> </colgroup>
  6804. <tr><td>set &lt;name&gt; motdetsc SVS [Empfindlichkeit] [Schwellwert] </td><td># Befehlsmuster </td></tr>
  6805. <tr><td>set &lt;name&gt; motdetsc SVS 91 30 </td><td># setzt die Empfindlichkeit auf 91 und den Schwellwert auf 30 </td></tr>
  6806. <tr><td>set &lt;name&gt; motdetsc SVS 0 40 </td><td># behält gesetzten Wert für Empfindlichkeit bei, setzt Schwellwert auf 40 </td></tr>
  6807. <tr><td>set &lt;name&gt; motdetsc SVS 15 </td><td># setzt die Empfindlichkeit auf 15, Schwellwert bleibt unverändert </td></tr>
  6808. </table>
  6809. </ul>
  6810. <br><br>
  6811. Wird die Bewegungserkennung durch die Kamera genutzt, stehen die Optionen "Empfindlichkeit", "Objektgröße" und "Prozentsatz für Auslösung" zur Verfügung. <br><br>
  6812. <ul>
  6813. <table>
  6814. <colgroup> <col width=50%> <col width=50%> </colgroup>
  6815. <tr><td>set &lt;name&gt; motdetsc camera [Empfindlichkeit] [Schwellwert] [Prozentsatz] </td><td># Befehlsmuster </td></tr>
  6816. <tr><td>set &lt;name&gt; motdetsc camera 89 0 20 </td><td># setzt die Empfindlichkeit auf 89, Prozentsatz auf 20 </td></tr>
  6817. <tr><td>set &lt;name&gt; motdetsc camera 0 40 10 </td><td># behält gesetzten Wert für Empfindlichkeit bei, setzt Schwellwert auf 40, Prozentsatz auf 10 </td></tr>
  6818. <tr><td>set &lt;name&gt; motdetsc camera 30 </td><td># setzt die Empfindlichkeit auf 30, andere Werte bleiben unverändert </td></tr>
  6819. </table>
  6820. </ul>
  6821. <br><br>
  6822. Es ist immer die Reihenfolge der Optionswerte zu beachten. Nicht gewünschte Optionen sind mit "0" zu besetzen sofern danach Optionen folgen
  6823. deren Werte verändert werden sollen (siehe Beispiele oben). Der Zahlenwert der Optionen beträgt 1 - 99 (außer Sonderfall "0"). <br><br>
  6824. Die jeweils verfügbaren Optionen unterliegen der Funktion der Kamera und der Unterstützung durch die SVS. Es können jeweils nur die Optionen genutzt werden die in
  6825. SVS -&gt; Kamera bearbeiten -&gt; Ereigniserkennung zur Verfügung stehen. Weitere Infos sind der Online-Hilfe zur SVS zu entnehmen. <br><br>
  6826. Über den Befehl "get &lt;name&gt; caminfoall" wird auch das <a href="#SSCamreadings">Reading</a> "CamMotDetSc" aktualisiert welches die gegenwärtige Einstellung der Bewegungserkennung dokumentiert.
  6827. Es werden nur die Parameter und Parameterwerte angezeigt, welche die SVS aktiv unterstützt. Die Kamera selbst kann weiterführende Einstellmöglichkeiten besitzen. <br><br>
  6828. Beipiel:
  6829. <pre>
  6830. CamMotDetSc SVS, sensitivity: 76, threshold: 55
  6831. </pre>
  6832. <br><br>
  6833. </ul>
  6834. <ul>
  6835. <li><b> set &lt;name&gt; move [ right | up | down | left | dir_X ] [Sekunden] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM bis SVS Version 7.1)</li>
  6836. <b> set &lt;name&gt; move [ right | upright | up | upleft | left | downleft | down | downright ] [Sekunden] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM ab SVS Version 7.2) <br><br>
  6837. Mit diesem Kommando wird eine kontinuierliche Bewegung der PTZ-Kamera gestartet. Neben den vier Grundrichtungen up/down/left/right stehen auch
  6838. Zwischenwinkelmaße "dir_X" zur Verfügung. Die Feinheit dieser Graduierung ist von der Kamera abhängig und kann dem Reading "CapPTZDirections" entnommen werden. <br><br>
  6839. Das Bogenmaß von 360 Grad teilt sich durch den Wert von "CapPTZDirections" und beschreibt die Bewegungsrichtungen beginnend mit "0=rechts" entgegen dem
  6840. Uhrzeigersinn. D.h. bei einer Kamera mit "CapPTZDirections = 8" bedeutet dir_0 = rechts, dir_2 = oben, dir_4 = links, dir_6 = unten bzw. dir_1, dir_3, dir_5 und dir_7
  6841. die entsprechenden Zwischenrichtungen. Die möglichen Bewegungsrichtungen bei Kameras mit "CapPTZDirections = 32" sind dementsprechend kleinteiliger. <br><br>
  6842. Im Gegensatz zum "set &lt;name&gt; goAbsPTZ"-Befehl startet der Befehl "set &lt;name&gt; move" eine kontinuierliche Bewegung bis ein Stop-Kommando empfangen wird.
  6843. Das Stop-Kommando wird nach Ablauf der optional anzugebenden Zeit [Sekunden] ausgelöst. Wird diese Laufzeit nicht angegeben, wird implizit Sekunde = 1 gesetzt. <br><br>
  6844. <b>Beispiele: </b><br>
  6845. <pre>
  6846. set &lt;name&gt; move up 0.5 : bewegt PTZ 0,5 Sek. (zzgl. Prozesszeit) nach oben
  6847. set &lt;name&gt; move dir_1 1.5 : bewegt PTZ 1,5 Sek. (zzgl. Prozesszeit) nach rechts-oben
  6848. set &lt;name&gt; move dir_20 0.7 : bewegt PTZ 1,5 Sek. (zzgl. Prozesszeit) nach links-unten ("CapPTZDirections = 32)"
  6849. </pre>
  6850. </ul>
  6851. <br><br>
  6852. <ul>
  6853. <li><b> set &lt;name&gt; [on [&lt;rectime&gt;] | off] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li><br>
  6854. Der Befehl "set &lt;name&gt; on" startet eine Aufnahme. Die Standardaufnahmedauer beträgt 15 Sekunden. Sie kann mit dem
  6855. Attribut "rectime" individuell festgelegt werden.
  6856. Die im Attribut (bzw. im Standard) hinterlegte Aufnahmedauer kann einmalig mit "set &lt;name&gt; on &lt;rectime&gt;"
  6857. überschrieben werden.
  6858. Die Aufnahme stoppt automatisch nach Ablauf der Zeit "rectime".<br>
  6859. Ein Sonderfall ist der Start einer Daueraufnahme mit "set &lt;name&gt; on 0" bzw. dem Attributwert "rectime = 0".
  6860. In diesem Fall wird eine Daueraufnahme gestartet, die explizit wieder mit dem Befehl "set &lt;name&gt; off" gestoppt
  6861. werden muß.<br>
  6862. Das Aufnahmeverhalten kann weiterhin mit dem Attribut "recextend" beeinflusst werden.<br><br>
  6863. <b>Attribut "recextend = 0" bzw. nicht gesetzt (Standard):</b><br><br>
  6864. <ul>
  6865. <li> wird eine Aufnahme mit z.B. rectime=22 gestartet, wird kein weiterer Startbefehl für eine Aufnahme akzeptiert bis diese gestartete Aufnahme nach 22 Sekunden
  6866. beendet ist. Ein Hinweis wird bei verbose=3 im Logfile protokolliert. </li>
  6867. </ul>
  6868. <br>
  6869. <b>Attribut "recextend = 1" gesetzt:</b><br>
  6870. <ul>
  6871. <li> eine zuvor gestartete Aufnahme wird bei einem erneuten "set <name> on" -Befehl um die Aufnahmezeit "rectime" verlängert. Das bedeutet, dass der Timer für
  6872. den automatischen Stop auf den Wert "rectime" neu gesetzt wird. Dieser Vorgang wiederholt sich mit jedem Start-Befehl. Dadurch verlängert sich eine laufende
  6873. Aufnahme bis kein Start-Inpuls mehr registriert wird. </li>
  6874. <li> eine zuvor gestartete Endlos-Aufnahme wird mit einem erneuten "set <name> on"-Befehl nach der Aufnahmezeit "rectime" gestoppt (Timerneustart). Ist dies
  6875. nicht gewünscht, ist darauf zu achten dass bei der Verwendung einer Endlos-Aufnahme das Attribut "recextend" nicht verwendet wird. </li>
  6876. </ul>
  6877. <br>
  6878. Beispiele für einfachen <b>Start/Stop einer Aufnahme</b>: <br><br>
  6879. <table>
  6880. <colgroup> <col width=20%> <col width=80%> </colgroup>
  6881. <tr><td>set &lt;name&gt; on [rectime] </td><td>startet die Aufnahme der Kamera &lt;name&gt;, automatischer Stop der Aufnahme nach Ablauf der Zeit [rectime] (default 15s oder wie im <a href="#SSCamattr">Attribut</a> "rectime" angegeben)</td></tr>
  6882. <tr><td>set &lt;name&gt; off </td><td>stoppt die Aufnahme der Kamera &lt;name&gt;</td></tr>
  6883. </table>
  6884. </ul>
  6885. <br><br>
  6886. <ul>
  6887. <li><b> set &lt;name&gt; optimizeParams [mirror:&lt;value&gt;] [flip:&lt;value&gt;] [rotate:&lt;value&gt;] [ntp:&lt;value&gt;]</b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6888. Setzt eine oder mehrere Eigenschaften für die Kamera. Das Video kann gespiegelt (mirror), auf den Kopf gestellt (flip) oder
  6889. gedreht (rotate) werden. Die jeweiligen Eigenschaften müssen von der Kamera unterstützt werden. Mit "ntp" wird der Zeitserver
  6890. eingestellt den die Kamera zur Zeitsynchronisation verwendet. <br><br>
  6891. &lt;value&gt; kann sein für: <br>
  6892. <ul>
  6893. <li> <b>mirror, flip, rotate: </b> true | false </li>
  6894. <li> <b>ntp: </b> der Name oder die IP-Adresse des Zeitservers </li>
  6895. </ul>
  6896. <br><br>
  6897. <b>Beispiele:</b> <br>
  6898. <code> set &lt;name&gt; optimizeParams mirror:true flip:true ntp:time.windows.com </code><br>
  6899. # Das Bild wird gespiegelt, auf den Kopf gestellt und der Zeitserver auf "time.windows.com" eingestellt.<br>
  6900. <code> set &lt;name&gt; optimizeParams ntp:Surveillance%20Station </code><br>
  6901. # Die Surveillance Station wird als Zeitserver eingestellt. (NTP-Dienst muss im DSM aktiviert sein) <br>
  6902. <code> set &lt;name&gt; optimizeParams mirror:true flip:false rotate:true </code><br>
  6903. # Das Bild wird gespiegelt und um 90 Grad gedreht. <br>
  6904. <br><br>
  6905. </ul>
  6906. <ul>
  6907. <li><b> set &lt;name&gt; pirSensor [activate | deactivate] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6908. Aktiviert / deaktiviert den Infrarot-Sensor der Kamera (sofern die Kamera einen PIR-Sensor enthält).
  6909. </ul>
  6910. <br><br>
  6911. <ul>
  6912. <li><b> set &lt;name&gt; runPatrol &lt;Patrolname&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6913. Dieses Kommando startet die vordefinierterte Überwachungstour einer PTZ-Kamera. <br>
  6914. Die Überwachungstouren müssen dazu zunächst in der Synology Surveillance Station angelegt worden sein.
  6915. Das geschieht in der PTZ-Steuerung im IP-Kamera Setup -&gt; PTZ-Steuerung -&gt; Überwachung.
  6916. Die Überwachungstouren (Patrols) werden über das Kommando "get &lt;name&gt; caminfoall" eingelesen, welches beim Restart von FHEM automatisch abgearbeitet wird.
  6917. Der Einlesevorgang kann durch ein Kamerapolling regelmäßig wiederholt werden. Ein langes Pollingintervall ist in diesem Fall empfehlenswert, da sich die
  6918. Überwachungstouren nur im Fall der Neuanlage bzw. Änderung verändern werden.
  6919. Nähere Informationen zur Anlage von Überwachungstouren sind in der Hilfe zur Surveillance Station enthalten.
  6920. </ul>
  6921. <br><br>
  6922. <ul>
  6923. <li><b> set &lt;name&gt; runView [live_fw | live_fw_hls | live_link | live_open [&lt;room&gt;] | lastrec_fw | lastrec_fw_MJPEG | lastrec_fw_MPEG4/H.264 | lastrec_open [&lt;room&gt;] | lastsnap_fw] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  6924. <ul>
  6925. <table>
  6926. <colgroup> <col width=25%> <col width=75%> </colgroup>
  6927. <tr><td>live_fw </td><td>- MJPEG-LiveStream. Audiowiedergabe wird mit angeboten wenn verfügbar. </td></tr>
  6928. <tr><td>live_fw_hls </td><td>- HLS-LiveStream (aktuell nur Mac Safari und mobile iOS/Android-Geräte) </td></tr>
  6929. <tr><td>live_link </td><td>- Link zu einem MJPEG-Livestream </td></tr>
  6930. <tr><td>live_open [&lt;room&gt;] </td><td>- öffnet MJPEG-Stream in separatem Browser-Fenster </td></tr>
  6931. <tr><td>lastrec_fw </td><td>- letzte Aufnahme als iFrame Objekt </td></tr>
  6932. <tr><td>lastrec_fw_MJPEG </td><td>- nutzbar wenn Aufnahme im Format MJPEG vorliegt </td></tr>
  6933. <tr><td>lastrec_fw_MPEG4/H.264 </td><td>- nutzbar wenn Aufnahme im Format MPEG4/H.264 vorliegt </td></tr>
  6934. <tr><td>lastrec_open [&lt;room&gt;] </td><td>- letzte Aufnahme wird in separatem Browser-Fenster geöffnet </td></tr>
  6935. <tr><td>lastsnap_fw </td><td>- letzter Schnappschuss wird dargestellt </td></tr>
  6936. </table>
  6937. </ul>
  6938. <br><br>
  6939. Mit <b>"live_fw, live_link, live_open"</b> wird ein MJPEG-Livestream, entweder als eingebettetes Image
  6940. oder als generierter Link, gestartet. <br>
  6941. Der Befehl <b>"live_open"</b> öffnet ein separates Browserfenster mit dem MJPEG-Livestream. Wird dabei optional der Raum mit
  6942. angegeben, wird das Browserfenster nur dann gestartet, wenn dieser Raum aktuell im Browser geöffnet ist. <br>
  6943. Soll mit <b>"live_fw_hls"</b> ein HLS-Stream verwendet werden, muss die Kamera in der Synology Surveillance Station auf
  6944. das Videoformat H.264 (nicht MJPEG) eingestellt und HLS durch die eingesetzte SVS-Version unterstützt sein.
  6945. Diese Möglichkeit wird deshalb nur dann angeboten wenn das Reading "CamStreamFormat" den Wert "HLS" hat.
  6946. <br><br>
  6947. Der Zugriff auf die letzte Aufnahme einer Kamera kann über die Optionen <b>"lastrec_fw.*"</b> bzw. <b>"lastrec_open"</b> erfolgen.
  6948. Bei Verwendung von <b>"lastrec_fw.*"</b> wird die letzte Aufnahme als eingebettetes iFrame-Objekt abgespielt. Es werden entsprechende
  6949. Steuerungselemente zur Wiedergabegeschwindigkeit usw. angeboten wenn verfügbar. <br><br>
  6950. Der Befehl <b>"set &lt;name&gt; runView lastsnap_fw"</b> zeigt den letzten Schnappschuss der Kamera eingebettet an. <br>
  6951. Durch Angabe des optionalen Raumes bei <b>"lastrec_open"</b> erfolgt die gleiche Einschränkung wie bei "live_open". <br>
  6952. Die Gestaltung der Fenster im FHEMWEB kann durch HTML-Tags im <a href="#SSCamattr">Attribut</a> "htmlattr" beeinflusst werden.
  6953. <br><br>
  6954. <b>Beispiel:</b><br>
  6955. <pre>
  6956. attr &lt;name&gt; htmlattr width="500" height="375"
  6957. attr &lt;name&gt; htmlattr width="500" height="375" top="200" left="300"
  6958. </pre>
  6959. Wird der Stream als live_fw gestartet, ändert sich die Größe entsprechend der Angaben von Width und Hight. <br>
  6960. Das Kommando <b>"set &lt;name&gt; runView live_open"</b> startet den Livestreamlink sofort in einem neuen
  6961. Browserfenster.
  6962. Dabei wird für jede aktive FHEMWEB-Session eine Fensteröffnung initiiert. Soll dieses Verhalten geändert werden, kann
  6963. <b>"set &lt;name&gt; runView live_open &lt;room&gt;"</b> verwendet werden um das Öffnen des Browserfensters in einem
  6964. beliebigen, in einer FHEMWEB-Session aktiven Raum "&lt;room&gt;", zu initiieren.<br>
  6965. Das gesetzte <a href="#SSCamattr">Attribut</a> "livestreamprefix" überschreibt im <a href="#SSCamreadings">Reading</a> "LiveStreamUrl"
  6966. die Angaben für Protokoll, Servername und Port. Damit kann z.B. die LiveStreamUrl für den Versand und externen Zugriff
  6967. auf die SVS modifiziert werden. <br><br>
  6968. <b>Beispiel:</b><br>
  6969. <pre>
  6970. attr &lt;name&gt; livestreamprefix https://&lt;Servername&gt;:&lt;Port&gt;
  6971. </pre>
  6972. Der Livestream wird über das Kommando <b>"set &lt;name&gt; stopView"</b> wieder beendet. <br>
  6973. Die "runView" Funktion schaltet ebenfalls Streaming-Devices vom Typ "switched" in den entsprechenden Modus. <br><br>
  6974. Abhängig vom wiedergegebenen Content werden unterschiedliche Steuertasten angeboten: <br><br>
  6975. <ul>
  6976. <table>
  6977. <colgroup> <col width=25%> <col width=75%> </colgroup>
  6978. <tr><td> Start Recording </td><td>- startet eine Endlosaufnahme </td></tr>
  6979. <tr><td> Stop Recording </td><td>- stoppt eine Aufnahme </td></tr>
  6980. <tr><td> Take Snapshot </td><td>- löst einen Schnappschuß aus </td></tr>
  6981. <tr><td> Switch off </td><td>- stoppt eine laufende Wiedergabe </td></tr>
  6982. </table>
  6983. </ul>
  6984. <br>
  6985. <b>Hinweis zu HLS (HTTP Live Streaming):</b> <br>
  6986. Das Video startet mit einer technologisch bedingten Verzögerung. Jeder Stream wird in eine Reihe sehr kleiner Videodateien
  6987. (mit etwa 10 Sekunden Länge) segmentiert und an den Client ausgeliefert.
  6988. Die Kamera muss in der SVS auf das Videoformat H.264 eingestellt sein und nicht jeder Kameratyp ist gleichermassen für
  6989. HLS-Streaming geeignet.
  6990. Momentan kann HLS nur durch den Mac Safari Browser sowie auf mobilen iOS/Android-Geräten wiedergegeben werden.
  6991. </ul>
  6992. <br><br>
  6993. <ul>
  6994. <li><b> set &lt;name&gt; setHome &lt;PresetName&gt; </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br>
  6995. Setzt die Home-Position der Kamera auf einen vordefinierten Preset "&lt;PresetName&gt;" oder auf die aktuell angefahrene
  6996. Position.
  6997. </ul>
  6998. <br><br>
  6999. <ul>
  7000. <li><b> set &lt;name&gt; setPreset &lt;PresetNummer&gt; [&lt;PresetName&gt;] [&lt;Speed&gt;] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br>
  7001. Setzt einen Preset mit dem Namen "&lt;PresetName&gt;" auf die aktuell angefahrene Position der Kamera. Optional kann die
  7002. Geschwindigkeit angegeben werden (&lt;Speed&gt;). Ist kein PresetName angegeben, wird die PresetNummer als Name verwendet.
  7003. Aus diesem Grund ist &lt;PresetName&gt; optional definiert, sollte jedoch im Normalfall gesetzt werden.
  7004. </ul>
  7005. <br><br>
  7006. <ul>
  7007. <li><b> set &lt;name&gt; snap </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7008. Ein <b>Schnappschuß</b> kann ausgelöst werden mit:
  7009. <pre>
  7010. set &lt;name&gt; snap
  7011. </pre>
  7012. Nachfolgend einige Beispiele für die <b>Auslösung von Schnappschüssen</b>. <br><br>
  7013. Soll eine Reihe von Schnappschüssen ausgelöst werden wenn eine Aufnahme startet, kann das z.B. durch folgendes notify geschehen. <br>
  7014. Sobald der Start der Kamera CamHE1 ausgelöst wird (Attribut event-on-change-reading -> "Record" setzen), werden abhängig davon 3 Snapshots im Abstand von 2 Sekunden getriggert.
  7015. <pre>
  7016. define he1_snap_3 notify CamHE1:Record.*Start define h3 at +*{3}00:00:02 set CamHE1 snap
  7017. </pre>
  7018. Triggern von 2 Schnappschüssen der Kamera "CamHE1" im Abstand von 6 Sekunden nachdem der Bewegungsmelder "MelderHE1" einen Event gesendet hat, <br>
  7019. kann z.B. mit folgendem notify geschehen:
  7020. <pre>
  7021. define he1_snap_2 notify MelderHE1:on.* define h2 at +*{2}00:00:06 set CamHE1 snap
  7022. </pre>
  7023. Es wird die ID und der Filename des letzten Snapshots als Wert der Variable "LastSnapId" bzw. "LastSnapFilename" in den Readings der Kamera ausgegeben. <br><br>
  7024. </ul>
  7025. <br><br>
  7026. <ul>
  7027. <li><b> set &lt;name&gt; snapGallery [1-10] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7028. Der Befehl ist nur vorhanden wenn das Attribut "snapGalleryBoost=1" gesetzt wurde.
  7029. Er erzeugt eine Ausgabe der letzten [x] Schnappschüsse ebenso wie <a href="#SSCamget">"get &lt;name&gt; snapGallery"</a>. Abweichend von "get" wird mit Attribut
  7030. <a href="#SSCamattr">Attribut</a> "snapGalleryBoost=1" kein Popup erzeugt, sondern die Schnappschußgalerie als Browserseite
  7031. dargestellt. Alle weiteren Funktionen und Attribute entsprechen dem "get &lt;name&gt; snapGallery" Kommando. <br>
  7032. Wenn die Ausgabe einer Schnappschußgalerie, z.B. über ein "at oder "notify", getriggert wird, sollte besser das
  7033. <a href="#SSCamget">"get &lt;name&gt; snapGallery"</a> Kommando anstatt "set" verwendet werden.
  7034. </ul>
  7035. <br><br>
  7036. <ul>
  7037. <li><b> set &lt;name&gt; startTracking </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM mit Tracking Fähigkeit)</li> <br>
  7038. Startet Objekt Tracking der Kamera.
  7039. Der Befehl ist nur vorhanden wenn die Surveillance Station die Fähigkeit der Kamera zum Objekt Tracking erkannt hat
  7040. (Reading "CapPTZObjTracking").
  7041. </ul>
  7042. <br><br>
  7043. <ul>
  7044. <li><b> set &lt;name&gt; stopTracking </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM mit Tracking Fähigkeit)</li> <br>
  7045. Stoppt Objekt Tracking der Kamera.
  7046. Der Befehl ist nur vorhanden wenn die Surveillance Station die Fähigkeit der Kamera zum Objekt Tracking erkannt hat
  7047. (Reading "CapPTZObjTracking").
  7048. </ul>
  7049. <br><br>
  7050. </ul>
  7051. <br>
  7052. <a name="SSCamget"></a>
  7053. <b>Get</b>
  7054. <ul>
  7055. <br>
  7056. Mit SSCam können die Eigenschaften der Surveillance Station und der Kameras abgefragt werden. <br>
  7057. Die aufgeführten get-Befehle sind für CAM/SVS-Devices oder nur für CAM-Devices bzw. nur für SVS-Devices gültig. Sie stehen im
  7058. Drop-Down-Menü des jeweiligen Devices zur Auswahl zur Verfügung. <br><br>
  7059. <ul>
  7060. <li><b> get &lt;name&gt; caminfoall </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM/SVS)</li>
  7061. <b> get &lt;name&gt; caminfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM) <br><br>
  7062. Es werden SVS-Parameter und abhängig von der Art der Kamera (z.B. Fix- oder PTZ-Kamera) die verfügbaren Kamera-Eigenschaften
  7063. ermittelt und als Readings zur Verfügung gestellt. <br>
  7064. So wird zum Beispiel das Reading "Availability" auf "disconnected" gesetzt falls die Kamera von der Surveillance Station
  7065. getrennt ist. <br>
  7066. "getcaminfo" ruft eine Teilmenge von "getcaminfoall" ab.
  7067. </ul>
  7068. <br><br>
  7069. <ul>
  7070. <li><b> get &lt;name&gt; eventlist </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7071. Es wird das <a href="#SSCamreadings">Reading</a> "CamEventNum" und "CamLastRec"
  7072. aktualisiert, welches die Gesamtanzahl der registrierten Kameraevents und den Pfad / Namen der letzten Aufnahme enthält.
  7073. Dieser Befehl wird implizit mit "get &lt;name&gt; caminfoall" ausgeführt. <br>
  7074. Mit dem <a href="#SSCamattr">Attribut</a> "videofolderMap" kann der Inhalt des Readings "VideoFolder" überschrieben werden.
  7075. Dies kann von Vortel sein wenn das Surveillance-Verzeichnis der SVS an dem lokalen PC unter anderem Pfadnamen gemountet ist
  7076. und darüber der Zugriff auf die Aufnahmen erfolgen soll (z.B. Verwendung bei Email-Versand). <br><br>
  7077. Ein DOIF-Beispiel für den Email-Versand von Snapshot und Aufnahmelink per non-blocking sendmail:
  7078. <pre>
  7079. define CamHE1.snap.email DOIF ([CamHE1:"LastSnapFilename"])
  7080. ({DebianMailnbl ('Recipient@Domain','Bewegungsalarm CamHE1','Eine Bewegung wurde an der Haustür registriert. Aufnahmelink: \
  7081. \[CamHE1:VideoFolder]\[CamHE1:CamLastRec]','/media/sf_surveillance/@Snapshot/[CamHE1:LastSnapFilename]')})
  7082. </pre>
  7083. </ul>
  7084. <ul>
  7085. <li><b> get &lt;name&gt; homeModeState </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für SVS)</li> <br>
  7086. HomeMode-Status der Surveillance Station wird abgerufen.
  7087. </ul>
  7088. <br><br>
  7089. <ul>
  7090. <li><b> get &lt;name&gt; listLog [severity:&lt;Loglevel&gt;] [limit:&lt;Zeilenzahl&gt;] [match:&lt;Suchstring&gt;] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für SVS)</li> <br>
  7091. Ruft das Surveillance Station Log vom Synology Server ab. Ohne Angabe der optionalen Zusätze wird das gesamte Log abgerufen. <br>
  7092. Es können alle oder eine Auswahl der folgenden Optionen angegeben werden: <br><br>
  7093. <ul>
  7094. <li> &lt;Loglevel&gt; - Information, Warning oder Error. Nur Sätze mit dem Schweregrad werden abgerufen (default: alle) </li>
  7095. <li> &lt;Zeilenzahl&gt; - die angegebene Anzahl der Logzeilen (neueste) wird abgerufen (default: alle) </li>
  7096. <li> &lt;Suchstring&gt; - nur Logeinträge mit dem angegeben String werden abgerufen (Achtung: kein Regex, der Suchstring wird im Call an die SVS mitgegeben) </li>
  7097. </ul>
  7098. <br>
  7099. <b>Beispiele</b> <br>
  7100. <ul>
  7101. <code>get &lt;name&gt; listLog severity:Error limit:5 </code> <br>
  7102. Zeigt die letzten 5 Logeinträge mit dem Schweregrad "Error" <br>
  7103. <code>get &lt;name&gt; listLog severity:Information match:Carport </code> <br>
  7104. Zeigt alle Logeinträge mit dem Schweregrad "Information" die den String "Carport" enthalten <br>
  7105. <code>get &lt;name&gt; listLog severity:Warning </code> <br>
  7106. Zeigt alle Logeinträge mit dem Schweregrad "Warning" <br><br>
  7107. </ul>
  7108. Wurde mit dem <a href="#SSCamattr">Attribut</a> "pollcaminfoall" das Polling der SVS aktiviert, wird das <a href="#SSCamreadings">Reading</a>
  7109. "LastLogEntry" erstellt. <br>
  7110. Im Protokoll-Setup der SVS kann man einstellen was protokolliert werden soll. Für weitere Informationen
  7111. siehe <a href="https://www.synology.com/de-de/knowledgebase/Surveillance/help/SurveillanceStation/log_advanced">Synology Online-Hlfe</a>.
  7112. </ul>
  7113. <br><br>
  7114. <ul>
  7115. <li><b> get &lt;name&gt; listPresets </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für PTZ-CAM)</li> <br>
  7116. Die für die Kamera gespeicherten Presets werden in einem Popup ausgegeben.
  7117. </ul>
  7118. <br><br>
  7119. <ul>
  7120. <li><b> get &lt;name&gt; scanVirgin </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM/SVS)</li> <br>
  7121. Wie mit get caminfoall werden alle Informationen der SVS und Kamera abgerufen. Allerdings wird in jedem Fall eine
  7122. neue Session ID generiert (neues Login), die Kamera-ID neu ermittelt und es werden alle notwendigen API-Parameter neu
  7123. eingelesen.
  7124. </ul>
  7125. <br><br>
  7126. <ul>
  7127. <li><b> get &lt;name&gt; snapGallery [1-10] </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7128. Es wird ein Popup mit den letzten [x] Schnapschüssen erzeugt. Ist das <a href="#SSCamattr">Attribut</a> "snapGalleryBoost" gesetzt,
  7129. werden die letzten Schnappschüsse (default 3) über Polling abgefragt und im Speicher gehalten. Das Verfahren hilft die Ausgabe zu beschleunigen,
  7130. kann aber möglicherweise nicht den letzten Schnappschuß anzeigen, falls dieser NICHT über das Modul ausgelöst wurde. <br>
  7131. Diese Funktion kann ebenfalls, z.B. mit "at" oder "notify", getriggert werden. Dabei wird die Schnappschußgalerie auf allen
  7132. verbundenen FHEMWEB-Instanzen als Popup angezeigt. <br><br>
  7133. Zur weiteren Steuerung dieser Funktion stehen die <a href="#SSCamattr">Attribute</a>: <br><br>
  7134. <ul>
  7135. <li>snapGalleryBoost </li>
  7136. <li>snapGalleryColumns </li>
  7137. <li>snapGalleryHtmlAttr </li>
  7138. <li>snapGalleryNumber </li>
  7139. <li>snapGallerySize </li>
  7140. </ul> <br>
  7141. zur Verfügung.
  7142. </ul> <br>
  7143. <ul>
  7144. <b>Hinweis:</b><br>
  7145. Abhängig von der Anzahl und Auflösung (Qualität) der Schnappschuß-Images werden entsprechend ausreichende CPU und/oder
  7146. RAM-Ressourcen benötigt.
  7147. </ul>
  7148. <br><br>
  7149. <ul>
  7150. <li><b> get &lt;name&gt; snapfileinfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7151. Es wird der Filename des letzten Schnapschusses ermittelt. Der Befehl wird implizit mit <b>"get &lt;name&gt; snap"</b>
  7152. ausgeführt.
  7153. </ul>
  7154. <br><br>
  7155. <ul>
  7156. <li><b> get &lt;name&gt; snapinfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7157. Es werden Schnappschussinformationen gelesen. Hilfreich wenn Schnappschüsse nicht durch SSCam, sondern durch die Bewegungserkennung der Kamera
  7158. oder Surveillance Station erzeugt werden.
  7159. </ul>
  7160. <br><br>
  7161. <ul>
  7162. <li><b> get &lt;name&gt; stmUrlPath </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM)</li> <br>
  7163. Mit diesem Kommando wird der aktuelle Streamkey der Kamera abgerufen und das Reading mit dem Key-Wert gefüllt.
  7164. Dieser Streamkey kann verwendet werden um eigene Aufrufe eines Livestreams aufzubauen (siehe Beispiel).
  7165. Wenn das <a href="#SSCamattr">Attribut</a> "showStmInfoFull" gesetzt ist, werden zusaätzliche Stream-Informationen wie "StmKeyUnicst", "StmKeymjpegHttp" ausgegeben.
  7166. Diese Readings enthalten die gültigen Stream-Pfade zu einem Livestream und können z.B. versendet und von einer entsprechenden Anwendung ohne session Id geöffnet werden.
  7167. Wenn das Attribut "livestreamprefix" (Format: "http(s)://&lt;hostname&gt;&lt;port&gt;) gesetzt ist, wird der Servername und Port überschrieben soweit es sinnvoll ist.
  7168. Wird Polling der Kameraeigenschaften genutzt, wird die stmUrlPath-Funktion automatisch mit ausgeführt.
  7169. <br><br>
  7170. Beispiel für den Aufbau eines Http-Calls zu einem Livestream mit StmKey:
  7171. <pre>
  7172. http(s)://&lt;hostname&gt;&lt;port&gt;/webapi/entry.cgi?api=SYNO.SurveillanceStation.VideoStreaming&version=1&method=Stream&format=mjpeg&cameraId=5&StmKey="31fd87279976d89bb98409728cced890"
  7173. </pre>
  7174. cameraId (Internal CAMID), StmKey müssen durch gültige Werte ersetzt werden. <br><br>
  7175. <b>Hinweis:</b> <br>
  7176. Falls der Stream-Aufruf versendet und von extern genutzt wird sowie hostname / port durch gültige Werte ersetzt und die
  7177. Routerports entsprechend geöffnet werden, ist darauf zu achten, dass diese sensiblen Daten nicht durch unauthorisierte Personen
  7178. für den Zugriff genutzt werden können !
  7179. </ul>
  7180. <br><br>
  7181. <ul>
  7182. <li><b> get &lt;name&gt; storedCredentials </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM/SVS)</li> <br>
  7183. Die gespeicherten Anmeldeinformationen (Credentials) werden in einem Popup als Klartext angezeigt.
  7184. </ul>
  7185. <br><br>
  7186. <ul>
  7187. <li><b> get &lt;name&gt; svsinfo </b> &nbsp;&nbsp;&nbsp;&nbsp;(gilt für CAM/SVS)</li> <br>
  7188. Ermittelt allgemeine Informationen zur installierten SVS-Version und andere Eigenschaften. <br>
  7189. </ul>
  7190. <br><br>
  7191. </ul>
  7192. <br><br>
  7193. <b>Polling der Kamera/SVS-Eigenschaften:</b><br><br>
  7194. Die Abfrage der Kameraeigenschaften erfolgt automatisch, wenn das Attribut "pollcaminfoall" (siehe Attribute) mit einem Wert &gt; 10 gesetzt wird. <br>
  7195. Per Default ist das Attribut "pollcaminfoall" nicht gesetzt und das automatische Polling nicht aktiv. <br>
  7196. Der Wert dieses Attributes legt das Intervall der Abfrage in Sekunden fest. Ist das Attribut nicht gesetzt oder &lt; 10 wird kein automatisches Polling <br>
  7197. gestartet bzw. gestoppt wenn vorher der Wert &gt; 10 gesetzt war. <br><br>
  7198. Das Attribut "pollcaminfoall" wird durch einen Watchdog-Timer überwacht. Änderungen des Attributwertes werden alle 90 Sekunden ausgewertet und entsprechend umgesetzt. <br>
  7199. Eine Änderung des Pollingstatus / Pollingintervalls wird im FHEM-Logfile protokolliert. Diese Protokollierung kann durch Setzen des Attributes "pollnologging=1" abgeschaltet werden.<br>
  7200. Dadurch kann ein unnötiges Anwachsen des Logs vermieden werden. Ab verbose=4 wird allerdings trotz gesetzten "pollnologging"-Attribut ein Log des Pollings <br>
  7201. zu Analysezwecken aktiviert. <br><br>
  7202. Wird FHEM neu gestartet, wird bei aktivierten Polling der ersten Datenabruf innerhalb 60s nach dem Start ausgeführt. <br><br>
  7203. Der Status des automatischen Pollings wird durch das Reading "PollState" signalisiert: <br><br>
  7204. <ul>
  7205. <li><b> PollState = Active </b> - automatisches Polling wird mit Intervall entsprechend "pollcaminfoall" ausgeführt </li>
  7206. <li><b> PollState = Inactive </b> - automatisches Polling wird nicht ausgeführt </li>
  7207. </ul>
  7208. <br>
  7209. Die Bedeutung der Readingwerte ist unter <a href="#SSCamreadings">Readings</a> beschrieben. <br><br>
  7210. <b>Hinweise:</b> <br><br>
  7211. Wird Polling eingesetzt, sollte das Intervall nur so kurz wie benötigt eingestellt werden da die ermittelten Werte überwiegend statisch sind. <br>
  7212. Das eingestellte Intervall sollte nicht kleiner sein als die Summe aller HTTP-Verarbeitungszeiten.
  7213. Pro Pollingaufruf und Kamera werden ca. 10 - 20 Http-Calls gegen die Surveillance Station abgesetzt.<br><br>
  7214. Bei einem eingestellten HTTP-Timeout (siehe <a href="#SSCamattr">Attribut</a>) "httptimeout") von 4 Sekunden kann die theoretische Verarbeitungszeit nicht höher als 80 Sekunden betragen. <br>
  7215. In dem Beispiel sollte man das Pollingintervall mit einem Sicherheitszuschlag auf nicht weniger 160 Sekunden setzen. <br>
  7216. Ein praktikabler Richtwert könnte zwischen 600 - 1800 (s) liegen. <br>
  7217. Sind mehrere Kameras in SSCam definiert, sollte "pollcaminfoall" nicht bei allen Kameras auf exakt den gleichen Wert gesetzt werden um Verarbeitungsengpässe <br>
  7218. und dadurch versursachte potentielle Fehlerquellen bei der Abfrage der Synology Surveillance Station zu vermeiden. <br>
  7219. Ein geringfügiger Unterschied zwischen den Pollingintervallen der definierten Kameras von z.B. 1s kann bereits als ausreichend angesehen werden. <br><br>
  7220. <a name="SSCaminternals"></a>
  7221. <b>Internals</b> <br><br>
  7222. <ul>
  7223. Die Bedeutung der verwendeten Internals stellt die nachfolgende Liste dar: <br><br>
  7224. <ul>
  7225. <li><b>CAMID</b> - die ID der Kamera in der SVS, der Wert wird automatisch anhand des SVS-Kameranamens ermittelt. </li>
  7226. <li><b>CAMNAME</b> - der Name der Kamera in der SVS </li>
  7227. <li><b>COMPATIBILITY</b> - Information bis zu welcher SVS-Version das Modul kompatibel bzw. zur Zeit getestet ist (siehe Reading "compstate")</li>
  7228. <li><b>CREDENTIALS</b> - der Wert ist "Set" wenn die Credentials gesetzt wurden </li>
  7229. <li><b>MODEL</b> - Unterscheidung von Kamera-Device (Hersteller - Kameratyp) und Surveillance Station Device (SVS) </li>
  7230. <li><b>NAME</b> - der Kameraname in FHEM </li>
  7231. <li><b>OPMODE</b> - die zuletzt ausgeführte Operation des Moduls </li>
  7232. <li><b>SERVERADDR</b> - IP-Adresse des SVS Hostes </li>
  7233. <li><b>SERVERPORT</b> - der SVS-Port </li>
  7234. <br><br>
  7235. </ul>
  7236. </ul>
  7237. <a name="SSCamattr"></a>
  7238. <b>Attribute</b>
  7239. <br><br>
  7240. <ul>
  7241. <ul>
  7242. <li><b>debugactivetoken</b><br>
  7243. wenn gesetzt wird der Status des Active-Tokens gelogged - nur für Debugging, nicht im
  7244. normalen Betrieb benutzen ! </li><br>
  7245. <li><b>disable</b><br>
  7246. deaktiviert das Gerätemodul bzw. die Gerätedefinition </li><br>
  7247. <li><b>genericStrmHtmlTag</b><br>
  7248. Das Attribut enthält HTML-Tags zur Video-Spezifikation in einem Streaming-Device von Typ "generic".
  7249. (siehe "set &lt;name&gt; createStreamDev generic") <br><br>
  7250. <ul>
  7251. <b>Beispiel:</b>
  7252. <pre>
  7253. attr &lt;name&gt; genericStrmHtmlTag &lt;video $HTMLATTR controls autoplay&gt;
  7254. &lt;source src='http://192.168.2.10:32000/$NAME.m3u8' type='application/x-mpegURL'&gt;
  7255. &lt;/video&gt;
  7256. </pre>
  7257. Die Variablen $HTMLATTR, $NAME sind Platzhalter und übernehmen ein gesetztes Attribut "htmlattr" bzw. den SSCam-Devicenamen.
  7258. </ul>
  7259. <br><br>
  7260. </li>
  7261. <li><b>httptimeout</b><br>
  7262. Timeout-Wert für HTTP-Aufrufe zur Synology Surveillance Station, Default: 4 Sekunden (wenn
  7263. httptimeout = "0" oder nicht gesetzt) </li><br>
  7264. <li><b>htmlattr</b><br>
  7265. ergänzende Angaben zur Inline-Bilddarstellung um das Verhalten wie Bildgröße zu beeinflussen. <br><br>
  7266. <ul>
  7267. <b>Beispiel:</b><br>
  7268. attr &lt;name&gt; htmlattr width="500" height="325" top="200" left="300"
  7269. </ul>
  7270. <br>
  7271. </li>
  7272. <li><b>livestreamprefix</b><br>
  7273. überschreibt die Angaben zu Protokoll, Servernamen und Port zur Weiterverwendung der
  7274. Livestreamadresse als z.B. externer Link. Anzugeben in der Form
  7275. "http(s)://&lt;servername&gt;:&lt;port&gt;" </li><br>
  7276. <li><b>loginRetries</b><br>
  7277. setzt die Anzahl der Login-Wiederholungen im Fehlerfall (default = 1) </li><br>
  7278. <li><b>noQuotesForSID</b><br>
  7279. dieses Attribut kann in bestimmten Fällen die Fehlermeldung "402 - permission denied"
  7280. vermeiden und ein login ermöglichen. </li><br>
  7281. <li><b>pollcaminfoall</b><br>
  7282. Intervall der automatischen Eigenschaftsabfrage (Polling) einer Kamera (kleiner/gleich 10: kein
  7283. Polling, größer 10: Polling mit Intervall) </li><br>
  7284. <li><b>pollnologging</b><br>
  7285. "0" bzw. nicht gesetzt = Logging Gerätepolling aktiv (default), "1" = Logging
  7286. Gerätepolling inaktiv </li><br>
  7287. <li><b>ptzPanel_Home</b><br>
  7288. Im PTZ-Steuerungspaneel wird dem Home-Icon (im Attribut "ptzPanel_row02") automatisch der Wert des Readings
  7289. "PresetHome" zugewiesen.
  7290. Mit "ptzPanel_Home" kann diese Zuweisung mit einem Preset aus der verfügbaren Preset-Liste geändert werden. </li><br>
  7291. <li><b>ptzPanel_iconPath</b><br>
  7292. Pfad für Icons im PTZ-Steuerungspaneel, default ist "www/images/sscam".
  7293. Der Attribut-Wert wird für alle Icon-Dateien außer *.svg verwendet. </li><br>
  7294. <li><b>ptzPanel_iconPrefix</b><br>
  7295. Prefix für Icon-Dateien im PTZ-Steuerungspaneel, default ist "black_btn_".
  7296. Der Attribut-Wert wird für alle Icon-Dateien außer *.svg verwendet. <br>
  7297. Beginnen die verwendeten Icon-Dateien z.B. mit "black_btn_" ("black_btn_CAMDOWN.png"), braucht das Icon in den
  7298. Attributen "ptzPanel_row[00-09]" nur noch mit dem darauf folgenden Teilstring, z.B. "CAMDOWN.png" benannt zu werden.
  7299. </li><br>
  7300. <li><b>ptzPanel_row[00-09] &lt;command&gt;:&lt;icon&gt;,&lt;command&gt;:&lt;icon&gt;,... </b><br>
  7301. Für PTZ-Kameras werden automatisch die Attribute "ptzPanel_row00" bis "ptzPanel_row04" zur Verwendung im
  7302. PTZ-Steuerungspaneel angelegt. <br>
  7303. Die Attribute enthalten eine Komma-separarierte Liste von Befehl:Icon-Kombinationen (Tasten) je Paneelzeile.
  7304. Eine Paneelzeile kann beliebig viele Tasten enthalten. Die Attribute "ptzPanel_row00" bis "ptzPanel_row04" können nicht
  7305. gelöscht werden da sie in diesem Fall automatisch wieder angelegt werden. Der User kann die Attribute ändern und ergänzen.
  7306. Diese Änderungen bleiben erhalten. <br>
  7307. Bei Bedarf kann die Belegung der Home-Taste in "ptzPanel_row02" geändert werden mit dem Attribut "ptzPanel_Home". <br>
  7308. Die Icons werden im Pfad "ptzPanel_iconPath" gesucht. Dem Icon-Namen wird "ptzPanel_iconPrefix" vorangestellt.
  7309. Eigene Erweiterungen des PTZ-Steuerungspaneels können über die Attribute "ptzPanel_row05" bis "ptzPanel_row09"
  7310. vorgenommen werden. Zur Erstellung eigener Icons gibt es eine Vorlage im SVN:
  7311. <a href="https://svn.fhem.de/trac/browser/trunk/fhem/contrib/sscam">contrib/sscam/black_btn_CAM_Template.pdn</a>. Diese
  7312. Vorlage kann zum Beispiel mit Paint.Net bearbeitet werden. <br><br>
  7313. <b>Hinweis</b> <br>
  7314. Für eine Leerfeld verwenden sie bitte ":CAMBLANK.png" bzw. ":CAMBLANK.png,:CAMBLANK.png,:CAMBLANK.png,..." für eine
  7315. Leerzeile.
  7316. <br><br>
  7317. <ul>
  7318. <b>Beispiel:</b><br>
  7319. attr &lt;name&gt; ptzPanel_row00 move upleft:CAMUPLEFTFAST.png,:CAMBLANK.png,move up:CAMUPFAST.png,:CAMBLANK.png,move upright:CAMUPRIGHTFAST.png <br>
  7320. # Der Befehl "move upleft" wird der Kamera beim Druck auf Tastenicon "CAMUPLEFTFAST.png" übermittelt. <br>
  7321. </ul>
  7322. <br>
  7323. </li><br>
  7324. <li><b>ptzPanel_use</b><br>
  7325. Die Anzeige des PTZ-Steuerungspaneels in der Detailanzeige bzw. innerhalb eines generierten Streamdevice wird
  7326. ein- bzw. ausgeschaltet (default ein). </li><br>
  7327. <li><b>rectime</b><br>
  7328. festgelegte Aufnahmezeit wenn eine Aufnahme gestartet wird. Mit rectime = 0 wird eine
  7329. Endlosaufnahme gestartet. Ist "rectime" nicht gesetzt, wird der Defaultwert von 15s
  7330. verwendet.</li><br>
  7331. <li><b>recextend</b><br>
  7332. "rectime" einer gestarteten Aufnahme wird neu gesetzt. Dadurch verlängert sich die
  7333. Aufnahemzeit einer laufenden Aufnahme </li><br>
  7334. <li><b>session</b><br>
  7335. Auswahl der Login-Session. Nicht gesetzt oder "DSM" -> session wird mit DSM aufgebaut
  7336. (Standard). "SurveillanceStation" -> Session-Aufbau erfolgt mit SVS </li><br>
  7337. <li><b>simu_SVSversion</b><br>
  7338. Simuliert eine andere SVS-Version. (es ist nur eine niedrigere als die installierte SVS
  7339. Version möglich !) </li><br>
  7340. <li><b>snapGalleryBoost</b><br>
  7341. Wenn gesetzt, werden die letzten Schnappschüsse (default 3) über Polling im Speicher gehalten und mit "set/get snapGallery"
  7342. aufbereitet angezeigt. Dieser Modus bietet sich an wenn viele bzw. Fullsize Images angezeigt werden sollen.
  7343. Ist das Attribut eingeschaltet, können bei "set/get snapGallery" keine Argumente mehr mitgegeben werden.
  7344. (siehe Attribut "snapGalleryNumber") </li><br>
  7345. <li><b>snapGalleryColumns</b><br>
  7346. Die Anzahl der Snaps die in einer Reihe im Popup erscheinen sollen (default 3). </li><br>
  7347. <li><b>snapGalleryHtmlAttr</b><br>
  7348. hiermit kann die Bilddarstellung beeinflusst werden. <br>
  7349. Ist das Attribut nicht gesetzt, wird das Attribut "htmlattr" verwendet. <br>
  7350. Ist auch dieses nicht gesetzt, wird eine Standardvorgabe verwendet (width="500" height="325"). <br><br>
  7351. <ul>
  7352. <b>Beispiel:</b><br>
  7353. attr &lt;name&gt; snapGalleryHtmlAttr width="325" height="225"
  7354. </ul>
  7355. <br>
  7356. </li>
  7357. <li><b>snapGalleryNumber</b><br>
  7358. Die Anzahl der abzurufenden Schnappschüsse (default 3). </li><br>
  7359. <li><b>snapGallerySize</b><br>
  7360. Mit diesem Attribut kann die Qualität der Images eingestellt werden (default "Icon"). <br>
  7361. Im Modus "Full" wird die original vorhandene Auflösung der Images abgerufen. Dies erfordert mehr Ressourcen und kann die
  7362. Anzeige verlangsamen. Mit "snapGalleryBoost=1" kann die Ausgabe beschleunigt werden, da in diesem Fall die Aufnahmen über
  7363. Polling abgerufen und nur noch zur Anzeige gebracht werden. </li><br>
  7364. <li><b>showStmInfoFull</b><br>
  7365. zusaätzliche Streaminformationen wie LiveStreamUrl, StmKeyUnicst, StmKeymjpegHttp werden
  7366. ausgegeben</li><br>
  7367. <li><b>showPassInLog</b><br>
  7368. wenn gesetzt wird das verwendete Passwort im Logfile (verbose 4) angezeigt.
  7369. (default = 0) </li><br>
  7370. <li><b>videofolderMap</b><br>
  7371. ersetzt den Inhalt des Readings "VideoFolder", Verwendung z.B. bei gemounteten
  7372. Verzeichnissen </li><br>
  7373. <li><b>verbose</b> </li><br>
  7374. <ul>
  7375. Es werden verschiedene Verbose-Level unterstützt.
  7376. Dies sind im Einzelnen:
  7377. <table>
  7378. <colgroup> <col width=5%> <col width=95%> </colgroup>
  7379. <tr><td> 0 </td><td>- Start/Stop-Ereignisse werden geloggt </td></tr>
  7380. <tr><td> 1 </td><td>- Fehlermeldungen werden geloggt </td></tr>
  7381. <tr><td> 2 </td><td>- Meldungen über wichtige Ereignisse oder Alarme </td></tr>
  7382. <tr><td> 3 </td><td>- gesendete Kommandos werden geloggt </td></tr>
  7383. <tr><td> 4 </td><td>- gesendete und empfangene Daten werden geloggt </td></tr>
  7384. <tr><td> 5 </td><td>- alle Ausgaben zur Fehleranalyse werden geloggt. <b>ACHTUNG:</b> möglicherweise werden sehr viele Daten in das Logfile geschrieben! </td></tr>
  7385. </table>
  7386. </ul>
  7387. <br>
  7388. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  7389. <br><br>
  7390. </ul>
  7391. <a name="SSCamreadings"></a>
  7392. <b>Readings</b>
  7393. <ul>
  7394. <br>
  7395. Über den Pollingmechanismus bzw. durch Abfrage mit "Get" werden Readings bereitgestellt, deren Bedeutung in der nachfolgenden Tabelle dargestellt sind. <br>
  7396. Die übermittelten Readings können in Abhängigkeit des Kameratyps variieren.<br><br>
  7397. <ul>
  7398. <table>
  7399. <colgroup> <col width=5%> <col width=95%> </colgroup>
  7400. <tr><td><li>CamAudioType</li> </td><td>- listet den eingestellten Audiocodec auf wenn verwendet </td></tr>
  7401. <tr><td><li>Availability</li> </td><td>- Verfügbarkeit der Kamera (disabled, enabled, disconnected, other) </td></tr>
  7402. <tr><td><li>CamEventNum</li> </td><td>- liefert die Gesamtanzahl der in SVS registrierten Events der Kamera </td></tr>
  7403. <tr><td><li>CamExposureControl</li> </td><td>- zeigt den aktuell eingestellten Typ der Belichtungssteuerung </td></tr>
  7404. <tr><td><li>CamExposureMode</li> </td><td>- aktueller Belichtungsmodus (Day, Night, Auto, Schedule, Unknown) </td></tr>
  7405. <tr><td><li>CamForceEnableMulticast</li> </td><td>- sagt aus ob die Kamera verpflichet ist Multicast einzuschalten. </td></tr>
  7406. <tr><td><li>CamIP</li> </td><td>- IP-Adresse der Kamera </td></tr>
  7407. <tr><td><li>CamLastRec</li> </td><td>- Pfad / Name der letzten Aufnahme </td></tr>
  7408. <tr><td><li>CamLastRecTime</li> </td><td>- Datum / Startzeit - Stopzeit der letzten Aufnahme </td></tr>
  7409. <tr><td><li>CamLiveFps</li> </td><td>- Frames pro Sekunde des Live-Streams </td></tr>
  7410. <tr><td><li>CamLiveMode</li> </td><td>- Quelle für Live-Ansicht (DS, Camera) </td></tr>
  7411. <tr><td><li>camLiveQuality</li> </td><td>- in SVS eingestellte Live-Stream Qualität </td></tr>
  7412. <tr><td><li>camLiveResolution</li> </td><td>- in SVS eingestellte Live-Stream Auflösung </td></tr>
  7413. <tr><td><li>camLiveStreamNo</li> </td><td>- verwendete Stream-Nummer für Live-Stream </td></tr>
  7414. <tr><td><li>CamModel</li> </td><td>- Kameramodell </td></tr>
  7415. <tr><td><li>CamMotDetSc</li> </td><td>- Status der Bewegungserkennung (disabled, durch Kamera, durch SVS) und deren Parameter </td></tr>
  7416. <tr><td><li>CamNTPServer</li> </td><td>- eingestellter Zeitserver </td></tr>
  7417. <tr><td><li>CamPort</li> </td><td>- IP-Port der Kamera </td></tr>
  7418. <tr><td><li>CamPreRecTime</li> </td><td>- Dauer der der Voraufzeichnung in Sekunden (Einstellung in SVS) </td></tr>
  7419. <tr><td><li>CamPtSpeed</li> </td><td>- eingestellter Wert für Schwenken/Neige-Aktionen (Einstellung in SVS) </td></tr>
  7420. <tr><td><li>CamRecShare</li> </td><td>- gemeinsamer Ordner auf der DS für Aufnahmen </td></tr>
  7421. <tr><td><li>CamRecVolume</li> </td><td>- Volume auf der DS für Aufnahmen </td></tr>
  7422. <tr><td><li>CamStreamFormat</li> </td><td>- aktuelles Format des Videostream </td></tr>
  7423. <tr><td><li>CamVideoType</li> </td><td>- listet den eingestellten Videocodec auf </td></tr>
  7424. <tr><td><li>CamVendor</li> </td><td>- Kamerahersteller Bezeichnung </td></tr>
  7425. <tr><td><li>CamVideoFlip</li> </td><td>- Ist das Video gedreht </td></tr>
  7426. <tr><td><li>CamVideoMirror</li> </td><td>- Ist das Video gespiegelt </td></tr>
  7427. <tr><td><li>CamVideoRotate</li> </td><td>- Ist das Video gedreht </td></tr>
  7428. <tr><td><li>CapAudioOut</li> </td><td>- Fähigkeit der Kamera zur Audioausgabe über Surveillance Station (false/true) </td></tr>
  7429. <tr><td><li>CapChangeSpeed</li> </td><td>- Fähigkeit der Kamera verschiedene Bewegungsgeschwindigkeiten auszuführen </td></tr>
  7430. <tr><td><li>CapPIR</li> </td><td>- besitzt die Kamera einen PIR-Sensor </td></tr>
  7431. <tr><td><li>CapPTZAbs</li> </td><td>- Fähigkeit der Kamera für absolute PTZ-Aktionen </td></tr>
  7432. <tr><td><li>CapPTZAutoFocus</li> </td><td>- Fähigkeit der Kamera für Autofokus Aktionen </td></tr>
  7433. <tr><td><li>CapPTZDirections</li> </td><td>- die verfügbaren PTZ-Richtungen der Kamera </td></tr>
  7434. <tr><td><li>CapPTZFocus</li> </td><td>- Art der Kameraunterstützung für Fokussierung </td></tr>
  7435. <tr><td><li>CapPTZHome</li> </td><td>- Unterstützung der Kamera für Home-Position </td></tr>
  7436. <tr><td><li>CapPTZIris</li> </td><td>- Unterstützung der Kamera für Iris-Aktion </td></tr>
  7437. <tr><td><li>CapPTZObjTracking</li> </td><td>- Unterstützung der Kamera für Objekt-Tracking </td></tr>
  7438. <tr><td><li>CapPTZPan</li> </td><td>- Unterstützung der Kamera für Pan-Aktion </td></tr>
  7439. <tr><td><li>CapPTZPresetNumber</li> </td><td>- die maximale Anzahl unterstützter Presets. 0 steht für keine Preset-Unterstützung </td></tr>
  7440. <tr><td><li>CapPTZTilt</li> </td><td>- Unterstützung der Kamera für Tilt-Aktion </td></tr>
  7441. <tr><td><li>CapPTZZoom</li> </td><td>- Unterstützung der Kamera für Zoom-Aktion </td></tr>
  7442. <tr><td><li>DeviceType</li> </td><td>- Kameratyp (Camera, Video_Server, PTZ, Fisheye) </td></tr>
  7443. <tr><td><li>Error</li> </td><td>- Meldungstext des letzten Fehlers </td></tr>
  7444. <tr><td><li>Errorcode</li> </td><td>- Fehlercode des letzten Fehlers </td></tr>
  7445. <tr><td><li>HomeModeState</li> </td><td>- HomeMode-Status (ab SVS-Version 8.1.0) </td></tr>
  7446. <tr><td><li>LastLogEntry</li> </td><td>- der neueste Eintrag des Surveillance Station Logs (nur SVS-Device und wenn Attribut pollcaminfoall gesetzt) </td></tr>
  7447. <tr><td><li>LastSnapFilename</li> </td><td>- der Filename des letzten Schnapschusses </td></tr>
  7448. <tr><td><li>LastSnapId</li> </td><td>- die ID des letzten Schnapschusses </td></tr>
  7449. <tr><td><li>LastSnapTime</li> </td><td>- Zeitstempel des letzten Schnapschusses </td></tr>
  7450. <tr><td><li>LastUpdateTime</li> </td><td>- Datum / Zeit der letzten Aktualisierung durch "caminfoall" </td></tr>
  7451. <tr><td><li>LiveStreamUrl </li> </td><td>- die LiveStream-Url wenn der Stream gestartet ist. (<a href="#SSCamattr">Attribut</a> "showStmInfoFull" muss gesetzt sein) </td></tr>
  7452. <tr><td><li>Patrols</li> </td><td>- in Surveillance Station voreingestellte Überwachungstouren (bei PTZ-Kameras) </td></tr>
  7453. <tr><td><li>PollState</li> </td><td>- zeigt den Status des automatischen Pollings an </td></tr>
  7454. <tr><td><li>PresetHome</li> </td><td>- Name der Home-Position (bei PTZ-Kameras) </td></tr>
  7455. <tr><td><li>Presets</li> </td><td>- in Surveillance Station voreingestellte Positionen (bei PTZ-Kameras) </td></tr>
  7456. <tr><td><li>Record</li> </td><td>- Aufnahme läuft = Start, keine Aufnahme = Stop </td></tr>
  7457. <tr><td><li>StmKey</li> </td><td>- aktueller StreamKey. Kann zum öffnen eines Livestreams ohne Session Id genutzt werden. </td></tr>
  7458. <tr><td><li>StmKeyUnicst</li> </td><td>- Uni-cast Stream Pfad der Kamera. (<a href="#SSCamattr">Attribut</a> "showStmInfoFull" muss gesetzt sein) </td></tr>
  7459. <tr><td><li>StmKeymjpegHttp</li> </td><td>- Mjpeg Stream Pfad (über http) der Kamera. (<a href="#SSCamattr">Attribut</a> "showStmInfoFull" muss gesetzt sein) </td></tr>
  7460. <tr><td><li>SVScustomPortHttp</li> </td><td>- benutzerdefinierter Port der Surveillance Station (HTTP) im DSM-Anwendungsportal (get mit "svsinfo") </td></tr>
  7461. <tr><td><li>SVScustomPortHttps</li> </td><td>- benutzerdefinierter Port der Surveillance Station (HTTPS) im DSM-Anwendungsportal (get mit "svsinfo") </td></tr>
  7462. <tr><td><li>SVSlicenseNumber</li> </td><td>- die Anzahl der installierten Kameralizenzen (get mit "svsinfo") </td></tr>
  7463. <tr><td><li>SVSuserPriv</li> </td><td>- die effektiven Rechte des verwendeten Users nach dem Login (get mit "svsinfo") </td></tr>
  7464. <tr><td><li>SVSversion</li> </td><td>- die Paketversion der installierten Surveillance Station (get mit "svsinfo") </td></tr>
  7465. <tr><td><li>UsedSpaceMB</li> </td><td>- durch Aufnahmen der Kamera belegter Plattenplatz auf dem Volume </td></tr>
  7466. <tr><td><li>VideoFolder</li> </td><td>- Pfad zu den aufgenommenen Videos </td></tr>
  7467. <tr><td><li>compstate</li> </td><td>- Kompatibilitätsstatus (Vergleich von eingesetzter/simulierter SVS-Version zum Internal COMPATIBILITY) </td></tr>
  7468. </table>
  7469. </ul>
  7470. <br><br>
  7471. </ul>
  7472. </ul>
  7473. <br><br>
  7474. </ul>
  7475. =end html_DE
  7476. =cut