scrypted-detection-trainer 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.nodejs.js +1 -1
- package/dist/main.nodejs.js.map +1 -1
- package/dist/plugin.zip +0 -0
- package/out/main.nodejs.js +138 -8
- package/out/main.nodejs.js.map +1 -1
- package/out/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/main.ts +139 -9
package/dist/main.nodejs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.nodejs.js","mappings":"qCACA,IAAIA,EAAmBC,MAAQA,KAAKD,kBAAqBE,OAAOC,OAAS,SAAUC,EAAGC,EAAGC,EAAGC,QAC7EC,IAAPD,IAAkBA,EAAKD,GAC3B,IAAIG,EAAOP,OAAOQ,yBAAyBL,EAAGC,GACzCG,KAAS,QAASA,GAAQJ,EAAEM,WAAaF,EAAKG,UAAYH,EAAKI,gBAClEJ,EAAO,CAAEK,YAAY,EAAMC,IAAK,WAAa,OAAOV,EAAEC,EAAI,IAE5DJ,OAAOc,eAAeZ,EAAGG,EAAIE,EAChC,EAAI,SAAUL,EAAGC,EAAGC,EAAGC,QACTC,IAAPD,IAAkBA,EAAKD,GAC3BF,EAAEG,GAAMF,EAAEC,EACb,GACGW,EAAgBhB,MAAQA,KAAKgB,cAAiB,SAASZ,EAAGa,GAC1D,IAAK,IAAIC,KAAKd,EAAa,YAANc,GAAoBjB,OAAOkB,UAAUC,eAAeC,KAAKJ,EAASC,IAAInB,EAAgBkB,EAASb,EAAGc,EAC3H,EACAjB,OAAOc,eAAeE,EAAS,aAAc,CAAEK,OAAO,IACtDL,EAAQM,IAAMN,EAAQO,gBAAkBP,EAAQQ,wBAA0B,EAC1ET,EAAa,EAAQ,KAAuBC,GAC5C,MAAMS,EAAU,EAAQ,KACP,EAAQ,KAIzB,MAAMD,UAA2BC,EAAQC,WACrC,WAAAC,CAAYC,GACRC,QACA9B,KAAK6B,SAAWA,CACpB,CACA,WAAIE,GAIA,OAHK/B,KAAKgC,WACNhC,KAAKgC,SAAWf,EAAQM,IAAIU,cAAcC,iBAAiBlC,KAAK6B,WAE7D7B,KAAKgC,QAChB,CACA,OAAIG,GAIA,OAHKnC,KAAKoC,OACNpC,KAAKoC,KAAOnB,EAAQM,IAAIU,cAAcI,gBAAgBrC,KAAK6B,WAExD7B,KAAKoC,IAChB,CACA,WAAIE,GAIA,OAHKtC,KAAKuC,WACNvC,KAAKuC,SAAWtB,EAAQM,IAAIU,cAAcO,iBAAiBxC,KAAK6B,WAE7D7B,KAAKuC,QAChB,CACA,uBAAME,CAAkBC,EAAMC,GAC1B,OAAO1B,EAAQM,IAAIqB,aAAaH,kBAAkBC,EAAMC,EAAU,CAC9DE,SAAU7C,KAAK8C,IAEvB,CACA,qBAAAC,CAAsBC,GAClB,MAAoC,iBAAzBA,EAAYH,SACZ7C,KAAKsC,QACTrB,EAAQM,IAAIU,cAAcgB,gBAAgBD,EAAYH,SAAU7C,KAAK6B,SAChF,CACA,oBAAAqB,GACSlD,KAAKmD,eACFnD,KAAK6B,SACL7B,KAAKmD,aAAelC,EAAQM,IAAIU,cAAcmB,eAAepD,KAAK6B,UAGlE7B,KAAKmD,aAAelC,EAAQM,IAAIU,cAAcmB,iBAG1D,CAIA,aAAAC,CAAcC,EAAgBC,GAC1B,OAAOtC,EAAQM,IAAIU,cAAcoB,cAAcrD,KAAK6B,SAAUyB,EAAgBC,EAClF,EAEJtC,EAAQQ,mBAAqBA,EAI7B,MAAMD,UAAwBE,EAAQC,WAClC,WAAAC,CAAY4B,GACR1B,QACA9B,KAAKyD,WAAa,IAAIC,IACtB1D,KAAK2D,YAAcH,EAAQG,YAC3B3D,KAAK4D,sBAAwBJ,EAAQI,sBACrC5D,KAAK6D,mBAAqBL,EAAQK,mBAClC7D,KAAKmD,aAAeK,EAAQM,iBAC5B9D,KAAK6B,SAAWZ,EAAQM,IAAIwC,cAAcC,cAAchE,KAAK8C,IAAIjB,SACjE7B,KAAKiE,sBAAwBT,EAAQS,sBAIjCjE,KAAKmD,aAAae,iCAAmE,iBAAzBlE,KAAKmD,aAAaL,KAC9E9C,KAAKmD,aAAelC,EAAQM,IAAIU,cAAckC,kBAAkBnE,KAAKmD,aAAaL,GAAI9C,KAAKmD,aAAaiB,UAEhH,CACA,WAAIrC,GACA,IAAK/B,KAAKgC,SAAU,CAChB,MAAM6B,EAAqB7D,KAAK6D,mBAC1BQ,EAAkBrE,KAAK8C,IAAMe,EAAqB,IAAMA,EAAqB,IACnF7D,KAAKgC,SAAWf,EAAQM,IAAIU,cAAcqC,gBAAgBD,EAAiBrE,KAAKiE,sBACpF,CACA,OAAOjE,KAAKgC,QAChB,CACA,WAAIM,GAOA,OANKtC,KAAKuC,WACFtB,EAAQM,IAAIU,cAAcgB,gBAC1BjD,KAAKuC,SAAWtB,EAAQM,IAAIU,cAAcgB,gBAAgBjD,KAAK8C,GAAI9C,KAAKiE,uBAExEjE,KAAKuC,SAAWtB,EAAQM,IAAIU,cAAcO,iBAAiBxC,KAAKiE,wBAEjEjE,KAAKuC,QAChB,CACA,uBAAME,CAAkBC,EAAMC,GAC1B,OAAO1B,EAAQM,IAAIqB,aAAaH,kBAAkBC,EAAMC,EAAU,CAC9DE,SAAU7C,KAAK8C,IAEvB,CACA,qBAAAC,CAAsBC,GAClB,MAAoC,iBAAzBA,EAAYH,SACZ7C,KAAKsC,QACTrB,EAAQM,IAAIU,cAAcgB,gBAAgBD,EAAYH,SAAU7C,KAAKiE,sBAChF,CAIA,aAAAZ,CAAcC,EAAgBC,GAC1B,OAAOtC,EAAQM,IAAIU,cAAcsC,aAAavE,KAAK8C,GAAI9C,KAAMsD,EAAgBC,EACjF,CACA,oBAAAL,GACA,CACA,cAAAsB,CAAeC,GACXzE,KAAKyD,WAAWiB,IAAID,EACxB,CACA,OAAAE,GACI,IAAK,MAAMC,KAAK5E,KAAKyD,WACjBmB,EAAEC,gBAEV,EAEJ5D,EAAQO,gBAAkBA,EAC1B,WACI,SAASsD,EAAgBC,GACrB,OAAO,WAGH,OAFA/E,KAAKkD,uBAEElD,KAAKmD,eAAe4B,EAC/B,CACJ,CACA,SAASC,EAAgBD,GACrB,OAAO,SAAUzD,GACbtB,KAAKkD,uBAEAlD,KAAKmD,aAKNnD,KAAKmD,aAAa4B,GAASzD,EAJ3BgB,QAAQ2C,KAAK,kKAMrB,CACJ,CACA,IAAK,MAAMC,KAASjF,OAAOkF,OAAOzD,EAAQ0D,2BAClCF,IAAUxD,EAAQ0D,0BAA0BvD,WAEhD5B,OAAOc,eAAeU,EAAmBN,UAAW+D,EAAO,CACvDG,IAAKL,EAAgBE,GACrBpE,IAAKgE,EAAgBI,KAEzBjF,OAAOc,eAAeS,EAAgBL,UAAW+D,EAAO,CACpDG,IAAKL,EAAgBE,GACrBpE,IAAKgE,EAAgBI,KAGhC,CAjCD,GAkCAjE,EAAQM,IAAM,CAAC,EACf,IACI,IAAI+D,GAAS,EACb,IAIqBC,QAAQC,IAAIC,wBAA0BF,QAAQC,IAAIE,oBAAnE,MACMC,EAAYJ,QAAQC,IAAII,yBAA2BL,QAAQC,IAAIE,oBAShE,GAAIC,EAEL,GAAuC,oBAA5B,QAAyC,CAEhD,MAAME,EAAY,QAAwBN,QAAQC,IAAIE,qBACtDzF,OAAO6F,OAAO7E,EAAQM,IAAKsE,EAAUE,qBACrCT,GAAS,CACb,KACK,CACD,MAAMO,EAAY,OAAQF,GAC1B1F,OAAO6F,OAAO7E,EAAQM,IAAKsE,EAAUE,qBACrCT,GAAS,CACb,CAER,CACA,MAAOU,GAEH,MADA1D,QAAQ2C,KAAK,4BAA6Be,GACpCA,CACV,CACA,IAAKV,EAAQ,CACT,IAAIW,EACJ,IACIA,EAAaC,gBACjB,CACA,MAAOF,GACP,CACA/F,OAAO6F,OAAO7E,EAAQM,IAAK,CACvBY,IAAKF,cAAcI,qBAAgB9B,GACnC0B,cACAkE,gBACAvD,aACAmB,cACAqC,iBACGH,GAEX,CACA,IACIhF,EAAQM,IAAIwC,cAAcsC,kCAAkC3E,EAAQ4E,cAAe5E,EAAQ6E,+BAA+BC,MAAM,OACpI,CACA,MAAOR,GACP,CACJ,CACA,MAAOA,GACH1D,QAAQmE,MAAM,mFAAoFT,EACtG,CACA/E,EAAA,QAAkBA,EAAQM,G,SC3O1B,SAASmF,EAAoBC,GAC5B,IAAIX,EAAI,IAAIY,MAAM,uBAAyBD,EAAM,KAEjD,MADAX,EAAEa,KAAO,mBACHb,CACP,CACAU,EAAoBI,KAAO,IAAM,GACjCJ,EAAoBK,QAAUL,EAC9BA,EAAoB5D,GAAK,IACzBkE,EAAO/F,QAAUyF,C,wBCPjBzG,OAAOc,eAAeE,EAAS,aAAc,CAAEK,OAAO,IACtDL,EAAQgG,kBAAoBhG,EAAQiG,kBAAoBjG,EAAQkG,iBAAmBlG,EAAQmG,0BAA4BnG,EAAQoG,mBAAqBpG,EAAQqG,WAAarG,EAAQsG,gBAAkBtG,EAAQuG,kBAAoBvG,EAAQwG,YAAcxG,EAAQyG,UAAYzG,EAAQ0G,oBAAsB1G,EAAQ2G,eAAiB3G,EAAQ4G,gBAAkB5G,EAAQ6G,QAAU7G,EAAQ8G,aAAe9G,EAAQ+G,mBAAqB/G,EAAQsF,6BAA+BtF,EAAQgH,wBAA0BhH,EAAQmE,0BAA4BnE,EAAQU,WAAaV,EAAQqF,mBAAqB,EAC/jBrF,EAAQqF,cAAgB,UAIxB,IAAIlB,EAqEA6C,EA43BAD,EAwDAD,EAOAD,EAKAD,EAKAD,EAaAD,EAQAD,EAMAD,EAMAD,EAOAD,EAKAD,EASAD,EAOAD,EAOAD,EAOAD,EAoGAD,EA1rCJhG,EAAQU,WAFR,QAIA,SAAWyD,GACPA,EAA8B,GAAI,KAClCA,EAAgC,KAAI,OACpCA,EAAsC,WAAI,aAC1CA,EAAkC,OAAI,SACtCA,EAAgC,KAAI,OACpCA,EAAoC,SAAI,WACxCA,EAAoC,SAAI,WACxCA,EAA8C,mBAAI,qBAClDA,EAAwC,aAAI,eAC5CA,EAAwC,aAAI,eAC5CA,EAAwC,aAAI,eAC5CA,EAAsC,WAAI,aAC1CA,EAAgC,KAAI,OACpCA,EAAgC,KAAI,OACpCA,EAAoD,yBAAI,2BACxDA,EAA8B,GAAI,KAClCA,EAAsC,WAAI,aAC1CA,EAA4C,iBAAI,mBAChDA,EAA+B,IAAI,MACnCA,EAA+B,IAAI,MACnCA,EAAmC,QAAI,UACvCA,EAAmC,QAAI,UACvCA,EAAmC,QAAI,UACvCA,EAAkC,OAAI,SACtCA,EAAkC,OAAI,SACtCA,EAA8C,mBAAI,qBAClDA,EAAuC,YAAI,cAC3CA,EAA2C,gBAAI,kBAC/CA,EAAoC,SAAI,WACxCA,EAAwC,aAAI,eAC5CA,EAA2C,gBAAI,kBAC/CA,EAA2C,gBAAI,kBAC/CA,EAAqC,UAAI,YACzCA,EAAqC,UAAI,YACzCA,EAAwC,aAAI,eAC5CA,EAAuC,YAAI,cAC3CA,EAAkC,OAAI,SACtCA,EAAwC,aAAI,eAC5CA,EAAsC,WAAI,aAC1CA,EAAsC,WAAI,aAC1CA,EAAuC,YAAI,cAC3CA,EAAoC,SAAI,WACxCA,EAAoC,SAAI,WACxCA,EAAyC,cAAI,gBAC7CA,EAAyC,cAAI,gBAC7CA,EAA0C,eAAI,iBAC9CA,EAAwC,aAAI,eAC5CA,EAAoC,SAAI,WACxCA,EAAmC,QAAI,UACvCA,EAAuC,YAAI,cAC3CA,EAAqC,UAAI,YACzCA,EAAoC,SAAI,WACxCA,EAA+C,oBAAI,sBACnDA,EAAuC,YAAI,cAC3CA,EAAuC,YAAI,cAC3CA,EAAsC,WAAI,aAC1CA,EAAsC,WAAI,aAC1CA,EAAkC,OAAI,SACtCA,EAAsC,WAAI,aAC1CA,EAA4C,iBAAI,mBAChDA,EAAkD,uBAAI,yBACtDA,EAA2C,gBAAI,kBAC/CA,EAA2C,gBAAI,kBAC/CA,EAA+B,IAAI,MACnCA,EAA2C,gBAAI,kBAC/CA,EAAwC,aAAI,cAC/C,CAnED,CAmEGA,IAA8BnE,EAAQmE,0BAA4BA,EAA4B,CAAC,IAElG,SAAW6C,GACPA,EAAgC,OAAI,SACpCA,EAA+B,MAAI,QACnCA,EAAmC,UAAI,YACvCA,EAAiC,QAAI,UACrCA,EAAiC,QAAI,UACrCA,EAAiC,QAAI,UACrCA,EAAuC,cAAI,gBAC3CA,EAAiC,QAAI,UACrCA,EAAgC,OAAI,SACpCA,EAAuC,cAAI,gBAC3CA,EAA4C,mBAAI,qBAChDA,EAA4C,mBAAI,qBAChDA,EAA6C,oBAAI,sBACjDA,EAAgC,OAAI,SACpCA,EAAgC,OAAI,SACpCA,EAAqC,YAAI,cACzCA,EAA0C,iBAAI,mBAC9CA,EAA+B,MAAI,QACnCA,EAA8B,KAAI,OAClCA,EAA+B,MAAI,QACnCA,EAAgC,OAAI,SACpCA,EAA8B,KAAI,OAClCA,EAAwC,eAAI,iBAC5CA,EAA4C,mBAAI,qBAChDA,EAA2C,kBAAI,oBAC/CA,EAAqC,YAAI,cACzCA,EAAwC,eAAI,iBAC5CA,EAAyC,gBAAI,kBAC7CA,EAAsC,aAAI,eAC1CA,EAAqC,YAAI,cACzCA,EAAwC,eAAI,iBAC5CA,EAA+C,sBAAI,wBACnDA,EAAyC,gBAAI,kBAC7CA,EAAyC,gBAAI,kBAC7CA,EAA8C,qBAAI,uBAClDA,EAA6C,oBAAI,sBACjDA,EAA4C,mBAAI,qBAChDA,EAAuD,8BAAI,gCAC3DA,EAAmD,0BAAI,4BACvDA,EAAqD,4BAAI,8BACzDA,EAA+C,sBAAI,wBACnDA,EAA4C,mBAAI,qBAChDA,EAAoC,WAAI,aACxCA,EAA2C,kBAAI,oBAC/CA,EAAsC,aAAI,eAC1CA,EAAuC,cAAI,gBAC3CA,EAA+C,sBAAI,wBACnDA,EAA0C,iBAAI,mBAC9CA,EAA+C,sBAAI,wBACnDA,EAAuC,cAAI,gBAC3CA,EAAsC,aAAI,eAC1CA,EAA8B,KAAI,OAClCA,EAAgC,OAAI,SACpCA,EAAqC,YAAI,cACzCA,EAAsC,aAAI,eAC1CA,EAAwC,eAAI,iBAC5CA,EAAkC,SAAI,WACtCA,EAAoC,WAAI,aACxCA,EAAsC,aAAI,eAC1CA,EAAoC,WAAI,aACxCA,EAAmC,UAAI,YACvCA,EAAmC,UAAI,YACvCA,EAAuC,cAAI,gBAC3CA,EAAqC,YAAI,cACzCA,EAAyC,gBAAI,kBAC7CA,EAAsC,aAAI,eAC1CA,EAAiD,wBAAI,0BACrDA,EAAgC,OAAI,SACpCA,EAA6C,oBAAI,sBACjDA,EAAiC,QAAI,UACrCA,EAAwC,eAAI,iBAC5CA,EAA8B,KAAI,OAClCA,EAA8B,KAAI,OAClCA,EAAkC,SAAI,WACtCA,EAAsC,aAAI,eAC1CA,EAAiC,QAAI,UACrCA,EAAsC,aAAI,eAC1CA,EAAqC,YAAI,cACzCA,EAAoC,WAAI,aACxCA,EAA2C,kBAAI,oBAC/CA,EAA8C,qBAAI,uBAClDA,EAA6C,oBAAI,sBACjDA,EAA2C,kBAAI,oBAC/CA,EAAqC,YAAI,cACzCA,EAAyC,gBAAI,kBAC7CA,EAAkC,SAAI,WACtCA,EAAkC,SAAI,WACtCA,EAAsC,aAAI,eAC1CA,EAAmC,UAAI,YACvCA,EAAsC,aAAI,eAC1CA,EAAgC,OAAI,SACpCA,EAA6B,IAAI,MACjCA,EAA8B,KAAI,OAClCA,EAAqC,YAAI,cACzCA,EAAoC,WAAI,aACxCA,EAAuC,cAAI,gBAC3CA,EAAsC,aAAI,eAC1CA,EAA2C,kBAAI,oBAC/CA,EAAwC,eAAI,iBAC5CA,EAAuC,cAAI,gBAC3CA,EAAkD,yBAAI,2BACtDA,EAA2C,kBAAI,oBAC/CA,EAAqC,YAAI,cACzCA,EAAgC,OAAI,SACpCA,EAAkD,yBAAI,2BACtDA,EAAmD,0BAAI,4BACvDA,EAAsD,6BAAI,+BAC1DA,EAA6C,oBAAI,sBACjDA,EAAuC,cAAI,gBAC3CA,EAAwC,eAAI,gBAC/C,CA/GD,CA+GGA,IAA4BhH,EAAQgH,wBAA0BA,EAA0B,CAAC,IAC5FhH,EAAQsF,6BAA+B,CACnC,eAAkB,CACd,KAAQ,iBACR,QAAW,CACP,SACA,QACA,YACA,UACA,UACA,WAEJ,WAAc,CACV,KACA,OACA,aACA,SACA,OACA,WACA,WACA,qBACA,eACA,eACA,eACA,aACA,OACA,SAGR,eAAkB,CACd,KAAQ,iBACR,QAAW,CACP,iBAEJ,WAAc,IAElB,sBAAyB,CACrB,KAAQ,wBACR,QAAW,GACX,WAAc,CACV,6BAGR,MAAS,CACL,KAAQ,QACR,QAAW,CACP,UACA,UAEJ,WAAc,CACV,OAGR,WAAc,CACV,KAAQ,aACR,QAAW,CACP,iBAEJ,WAAc,CACV,eAGR,wBAA2B,CACvB,KAAQ,0BACR,QAAW,CACP,qBACA,qBACA,uBAEJ,WAAc,CACV,qBAGR,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,UAEJ,WAAc,CACV,QAGR,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,UAEJ,WAAc,CACV,QAGR,QAAW,CACP,KAAQ,UACR,QAAW,GACX,WAAc,CACV,YAGR,aAAgB,CACZ,KAAQ,eACR,QAAW,CACP,eAEJ,WAAc,IAElB,QAAW,CACP,KAAQ,UACR,QAAW,GACX,WAAc,CACV,YAGR,SAAY,CACR,KAAQ,WACR,QAAW,CACP,oBAEJ,WAAc,IAElB,UAAa,CACT,KAAQ,YACR,QAAW,CACP,QACA,QAEJ,WAAc,CACV,YAGR,MAAS,CACL,KAAQ,QACR,QAAW,CACP,QACA,UAEJ,WAAc,CACV,WAGR,KAAQ,CACJ,KAAQ,OACR,QAAW,CACP,QAEJ,WAAc,CACV,WAGR,mBAAsB,CAClB,KAAQ,qBACR,QAAW,CACP,kBAEJ,WAAc,CACV,uBAGR,YAAe,CACX,KAAQ,cACR,QAAW,CACP,sBAEJ,WAAc,CACV,cACA,oBAGR,eAAkB,CACd,KAAQ,iBACR,QAAW,GACX,WAAc,CACV,aAGR,OAAU,CACN,KAAQ,SACR,QAAW,CACP,oBACA,eAEJ,WAAc,IAElB,WAAc,CACV,KAAQ,aACR,QAAW,CACP,kBAEJ,WAAc,IAElB,mBAAsB,CAClB,KAAQ,qBACR,QAAW,CACP,mBAEJ,WAAc,CACV,iBAGR,QAAW,CACP,KAAQ,UACR,QAAW,CACP,eACA,eAEJ,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,CACP,iBACA,yBAEJ,WAAc,IAElB,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,kBACA,mBAEJ,WAAc,IAElB,kBAAqB,CACjB,KAAQ,oBACR,QAAW,CACP,uBACA,uBAEJ,WAAc,IAElB,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,qBACA,gCACA,4BACA,+BAEJ,WAAc,CACV,oBAGR,wBAA2B,CACvB,KAAQ,0BACR,QAAW,CACP,wBACA,sBAEJ,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,CACP,cAEJ,WAAc,CACV,oBAGR,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,qBAEJ,WAAc,IAElB,WAAc,CACV,KAAQ,aACR,QAAW,CACP,eACA,gBACA,wBACA,oBAEJ,WAAc,IAElB,yBAA4B,CACxB,KAAQ,2BACR,QAAW,CACP,yBAEJ,WAAc,IAElB,SAAY,CACR,KAAQ,WACR,QAAW,CACP,gBACA,gBAEJ,WAAc,IAElB,KAAQ,CACJ,KAAQ,OACR,QAAW,CACP,OACA,UAEJ,WAAc,CACV,cAGR,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,cACA,eACA,kBAEJ,WAAc,IAElB,MAAS,CACL,KAAQ,QACR,QAAW,CACP,WACA,aACA,gBAEJ,WAAc,IAElB,MAAS,CACL,KAAQ,QACR,QAAW,CACP,aACA,aAEJ,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,GACX,WAAc,CACV,cAGR,eAAkB,CACd,KAAQ,iBACR,QAAW,CACP,YACA,iBAEJ,WAAc,IAElB,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,cACA,mBAEJ,WAAc,IAElB,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,eACA,2BAEJ,WAAc,IAElB,QAAW,CACP,KAAQ,UACR,QAAW,GACX,WAAc,CACV,iBAGR,QAAW,CACP,KAAQ,UACR,QAAW,GACX,WAAc,CACV,gBAGR,OAAU,CACN,KAAQ,SACR,QAAW,CACP,UAEJ,WAAc,IAElB,QAAW,CACP,KAAQ,UACR,QAAW,CACP,sBACA,WAEJ,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,CACP,iBACA,OACA,OACA,WACA,gBAEJ,WAAc,IAElB,OAAU,CACN,KAAQ,SACR,QAAW,GACX,WAAc,CACV,WAGR,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,WAEJ,WAAc,CACV,eACA,eAGR,eAAkB,CACd,KAAQ,iBACR,QAAW,CACP,gBAEJ,WAAc,CACV,eAGR,SAAY,CACR,KAAQ,WACR,QAAW,CACP,cACA,cAEJ,WAAc,IAElB,aAAgB,CACZ,KAAQ,eACR,QAAW,GACX,WAAc,CACV,gBAGR,aAAgB,CACZ,KAAQ,eACR,QAAW,GACX,WAAc,CACV,aAGR,MAAS,CACL,KAAQ,QACR,QAAW,GACX,WAAc,CACV,aAGR,YAAe,CACX,KAAQ,cACR,QAAW,GACX,WAAc,CACV,kBAGR,YAAe,CACX,KAAQ,cACR,QAAW,GACX,WAAc,CACV,kBAGR,aAAgB,CACZ,KAAQ,eACR,QAAW,GACX,WAAc,CACV,mBAGR,mBAAsB,CAClB,KAAQ,qBACR,QAAW,GACX,WAAc,CACV,iBAGR,gBAAmB,CACf,KAAQ,kBACR,QAAW,GACX,WAAc,CACV,aAGR,YAAe,CACX,KAAQ,cACR,QAAW,GACX,WAAc,CACV,YAGR,kBAAqB,CACjB,KAAQ,oBACR,QAAW,GACX,WAAc,CACV,gBAGR,gBAAmB,CACf,KAAQ,kBACR,QAAW,GACX,WAAc,CACV,cAGR,eAAkB,CACd,KAAQ,iBACR,QAAW,GACX,WAAc,CACV,aAGR,eAAkB,CACd,KAAQ,iBACR,QAAW,CACP,oBACA,wBAEJ,WAAc,CACV,wBAGR,WAAc,CACV,KAAQ,aACR,QAAW,GACX,WAAc,CACV,gBAGR,WAAc,CACV,KAAQ,aACR,QAAW,GACX,WAAc,CACV,gBAGR,UAAa,CACT,KAAQ,YACR,QAAW,GACX,WAAc,CACV,eAGR,UAAa,CACT,KAAQ,YACR,QAAW,GACX,WAAc,CACV,eAGR,UAAa,CACT,KAAQ,YACR,QAAW,GACX,WAAc,CACV,WAGR,iBAAoB,CAChB,KAAQ,mBACR,QAAW,GACX,WAAc,CACV,eAGR,YAAe,CACX,KAAQ,cACR,QAAW,CACP,uBAEJ,WAAc,CACV,qBAGR,kBAAqB,CACjB,KAAQ,oBACR,QAAW,GACX,WAAc,CACV,yBACA,oBAGR,OAAU,CACN,KAAQ,SACR,QAAW,CACP,qBAEJ,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,CACP,cACA,mBAEJ,WAAc,IAElB,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,WACA,WACA,gBAEJ,WAAc,IAElB,mBAAsB,CAClB,KAAQ,qBACR,QAAW,CACP,aAEJ,WAAc,IAElB,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,gBAEJ,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,CACP,UAEJ,WAAc,IAElB,QAAW,CACP,KAAQ,UACR,QAAW,CACP,OAEJ,WAAc,IAElB,WAAc,CACV,KAAQ,aACR,QAAW,CACP,OACA,cACA,cAEJ,WAAc,IAElB,qBAAwB,CACpB,KAAQ,uBACR,QAAW,CACP,iBAEJ,WAAc,IAElB,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,gBAEJ,WAAc,IAElB,eAAkB,CACd,KAAQ,iBACR,QAAW,CACP,oBACA,kBAEJ,WAAc,IAElB,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,gBACA,2BACA,qBAEJ,WAAc,IAElB,uBAA0B,CACtB,KAAQ,yBACR,QAAW,GACX,WAAc,IAElB,yBAA4B,CACxB,KAAQ,2BACR,QAAW,GACX,WAAc,IAElB,gBAAmB,CACf,KAAQ,kBACR,QAAW,CACP,eAEJ,WAAc,CACV,oBAGR,IAAO,CACH,KAAQ,MACR,QAAW,CACP,UAEJ,WAAc,CACV,QAGR,oBAAuB,CACnB,KAAQ,sBACR,QAAW,CACP,4BAEJ,WAAc,IAElB,mBAAsB,CAClB,KAAQ,qBACR,QAAW,CACP,6BAEJ,WAAc,IAElB,oBAAuB,CACnB,KAAQ,sBACR,QAAW,GACX,WAAc,CACV,oBAGR,aAAgB,CACZ,KAAQ,eACR,QAAW,CACP,gCAEJ,WAAc,IAElB,oBAAuB,CACnB,KAAQ,sBACR,QAAW,CACP,uBAEJ,WAAc,IAElB,cAAiB,CACb,KAAQ,gBACR,QAAW,CACP,iBAEJ,WAAc,IAElB,IAAO,CACH,KAAQ,MACR,QAAW,GACX,WAAc,IAElB,YAAe,CACX,KAAQ,cACR,QAAW,CACP,kBAEJ,WAAc,IAElB,qBAAwB,CACpB,KAAQ,uBACR,QAAW,GACX,WAAc,CACV,iBAGR,sBAAyB,CACrB,KAAQ,wBACR,QAAW,GACX,WAAc,IAElB,iBAAoB,CAChB,KAAQ,mBACR,QAAW,GACX,WAAc,KAOtB,SAAWyB,GAIPA,EAA4B,QAAI,UAIhCA,EAA6B,SAAI,WACjCA,EAA2B,OAAI,SAC/BA,EAAwB,IAAI,MAC5BA,EAA0B,MAAI,QAC9BA,EAA2B,OAAI,SAC/BA,EAA2B,OAAI,SAC/BA,EAA2B,OAAI,SAC/BA,EAA0B,MAAI,QAC9BA,EAA4B,QAAI,UAChCA,EAA+B,WAAI,aACnCA,EAA2B,OAAI,SAC/BA,EAA6B,SAAI,WACjCA,EAA+B,WAAI,aACnCA,EAAyB,KAAI,OAC7BA,EAAoC,gBAAI,kBAIxCA,EAA4B,QAAI,UAIhCA,EAAiC,aAAI,eACrCA,EAA4B,QAAI,UAIhCA,EAAiC,aAAI,eACrCA,EAA0B,MAAI,QAC9BA,EAA0B,MAAI,QAC9BA,EAA2B,OAAI,SAC/BA,EAAmC,eAAI,iBACvCA,EAA+B,WAAI,aACnCA,EAAwB,IAAI,MAC5BA,EAA6B,SAAI,WACjCA,EAA+B,WAAI,aACnCA,EAA0B,MAAI,QAC9BA,EAA2B,OAAI,SAC/BA,EAAmC,eAAI,iBACvCA,EAAmC,eAAI,iBACvCA,EAA0B,MAAI,QAC9BA,EAAgC,YAAI,cACpCA,EAA6B,SAAI,WACjCA,EAA4B,QAAI,UAChCA,EAA2B,OAAI,SAC/BA,EAA4B,QAAI,SACnC,CAtDD,CAsDGA,IAAuB/G,EAAQ+G,mBAAqBA,EAAqB,CAAC,IAE7E,SAAWD,GACPA,EAAuB,SAAI,WAC3BA,EAAyB,WAAI,aAC7BA,EAAmB,KAAI,OACvBA,EAAkB,IAAI,KACzB,CALD,CAKGA,IAAiB9G,EAAQ8G,aAAeA,EAAe,CAAC,IAE3D,SAAWD,GACPA,EAAc,KAAI,OAClBA,EAAgB,OAAI,QACvB,CAHD,CAGGA,IAAY7G,EAAQ6G,QAAUA,EAAU,CAAC,IAE5C,SAAWD,GACPA,EAAmB,EAAI,IACvBA,EAAmB,EAAI,GAC1B,CAHD,CAGGA,IAAoB5G,EAAQ4G,gBAAkBA,EAAkB,CAAC,IAEpE,SAAWD,GACPA,EAAoB,IAAI,MACxBA,EAAqB,KAAI,OACzBA,EAAqB,KAAI,OACzBA,EAAyB,SAAI,WAC7BA,EAAqB,KAAI,OACzBA,EAAwB,QAAI,UAC5BA,EAAyB,SAAI,WAC7BA,EAAoB,IAAI,MACxBA,EAAoB,IAAI,MACxBA,EAAmB,GAAI,IAC1B,CAXD,CAWGA,IAAmB3G,EAAQ2G,eAAiBA,EAAiB,CAAC,IAEjE,SAAWD,GACPA,EAA8B,SAAI,WAClCA,EAA8B,SAAI,WAClCA,EAAgC,WAAI,aACpCA,EAA4B,OAAI,SAChCA,EAA0B,KAAI,MACjC,CAND,CAMGA,IAAwB1G,EAAQ0G,oBAAsBA,EAAsB,CAAC,IAEhF,SAAWD,GACPA,EAAkB,OAAI,SACtBA,EAAoB,SAAI,WACxBA,EAAkB,OAAI,QACzB,CAJD,CAIGA,IAAczG,EAAQyG,UAAYA,EAAY,CAAC,IAElD,SAAWD,GACPA,EAAqB,QAAI,UACzBA,EAAsB,SAAI,WAC1BA,EAAyB,YAAI,cAChC,CAJD,CAIGA,IAAgBxG,EAAQwG,YAAcA,EAAc,CAAC,IAExD,SAAWD,GACPA,EAA4B,SAAI,WAChCA,EAAwB,KAAI,OAC5BA,EAA0B,OAAI,SAC9BA,EAAmC,gBAAI,iBAC1C,CALD,CAKGA,IAAsBvG,EAAQuG,kBAAoBA,EAAoB,CAAC,IAE1E,SAAWD,GACPA,EAAwB,OAAI,SAC5BA,EAA2B,UAAI,WAClC,CAHD,CAGGA,IAAoBtG,EAAQsG,gBAAkBA,EAAkB,CAAC,IAEpE,SAAWD,GACPA,EAAoB,QAAI,UACxBA,EAAsB,UAAI,YAC1BA,EAAiB,KAAI,OACrBA,EAAiB,KAAI,OACrBA,EAAqB,SAAI,WACzBA,EAAiB,KAAI,MACxB,CAPD,CAOGA,IAAerG,EAAQqG,WAAaA,EAAa,CAAC,IAErD,SAAWD,GACPA,EAA6B,SAAI,WACjCA,EAA8B,UAAI,YAClCA,EAA8B,UAAI,YAClCA,EAA+B,WAAI,YACtC,CALD,CAKGA,IAAuBpG,EAAQoG,mBAAqBA,EAAqB,CAAC,IAE7E,SAAWD,GACPA,EAAkC,OAAI,SACtCA,EAAoC,SAAI,WACxCA,EAAgC,KAAI,OACpCA,EAAiC,MAAI,OACxC,CALD,CAKGA,IAA8BnG,EAAQmG,0BAA4BA,EAA4B,CAAC,IAElG,SAAWD,GACPA,EAAuB,KAAI,OAC3BA,EAA0B,QAAI,UAC9BA,EAAyB,OAAI,SAC7BA,EAA4B,UAAI,WACnC,CALD,CAKGA,IAAqBlG,EAAQkG,iBAAmBA,EAAmB,CAAC,IAEvE,SAAWD,GACPA,EAAkC,eAAI,iBACtCA,EAAkC,eAAI,iBACtCA,EAAyC,sBAAI,wBAC7CA,EAAyB,MAAI,QAC7BA,EAA8B,WAAI,aAClCA,EAA2C,wBAAI,0BAC/CA,EAAmC,gBAAI,kBACvCA,EAAmC,gBAAI,kBACvCA,EAA2B,QAAI,UAC/BA,EAAgC,aAAI,eACpCA,EAA2B,QAAI,UAC/BA,EAA4B,SAAI,WAChCA,EAA6B,UAAI,YACjCA,EAAyB,MAAI,QAC7BA,EAAwB,KAAI,OAC5BA,EAAsC,mBAAI,qBAC1CA,EAA+B,YAAI,cACnCA,EAAkC,eAAI,iBACtCA,EAA0B,OAAI,SAC9BA,EAA8B,WAAI,aAClCA,EAAsC,mBAAI,qBAC1CA,EAA2B,QAAI,UAC/BA,EAA+B,YAAI,cACnCA,EAAmC,gBAAI,kBACvCA,EAAqC,kBAAI,oBACzCA,EAAiC,cAAI,gBACrCA,EAA2C,wBAAI,0BAC/CA,EAA+B,YAAI,cACnCA,EAAiC,cAAI,gBACrCA,EAA8B,WAAI,aAClCA,EAA4C,yBAAI,2BAChDA,EAA4B,SAAI,WAChCA,EAAwB,KAAI,OAC5BA,EAAiC,cAAI,gBACrCA,EAAyB,MAAI,QAC7BA,EAAyB,MAAI,QAC7BA,EAA+B,YAAI,cACnCA,EAAkC,eAAI,iBACtCA,EAAmC,gBAAI,kBACvCA,EAAiC,cAAI,gBACrCA,EAA2B,QAAI,UAC/BA,EAA2B,QAAI,UAC/BA,EAA0B,OAAI,SAC9BA,EAA2B,QAAI,UAC/BA,EAA+B,YAAI,cACnCA,EAA0B,OAAI,SAC9BA,EAAmC,gBAAI,kBACvCA,EAAkC,eAAI,iBACtCA,EAA4B,SAAI,WAChCA,EAAgC,aAAI,eACpCA,EAAgC,aAAI,eACpCA,EAAyB,MAAI,QAC7BA,EAA+B,YAAI,cACnCA,EAA+B,YAAI,cACnCA,EAAgC,aAAI,eACpCA,EAAsC,mBAAI,qBAC1CA,EAAmC,gBAAI,kBACvCA,EAA+B,YAAI,cACnCA,EAAqC,kBAAI,oBACzCA,EAAmC,gBAAI,kBACvCA,EAAkC,eAAI,iBACtCA,EAAkC,eAAI,iBACtCA,EAA8B,WAAI,aAClCA,EAA8B,WAAI,aAClCA,EAA6B,UAAI,YACjCA,EAA6B,UAAI,YACjCA,EAA6B,UAAI,YACjCA,EAAoC,iBAAI,mBACxCA,EAA+B,YAAI,cACnCA,EAAqC,kBAAI,oBACzCA,EAA0B,OAAI,SAC9BA,EAA+B,YAAI,cACnCA,EAAiC,cAAI,gBACrCA,EAAsC,mBAAI,qBAC1CA,EAAmC,gBAAI,kBACvCA,EAA+B,YAAI,cACnCA,EAA2B,QAAI,UAC/BA,EAA8B,WAAI,aAClCA,EAAwC,qBAAI,uBAC5CA,EAAiC,cAAI,gBACrCA,EAAkC,eAAI,iBACtCA,EAAmC,gBAAI,kBACvCA,EAA0C,uBAAI,yBAC9CA,EAA4C,yBAAI,2BAChDA,EAAmC,gBAAI,kBACvCA,EAAuB,IAAI,MAC3BA,EAAuC,oBAAI,sBAC3CA,EAAsC,mBAAI,qBAC1CA,EAAuC,oBAAI,sBAC3CA,EAAgC,aAAI,eACpCA,EAAuC,oBAAI,sBAC3CA,EAAiC,cAAI,gBACrCA,EAAuB,IAAI,MAC3BA,EAA+B,YAAI,cACnCA,EAAwC,qBAAI,uBAC5CA,EAAyC,sBAAI,wBAC7CA,EAAoC,iBAAI,kBAC3C,CAlGD,CAkGGA,IAAsBjG,EAAQiG,kBAAoBA,EAAoB,CAAC,IAE1E,SAAWD,GACPA,EAAuB,IAAI,aAC3BA,EAAoC,iBAAI,4BACxCA,EAA4B,SAAI,mBAChCA,EAA4B,SAAI,mBAChCA,EAAgC,aAAI,uBACpCA,EAAgC,aAAI,gCACpCA,EAAkC,eAAI,mBACtCA,EAA+B,YAAI,qCACnCA,EAAsC,mBAAI,6CAC1CA,EAAsC,mBAAI,uCAC1CA,EAAuC,oBAAI,qCAC3CA,EAA+B,YAAI,4BACnCA,EAAyC,sBAAI,uCAC7CA,EAAuC,oBAAI,8CAC3CA,EAAuC,oBAAI,8CAC3CA,EAA2C,wBAAI,kDAC/CA,EAAyB,MAAI,6BAChC,CAlBD,CAkBGA,IAAsBhG,EAAQgG,kBAAoBA,EAAoB,CAAC,G,u2BCntC1E,mBAaM,cAAElD,EAAa,cAAE9B,EAAa,aAAEW,GAAiB,UAOjDsF,EAAkB,IAAIxE,IAAI,CAAC,SAAU,MAAO,MAAO,SAAU,OAAQ,OAAQ,UAAW,MAAO,QAAS,MAAO,aAAc,UAAW,QAAS,YAEjJyE,EAAe,CAAC,WAAY,eAAgB,mBAAoB,mBAGhEC,EAAsC,CACxC,SAAYC,IACZ,eAAgB,IAChB,mBAAoB,IACpB,kBAAmB,GAuBvB,MAAMC,UAAyB,EAAA7G,mBAU3B,WAAAG,CAAYC,GACRC,MAAMD,GATF,KAAA0G,YAAc,IAAIC,IAElB,KAAAC,SAAW,IAAID,IAEf,KAAAE,OAAS,IAAIF,IAEb,KAAAG,UAA4B,GAIhC3I,KAAK4I,YACL5I,KAAK6I,mBACT,CAIQ,SAAAD,GACJ,IACI,MAAME,EAAM9I,KAAK+B,QAAQgH,QAAQ,YACjC,GAAID,EAAK,CACL,MAAME,EAAuBC,KAAKC,MAAMJ,GACxC,IAAK,MAAMK,KAAKH,EAAKhJ,KAAKyI,SAASpD,IAAI8D,EAAErG,GAAIqG,GAC7CnJ,KAAKsC,QAAQH,IAAI,UAAUnC,KAAKyI,SAASW,8BAC7C,CACJ,CAAE,MAAOpD,GACLhG,KAAKsC,QAAQ2C,KAAK,wCAAyCe,EAC/D,CAEA,IAAK,MAAOlD,KAAO9C,KAAKyI,SAAU,CAC9B,MAAMK,EAAM9I,KAAK+B,QAAQgH,QAAQ,OAAOjG,KACpCgG,GAAK9I,KAAK0I,OAAOrD,IAAIvC,EAAIuG,OAAOC,KAAKR,EAAK,UAClD,CACJ,CAEQ,YAAAS,GACJvJ,KAAK+B,QAAQyH,QAAQ,WAAYP,KAAKQ,UAAU,IAAIzJ,KAAKyI,SAAStD,WACtE,CAEQ,SAAAuE,CAAU5G,EAAY6G,GAC1B3J,KAAK+B,QAAQyH,QAAQ,OAAO1G,IAAM6G,EAAIC,SAAS,UACnD,CAEQ,aAAAC,CAAc/G,GACN9C,KAAK+B,QAAQgH,QAAQ,OAAOjG,MAC/B9C,KAAK+B,QAAQ+H,WAAW,OAAOhH,KACxC9C,KAAKyI,SAASsB,OAAOjH,GACrB9C,KAAK0I,OAAOqB,OAAOjH,GACnB9C,KAAKuJ,cACT,CAIA,iBAAMS,GACF,MAAMC,EAAUhK,OAAO6G,KAAK/C,EAAcmG,kBACrCC,IAAIrH,GAAMiB,EAAcC,cAAclB,IACtCsH,OAAOC,GAAKA,IACRA,EAAEC,OAAS,EAAAtC,mBAAmBuC,QAAUF,EAAEC,OAAS,EAAAtC,mBAAmBwC,WACvEH,EAAEI,YAAYC,SAAS,EAAAxD,kBAAkByD,iBAGjD,IAAIC,EACJ,IAEIA,EAAQ,SADe,UAAIzE,gBAAgB0E,mEAE/C,CAAE,MACED,EAAQ,8CACZ,CAEA,MAAME,EAAsB,CACxB,CACIC,IAAK,OACLC,MAAO,oBACPC,YAAa,GAAGjL,KAAKyI,SAASW,yBAAyB,IAAIpJ,KAAKyI,SAAStD,UAAUiF,OAAOc,IAAMA,EAAEC,UAAUC,0BAA0B,IAAIpL,KAAKyI,SAAStD,UAAUiF,OAAOc,GAAKA,EAAEC,UAAwB,YAAZD,EAAEG,OAAqBD,mBACnNE,UAAU,EACVhK,MAAO,IAEX,CACIyJ,IAAK,UACLC,MAAO,YACPC,YAAa,oDACbX,KAAM,OACNgB,UAAU,EACVhK,MAAO,YAAYsJ,+KAI3B,IAAK,MAAMW,KAAOtB,EAAS,CACvB,MAAMc,EAAM,QAAQQ,EAAIzI,KACxBgI,EAASU,KAAK,CACVT,MACAC,MAAOO,EAAIE,KACXC,MAAO,0BACPT,YAAa,oDACb3J,MAAOtB,KAAK+B,QAAQgH,QAAQgC,IAAQ,eACpCY,QAAS,IAAIxD,IAErB,CAEA,OAAO2C,CACX,CAEA,gBAAMc,CAAWb,EAAazJ,GACd,YAARyJ,GAA6B,YAARA,GAA6B,SAARA,IAC9C/K,KAAK+B,QAAQyH,QAAQuB,EAAKzJ,GACtByJ,EAAIc,WAAW,UAEf7L,KAAK6I,oBAEb,CAIQ,iBAAAA,GAEJ,IAAK,MAAMiD,KAAU9L,KAAK2I,UAAWmD,IACrC9L,KAAK2I,UAAY,GAEjB,MAAMsB,EAAUhK,OAAO6G,KAAK/C,EAAcmG,kBACrCC,IAAIrH,GAAMiB,EAAcC,cAAclB,IACtCsH,OAAOC,GAAKA,IACRA,EAAEC,OAAS,EAAAtC,mBAAmBuC,QAAUF,EAAEC,OAAS,EAAAtC,mBAAmBwC,WACvEH,EAAEI,YAAYC,SAAS,EAAAxD,kBAAkByD,iBAGjD,IAAK,MAAMY,KAAOtB,EAAS,CACvB,MAAM8B,EAAU,QAAQR,EAAIzI,KACtBkJ,EAAahM,KAAK+B,QAAQgH,QAAQgD,IAAY,eACpD,GAAkB,aAAdC,EAA0B,SAE9B,MAAMvH,EAAW8G,EAAIU,OAAO,EAAA/E,kBAAkByD,eAAgBuB,MAAOC,EAAQC,EAAS1J,WAC5E1C,KAAKqM,YAAYd,EAAIzI,GAAIyI,EAAIE,KAAM/I,EAAyB0F,EAAQ4D,MAE9EhM,KAAK2I,UAAU6C,KAAK,IAAM/G,EAASI,iBACvC,CAEA7E,KAAKsC,QAAQH,IAAI,gBAAgBnC,KAAK2I,UAAUyC,oBACpD,CAIQ,iBAAMiB,CAAYC,EAAkBC,EAAoB7J,EAAuB8J,GACnF,IAAK9J,GAAM+J,YAAYrB,SAAW1I,EAAKgK,gBAAiB,OAGxD,MAAMC,EAAMC,KAAKD,MAEjB,GAAIA,GADS3M,KAAKuI,YAAYzH,IAAIwL,IAAa,GAC9BE,EAAa,OAG9B,MAAMK,EAAUnK,EAAK+J,WAAWrC,OAAOC,GACnCA,EAAEyC,WAAa5E,EAAgB6E,IAAI1C,EAAEyC,UAAUE,gBAAkB3C,EAAE4C,aAEvE,IAAKJ,EAAQzB,OAAQ,OAGrB,MAAM8B,EAAOL,EAAQM,KAAK,CAACC,EAAGC,KAAOA,EAAEC,OAAS,IAAMF,EAAEE,OAAS,IAAI,GAGrE,GAAItN,KAAKyI,SAASW,MApLL,IAoL2B,CAEpC,MAAMmE,EAAS,IAAIvN,KAAKyI,SAAStD,UAC5BiF,OAAOc,IAAMA,EAAEC,UACfgC,KAAK,CAACC,EAAGC,IAAMD,EAAEI,UAAYH,EAAEG,WAAW,GAC/C,IAAID,EACC,OADOvN,KAAK6J,cAAc0D,EAAOzK,GAE1C,CAKA,IAAI2K,EAHJzN,KAAKuI,YAAYlD,IAAIiH,EAAUK,GAI/B,IACI,GAAIjK,EAAKgL,YAAa,CAClB,MAAMnC,EAAMxH,EAAcC,cAAcsI,GAClCqB,QAAWpC,EAAIqC,kBAAkBlL,EAAKgL,aAC5CD,QAAa7K,EAAaiL,2BAA2BF,EAAI,aAC7D,CACJ,CAAE,MAAO3H,GACLhG,KAAKsC,QAAQ2C,KAAK,qCAAqCsH,KAAevG,EAC1E,CAEA,IAAKyH,EAAM,OAEX,MAAM3K,EAAK,GAAG6J,KAAOmB,KAAKC,SAASnE,SAAS,IAAIoE,MAAM,EAAG,KACnDC,EAAwB,CAC1BnL,KACAwJ,WACAC,aACAiB,UAAWb,EACXuB,cAAehB,EAAKJ,UACpBQ,MAAOJ,EAAKI,OAAS,EACrBL,YAAaC,EAAKD,YAClBP,gBAAiBhK,EAAKgK,gBACtBgB,YAAahL,EAAKgL,YAClBvC,UAAU,GAGdnL,KAAKyI,SAASpD,IAAIvC,EAAImL,GACtBjO,KAAK0I,OAAOrD,IAAIvC,EAAI2K,GACpBzN,KAAK0J,UAAU5G,EAAI2K,GACnBzN,KAAKuJ,eAELvJ,KAAKsC,QAAQH,IAAI,YAAY+K,EAAKJ,cAAcgB,KAAKK,MAA0B,KAAnBjB,EAAKI,OAAS,cAAoBf,MAAevM,KAAKyI,SAASW,cAC/H,CAIA,eAAMgF,CAAUC,EAAsBC,GAElC,IAAKD,EAAQE,SAET,YADAD,EAASE,KAAK,eAAgB,CAAE3H,KAAM,IAAK4H,QAAS,CAAE,mBAAoB,qCAI9E,MACMC,EADM,IAAIC,IAAIN,EAAQO,IAAK,oBAChBC,SAASC,QAAQT,EAAQU,SAAU,IAGpD,GAAIL,EAAK7C,WAAW,SAAU,CAC1B,MAAM/I,EAAK4L,EAAKV,MAAM,GAChBgB,EAAMhP,KAAK0I,OAAO5H,IAAIgC,GAC5B,OAAKkM,EACEV,EAASE,KAAKQ,EAAK,CAAEP,QAAS,CAAE,eAAgB,aAAc,gBAAiB,kBADrEH,EAASE,KAAK,YAAa,CAAE3H,KAAM,KAExD,CAGA,GAAa,eAAT6H,GAAyBL,EAAQY,KAAM,CACvC,MAAMC,EAAUb,EAAQY,KAClBA,EAAOhG,KAAKC,MAAyB,iBAAZgG,EAAuBA,EAAU7F,OAAO8F,SAASD,GAAWA,EAAQtF,WAAawF,OAAOF,IACjHjB,EAASjO,KAAKyI,SAAS3H,IAAImO,EAAKnM,IACtC,OAAKmL,GACLA,EAAO5C,MAAQ4D,EAAK5D,MACpB4C,EAAO9C,UAAW,EACC,YAAf8D,EAAK5D,MACLrL,KAAK6J,cAAcoF,EAAKnM,KAExB9C,KAAKyI,SAASpD,IAAI4J,EAAKnM,GAAImL,GAC3BjO,KAAKuJ,gBAEF+E,EAASE,KAAKvF,KAAKQ,UAAU,CAAE4F,IAAI,IAAS,CAAEZ,QAAS,CAAE,eAAgB,uBAT5DH,EAASE,KAAK,YAAa,CAAE3H,KAAM,KAU3D,CAGA,GAAa,iBAAT6H,EAAyB,CACzB,MAAMY,EAAU,IAAItP,KAAKyI,SAAStD,UAC7BiF,OAAOc,IAAMA,EAAEC,UACfgC,KAAK,CAACC,EAAGC,IAAMA,EAAEG,UAAYJ,EAAEI,WAC/BQ,MAAM,EAAG,IACd,OAAOM,EAASE,KAAKvF,KAAKQ,UAAU6F,GAAU,CAAEb,QAAS,CAAE,eAAgB,qBAC/E,CAGA,GAAa,eAATC,EAAuB,CACvB,MAAMa,EAAM,IAAIvP,KAAKyI,SAAStD,UACxBqK,EAAQ,CACVC,MAAOF,EAAInE,OACXkE,QAASC,EAAInF,OAAOc,IAAMA,EAAEC,UAAUC,OACtCsE,QAASH,EAAInF,OAAOc,GAAKA,EAAEC,UAAwB,YAAZD,EAAEG,OAAqBD,OAC9DuE,QAAS,CAAC,EACVC,SAAU,CAAC,EACXC,gBAAiB,CAAC,GAEtB,IAAK,MAAM1G,KAAKoG,EACRpG,EAAEkC,QAAOmE,EAAMG,QAAQxG,EAAEkC,QAAUmE,EAAMG,QAAQxG,EAAEkC,QAAU,GAAK,GACtEmE,EAAMI,SAASzG,EAAEoD,aAAeiD,EAAMI,SAASzG,EAAEoD,aAAe,GAAK,EACrEiD,EAAMK,gBAAgB1G,EAAE+E,gBAAkBsB,EAAMK,gBAAgB1G,EAAE+E,gBAAkB,GAAK,EAE7F,OAAOI,EAASE,KAAKvF,KAAKQ,UAAU+F,GAAQ,CAAEf,QAAS,CAAE,eAAgB,qBAC7E,CAGA,GAAa,gBAATC,EAAwB,CACxB,MAAMgB,EAAU,IAAI1P,KAAKyI,SAAStD,UAAUiF,OAAOc,GAAKA,EAAEC,UAAYD,EAAEG,OAAqB,YAAZH,EAAEG,OACnF,IAAKqE,EAAQtE,OAAQ,OAAOkD,EAASE,KAAKvF,KAAKQ,UAAU,CAAEhD,MAAO,wBAA0B,CAAEgI,QAAS,CAAE,eAAgB,oBAAsB5H,KAAM,MAErJ,MAAMiJ,EAAkC,CACpCC,OAAQ,EAAGC,OAAQ,EAAGC,KAAM,EAAGC,QAAS,EAAGC,MAAO,EAAGC,QAAS,EAAGC,SAAU,GAIzEC,EAAqE,GAE3E,IAAK,MAAMrC,KAAUyB,EAAS,CAC1B,MAAMV,EAAMhP,KAAK0I,OAAO5H,IAAImN,EAAOnL,IACnC,IAAKkM,EAAK,SAEV,MAAMuB,EAAQ,GAAGtC,EAAOnL,KACxBwN,EAAQ9E,KAAK,CAAEgF,SAAU,UAAUD,QAAaE,QAASzB,EAAIpF,SAAS,UAAW8G,SAAU,WAE3F,MAAOC,EAAGC,EAAGC,EAAGC,GAAK7C,EAAOhB,aACrB8D,EAAMC,GAAQ/C,EAAOvB,gBACtBuE,GAAMN,EAAIE,EAAI,GAAKE,EACnBG,GAAMN,EAAIE,EAAI,GAAKE,EACnBG,EAAKN,EAAIE,EACTK,EAAKN,EAAIE,EAETK,EAAY,GADFvB,EAAS7B,EAAO5C,UACA4F,EAAGK,QAAQ,MAAMJ,EAAGI,QAAQ,MAAMH,EAAGG,QAAQ,MAAMF,EAAGE,QAAQ,OAC9FhB,EAAQ9E,KAAK,CAAEgF,SAAU,UAAUD,QAAaE,QAASY,EAAWX,SAAU,QAClF,CAEA,MAAMa,EAAO,CACT,gBACA,gBACA,cACA,GACA,QACA,qEACA,GACA,4CACA,KAAK7B,EAAQtE,0BACfoG,KAAK,MAGP,OAFAlB,EAAQ9E,KAAK,CAAEgF,SAAU,YAAaC,QAASc,EAAMb,SAAU,SAExDpC,EAASE,KAAKvF,KAAKQ,UAAU,CAAEgI,MAAOnB,EAASoB,MAAOhC,EAAQtE,SAAW,CAC5EqD,QAAS,CAAE,eAAgB,qBAEnC,CAGA,GAAa,MAATC,GAAyB,KAATA,GAAwB,gBAATA,EAC/B,OAAOJ,EAASE,KAAKxO,KAAK2R,WAAY,CAAElD,QAAS,CAAE,eAAgB,eAGvEH,EAASE,KAAK,YAAa,CAAE3H,KAAM,KACvC,CAIQ,QAAA8K,GACJ,MAAO,y3nBAocX,EAGJ,UAAerJ,C,sBCt0BftB,EAAO/F,QAAU2Q,QAAQ,S,GCCrBC,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBxR,IAAjByR,EACH,OAAOA,EAAa/Q,QAGrB,IAAI+F,EAAS6K,EAAyBE,GAAY,CAGjD9Q,QAAS,CAAC,GAOX,OAHAgR,EAAoBF,GAAU1Q,KAAK2F,EAAO/F,QAAS+F,EAAQA,EAAO/F,QAAS6Q,GAGpE9K,EAAO/F,OACf,CCtBA6Q,EAAoB3R,EAAI,CAAC+R,EAAKC,IAAUlS,OAAOkB,UAAUC,eAAeC,KAAK6Q,EAAKC,GCGlF,IAAIC,EAAsBN,EAAoB,K","sources":["../node_modules/@scrypted/sdk/dist/src/index.js","../node_modules/@scrypted/sdk/dist/src|sync","../node_modules/@scrypted/sdk/dist/types/gen/index.js","../src/main.ts","../external node-commonjs \"module\"","../webpack/bootstrap","../webpack/runtime/hasOwnProperty shorthand","../webpack/startup"],"sourcesContent":["\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.sdk = exports.MixinDeviceBase = exports.ScryptedDeviceBase = void 0;\n__exportStar(require(\"../types/gen/index\"), exports);\nconst index_1 = require(\"../types/gen/index\");\nconst module_1 = require(\"module\");\n/**\n * @category Core Reference\n */\nclass ScryptedDeviceBase extends index_1.DeviceBase {\n constructor(nativeId) {\n super();\n this.nativeId = nativeId;\n }\n get storage() {\n if (!this._storage) {\n this._storage = exports.sdk.deviceManager.getDeviceStorage(this.nativeId);\n }\n return this._storage;\n }\n get log() {\n if (!this._log) {\n this._log = exports.sdk.deviceManager.getDeviceLogger(this.nativeId);\n }\n return this._log;\n }\n get console() {\n if (!this._console) {\n this._console = exports.sdk.deviceManager.getDeviceConsole(this.nativeId);\n }\n return this._console;\n }\n async createMediaObject(data, mimeType) {\n return exports.sdk.mediaManager.createMediaObject(data, mimeType, {\n sourceId: this.id,\n });\n }\n getMediaObjectConsole(mediaObject) {\n if (typeof mediaObject.sourceId !== 'string')\n return this.console;\n return exports.sdk.deviceManager.getMixinConsole(mediaObject.sourceId, this.nativeId);\n }\n _lazyLoadDeviceState() {\n if (!this._deviceState) {\n if (this.nativeId) {\n this._deviceState = exports.sdk.deviceManager.getDeviceState(this.nativeId);\n }\n else {\n this._deviceState = exports.sdk.deviceManager.getDeviceState();\n }\n }\n }\n /**\n * Fire an event for this device.\n */\n onDeviceEvent(eventInterface, eventData) {\n return exports.sdk.deviceManager.onDeviceEvent(this.nativeId, eventInterface, eventData);\n }\n}\nexports.ScryptedDeviceBase = ScryptedDeviceBase;\n/**\n * @category Mixin Reference\n */\nclass MixinDeviceBase extends index_1.DeviceBase {\n constructor(options) {\n super();\n this._listeners = new Set();\n this.mixinDevice = options.mixinDevice;\n this.mixinDeviceInterfaces = options.mixinDeviceInterfaces;\n this.mixinStorageSuffix = options.mixinStorageSuffix;\n this._deviceState = options.mixinDeviceState;\n this.nativeId = exports.sdk.systemManager.getDeviceById(this.id).nativeId;\n this.mixinProviderNativeId = options.mixinProviderNativeId;\n // RpcProxy will trap all properties, and the following check/hack will determine\n // if the device state came from another node worker thread.\n // This should ultimately be discouraged and warned at some point in the future.\n if (this._deviceState.__rpcproxy_traps_all_properties && typeof this._deviceState.id === 'string') {\n this._deviceState = exports.sdk.deviceManager.createDeviceState(this._deviceState.id, this._deviceState.setState);\n }\n }\n get storage() {\n if (!this._storage) {\n const mixinStorageSuffix = this.mixinStorageSuffix;\n const mixinStorageKey = this.id + (mixinStorageSuffix ? ':' + mixinStorageSuffix : '');\n this._storage = exports.sdk.deviceManager.getMixinStorage(mixinStorageKey, this.mixinProviderNativeId);\n }\n return this._storage;\n }\n get console() {\n if (!this._console) {\n if (exports.sdk.deviceManager.getMixinConsole)\n this._console = exports.sdk.deviceManager.getMixinConsole(this.id, this.mixinProviderNativeId);\n else\n this._console = exports.sdk.deviceManager.getDeviceConsole(this.mixinProviderNativeId);\n }\n return this._console;\n }\n async createMediaObject(data, mimeType) {\n return exports.sdk.mediaManager.createMediaObject(data, mimeType, {\n sourceId: this.id,\n });\n }\n getMediaObjectConsole(mediaObject) {\n if (typeof mediaObject.sourceId !== 'string')\n return this.console;\n return exports.sdk.deviceManager.getMixinConsole(mediaObject.sourceId, this.mixinProviderNativeId);\n }\n /**\n * Fire an event for this device.\n */\n onDeviceEvent(eventInterface, eventData) {\n return exports.sdk.deviceManager.onMixinEvent(this.id, this, eventInterface, eventData);\n }\n _lazyLoadDeviceState() {\n }\n manageListener(listener) {\n this._listeners.add(listener);\n }\n release() {\n for (const l of this._listeners) {\n l.removeListener();\n }\n }\n}\nexports.MixinDeviceBase = MixinDeviceBase;\n(function () {\n function _createGetState(state) {\n return function () {\n this._lazyLoadDeviceState();\n // @ts-ignore: accessing private property\n return this._deviceState?.[state];\n };\n }\n function _createSetState(state) {\n return function (value) {\n this._lazyLoadDeviceState();\n // @ts-ignore: accessing private property\n if (!this._deviceState) {\n console.warn('device state is unavailable. the device must be discovered with deviceManager.onDeviceDiscovered or deviceManager.onDevicesChanged before the state can be set.');\n }\n else {\n // @ts-ignore: accessing private property\n this._deviceState[state] = value;\n }\n };\n }\n for (const field of Object.values(index_1.ScryptedInterfaceProperty)) {\n if (field === index_1.ScryptedInterfaceProperty.nativeId)\n continue;\n Object.defineProperty(ScryptedDeviceBase.prototype, field, {\n set: _createSetState(field),\n get: _createGetState(field),\n });\n Object.defineProperty(MixinDeviceBase.prototype, field, {\n set: _createSetState(field),\n get: _createGetState(field),\n });\n }\n})();\nexports.sdk = {};\ntry {\n let loaded = false;\n try {\n // todo: remove usage of process.env.SCRYPTED_SDK_MODULE, only existed in prerelease builds.\n // import.meta is not a reliable way to detect es module support in webpack since webpack\n // evaluates that to true at runtime.\n const esModule = process.env.SCRYPTED_SDK_ES_MODULE || process.env.SCRYPTED_SDK_MODULE;\n const cjsModule = process.env.SCRYPTED_SDK_CJS_MODULE || process.env.SCRYPTED_SDK_MODULE;\n // @ts-expect-error\n if (esModule && typeof import.meta !== 'undefined') {\n // @ts-expect-error\n const require = (0, module_1.createRequire)(import.meta.url);\n const sdkModule = require(esModule);\n Object.assign(exports.sdk, sdkModule.getScryptedStatic());\n loaded = true;\n }\n else if (cjsModule) {\n // @ts-expect-error\n if (typeof __non_webpack_require__ !== 'undefined') {\n // @ts-expect-error\n const sdkModule = __non_webpack_require__(process.env.SCRYPTED_SDK_MODULE);\n Object.assign(exports.sdk, sdkModule.getScryptedStatic());\n loaded = true;\n }\n else {\n const sdkModule = require(cjsModule);\n Object.assign(exports.sdk, sdkModule.getScryptedStatic());\n loaded = true;\n }\n }\n }\n catch (e) {\n console.warn(\"failed to load sdk module\", e);\n throw e;\n }\n if (!loaded) {\n let runtimeAPI;\n try {\n runtimeAPI = pluginRuntimeAPI;\n }\n catch (e) {\n }\n Object.assign(exports.sdk, {\n log: deviceManager.getDeviceLogger(undefined),\n deviceManager,\n endpointManager,\n mediaManager,\n systemManager,\n pluginHostAPI,\n ...runtimeAPI,\n });\n }\n try {\n exports.sdk.systemManager.setScryptedInterfaceDescriptors?.(index_1.TYPES_VERSION, index_1.ScryptedInterfaceDescriptors)?.catch(() => { });\n }\n catch (e) {\n }\n}\ncatch (e) {\n console.error('sdk initialization error, import @scrypted/types or use @scrypted/client instead', e);\n}\nexports.default = exports.sdk;\n//# sourceMappingURL=index.js.map","function webpackEmptyContext(req) {\n\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\te.code = 'MODULE_NOT_FOUND';\n\tthrow e;\n}\nwebpackEmptyContext.keys = () => ([]);\nwebpackEmptyContext.resolve = webpackEmptyContext;\nwebpackEmptyContext.id = 891;\nmodule.exports = webpackEmptyContext;","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ScryptedMimeTypes = exports.ScryptedInterface = exports.MediaPlayerState = exports.SecuritySystemObstruction = exports.SecuritySystemMode = exports.AirQuality = exports.AirPurifierMode = exports.AirPurifierStatus = exports.ChargeState = exports.LockState = exports.PanTiltZoomMovement = exports.ThermostatMode = exports.TemperatureUnit = exports.FanMode = exports.HumidityMode = exports.ScryptedDeviceType = exports.ScryptedInterfaceDescriptors = exports.ScryptedInterfaceMethod = exports.ScryptedInterfaceProperty = exports.DeviceBase = exports.TYPES_VERSION = void 0;\nexports.TYPES_VERSION = \"0.3.116\";\nclass DeviceBase {\n}\nexports.DeviceBase = DeviceBase;\nvar ScryptedInterfaceProperty;\n(function (ScryptedInterfaceProperty) {\n ScryptedInterfaceProperty[\"id\"] = \"id\";\n ScryptedInterfaceProperty[\"info\"] = \"info\";\n ScryptedInterfaceProperty[\"interfaces\"] = \"interfaces\";\n ScryptedInterfaceProperty[\"mixins\"] = \"mixins\";\n ScryptedInterfaceProperty[\"name\"] = \"name\";\n ScryptedInterfaceProperty[\"nativeId\"] = \"nativeId\";\n ScryptedInterfaceProperty[\"pluginId\"] = \"pluginId\";\n ScryptedInterfaceProperty[\"providedInterfaces\"] = \"providedInterfaces\";\n ScryptedInterfaceProperty[\"providedName\"] = \"providedName\";\n ScryptedInterfaceProperty[\"providedRoom\"] = \"providedRoom\";\n ScryptedInterfaceProperty[\"providedType\"] = \"providedType\";\n ScryptedInterfaceProperty[\"providerId\"] = \"providerId\";\n ScryptedInterfaceProperty[\"room\"] = \"room\";\n ScryptedInterfaceProperty[\"type\"] = \"type\";\n ScryptedInterfaceProperty[\"scryptedRuntimeArguments\"] = \"scryptedRuntimeArguments\";\n ScryptedInterfaceProperty[\"on\"] = \"on\";\n ScryptedInterfaceProperty[\"brightness\"] = \"brightness\";\n ScryptedInterfaceProperty[\"colorTemperature\"] = \"colorTemperature\";\n ScryptedInterfaceProperty[\"rgb\"] = \"rgb\";\n ScryptedInterfaceProperty[\"hsv\"] = \"hsv\";\n ScryptedInterfaceProperty[\"buttons\"] = \"buttons\";\n ScryptedInterfaceProperty[\"sensors\"] = \"sensors\";\n ScryptedInterfaceProperty[\"running\"] = \"running\";\n ScryptedInterfaceProperty[\"paused\"] = \"paused\";\n ScryptedInterfaceProperty[\"docked\"] = \"docked\";\n ScryptedInterfaceProperty[\"temperatureSetting\"] = \"temperatureSetting\";\n ScryptedInterfaceProperty[\"temperature\"] = \"temperature\";\n ScryptedInterfaceProperty[\"temperatureUnit\"] = \"temperatureUnit\";\n ScryptedInterfaceProperty[\"humidity\"] = \"humidity\";\n ScryptedInterfaceProperty[\"audioVolumes\"] = \"audioVolumes\";\n ScryptedInterfaceProperty[\"recordingActive\"] = \"recordingActive\";\n ScryptedInterfaceProperty[\"ptzCapabilities\"] = \"ptzCapabilities\";\n ScryptedInterfaceProperty[\"lockState\"] = \"lockState\";\n ScryptedInterfaceProperty[\"entryOpen\"] = \"entryOpen\";\n ScryptedInterfaceProperty[\"batteryLevel\"] = \"batteryLevel\";\n ScryptedInterfaceProperty[\"chargeState\"] = \"chargeState\";\n ScryptedInterfaceProperty[\"online\"] = \"online\";\n ScryptedInterfaceProperty[\"fromMimeType\"] = \"fromMimeType\";\n ScryptedInterfaceProperty[\"toMimeType\"] = \"toMimeType\";\n ScryptedInterfaceProperty[\"converters\"] = \"converters\";\n ScryptedInterfaceProperty[\"binaryState\"] = \"binaryState\";\n ScryptedInterfaceProperty[\"tampered\"] = \"tampered\";\n ScryptedInterfaceProperty[\"sleeping\"] = \"sleeping\";\n ScryptedInterfaceProperty[\"powerDetected\"] = \"powerDetected\";\n ScryptedInterfaceProperty[\"audioDetected\"] = \"audioDetected\";\n ScryptedInterfaceProperty[\"motionDetected\"] = \"motionDetected\";\n ScryptedInterfaceProperty[\"ambientLight\"] = \"ambientLight\";\n ScryptedInterfaceProperty[\"occupied\"] = \"occupied\";\n ScryptedInterfaceProperty[\"flooded\"] = \"flooded\";\n ScryptedInterfaceProperty[\"ultraviolet\"] = \"ultraviolet\";\n ScryptedInterfaceProperty[\"luminance\"] = \"luminance\";\n ScryptedInterfaceProperty[\"position\"] = \"position\";\n ScryptedInterfaceProperty[\"securitySystemState\"] = \"securitySystemState\";\n ScryptedInterfaceProperty[\"pm10Density\"] = \"pm10Density\";\n ScryptedInterfaceProperty[\"pm25Density\"] = \"pm25Density\";\n ScryptedInterfaceProperty[\"vocDensity\"] = \"vocDensity\";\n ScryptedInterfaceProperty[\"noxDensity\"] = \"noxDensity\";\n ScryptedInterfaceProperty[\"co2ppm\"] = \"co2ppm\";\n ScryptedInterfaceProperty[\"airQuality\"] = \"airQuality\";\n ScryptedInterfaceProperty[\"airPurifierState\"] = \"airPurifierState\";\n ScryptedInterfaceProperty[\"filterChangeIndication\"] = \"filterChangeIndication\";\n ScryptedInterfaceProperty[\"filterLifeLevel\"] = \"filterLifeLevel\";\n ScryptedInterfaceProperty[\"humiditySetting\"] = \"humiditySetting\";\n ScryptedInterfaceProperty[\"fan\"] = \"fan\";\n ScryptedInterfaceProperty[\"applicationInfo\"] = \"applicationInfo\";\n ScryptedInterfaceProperty[\"systemDevice\"] = \"systemDevice\";\n})(ScryptedInterfaceProperty || (exports.ScryptedInterfaceProperty = ScryptedInterfaceProperty = {}));\nvar ScryptedInterfaceMethod;\n(function (ScryptedInterfaceMethod) {\n ScryptedInterfaceMethod[\"listen\"] = \"listen\";\n ScryptedInterfaceMethod[\"probe\"] = \"probe\";\n ScryptedInterfaceMethod[\"setMixins\"] = \"setMixins\";\n ScryptedInterfaceMethod[\"setName\"] = \"setName\";\n ScryptedInterfaceMethod[\"setRoom\"] = \"setRoom\";\n ScryptedInterfaceMethod[\"setType\"] = \"setType\";\n ScryptedInterfaceMethod[\"getPluginJson\"] = \"getPluginJson\";\n ScryptedInterfaceMethod[\"turnOff\"] = \"turnOff\";\n ScryptedInterfaceMethod[\"turnOn\"] = \"turnOn\";\n ScryptedInterfaceMethod[\"setBrightness\"] = \"setBrightness\";\n ScryptedInterfaceMethod[\"getTemperatureMaxK\"] = \"getTemperatureMaxK\";\n ScryptedInterfaceMethod[\"getTemperatureMinK\"] = \"getTemperatureMinK\";\n ScryptedInterfaceMethod[\"setColorTemperature\"] = \"setColorTemperature\";\n ScryptedInterfaceMethod[\"setRgb\"] = \"setRgb\";\n ScryptedInterfaceMethod[\"setHsv\"] = \"setHsv\";\n ScryptedInterfaceMethod[\"pressButton\"] = \"pressButton\";\n ScryptedInterfaceMethod[\"sendNotification\"] = \"sendNotification\";\n ScryptedInterfaceMethod[\"start\"] = \"start\";\n ScryptedInterfaceMethod[\"stop\"] = \"stop\";\n ScryptedInterfaceMethod[\"pause\"] = \"pause\";\n ScryptedInterfaceMethod[\"resume\"] = \"resume\";\n ScryptedInterfaceMethod[\"dock\"] = \"dock\";\n ScryptedInterfaceMethod[\"setTemperature\"] = \"setTemperature\";\n ScryptedInterfaceMethod[\"setTemperatureUnit\"] = \"setTemperatureUnit\";\n ScryptedInterfaceMethod[\"getPictureOptions\"] = \"getPictureOptions\";\n ScryptedInterfaceMethod[\"takePicture\"] = \"takePicture\";\n ScryptedInterfaceMethod[\"getAudioStream\"] = \"getAudioStream\";\n ScryptedInterfaceMethod[\"setAudioVolumes\"] = \"setAudioVolumes\";\n ScryptedInterfaceMethod[\"startDisplay\"] = \"startDisplay\";\n ScryptedInterfaceMethod[\"stopDisplay\"] = \"stopDisplay\";\n ScryptedInterfaceMethod[\"getVideoStream\"] = \"getVideoStream\";\n ScryptedInterfaceMethod[\"getVideoStreamOptions\"] = \"getVideoStreamOptions\";\n ScryptedInterfaceMethod[\"getPrivacyMasks\"] = \"getPrivacyMasks\";\n ScryptedInterfaceMethod[\"setPrivacyMasks\"] = \"setPrivacyMasks\";\n ScryptedInterfaceMethod[\"getVideoTextOverlays\"] = \"getVideoTextOverlays\";\n ScryptedInterfaceMethod[\"setVideoTextOverlay\"] = \"setVideoTextOverlay\";\n ScryptedInterfaceMethod[\"getRecordingStream\"] = \"getRecordingStream\";\n ScryptedInterfaceMethod[\"getRecordingStreamCurrentTime\"] = \"getRecordingStreamCurrentTime\";\n ScryptedInterfaceMethod[\"getRecordingStreamOptions\"] = \"getRecordingStreamOptions\";\n ScryptedInterfaceMethod[\"getRecordingStreamThumbnail\"] = \"getRecordingStreamThumbnail\";\n ScryptedInterfaceMethod[\"deleteRecordingStream\"] = \"deleteRecordingStream\";\n ScryptedInterfaceMethod[\"setRecordingActive\"] = \"setRecordingActive\";\n ScryptedInterfaceMethod[\"ptzCommand\"] = \"ptzCommand\";\n ScryptedInterfaceMethod[\"getRecordedEvents\"] = \"getRecordedEvents\";\n ScryptedInterfaceMethod[\"getVideoClip\"] = \"getVideoClip\";\n ScryptedInterfaceMethod[\"getVideoClips\"] = \"getVideoClips\";\n ScryptedInterfaceMethod[\"getVideoClipThumbnail\"] = \"getVideoClipThumbnail\";\n ScryptedInterfaceMethod[\"removeVideoClips\"] = \"removeVideoClips\";\n ScryptedInterfaceMethod[\"setVideoStreamOptions\"] = \"setVideoStreamOptions\";\n ScryptedInterfaceMethod[\"startIntercom\"] = \"startIntercom\";\n ScryptedInterfaceMethod[\"stopIntercom\"] = \"stopIntercom\";\n ScryptedInterfaceMethod[\"lock\"] = \"lock\";\n ScryptedInterfaceMethod[\"unlock\"] = \"unlock\";\n ScryptedInterfaceMethod[\"addPassword\"] = \"addPassword\";\n ScryptedInterfaceMethod[\"getPasswords\"] = \"getPasswords\";\n ScryptedInterfaceMethod[\"removePassword\"] = \"removePassword\";\n ScryptedInterfaceMethod[\"activate\"] = \"activate\";\n ScryptedInterfaceMethod[\"deactivate\"] = \"deactivate\";\n ScryptedInterfaceMethod[\"isReversible\"] = \"isReversible\";\n ScryptedInterfaceMethod[\"closeEntry\"] = \"closeEntry\";\n ScryptedInterfaceMethod[\"openEntry\"] = \"openEntry\";\n ScryptedInterfaceMethod[\"getDevice\"] = \"getDevice\";\n ScryptedInterfaceMethod[\"releaseDevice\"] = \"releaseDevice\";\n ScryptedInterfaceMethod[\"adoptDevice\"] = \"adoptDevice\";\n ScryptedInterfaceMethod[\"discoverDevices\"] = \"discoverDevices\";\n ScryptedInterfaceMethod[\"createDevice\"] = \"createDevice\";\n ScryptedInterfaceMethod[\"getCreateDeviceSettings\"] = \"getCreateDeviceSettings\";\n ScryptedInterfaceMethod[\"reboot\"] = \"reboot\";\n ScryptedInterfaceMethod[\"getRefreshFrequency\"] = \"getRefreshFrequency\";\n ScryptedInterfaceMethod[\"refresh\"] = \"refresh\";\n ScryptedInterfaceMethod[\"getMediaStatus\"] = \"getMediaStatus\";\n ScryptedInterfaceMethod[\"load\"] = \"load\";\n ScryptedInterfaceMethod[\"seek\"] = \"seek\";\n ScryptedInterfaceMethod[\"skipNext\"] = \"skipNext\";\n ScryptedInterfaceMethod[\"skipPrevious\"] = \"skipPrevious\";\n ScryptedInterfaceMethod[\"convert\"] = \"convert\";\n ScryptedInterfaceMethod[\"convertMedia\"] = \"convertMedia\";\n ScryptedInterfaceMethod[\"getSettings\"] = \"getSettings\";\n ScryptedInterfaceMethod[\"putSetting\"] = \"putSetting\";\n ScryptedInterfaceMethod[\"armSecuritySystem\"] = \"armSecuritySystem\";\n ScryptedInterfaceMethod[\"disarmSecuritySystem\"] = \"disarmSecuritySystem\";\n ScryptedInterfaceMethod[\"setAirPurifierState\"] = \"setAirPurifierState\";\n ScryptedInterfaceMethod[\"getReadmeMarkdown\"] = \"getReadmeMarkdown\";\n ScryptedInterfaceMethod[\"getOauthUrl\"] = \"getOauthUrl\";\n ScryptedInterfaceMethod[\"onOauthCallback\"] = \"onOauthCallback\";\n ScryptedInterfaceMethod[\"canMixin\"] = \"canMixin\";\n ScryptedInterfaceMethod[\"getMixin\"] = \"getMixin\";\n ScryptedInterfaceMethod[\"releaseMixin\"] = \"releaseMixin\";\n ScryptedInterfaceMethod[\"onRequest\"] = \"onRequest\";\n ScryptedInterfaceMethod[\"onConnection\"] = \"onConnection\";\n ScryptedInterfaceMethod[\"onPush\"] = \"onPush\";\n ScryptedInterfaceMethod[\"run\"] = \"run\";\n ScryptedInterfaceMethod[\"eval\"] = \"eval\";\n ScryptedInterfaceMethod[\"loadScripts\"] = \"loadScripts\";\n ScryptedInterfaceMethod[\"saveScript\"] = \"saveScript\";\n ScryptedInterfaceMethod[\"forkInterface\"] = \"forkInterface\";\n ScryptedInterfaceMethod[\"trackObjects\"] = \"trackObjects\";\n ScryptedInterfaceMethod[\"getDetectionInput\"] = \"getDetectionInput\";\n ScryptedInterfaceMethod[\"getObjectTypes\"] = \"getObjectTypes\";\n ScryptedInterfaceMethod[\"detectObjects\"] = \"detectObjects\";\n ScryptedInterfaceMethod[\"generateObjectDetections\"] = \"generateObjectDetections\";\n ScryptedInterfaceMethod[\"getDetectionModel\"] = \"getDetectionModel\";\n ScryptedInterfaceMethod[\"setHumidity\"] = \"setHumidity\";\n ScryptedInterfaceMethod[\"setFan\"] = \"setFan\";\n ScryptedInterfaceMethod[\"startRTCSignalingSession\"] = \"startRTCSignalingSession\";\n ScryptedInterfaceMethod[\"createRTCSignalingSession\"] = \"createRTCSignalingSession\";\n ScryptedInterfaceMethod[\"getScryptedUserAccessControl\"] = \"getScryptedUserAccessControl\";\n ScryptedInterfaceMethod[\"generateVideoFrames\"] = \"generateVideoFrames\";\n ScryptedInterfaceMethod[\"connectStream\"] = \"connectStream\";\n ScryptedInterfaceMethod[\"getTTYSettings\"] = \"getTTYSettings\";\n})(ScryptedInterfaceMethod || (exports.ScryptedInterfaceMethod = ScryptedInterfaceMethod = {}));\nexports.ScryptedInterfaceDescriptors = {\n \"ScryptedDevice\": {\n \"name\": \"ScryptedDevice\",\n \"methods\": [\n \"listen\",\n \"probe\",\n \"setMixins\",\n \"setName\",\n \"setRoom\",\n \"setType\"\n ],\n \"properties\": [\n \"id\",\n \"info\",\n \"interfaces\",\n \"mixins\",\n \"name\",\n \"nativeId\",\n \"pluginId\",\n \"providedInterfaces\",\n \"providedName\",\n \"providedRoom\",\n \"providedType\",\n \"providerId\",\n \"room\",\n \"type\"\n ]\n },\n \"ScryptedPlugin\": {\n \"name\": \"ScryptedPlugin\",\n \"methods\": [\n \"getPluginJson\"\n ],\n \"properties\": []\n },\n \"ScryptedPluginRuntime\": {\n \"name\": \"ScryptedPluginRuntime\",\n \"methods\": [],\n \"properties\": [\n \"scryptedRuntimeArguments\"\n ]\n },\n \"OnOff\": {\n \"name\": \"OnOff\",\n \"methods\": [\n \"turnOff\",\n \"turnOn\"\n ],\n \"properties\": [\n \"on\"\n ]\n },\n \"Brightness\": {\n \"name\": \"Brightness\",\n \"methods\": [\n \"setBrightness\"\n ],\n \"properties\": [\n \"brightness\"\n ]\n },\n \"ColorSettingTemperature\": {\n \"name\": \"ColorSettingTemperature\",\n \"methods\": [\n \"getTemperatureMaxK\",\n \"getTemperatureMinK\",\n \"setColorTemperature\"\n ],\n \"properties\": [\n \"colorTemperature\"\n ]\n },\n \"ColorSettingRgb\": {\n \"name\": \"ColorSettingRgb\",\n \"methods\": [\n \"setRgb\"\n ],\n \"properties\": [\n \"rgb\"\n ]\n },\n \"ColorSettingHsv\": {\n \"name\": \"ColorSettingHsv\",\n \"methods\": [\n \"setHsv\"\n ],\n \"properties\": [\n \"hsv\"\n ]\n },\n \"Buttons\": {\n \"name\": \"Buttons\",\n \"methods\": [],\n \"properties\": [\n \"buttons\"\n ]\n },\n \"PressButtons\": {\n \"name\": \"PressButtons\",\n \"methods\": [\n \"pressButton\"\n ],\n \"properties\": []\n },\n \"Sensors\": {\n \"name\": \"Sensors\",\n \"methods\": [],\n \"properties\": [\n \"sensors\"\n ]\n },\n \"Notifier\": {\n \"name\": \"Notifier\",\n \"methods\": [\n \"sendNotification\"\n ],\n \"properties\": []\n },\n \"StartStop\": {\n \"name\": \"StartStop\",\n \"methods\": [\n \"start\",\n \"stop\"\n ],\n \"properties\": [\n \"running\"\n ]\n },\n \"Pause\": {\n \"name\": \"Pause\",\n \"methods\": [\n \"pause\",\n \"resume\"\n ],\n \"properties\": [\n \"paused\"\n ]\n },\n \"Dock\": {\n \"name\": \"Dock\",\n \"methods\": [\n \"dock\"\n ],\n \"properties\": [\n \"docked\"\n ]\n },\n \"TemperatureSetting\": {\n \"name\": \"TemperatureSetting\",\n \"methods\": [\n \"setTemperature\"\n ],\n \"properties\": [\n \"temperatureSetting\"\n ]\n },\n \"Thermometer\": {\n \"name\": \"Thermometer\",\n \"methods\": [\n \"setTemperatureUnit\"\n ],\n \"properties\": [\n \"temperature\",\n \"temperatureUnit\"\n ]\n },\n \"HumiditySensor\": {\n \"name\": \"HumiditySensor\",\n \"methods\": [],\n \"properties\": [\n \"humidity\"\n ]\n },\n \"Camera\": {\n \"name\": \"Camera\",\n \"methods\": [\n \"getPictureOptions\",\n \"takePicture\"\n ],\n \"properties\": []\n },\n \"Microphone\": {\n \"name\": \"Microphone\",\n \"methods\": [\n \"getAudioStream\"\n ],\n \"properties\": []\n },\n \"AudioVolumeControl\": {\n \"name\": \"AudioVolumeControl\",\n \"methods\": [\n \"setAudioVolumes\"\n ],\n \"properties\": [\n \"audioVolumes\"\n ]\n },\n \"Display\": {\n \"name\": \"Display\",\n \"methods\": [\n \"startDisplay\",\n \"stopDisplay\"\n ],\n \"properties\": []\n },\n \"VideoCamera\": {\n \"name\": \"VideoCamera\",\n \"methods\": [\n \"getVideoStream\",\n \"getVideoStreamOptions\"\n ],\n \"properties\": []\n },\n \"VideoCameraMask\": {\n \"name\": \"VideoCameraMask\",\n \"methods\": [\n \"getPrivacyMasks\",\n \"setPrivacyMasks\"\n ],\n \"properties\": []\n },\n \"VideoTextOverlays\": {\n \"name\": \"VideoTextOverlays\",\n \"methods\": [\n \"getVideoTextOverlays\",\n \"setVideoTextOverlay\"\n ],\n \"properties\": []\n },\n \"VideoRecorder\": {\n \"name\": \"VideoRecorder\",\n \"methods\": [\n \"getRecordingStream\",\n \"getRecordingStreamCurrentTime\",\n \"getRecordingStreamOptions\",\n \"getRecordingStreamThumbnail\"\n ],\n \"properties\": [\n \"recordingActive\"\n ]\n },\n \"VideoRecorderManagement\": {\n \"name\": \"VideoRecorderManagement\",\n \"methods\": [\n \"deleteRecordingStream\",\n \"setRecordingActive\"\n ],\n \"properties\": []\n },\n \"PanTiltZoom\": {\n \"name\": \"PanTiltZoom\",\n \"methods\": [\n \"ptzCommand\"\n ],\n \"properties\": [\n \"ptzCapabilities\"\n ]\n },\n \"EventRecorder\": {\n \"name\": \"EventRecorder\",\n \"methods\": [\n \"getRecordedEvents\"\n ],\n \"properties\": []\n },\n \"VideoClips\": {\n \"name\": \"VideoClips\",\n \"methods\": [\n \"getVideoClip\",\n \"getVideoClips\",\n \"getVideoClipThumbnail\",\n \"removeVideoClips\"\n ],\n \"properties\": []\n },\n \"VideoCameraConfiguration\": {\n \"name\": \"VideoCameraConfiguration\",\n \"methods\": [\n \"setVideoStreamOptions\"\n ],\n \"properties\": []\n },\n \"Intercom\": {\n \"name\": \"Intercom\",\n \"methods\": [\n \"startIntercom\",\n \"stopIntercom\"\n ],\n \"properties\": []\n },\n \"Lock\": {\n \"name\": \"Lock\",\n \"methods\": [\n \"lock\",\n \"unlock\"\n ],\n \"properties\": [\n \"lockState\"\n ]\n },\n \"PasswordStore\": {\n \"name\": \"PasswordStore\",\n \"methods\": [\n \"addPassword\",\n \"getPasswords\",\n \"removePassword\"\n ],\n \"properties\": []\n },\n \"Scene\": {\n \"name\": \"Scene\",\n \"methods\": [\n \"activate\",\n \"deactivate\",\n \"isReversible\"\n ],\n \"properties\": []\n },\n \"Entry\": {\n \"name\": \"Entry\",\n \"methods\": [\n \"closeEntry\",\n \"openEntry\"\n ],\n \"properties\": []\n },\n \"EntrySensor\": {\n \"name\": \"EntrySensor\",\n \"methods\": [],\n \"properties\": [\n \"entryOpen\"\n ]\n },\n \"DeviceProvider\": {\n \"name\": \"DeviceProvider\",\n \"methods\": [\n \"getDevice\",\n \"releaseDevice\"\n ],\n \"properties\": []\n },\n \"DeviceDiscovery\": {\n \"name\": \"DeviceDiscovery\",\n \"methods\": [\n \"adoptDevice\",\n \"discoverDevices\"\n ],\n \"properties\": []\n },\n \"DeviceCreator\": {\n \"name\": \"DeviceCreator\",\n \"methods\": [\n \"createDevice\",\n \"getCreateDeviceSettings\"\n ],\n \"properties\": []\n },\n \"Battery\": {\n \"name\": \"Battery\",\n \"methods\": [],\n \"properties\": [\n \"batteryLevel\"\n ]\n },\n \"Charger\": {\n \"name\": \"Charger\",\n \"methods\": [],\n \"properties\": [\n \"chargeState\"\n ]\n },\n \"Reboot\": {\n \"name\": \"Reboot\",\n \"methods\": [\n \"reboot\"\n ],\n \"properties\": []\n },\n \"Refresh\": {\n \"name\": \"Refresh\",\n \"methods\": [\n \"getRefreshFrequency\",\n \"refresh\"\n ],\n \"properties\": []\n },\n \"MediaPlayer\": {\n \"name\": \"MediaPlayer\",\n \"methods\": [\n \"getMediaStatus\",\n \"load\",\n \"seek\",\n \"skipNext\",\n \"skipPrevious\"\n ],\n \"properties\": []\n },\n \"Online\": {\n \"name\": \"Online\",\n \"methods\": [],\n \"properties\": [\n \"online\"\n ]\n },\n \"BufferConverter\": {\n \"name\": \"BufferConverter\",\n \"methods\": [\n \"convert\"\n ],\n \"properties\": [\n \"fromMimeType\",\n \"toMimeType\"\n ]\n },\n \"MediaConverter\": {\n \"name\": \"MediaConverter\",\n \"methods\": [\n \"convertMedia\"\n ],\n \"properties\": [\n \"converters\"\n ]\n },\n \"Settings\": {\n \"name\": \"Settings\",\n \"methods\": [\n \"getSettings\",\n \"putSetting\"\n ],\n \"properties\": []\n },\n \"BinarySensor\": {\n \"name\": \"BinarySensor\",\n \"methods\": [],\n \"properties\": [\n \"binaryState\"\n ]\n },\n \"TamperSensor\": {\n \"name\": \"TamperSensor\",\n \"methods\": [],\n \"properties\": [\n \"tampered\"\n ]\n },\n \"Sleep\": {\n \"name\": \"Sleep\",\n \"methods\": [],\n \"properties\": [\n \"sleeping\"\n ]\n },\n \"PowerSensor\": {\n \"name\": \"PowerSensor\",\n \"methods\": [],\n \"properties\": [\n \"powerDetected\"\n ]\n },\n \"AudioSensor\": {\n \"name\": \"AudioSensor\",\n \"methods\": [],\n \"properties\": [\n \"audioDetected\"\n ]\n },\n \"MotionSensor\": {\n \"name\": \"MotionSensor\",\n \"methods\": [],\n \"properties\": [\n \"motionDetected\"\n ]\n },\n \"AmbientLightSensor\": {\n \"name\": \"AmbientLightSensor\",\n \"methods\": [],\n \"properties\": [\n \"ambientLight\"\n ]\n },\n \"OccupancySensor\": {\n \"name\": \"OccupancySensor\",\n \"methods\": [],\n \"properties\": [\n \"occupied\"\n ]\n },\n \"FloodSensor\": {\n \"name\": \"FloodSensor\",\n \"methods\": [],\n \"properties\": [\n \"flooded\"\n ]\n },\n \"UltravioletSensor\": {\n \"name\": \"UltravioletSensor\",\n \"methods\": [],\n \"properties\": [\n \"ultraviolet\"\n ]\n },\n \"LuminanceSensor\": {\n \"name\": \"LuminanceSensor\",\n \"methods\": [],\n \"properties\": [\n \"luminance\"\n ]\n },\n \"PositionSensor\": {\n \"name\": \"PositionSensor\",\n \"methods\": [],\n \"properties\": [\n \"position\"\n ]\n },\n \"SecuritySystem\": {\n \"name\": \"SecuritySystem\",\n \"methods\": [\n \"armSecuritySystem\",\n \"disarmSecuritySystem\"\n ],\n \"properties\": [\n \"securitySystemState\"\n ]\n },\n \"PM10Sensor\": {\n \"name\": \"PM10Sensor\",\n \"methods\": [],\n \"properties\": [\n \"pm10Density\"\n ]\n },\n \"PM25Sensor\": {\n \"name\": \"PM25Sensor\",\n \"methods\": [],\n \"properties\": [\n \"pm25Density\"\n ]\n },\n \"VOCSensor\": {\n \"name\": \"VOCSensor\",\n \"methods\": [],\n \"properties\": [\n \"vocDensity\"\n ]\n },\n \"NOXSensor\": {\n \"name\": \"NOXSensor\",\n \"methods\": [],\n \"properties\": [\n \"noxDensity\"\n ]\n },\n \"CO2Sensor\": {\n \"name\": \"CO2Sensor\",\n \"methods\": [],\n \"properties\": [\n \"co2ppm\"\n ]\n },\n \"AirQualitySensor\": {\n \"name\": \"AirQualitySensor\",\n \"methods\": [],\n \"properties\": [\n \"airQuality\"\n ]\n },\n \"AirPurifier\": {\n \"name\": \"AirPurifier\",\n \"methods\": [\n \"setAirPurifierState\"\n ],\n \"properties\": [\n \"airPurifierState\"\n ]\n },\n \"FilterMaintenance\": {\n \"name\": \"FilterMaintenance\",\n \"methods\": [],\n \"properties\": [\n \"filterChangeIndication\",\n \"filterLifeLevel\"\n ]\n },\n \"Readme\": {\n \"name\": \"Readme\",\n \"methods\": [\n \"getReadmeMarkdown\"\n ],\n \"properties\": []\n },\n \"OauthClient\": {\n \"name\": \"OauthClient\",\n \"methods\": [\n \"getOauthUrl\",\n \"onOauthCallback\"\n ],\n \"properties\": []\n },\n \"MixinProvider\": {\n \"name\": \"MixinProvider\",\n \"methods\": [\n \"canMixin\",\n \"getMixin\",\n \"releaseMixin\"\n ],\n \"properties\": []\n },\n \"HttpRequestHandler\": {\n \"name\": \"HttpRequestHandler\",\n \"methods\": [\n \"onRequest\"\n ],\n \"properties\": []\n },\n \"EngineIOHandler\": {\n \"name\": \"EngineIOHandler\",\n \"methods\": [\n \"onConnection\"\n ],\n \"properties\": []\n },\n \"PushHandler\": {\n \"name\": \"PushHandler\",\n \"methods\": [\n \"onPush\"\n ],\n \"properties\": []\n },\n \"Program\": {\n \"name\": \"Program\",\n \"methods\": [\n \"run\"\n ],\n \"properties\": []\n },\n \"Scriptable\": {\n \"name\": \"Scriptable\",\n \"methods\": [\n \"eval\",\n \"loadScripts\",\n \"saveScript\"\n ],\n \"properties\": []\n },\n \"ClusterForkInterface\": {\n \"name\": \"ClusterForkInterface\",\n \"methods\": [\n \"forkInterface\"\n ],\n \"properties\": []\n },\n \"ObjectTracker\": {\n \"name\": \"ObjectTracker\",\n \"methods\": [\n \"trackObjects\"\n ],\n \"properties\": []\n },\n \"ObjectDetector\": {\n \"name\": \"ObjectDetector\",\n \"methods\": [\n \"getDetectionInput\",\n \"getObjectTypes\"\n ],\n \"properties\": []\n },\n \"ObjectDetection\": {\n \"name\": \"ObjectDetection\",\n \"methods\": [\n \"detectObjects\",\n \"generateObjectDetections\",\n \"getDetectionModel\"\n ],\n \"properties\": []\n },\n \"ObjectDetectionPreview\": {\n \"name\": \"ObjectDetectionPreview\",\n \"methods\": [],\n \"properties\": []\n },\n \"ObjectDetectionGenerator\": {\n \"name\": \"ObjectDetectionGenerator\",\n \"methods\": [],\n \"properties\": []\n },\n \"HumiditySetting\": {\n \"name\": \"HumiditySetting\",\n \"methods\": [\n \"setHumidity\"\n ],\n \"properties\": [\n \"humiditySetting\"\n ]\n },\n \"Fan\": {\n \"name\": \"Fan\",\n \"methods\": [\n \"setFan\"\n ],\n \"properties\": [\n \"fan\"\n ]\n },\n \"RTCSignalingChannel\": {\n \"name\": \"RTCSignalingChannel\",\n \"methods\": [\n \"startRTCSignalingSession\"\n ],\n \"properties\": []\n },\n \"RTCSignalingClient\": {\n \"name\": \"RTCSignalingClient\",\n \"methods\": [\n \"createRTCSignalingSession\"\n ],\n \"properties\": []\n },\n \"LauncherApplication\": {\n \"name\": \"LauncherApplication\",\n \"methods\": [],\n \"properties\": [\n \"applicationInfo\"\n ]\n },\n \"ScryptedUser\": {\n \"name\": \"ScryptedUser\",\n \"methods\": [\n \"getScryptedUserAccessControl\"\n ],\n \"properties\": []\n },\n \"VideoFrameGenerator\": {\n \"name\": \"VideoFrameGenerator\",\n \"methods\": [\n \"generateVideoFrames\"\n ],\n \"properties\": []\n },\n \"StreamService\": {\n \"name\": \"StreamService\",\n \"methods\": [\n \"connectStream\"\n ],\n \"properties\": []\n },\n \"TTY\": {\n \"name\": \"TTY\",\n \"methods\": [],\n \"properties\": []\n },\n \"TTYSettings\": {\n \"name\": \"TTYSettings\",\n \"methods\": [\n \"getTTYSettings\"\n ],\n \"properties\": []\n },\n \"ScryptedSystemDevice\": {\n \"name\": \"ScryptedSystemDevice\",\n \"methods\": [],\n \"properties\": [\n \"systemDevice\"\n ]\n },\n \"ScryptedDeviceCreator\": {\n \"name\": \"ScryptedDeviceCreator\",\n \"methods\": [],\n \"properties\": []\n },\n \"ScryptedSettings\": {\n \"name\": \"ScryptedSettings\",\n \"methods\": [],\n \"properties\": []\n }\n};\n/**\n * @category Core Reference\n */\nvar ScryptedDeviceType;\n(function (ScryptedDeviceType) {\n /**\n * @deprecated\n */\n ScryptedDeviceType[\"Builtin\"] = \"Builtin\";\n /**\n * Internal devices will not show up in device lists unless explicitly searched.\n */\n ScryptedDeviceType[\"Internal\"] = \"Internal\";\n ScryptedDeviceType[\"Camera\"] = \"Camera\";\n ScryptedDeviceType[\"Fan\"] = \"Fan\";\n ScryptedDeviceType[\"Light\"] = \"Light\";\n ScryptedDeviceType[\"Switch\"] = \"Switch\";\n ScryptedDeviceType[\"Outlet\"] = \"Outlet\";\n ScryptedDeviceType[\"Sensor\"] = \"Sensor\";\n ScryptedDeviceType[\"Scene\"] = \"Scene\";\n ScryptedDeviceType[\"Program\"] = \"Program\";\n ScryptedDeviceType[\"Automation\"] = \"Automation\";\n ScryptedDeviceType[\"Vacuum\"] = \"Vacuum\";\n ScryptedDeviceType[\"Notifier\"] = \"Notifier\";\n ScryptedDeviceType[\"Thermostat\"] = \"Thermostat\";\n ScryptedDeviceType[\"Lock\"] = \"Lock\";\n ScryptedDeviceType[\"PasswordControl\"] = \"PasswordControl\";\n /**\n * Displays have audio and video output.\n */\n ScryptedDeviceType[\"Display\"] = \"Display\";\n /**\n * Smart Displays have two way audio and video.\n */\n ScryptedDeviceType[\"SmartDisplay\"] = \"SmartDisplay\";\n ScryptedDeviceType[\"Speaker\"] = \"Speaker\";\n /**\n * Smart Speakers have two way audio.\n */\n ScryptedDeviceType[\"SmartSpeaker\"] = \"SmartSpeaker\";\n ScryptedDeviceType[\"Event\"] = \"Event\";\n ScryptedDeviceType[\"Entry\"] = \"Entry\";\n ScryptedDeviceType[\"Garage\"] = \"Garage\";\n ScryptedDeviceType[\"DeviceProvider\"] = \"DeviceProvider\";\n ScryptedDeviceType[\"DataSource\"] = \"DataSource\";\n ScryptedDeviceType[\"API\"] = \"API\";\n ScryptedDeviceType[\"Doorbell\"] = \"Doorbell\";\n ScryptedDeviceType[\"Irrigation\"] = \"Irrigation\";\n ScryptedDeviceType[\"Valve\"] = \"Valve\";\n ScryptedDeviceType[\"Person\"] = \"Person\";\n ScryptedDeviceType[\"SecuritySystem\"] = \"SecuritySystem\";\n ScryptedDeviceType[\"WindowCovering\"] = \"WindowCovering\";\n ScryptedDeviceType[\"Siren\"] = \"Siren\";\n ScryptedDeviceType[\"AirPurifier\"] = \"AirPurifier\";\n ScryptedDeviceType[\"Internet\"] = \"Internet\";\n ScryptedDeviceType[\"Network\"] = \"Network\";\n ScryptedDeviceType[\"Bridge\"] = \"Bridge\";\n ScryptedDeviceType[\"Unknown\"] = \"Unknown\";\n})(ScryptedDeviceType || (exports.ScryptedDeviceType = ScryptedDeviceType = {}));\nvar HumidityMode;\n(function (HumidityMode) {\n HumidityMode[\"Humidify\"] = \"Humidify\";\n HumidityMode[\"Dehumidify\"] = \"Dehumidify\";\n HumidityMode[\"Auto\"] = \"Auto\";\n HumidityMode[\"Off\"] = \"Off\";\n})(HumidityMode || (exports.HumidityMode = HumidityMode = {}));\nvar FanMode;\n(function (FanMode) {\n FanMode[\"Auto\"] = \"Auto\";\n FanMode[\"Manual\"] = \"Manual\";\n})(FanMode || (exports.FanMode = FanMode = {}));\nvar TemperatureUnit;\n(function (TemperatureUnit) {\n TemperatureUnit[\"C\"] = \"C\";\n TemperatureUnit[\"F\"] = \"F\";\n})(TemperatureUnit || (exports.TemperatureUnit = TemperatureUnit = {}));\nvar ThermostatMode;\n(function (ThermostatMode) {\n ThermostatMode[\"Off\"] = \"Off\";\n ThermostatMode[\"Cool\"] = \"Cool\";\n ThermostatMode[\"Heat\"] = \"Heat\";\n ThermostatMode[\"HeatCool\"] = \"HeatCool\";\n ThermostatMode[\"Auto\"] = \"Auto\";\n ThermostatMode[\"FanOnly\"] = \"FanOnly\";\n ThermostatMode[\"Purifier\"] = \"Purifier\";\n ThermostatMode[\"Eco\"] = \"Eco\";\n ThermostatMode[\"Dry\"] = \"Dry\";\n ThermostatMode[\"On\"] = \"On\";\n})(ThermostatMode || (exports.ThermostatMode = ThermostatMode = {}));\nvar PanTiltZoomMovement;\n(function (PanTiltZoomMovement) {\n PanTiltZoomMovement[\"Absolute\"] = \"Absolute\";\n PanTiltZoomMovement[\"Relative\"] = \"Relative\";\n PanTiltZoomMovement[\"Continuous\"] = \"Continuous\";\n PanTiltZoomMovement[\"Preset\"] = \"Preset\";\n PanTiltZoomMovement[\"Home\"] = \"Home\";\n})(PanTiltZoomMovement || (exports.PanTiltZoomMovement = PanTiltZoomMovement = {}));\nvar LockState;\n(function (LockState) {\n LockState[\"Locked\"] = \"Locked\";\n LockState[\"Unlocked\"] = \"Unlocked\";\n LockState[\"Jammed\"] = \"Jammed\";\n})(LockState || (exports.LockState = LockState = {}));\nvar ChargeState;\n(function (ChargeState) {\n ChargeState[\"Trickle\"] = \"trickle\";\n ChargeState[\"Charging\"] = \"charging\";\n ChargeState[\"NotCharging\"] = \"not-charging\";\n})(ChargeState || (exports.ChargeState = ChargeState = {}));\nvar AirPurifierStatus;\n(function (AirPurifierStatus) {\n AirPurifierStatus[\"Inactive\"] = \"Inactive\";\n AirPurifierStatus[\"Idle\"] = \"Idle\";\n AirPurifierStatus[\"Active\"] = \"Active\";\n AirPurifierStatus[\"ActiveNightMode\"] = \"ActiveNightMode\";\n})(AirPurifierStatus || (exports.AirPurifierStatus = AirPurifierStatus = {}));\nvar AirPurifierMode;\n(function (AirPurifierMode) {\n AirPurifierMode[\"Manual\"] = \"Manual\";\n AirPurifierMode[\"Automatic\"] = \"Automatic\";\n})(AirPurifierMode || (exports.AirPurifierMode = AirPurifierMode = {}));\nvar AirQuality;\n(function (AirQuality) {\n AirQuality[\"Unknown\"] = \"Unknown\";\n AirQuality[\"Excellent\"] = \"Excellent\";\n AirQuality[\"Good\"] = \"Good\";\n AirQuality[\"Fair\"] = \"Fair\";\n AirQuality[\"Inferior\"] = \"Inferior\";\n AirQuality[\"Poor\"] = \"Poor\";\n})(AirQuality || (exports.AirQuality = AirQuality = {}));\nvar SecuritySystemMode;\n(function (SecuritySystemMode) {\n SecuritySystemMode[\"Disarmed\"] = \"Disarmed\";\n SecuritySystemMode[\"HomeArmed\"] = \"HomeArmed\";\n SecuritySystemMode[\"AwayArmed\"] = \"AwayArmed\";\n SecuritySystemMode[\"NightArmed\"] = \"NightArmed\";\n})(SecuritySystemMode || (exports.SecuritySystemMode = SecuritySystemMode = {}));\nvar SecuritySystemObstruction;\n(function (SecuritySystemObstruction) {\n SecuritySystemObstruction[\"Sensor\"] = \"Sensor\";\n SecuritySystemObstruction[\"Occupied\"] = \"Occupied\";\n SecuritySystemObstruction[\"Time\"] = \"Time\";\n SecuritySystemObstruction[\"Error\"] = \"Error\";\n})(SecuritySystemObstruction || (exports.SecuritySystemObstruction = SecuritySystemObstruction = {}));\nvar MediaPlayerState;\n(function (MediaPlayerState) {\n MediaPlayerState[\"Idle\"] = \"Idle\";\n MediaPlayerState[\"Playing\"] = \"Playing\";\n MediaPlayerState[\"Paused\"] = \"Paused\";\n MediaPlayerState[\"Buffering\"] = \"Buffering\";\n})(MediaPlayerState || (exports.MediaPlayerState = MediaPlayerState = {}));\nvar ScryptedInterface;\n(function (ScryptedInterface) {\n ScryptedInterface[\"ScryptedDevice\"] = \"ScryptedDevice\";\n ScryptedInterface[\"ScryptedPlugin\"] = \"ScryptedPlugin\";\n ScryptedInterface[\"ScryptedPluginRuntime\"] = \"ScryptedPluginRuntime\";\n ScryptedInterface[\"OnOff\"] = \"OnOff\";\n ScryptedInterface[\"Brightness\"] = \"Brightness\";\n ScryptedInterface[\"ColorSettingTemperature\"] = \"ColorSettingTemperature\";\n ScryptedInterface[\"ColorSettingRgb\"] = \"ColorSettingRgb\";\n ScryptedInterface[\"ColorSettingHsv\"] = \"ColorSettingHsv\";\n ScryptedInterface[\"Buttons\"] = \"Buttons\";\n ScryptedInterface[\"PressButtons\"] = \"PressButtons\";\n ScryptedInterface[\"Sensors\"] = \"Sensors\";\n ScryptedInterface[\"Notifier\"] = \"Notifier\";\n ScryptedInterface[\"StartStop\"] = \"StartStop\";\n ScryptedInterface[\"Pause\"] = \"Pause\";\n ScryptedInterface[\"Dock\"] = \"Dock\";\n ScryptedInterface[\"TemperatureSetting\"] = \"TemperatureSetting\";\n ScryptedInterface[\"Thermometer\"] = \"Thermometer\";\n ScryptedInterface[\"HumiditySensor\"] = \"HumiditySensor\";\n ScryptedInterface[\"Camera\"] = \"Camera\";\n ScryptedInterface[\"Microphone\"] = \"Microphone\";\n ScryptedInterface[\"AudioVolumeControl\"] = \"AudioVolumeControl\";\n ScryptedInterface[\"Display\"] = \"Display\";\n ScryptedInterface[\"VideoCamera\"] = \"VideoCamera\";\n ScryptedInterface[\"VideoCameraMask\"] = \"VideoCameraMask\";\n ScryptedInterface[\"VideoTextOverlays\"] = \"VideoTextOverlays\";\n ScryptedInterface[\"VideoRecorder\"] = \"VideoRecorder\";\n ScryptedInterface[\"VideoRecorderManagement\"] = \"VideoRecorderManagement\";\n ScryptedInterface[\"PanTiltZoom\"] = \"PanTiltZoom\";\n ScryptedInterface[\"EventRecorder\"] = \"EventRecorder\";\n ScryptedInterface[\"VideoClips\"] = \"VideoClips\";\n ScryptedInterface[\"VideoCameraConfiguration\"] = \"VideoCameraConfiguration\";\n ScryptedInterface[\"Intercom\"] = \"Intercom\";\n ScryptedInterface[\"Lock\"] = \"Lock\";\n ScryptedInterface[\"PasswordStore\"] = \"PasswordStore\";\n ScryptedInterface[\"Scene\"] = \"Scene\";\n ScryptedInterface[\"Entry\"] = \"Entry\";\n ScryptedInterface[\"EntrySensor\"] = \"EntrySensor\";\n ScryptedInterface[\"DeviceProvider\"] = \"DeviceProvider\";\n ScryptedInterface[\"DeviceDiscovery\"] = \"DeviceDiscovery\";\n ScryptedInterface[\"DeviceCreator\"] = \"DeviceCreator\";\n ScryptedInterface[\"Battery\"] = \"Battery\";\n ScryptedInterface[\"Charger\"] = \"Charger\";\n ScryptedInterface[\"Reboot\"] = \"Reboot\";\n ScryptedInterface[\"Refresh\"] = \"Refresh\";\n ScryptedInterface[\"MediaPlayer\"] = \"MediaPlayer\";\n ScryptedInterface[\"Online\"] = \"Online\";\n ScryptedInterface[\"BufferConverter\"] = \"BufferConverter\";\n ScryptedInterface[\"MediaConverter\"] = \"MediaConverter\";\n ScryptedInterface[\"Settings\"] = \"Settings\";\n ScryptedInterface[\"BinarySensor\"] = \"BinarySensor\";\n ScryptedInterface[\"TamperSensor\"] = \"TamperSensor\";\n ScryptedInterface[\"Sleep\"] = \"Sleep\";\n ScryptedInterface[\"PowerSensor\"] = \"PowerSensor\";\n ScryptedInterface[\"AudioSensor\"] = \"AudioSensor\";\n ScryptedInterface[\"MotionSensor\"] = \"MotionSensor\";\n ScryptedInterface[\"AmbientLightSensor\"] = \"AmbientLightSensor\";\n ScryptedInterface[\"OccupancySensor\"] = \"OccupancySensor\";\n ScryptedInterface[\"FloodSensor\"] = \"FloodSensor\";\n ScryptedInterface[\"UltravioletSensor\"] = \"UltravioletSensor\";\n ScryptedInterface[\"LuminanceSensor\"] = \"LuminanceSensor\";\n ScryptedInterface[\"PositionSensor\"] = \"PositionSensor\";\n ScryptedInterface[\"SecuritySystem\"] = \"SecuritySystem\";\n ScryptedInterface[\"PM10Sensor\"] = \"PM10Sensor\";\n ScryptedInterface[\"PM25Sensor\"] = \"PM25Sensor\";\n ScryptedInterface[\"VOCSensor\"] = \"VOCSensor\";\n ScryptedInterface[\"NOXSensor\"] = \"NOXSensor\";\n ScryptedInterface[\"CO2Sensor\"] = \"CO2Sensor\";\n ScryptedInterface[\"AirQualitySensor\"] = \"AirQualitySensor\";\n ScryptedInterface[\"AirPurifier\"] = \"AirPurifier\";\n ScryptedInterface[\"FilterMaintenance\"] = \"FilterMaintenance\";\n ScryptedInterface[\"Readme\"] = \"Readme\";\n ScryptedInterface[\"OauthClient\"] = \"OauthClient\";\n ScryptedInterface[\"MixinProvider\"] = \"MixinProvider\";\n ScryptedInterface[\"HttpRequestHandler\"] = \"HttpRequestHandler\";\n ScryptedInterface[\"EngineIOHandler\"] = \"EngineIOHandler\";\n ScryptedInterface[\"PushHandler\"] = \"PushHandler\";\n ScryptedInterface[\"Program\"] = \"Program\";\n ScryptedInterface[\"Scriptable\"] = \"Scriptable\";\n ScryptedInterface[\"ClusterForkInterface\"] = \"ClusterForkInterface\";\n ScryptedInterface[\"ObjectTracker\"] = \"ObjectTracker\";\n ScryptedInterface[\"ObjectDetector\"] = \"ObjectDetector\";\n ScryptedInterface[\"ObjectDetection\"] = \"ObjectDetection\";\n ScryptedInterface[\"ObjectDetectionPreview\"] = \"ObjectDetectionPreview\";\n ScryptedInterface[\"ObjectDetectionGenerator\"] = \"ObjectDetectionGenerator\";\n ScryptedInterface[\"HumiditySetting\"] = \"HumiditySetting\";\n ScryptedInterface[\"Fan\"] = \"Fan\";\n ScryptedInterface[\"RTCSignalingChannel\"] = \"RTCSignalingChannel\";\n ScryptedInterface[\"RTCSignalingClient\"] = \"RTCSignalingClient\";\n ScryptedInterface[\"LauncherApplication\"] = \"LauncherApplication\";\n ScryptedInterface[\"ScryptedUser\"] = \"ScryptedUser\";\n ScryptedInterface[\"VideoFrameGenerator\"] = \"VideoFrameGenerator\";\n ScryptedInterface[\"StreamService\"] = \"StreamService\";\n ScryptedInterface[\"TTY\"] = \"TTY\";\n ScryptedInterface[\"TTYSettings\"] = \"TTYSettings\";\n ScryptedInterface[\"ScryptedSystemDevice\"] = \"ScryptedSystemDevice\";\n ScryptedInterface[\"ScryptedDeviceCreator\"] = \"ScryptedDeviceCreator\";\n ScryptedInterface[\"ScryptedSettings\"] = \"ScryptedSettings\";\n})(ScryptedInterface || (exports.ScryptedInterface = ScryptedInterface = {}));\nvar ScryptedMimeTypes;\n(function (ScryptedMimeTypes) {\n ScryptedMimeTypes[\"Url\"] = \"text/x-uri\";\n ScryptedMimeTypes[\"InsecureLocalUrl\"] = \"text/x-insecure-local-uri\";\n ScryptedMimeTypes[\"LocalUrl\"] = \"text/x-local-uri\";\n ScryptedMimeTypes[\"ServerId\"] = \"text/x-server-id\";\n ScryptedMimeTypes[\"PushEndpoint\"] = \"text/x-push-endpoint\";\n ScryptedMimeTypes[\"SchemePrefix\"] = \"x-scrypted/x-scrypted-scheme-\";\n ScryptedMimeTypes[\"MediaStreamUrl\"] = \"text/x-media-url\";\n ScryptedMimeTypes[\"MediaObject\"] = \"x-scrypted/x-scrypted-media-object\";\n ScryptedMimeTypes[\"RequestMediaObject\"] = \"x-scrypted/x-scrypted-request-media-object\";\n ScryptedMimeTypes[\"RequestMediaStream\"] = \"x-scrypted/x-scrypted-request-stream\";\n ScryptedMimeTypes[\"MediaStreamFeedback\"] = \"x-scrypted/x-media-stream-feedback\";\n ScryptedMimeTypes[\"FFmpegInput\"] = \"x-scrypted/x-ffmpeg-input\";\n ScryptedMimeTypes[\"FFmpegTranscodeStream\"] = \"x-scrypted/x-ffmpeg-transcode-stream\";\n ScryptedMimeTypes[\"RTCSignalingChannel\"] = \"x-scrypted/x-scrypted-rtc-signaling-channel\";\n ScryptedMimeTypes[\"RTCSignalingSession\"] = \"x-scrypted/x-scrypted-rtc-signaling-session\";\n ScryptedMimeTypes[\"RTCConnectionManagement\"] = \"x-scrypted/x-scrypted-rtc-connection-management\";\n ScryptedMimeTypes[\"Image\"] = \"x-scrypted/x-scrypted-image\";\n})(ScryptedMimeTypes || (exports.ScryptedMimeTypes = ScryptedMimeTypes = {}));\n//# sourceMappingURL=index.js.map","import sdk, {\n ScryptedDeviceBase,\n Settings,\n Setting,\n HttpRequestHandler,\n HttpRequest,\n HttpResponse,\n ScryptedInterface,\n ScryptedDeviceType,\n ObjectsDetected,\n ObjectDetector,\n} from '@scrypted/sdk';\n\nconst { systemManager, deviceManager, mediaManager } = sdk;\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst LABELS = ['person', 'animal', 'face', 'vehicle', 'plate', 'package', 'discard'] as const;\ntype Label = typeof LABELS[number];\n\nconst CAPTURE_CLASSES = new Set(['person', 'cat', 'dog', 'animal', 'bird', 'face', 'vehicle', 'car', 'truck', 'bus', 'motorcycle', 'bicycle', 'plate', 'package']);\n\nconst RATE_OPTIONS = ['disabled', '1 per minute', '1 per 10 seconds', 'every detection'] as const;\ntype RateOption = typeof RATE_OPTIONS[number];\n\nconst RATE_MS: Record<RateOption, number> = {\n 'disabled': Infinity,\n '1 per minute': 60_000,\n '1 per 10 seconds': 10_000,\n 'every detection': 0,\n};\n\nconst MAX_CAPTURES = 2000;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface CaptureRecord {\n id: string;\n cameraId: string;\n cameraName: string;\n timestamp: number;\n detectedClass: string;\n score: number;\n boundingBox: number[]; // [x, y, w, h] in pixels\n inputDimensions: number[]; // [width, height]\n detectionId?: string;\n label?: Label; // set after review\n reviewed: boolean;\n}\n\n// ─── Plugin ───────────────────────────────────────────────────────────────────\n\nclass DetectionTrainer extends ScryptedDeviceBase implements Settings, HttpRequestHandler {\n // Map<cameraId, lastCaptureTimestamp>\n private lastCapture = new Map<string, number>();\n // Map<captureId, CaptureRecord>\n private captures = new Map<string, CaptureRecord>();\n // Map<captureId, jpegBuffer>\n private images = new Map<string, Buffer>();\n // Active event listeners\n private listeners: (() => void)[] = [];\n\n constructor(nativeId?: string) {\n super(nativeId);\n this.loadState();\n this.registerListeners();\n }\n\n // ── Persistence ──────────────────────────────────────────────────────────\n\n private loadState() {\n try {\n const raw = this.storage.getItem('captures');\n if (raw) {\n const arr: CaptureRecord[] = JSON.parse(raw);\n for (const r of arr) this.captures.set(r.id, r);\n this.console.log(`Loaded ${this.captures.size} captures from storage.`);\n }\n } catch (e) {\n this.console.warn('Could not load captures from storage:', e);\n }\n // images are stored as individual items\n for (const [id] of this.captures) {\n const raw = this.storage.getItem(`img:${id}`);\n if (raw) this.images.set(id, Buffer.from(raw, 'base64'));\n }\n }\n\n private saveCaptures() {\n this.storage.setItem('captures', JSON.stringify([...this.captures.values()]));\n }\n\n private saveImage(id: string, buf: Buffer) {\n this.storage.setItem(`img:${id}`, buf.toString('base64'));\n }\n\n private deleteCapture(id: string) {\n const old = this.storage.getItem(`img:${id}`);\n if (old) this.storage.removeItem(`img:${id}`);\n this.captures.delete(id);\n this.images.delete(id);\n this.saveCaptures();\n }\n\n // ── Settings ─────────────────────────────────────────────────────────────\n\n async getSettings(): Promise<Setting[]> {\n const cameras = Object.keys(systemManager.getSystemState())\n .map(id => systemManager.getDeviceById(id))\n .filter(d => d &&\n (d.type === ScryptedDeviceType.Camera || d.type === ScryptedDeviceType.Doorbell) &&\n d.interfaces?.includes(ScryptedInterface.ObjectDetector)\n );\n\n let uiUrl: string;\n try {\n const authPath = await sdk.endpointManager.getAuthenticatedPath();\n uiUrl = `${authPath}endpoint/scrypted-detection-trainer/public/`;\n } catch {\n uiUrl = '/endpoint/scrypted-detection-trainer/public/';\n }\n\n const settings: Setting[] = [\n {\n key: 'info',\n title: 'Detection Trainer',\n description: `${this.captures.size} captures stored (${[...this.captures.values()].filter(c => !c.reviewed).length} pending review, ${[...this.captures.values()].filter(c => c.reviewed && c.label !== 'discard').length} labeled).`,\n readonly: true,\n value: '',\n },\n {\n key: 'open_ui',\n title: 'Review UI',\n description: 'Open the detection review and labeling interface.',\n type: 'html',\n readonly: true,\n value: `<a href=\"${uiUrl}\" target=\"_blank\" style=\"display:inline-block;padding:8px 16px;background:#1a4d8a;color:#fff;border-radius:6px;text-decoration:none;font-size:13px;\">Open Review UI ↗</a>`,\n },\n ];\n\n for (const cam of cameras) {\n const key = `rate:${cam.id}`;\n settings.push({\n key,\n title: cam.name,\n group: 'Capture Rate per Camera',\n description: 'How often to capture detections from this camera.',\n value: this.storage.getItem(key) || '1 per minute',\n choices: [...RATE_OPTIONS],\n });\n }\n\n return settings;\n }\n\n async putSetting(key: string, value: string) {\n if (key === 'open_ui' || key === 'ui_link' || key === 'info') return;\n this.storage.setItem(key, value);\n if (key.startsWith('rate:')) {\n // Re-register listeners when rates change\n this.registerListeners();\n }\n }\n\n // ── Listeners ─────────────────────────────────────────────────────────────\n\n private registerListeners() {\n // Remove old listeners\n for (const remove of this.listeners) remove();\n this.listeners = [];\n\n const cameras = Object.keys(systemManager.getSystemState())\n .map(id => systemManager.getDeviceById(id))\n .filter(d => d &&\n (d.type === ScryptedDeviceType.Camera || d.type === ScryptedDeviceType.Doorbell) &&\n d.interfaces?.includes(ScryptedInterface.ObjectDetector)\n );\n\n for (const cam of cameras) {\n const rateKey = `rate:${cam.id}`;\n const rateLabel = (this.storage.getItem(rateKey) || '1 per minute') as RateOption;\n if (rateLabel === 'disabled') continue;\n\n const listener = cam.listen(ScryptedInterface.ObjectDetector, async (source, details, data) => {\n await this.onDetection(cam.id, cam.name, data as ObjectsDetected, RATE_MS[rateLabel]);\n });\n this.listeners.push(() => listener.removeListener());\n }\n\n this.console.log(`Listening to ${this.listeners.length} camera(s).`);\n }\n\n // ── Detection Handler ─────────────────────────────────────────────────────\n\n private async onDetection(cameraId: string, cameraName: string, data: ObjectsDetected, rateLimitMs: number) {\n if (!data?.detections?.length || !data.inputDimensions) return;\n\n // Rate limit per camera\n const now = Date.now();\n const last = this.lastCapture.get(cameraId) || 0;\n if (now - last < rateLimitMs) return;\n\n // Filter to target classes\n const targets = data.detections.filter(d =>\n d.className && CAPTURE_CLASSES.has(d.className.toLowerCase()) && d.boundingBox\n );\n if (!targets.length) return;\n\n // Pick the highest-confidence target detection\n const best = targets.sort((a, b) => (b.score || 0) - (a.score || 0))[0];\n\n // Enforce max storage\n if (this.captures.size >= MAX_CAPTURES) {\n // Evict oldest unreviewed capture\n const oldest = [...this.captures.values()]\n .filter(c => !c.reviewed)\n .sort((a, b) => a.timestamp - b.timestamp)[0];\n if (oldest) this.deleteCapture(oldest.id);\n else return; // All reviewed, don't evict labeled data\n }\n\n this.lastCapture.set(cameraId, now);\n\n // Try to get the detection image\n let jpeg: Buffer | undefined;\n try {\n if (data.detectionId) {\n const cam = systemManager.getDeviceById(cameraId) as unknown as ObjectDetector;\n const mo = await cam.getDetectionInput(data.detectionId);\n jpeg = await mediaManager.convertMediaObjectToBuffer(mo, 'image/jpeg');\n }\n } catch (e) {\n this.console.warn(`Could not get detection image for ${cameraName}:`, e);\n }\n\n if (!jpeg) return; // Skip if no image\n\n const id = `${now}-${Math.random().toString(36).slice(2, 8)}`;\n const record: CaptureRecord = {\n id,\n cameraId,\n cameraName,\n timestamp: now,\n detectedClass: best.className!,\n score: best.score || 0,\n boundingBox: best.boundingBox as number[],\n inputDimensions: data.inputDimensions as number[],\n detectionId: data.detectionId,\n reviewed: false,\n };\n\n this.captures.set(id, record);\n this.images.set(id, jpeg);\n this.saveImage(id, jpeg);\n this.saveCaptures();\n\n this.console.log(`Captured ${best.className} (${Math.round((best.score || 0) * 100)}%) from ${cameraName} [${this.captures.size} total]`);\n }\n\n // ── HTTP Handler ──────────────────────────────────────────────────────────\n\n async onRequest(request: HttpRequest, response: HttpResponse) {\n // Require authentication — reject unauthenticated requests\n if (!request.username) {\n response.send('Unauthorized', { code: 401, headers: { 'WWW-Authenticate': 'Basic realm=\"Detection Trainer\"' } });\n return;\n }\n\n const url = new URL(request.url, 'http://localhost');\n const path = url.pathname.replace(request.rootPath, '');\n\n // Serve image\n if (path.startsWith('/img/')) {\n const id = path.slice(5);\n const img = this.images.get(id);\n if (!img) return response.send('Not found', { code: 404 });\n return response.send(img, { headers: { 'Content-Type': 'image/jpeg', 'Cache-Control': 'max-age=3600' } });\n }\n\n // API: label a capture\n if (path === '/api/label' && request.body) {\n const rawBody = request.body as any;\n const body = JSON.parse(typeof rawBody === 'string' ? rawBody : Buffer.isBuffer(rawBody) ? rawBody.toString() : String(rawBody));\n const record = this.captures.get(body.id);\n if (!record) return response.send('Not found', { code: 404 });\n record.label = body.label as Label;\n record.reviewed = true;\n if (body.label === 'discard') {\n this.deleteCapture(body.id);\n } else {\n this.captures.set(body.id, record);\n this.saveCaptures();\n }\n return response.send(JSON.stringify({ ok: true }), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: get pending captures\n if (path === '/api/pending') {\n const pending = [...this.captures.values()]\n .filter(c => !c.reviewed)\n .sort((a, b) => b.timestamp - a.timestamp)\n .slice(0, 50);\n return response.send(JSON.stringify(pending), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: stats\n if (path === '/api/stats') {\n const all = [...this.captures.values()];\n const stats = {\n total: all.length,\n pending: all.filter(c => !c.reviewed).length,\n labeled: all.filter(c => c.reviewed && c.label !== 'discard').length,\n byLabel: {} as Record<string, number>,\n byCamera: {} as Record<string, number>,\n byDetectedClass: {} as Record<string, number>,\n };\n for (const r of all) {\n if (r.label) stats.byLabel[r.label] = (stats.byLabel[r.label] || 0) + 1;\n stats.byCamera[r.cameraName] = (stats.byCamera[r.cameraName] || 0) + 1;\n stats.byDetectedClass[r.detectedClass] = (stats.byDetectedClass[r.detectedClass] || 0) + 1;\n }\n return response.send(JSON.stringify(stats), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: export YOLO dataset\n if (path === '/api/export') {\n const labeled = [...this.captures.values()].filter(c => c.reviewed && c.label && c.label !== 'discard');\n if (!labeled.length) return response.send(JSON.stringify({ error: 'No labeled data yet' }), { headers: { 'Content-Type': 'application/json' }, code: 400 });\n\n const classMap: Record<Label, number> = {\n person: 0, animal: 1, face: 2, vehicle: 3, plate: 4, package: 5, discard: -1,\n };\n\n // Build a simple tarball-like structure as JSON for download\n const dataset: { filename: string; content: string; encoding: string }[] = [];\n\n for (const record of labeled) {\n const img = this.images.get(record.id);\n if (!img) continue;\n\n const fname = `${record.id}`;\n dataset.push({ filename: `images/${fname}.jpg`, content: img.toString('base64'), encoding: 'base64' });\n\n const [x, y, w, h] = record.boundingBox;\n const [imgW, imgH] = record.inputDimensions;\n const cx = (x + w / 2) / imgW;\n const cy = (y + h / 2) / imgH;\n const nw = w / imgW;\n const nh = h / imgH;\n const classId = classMap[record.label!];\n const labelLine = `${classId} ${cx.toFixed(6)} ${cy.toFixed(6)} ${nw.toFixed(6)} ${nh.toFixed(6)}\\n`;\n dataset.push({ filename: `labels/${fname}.txt`, content: labelLine, encoding: 'utf8' });\n }\n\n const yaml = [\n 'path: dataset',\n 'train: images',\n 'val: images',\n '',\n 'nc: 6',\n \"names: ['person', 'animal', 'face', 'vehicle', 'plate', 'package']\",\n '',\n '# Generated by Scrypted Detection Trainer',\n `# ${labeled.length} labeled samples`,\n ].join('\\n');\n dataset.push({ filename: 'data.yaml', content: yaml, encoding: 'utf8' });\n\n return response.send(JSON.stringify({ files: dataset, count: labeled.length }), {\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n // Serve Web UI\n if (path === '/' || path === '' || path === '/index.html') {\n return response.send(this.renderUI(), { headers: { 'Content-Type': 'text/html' } });\n }\n\n response.send('Not found', { code: 404 });\n }\n\n // ── Web UI ────────────────────────────────────────────────────────────────\n\n private renderUI(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Detection Trainer</title>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js\"></script>\n<style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f0f0f; color: #e8e8e8; min-height: 100vh; }\n header { background: #1a1a1a; border-bottom: 1px solid #333; padding: 16px 24px; display: flex; align-items: center; justify-content: space-between; }\n header h1 { font-size: 18px; font-weight: 600; color: #fff; }\n .stats { display: flex; gap: 20px; font-size: 13px; color: #aaa; }\n .stat span { color: #fff; font-weight: 600; }\n .container { max-width: 1000px; margin: 0 auto; padding: 24px; }\n .card { background: #1a1a1a; border: 1px solid #2a2a2a; border-radius: 12px; overflow: hidden; margin-bottom: 24px; }\n .card-header { padding: 16px 20px; border-bottom: 1px solid #2a2a2a; display: flex; align-items: center; justify-content: space-between; }\n .card-header h2 { font-size: 15px; font-weight: 600; }\n .badge { background: #333; color: #aaa; font-size: 12px; padding: 2px 8px; border-radius: 20px; }\n .badge.orange { background: #3d2a00; color: #f90; }\n .badge.green { background: #0d2d0d; color: #4c4; }\n\n /* Detection card */\n .detection { display: grid; grid-template-columns: 420px 1fr; gap: 0; border-bottom: 1px solid #222; }\n .detection:last-child { border-bottom: none; }\n .detection-imgs { display: flex; gap: 8px; padding: 10px; background: #111; align-items: center; }\n .img-panel { display: flex; flex-direction: column; align-items: center; gap: 4px; }\n .img-label { font-size: 10px; color: #555; text-transform: uppercase; letter-spacing: .5px; }\n .det-canvas { border-radius: 6px; display: block; }\n .det-class-badge { display: inline-block; background: #3d2a00; color: #f90; font-size: 11px; padding: 2px 8px; border-radius: 4px; }\n .detection-info { padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }\n .detection-meta { font-size: 12px; color: #888; display: flex; flex-wrap: wrap; gap: 10px; }\n .detection-meta strong { color: #ccc; }\n .label-buttons { display: flex; flex-wrap: wrap; gap: 8px; }\n .label-btn { padding: 7px 14px; border-radius: 8px; border: 1px solid #444; background: #222; color: #ccc; cursor: pointer; font-size: 13px; transition: all .15s; }\n .label-btn:hover { border-color: #666; background: #2a2a2a; color: #fff; }\n .label-btn.person { border-color: #2a6; color: #4d9; }\n .label-btn.person:hover { background: #0d2a1a; }\n .label-btn.animal { border-color: #a63; color: #d85; }\n .label-btn.animal:hover { background: #2a1a0d; }\n .label-btn.face { border-color: #49c; color: #6be; }\n .label-btn.face:hover { background: #0d1a2a; }\n .label-btn.vehicle { border-color: #76b; color: #99d; }\n .label-btn.vehicle:hover { background: #1a1a2a; }\n .label-btn.discard { border-color: #622; color: #a44; }\n .label-btn.discard:hover { background: #2a0d0d; }\n .detection.labeled { opacity: 0.4; pointer-events: none; }\n .labeled-tag { font-size: 11px; color: #4d9; background: #0d2a1a; border: 1px solid #2a6; padding: 2px 8px; border-radius: 4px; }\n\n /* Empty state */\n .empty { padding: 48px; text-align: center; color: #555; }\n .empty .icon { font-size: 48px; margin-bottom: 12px; }\n\n /* Export section */\n .export-btn { padding: 10px 20px; background: #1a4d8a; border: none; border-radius: 8px; color: #fff; cursor: pointer; font-size: 14px; font-weight: 500; }\n .export-btn:hover { background: #1e5ca0; }\n .export-btn:disabled { background: #333; color: #666; cursor: not-allowed; }\n .export-info { font-size: 13px; color: #888; padding: 12px 20px; }\n\n /* Progress bar */\n .progress { height: 4px; background: #222; border-radius: 2px; overflow: hidden; margin-top: 8px; }\n .progress-bar { height: 100%; background: #1a6; border-radius: 2px; transition: width .3s; }\n\n .toast { position: fixed; bottom: 24px; right: 24px; background: #1a3; color: #fff; padding: 10px 18px; border-radius: 8px; font-size: 13px; opacity: 0; transition: opacity .3s; pointer-events: none; }\n .toast.show { opacity: 1; }\n\n .tab-bar { display: flex; gap: 2px; padding: 12px 20px 0; border-bottom: 1px solid #2a2a2a; }\n .tab { padding: 8px 14px; font-size: 13px; color: #888; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }\n .tab.active { color: #fff; border-bottom-color: #4a9; }\n .tab-content { padding: 20px; }\n .tab-panel { display: none; }\n .tab-panel.active { display: block; }\n\n .breakdown-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }\n .breakdown-item { background: #222; border-radius: 8px; padding: 12px; }\n .breakdown-item .label { font-size: 12px; color: #888; margin-bottom: 4px; }\n .breakdown-item .value { font-size: 20px; font-weight: 600; color: #fff; }\n\n /* Lightbox */\n .lightbox { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.92); z-index: 1000; align-items: center; justify-content: center; flex-direction: column; gap: 12px; }\n .lightbox.open { display: flex; }\n .lightbox canvas { max-width: 92vw; max-height: 82vh; border-radius: 8px; cursor: zoom-out; }\n .lightbox-meta { color: #aaa; font-size: 13px; text-align: center; }\n .lightbox-close { position: absolute; top: 16px; right: 20px; font-size: 28px; color: #888; cursor: pointer; line-height: 1; }\n .lightbox-close:hover { color: #fff; }\n .det-canvas { cursor: zoom-in; }\n</style>\n</head>\n<body>\n<header>\n <h1>🎯 Detection Trainer</h1>\n <div class=\"stats\">\n <div>Pending <span id=\"stat-pending\">—</span></div>\n <div>Labeled <span id=\"stat-labeled\">—</span></div>\n <div>Total <span id=\"stat-total\">—</span></div>\n </div>\n</header>\n<div class=\"container\">\n\n <div class=\"card\">\n <div class=\"tab-bar\">\n <div class=\"tab active\" onclick=\"showTab('review')\">Review</div>\n <div class=\"tab\" onclick=\"showTab('stats')\">Stats</div>\n <div class=\"tab\" onclick=\"showTab('export')\">Export Dataset</div>\n </div>\n\n <!-- Review tab -->\n <div class=\"tab-panel active\" id=\"tab-review\">\n <div id=\"detections-list\"></div>\n </div>\n\n <!-- Stats tab -->\n <div class=\"tab-panel\" id=\"tab-stats\">\n <div class=\"tab-content\">\n <p style=\"font-size:13px;color:#888;margin-bottom:16px;\">Breakdown of captured and labeled detections.</p>\n <h3 style=\"font-size:13px;color:#aaa;margin-bottom:10px;\">By Detected Class (what the model said)</h3>\n <div class=\"breakdown-grid\" id=\"stats-detected\"></div>\n <h3 style=\"font-size:13px;color:#aaa;margin:20px 0 10px;\">By Corrected Label (what you said)</h3>\n <div class=\"breakdown-grid\" id=\"stats-label\"></div>\n <h3 style=\"font-size:13px;color:#aaa;margin:20px 0 10px;\">By Camera</h3>\n <div class=\"breakdown-grid\" id=\"stats-camera\"></div>\n </div>\n </div>\n\n <!-- Export tab -->\n <div class=\"tab-panel\" id=\"tab-export\">\n <div class=\"tab-content\">\n <p style=\"font-size:13px;color:#888;margin-bottom:16px;\">\n Exports a YOLO-format dataset (images + labels + data.yaml) as a downloadable bundle.\n Only labeled detections are included. Review more detections first to build a larger dataset.\n </p>\n <div id=\"export-stats\" class=\"export-info\">Loading…</div>\n <div style=\"display:flex;gap:12px;align-items:center;margin-top:12px;\">\n <button class=\"export-btn\" id=\"export-btn\" onclick=\"exportDataset()\">Download Dataset</button>\n <span id=\"export-status\" style=\"font-size:13px;color:#888;\"></span>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"lightbox\" id=\"lightbox\" onclick=\"closeLightbox()\">\n <div class=\"lightbox-close\" onclick=\"closeLightbox()\">✕</div>\n <canvas id=\"lightbox-canvas\"></canvas>\n <div class=\"lightbox-meta\" id=\"lightbox-meta\"></div>\n</div>\n\n<div class=\"toast\" id=\"toast\"></div>\n\n<script>\nconst BASE = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;\nlet pending = [];\nlet labeledCount = 0;\n\nfunction imgError(img) {\n img.parentElement.innerHTML = '<div style=\"padding:20px;color:#555;font-size:12px;text-align:center\">No image</div>';\n}\n\nfunction drawDetection(img, r) {\n const [bx, by, bw, bh] = r.boundingBox;\n const [iw, ih] = r.inputDimensions;\n\n // --- Full frame canvas with box overlay ---\n const fullCanvas = document.getElementById('canvas-full-' + r.id);\n if (fullCanvas) {\n const cw = fullCanvas.width, ch = fullCanvas.height;\n const scale = Math.min(cw / iw, ch / ih);\n const dw = iw * scale, dh = ih * scale;\n const ox = (cw - dw) / 2, oy = (ch - dh) / 2;\n const ctx = fullCanvas.getContext('2d');\n ctx.fillStyle = '#111';\n ctx.fillRect(0, 0, cw, ch);\n ctx.drawImage(img, ox, oy, dw, dh);\n // Draw bounding box\n const rx = ox + bx * scale, ry = oy + by * scale;\n const rw = bw * scale, rh = bh * scale;\n ctx.strokeStyle = '#f90';\n ctx.lineWidth = 2;\n ctx.strokeRect(rx, ry, rw, rh);\n // Label badge\n ctx.fillStyle = 'rgba(255,153,0,0.85)';\n ctx.fillRect(rx, ry - 18, rw, 18);\n ctx.fillStyle = '#000';\n ctx.font = 'bold 11px sans-serif';\n ctx.fillText(r.detectedClass + ' ' + Math.round(r.score * 100) + '%', rx + 3, ry - 4);\n }\n\n // --- Crop canvas ---\n const cropCanvas = document.getElementById('canvas-crop-' + r.id);\n if (cropCanvas) {\n const cc = cropCanvas.width, ch2 = cropCanvas.height;\n const ctx2 = cropCanvas.getContext('2d');\n ctx2.fillStyle = '#111';\n ctx2.fillRect(0, 0, cc, ch2);\n // Add padding around the crop\n const pad = Math.min(bw, bh) * 0.15;\n const sx = Math.max(0, bx - pad), sy = Math.max(0, by - pad);\n const sw = Math.min(iw - sx, bw + pad * 2), sh = Math.min(ih - sy, bh + pad * 2);\n const scale2 = Math.min(cc / sw, ch2 / sh);\n const dw2 = sw * scale2, dh2 = sh * scale2;\n const ox2 = (cc - dw2) / 2, oy2 = (ch2 - dh2) / 2;\n ctx2.drawImage(img, sx, sy, sw, sh, ox2, oy2, dw2, dh2);\n // Thin box outline on crop\n ctx2.strokeStyle = '#f90';\n ctx2.lineWidth = 1.5;\n const rx2 = ox2 + pad * scale2, ry2 = oy2 + pad * scale2;\n ctx2.strokeRect(rx2, ry2, bw * scale2, bh * scale2);\n }\n}\n\n// Cache loaded images so lightbox reuses them\nconst imgCache = new Map();\n\nfunction openLightbox(r) {\n const img = imgCache.get(r.id);\n if (!img) return;\n\n const lb = document.getElementById('lightbox');\n const lbCanvas = document.getElementById('lightbox-canvas');\n\n // Size canvas to image, capped at viewport\n const maxW = window.innerWidth * 0.9;\n const maxH = window.innerHeight * 0.8;\n const [iw, ih] = r.inputDimensions;\n const scale = Math.min(maxW / iw, maxH / ih, 1);\n lbCanvas.width = Math.round(iw * scale);\n lbCanvas.height = Math.round(ih * scale);\n\n const ctx = lbCanvas.getContext('2d');\n ctx.drawImage(img, 0, 0, lbCanvas.width, lbCanvas.height);\n\n // Draw all bounding boxes for this detection (primary + others in same event if available)\n const boxes = r.allDetections || [{ boundingBox: r.boundingBox, detectedClass: r.detectedClass, score: r.score }];\n const colors = ['#f90', '#4af', '#f44', '#4f4', '#f4f', '#ff4'];\n boxes.forEach((d, i) => {\n const [bx, by, bw, bh] = d.boundingBox;\n const color = colors[i % colors.length];\n const rx = bx * scale, ry = by * scale, rw = bw * scale, rh = bh * scale;\n ctx.strokeStyle = color;\n ctx.lineWidth = 2;\n ctx.strokeRect(rx, ry, rw, rh);\n const label = d.detectedClass + ' ' + Math.round((d.score || 0) * 100) + '%';\n const textW = ctx.measureText(label).width + 8;\n ctx.fillStyle = color;\n ctx.globalAlpha = 0.85;\n ctx.fillRect(rx, Math.max(0, ry - 20), textW, 20);\n ctx.globalAlpha = 1;\n ctx.fillStyle = '#000';\n ctx.font = 'bold 12px sans-serif';\n ctx.fillText(label, rx + 4, Math.max(14, ry - 4));\n });\n\n document.getElementById('lightbox-meta').textContent =\n r.cameraName + ' · ' + new Date(r.timestamp).toLocaleString() + ' · ' + iw + '×' + ih;\n lb.classList.add('open');\n document.addEventListener('keydown', lbKeyHandler);\n}\n\nfunction closeLightbox() {\n document.getElementById('lightbox').classList.remove('open');\n document.removeEventListener('keydown', lbKeyHandler);\n}\n\nfunction lbKeyHandler(e) {\n if (e.key === 'Escape') closeLightbox();\n}\n\nfunction showTab(name) {\n document.querySelectorAll('.tab').forEach((t, i) => {\n const names = ['review', 'stats', 'export'];\n t.classList.toggle('active', names[i] === name);\n });\n document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));\n document.getElementById('tab-' + name).classList.add('active');\n if (name === 'stats') loadStats();\n if (name === 'export') loadExportInfo();\n}\n\nfunction toast(msg, color='#1a3') {\n const el = document.getElementById('toast');\n el.textContent = msg;\n el.style.background = color;\n el.classList.add('show');\n setTimeout(() => el.classList.remove('show'), 2500);\n}\n\nasync function loadPending() {\n try {\n const res = await fetch(BASE + '/api/pending');\n pending = await res.json();\n\n const statsRes = await fetch(BASE + '/api/stats');\n const stats = await statsRes.json();\n document.getElementById('stat-pending').textContent = stats.pending;\n document.getElementById('stat-labeled').textContent = stats.labeled;\n document.getElementById('stat-total').textContent = stats.total;\n\n const list = document.getElementById('detections-list');\n if (!pending.length) {\n list.innerHTML = '<div class=\"empty\"><div class=\"icon\">✅</div><div>No pending detections to review.<br><span style=\"font-size:12px;color:#444\">Captures will appear here as cameras detect objects.</span></div></div>';\n return;\n }\n\n list.innerHTML = pending.map(r => {\n const date = new Date(r.timestamp).toLocaleString();\n const score = Math.round(r.score * 100);\n const bb = r.boundingBox;\n const dim = r.inputDimensions;\n return \\`\n <div class=\"detection\" id=\"det-\\${r.id}\">\n <div class=\"detection-imgs\">\n <div class=\"img-panel\">\n <div class=\"img-label\">Full frame</div>\n <canvas id=\"canvas-full-\\${r.id}\" class=\"det-canvas\" width=\"240\" height=\"160\"></canvas>\n </div>\n <div class=\"img-panel\">\n <div class=\"img-label\">Crop</div>\n <canvas id=\"canvas-crop-\\${r.id}\" class=\"det-canvas\" width=\"160\" height=\"160\"></canvas>\n </div>\n </div>\n <div class=\"detection-info\">\n <div class=\"detection-meta\">\n <div><strong>\\${r.cameraName}</strong></div>\n <div>\\${date}</div>\n <div class=\"det-class-badge\">\\${r.detectedClass} \\${score}%</div>\n </div>\n <div style=\"font-size:12px;color:#888;\">What is this actually?</div>\n <div class=\"label-buttons\">\n <button class=\"label-btn person\" onclick=\"label('\\${r.id}', 'person')\">👤 Person</button>\n <button class=\"label-btn animal\" onclick=\"label('\\${r.id}', 'animal')\">🐾 Animal</button>\n <button class=\"label-btn face\" onclick=\"label('\\${r.id}', 'face')\">😀 Face</button>\n <button class=\"label-btn vehicle\" onclick=\"label('\\${r.id}', 'vehicle')\">🚗 Vehicle</button>\n <button class=\"label-btn\" onclick=\"label('\\${r.id}', 'plate')\">🔢 Plate</button>\n <button class=\"label-btn\" onclick=\"label('\\${r.id}', 'package')\">📦 Package</button>\n <button class=\"label-btn discard\" onclick=\"label('\\${r.id}', 'discard')\">🗑 Discard</button>\n </div>\n </div>\n </div>\\`;\n }).join('');\n\n // Draw bounding boxes and crops onto canvases after DOM is ready\n for (const r of pending) {\n const img = new Image();\n img.onload = () => {\n imgCache.set(r.id, img);\n drawDetection(img, r);\n // Wire up click to open lightbox\n const fullCanvas = document.getElementById('canvas-full-' + r.id);\n const cropCanvas = document.getElementById('canvas-crop-' + r.id);\n if (fullCanvas) fullCanvas.onclick = () => openLightbox(r);\n if (cropCanvas) cropCanvas.onclick = () => openLightbox(r);\n };\n img.onerror = () => {\n const c = document.getElementById('canvas-full-' + r.id);\n if (c) c.parentElement.innerHTML = '<div style=\"padding:10px;color:#555;font-size:11px\">No image</div>';\n };\n img.src = BASE + '/img/' + r.id;\n } } catch(e) {\n console.error('loadPending error', e);\n const list = document.getElementById('detections-list');\n if (list) list.innerHTML = '<div class=\"empty\"><div style=\"color:#a44\">Error loading captures: ' + e.message + '</div></div>';\n }\n}\n\nasync function label(id, labelVal) {\n const el = document.getElementById('det-' + id);\n if (el) {\n el.classList.add('labeled');\n const btns = el.querySelectorAll('.label-btn');\n btns.forEach(b => b.disabled = true);\n }\n await fetch(BASE + '/api/label', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id, label: labelVal }),\n });\n toast(labelVal === 'discard' ? 'Discarded' : 'Labeled: ' + labelVal, labelVal === 'discard' ? '#633' : '#1a6');\n setTimeout(() => {\n if (el) el.remove();\n loadPending();\n }, 600);\n}\n\nasync function loadStats() {\n const res = await fetch(BASE + '/api/stats');\n const stats = await res.json();\n\n const renderBreakdown = (obj, container) => {\n const el = document.getElementById(container);\n const entries = Object.entries(obj).sort((a, b) => b[1] - a[1]);\n el.innerHTML = entries.length\n ? entries.map(([k, v]) => \\`<div class=\"breakdown-item\"><div class=\"label\">\\${k}</div><div class=\"value\">\\${v}</div></div>\\`).join('')\n : '<div style=\"color:#555;font-size:13px;\">None yet</div>';\n };\n\n renderBreakdown(stats.byDetectedClass, 'stats-detected');\n renderBreakdown(stats.byLabel, 'stats-label');\n renderBreakdown(stats.byCamera, 'stats-camera');\n}\n\nasync function loadExportInfo() {\n const res = await fetch(BASE + '/api/stats');\n const stats = await res.json();\n document.getElementById('export-stats').textContent =\n \\`\\${stats.labeled} labeled samples ready for export across \\${Object.keys(stats.byCamera).length} camera(s).\\`;\n}\n\nasync function exportDataset() {\n const btn = document.getElementById('export-btn');\n const status = document.getElementById('export-status');\n btn.disabled = true;\n status.textContent = 'Fetching data…';\n\n try {\n const res = await fetch(BASE + '/api/export');\n if (!res.ok) { status.textContent = 'Nothing to export yet.'; btn.disabled = false; return; }\n const data = await res.json();\n if (data.error) { status.textContent = data.error; btn.disabled = false; return; }\n\n status.textContent = 'Building zip…';\n\n const zip = new JSZip();\n for (const f of data.files) {\n if (f.encoding === 'base64') {\n zip.file(f.filename, f.content, { base64: true });\n } else {\n zip.file(f.filename, f.content);\n }\n }\n\n const blob = await zip.generateAsync({ type: 'blob', compression: 'DEFLATE' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'scrypted_dataset_' + new Date().toISOString().slice(0,10) + '.zip';\n a.click();\n URL.revokeObjectURL(url);\n status.textContent = \\`Downloaded \\${data.count} samples.\\`;\n toast('Dataset downloaded!');\n } catch (e) {\n status.textContent = 'Export failed: ' + e.message;\n }\n btn.disabled = false;\n}\n\n// Initial load\nloadPending();\n// Auto-refresh pending every 30s\nsetInterval(loadPending, 30_000);\n</script>\n</body>\n</html>`;\n }\n}\n\nexport default DetectionTrainer;\n","module.exports = require(\"module\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(927);\n"],"names":["__createBinding","this","Object","create","o","m","k","k2","undefined","desc","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","get","defineProperty","__exportStar","exports","p","prototype","hasOwnProperty","call","value","sdk","MixinDeviceBase","ScryptedDeviceBase","index_1","DeviceBase","constructor","nativeId","super","storage","_storage","deviceManager","getDeviceStorage","log","_log","getDeviceLogger","console","_console","getDeviceConsole","createMediaObject","data","mimeType","mediaManager","sourceId","id","getMediaObjectConsole","mediaObject","getMixinConsole","_lazyLoadDeviceState","_deviceState","getDeviceState","onDeviceEvent","eventInterface","eventData","options","_listeners","Set","mixinDevice","mixinDeviceInterfaces","mixinStorageSuffix","mixinDeviceState","systemManager","getDeviceById","mixinProviderNativeId","__rpcproxy_traps_all_properties","createDeviceState","setState","mixinStorageKey","getMixinStorage","onMixinEvent","manageListener","listener","add","release","l","removeListener","_createGetState","state","_createSetState","warn","field","values","ScryptedInterfaceProperty","set","loaded","process","env","SCRYPTED_SDK_ES_MODULE","SCRYPTED_SDK_MODULE","cjsModule","SCRYPTED_SDK_CJS_MODULE","sdkModule","assign","getScryptedStatic","e","runtimeAPI","pluginRuntimeAPI","endpointManager","pluginHostAPI","setScryptedInterfaceDescriptors","TYPES_VERSION","ScryptedInterfaceDescriptors","catch","error","webpackEmptyContext","req","Error","code","keys","resolve","module","ScryptedMimeTypes","ScryptedInterface","MediaPlayerState","SecuritySystemObstruction","SecuritySystemMode","AirQuality","AirPurifierMode","AirPurifierStatus","ChargeState","LockState","PanTiltZoomMovement","ThermostatMode","TemperatureUnit","FanMode","HumidityMode","ScryptedDeviceType","ScryptedInterfaceMethod","CAPTURE_CLASSES","RATE_OPTIONS","RATE_MS","Infinity","DetectionTrainer","lastCapture","Map","captures","images","listeners","loadState","registerListeners","raw","getItem","arr","JSON","parse","r","size","Buffer","from","saveCaptures","setItem","stringify","saveImage","buf","toString","deleteCapture","removeItem","delete","getSettings","cameras","getSystemState","map","filter","d","type","Camera","Doorbell","interfaces","includes","ObjectDetector","uiUrl","getAuthenticatedPath","settings","key","title","description","c","reviewed","length","label","readonly","cam","push","name","group","choices","putSetting","startsWith","remove","rateKey","rateLabel","listen","async","source","details","onDetection","cameraId","cameraName","rateLimitMs","detections","inputDimensions","now","Date","targets","className","has","toLowerCase","boundingBox","best","sort","a","b","score","oldest","timestamp","jpeg","detectionId","mo","getDetectionInput","convertMediaObjectToBuffer","Math","random","slice","record","detectedClass","round","onRequest","request","response","username","send","headers","path","URL","url","pathname","replace","rootPath","img","body","rawBody","isBuffer","String","ok","pending","all","stats","total","labeled","byLabel","byCamera","byDetectedClass","classMap","person","animal","face","vehicle","plate","package","discard","dataset","fname","filename","content","encoding","x","y","w","h","imgW","imgH","cx","cy","nw","nh","labelLine","toFixed","yaml","join","files","count","renderUI","require","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","obj","prop","__webpack_exports__"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"main.nodejs.js","mappings":"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","sources":["../node_modules/@scrypted/sdk/dist/src/index.js","../node_modules/@scrypted/sdk/dist/src|sync","../node_modules/@scrypted/sdk/dist/types/gen/index.js","../src/main.ts","../external node-commonjs \"module\"","../webpack/bootstrap","../webpack/runtime/hasOwnProperty shorthand","../webpack/startup"],"sourcesContent":["\"use strict\";\nvar __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n var desc = Object.getOwnPropertyDescriptor(m, k);\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\n desc = { enumerable: true, get: function() { return m[k]; } };\n }\n Object.defineProperty(o, k2, desc);\n}) : (function(o, m, k, k2) {\n if (k2 === undefined) k2 = k;\n o[k2] = m[k];\n}));\nvar __exportStar = (this && this.__exportStar) || function(m, exports) {\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.sdk = exports.MixinDeviceBase = exports.ScryptedDeviceBase = void 0;\n__exportStar(require(\"../types/gen/index\"), exports);\nconst index_1 = require(\"../types/gen/index\");\nconst module_1 = require(\"module\");\n/**\n * @category Core Reference\n */\nclass ScryptedDeviceBase extends index_1.DeviceBase {\n constructor(nativeId) {\n super();\n this.nativeId = nativeId;\n }\n get storage() {\n if (!this._storage) {\n this._storage = exports.sdk.deviceManager.getDeviceStorage(this.nativeId);\n }\n return this._storage;\n }\n get log() {\n if (!this._log) {\n this._log = exports.sdk.deviceManager.getDeviceLogger(this.nativeId);\n }\n return this._log;\n }\n get console() {\n if (!this._console) {\n this._console = exports.sdk.deviceManager.getDeviceConsole(this.nativeId);\n }\n return this._console;\n }\n async createMediaObject(data, mimeType) {\n return exports.sdk.mediaManager.createMediaObject(data, mimeType, {\n sourceId: this.id,\n });\n }\n getMediaObjectConsole(mediaObject) {\n if (typeof mediaObject.sourceId !== 'string')\n return this.console;\n return exports.sdk.deviceManager.getMixinConsole(mediaObject.sourceId, this.nativeId);\n }\n _lazyLoadDeviceState() {\n if (!this._deviceState) {\n if (this.nativeId) {\n this._deviceState = exports.sdk.deviceManager.getDeviceState(this.nativeId);\n }\n else {\n this._deviceState = exports.sdk.deviceManager.getDeviceState();\n }\n }\n }\n /**\n * Fire an event for this device.\n */\n onDeviceEvent(eventInterface, eventData) {\n return exports.sdk.deviceManager.onDeviceEvent(this.nativeId, eventInterface, eventData);\n }\n}\nexports.ScryptedDeviceBase = ScryptedDeviceBase;\n/**\n * @category Mixin Reference\n */\nclass MixinDeviceBase extends index_1.DeviceBase {\n constructor(options) {\n super();\n this._listeners = new Set();\n this.mixinDevice = options.mixinDevice;\n this.mixinDeviceInterfaces = options.mixinDeviceInterfaces;\n this.mixinStorageSuffix = options.mixinStorageSuffix;\n this._deviceState = options.mixinDeviceState;\n this.nativeId = exports.sdk.systemManager.getDeviceById(this.id).nativeId;\n this.mixinProviderNativeId = options.mixinProviderNativeId;\n // RpcProxy will trap all properties, and the following check/hack will determine\n // if the device state came from another node worker thread.\n // This should ultimately be discouraged and warned at some point in the future.\n if (this._deviceState.__rpcproxy_traps_all_properties && typeof this._deviceState.id === 'string') {\n this._deviceState = exports.sdk.deviceManager.createDeviceState(this._deviceState.id, this._deviceState.setState);\n }\n }\n get storage() {\n if (!this._storage) {\n const mixinStorageSuffix = this.mixinStorageSuffix;\n const mixinStorageKey = this.id + (mixinStorageSuffix ? ':' + mixinStorageSuffix : '');\n this._storage = exports.sdk.deviceManager.getMixinStorage(mixinStorageKey, this.mixinProviderNativeId);\n }\n return this._storage;\n }\n get console() {\n if (!this._console) {\n if (exports.sdk.deviceManager.getMixinConsole)\n this._console = exports.sdk.deviceManager.getMixinConsole(this.id, this.mixinProviderNativeId);\n else\n this._console = exports.sdk.deviceManager.getDeviceConsole(this.mixinProviderNativeId);\n }\n return this._console;\n }\n async createMediaObject(data, mimeType) {\n return exports.sdk.mediaManager.createMediaObject(data, mimeType, {\n sourceId: this.id,\n });\n }\n getMediaObjectConsole(mediaObject) {\n if (typeof mediaObject.sourceId !== 'string')\n return this.console;\n return exports.sdk.deviceManager.getMixinConsole(mediaObject.sourceId, this.mixinProviderNativeId);\n }\n /**\n * Fire an event for this device.\n */\n onDeviceEvent(eventInterface, eventData) {\n return exports.sdk.deviceManager.onMixinEvent(this.id, this, eventInterface, eventData);\n }\n _lazyLoadDeviceState() {\n }\n manageListener(listener) {\n this._listeners.add(listener);\n }\n release() {\n for (const l of this._listeners) {\n l.removeListener();\n }\n }\n}\nexports.MixinDeviceBase = MixinDeviceBase;\n(function () {\n function _createGetState(state) {\n return function () {\n this._lazyLoadDeviceState();\n // @ts-ignore: accessing private property\n return this._deviceState?.[state];\n };\n }\n function _createSetState(state) {\n return function (value) {\n this._lazyLoadDeviceState();\n // @ts-ignore: accessing private property\n if (!this._deviceState) {\n console.warn('device state is unavailable. the device must be discovered with deviceManager.onDeviceDiscovered or deviceManager.onDevicesChanged before the state can be set.');\n }\n else {\n // @ts-ignore: accessing private property\n this._deviceState[state] = value;\n }\n };\n }\n for (const field of Object.values(index_1.ScryptedInterfaceProperty)) {\n if (field === index_1.ScryptedInterfaceProperty.nativeId)\n continue;\n Object.defineProperty(ScryptedDeviceBase.prototype, field, {\n set: _createSetState(field),\n get: _createGetState(field),\n });\n Object.defineProperty(MixinDeviceBase.prototype, field, {\n set: _createSetState(field),\n get: _createGetState(field),\n });\n }\n})();\nexports.sdk = {};\ntry {\n let loaded = false;\n try {\n // todo: remove usage of process.env.SCRYPTED_SDK_MODULE, only existed in prerelease builds.\n // import.meta is not a reliable way to detect es module support in webpack since webpack\n // evaluates that to true at runtime.\n const esModule = process.env.SCRYPTED_SDK_ES_MODULE || process.env.SCRYPTED_SDK_MODULE;\n const cjsModule = process.env.SCRYPTED_SDK_CJS_MODULE || process.env.SCRYPTED_SDK_MODULE;\n // @ts-expect-error\n if (esModule && typeof import.meta !== 'undefined') {\n // @ts-expect-error\n const require = (0, module_1.createRequire)(import.meta.url);\n const sdkModule = require(esModule);\n Object.assign(exports.sdk, sdkModule.getScryptedStatic());\n loaded = true;\n }\n else if (cjsModule) {\n // @ts-expect-error\n if (typeof __non_webpack_require__ !== 'undefined') {\n // @ts-expect-error\n const sdkModule = __non_webpack_require__(process.env.SCRYPTED_SDK_MODULE);\n Object.assign(exports.sdk, sdkModule.getScryptedStatic());\n loaded = true;\n }\n else {\n const sdkModule = require(cjsModule);\n Object.assign(exports.sdk, sdkModule.getScryptedStatic());\n loaded = true;\n }\n }\n }\n catch (e) {\n console.warn(\"failed to load sdk module\", e);\n throw e;\n }\n if (!loaded) {\n let runtimeAPI;\n try {\n runtimeAPI = pluginRuntimeAPI;\n }\n catch (e) {\n }\n Object.assign(exports.sdk, {\n log: deviceManager.getDeviceLogger(undefined),\n deviceManager,\n endpointManager,\n mediaManager,\n systemManager,\n pluginHostAPI,\n ...runtimeAPI,\n });\n }\n try {\n exports.sdk.systemManager.setScryptedInterfaceDescriptors?.(index_1.TYPES_VERSION, index_1.ScryptedInterfaceDescriptors)?.catch(() => { });\n }\n catch (e) {\n }\n}\ncatch (e) {\n console.error('sdk initialization error, import @scrypted/types or use @scrypted/client instead', e);\n}\nexports.default = exports.sdk;\n//# sourceMappingURL=index.js.map","function webpackEmptyContext(req) {\n\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\te.code = 'MODULE_NOT_FOUND';\n\tthrow e;\n}\nwebpackEmptyContext.keys = () => ([]);\nwebpackEmptyContext.resolve = webpackEmptyContext;\nwebpackEmptyContext.id = 891;\nmodule.exports = webpackEmptyContext;","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.ScryptedMimeTypes = exports.ScryptedInterface = exports.MediaPlayerState = exports.SecuritySystemObstruction = exports.SecuritySystemMode = exports.AirQuality = exports.AirPurifierMode = exports.AirPurifierStatus = exports.ChargeState = exports.LockState = exports.PanTiltZoomMovement = exports.ThermostatMode = exports.TemperatureUnit = exports.FanMode = exports.HumidityMode = exports.ScryptedDeviceType = exports.ScryptedInterfaceDescriptors = exports.ScryptedInterfaceMethod = exports.ScryptedInterfaceProperty = exports.DeviceBase = exports.TYPES_VERSION = void 0;\nexports.TYPES_VERSION = \"0.3.116\";\nclass DeviceBase {\n}\nexports.DeviceBase = DeviceBase;\nvar ScryptedInterfaceProperty;\n(function (ScryptedInterfaceProperty) {\n ScryptedInterfaceProperty[\"id\"] = \"id\";\n ScryptedInterfaceProperty[\"info\"] = \"info\";\n ScryptedInterfaceProperty[\"interfaces\"] = \"interfaces\";\n ScryptedInterfaceProperty[\"mixins\"] = \"mixins\";\n ScryptedInterfaceProperty[\"name\"] = \"name\";\n ScryptedInterfaceProperty[\"nativeId\"] = \"nativeId\";\n ScryptedInterfaceProperty[\"pluginId\"] = \"pluginId\";\n ScryptedInterfaceProperty[\"providedInterfaces\"] = \"providedInterfaces\";\n ScryptedInterfaceProperty[\"providedName\"] = \"providedName\";\n ScryptedInterfaceProperty[\"providedRoom\"] = \"providedRoom\";\n ScryptedInterfaceProperty[\"providedType\"] = \"providedType\";\n ScryptedInterfaceProperty[\"providerId\"] = \"providerId\";\n ScryptedInterfaceProperty[\"room\"] = \"room\";\n ScryptedInterfaceProperty[\"type\"] = \"type\";\n ScryptedInterfaceProperty[\"scryptedRuntimeArguments\"] = \"scryptedRuntimeArguments\";\n ScryptedInterfaceProperty[\"on\"] = \"on\";\n ScryptedInterfaceProperty[\"brightness\"] = \"brightness\";\n ScryptedInterfaceProperty[\"colorTemperature\"] = \"colorTemperature\";\n ScryptedInterfaceProperty[\"rgb\"] = \"rgb\";\n ScryptedInterfaceProperty[\"hsv\"] = \"hsv\";\n ScryptedInterfaceProperty[\"buttons\"] = \"buttons\";\n ScryptedInterfaceProperty[\"sensors\"] = \"sensors\";\n ScryptedInterfaceProperty[\"running\"] = \"running\";\n ScryptedInterfaceProperty[\"paused\"] = \"paused\";\n ScryptedInterfaceProperty[\"docked\"] = \"docked\";\n ScryptedInterfaceProperty[\"temperatureSetting\"] = \"temperatureSetting\";\n ScryptedInterfaceProperty[\"temperature\"] = \"temperature\";\n ScryptedInterfaceProperty[\"temperatureUnit\"] = \"temperatureUnit\";\n ScryptedInterfaceProperty[\"humidity\"] = \"humidity\";\n ScryptedInterfaceProperty[\"audioVolumes\"] = \"audioVolumes\";\n ScryptedInterfaceProperty[\"recordingActive\"] = \"recordingActive\";\n ScryptedInterfaceProperty[\"ptzCapabilities\"] = \"ptzCapabilities\";\n ScryptedInterfaceProperty[\"lockState\"] = \"lockState\";\n ScryptedInterfaceProperty[\"entryOpen\"] = \"entryOpen\";\n ScryptedInterfaceProperty[\"batteryLevel\"] = \"batteryLevel\";\n ScryptedInterfaceProperty[\"chargeState\"] = \"chargeState\";\n ScryptedInterfaceProperty[\"online\"] = \"online\";\n ScryptedInterfaceProperty[\"fromMimeType\"] = \"fromMimeType\";\n ScryptedInterfaceProperty[\"toMimeType\"] = \"toMimeType\";\n ScryptedInterfaceProperty[\"converters\"] = \"converters\";\n ScryptedInterfaceProperty[\"binaryState\"] = \"binaryState\";\n ScryptedInterfaceProperty[\"tampered\"] = \"tampered\";\n ScryptedInterfaceProperty[\"sleeping\"] = \"sleeping\";\n ScryptedInterfaceProperty[\"powerDetected\"] = \"powerDetected\";\n ScryptedInterfaceProperty[\"audioDetected\"] = \"audioDetected\";\n ScryptedInterfaceProperty[\"motionDetected\"] = \"motionDetected\";\n ScryptedInterfaceProperty[\"ambientLight\"] = \"ambientLight\";\n ScryptedInterfaceProperty[\"occupied\"] = \"occupied\";\n ScryptedInterfaceProperty[\"flooded\"] = \"flooded\";\n ScryptedInterfaceProperty[\"ultraviolet\"] = \"ultraviolet\";\n ScryptedInterfaceProperty[\"luminance\"] = \"luminance\";\n ScryptedInterfaceProperty[\"position\"] = \"position\";\n ScryptedInterfaceProperty[\"securitySystemState\"] = \"securitySystemState\";\n ScryptedInterfaceProperty[\"pm10Density\"] = \"pm10Density\";\n ScryptedInterfaceProperty[\"pm25Density\"] = \"pm25Density\";\n ScryptedInterfaceProperty[\"vocDensity\"] = \"vocDensity\";\n ScryptedInterfaceProperty[\"noxDensity\"] = \"noxDensity\";\n ScryptedInterfaceProperty[\"co2ppm\"] = \"co2ppm\";\n ScryptedInterfaceProperty[\"airQuality\"] = \"airQuality\";\n ScryptedInterfaceProperty[\"airPurifierState\"] = \"airPurifierState\";\n ScryptedInterfaceProperty[\"filterChangeIndication\"] = \"filterChangeIndication\";\n ScryptedInterfaceProperty[\"filterLifeLevel\"] = \"filterLifeLevel\";\n ScryptedInterfaceProperty[\"humiditySetting\"] = \"humiditySetting\";\n ScryptedInterfaceProperty[\"fan\"] = \"fan\";\n ScryptedInterfaceProperty[\"applicationInfo\"] = \"applicationInfo\";\n ScryptedInterfaceProperty[\"systemDevice\"] = \"systemDevice\";\n})(ScryptedInterfaceProperty || (exports.ScryptedInterfaceProperty = ScryptedInterfaceProperty = {}));\nvar ScryptedInterfaceMethod;\n(function (ScryptedInterfaceMethod) {\n ScryptedInterfaceMethod[\"listen\"] = \"listen\";\n ScryptedInterfaceMethod[\"probe\"] = \"probe\";\n ScryptedInterfaceMethod[\"setMixins\"] = \"setMixins\";\n ScryptedInterfaceMethod[\"setName\"] = \"setName\";\n ScryptedInterfaceMethod[\"setRoom\"] = \"setRoom\";\n ScryptedInterfaceMethod[\"setType\"] = \"setType\";\n ScryptedInterfaceMethod[\"getPluginJson\"] = \"getPluginJson\";\n ScryptedInterfaceMethod[\"turnOff\"] = \"turnOff\";\n ScryptedInterfaceMethod[\"turnOn\"] = \"turnOn\";\n ScryptedInterfaceMethod[\"setBrightness\"] = \"setBrightness\";\n ScryptedInterfaceMethod[\"getTemperatureMaxK\"] = \"getTemperatureMaxK\";\n ScryptedInterfaceMethod[\"getTemperatureMinK\"] = \"getTemperatureMinK\";\n ScryptedInterfaceMethod[\"setColorTemperature\"] = \"setColorTemperature\";\n ScryptedInterfaceMethod[\"setRgb\"] = \"setRgb\";\n ScryptedInterfaceMethod[\"setHsv\"] = \"setHsv\";\n ScryptedInterfaceMethod[\"pressButton\"] = \"pressButton\";\n ScryptedInterfaceMethod[\"sendNotification\"] = \"sendNotification\";\n ScryptedInterfaceMethod[\"start\"] = \"start\";\n ScryptedInterfaceMethod[\"stop\"] = \"stop\";\n ScryptedInterfaceMethod[\"pause\"] = \"pause\";\n ScryptedInterfaceMethod[\"resume\"] = \"resume\";\n ScryptedInterfaceMethod[\"dock\"] = \"dock\";\n ScryptedInterfaceMethod[\"setTemperature\"] = \"setTemperature\";\n ScryptedInterfaceMethod[\"setTemperatureUnit\"] = \"setTemperatureUnit\";\n ScryptedInterfaceMethod[\"getPictureOptions\"] = \"getPictureOptions\";\n ScryptedInterfaceMethod[\"takePicture\"] = \"takePicture\";\n ScryptedInterfaceMethod[\"getAudioStream\"] = \"getAudioStream\";\n ScryptedInterfaceMethod[\"setAudioVolumes\"] = \"setAudioVolumes\";\n ScryptedInterfaceMethod[\"startDisplay\"] = \"startDisplay\";\n ScryptedInterfaceMethod[\"stopDisplay\"] = \"stopDisplay\";\n ScryptedInterfaceMethod[\"getVideoStream\"] = \"getVideoStream\";\n ScryptedInterfaceMethod[\"getVideoStreamOptions\"] = \"getVideoStreamOptions\";\n ScryptedInterfaceMethod[\"getPrivacyMasks\"] = \"getPrivacyMasks\";\n ScryptedInterfaceMethod[\"setPrivacyMasks\"] = \"setPrivacyMasks\";\n ScryptedInterfaceMethod[\"getVideoTextOverlays\"] = \"getVideoTextOverlays\";\n ScryptedInterfaceMethod[\"setVideoTextOverlay\"] = \"setVideoTextOverlay\";\n ScryptedInterfaceMethod[\"getRecordingStream\"] = \"getRecordingStream\";\n ScryptedInterfaceMethod[\"getRecordingStreamCurrentTime\"] = \"getRecordingStreamCurrentTime\";\n ScryptedInterfaceMethod[\"getRecordingStreamOptions\"] = \"getRecordingStreamOptions\";\n ScryptedInterfaceMethod[\"getRecordingStreamThumbnail\"] = \"getRecordingStreamThumbnail\";\n ScryptedInterfaceMethod[\"deleteRecordingStream\"] = \"deleteRecordingStream\";\n ScryptedInterfaceMethod[\"setRecordingActive\"] = \"setRecordingActive\";\n ScryptedInterfaceMethod[\"ptzCommand\"] = \"ptzCommand\";\n ScryptedInterfaceMethod[\"getRecordedEvents\"] = \"getRecordedEvents\";\n ScryptedInterfaceMethod[\"getVideoClip\"] = \"getVideoClip\";\n ScryptedInterfaceMethod[\"getVideoClips\"] = \"getVideoClips\";\n ScryptedInterfaceMethod[\"getVideoClipThumbnail\"] = \"getVideoClipThumbnail\";\n ScryptedInterfaceMethod[\"removeVideoClips\"] = \"removeVideoClips\";\n ScryptedInterfaceMethod[\"setVideoStreamOptions\"] = \"setVideoStreamOptions\";\n ScryptedInterfaceMethod[\"startIntercom\"] = \"startIntercom\";\n ScryptedInterfaceMethod[\"stopIntercom\"] = \"stopIntercom\";\n ScryptedInterfaceMethod[\"lock\"] = \"lock\";\n ScryptedInterfaceMethod[\"unlock\"] = \"unlock\";\n ScryptedInterfaceMethod[\"addPassword\"] = \"addPassword\";\n ScryptedInterfaceMethod[\"getPasswords\"] = \"getPasswords\";\n ScryptedInterfaceMethod[\"removePassword\"] = \"removePassword\";\n ScryptedInterfaceMethod[\"activate\"] = \"activate\";\n ScryptedInterfaceMethod[\"deactivate\"] = \"deactivate\";\n ScryptedInterfaceMethod[\"isReversible\"] = \"isReversible\";\n ScryptedInterfaceMethod[\"closeEntry\"] = \"closeEntry\";\n ScryptedInterfaceMethod[\"openEntry\"] = \"openEntry\";\n ScryptedInterfaceMethod[\"getDevice\"] = \"getDevice\";\n ScryptedInterfaceMethod[\"releaseDevice\"] = \"releaseDevice\";\n ScryptedInterfaceMethod[\"adoptDevice\"] = \"adoptDevice\";\n ScryptedInterfaceMethod[\"discoverDevices\"] = \"discoverDevices\";\n ScryptedInterfaceMethod[\"createDevice\"] = \"createDevice\";\n ScryptedInterfaceMethod[\"getCreateDeviceSettings\"] = \"getCreateDeviceSettings\";\n ScryptedInterfaceMethod[\"reboot\"] = \"reboot\";\n ScryptedInterfaceMethod[\"getRefreshFrequency\"] = \"getRefreshFrequency\";\n ScryptedInterfaceMethod[\"refresh\"] = \"refresh\";\n ScryptedInterfaceMethod[\"getMediaStatus\"] = \"getMediaStatus\";\n ScryptedInterfaceMethod[\"load\"] = \"load\";\n ScryptedInterfaceMethod[\"seek\"] = \"seek\";\n ScryptedInterfaceMethod[\"skipNext\"] = \"skipNext\";\n ScryptedInterfaceMethod[\"skipPrevious\"] = \"skipPrevious\";\n ScryptedInterfaceMethod[\"convert\"] = \"convert\";\n ScryptedInterfaceMethod[\"convertMedia\"] = \"convertMedia\";\n ScryptedInterfaceMethod[\"getSettings\"] = \"getSettings\";\n ScryptedInterfaceMethod[\"putSetting\"] = \"putSetting\";\n ScryptedInterfaceMethod[\"armSecuritySystem\"] = \"armSecuritySystem\";\n ScryptedInterfaceMethod[\"disarmSecuritySystem\"] = \"disarmSecuritySystem\";\n ScryptedInterfaceMethod[\"setAirPurifierState\"] = \"setAirPurifierState\";\n ScryptedInterfaceMethod[\"getReadmeMarkdown\"] = \"getReadmeMarkdown\";\n ScryptedInterfaceMethod[\"getOauthUrl\"] = \"getOauthUrl\";\n ScryptedInterfaceMethod[\"onOauthCallback\"] = \"onOauthCallback\";\n ScryptedInterfaceMethod[\"canMixin\"] = \"canMixin\";\n ScryptedInterfaceMethod[\"getMixin\"] = \"getMixin\";\n ScryptedInterfaceMethod[\"releaseMixin\"] = \"releaseMixin\";\n ScryptedInterfaceMethod[\"onRequest\"] = \"onRequest\";\n ScryptedInterfaceMethod[\"onConnection\"] = \"onConnection\";\n ScryptedInterfaceMethod[\"onPush\"] = \"onPush\";\n ScryptedInterfaceMethod[\"run\"] = \"run\";\n ScryptedInterfaceMethod[\"eval\"] = \"eval\";\n ScryptedInterfaceMethod[\"loadScripts\"] = \"loadScripts\";\n ScryptedInterfaceMethod[\"saveScript\"] = \"saveScript\";\n ScryptedInterfaceMethod[\"forkInterface\"] = \"forkInterface\";\n ScryptedInterfaceMethod[\"trackObjects\"] = \"trackObjects\";\n ScryptedInterfaceMethod[\"getDetectionInput\"] = \"getDetectionInput\";\n ScryptedInterfaceMethod[\"getObjectTypes\"] = \"getObjectTypes\";\n ScryptedInterfaceMethod[\"detectObjects\"] = \"detectObjects\";\n ScryptedInterfaceMethod[\"generateObjectDetections\"] = \"generateObjectDetections\";\n ScryptedInterfaceMethod[\"getDetectionModel\"] = \"getDetectionModel\";\n ScryptedInterfaceMethod[\"setHumidity\"] = \"setHumidity\";\n ScryptedInterfaceMethod[\"setFan\"] = \"setFan\";\n ScryptedInterfaceMethod[\"startRTCSignalingSession\"] = \"startRTCSignalingSession\";\n ScryptedInterfaceMethod[\"createRTCSignalingSession\"] = \"createRTCSignalingSession\";\n ScryptedInterfaceMethod[\"getScryptedUserAccessControl\"] = \"getScryptedUserAccessControl\";\n ScryptedInterfaceMethod[\"generateVideoFrames\"] = \"generateVideoFrames\";\n ScryptedInterfaceMethod[\"connectStream\"] = \"connectStream\";\n ScryptedInterfaceMethod[\"getTTYSettings\"] = \"getTTYSettings\";\n})(ScryptedInterfaceMethod || (exports.ScryptedInterfaceMethod = ScryptedInterfaceMethod = {}));\nexports.ScryptedInterfaceDescriptors = {\n \"ScryptedDevice\": {\n \"name\": \"ScryptedDevice\",\n \"methods\": [\n \"listen\",\n \"probe\",\n \"setMixins\",\n \"setName\",\n \"setRoom\",\n \"setType\"\n ],\n \"properties\": [\n \"id\",\n \"info\",\n \"interfaces\",\n \"mixins\",\n \"name\",\n \"nativeId\",\n \"pluginId\",\n \"providedInterfaces\",\n \"providedName\",\n \"providedRoom\",\n \"providedType\",\n \"providerId\",\n \"room\",\n \"type\"\n ]\n },\n \"ScryptedPlugin\": {\n \"name\": \"ScryptedPlugin\",\n \"methods\": [\n \"getPluginJson\"\n ],\n \"properties\": []\n },\n \"ScryptedPluginRuntime\": {\n \"name\": \"ScryptedPluginRuntime\",\n \"methods\": [],\n \"properties\": [\n \"scryptedRuntimeArguments\"\n ]\n },\n \"OnOff\": {\n \"name\": \"OnOff\",\n \"methods\": [\n \"turnOff\",\n \"turnOn\"\n ],\n \"properties\": [\n \"on\"\n ]\n },\n \"Brightness\": {\n \"name\": \"Brightness\",\n \"methods\": [\n \"setBrightness\"\n ],\n \"properties\": [\n \"brightness\"\n ]\n },\n \"ColorSettingTemperature\": {\n \"name\": \"ColorSettingTemperature\",\n \"methods\": [\n \"getTemperatureMaxK\",\n \"getTemperatureMinK\",\n \"setColorTemperature\"\n ],\n \"properties\": [\n \"colorTemperature\"\n ]\n },\n \"ColorSettingRgb\": {\n \"name\": \"ColorSettingRgb\",\n \"methods\": [\n \"setRgb\"\n ],\n \"properties\": [\n \"rgb\"\n ]\n },\n \"ColorSettingHsv\": {\n \"name\": \"ColorSettingHsv\",\n \"methods\": [\n \"setHsv\"\n ],\n \"properties\": [\n \"hsv\"\n ]\n },\n \"Buttons\": {\n \"name\": \"Buttons\",\n \"methods\": [],\n \"properties\": [\n \"buttons\"\n ]\n },\n \"PressButtons\": {\n \"name\": \"PressButtons\",\n \"methods\": [\n \"pressButton\"\n ],\n \"properties\": []\n },\n \"Sensors\": {\n \"name\": \"Sensors\",\n \"methods\": [],\n \"properties\": [\n \"sensors\"\n ]\n },\n \"Notifier\": {\n \"name\": \"Notifier\",\n \"methods\": [\n \"sendNotification\"\n ],\n \"properties\": []\n },\n \"StartStop\": {\n \"name\": \"StartStop\",\n \"methods\": [\n \"start\",\n \"stop\"\n ],\n \"properties\": [\n \"running\"\n ]\n },\n \"Pause\": {\n \"name\": \"Pause\",\n \"methods\": [\n \"pause\",\n \"resume\"\n ],\n \"properties\": [\n \"paused\"\n ]\n },\n \"Dock\": {\n \"name\": \"Dock\",\n \"methods\": [\n \"dock\"\n ],\n \"properties\": [\n \"docked\"\n ]\n },\n \"TemperatureSetting\": {\n \"name\": \"TemperatureSetting\",\n \"methods\": [\n \"setTemperature\"\n ],\n \"properties\": [\n \"temperatureSetting\"\n ]\n },\n \"Thermometer\": {\n \"name\": \"Thermometer\",\n \"methods\": [\n \"setTemperatureUnit\"\n ],\n \"properties\": [\n \"temperature\",\n \"temperatureUnit\"\n ]\n },\n \"HumiditySensor\": {\n \"name\": \"HumiditySensor\",\n \"methods\": [],\n \"properties\": [\n \"humidity\"\n ]\n },\n \"Camera\": {\n \"name\": \"Camera\",\n \"methods\": [\n \"getPictureOptions\",\n \"takePicture\"\n ],\n \"properties\": []\n },\n \"Microphone\": {\n \"name\": \"Microphone\",\n \"methods\": [\n \"getAudioStream\"\n ],\n \"properties\": []\n },\n \"AudioVolumeControl\": {\n \"name\": \"AudioVolumeControl\",\n \"methods\": [\n \"setAudioVolumes\"\n ],\n \"properties\": [\n \"audioVolumes\"\n ]\n },\n \"Display\": {\n \"name\": \"Display\",\n \"methods\": [\n \"startDisplay\",\n \"stopDisplay\"\n ],\n \"properties\": []\n },\n \"VideoCamera\": {\n \"name\": \"VideoCamera\",\n \"methods\": [\n \"getVideoStream\",\n \"getVideoStreamOptions\"\n ],\n \"properties\": []\n },\n \"VideoCameraMask\": {\n \"name\": \"VideoCameraMask\",\n \"methods\": [\n \"getPrivacyMasks\",\n \"setPrivacyMasks\"\n ],\n \"properties\": []\n },\n \"VideoTextOverlays\": {\n \"name\": \"VideoTextOverlays\",\n \"methods\": [\n \"getVideoTextOverlays\",\n \"setVideoTextOverlay\"\n ],\n \"properties\": []\n },\n \"VideoRecorder\": {\n \"name\": \"VideoRecorder\",\n \"methods\": [\n \"getRecordingStream\",\n \"getRecordingStreamCurrentTime\",\n \"getRecordingStreamOptions\",\n \"getRecordingStreamThumbnail\"\n ],\n \"properties\": [\n \"recordingActive\"\n ]\n },\n \"VideoRecorderManagement\": {\n \"name\": \"VideoRecorderManagement\",\n \"methods\": [\n \"deleteRecordingStream\",\n \"setRecordingActive\"\n ],\n \"properties\": []\n },\n \"PanTiltZoom\": {\n \"name\": \"PanTiltZoom\",\n \"methods\": [\n \"ptzCommand\"\n ],\n \"properties\": [\n \"ptzCapabilities\"\n ]\n },\n \"EventRecorder\": {\n \"name\": \"EventRecorder\",\n \"methods\": [\n \"getRecordedEvents\"\n ],\n \"properties\": []\n },\n \"VideoClips\": {\n \"name\": \"VideoClips\",\n \"methods\": [\n \"getVideoClip\",\n \"getVideoClips\",\n \"getVideoClipThumbnail\",\n \"removeVideoClips\"\n ],\n \"properties\": []\n },\n \"VideoCameraConfiguration\": {\n \"name\": \"VideoCameraConfiguration\",\n \"methods\": [\n \"setVideoStreamOptions\"\n ],\n \"properties\": []\n },\n \"Intercom\": {\n \"name\": \"Intercom\",\n \"methods\": [\n \"startIntercom\",\n \"stopIntercom\"\n ],\n \"properties\": []\n },\n \"Lock\": {\n \"name\": \"Lock\",\n \"methods\": [\n \"lock\",\n \"unlock\"\n ],\n \"properties\": [\n \"lockState\"\n ]\n },\n \"PasswordStore\": {\n \"name\": \"PasswordStore\",\n \"methods\": [\n \"addPassword\",\n \"getPasswords\",\n \"removePassword\"\n ],\n \"properties\": []\n },\n \"Scene\": {\n \"name\": \"Scene\",\n \"methods\": [\n \"activate\",\n \"deactivate\",\n \"isReversible\"\n ],\n \"properties\": []\n },\n \"Entry\": {\n \"name\": \"Entry\",\n \"methods\": [\n \"closeEntry\",\n \"openEntry\"\n ],\n \"properties\": []\n },\n \"EntrySensor\": {\n \"name\": \"EntrySensor\",\n \"methods\": [],\n \"properties\": [\n \"entryOpen\"\n ]\n },\n \"DeviceProvider\": {\n \"name\": \"DeviceProvider\",\n \"methods\": [\n \"getDevice\",\n \"releaseDevice\"\n ],\n \"properties\": []\n },\n \"DeviceDiscovery\": {\n \"name\": \"DeviceDiscovery\",\n \"methods\": [\n \"adoptDevice\",\n \"discoverDevices\"\n ],\n \"properties\": []\n },\n \"DeviceCreator\": {\n \"name\": \"DeviceCreator\",\n \"methods\": [\n \"createDevice\",\n \"getCreateDeviceSettings\"\n ],\n \"properties\": []\n },\n \"Battery\": {\n \"name\": \"Battery\",\n \"methods\": [],\n \"properties\": [\n \"batteryLevel\"\n ]\n },\n \"Charger\": {\n \"name\": \"Charger\",\n \"methods\": [],\n \"properties\": [\n \"chargeState\"\n ]\n },\n \"Reboot\": {\n \"name\": \"Reboot\",\n \"methods\": [\n \"reboot\"\n ],\n \"properties\": []\n },\n \"Refresh\": {\n \"name\": \"Refresh\",\n \"methods\": [\n \"getRefreshFrequency\",\n \"refresh\"\n ],\n \"properties\": []\n },\n \"MediaPlayer\": {\n \"name\": \"MediaPlayer\",\n \"methods\": [\n \"getMediaStatus\",\n \"load\",\n \"seek\",\n \"skipNext\",\n \"skipPrevious\"\n ],\n \"properties\": []\n },\n \"Online\": {\n \"name\": \"Online\",\n \"methods\": [],\n \"properties\": [\n \"online\"\n ]\n },\n \"BufferConverter\": {\n \"name\": \"BufferConverter\",\n \"methods\": [\n \"convert\"\n ],\n \"properties\": [\n \"fromMimeType\",\n \"toMimeType\"\n ]\n },\n \"MediaConverter\": {\n \"name\": \"MediaConverter\",\n \"methods\": [\n \"convertMedia\"\n ],\n \"properties\": [\n \"converters\"\n ]\n },\n \"Settings\": {\n \"name\": \"Settings\",\n \"methods\": [\n \"getSettings\",\n \"putSetting\"\n ],\n \"properties\": []\n },\n \"BinarySensor\": {\n \"name\": \"BinarySensor\",\n \"methods\": [],\n \"properties\": [\n \"binaryState\"\n ]\n },\n \"TamperSensor\": {\n \"name\": \"TamperSensor\",\n \"methods\": [],\n \"properties\": [\n \"tampered\"\n ]\n },\n \"Sleep\": {\n \"name\": \"Sleep\",\n \"methods\": [],\n \"properties\": [\n \"sleeping\"\n ]\n },\n \"PowerSensor\": {\n \"name\": \"PowerSensor\",\n \"methods\": [],\n \"properties\": [\n \"powerDetected\"\n ]\n },\n \"AudioSensor\": {\n \"name\": \"AudioSensor\",\n \"methods\": [],\n \"properties\": [\n \"audioDetected\"\n ]\n },\n \"MotionSensor\": {\n \"name\": \"MotionSensor\",\n \"methods\": [],\n \"properties\": [\n \"motionDetected\"\n ]\n },\n \"AmbientLightSensor\": {\n \"name\": \"AmbientLightSensor\",\n \"methods\": [],\n \"properties\": [\n \"ambientLight\"\n ]\n },\n \"OccupancySensor\": {\n \"name\": \"OccupancySensor\",\n \"methods\": [],\n \"properties\": [\n \"occupied\"\n ]\n },\n \"FloodSensor\": {\n \"name\": \"FloodSensor\",\n \"methods\": [],\n \"properties\": [\n \"flooded\"\n ]\n },\n \"UltravioletSensor\": {\n \"name\": \"UltravioletSensor\",\n \"methods\": [],\n \"properties\": [\n \"ultraviolet\"\n ]\n },\n \"LuminanceSensor\": {\n \"name\": \"LuminanceSensor\",\n \"methods\": [],\n \"properties\": [\n \"luminance\"\n ]\n },\n \"PositionSensor\": {\n \"name\": \"PositionSensor\",\n \"methods\": [],\n \"properties\": [\n \"position\"\n ]\n },\n \"SecuritySystem\": {\n \"name\": \"SecuritySystem\",\n \"methods\": [\n \"armSecuritySystem\",\n \"disarmSecuritySystem\"\n ],\n \"properties\": [\n \"securitySystemState\"\n ]\n },\n \"PM10Sensor\": {\n \"name\": \"PM10Sensor\",\n \"methods\": [],\n \"properties\": [\n \"pm10Density\"\n ]\n },\n \"PM25Sensor\": {\n \"name\": \"PM25Sensor\",\n \"methods\": [],\n \"properties\": [\n \"pm25Density\"\n ]\n },\n \"VOCSensor\": {\n \"name\": \"VOCSensor\",\n \"methods\": [],\n \"properties\": [\n \"vocDensity\"\n ]\n },\n \"NOXSensor\": {\n \"name\": \"NOXSensor\",\n \"methods\": [],\n \"properties\": [\n \"noxDensity\"\n ]\n },\n \"CO2Sensor\": {\n \"name\": \"CO2Sensor\",\n \"methods\": [],\n \"properties\": [\n \"co2ppm\"\n ]\n },\n \"AirQualitySensor\": {\n \"name\": \"AirQualitySensor\",\n \"methods\": [],\n \"properties\": [\n \"airQuality\"\n ]\n },\n \"AirPurifier\": {\n \"name\": \"AirPurifier\",\n \"methods\": [\n \"setAirPurifierState\"\n ],\n \"properties\": [\n \"airPurifierState\"\n ]\n },\n \"FilterMaintenance\": {\n \"name\": \"FilterMaintenance\",\n \"methods\": [],\n \"properties\": [\n \"filterChangeIndication\",\n \"filterLifeLevel\"\n ]\n },\n \"Readme\": {\n \"name\": \"Readme\",\n \"methods\": [\n \"getReadmeMarkdown\"\n ],\n \"properties\": []\n },\n \"OauthClient\": {\n \"name\": \"OauthClient\",\n \"methods\": [\n \"getOauthUrl\",\n \"onOauthCallback\"\n ],\n \"properties\": []\n },\n \"MixinProvider\": {\n \"name\": \"MixinProvider\",\n \"methods\": [\n \"canMixin\",\n \"getMixin\",\n \"releaseMixin\"\n ],\n \"properties\": []\n },\n \"HttpRequestHandler\": {\n \"name\": \"HttpRequestHandler\",\n \"methods\": [\n \"onRequest\"\n ],\n \"properties\": []\n },\n \"EngineIOHandler\": {\n \"name\": \"EngineIOHandler\",\n \"methods\": [\n \"onConnection\"\n ],\n \"properties\": []\n },\n \"PushHandler\": {\n \"name\": \"PushHandler\",\n \"methods\": [\n \"onPush\"\n ],\n \"properties\": []\n },\n \"Program\": {\n \"name\": \"Program\",\n \"methods\": [\n \"run\"\n ],\n \"properties\": []\n },\n \"Scriptable\": {\n \"name\": \"Scriptable\",\n \"methods\": [\n \"eval\",\n \"loadScripts\",\n \"saveScript\"\n ],\n \"properties\": []\n },\n \"ClusterForkInterface\": {\n \"name\": \"ClusterForkInterface\",\n \"methods\": [\n \"forkInterface\"\n ],\n \"properties\": []\n },\n \"ObjectTracker\": {\n \"name\": \"ObjectTracker\",\n \"methods\": [\n \"trackObjects\"\n ],\n \"properties\": []\n },\n \"ObjectDetector\": {\n \"name\": \"ObjectDetector\",\n \"methods\": [\n \"getDetectionInput\",\n \"getObjectTypes\"\n ],\n \"properties\": []\n },\n \"ObjectDetection\": {\n \"name\": \"ObjectDetection\",\n \"methods\": [\n \"detectObjects\",\n \"generateObjectDetections\",\n \"getDetectionModel\"\n ],\n \"properties\": []\n },\n \"ObjectDetectionPreview\": {\n \"name\": \"ObjectDetectionPreview\",\n \"methods\": [],\n \"properties\": []\n },\n \"ObjectDetectionGenerator\": {\n \"name\": \"ObjectDetectionGenerator\",\n \"methods\": [],\n \"properties\": []\n },\n \"HumiditySetting\": {\n \"name\": \"HumiditySetting\",\n \"methods\": [\n \"setHumidity\"\n ],\n \"properties\": [\n \"humiditySetting\"\n ]\n },\n \"Fan\": {\n \"name\": \"Fan\",\n \"methods\": [\n \"setFan\"\n ],\n \"properties\": [\n \"fan\"\n ]\n },\n \"RTCSignalingChannel\": {\n \"name\": \"RTCSignalingChannel\",\n \"methods\": [\n \"startRTCSignalingSession\"\n ],\n \"properties\": []\n },\n \"RTCSignalingClient\": {\n \"name\": \"RTCSignalingClient\",\n \"methods\": [\n \"createRTCSignalingSession\"\n ],\n \"properties\": []\n },\n \"LauncherApplication\": {\n \"name\": \"LauncherApplication\",\n \"methods\": [],\n \"properties\": [\n \"applicationInfo\"\n ]\n },\n \"ScryptedUser\": {\n \"name\": \"ScryptedUser\",\n \"methods\": [\n \"getScryptedUserAccessControl\"\n ],\n \"properties\": []\n },\n \"VideoFrameGenerator\": {\n \"name\": \"VideoFrameGenerator\",\n \"methods\": [\n \"generateVideoFrames\"\n ],\n \"properties\": []\n },\n \"StreamService\": {\n \"name\": \"StreamService\",\n \"methods\": [\n \"connectStream\"\n ],\n \"properties\": []\n },\n \"TTY\": {\n \"name\": \"TTY\",\n \"methods\": [],\n \"properties\": []\n },\n \"TTYSettings\": {\n \"name\": \"TTYSettings\",\n \"methods\": [\n \"getTTYSettings\"\n ],\n \"properties\": []\n },\n \"ScryptedSystemDevice\": {\n \"name\": \"ScryptedSystemDevice\",\n \"methods\": [],\n \"properties\": [\n \"systemDevice\"\n ]\n },\n \"ScryptedDeviceCreator\": {\n \"name\": \"ScryptedDeviceCreator\",\n \"methods\": [],\n \"properties\": []\n },\n \"ScryptedSettings\": {\n \"name\": \"ScryptedSettings\",\n \"methods\": [],\n \"properties\": []\n }\n};\n/**\n * @category Core Reference\n */\nvar ScryptedDeviceType;\n(function (ScryptedDeviceType) {\n /**\n * @deprecated\n */\n ScryptedDeviceType[\"Builtin\"] = \"Builtin\";\n /**\n * Internal devices will not show up in device lists unless explicitly searched.\n */\n ScryptedDeviceType[\"Internal\"] = \"Internal\";\n ScryptedDeviceType[\"Camera\"] = \"Camera\";\n ScryptedDeviceType[\"Fan\"] = \"Fan\";\n ScryptedDeviceType[\"Light\"] = \"Light\";\n ScryptedDeviceType[\"Switch\"] = \"Switch\";\n ScryptedDeviceType[\"Outlet\"] = \"Outlet\";\n ScryptedDeviceType[\"Sensor\"] = \"Sensor\";\n ScryptedDeviceType[\"Scene\"] = \"Scene\";\n ScryptedDeviceType[\"Program\"] = \"Program\";\n ScryptedDeviceType[\"Automation\"] = \"Automation\";\n ScryptedDeviceType[\"Vacuum\"] = \"Vacuum\";\n ScryptedDeviceType[\"Notifier\"] = \"Notifier\";\n ScryptedDeviceType[\"Thermostat\"] = \"Thermostat\";\n ScryptedDeviceType[\"Lock\"] = \"Lock\";\n ScryptedDeviceType[\"PasswordControl\"] = \"PasswordControl\";\n /**\n * Displays have audio and video output.\n */\n ScryptedDeviceType[\"Display\"] = \"Display\";\n /**\n * Smart Displays have two way audio and video.\n */\n ScryptedDeviceType[\"SmartDisplay\"] = \"SmartDisplay\";\n ScryptedDeviceType[\"Speaker\"] = \"Speaker\";\n /**\n * Smart Speakers have two way audio.\n */\n ScryptedDeviceType[\"SmartSpeaker\"] = \"SmartSpeaker\";\n ScryptedDeviceType[\"Event\"] = \"Event\";\n ScryptedDeviceType[\"Entry\"] = \"Entry\";\n ScryptedDeviceType[\"Garage\"] = \"Garage\";\n ScryptedDeviceType[\"DeviceProvider\"] = \"DeviceProvider\";\n ScryptedDeviceType[\"DataSource\"] = \"DataSource\";\n ScryptedDeviceType[\"API\"] = \"API\";\n ScryptedDeviceType[\"Doorbell\"] = \"Doorbell\";\n ScryptedDeviceType[\"Irrigation\"] = \"Irrigation\";\n ScryptedDeviceType[\"Valve\"] = \"Valve\";\n ScryptedDeviceType[\"Person\"] = \"Person\";\n ScryptedDeviceType[\"SecuritySystem\"] = \"SecuritySystem\";\n ScryptedDeviceType[\"WindowCovering\"] = \"WindowCovering\";\n ScryptedDeviceType[\"Siren\"] = \"Siren\";\n ScryptedDeviceType[\"AirPurifier\"] = \"AirPurifier\";\n ScryptedDeviceType[\"Internet\"] = \"Internet\";\n ScryptedDeviceType[\"Network\"] = \"Network\";\n ScryptedDeviceType[\"Bridge\"] = \"Bridge\";\n ScryptedDeviceType[\"Unknown\"] = \"Unknown\";\n})(ScryptedDeviceType || (exports.ScryptedDeviceType = ScryptedDeviceType = {}));\nvar HumidityMode;\n(function (HumidityMode) {\n HumidityMode[\"Humidify\"] = \"Humidify\";\n HumidityMode[\"Dehumidify\"] = \"Dehumidify\";\n HumidityMode[\"Auto\"] = \"Auto\";\n HumidityMode[\"Off\"] = \"Off\";\n})(HumidityMode || (exports.HumidityMode = HumidityMode = {}));\nvar FanMode;\n(function (FanMode) {\n FanMode[\"Auto\"] = \"Auto\";\n FanMode[\"Manual\"] = \"Manual\";\n})(FanMode || (exports.FanMode = FanMode = {}));\nvar TemperatureUnit;\n(function (TemperatureUnit) {\n TemperatureUnit[\"C\"] = \"C\";\n TemperatureUnit[\"F\"] = \"F\";\n})(TemperatureUnit || (exports.TemperatureUnit = TemperatureUnit = {}));\nvar ThermostatMode;\n(function (ThermostatMode) {\n ThermostatMode[\"Off\"] = \"Off\";\n ThermostatMode[\"Cool\"] = \"Cool\";\n ThermostatMode[\"Heat\"] = \"Heat\";\n ThermostatMode[\"HeatCool\"] = \"HeatCool\";\n ThermostatMode[\"Auto\"] = \"Auto\";\n ThermostatMode[\"FanOnly\"] = \"FanOnly\";\n ThermostatMode[\"Purifier\"] = \"Purifier\";\n ThermostatMode[\"Eco\"] = \"Eco\";\n ThermostatMode[\"Dry\"] = \"Dry\";\n ThermostatMode[\"On\"] = \"On\";\n})(ThermostatMode || (exports.ThermostatMode = ThermostatMode = {}));\nvar PanTiltZoomMovement;\n(function (PanTiltZoomMovement) {\n PanTiltZoomMovement[\"Absolute\"] = \"Absolute\";\n PanTiltZoomMovement[\"Relative\"] = \"Relative\";\n PanTiltZoomMovement[\"Continuous\"] = \"Continuous\";\n PanTiltZoomMovement[\"Preset\"] = \"Preset\";\n PanTiltZoomMovement[\"Home\"] = \"Home\";\n})(PanTiltZoomMovement || (exports.PanTiltZoomMovement = PanTiltZoomMovement = {}));\nvar LockState;\n(function (LockState) {\n LockState[\"Locked\"] = \"Locked\";\n LockState[\"Unlocked\"] = \"Unlocked\";\n LockState[\"Jammed\"] = \"Jammed\";\n})(LockState || (exports.LockState = LockState = {}));\nvar ChargeState;\n(function (ChargeState) {\n ChargeState[\"Trickle\"] = \"trickle\";\n ChargeState[\"Charging\"] = \"charging\";\n ChargeState[\"NotCharging\"] = \"not-charging\";\n})(ChargeState || (exports.ChargeState = ChargeState = {}));\nvar AirPurifierStatus;\n(function (AirPurifierStatus) {\n AirPurifierStatus[\"Inactive\"] = \"Inactive\";\n AirPurifierStatus[\"Idle\"] = \"Idle\";\n AirPurifierStatus[\"Active\"] = \"Active\";\n AirPurifierStatus[\"ActiveNightMode\"] = \"ActiveNightMode\";\n})(AirPurifierStatus || (exports.AirPurifierStatus = AirPurifierStatus = {}));\nvar AirPurifierMode;\n(function (AirPurifierMode) {\n AirPurifierMode[\"Manual\"] = \"Manual\";\n AirPurifierMode[\"Automatic\"] = \"Automatic\";\n})(AirPurifierMode || (exports.AirPurifierMode = AirPurifierMode = {}));\nvar AirQuality;\n(function (AirQuality) {\n AirQuality[\"Unknown\"] = \"Unknown\";\n AirQuality[\"Excellent\"] = \"Excellent\";\n AirQuality[\"Good\"] = \"Good\";\n AirQuality[\"Fair\"] = \"Fair\";\n AirQuality[\"Inferior\"] = \"Inferior\";\n AirQuality[\"Poor\"] = \"Poor\";\n})(AirQuality || (exports.AirQuality = AirQuality = {}));\nvar SecuritySystemMode;\n(function (SecuritySystemMode) {\n SecuritySystemMode[\"Disarmed\"] = \"Disarmed\";\n SecuritySystemMode[\"HomeArmed\"] = \"HomeArmed\";\n SecuritySystemMode[\"AwayArmed\"] = \"AwayArmed\";\n SecuritySystemMode[\"NightArmed\"] = \"NightArmed\";\n})(SecuritySystemMode || (exports.SecuritySystemMode = SecuritySystemMode = {}));\nvar SecuritySystemObstruction;\n(function (SecuritySystemObstruction) {\n SecuritySystemObstruction[\"Sensor\"] = \"Sensor\";\n SecuritySystemObstruction[\"Occupied\"] = \"Occupied\";\n SecuritySystemObstruction[\"Time\"] = \"Time\";\n SecuritySystemObstruction[\"Error\"] = \"Error\";\n})(SecuritySystemObstruction || (exports.SecuritySystemObstruction = SecuritySystemObstruction = {}));\nvar MediaPlayerState;\n(function (MediaPlayerState) {\n MediaPlayerState[\"Idle\"] = \"Idle\";\n MediaPlayerState[\"Playing\"] = \"Playing\";\n MediaPlayerState[\"Paused\"] = \"Paused\";\n MediaPlayerState[\"Buffering\"] = \"Buffering\";\n})(MediaPlayerState || (exports.MediaPlayerState = MediaPlayerState = {}));\nvar ScryptedInterface;\n(function (ScryptedInterface) {\n ScryptedInterface[\"ScryptedDevice\"] = \"ScryptedDevice\";\n ScryptedInterface[\"ScryptedPlugin\"] = \"ScryptedPlugin\";\n ScryptedInterface[\"ScryptedPluginRuntime\"] = \"ScryptedPluginRuntime\";\n ScryptedInterface[\"OnOff\"] = \"OnOff\";\n ScryptedInterface[\"Brightness\"] = \"Brightness\";\n ScryptedInterface[\"ColorSettingTemperature\"] = \"ColorSettingTemperature\";\n ScryptedInterface[\"ColorSettingRgb\"] = \"ColorSettingRgb\";\n ScryptedInterface[\"ColorSettingHsv\"] = \"ColorSettingHsv\";\n ScryptedInterface[\"Buttons\"] = \"Buttons\";\n ScryptedInterface[\"PressButtons\"] = \"PressButtons\";\n ScryptedInterface[\"Sensors\"] = \"Sensors\";\n ScryptedInterface[\"Notifier\"] = \"Notifier\";\n ScryptedInterface[\"StartStop\"] = \"StartStop\";\n ScryptedInterface[\"Pause\"] = \"Pause\";\n ScryptedInterface[\"Dock\"] = \"Dock\";\n ScryptedInterface[\"TemperatureSetting\"] = \"TemperatureSetting\";\n ScryptedInterface[\"Thermometer\"] = \"Thermometer\";\n ScryptedInterface[\"HumiditySensor\"] = \"HumiditySensor\";\n ScryptedInterface[\"Camera\"] = \"Camera\";\n ScryptedInterface[\"Microphone\"] = \"Microphone\";\n ScryptedInterface[\"AudioVolumeControl\"] = \"AudioVolumeControl\";\n ScryptedInterface[\"Display\"] = \"Display\";\n ScryptedInterface[\"VideoCamera\"] = \"VideoCamera\";\n ScryptedInterface[\"VideoCameraMask\"] = \"VideoCameraMask\";\n ScryptedInterface[\"VideoTextOverlays\"] = \"VideoTextOverlays\";\n ScryptedInterface[\"VideoRecorder\"] = \"VideoRecorder\";\n ScryptedInterface[\"VideoRecorderManagement\"] = \"VideoRecorderManagement\";\n ScryptedInterface[\"PanTiltZoom\"] = \"PanTiltZoom\";\n ScryptedInterface[\"EventRecorder\"] = \"EventRecorder\";\n ScryptedInterface[\"VideoClips\"] = \"VideoClips\";\n ScryptedInterface[\"VideoCameraConfiguration\"] = \"VideoCameraConfiguration\";\n ScryptedInterface[\"Intercom\"] = \"Intercom\";\n ScryptedInterface[\"Lock\"] = \"Lock\";\n ScryptedInterface[\"PasswordStore\"] = \"PasswordStore\";\n ScryptedInterface[\"Scene\"] = \"Scene\";\n ScryptedInterface[\"Entry\"] = \"Entry\";\n ScryptedInterface[\"EntrySensor\"] = \"EntrySensor\";\n ScryptedInterface[\"DeviceProvider\"] = \"DeviceProvider\";\n ScryptedInterface[\"DeviceDiscovery\"] = \"DeviceDiscovery\";\n ScryptedInterface[\"DeviceCreator\"] = \"DeviceCreator\";\n ScryptedInterface[\"Battery\"] = \"Battery\";\n ScryptedInterface[\"Charger\"] = \"Charger\";\n ScryptedInterface[\"Reboot\"] = \"Reboot\";\n ScryptedInterface[\"Refresh\"] = \"Refresh\";\n ScryptedInterface[\"MediaPlayer\"] = \"MediaPlayer\";\n ScryptedInterface[\"Online\"] = \"Online\";\n ScryptedInterface[\"BufferConverter\"] = \"BufferConverter\";\n ScryptedInterface[\"MediaConverter\"] = \"MediaConverter\";\n ScryptedInterface[\"Settings\"] = \"Settings\";\n ScryptedInterface[\"BinarySensor\"] = \"BinarySensor\";\n ScryptedInterface[\"TamperSensor\"] = \"TamperSensor\";\n ScryptedInterface[\"Sleep\"] = \"Sleep\";\n ScryptedInterface[\"PowerSensor\"] = \"PowerSensor\";\n ScryptedInterface[\"AudioSensor\"] = \"AudioSensor\";\n ScryptedInterface[\"MotionSensor\"] = \"MotionSensor\";\n ScryptedInterface[\"AmbientLightSensor\"] = \"AmbientLightSensor\";\n ScryptedInterface[\"OccupancySensor\"] = \"OccupancySensor\";\n ScryptedInterface[\"FloodSensor\"] = \"FloodSensor\";\n ScryptedInterface[\"UltravioletSensor\"] = \"UltravioletSensor\";\n ScryptedInterface[\"LuminanceSensor\"] = \"LuminanceSensor\";\n ScryptedInterface[\"PositionSensor\"] = \"PositionSensor\";\n ScryptedInterface[\"SecuritySystem\"] = \"SecuritySystem\";\n ScryptedInterface[\"PM10Sensor\"] = \"PM10Sensor\";\n ScryptedInterface[\"PM25Sensor\"] = \"PM25Sensor\";\n ScryptedInterface[\"VOCSensor\"] = \"VOCSensor\";\n ScryptedInterface[\"NOXSensor\"] = \"NOXSensor\";\n ScryptedInterface[\"CO2Sensor\"] = \"CO2Sensor\";\n ScryptedInterface[\"AirQualitySensor\"] = \"AirQualitySensor\";\n ScryptedInterface[\"AirPurifier\"] = \"AirPurifier\";\n ScryptedInterface[\"FilterMaintenance\"] = \"FilterMaintenance\";\n ScryptedInterface[\"Readme\"] = \"Readme\";\n ScryptedInterface[\"OauthClient\"] = \"OauthClient\";\n ScryptedInterface[\"MixinProvider\"] = \"MixinProvider\";\n ScryptedInterface[\"HttpRequestHandler\"] = \"HttpRequestHandler\";\n ScryptedInterface[\"EngineIOHandler\"] = \"EngineIOHandler\";\n ScryptedInterface[\"PushHandler\"] = \"PushHandler\";\n ScryptedInterface[\"Program\"] = \"Program\";\n ScryptedInterface[\"Scriptable\"] = \"Scriptable\";\n ScryptedInterface[\"ClusterForkInterface\"] = \"ClusterForkInterface\";\n ScryptedInterface[\"ObjectTracker\"] = \"ObjectTracker\";\n ScryptedInterface[\"ObjectDetector\"] = \"ObjectDetector\";\n ScryptedInterface[\"ObjectDetection\"] = \"ObjectDetection\";\n ScryptedInterface[\"ObjectDetectionPreview\"] = \"ObjectDetectionPreview\";\n ScryptedInterface[\"ObjectDetectionGenerator\"] = \"ObjectDetectionGenerator\";\n ScryptedInterface[\"HumiditySetting\"] = \"HumiditySetting\";\n ScryptedInterface[\"Fan\"] = \"Fan\";\n ScryptedInterface[\"RTCSignalingChannel\"] = \"RTCSignalingChannel\";\n ScryptedInterface[\"RTCSignalingClient\"] = \"RTCSignalingClient\";\n ScryptedInterface[\"LauncherApplication\"] = \"LauncherApplication\";\n ScryptedInterface[\"ScryptedUser\"] = \"ScryptedUser\";\n ScryptedInterface[\"VideoFrameGenerator\"] = \"VideoFrameGenerator\";\n ScryptedInterface[\"StreamService\"] = \"StreamService\";\n ScryptedInterface[\"TTY\"] = \"TTY\";\n ScryptedInterface[\"TTYSettings\"] = \"TTYSettings\";\n ScryptedInterface[\"ScryptedSystemDevice\"] = \"ScryptedSystemDevice\";\n ScryptedInterface[\"ScryptedDeviceCreator\"] = \"ScryptedDeviceCreator\";\n ScryptedInterface[\"ScryptedSettings\"] = \"ScryptedSettings\";\n})(ScryptedInterface || (exports.ScryptedInterface = ScryptedInterface = {}));\nvar ScryptedMimeTypes;\n(function (ScryptedMimeTypes) {\n ScryptedMimeTypes[\"Url\"] = \"text/x-uri\";\n ScryptedMimeTypes[\"InsecureLocalUrl\"] = \"text/x-insecure-local-uri\";\n ScryptedMimeTypes[\"LocalUrl\"] = \"text/x-local-uri\";\n ScryptedMimeTypes[\"ServerId\"] = \"text/x-server-id\";\n ScryptedMimeTypes[\"PushEndpoint\"] = \"text/x-push-endpoint\";\n ScryptedMimeTypes[\"SchemePrefix\"] = \"x-scrypted/x-scrypted-scheme-\";\n ScryptedMimeTypes[\"MediaStreamUrl\"] = \"text/x-media-url\";\n ScryptedMimeTypes[\"MediaObject\"] = \"x-scrypted/x-scrypted-media-object\";\n ScryptedMimeTypes[\"RequestMediaObject\"] = \"x-scrypted/x-scrypted-request-media-object\";\n ScryptedMimeTypes[\"RequestMediaStream\"] = \"x-scrypted/x-scrypted-request-stream\";\n ScryptedMimeTypes[\"MediaStreamFeedback\"] = \"x-scrypted/x-media-stream-feedback\";\n ScryptedMimeTypes[\"FFmpegInput\"] = \"x-scrypted/x-ffmpeg-input\";\n ScryptedMimeTypes[\"FFmpegTranscodeStream\"] = \"x-scrypted/x-ffmpeg-transcode-stream\";\n ScryptedMimeTypes[\"RTCSignalingChannel\"] = \"x-scrypted/x-scrypted-rtc-signaling-channel\";\n ScryptedMimeTypes[\"RTCSignalingSession\"] = \"x-scrypted/x-scrypted-rtc-signaling-session\";\n ScryptedMimeTypes[\"RTCConnectionManagement\"] = \"x-scrypted/x-scrypted-rtc-connection-management\";\n ScryptedMimeTypes[\"Image\"] = \"x-scrypted/x-scrypted-image\";\n})(ScryptedMimeTypes || (exports.ScryptedMimeTypes = ScryptedMimeTypes = {}));\n//# sourceMappingURL=index.js.map","import sdk, {\n ScryptedDeviceBase,\n Settings,\n Setting,\n HttpRequestHandler,\n HttpRequest,\n HttpResponse,\n ScryptedInterface,\n ScryptedDeviceType,\n ObjectsDetected,\n ObjectDetector,\n} from '@scrypted/sdk';\n\nconst { systemManager, deviceManager, mediaManager } = sdk;\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nconst LABELS = ['person', 'animal', 'face', 'vehicle', 'plate', 'package', 'discard'] as const;\ntype Label = typeof LABELS[number];\n\nconst CAPTURE_CLASSES = new Set(['person', 'cat', 'dog', 'animal', 'bird', 'face', 'vehicle', 'car', 'truck', 'bus', 'motorcycle', 'bicycle', 'plate', 'package']);\n\nconst RATE_OPTIONS = ['disabled', '1 per minute', '1 per 10 seconds', 'every detection'] as const;\ntype RateOption = typeof RATE_OPTIONS[number];\n\nconst RATE_MS: Record<RateOption, number> = {\n 'disabled': Infinity,\n '1 per minute': 60_000,\n '1 per 10 seconds': 10_000,\n 'every detection': 0,\n};\n\nconst MAX_CAPTURES = 2000;\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\ninterface CaptureRecord {\n id: string;\n cameraId: string;\n cameraName: string;\n timestamp: number;\n detectedClass: string;\n score: number;\n boundingBox: number[]; // [x, y, w, h] in pixels\n inputDimensions: number[]; // [width, height]\n detectionId?: string;\n label?: Label; // set after review\n reviewed: boolean;\n}\n\n// ─── Plugin ───────────────────────────────────────────────────────────────────\n\nclass DetectionTrainer extends ScryptedDeviceBase implements Settings, HttpRequestHandler {\n // Map<cameraId, lastCaptureTimestamp>\n private lastCapture = new Map<string, number>();\n // Map<captureId, CaptureRecord>\n private captures = new Map<string, CaptureRecord>();\n // Map<captureId, jpegBuffer>\n private images = new Map<string, Buffer>();\n // Active event listeners\n private listeners: (() => void)[] = [];\n\n constructor(nativeId?: string) {\n super(nativeId);\n this.loadState();\n this.registerListeners();\n }\n\n // ── Persistence ──────────────────────────────────────────────────────────\n\n private loadState() {\n try {\n const raw = this.storage.getItem('captures');\n if (raw) {\n const arr: CaptureRecord[] = JSON.parse(raw);\n for (const r of arr) this.captures.set(r.id, r);\n this.console.log(`Loaded ${this.captures.size} captures from storage.`);\n }\n } catch (e) {\n this.console.warn('Could not load captures from storage:', e);\n }\n // images are stored as individual items\n for (const [id] of this.captures) {\n const raw = this.storage.getItem(`img:${id}`);\n if (raw) this.images.set(id, Buffer.from(raw, 'base64'));\n }\n }\n\n private saveCaptures() {\n this.storage.setItem('captures', JSON.stringify([...this.captures.values()]));\n }\n\n private saveImage(id: string, buf: Buffer) {\n this.storage.setItem(`img:${id}`, buf.toString('base64'));\n }\n\n private deleteCapture(id: string) {\n const old = this.storage.getItem(`img:${id}`);\n if (old) this.storage.removeItem(`img:${id}`);\n this.captures.delete(id);\n this.images.delete(id);\n this.saveCaptures();\n }\n\n // ── Settings ─────────────────────────────────────────────────────────────\n\n async getSettings(): Promise<Setting[]> {\n const cameras = Object.keys(systemManager.getSystemState())\n .map(id => systemManager.getDeviceById(id))\n .filter(d => d &&\n (d.type === ScryptedDeviceType.Camera || d.type === ScryptedDeviceType.Doorbell) &&\n d.interfaces?.includes(ScryptedInterface.ObjectDetector)\n );\n\n let uiUrl: string;\n try {\n uiUrl = await sdk.endpointManager.getLocalEndpoint(undefined, { public: true });\n } catch {\n uiUrl = '/endpoint/scrypted-detection-trainer/public/';\n }\n\n const settings: Setting[] = [\n {\n key: 'info',\n title: 'Detection Trainer',\n description: `${this.captures.size} captures stored (${[...this.captures.values()].filter(c => !c.reviewed).length} pending review, ${[...this.captures.values()].filter(c => c.reviewed && c.label !== 'discard').length} labeled).`,\n readonly: true,\n value: '',\n },\n {\n key: 'open_ui',\n title: 'Review UI',\n description: 'Open the detection review and labeling interface.',\n type: 'html',\n readonly: true,\n value: `<a href=\"${uiUrl}\" target=\"_blank\" style=\"display:inline-block;padding:8px 16px;background:#1a4d8a;color:#fff;border-radius:6px;text-decoration:none;font-size:13px;\">Open Review UI ↗</a>`,\n },\n ];\n\n for (const cam of cameras) {\n const key = `rate:${cam.id}`;\n settings.push({\n key,\n title: cam.name,\n group: 'Capture Rate per Camera',\n description: 'How often to capture detections from this camera.',\n value: this.storage.getItem(key) || '1 per minute',\n choices: [...RATE_OPTIONS],\n });\n }\n\n return settings;\n }\n\n async putSetting(key: string, value: string) {\n if (key === 'open_ui' || key === 'ui_link' || key === 'info') return;\n this.storage.setItem(key, value);\n if (key.startsWith('rate:')) {\n // Re-register listeners when rates change\n this.registerListeners();\n }\n }\n\n // ── Listeners ─────────────────────────────────────────────────────────────\n\n private registerListeners() {\n // Remove old listeners\n for (const remove of this.listeners) remove();\n this.listeners = [];\n\n const cameras = Object.keys(systemManager.getSystemState())\n .map(id => systemManager.getDeviceById(id))\n .filter(d => d &&\n (d.type === ScryptedDeviceType.Camera || d.type === ScryptedDeviceType.Doorbell) &&\n d.interfaces?.includes(ScryptedInterface.ObjectDetector)\n );\n\n for (const cam of cameras) {\n const rateKey = `rate:${cam.id}`;\n const rateLabel = (this.storage.getItem(rateKey) || '1 per minute') as RateOption;\n if (rateLabel === 'disabled') continue;\n\n const listener = cam.listen(ScryptedInterface.ObjectDetector, async (source, details, data) => {\n await this.onDetection(cam.id, cam.name, data as ObjectsDetected, RATE_MS[rateLabel]);\n });\n this.listeners.push(() => listener.removeListener());\n }\n\n this.console.log(`Listening to ${this.listeners.length} camera(s).`);\n }\n\n // ── Detection Handler ─────────────────────────────────────────────────────\n\n private async onDetection(cameraId: string, cameraName: string, data: ObjectsDetected, rateLimitMs: number) {\n if (!data?.detections?.length || !data.inputDimensions) return;\n\n // Rate limit per camera\n const now = Date.now();\n const last = this.lastCapture.get(cameraId) || 0;\n if (now - last < rateLimitMs) return;\n\n // Filter to target classes\n const targets = data.detections.filter(d =>\n d.className && CAPTURE_CLASSES.has(d.className.toLowerCase()) && d.boundingBox\n );\n if (!targets.length) return;\n\n // Pick the highest-confidence target detection\n const best = targets.sort((a, b) => (b.score || 0) - (a.score || 0))[0];\n\n // Enforce max storage\n if (this.captures.size >= MAX_CAPTURES) {\n // Evict oldest unreviewed capture\n const oldest = [...this.captures.values()]\n .filter(c => !c.reviewed)\n .sort((a, b) => a.timestamp - b.timestamp)[0];\n if (oldest) this.deleteCapture(oldest.id);\n else return; // All reviewed, don't evict labeled data\n }\n\n this.lastCapture.set(cameraId, now);\n\n // Try to get the detection image\n let jpeg: Buffer | undefined;\n try {\n if (data.detectionId) {\n const cam = systemManager.getDeviceById(cameraId) as unknown as ObjectDetector;\n const mo = await cam.getDetectionInput(data.detectionId);\n jpeg = await mediaManager.convertMediaObjectToBuffer(mo, 'image/jpeg');\n }\n } catch (e) {\n this.console.warn(`Could not get detection image for ${cameraName}:`, e);\n }\n\n if (!jpeg) return; // Skip if no image\n\n const id = `${now}-${Math.random().toString(36).slice(2, 8)}`;\n const record: CaptureRecord = {\n id,\n cameraId,\n cameraName,\n timestamp: now,\n detectedClass: best.className!,\n score: best.score || 0,\n boundingBox: best.boundingBox as number[],\n inputDimensions: data.inputDimensions as number[],\n detectionId: data.detectionId,\n reviewed: false,\n };\n\n this.captures.set(id, record);\n this.images.set(id, jpeg);\n this.saveImage(id, jpeg);\n this.saveCaptures();\n\n this.console.log(`Captured ${best.className} (${Math.round((best.score || 0) * 100)}%) from ${cameraName} [${this.captures.size} total]`);\n }\n\n // ── HTTP Handler ──────────────────────────────────────────────────────────\n\n async onRequest(request: HttpRequest, response: HttpResponse) {\n const url = new URL(request.url, 'http://localhost');\n const path = url.pathname.replace(request.rootPath, '');\n\n // Serve image\n if (path.startsWith('/img/')) {\n const id = path.slice(5);\n const img = this.images.get(id);\n if (!img) return response.send('Not found', { code: 404 });\n return response.send(img, { headers: { 'Content-Type': 'image/jpeg', 'Cache-Control': 'max-age=3600' } });\n }\n\n // API: label a capture\n if (path === '/api/label' && request.body) {\n const rawBody = request.body as any;\n const body = JSON.parse(typeof rawBody === 'string' ? rawBody : Buffer.isBuffer(rawBody) ? rawBody.toString() : String(rawBody));\n const record = this.captures.get(body.id);\n if (!record) return response.send('Not found', { code: 404 });\n record.label = body.label as Label;\n record.reviewed = true;\n if (body.label === 'discard') {\n this.deleteCapture(body.id);\n } else {\n this.captures.set(body.id, record);\n this.saveCaptures();\n }\n return response.send(JSON.stringify({ ok: true }), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: get pending captures\n if (path === '/api/pending') {\n const pending = [...this.captures.values()]\n .filter(c => !c.reviewed)\n .sort((a, b) => b.timestamp - a.timestamp)\n .slice(0, 50);\n return response.send(JSON.stringify(pending), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: get labeled captures\n if (path === '/api/labeled') {\n const page = parseInt(new URL(request.url, 'http://localhost').searchParams.get('page') || '0');\n const pageSize = 50;\n const labeled = [...this.captures.values()]\n .filter(c => c.reviewed)\n .sort((a, b) => b.timestamp - a.timestamp);\n const slice = labeled.slice(page * pageSize, (page + 1) * pageSize);\n return response.send(JSON.stringify({ items: slice, total: labeled.length, page, pageSize }), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: stats\n if (path === '/api/stats') {\n const all = [...this.captures.values()];\n const stats = {\n total: all.length,\n pending: all.filter(c => !c.reviewed).length,\n labeled: all.filter(c => c.reviewed && c.label !== 'discard').length,\n byLabel: {} as Record<string, number>,\n byCamera: {} as Record<string, number>,\n byDetectedClass: {} as Record<string, number>,\n };\n for (const r of all) {\n if (r.label) stats.byLabel[r.label] = (stats.byLabel[r.label] || 0) + 1;\n stats.byCamera[r.cameraName] = (stats.byCamera[r.cameraName] || 0) + 1;\n stats.byDetectedClass[r.detectedClass] = (stats.byDetectedClass[r.detectedClass] || 0) + 1;\n }\n return response.send(JSON.stringify(stats), { headers: { 'Content-Type': 'application/json' } });\n }\n\n // API: export YOLO dataset\n if (path === '/api/export') {\n const labeled = [...this.captures.values()].filter(c => c.reviewed && c.label && c.label !== 'discard');\n if (!labeled.length) return response.send(JSON.stringify({ error: 'No labeled data yet' }), { headers: { 'Content-Type': 'application/json' }, code: 400 });\n\n const classMap: Record<Label, number> = {\n person: 0, animal: 1, face: 2, vehicle: 3, plate: 4, package: 5, discard: -1,\n };\n\n // Build a simple tarball-like structure as JSON for download\n const dataset: { filename: string; content: string; encoding: string }[] = [];\n\n for (const record of labeled) {\n const img = this.images.get(record.id);\n if (!img) continue;\n\n const fname = `${record.id}`;\n dataset.push({ filename: `images/${fname}.jpg`, content: img.toString('base64'), encoding: 'base64' });\n\n const [x, y, w, h] = record.boundingBox;\n const [imgW, imgH] = record.inputDimensions;\n const cx = (x + w / 2) / imgW;\n const cy = (y + h / 2) / imgH;\n const nw = w / imgW;\n const nh = h / imgH;\n const classId = classMap[record.label!];\n const labelLine = `${classId} ${cx.toFixed(6)} ${cy.toFixed(6)} ${nw.toFixed(6)} ${nh.toFixed(6)}\\n`;\n dataset.push({ filename: `labels/${fname}.txt`, content: labelLine, encoding: 'utf8' });\n }\n\n const yaml = [\n 'path: dataset',\n 'train: images',\n 'val: images',\n '',\n 'nc: 6',\n \"names: ['person', 'animal', 'face', 'vehicle', 'plate', 'package']\",\n '',\n '# Generated by Scrypted Detection Trainer',\n `# ${labeled.length} labeled samples`,\n ].join('\\n');\n dataset.push({ filename: 'data.yaml', content: yaml, encoding: 'utf8' });\n\n return response.send(JSON.stringify({ files: dataset, count: labeled.length }), {\n headers: { 'Content-Type': 'application/json' },\n });\n }\n\n // Serve Web UI\n if (path === '/' || path === '' || path === '/index.html') {\n return response.send(this.renderUI(), { headers: { 'Content-Type': 'text/html' } });\n }\n\n response.send('Not found', { code: 404 });\n }\n\n // ── Web UI ────────────────────────────────────────────────────────────────\n\n private renderUI(): string {\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Detection Trainer</title>\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js\"></script>\n<style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #0f0f0f; color: #e8e8e8; min-height: 100vh; }\n header { background: #1a1a1a; border-bottom: 1px solid #333; padding: 16px 24px; display: flex; align-items: center; justify-content: space-between; }\n header h1 { font-size: 18px; font-weight: 600; color: #fff; }\n .stats { display: flex; gap: 20px; font-size: 13px; color: #aaa; }\n .stat span { color: #fff; font-weight: 600; }\n .container { max-width: 1000px; margin: 0 auto; padding: 24px; }\n .card { background: #1a1a1a; border: 1px solid #2a2a2a; border-radius: 12px; overflow: hidden; margin-bottom: 24px; }\n .card-header { padding: 16px 20px; border-bottom: 1px solid #2a2a2a; display: flex; align-items: center; justify-content: space-between; }\n .card-header h2 { font-size: 15px; font-weight: 600; }\n .badge { background: #333; color: #aaa; font-size: 12px; padding: 2px 8px; border-radius: 20px; }\n .badge.orange { background: #3d2a00; color: #f90; }\n .badge.green { background: #0d2d0d; color: #4c4; }\n\n /* Detection card */\n .detection { display: grid; grid-template-columns: 420px 1fr; gap: 0; border-bottom: 1px solid #222; }\n .detection:last-child { border-bottom: none; }\n .detection-imgs { display: flex; gap: 8px; padding: 10px; background: #111; align-items: center; }\n .img-panel { display: flex; flex-direction: column; align-items: center; gap: 4px; }\n .img-label { font-size: 10px; color: #555; text-transform: uppercase; letter-spacing: .5px; }\n .det-canvas { border-radius: 6px; display: block; }\n .det-class-badge { display: inline-block; background: #3d2a00; color: #f90; font-size: 11px; padding: 2px 8px; border-radius: 4px; }\n .detection-info { padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }\n .detection-meta { font-size: 12px; color: #888; display: flex; flex-wrap: wrap; gap: 10px; }\n .detection-meta strong { color: #ccc; }\n .label-buttons { display: flex; flex-wrap: wrap; gap: 8px; }\n .label-btn { padding: 7px 14px; border-radius: 8px; border: 1px solid #444; background: #222; color: #ccc; cursor: pointer; font-size: 13px; transition: all .15s; }\n .label-btn:hover { border-color: #666; background: #2a2a2a; color: #fff; }\n .label-btn.person { border-color: #2a6; color: #4d9; }\n .label-btn.person:hover { background: #0d2a1a; }\n .label-btn.animal { border-color: #a63; color: #d85; }\n .label-btn.animal:hover { background: #2a1a0d; }\n .label-btn.face { border-color: #49c; color: #6be; }\n .label-btn.face:hover { background: #0d1a2a; }\n .label-btn.vehicle { border-color: #76b; color: #99d; }\n .label-btn.vehicle:hover { background: #1a1a2a; }\n .label-btn.discard { border-color: #622; color: #a44; }\n .label-btn.discard:hover { background: #2a0d0d; }\n .detection.labeled { opacity: 0.4; pointer-events: none; }\n .labeled-tag { font-size: 11px; color: #4d9; background: #0d2a1a; border: 1px solid #2a6; padding: 2px 8px; border-radius: 4px; }\n\n /* Empty state */\n .empty { padding: 48px; text-align: center; color: #555; }\n .empty .icon { font-size: 48px; margin-bottom: 12px; }\n\n /* Export section */\n .export-btn { padding: 10px 20px; background: #1a4d8a; border: none; border-radius: 8px; color: #fff; cursor: pointer; font-size: 14px; font-weight: 500; }\n .export-btn:hover { background: #1e5ca0; }\n .export-btn:disabled { background: #333; color: #666; cursor: not-allowed; }\n .export-info { font-size: 13px; color: #888; padding: 12px 20px; }\n\n /* Progress bar */\n .progress { height: 4px; background: #222; border-radius: 2px; overflow: hidden; margin-top: 8px; }\n .progress-bar { height: 100%; background: #1a6; border-radius: 2px; transition: width .3s; }\n\n .toast { position: fixed; bottom: 24px; right: 24px; background: #1a3; color: #fff; padding: 10px 18px; border-radius: 8px; font-size: 13px; opacity: 0; transition: opacity .3s; pointer-events: none; }\n .toast.show { opacity: 1; }\n\n .tab-bar { display: flex; gap: 2px; padding: 12px 20px 0; border-bottom: 1px solid #2a2a2a; }\n .tab { padding: 8px 14px; font-size: 13px; color: #888; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }\n .tab.active { color: #fff; border-bottom-color: #4a9; }\n .tab-content { padding: 20px; }\n .tab-panel { display: none; }\n .tab-panel.active { display: block; }\n\n .breakdown-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }\n .breakdown-item { background: #222; border-radius: 8px; padding: 12px; }\n .breakdown-item .label { font-size: 12px; color: #888; margin-bottom: 4px; }\n .breakdown-item .value { font-size: 20px; font-weight: 600; color: #fff; }\n\n /* Lightbox */\n .lightbox { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.92); z-index: 1000; align-items: center; justify-content: center; flex-direction: column; gap: 12px; }\n .lightbox.open { display: flex; }\n .lightbox canvas { max-width: 92vw; max-height: 82vh; border-radius: 8px; cursor: zoom-out; }\n .lightbox-meta { color: #aaa; font-size: 13px; text-align: center; }\n .lightbox-close { position: absolute; top: 16px; right: 20px; font-size: 28px; color: #888; cursor: pointer; line-height: 1; }\n .lightbox-close:hover { color: #fff; }\n .det-canvas { cursor: zoom-in; }\n</style>\n</head>\n<body>\n<header>\n <h1>🎯 Detection Trainer</h1>\n <div class=\"stats\">\n <div>Pending <span id=\"stat-pending\">—</span></div>\n <div>Labeled <span id=\"stat-labeled\">—</span></div>\n <div>Total <span id=\"stat-total\">—</span></div>\n </div>\n</header>\n<div class=\"container\">\n\n <div class=\"card\">\n <div class=\"tab-bar\">\n <div class=\"tab active\" onclick=\"showTab('review')\">Review</div>\n <div class=\"tab\" onclick=\"showTab('labeled')\">Labeled</div>\n <div class=\"tab\" onclick=\"showTab('stats')\">Stats</div>\n <div class=\"tab\" onclick=\"showTab('export')\">Export Dataset</div>\n </div>\n\n <!-- Review tab -->\n <div class=\"tab-panel active\" id=\"tab-review\">\n <div id=\"detections-list\"></div>\n </div>\n\n <!-- Labeled tab -->\n <div class=\"tab-panel\" id=\"tab-labeled\">\n <div id=\"labeled-list\"></div>\n </div>\n\n <!-- Stats tab -->\n <div class=\"tab-panel\" id=\"tab-stats\">\n <div class=\"tab-content\">\n <p style=\"font-size:13px;color:#888;margin-bottom:16px;\">Breakdown of captured and labeled detections.</p>\n <h3 style=\"font-size:13px;color:#aaa;margin-bottom:10px;\">By Detected Class (what the model said)</h3>\n <div class=\"breakdown-grid\" id=\"stats-detected\"></div>\n <h3 style=\"font-size:13px;color:#aaa;margin:20px 0 10px;\">By Corrected Label (what you said)</h3>\n <div class=\"breakdown-grid\" id=\"stats-label\"></div>\n <h3 style=\"font-size:13px;color:#aaa;margin:20px 0 10px;\">By Camera</h3>\n <div class=\"breakdown-grid\" id=\"stats-camera\"></div>\n </div>\n </div>\n\n <!-- Export tab -->\n <div class=\"tab-panel\" id=\"tab-export\">\n <div class=\"tab-content\">\n <p style=\"font-size:13px;color:#888;margin-bottom:16px;\">\n Exports a YOLO-format dataset (images + labels + data.yaml) as a downloadable bundle.\n Only labeled detections are included. Review more detections first to build a larger dataset.\n </p>\n <div id=\"export-stats\" class=\"export-info\">Loading…</div>\n <div style=\"display:flex;gap:12px;align-items:center;margin-top:12px;\">\n <button class=\"export-btn\" id=\"export-btn\" onclick=\"exportDataset()\">Download Dataset</button>\n <span id=\"export-status\" style=\"font-size:13px;color:#888;\"></span>\n </div>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"lightbox\" id=\"lightbox\" onclick=\"closeLightbox()\">\n <div class=\"lightbox-close\" onclick=\"closeLightbox()\">✕</div>\n <canvas id=\"lightbox-canvas\"></canvas>\n <div class=\"lightbox-meta\" id=\"lightbox-meta\"></div>\n</div>\n\n<div class=\"toast\" id=\"toast\"></div>\n\n<script>\nconst BASE = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;\nlet pending = [];\nlet labeledCount = 0;\n\nfunction imgError(img) {\n img.parentElement.innerHTML = '<div style=\"padding:20px;color:#555;font-size:12px;text-align:center\">No image</div>';\n}\n\nfunction drawDetection(img, r) {\n const [bx, by, bw, bh] = r.boundingBox;\n const [iw, ih] = r.inputDimensions;\n\n // --- Full frame canvas with box overlay ---\n const fullCanvas = document.getElementById('canvas-full-' + r.id);\n if (fullCanvas) {\n const cw = fullCanvas.width, ch = fullCanvas.height;\n const scale = Math.min(cw / iw, ch / ih);\n const dw = iw * scale, dh = ih * scale;\n const ox = (cw - dw) / 2, oy = (ch - dh) / 2;\n const ctx = fullCanvas.getContext('2d');\n ctx.fillStyle = '#111';\n ctx.fillRect(0, 0, cw, ch);\n ctx.drawImage(img, ox, oy, dw, dh);\n // Draw bounding box\n const rx = ox + bx * scale, ry = oy + by * scale;\n const rw = bw * scale, rh = bh * scale;\n ctx.strokeStyle = '#f90';\n ctx.lineWidth = 2;\n ctx.strokeRect(rx, ry, rw, rh);\n // Label badge\n ctx.fillStyle = 'rgba(255,153,0,0.85)';\n ctx.fillRect(rx, ry - 18, rw, 18);\n ctx.fillStyle = '#000';\n ctx.font = 'bold 11px sans-serif';\n ctx.fillText(r.detectedClass + ' ' + Math.round(r.score * 100) + '%', rx + 3, ry - 4);\n }\n\n // --- Crop canvas ---\n const cropCanvas = document.getElementById('canvas-crop-' + r.id);\n if (cropCanvas) {\n const cc = cropCanvas.width, ch2 = cropCanvas.height;\n const ctx2 = cropCanvas.getContext('2d');\n ctx2.fillStyle = '#111';\n ctx2.fillRect(0, 0, cc, ch2);\n // Add padding around the crop\n const pad = Math.min(bw, bh) * 0.15;\n const sx = Math.max(0, bx - pad), sy = Math.max(0, by - pad);\n const sw = Math.min(iw - sx, bw + pad * 2), sh = Math.min(ih - sy, bh + pad * 2);\n const scale2 = Math.min(cc / sw, ch2 / sh);\n const dw2 = sw * scale2, dh2 = sh * scale2;\n const ox2 = (cc - dw2) / 2, oy2 = (ch2 - dh2) / 2;\n ctx2.drawImage(img, sx, sy, sw, sh, ox2, oy2, dw2, dh2);\n // Thin box outline on crop\n ctx2.strokeStyle = '#f90';\n ctx2.lineWidth = 1.5;\n const rx2 = ox2 + pad * scale2, ry2 = oy2 + pad * scale2;\n ctx2.strokeRect(rx2, ry2, bw * scale2, bh * scale2);\n }\n}\n\n// Cache loaded images so lightbox reuses them\nconst imgCache = new Map();\n\nfunction openLightbox(r) {\n const img = imgCache.get(r.id);\n if (!img) return;\n\n const lb = document.getElementById('lightbox');\n const lbCanvas = document.getElementById('lightbox-canvas');\n\n // Size canvas to image, capped at viewport\n const maxW = window.innerWidth * 0.9;\n const maxH = window.innerHeight * 0.8;\n const [iw, ih] = r.inputDimensions;\n const scale = Math.min(maxW / iw, maxH / ih, 1);\n lbCanvas.width = Math.round(iw * scale);\n lbCanvas.height = Math.round(ih * scale);\n\n const ctx = lbCanvas.getContext('2d');\n ctx.drawImage(img, 0, 0, lbCanvas.width, lbCanvas.height);\n\n // Draw all bounding boxes for this detection (primary + others in same event if available)\n const boxes = r.allDetections || [{ boundingBox: r.boundingBox, detectedClass: r.detectedClass, score: r.score }];\n const colors = ['#f90', '#4af', '#f44', '#4f4', '#f4f', '#ff4'];\n boxes.forEach((d, i) => {\n const [bx, by, bw, bh] = d.boundingBox;\n const color = colors[i % colors.length];\n const rx = bx * scale, ry = by * scale, rw = bw * scale, rh = bh * scale;\n ctx.strokeStyle = color;\n ctx.lineWidth = 2;\n ctx.strokeRect(rx, ry, rw, rh);\n const label = d.detectedClass + ' ' + Math.round((d.score || 0) * 100) + '%';\n const textW = ctx.measureText(label).width + 8;\n ctx.fillStyle = color;\n ctx.globalAlpha = 0.85;\n ctx.fillRect(rx, Math.max(0, ry - 20), textW, 20);\n ctx.globalAlpha = 1;\n ctx.fillStyle = '#000';\n ctx.font = 'bold 12px sans-serif';\n ctx.fillText(label, rx + 4, Math.max(14, ry - 4));\n });\n\n document.getElementById('lightbox-meta').textContent =\n r.cameraName + ' · ' + new Date(r.timestamp).toLocaleString() + ' · ' + iw + '×' + ih;\n lb.classList.add('open');\n document.addEventListener('keydown', lbKeyHandler);\n}\n\nfunction closeLightbox() {\n document.getElementById('lightbox').classList.remove('open');\n document.removeEventListener('keydown', lbKeyHandler);\n}\n\nfunction lbKeyHandler(e) {\n if (e.key === 'Escape') closeLightbox();\n}\n\nfunction showTab(name) {\n const names = ['review', 'labeled', 'stats', 'export'];\n document.querySelectorAll('.tab').forEach((t, i) => {\n t.classList.toggle('active', names[i] === name);\n });\n document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));\n document.getElementById('tab-' + name).classList.add('active');\n if (name === 'stats') loadStats();\n if (name === 'export') loadExportInfo();\n if (name === 'labeled') loadLabeled(0);\n}\n\nconst LABEL_COLORS = { person:'#4d9', animal:'#d85', face:'#6be', vehicle:'#99d', plate:'#cc9', package:'#fc9', discard:'#a44' };\n\nasync function loadLabeled(page) {\n const list = document.getElementById('labeled-list');\n list.innerHTML = '<div class=\"empty\"><div style=\"color:#888\">Loading…</div></div>';\n try {\n const res = await fetch(BASE + '/api/labeled?page=' + page);\n const data = await res.json();\n const { items, total, pageSize } = data;\n const totalPages = Math.ceil(total / pageSize);\n\n if (!items.length) {\n list.innerHTML = '<div class=\"empty\"><div class=\"icon\">🏷️</div><div>No labeled detections yet.</div></div>';\n return;\n }\n\n const pagerHtml = totalPages > 1 ? \\`\n <div style=\"display:flex;align-items:center;gap:12px;padding:14px 16px;border-top:1px solid #222;font-size:13px;color:#888;\">\n \\${page > 0 ? \\`<button class=\"label-btn\" onclick=\"loadLabeled(\\${page-1})\">← Prev</button>\\` : ''}\n <span>Page \\${page+1} of \\${totalPages} · \\${total} total</span>\n \\${page < totalPages-1 ? \\`<button class=\"label-btn\" onclick=\"loadLabeled(\\${page+1})\">Next →</button>\\` : ''}\n </div>\\` : '';\n\n list.innerHTML = items.map(r => {\n const date = new Date(r.timestamp).toLocaleString();\n const score = Math.round(r.score * 100);\n const labelColor = LABEL_COLORS[r.label] || '#aaa';\n return \\`\n <div class=\"detection\" id=\"ldet-\\${r.id}\">\n <div class=\"detection-imgs\">\n <div class=\"img-panel\">\n <div class=\"img-label\">Full frame</div>\n <canvas id=\"lcanvas-full-\\${r.id}\" class=\"det-canvas\" width=\"240\" height=\"160\"></canvas>\n </div>\n <div class=\"img-panel\">\n <div class=\"img-label\">Crop</div>\n <canvas id=\"lcanvas-crop-\\${r.id}\" class=\"det-canvas\" width=\"160\" height=\"160\"></canvas>\n </div>\n </div>\n <div class=\"detection-info\">\n <div class=\"detection-meta\">\n <div><strong>\\${r.cameraName}</strong></div>\n <div>\\${date}</div>\n <div class=\"det-class-badge\">\\${r.detectedClass} \\${score}%</div>\n <div style=\"display:inline-block;background:#1a1a1a;border:1px solid \\${labelColor};color:\\${labelColor};font-size:11px;padding:2px 8px;border-radius:4px;\">✓ \\${r.label}</div>\n </div>\n <div style=\"font-size:12px;color:#888;\">Change label:</div>\n <div class=\"label-buttons\">\n <button class=\"label-btn person\" onclick=\"relabel('\\${r.id}', 'person')\">👤 Person</button>\n <button class=\"label-btn animal\" onclick=\"relabel('\\${r.id}', 'animal')\">🐾 Animal</button>\n <button class=\"label-btn face\" onclick=\"relabel('\\${r.id}', 'face')\">😀 Face</button>\n <button class=\"label-btn vehicle\" onclick=\"relabel('\\${r.id}', 'vehicle')\">🚗 Vehicle</button>\n <button class=\"label-btn\" onclick=\"relabel('\\${r.id}', 'plate')\">🔢 Plate</button>\n <button class=\"label-btn\" onclick=\"relabel('\\${r.id}', 'package')\">📦 Package</button>\n <button class=\"label-btn discard\" onclick=\"relabel('\\${r.id}', 'discard')\">🗑 Discard</button>\n </div>\n </div>\n </div>\\`;\n }).join('') + pagerHtml;\n\n // Draw bounding boxes\n for (const r of items) {\n const img = new Image();\n img.onload = () => {\n imgCache.set(r.id, img);\n // Reuse drawDetection with the labeled canvases\n const origFull = document.getElementById('canvas-full-' + r.id);\n const origCrop = document.getElementById('canvas-crop-' + r.id);\n // Temporarily point to labeled canvases\n const fakeFull = document.getElementById('lcanvas-full-' + r.id);\n const fakeCrop = document.getElementById('lcanvas-crop-' + r.id);\n if (fakeFull) fakeFull.id = 'canvas-full-' + r.id;\n if (fakeCrop) fakeCrop.id = 'canvas-crop-' + r.id;\n drawDetection(img, r);\n if (fakeFull) fakeFull.id = 'lcanvas-full-' + r.id;\n if (fakeCrop) fakeCrop.id = 'lcanvas-crop-' + r.id;\n if (fakeFull) fakeFull.onclick = () => openLightbox(r);\n if (fakeCrop) fakeCrop.onclick = () => openLightbox(r);\n };\n img.src = BASE + '/img/' + r.id;\n }\n } catch(e) {\n list.innerHTML = '<div class=\"empty\"><div style=\"color:#a44\">Error: ' + e.message + '</div></div>';\n }\n}\n\nasync function relabel(id, labelVal) {\n await fetch(BASE + '/api/label', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id, label: labelVal }),\n });\n const el = document.getElementById('ldet-' + id);\n if (labelVal === 'discard') {\n if (el) el.remove();\n toast('Discarded', '#633');\n } else {\n // Update the label badge in place\n const badge = el && el.querySelector('[style*=\"✓\"]');\n const labelColor = LABEL_COLORS[labelVal] || '#aaa';\n if (el) {\n const badges = el.querySelectorAll('.detection-meta > div');\n badges.forEach(b => { if (b.textContent.startsWith('✓')) b.remove(); });\n const meta = el.querySelector('.detection-meta');\n const newBadge = document.createElement('div');\n newBadge.style.cssText = \\`display:inline-block;background:#1a1a1a;border:1px solid \\${labelColor};color:\\${labelColor};font-size:11px;padding:2px 8px;border-radius:4px;\\`;\n newBadge.textContent = '✓ ' + labelVal;\n meta.appendChild(newBadge);\n }\n toast('Re-labeled: ' + labelVal, '#1a6');\n }\n // Refresh stats\n const statsRes = await fetch(BASE + '/api/stats');\n const stats = await statsRes.json();\n document.getElementById('stat-pending').textContent = stats.pending;\n document.getElementById('stat-labeled').textContent = stats.labeled;\n document.getElementById('stat-total').textContent = stats.total;\n}\n\nfunction toast(msg, color='#1a3') {\n const el = document.getElementById('toast');\n el.textContent = msg;\n el.style.background = color;\n el.classList.add('show');\n setTimeout(() => el.classList.remove('show'), 2500);\n}\n\nasync function loadPending() {\n try {\n const res = await fetch(BASE + '/api/pending');\n pending = await res.json();\n\n const statsRes = await fetch(BASE + '/api/stats');\n const stats = await statsRes.json();\n document.getElementById('stat-pending').textContent = stats.pending;\n document.getElementById('stat-labeled').textContent = stats.labeled;\n document.getElementById('stat-total').textContent = stats.total;\n\n const list = document.getElementById('detections-list');\n if (!pending.length) {\n list.innerHTML = '<div class=\"empty\"><div class=\"icon\">✅</div><div>No pending detections to review.<br><span style=\"font-size:12px;color:#444\">Captures will appear here as cameras detect objects.</span></div></div>';\n return;\n }\n\n list.innerHTML = pending.map(r => {\n const date = new Date(r.timestamp).toLocaleString();\n const score = Math.round(r.score * 100);\n const bb = r.boundingBox;\n const dim = r.inputDimensions;\n return \\`\n <div class=\"detection\" id=\"det-\\${r.id}\">\n <div class=\"detection-imgs\">\n <div class=\"img-panel\">\n <div class=\"img-label\">Full frame</div>\n <canvas id=\"canvas-full-\\${r.id}\" class=\"det-canvas\" width=\"240\" height=\"160\"></canvas>\n </div>\n <div class=\"img-panel\">\n <div class=\"img-label\">Crop</div>\n <canvas id=\"canvas-crop-\\${r.id}\" class=\"det-canvas\" width=\"160\" height=\"160\"></canvas>\n </div>\n </div>\n <div class=\"detection-info\">\n <div class=\"detection-meta\">\n <div><strong>\\${r.cameraName}</strong></div>\n <div>\\${date}</div>\n <div class=\"det-class-badge\">\\${r.detectedClass} \\${score}%</div>\n </div>\n <div style=\"font-size:12px;color:#888;\">What is this actually?</div>\n <div class=\"label-buttons\">\n <button class=\"label-btn person\" onclick=\"label('\\${r.id}', 'person')\">👤 Person</button>\n <button class=\"label-btn animal\" onclick=\"label('\\${r.id}', 'animal')\">🐾 Animal</button>\n <button class=\"label-btn face\" onclick=\"label('\\${r.id}', 'face')\">😀 Face</button>\n <button class=\"label-btn vehicle\" onclick=\"label('\\${r.id}', 'vehicle')\">🚗 Vehicle</button>\n <button class=\"label-btn\" onclick=\"label('\\${r.id}', 'plate')\">🔢 Plate</button>\n <button class=\"label-btn\" onclick=\"label('\\${r.id}', 'package')\">📦 Package</button>\n <button class=\"label-btn discard\" onclick=\"label('\\${r.id}', 'discard')\">🗑 Discard</button>\n </div>\n </div>\n </div>\\`;\n }).join('');\n\n // Draw bounding boxes and crops onto canvases after DOM is ready\n for (const r of pending) {\n const img = new Image();\n img.onload = () => {\n imgCache.set(r.id, img);\n drawDetection(img, r);\n // Wire up click to open lightbox\n const fullCanvas = document.getElementById('canvas-full-' + r.id);\n const cropCanvas = document.getElementById('canvas-crop-' + r.id);\n if (fullCanvas) fullCanvas.onclick = () => openLightbox(r);\n if (cropCanvas) cropCanvas.onclick = () => openLightbox(r);\n };\n img.onerror = () => {\n const c = document.getElementById('canvas-full-' + r.id);\n if (c) c.parentElement.innerHTML = '<div style=\"padding:10px;color:#555;font-size:11px\">No image</div>';\n };\n img.src = BASE + '/img/' + r.id;\n } } catch(e) {\n console.error('loadPending error', e);\n const list = document.getElementById('detections-list');\n if (list) list.innerHTML = '<div class=\"empty\"><div style=\"color:#a44\">Error loading captures: ' + e.message + '</div></div>';\n }\n}\n\nasync function label(id, labelVal) {\n const el = document.getElementById('det-' + id);\n if (el) {\n el.classList.add('labeled');\n const btns = el.querySelectorAll('.label-btn');\n btns.forEach(b => b.disabled = true);\n }\n await fetch(BASE + '/api/label', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id, label: labelVal }),\n });\n toast(labelVal === 'discard' ? 'Discarded' : 'Labeled: ' + labelVal, labelVal === 'discard' ? '#633' : '#1a6');\n setTimeout(() => {\n if (el) el.remove();\n loadPending();\n }, 600);\n}\n\nasync function loadStats() {\n const res = await fetch(BASE + '/api/stats');\n const stats = await res.json();\n\n const renderBreakdown = (obj, container) => {\n const el = document.getElementById(container);\n const entries = Object.entries(obj).sort((a, b) => b[1] - a[1]);\n el.innerHTML = entries.length\n ? entries.map(([k, v]) => \\`<div class=\"breakdown-item\"><div class=\"label\">\\${k}</div><div class=\"value\">\\${v}</div></div>\\`).join('')\n : '<div style=\"color:#555;font-size:13px;\">None yet</div>';\n };\n\n renderBreakdown(stats.byDetectedClass, 'stats-detected');\n renderBreakdown(stats.byLabel, 'stats-label');\n renderBreakdown(stats.byCamera, 'stats-camera');\n}\n\nasync function loadExportInfo() {\n const res = await fetch(BASE + '/api/stats');\n const stats = await res.json();\n document.getElementById('export-stats').textContent =\n \\`\\${stats.labeled} labeled samples ready for export across \\${Object.keys(stats.byCamera).length} camera(s).\\`;\n}\n\nasync function exportDataset() {\n const btn = document.getElementById('export-btn');\n const status = document.getElementById('export-status');\n btn.disabled = true;\n status.textContent = 'Fetching data…';\n\n try {\n const res = await fetch(BASE + '/api/export');\n if (!res.ok) { status.textContent = 'Nothing to export yet.'; btn.disabled = false; return; }\n const data = await res.json();\n if (data.error) { status.textContent = data.error; btn.disabled = false; return; }\n\n status.textContent = 'Building zip…';\n\n const zip = new JSZip();\n for (const f of data.files) {\n if (f.encoding === 'base64') {\n zip.file(f.filename, f.content, { base64: true });\n } else {\n zip.file(f.filename, f.content);\n }\n }\n\n const blob = await zip.generateAsync({ type: 'blob', compression: 'DEFLATE' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'scrypted_dataset_' + new Date().toISOString().slice(0,10) + '.zip';\n a.click();\n URL.revokeObjectURL(url);\n status.textContent = \\`Downloaded \\${data.count} samples.\\`;\n toast('Dataset downloaded!');\n } catch (e) {\n status.textContent = 'Export failed: ' + e.message;\n }\n btn.disabled = false;\n}\n\n// Initial load\nloadPending();\n// Auto-refresh pending every 30s\nsetInterval(loadPending, 30_000);\n</script>\n</body>\n</html>`;\n }\n}\n\nexport default DetectionTrainer;\n","module.exports = require(\"module\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(927);\n"],"names":["__createBinding","this","Object","create","o","m","k","k2","undefined","desc","getOwnPropertyDescriptor","__esModule","writable","configurable","enumerable","get","defineProperty","__exportStar","exports","p","prototype","hasOwnProperty","call","value","sdk","MixinDeviceBase","ScryptedDeviceBase","index_1","DeviceBase","constructor","nativeId","super","storage","_storage","deviceManager","getDeviceStorage","log","_log","getDeviceLogger","console","_console","getDeviceConsole","createMediaObject","data","mimeType","mediaManager","sourceId","id","getMediaObjectConsole","mediaObject","getMixinConsole","_lazyLoadDeviceState","_deviceState","getDeviceState","onDeviceEvent","eventInterface","eventData","options","_listeners","Set","mixinDevice","mixinDeviceInterfaces","mixinStorageSuffix","mixinDeviceState","systemManager","getDeviceById","mixinProviderNativeId","__rpcproxy_traps_all_properties","createDeviceState","setState","mixinStorageKey","getMixinStorage","onMixinEvent","manageListener","listener","add","release","l","removeListener","_createGetState","state","_createSetState","warn","field","values","ScryptedInterfaceProperty","set","loaded","process","env","SCRYPTED_SDK_ES_MODULE","SCRYPTED_SDK_MODULE","cjsModule","SCRYPTED_SDK_CJS_MODULE","sdkModule","assign","getScryptedStatic","e","runtimeAPI","pluginRuntimeAPI","endpointManager","pluginHostAPI","setScryptedInterfaceDescriptors","TYPES_VERSION","ScryptedInterfaceDescriptors","catch","error","webpackEmptyContext","req","Error","code","keys","resolve","module","ScryptedMimeTypes","ScryptedInterface","MediaPlayerState","SecuritySystemObstruction","SecuritySystemMode","AirQuality","AirPurifierMode","AirPurifierStatus","ChargeState","LockState","PanTiltZoomMovement","ThermostatMode","TemperatureUnit","FanMode","HumidityMode","ScryptedDeviceType","ScryptedInterfaceMethod","CAPTURE_CLASSES","RATE_OPTIONS","RATE_MS","Infinity","DetectionTrainer","lastCapture","Map","captures","images","listeners","loadState","registerListeners","raw","getItem","arr","JSON","parse","r","size","Buffer","from","saveCaptures","setItem","stringify","saveImage","buf","toString","deleteCapture","removeItem","delete","getSettings","cameras","getSystemState","map","filter","d","type","Camera","Doorbell","interfaces","includes","ObjectDetector","uiUrl","getLocalEndpoint","public","settings","key","title","description","c","reviewed","length","label","readonly","cam","push","name","group","choices","putSetting","startsWith","remove","rateKey","rateLabel","listen","async","source","details","onDetection","cameraId","cameraName","rateLimitMs","detections","inputDimensions","now","Date","targets","className","has","toLowerCase","boundingBox","best","sort","a","b","score","oldest","timestamp","jpeg","detectionId","mo","getDetectionInput","convertMediaObjectToBuffer","Math","random","slice","record","detectedClass","round","onRequest","request","response","path","URL","url","pathname","replace","rootPath","img","send","headers","body","rawBody","isBuffer","String","ok","pending","page","parseInt","searchParams","pageSize","labeled","items","total","all","stats","byLabel","byCamera","byDetectedClass","classMap","person","animal","face","vehicle","plate","package","discard","dataset","fname","filename","content","encoding","x","y","w","h","imgW","imgH","cx","cy","nw","nh","labelLine","toFixed","yaml","join","files","count","renderUI","require","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__","obj","prop","__webpack_exports__"],"sourceRoot":""}
|