From 7938b0a0e5d69b1b485a16816b583319d4bdf189 Mon Sep 17 00:00:00 2001 From: kaburagisec <135169292+kaburagisec@users.noreply.github.com> Date: Wed, 21 Oct 2026 03:07:13 +0700 Subject: [PATCH 1/4] docs: Add prebuilt binaries section and installation instructions to documentation --- README.md | 27 +++++++-- docs/assets/onvif.png | Bin 0 -> 19280 bytes docs/misc/binaries.md | 137 ++++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 4 +- 4 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 docs/assets/onvif.png create mode 100644 docs/misc/binaries.md diff --git a/README.md b/README.md index 24cbb32..4bb8b7b 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ This library simplifies that process by wrapping SOAP communication into a clean
*XUJk~86DA^m;*1U9^cv6nNnznu(dW$}23QX;B?q@!A;_Q(K_fd~EEY-KZYpAm>fl{GFsX@7qFu7$b O`T0 z%{%+<(i`UqVK*Tp%GG0yxI2E>sKh$99zX1d7Ps>zuIAo1V&90dzxL}`9I(NOlY)&W zH@x?KEyDQTr1Gpic?}ii *_w0sUB%^>Igxw+I^4B&=6nvvoi24>;rguexk24* z&6~+Jd8jl!vX9Wc8u!PK^*TkljvygoY9In++`oK*FSV#KO1+4hd%`C$*Y>nu={q{t zYBK-Dq$SbU#{CSxD~W1+0b-?PysQ*z>{)|SN%N9-dC(J%lN+Qt>_|2bS&wDPnI0U` zZQm(} =ViBmV#lodZk}fD`3J3vBGBO-`w*_I3z0>g-XrZ>mo2`!CL}3! z!#DPKi-}<;XJ ?^Kyzd?2J)}9Io)P0O~Hoyuei7LB6a%__R4lcy0;3@c{hF zYxa32QM2gygdTMOO>mzBGS&o@3evY~*N@_TO(BlFk59b$jEG$oN7s|2!%gnNq`ojn zO+ldJp5p#T)h{_mdXe_U`?s*{D7nNHI?>m+?jhdLVEEZjc0FT*nQZPK9NM&N<%=zj zT-JPMw{6P58E`WV#l12As>qt%(^J=p{zb?;JakIT7c*l~9)f^-Sbyu^kles-j@**# zRT?2kcIlucC>KJ`sC-O^Gz3 zkN|=_$N$zkkFF+(V|P q^8DU~@?MIzvLOaGMoH{1BoqiL$WbU CJ4q9RJEH`Ybm1dc18t|tSp zeMr+#4xXXzJfw5Ny;p)eC&_I)*wO?f9z+k+hFLMgmOE{o&3R}cT$~Ad-v5m{R@9fo z`Mi|x#dq5f3(Wcp$%c4VkEAm8W#{P4e&`BjEh{fgyZRRut~w%& z4qCkg$p8=AY Wq4lGeX2kDt6_Uc_lfIUdB!d)w zi&JOP+$#g2Cak4zWN#}gjV-Xg-e$MI_9ziczqo>33<~I~<=-^~LrWufW+jRr)5q)d znI$5>5`^0*o?V=0d^ZzhQK-Kr!jww*o$F)AB#xv+g+BC5B9D?Ezi;R1$udCSJkJ10 z+TWKP>9uQ7vUyKwezC$9iJyH);i~D_F^0}@d>tmRogs?X|0w8ssdMP`OTBPAmp~RL zu%-}z=eULREam;ccYsh9bY63RAoK!9dUb<+c9NkQVm$SPfv2M9#e@}(oBr1m_#
Yad0E4K(H&f#*HVSpDpt`SaWU@iE5I&FDR^(3Vcr+qp3y+VJ@ai}sU!KK4*I@?sp zvvbNB+>T`_`gzeGtiiu?3&KC)`Grl_`Q1bFJOuUZI3>>2*zB0aUmGo4JRDYS^0==_ z+{snCcW z0 zrio_YS0`8O@-*{4x4)3ch)J1hxo1^ItcqSWzi?FIdU5%bal$^&ShFD2GiZM7mS%o? zyurK?rA2JtmpccV#LqdJ=dMWe%5-NLzZyC`>()Y13Zkgzt|R15&4UcV0{Y7ev6APP z0orHp7G6DsM=Y{Ut)yAVdLitYP+XvhsyKDETc5KI!5Bpx-Y|qswY3cm%?2B=&@f}X z87p+?BU?~IlBTca#)c 3xaqryJ1P;auG(ftSV6@v`!?ZhhOQwr?J5bc>u#+}OSGp6`dJDi-IS!WAJrX@QQ zd5frvH<*vQ2;$9fF|tF2+)8FGux)5)ANgniXnstPoLWLRg9JVSPL@ADIc#Gc6X!Q( z{NcB_v<2)T4RK4EKFN7}{YiG+0_-NaCL=t!=`cjwElXgAegE*rFOpwDwIzn^-|@n8 zx;q`Vs|(^oH4IY_IJR`?!42_nd9~LRnIuxo(r2$6Sa&QXZllrYi3Q?>(QxsXrGxDf zhZ*@m>bsb;bXEH$pVFesQyIZuW)7mhIMo`r*xC0Dx#C;@77zP`->H&N7N&k{?L2K2 z)LyZ>u{eGi6rz)lc-QGpcV>j~mGG&j_n75-6a{P^ tL6Di3rZo=A@ zNRGY-_R|x` !nHm9&Ym4gMkS_|iIR=+~vz=R~P-QclSV zcY{{#R9HJAp@RDwQZUz=RR^RhoHP (Ib3=3}T^q~E5ApJ!Lk!-fj#(jQMGwk%c|{I9 z3(aKRV7pbeFvV<*&egZNhrBoT@~Gl8?<(#h%~a$!ilbcECpn&<=N=9OW&XT`*r-;I zP2#cC_PM!%$B#d4s*k-Z>BK=wRZ#qrk+u>i>mW*AV+-DGp?4#?{;e)eu>F{fD6Kv{ z%ki1tVXfh;USt~rXU7_`%z6HUfHx?i1E^yv!~Dnau_h@OTbNJl3(R0K&OBcw#APYp zZ(Y~)SppG^*o7oN;oRU^C>kfVA}BM%5_W%jDG?$_(c;!b&|DZ@mgHV1n^46~_YS1? zYvBGc?Rxp;meK&(m;MA-gBm5_Lz3gqoncxlzLQ(X5bQOY(RtDJ<;A_|X78G}9Rr@_iH&^l4za6tK z;iE7ULkey)ne=DoB*bePK-I*0$W6%l-NiS_Vx>Ew67+yfK@Pfq7y%==8HTDgnwPzu zKGlC;WKBgXJw59(&$g<M@z%E&B-L6dWkhn{DJ+^cyQ&fMn<;_#3xwCO;MYfQ#d`)R&p# ziK&`I>1uqJN3c(C$_W*1QWYL4xAT2lue;6&{2nydoRV;443 lj-~?(t>$G?N%_7 Udzd7Us#>S#$kYz3 z`A9)Av$fO)tO4j}o~ZqJe0Yq_8yo~^XRkh!6;ED<=Uh6xCZt#;eDWST=gsYsTE-Wd zNR-drX0z>$g5Z$ddlw~j@@8QU!N3~Q#yeM@he(uW&YY=dxX1;n)4AJ?h-4a+*pfDi zXh|-#QoDBV!K+sWl9uwkr=;xWL?I7&&m-%0k^MAkc&iDr>=~V5v3;jOdo#quJ#j#- zXo`KM?q`D-S~DFm1 W+GvWQ>mXX1`}jc83 (Xk_fs2u-W43zCVN{d2(dV&0h;JvEP_x<-KU+GgTWnlZw!RVAiT?7nN zJ)E~hsc*|sdG(3?l+0r*xK&TNo%;>28Rt!yWAPEiHk{sil?klTPj_1e>qZ)HYsKn) zD%-m@a8vU2Ouk!4$^0zgGflLddzC_jb!@)Id<1*IR!IHOvK$~5eAYmfoq5^qCIw{Y zZN1rdJbkpX0?9drGU(fC^KN{~;5`?GJm|qj&KmgbM}?$m601%tV$BN9+^nHY5xy+j z6XD*bgpH+Pz}i@|r%QDpwFlp?LT)r?m#Yqq2XN~8`omn83Te@_>Kq?B%_iPzhBND# z@gTqU=7hC9+9*IYV$n=z(vD^LO$HzxY2Rwfc{Sm#JbUx#mj|k`GPED7#k@t2Qq}Q- z**V6HqHBmYgKd@1=ql^FE=itKD|}fXiOrFoa8vO%0o`HjeB2kM@cX!U;P!Hz0}gXq z uaviHU7w(NWoL`-je3zo1N-?jH238Jqq?KI4a;WPrM>*gmL7qa z3x-NVd=8hBz_EMFpYOKc|4!}m9zo?*tHhUMG_7Q8f_SB}6aV{VF7jLZ)Y7>=G4Xpm zU*p;)9$W`N0OZK~DXzVm`+b65B_t^P=WOT;UUl7C;svJ`0RlKy>#bxU>9;pKBW<;H z VsZZs&Dfq=&T zjvT&;o~Tvb8;b3@$8{)6v7%BiOqgPPzDpD5<5K7ds1#)#0-E=xZ~hf-_cg5Dt6Osh zl~0WIEWh3g<=oR$`g*c@0cTU<8YQ5)_uzuxQgNLmbBWoDaN+FAMXubIcI6~5HaK)P zIX@5452V_1{LsoiH?}bs-y>!}>moofB7A$Fz%s?fp?d=7@9cjglWZj-Z?z2!IW#N` zCxl-Jr{R2OjQtEbDTp tf;x=z~%A?Zg zWgH?Y*fis6;WN;$UwN%}8#DyT?QXBA uSfhy>lqQNb7W@Ey| zH+w81f(~`}y$YRIf)?!6$g+Bfp?EVn#TuF|AGc44R5|)FUY)!7jPmGhtUu>oi@L%y zG}^IUa~h=#fw9o4gmz9}z`Dl*L8oaJr969S^PYaZMAZuPvjhoB^faFZ3BLTMZ(ZU@ zn6awOLp+94Nx}3$$$`J?6JuEz4JVbiCV(2Z{CMUnP2hO4)HURFa{ zA=ggo_{Ri^-|#k7y3EjTK*WZmK=epr3xV(#!CW4O-v`HLkf8)-88zh>iZ^3Sq($+a zT#2cd)GP$>nG8wowUio3L~0dzNF1rE(r`VBVTxwII{EmrB+VYFvNKYo@PllAq|_ZA z4G%QYskGr6#~d8+#BGrDKC_PHP-9)Xr^Wq+vS{#X>#Q_4?9!?cUx3f}YGrJ=*8@^9 zZ#QSg!x>{#e9T?lx)92@q!>JizT)O!hY>vFP`ll9F8MQ_!4RqzS(*?`2!V{m%7z}t zNSVHVvBMz%qLfjK9CKWJkWTd8T^v>sM?b8h{hoz$-bmsa7p(hY_wW*JfL-mZcmQ1U zqci>tJ!^ zqx`VQ0c16 3!j8whFj9_jAZq|1y@9n1IFgu;ZZ3_yo zREFj%+64FHd45B|*VktvW}>_nGv@-ktfh2?__7Q~tu8en!ysf=LTepGg(#`v1?2nE z%RrJH6Ei$k(!P zm`vr7I?y##1-c~fkfi{j(cg|^o1*xRxn2!T10WP)!<%bom*p`SaBNAr{dUyxH%=vW z{AW9BQ3`>SsMum$hI5ZnqN@-mdQJjKfussr1}&=}H9RL_;|Cxh2~%D_)Kgq<_Xgpt zKNS;G$>hNaRGe$LewS|b{wTC%_gzF+6Y(co>E{fOZw1m*R!%CQIUYlcq4SFA(s+3; zS0)u{5AQHQYalSgaRPe Qsd!0j?w62tX!CaOM zX&|~4)_ ZbdYfUciDg^{G0Tro?BI19v^UG|40i*qVErroTFpc21z}ddtvKJAQhe z73@d;;;aYJ{DIAzK;M!whb#611m(kb-oN=v#6gMrX*b}PyG5$_ZUh@`T9JqCQc`5% zi04iItJTKg_?njKVP$tp2{{9vq?zWW@=zM2#dG^ISmKC1N#rNaL%b^xVKkmovYpfH z`_O!a!cx7ZNPWs4d&x`Ro*p5&OYo^K_svOx9QJ2Xs0tF^0R3>L`w#>XWcB@wX)P}4 zThl0@6h 0Qc1#~=A=GwWUPvZ;=uhV zQQdXgkhXs)iw8GI3N gmgd%f(P 2zhrTWK<@#zc;pK0IPgBIx)mJ%pVnvjB$fQ@H^sZ26 z!Ou$B!6{ahkz*Klr$Er3%ydShR9hYXqnYyx|0a$>iK5#kt75deT0FGt(3MG gTqEvj!#4O7UdP__Lr$ (1Uu}Q->9T v+fY6(>&bkFLJfXqLj znxJb4TIz?rrz-FQqfgm;^#NoLZSuDi)PndS-kZ~{=?Eu3%bni+VVJ@f3Nw*#z$UG6 zgLFQ0E!-rk2ISwntYZ1_=sO;p0?9L89XNMpg^N3Mo?0CWR94AW?Fn>c8vDDmN|%Ce zxK6sBQ;qoB$aP4l{Z2I?*dx@s5l!172(R#hn>pCrK>YDlM&GL|qw?=oZP0y+(^K%n z*zU<4^xm=!VLLPUir8-8&IBh+@NjdgyBm~G-A$(d9CzDt?ijGY?C9CKCB%h3RSviR zy-u8>@{X!x*un1Zjo^s;;cB^-<)^$u=7}V@s(Y!AjbPm5oF&wR%An*!8k!Qb(bMy} z*&>m0-+(KAW!`(&-9*TbCtQ Dx80GYdcyD z@}L7L)y2hFte4YosI~KqP*)y>J?4JP1#%Qt@}r17*4^74TCT-cF~#*)yeJnHkOx*6 z^%*+QRCNpJK!t_p_lNBAw6pux84$$lYc@LK$%eh5r4YVfQR-e%&>l)*h;&|03{d81 z7fs^qs7oFumZX0DepNkNCfIc2ltk=^-UvV2mQn2(^XaSVa6b?I!GMZxJ)aw33gBQv z4D*SpX}VP_Wi!@hU1Ew&FGO`i5gID?o8C-FH~3TD`a>79-en5Do5OftP|$~62E Ui7bi@C#Hx;oUdA#n20^PP~@enUQ=B+9lG56n9UCCtlut*I&ZlLac$HT zIG-Ajgq`d#Q(ch|7vz%gL(}89xj{;FGDTE@FFcOz@{$k?F=e7K&U$J=in3EHU@@0X zDrs!nBnvm?BH3O%2+&N*B7rWR;C^W4AEiH{BSf=F9qBU%FZJJGqEj|k>qeZ@Iq!Gn z=@;uJef&FK2-sVMo?Koyb(NAuZhCeYRC}X}Y{Oo|f0cPwh7?QDJ@mXPQSsO??LJer zPHmGiP@lg8(rSFWgN^>nJ+}=F_3Tk}>@ yD-m;eF$L)BT4N?*n}`l5qqhdR3tC zdOCs7FuNs+U}bKm)P^J_>-b8!=hL)}rN)j=v46H^oErI{I!Qb?=m{>gdf#V>{TH|8 z^D>ebv>?*KrSQY!5b?J T%HJ?*Ji>Q*iRy61dBK z2ZkAzl@4BvNz3D^+>@uP!bv}+c#Ipn#+v|7`Eli>k6M#3lus=xtMyvp=ndNndy1V0 zSf `kasi;~+imeQqHPNym$eqhC`5$FN-pI8KeGUQr1;9@@` |^qFP&vdORDdm03?*p(hGmzXzadGu*>GesH%t?Q9TagaoOeAoQCFYW73S)*JZ zWC|}KUfz=jnD>c_w5h}0>Ry6eCS2qFT-( Wy#s)u7vgoZI*SEU(G_DtPx8{dxZq8I@2Caze~(g?`_VKaj& zxHEd0hXX2mTGB>U(a@=5Ju|XV;&&0p(c(e&cGP^&L{1Mcev-m4yh(C{F|UEB<>zqn zm&eRPsp%SfMZh6egv0#NCIh65%smZ)_^rj7Mp8b>{uwxZKuRz>sBB!LRodJ9wK@>R zl;E_RL?Jwon_2EDJ)D|zY(8y;p=(TtKx9Vp P*E9K8bgc+LQv^TV*=Tx(Z! z*lb|WgUY=gvD~C`7A?LpgGZKPkEk+{CMu|7NrM(6TgYeL)mYSqVrU^5MGVvPP=OM{ zU~VRH!QYL?A^p7D@^1)?bSw0cGlb`@B@?d4oiQ4ITDH`l;H0pq5 6)ZL;l$Ez|C;C@nAqGr~6oNIhj1ZkN^(yYLwt zeLt69y{PgvZm(H5#0(Ig=bD2V1Wlo#n+p8-UsM8Z^JQx|b$Kw=UI?pu6+eEbkSSgI zu8wOd8~ajF2&QG9`?+OuY~eKn5a_}@gbR>Cu9-FZZDvR>jM@8WFhe2%;SA2AlBrwu zUAHiNT>`%d9>NP`C_H<}MN~zG4g8g9$;Zag^cPu4EMDXS3E>MZ-dos=ue_lPeq6yR z5J&;WIeaRy;yNK{rjGoRfjI~?nMl}EeSYKQoS!e3MtN>YJj8>#YLbz#IM`=}d`wB8 zLp$Tnu&w3yyQxwz7V7P?z8PqaQ75h-pD`71!6^aXo7-4g3kQw~T!?S9R)# w~E(w83z@c&2|GT(-pR=eNf8HJNrPn_sal6aVkw_a$QT=HD$VE^+edZ*Bc@Z;Ou zVV$3b%~WanhIbm2EAU5|B7$OTc_(&;iHSAhfiu868bhX+Re)D~B#3DMA>OvhIQ&9? zC5uJK^JiJ4JA=AtuvQ7Enh&B*+3Xe2XBk*O*tn{uVYI$boKUJJ^2=FosLOU>j-_&Y zpNBxjQ0%rC;;K`K7_@Oi6}t6$OE*pAn$dv>If04wC035w= !CB%8VzHjH;`^eLD zP0C3H1{;4F;TMA{KMSO2aeWy0nP&*)_bPW%k39d_Ce$K5a3$cNtY%TUCB|MFq}Po` zfASD1Fg>6iCTJDg=+cFFT-u3VzEi#;szlg7=_5}(2#-!6S98WtM|_Jh8b?6`aCyeE zT9?V6HKjaC-e*DuwzW4vHPtEKkjLjMf0gT6KUVqm>L;6>va&YdfXv~YnOMWQO#lMN z;%7}q0)hs$W-%sisAaWlf1~qEI0BO}B+g_s5lmX@5++H(ajausp;wP_56j<~c#=2% zMx4{q<4CMin7mjSBmt7*)?r`rv)>&MYFwR*7VkJW|0@?>dn3@!yXcMPvGV0^A}@BX zre+CHI4|M%Cp&0Y|5PDd%g&)p2Jh$KZ)qMP5qF8XD#Kq;5joRXv!R!$N5wSVP-S;e zeRA8i^PL5J<@&l6&{z1=u0&hatS8@Hc!8tP3G=Iu*OUYFq)pF;N$}f;kL|A>V63}H zJPQ1hjTkjd=dAiTYv2u%G?#Raw@jv6qeKm;BKqOQ(O_DjGoO zz_5^eK24&)Mf%*3pO-%!2w#T1@>Vm7xp_F@WOA;-MwtlN?&pR+)av9;XN#RyhF`jB z!Eb)!Bpg>(WYdYyPp*9P^UXBm*uf=M^G6Z4S `J zb(JhBdXuYc*iSFzTVNwTwA~|W-X&IsZ*blq0}uLY=Bwzl^H=N2?8}y8xQJ!iU6pq6 zW`9FHwK$B4weq{ltue8;5_jT)*iXZ&9^@g+kgOgnR5R=N*o7I1AEh`y0=w6{hOeK6 zui!*}QE8cdvKM1wdd4tGIfL*2x*GcG5q#DcKKoR+gOs6(ix(`h>8{u0A+OG(nIAr2 zU2#{eA#^*T?|k`^kc8L?K-L6E?;P X~7!}z@cHt_52%9&FSfdd59P9hgb zw{<>*osMH|@Obk@%p+LEa+grUyf7_Q|C1OMadvFK1cN@gNnqvIXZ@C?02*^~`DzOS zIRrBDG~|S|z Shkq@H5AKy0V>++x_%F`HaEu%!D-!w5@hO0=wTd zsURd!Rry-gL%5kjRPOc7R1DWi4i8^~8iPGu^g#>yCu1pynmVhm?>;u-SYhE6?$X&6 z1d Y7618vi?>8JFQwHW@8I|Gp@F;7Hfpf62%K9_`UaKrHAuV^UtGoJ zPLgT(aok$Cgg<5QjODnCZgY1;W^!r}5^}%Yj%jV0y=5l8%Jsgop7Q+EH>T~nZa?G= z1VYl~9NsIsd)xos6=XmU+~+{*#w6i{Pd~DwvZ)g2Ha_TJwR|qe;Wx4Eg|nIg?om@8 zPGMy@i#7QjHFshXl<6 2I*EI7St%l2m-g{CyR36M)tn*rDIZJ;v)c~ zRtUMr7CK90CY>9-zjvo@rr|Vfykur)8G{SUS_}V9-G-3n1Jkq6FkMxnUU(|BnY_bm z%cqKK&dbK jKG*0Zg6?~1oOAuCi$PW=Ao3w*(#rJkK-0vyUPi(_a5R+dK2|H>i zm73cr4a*s-1`ba}fjZ@N_%@FJ;|0?&;2L1)9(d!f(4G%W_ScP1IQ-3-r%RE9D8BKw z?Gs$uvk~!tTbpA+RyR)f{bK6j&F35fvXq)iHUKtWZ%~DSBwOuZQSzyhQs@dQrmawj zL7)i0MLFP~a98-nxzF@|UTcQCL;jrZ6DYKu8*-2~h!fW-ET7==R*;>?JQ?SGU}Z!% z*L#PFGhlfJlIitokINa{r>((4vi@ zWLG%|4c5ee6p!K0d+jtXC2*JD81jITsHch0i-N1E)f?M6*zko-Asvk-1?nFktc*=V zE!Ng&_6OG=8N!IoYIrA5kJ >}D885*kslYgkc{)9Qc5}dNrivnCrQ)xo4{#90AwdxZ01T3z{)2#ltlgF zn&^452Db)qLu7%ex-bSkK4`ZL3K`nIi!WBmr^c;MXG2P2J?fbd#Igs)UbCH4h-;X? z%}2b*pIl?1Xm&_c{b4gXZSz;#_*b4f B^pX{J~j`47+B8=KYI_8y8tRSim``0kNN87k@Fj-HY1>lBe^M+jE@qF-2OnuGxd@WQ6!4@vKiYu3P}DUlO=ZRYKJN`PSS9SEXajNC@~W@BFS zF95f8)eYcp*dQBiDeHH@1vHUX 9$ z3Fd@;b##~9wcziTnEmPEJGi^vKtjw3I4?ey3R`Bw){nOHe0Ze=oZ2u++lqzUr&OSL z1)x*?2PUf!lLY{16}SH9mQIiSGiQJpdYweb&oF3)vpn~PJno5o^%%cta=8ak9nsHw zZT1RZRA@4qJ;MPmWL|nYzcM101Z4tkimb; _7sNg75N(nxnudYGP&y$!VE%LP1gJL=0NW~d zG;$ $KZ5*2`v-=8g2cUH0VS-4)9Hh zZS*~oQ9tp=z5oK{e34DFeF4jLn;kDlVylw0{SKg-{k63cw;TIpm~!VW@5dfG*gare z{~v+ofy#maR}pbD>e}AP!qM0{&e~FTqaKsKw&5QS$7N};-;5?G1E7ghQ*P52F`g7f zh$~=-C?+)|ooOjV9blw+ko*qimkan#3*~{FHuC09IzYVU4{ >@E^^+Vck=63oqHXcnv4`nscd#e`>Q`h3jNk?Ip2BMR c8YfZ~iimOR2chr%;~-J^R_5KNF3Q1TXLZV@kxX(t1~6g+$AtFTsORESNZ zyK?C|enB@)a-vZ^c1o2r+-Nn8` arX^8ascwo#WR}8?F?Lf0RPQgel+b&TuEJDc0t;9 ztfEW?kgdnfiQzhZ?xi>QX(t D;>!V9c;*M63%Sp2r`JWjn-g&S36r)vJ&Mu~F#iA$_Q$bE+TYI%6m6CD z1b~kKK#7~N_TDFt-tA|BL $1}Oc@z-uKHpN^LQyrHU zN?1msL^mbk5J$(TIF7JY3(ajVU9r>UER{QnntQdC+be99M5i+6W3_3ea}Ldh^Rcqi z&NKhM&-*-|=lT7f@9+10F5k!bDkl049r;q2y ;0z(Ylw5SfBL7uY`b#em@Ejwgzw0_G8%rs zI9c$vri1#%KxqSlm>5SP+N%uB=V&`w8xaS9c^ xb4>lNs$m`!kh!0`l2oXAi?~ zVLOe;N@)1&CQz`y6t+fN>T&bSZf57sEozvS?$(L_5-T|A=wzqN?Om!Liv7f>Q>;dS z8y~@zT9kFu7Kl<}Grw5G2nt|lBZ;FRBX~6F6n15VgNr>7-|~>Fyp;=yu~FwvTFpxs zpkgXR@}hly0X1s)wS)O?;g*ZqEKnu9sV1LBLm*n<2ZlnKY^I|F0im{+?|PJ3-18HC zRV=q$HiM^3ROAo2+TnPJUBC<0h0N8)RS*PhUBhY)88sj{rc6WS+8at+ -8Ld1NaS){>0D_b=Fr+rN zS36f>p=w*2Ra5O)e{p*y)qPB-l#&qFBj_J)^7d5t?>*l_eN1zpy|7u4)#t3lLb2tr zi1f@C{hFmg5Z(3Y-yb=ffUg26kCf1dzFL&MjOZ#i==mBOI}1&M+o0X}G;_u4rEZ(5 zQM{8gp}Ic%E+e3&vvUf9e_VWow60!yP<*$$)oD6Hw{EWvq-FgGwobR3yp=#m%UHoH z&vpzrW0u!o(45pkpKBr~x@X{3)?$}G8bXeu2N4~#MO-JKLI*x^QbKkhUSgtunfKlM zU?TVS01l=HM8GErCEsqei;`05{ 2=acr>7& X{`$+i{LkAc!q6I PVwYt;mF!?>G3IgNM)R`*yh{X4pNt2tWO`X etrn $jnnlYQE;7=446lwZ zy^&3C9_MUg$Nve={a0uM8ZiwUxYFw)sS) |U32wMg5EBf#qkSFZJ5h7SuoE0q&K0$K{E$Qk2ZN__mM zD)59v-yCK^NXp0Y2_G{Bp7pOLOvR>=F&qtD`B`|W8nOdCHXg%U{kOAp8?{SwYcp@+ zIvl1+b)wnQ_BW5q*^E&1%8Q5+?LJXv4sthk&AM|8_=~`eD?y4bqqeFKi>4k1logPG zK|}B}zSHaw%;E=MHgi$*Rn5|GANo8Kra5CAIFho?PJK$IL5@u75650pKGQygwZ}iu JugRC1`#*q4ubTh> literal 0 HcmV?d00001 diff --git a/docs/misc/binaries.md b/docs/misc/binaries.md new file mode 100644 index 0000000..0627ed8 --- /dev/null +++ b/docs/misc/binaries.md @@ -0,0 +1,137 @@ +--- +hide: + - path +comments: true +--- + +# Prebuilt Binaries (No Python Required) + +Run the [ONVIF CLI](../main/onvif_cli.md) without installing Python or additional dependencies. Download a prebuilt binary for your platform from the [GitHub Releases](https://github.com/nirsimetri/onvif-python/releases) page. + +Each release provides ZIP archives for supported operating systems and architectures. Choose the appropriate binary from the table below. + +| Platform | Architecture | Download | +|---|---|---| +| :fontawesome-brands-linux: Linux | AMD64 (64-bit) | [onvif-linux-amd64.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-linux-amd64.zip) | +| :fontawesome-brands-linux: Linux | i386 (32-bit) | [onvif-linux-i386.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-linux-i386.zip) | +| :fontawesome-brands-linux: Linux | ARM64 (aarch64) | [onvif-linux-arm64.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-linux-arm64.zip) | +| :fontawesome-brands-windows: Windows | x64 (64-bit) | [onvif-windows-win64.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-windows-win64.zip) | +| :fontawesome-brands-windows: Windows | x86 (32-bit) | [onvif-windows-win32.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-windows-win32.zip) | +| :fontawesome-brands-windows: Windows | ARM64 | [onvif-windows-arm64.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-windows-arm64.zip) | +| :fontawesome-brands-apple: macOS | Intel (AMD64) | [onvif-macos-amd64.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-macos-amd64.zip) | +| :fontawesome-brands-apple: macOS | Apple Silicon (ARM64) | [onvif-macos-arm64.zip](https://github.com/nirsimetri/onvif-python/releases/latest/download/onvif-macos-arm64.zip) | + +## Installation + +### :fontawesome-brands-linux: Linux + +1. Download the ZIP archive matching your Linux architecture. +2. Extract the archive into a permanent location. +3. Create a symbolic link in `~/.local/bin` so the executable can be invoked from any directory. + +For example, for Linux AMD64, assuming the archive is in `~/Downloads`: + +```console +mkdir -p ~/.local/opt ~/.local/bin +unzip ~/Downloads/onvif-linux-amd64.zip -d ~/.local/opt +chmod +x ~/.local/opt/onvif/onvif +ln -sf ~/.local/opt/onvif/onvif ~/.local/bin/onvif +``` + +Ensure `~/.local/bin` is included in your `PATH`. If necessary, add the following to `~/.bashrc` or `~/.zshrc`: + +```console +export PATH="$HOME/.local/bin:$PATH" +``` + +Reload your shell configuration or open a new terminal, then verify: + +```console +onvif --help +``` + +Replace `onvif-linux-amd64.zip` with the archive matching your system. + +### :fontawesome-brands-windows: Windows + +1. Download the ZIP archive matching your Windows architecture. +2. Extract the archive. It contains an `onvif` directory with the executable and its bundled dependencies. +3. Move the extracted `onvif` directory to a permanent location, such as `%LOCALAPPDATA%\Programs\ONVIF`. +4. Add that directory to your user `PATH` environment variable. + +To configure `PATH`, open **Edit environment variables for your account**, select `Path`, click **New**, and enter: + +```text +%LOCALAPPDATA%\Programs\ONVIF +``` + +Open a new terminal and verify the installation: + +```console +onvif --help +``` + +You can now invoke `onvif` from any working directory in PowerShell or Command Prompt. + +### :fontawesome-brands-apple: macOS + +1. Download the ZIP archive matching your Mac's processor: Intel or Apple Silicon. +2. Extract the archive into a permanent location. +3. Create a symbolic link in `~/.local/bin`. + +For example, for Apple Silicon: + +```console +mkdir -p ~/.local/opt ~/.local/bin +unzip ~/Downloads/onvif-macos-arm64.zip -d ~/.local/opt +chmod +x ~/.local/opt/onvif/onvif +ln -sf ~/.local/opt/onvif/onvif ~/.local/bin/onvif +``` + +Ensure `~/.local/bin` is included in your `PATH`. If necessary, add this line to `~/.zshrc`: + +```console +export PATH="$HOME/.local/bin:$PATH" +``` + +Open a new terminal and verify: + +```console +onvif --help +``` + +For Intel Macs, use `onvif-macos-amd64.zip` instead. + +## Understanding the Distribution + +The prebuilt binaries use PyInstaller's `--onedir` mode. Each archive contains the executable, bundled runtime dependencies, and project license documents. + +The extracted directory has the following structure: + +```text +onvif/ +├── onvif # Linux and macOS +├── onvif.exe # Windows only +├── LICENSE +├── NOTICE +└── _internal/ + └── ... # Bundled runtime and dependencies +``` + +The `_internal` directory contains the Python runtime components, third-party dependencies, and bundled resources required by the executable. + +**Keep the executable and `_internal` directory together.** Do not delete, rename, or move `_internal` independently. The application may fail to start or operate correctly if its bundled files are missing. + +The `LICENSE` and `NOTICE` files provide licensing and attribution information for the distribution. + +## Verify the Installation + +After completing the platform-specific setup, run: + +```console +onvif --help +``` + +To see the available commands and options, consult the [ONVIF CLI documentation](../main/onvif_cli.md). + +These prebuilt binaries do not require a separate Python installation or a separate installation of the ONVIF Python package. diff --git a/mkdocs.yml b/mkdocs.yml index 3b54c79..0c16524 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,6 @@ site_name: ONVIF Python site_description: >- - A modern Python library for ONVIF-compliant IP cameras and devices, providing a clean, + A Python Library + CLI for ONVIF-compliant IP cameras and devices, providing a clean, typed API for discovery, device management, media, PTZ, and events. site_url: !ENV [SITE_URL, 'https://onvif-python.pages.dev/'] repo_url: https://github.com/nirsimetri/onvif-python @@ -81,6 +81,8 @@ nav: - Conventions: conventions.md - Quickstart: quick_start.md - Approach: approach.md + - Misc: + - Prebuilt Binaries: misc/binaries.md - Usage: - Client: main/onvif_client.md - CLI: main/onvif_cli.md From a83bbe0a28a2fdaba9fb8f9574eaa98d70ecd576 Mon Sep 17 00:00:00 2001 From: kaburagisec <135169292+kaburagisec@users.noreply.github.com> Date: Wed, 21 Oct 2026 03:07:42 +0700 Subject: [PATCH 2/4] ci: Add GitHub Actions workflow for building Python binaries --- .github/workflows/python-binary.yml | 124 ++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 .github/workflows/python-binary.yml diff --git a/.github/workflows/python-binary.yml b/.github/workflows/python-binary.yml new file mode 100644 index 0000000..0de0a03 --- /dev/null +++ b/.github/workflows/python-binary.yml @@ -0,0 +1,124 @@ +name: Python Binary + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + binary-build: + name: Build ${{ matrix.asset_name }} + runs-on: ${{ matrix.runner }} + + permissions: + contents: write + + strategy: + fail-fast: true + matrix: + include: + - runner: ubuntu-26.04 + python_arch: x64 + asset_name: onvif-linux-amd64 + executable_name: onvif + + - runner: ubuntu-26.04 + python_arch: x86 + asset_name: onvif-linux-i386 + executable_name: onvif + + - runner: ubuntu-26.04-arm + python_arch: arm64 + asset_name: onvif-linux-arm64 + executable_name: onvif + + - runner: windows-latest + python_arch: x64 + asset_name: onvif-windows-win64 + executable_name: onvif.exe + + - runner: windows-latest + python_arch: x86 + asset_name: onvif-windows-win32 + executable_name: onvif.exe + + - runner: windows-11-arm + python_arch: arm64 + asset_name: onvif-windows-arm64 + executable_name: onvif.exe + + - runner: macos-15-intel + python_arch: x64 + asset_name: onvif-macos-amd64 + executable_name: onvif + + - runner: macos-latest + python_arch: arm64 + asset_name: onvif-macos-arm64 + executable_name: onvif + + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Set up Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.13" + architecture: ${{ matrix.python_arch }} + + - name: Verify Python architecture ${{ matrix.python_arch }} | ${{ matrix.runner }} + env: + EXPECTED_ARCH: ${{ matrix.python_arch }} + run: | + python -c "import os, platform, struct, sys; actual = struct.calcsize('P') * 8; expected = {'x86': 32, 'x64': 64, 'arm64': 64}[os.environ['EXPECTED_ARCH']]; print(f'Python: {platform.python_version()}'); print(f'Architecture: {platform.machine()} ({actual}-bit)'); sys.exit(0 if actual == expected else f'Expected {expected}-bit Python, got {actual}-bit')" + + - name: Install project and PyInstaller ${{ matrix.python_arch }} | ${{ matrix.runner }} + run: | + python -m pip install --upgrade pip + python -m pip install . pyinstaller pillow + + - name: Build executable (${{ matrix.asset_name }}) + run: > + pyinstaller + --clean + --noconfirm + --onedir + --collect-all onvif + --icon docs/assets/onvif.png + --name onvif + onvif/cli/__main__.py + + - name: Include license and notice (${{ matrix.asset_name }}) + shell: bash + run: | + cp LICENSE dist/onvif/LICENSE + if [ -f NOTICE ]; then + cp NOTICE dist/onvif/NOTICE + fi + + - name: Test executable (${{ matrix.asset_name }}) + env: + EXECUTABLE_NAME: ${{ matrix.executable_name }} + run: | + python -c "import os, subprocess; from pathlib import Path; p = (Path('dist/onvif') / os.environ['EXECUTABLE_NAME']).resolve(); print(f'Testing: {p}'); result = subprocess.run([str(p), '--help'], capture_output=True, text=True, timeout=60); print(result.stdout); print(result.stderr); raise SystemExit(result.returncode)" + + - name: Package distribution (${{ matrix.asset_name }}) + env: + ASSET_NAME: ${{ matrix.asset_name }} + run: | + python -c "import os, shutil; from pathlib import Path; src = Path('dist/onvif'); dst = Path('dist') / os.environ['ASSET_NAME']; shutil.make_archive(str(dst), 'zip', root_dir=src.parent, base_dir=src.name); print(f'Created {dst}.zip')" + + - name: Verify archive (${{ matrix.asset_name }}) + env: + ASSET_NAME: ${{ matrix.asset_name }} + run: | + python -c "import os, sys, zipfile; from pathlib import Path; p = Path('dist') / (os.environ['ASSET_NAME'] + '.zip'); valid = p.is_file() and p.stat().st_size > 0 and zipfile.is_zipfile(p); print(f'Archive: {p} ({p.stat().st_size if p.exists() else 0} bytes)'); sys.exit(0 if valid else f'Invalid archive: {p}')" + + - name: Upload to GitHub Release (${{ matrix.asset_name }}) + env: + GH_TOKEN: ${{ github.token }} + run: gh release upload "$GITHUB_REF_NAME" "dist/${{ matrix.asset_name }}.zip" --clobber + shell: bash \ No newline at end of file From 348c47d55b689cbaca29e7e8849e7e331a322577 Mon Sep 17 00:00:00 2001 From: kaburagisec <135169292+kaburagisec@users.noreply.github.com> Date: Wed, 21 Oct 2026 03:09:09 +0700 Subject: [PATCH 3/4] docs: Update descriptions to add CLI --- docs/llms.txt | 2 +- docs/overrides/main.html | 4 ++-- pyproject.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/llms.txt b/docs/llms.txt index 7121e4b..618acd0 100644 --- a/docs/llms.txt +++ b/docs/llms.txt @@ -1,6 +1,6 @@ # ONVIF Python -> A modern, developer-friendly Python library for discovering, connecting to, and managing ONVIF-compliant IP cameras, NVRs, and other ONVIF-compliant devices. It provides a Pythonic interface to ONVIF SOAP services, built-in WSDL definitions, WS-Discovery, device management, media streaming, PTZ, events, analytics, and a feature-rich command-line interface. +> A modern, developer-friendly Python Library + CLI for discovering, connecting to, and managing ONVIF-compliant IP cameras, NVRs, and other ONVIF-compliant devices. It provides a Pythonic interface to ONVIF SOAP services, built-in WSDL definitions, WS-Discovery, device management, media streaming, PTZ, events, analytics, and a feature-rich command-line interface. ONVIF Python is an independent open-source implementation of the ONVIF specifications, maintained by Nirsimetri Technologies. It is designed for individual developers, companies building video management systems (VMS) and video intelligence platforms, security integrators, and IoT developers. diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 44612a8..d127dc1 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -71,7 +71,7 @@ @@ -94,7 +94,7 @@ /> Date: Wed, 21 Oct 2026 03:20:28 +0700 Subject: [PATCH 4/4] chore: Exclude non-module folders --- pyproject.toml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c408a90..61c11e5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -98,6 +98,9 @@ exclude = [ "build*", "site*", "device-test*", + "docs*", + "dist*", + "scripts*", ] [tool.setuptools.package-data] @@ -122,6 +125,7 @@ skip = [ "^temp/", "^build/", "^site/", + "^dist/", ] [tool.docformatter] @@ -140,6 +144,7 @@ ignore-paths = [ "^temp/", "^build/", "^site/", + "^dist/", ] load-plugins = ["pylint_pytest"] @@ -168,6 +173,8 @@ exclude = [ "^build/", "^site/", "^docs/", + "^scripts/", + "^dist/", ] [tool.coverage.run] @@ -176,6 +183,8 @@ omit = [ "device-test/*", "examples/*", "docs/*", + "scripts/*", + "dist/*", ] [tool.codespell]