pax_global_header00006660000000000000000000000064150121155450014511gustar00rootroot0000000000000052 comment=896894c56a832242e15587f0e990012273636c3a fritzconnection-1.15.0/000077500000000000000000000000001501211554500150135ustar00rootroot00000000000000fritzconnection-1.15.0/.coveragerc000066400000000000000000000002251501211554500171330ustar00rootroot00000000000000[report] exclude_lines = pragma: no cover omit = */tests/* */test_* *conftest.py */cli/* *fritzhosts.py *fritzstatus.py fritzconnection-1.15.0/.gitignore000066400000000000000000000004101501211554500167760ustar00rootroot00000000000000 .DS_Store .coverage .coveragec .coveralls.yml .pytest* .Python .tox .nox .pytest_cache .vscode/* *.ipynb* *.pyc __pycache__/* _jupyter bin build/* dist/* docs/requirements.out docs/requirements.local.txt fritzconnection.egg-info/* include lib_ .idea x_* docs_out fritzconnection-1.15.0/.readthedocs.yml000066400000000000000000000003271501211554500201030ustar00rootroot00000000000000version: 2 build: os: ubuntu-22.04 tools: python: "3.12" python: install: - requirements: docs/requirements.txt - method: pip path: . sphinx: builder: html configuration: docs/conf.py fritzconnection-1.15.0/CODE_OF_CONDUCT.md000066400000000000000000000011001501211554500176020ustar00rootroot00000000000000 # Code of Conduct ## tldr: There are a lot of CoC files out there and the essence is: be nice and respectful to others and keep in mind that written communication differs from in person communication. So in comments please don't be negative but neutral, or –even better– all the time friendly. Because every other mode can get misunderstood (and everything misunderstandable will get misunderstood). However, even then it may happen that one can feel upset in a discussion. In this case take a night of sleep before responding. Also asking questions can help a lot. fritzconnection-1.15.0/CONTRIBUTING.md000066400000000000000000000106611501211554500172500ustar00rootroot00000000000000# Contributing Thank you for taking time to contribute to this project. The project is not large enough to need a lot of rules, but here are some guidelines: ## Issues In case you think that something is not working as expected or you have a new idea, feel free to create an issue. Especially if you want to provide a pull-request, it is a good idea to create an issue first. Please also keep in mind that issues are not for support. For support try 'discussions' (please keep in mind that this is not a commercial product, so you may get support or not). ## Pull requests In general pull requests are welcome. Please create an issue first before putting too much work into a pull request that may not get merged at the end, for whatever reason. An issue can help to clarify points of view and motivation. In case of providing a pull-request please do this for the **development-branch** and not for the master-branch. For pull-requests there is a golden rule: **keep them small**. Smaller pull-requests are easier to review and easier to merge – especially in cases when not every part of a larger changeset should get merged and has to get modifications. Please avoid to just change the formatting. The result is most often nothing else than git-diff pollution. This is especially true for `black` (or `blue` or the corresponding modes in `ruff`) – this project startet before `black`. It is ok to use these tools for modified code snippets, but not for a module. ## Status of core and lib fritzconnection is mainly the code in the core-directory. This code is pretty mature and stable so far. Most changes are in the library (the lib-directory). The library started mainly as a collection of examples how to use the core. Because it's easier to use an existing function instead of reading the AVM TR-064 documentation, the library modules have grown over time. But every action supported by AVM can get executed without the library. So best enhancements should not be to trivial. ## Style guide - In general the style guide is PEP 8. - Recommended maximum line length is 80 something. - Use proper names: i.e. an atrribute for `attributes` or `properties`, a verb for `callables`. - Avoid `black` (see "Pull requests"). ## Comments No new function, method or class should get undocumented. Write meaningful comments: what the code does, about the arguments and return values, and - important - the corresponding types. ## Type hints This project started long ago without type hints. Keep it that way. The project is small enough, so there is no real benefit. Also some parts of the code are really dynamic (one strength of Python), where type-hints can lead to a nightmare. The place for types in this project are in the comments. Readability counts! Update: since version `1.13.0` type hints are introduced for the public API (and only there). Type-hints must be backward compatible for the oldest supported python-version. For type-checking `mypy` is used. ## Tests This project comes with tests. Since version `1.13.0` `nox` is used for testautomation (`https://nox.thea.codes/en/stable/index.html`). `nox` should get installed separately. In the same environment where `nox` has been installed also `ruff` must be installed because the `noxfile` makes use of `ruff` as external module for linting. After installation the sessions from the `noxfile.py` can be used like: - `nox -s test`: run the tests with all supported python versions. The supported versions must be installed on the local development system and must be callable like `python3.11` or `python3.12`. Currently python `3.7` and newer are supported (no new language features are used, so backward compatibility is cheap). You can run `nox -s test-3.11` to run the tests with a single python version. This can be handy for development running the test for all versions later on. - `nox -s test_router`: run all tests making a connection to the router. These tests are taking much more time and can fail because of connection errors. In case of a connection error run the tests again - chances are good the error was temporarly and gone and there are no real bugs. In all other cases: fix it. A test run with a defined python version (here `3.11`) can get started with `nox -s test_router-3.11`. - `nox -s test_all`: run all tests including the time consuming router-tests. - `nox -s check`: run `ruff` to `lint` the code. - `nox -s mypy`: apply a mypy check. - `nox -s sphinx`: make a local build of the documentation. fritzconnection-1.15.0/LICENSE.txt000066400000000000000000000020441501211554500166360ustar00rootroot00000000000000Copyright (c) 2012-now Klaus Bremer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fritzconnection-1.15.0/MANIFEST.in000066400000000000000000000002041501211554500165450ustar00rootroot00000000000000include README.rst include LICENSE.txt include fritzconnection/*.py include fritzconnection/test_xml/* include pypi_description.rst fritzconnection-1.15.0/README.md000066400000000000000000000060461501211554500163000ustar00rootroot00000000000000 # fritzconnection ![](https://img.shields.io/pypi/pyversions/fritzconnection.svg) ![](https://img.shields.io/pypi/l/fritzconnection.svg) Python-Interface to communicate with the AVM Fritz!Box. Supports the TR-064 protocol, the (AHA-)HTTP-Interface and also allows call-monitoring. ## Installation For installation use pip: ``` $ pip install fritzconnection or $ pip install fritzconnection[qr] ``` The latter will install the [segno](https://github.com/heuer/segno) package to enable QR-code creation for wifi login. ## Quickstart Using fritzconnection is as easy as: ``` from fritzconnection import FritzConnection fc = FritzConnection(address="192.168.178.1", user="user", password="pw") print(fc) # print router model information # tr-064 interface: reconnect for a new ip fc.call_action("WANIPConn1", "ForceTermination") # http interface: gets history data from a device with given 'ain' fc.call_http("getbasicdevicestats", "12345 7891011") ``` FritzConnection provides two basic commands to communicate with the router APIs: `call_action()` for the __TR-064-Interface__ and `call_http()` for the __(AHA)-HTTP-Interface__. Both APIs can be used on the same FritzConnection instance side by side. ### call_action `call_action()` expects a __TR-064__ service- and an action-name (and optional arguments). In general FritzConnection can execute every service and action provided by the (model-specific) API as documented by AVM. For i.e. this can be network settings, status informations, access to home automation devices and much more. The `call_action()` method returns the response from the router as a dictionary with the values already converted to the matching Python datatypes. ### call_http `call_http()` expects a command for the __http-interface__ like "getbasicdevicestats" and, depending on the command, additional arguments like a device "ain" (identifier). A call to the method returns a dictionary with the `content-type`, the `encoding` and the `response` data of the http-response. The content-type of the response-data is typical "text/plain" or "text/xml" and may need further processing. ### Username and password To avoid hardcoding the arguments `user` and `password` in applications FritzConnection can read both from the environment variables `FRITZ_USERNAME` and `FRITZ_PASSWORD`. ### Caching On instantiation FritzConnection has to inspect the model-specific router-API. This causes a lot of network requests and can take some seconds. To avoid this FritzConnection provides a cache that can get activated by the `use_cache` parameter: ``` fc = FritzConnection(..., use_cache=True) ``` This argument defaults to `False`. After creating the cache FritzConnection will start up much more faster. ## Library The package comes with library-modules to make some API calls easier and also demonstrates how to implement applications on top of FritzConnection. ## Documentation The full documentation and release notes are at [https://fritzconnection.readthedocs.org](https://fritzconnection.readthedocs.org) fritzconnection-1.15.0/docs/000077500000000000000000000000001501211554500157435ustar00rootroot00000000000000fritzconnection-1.15.0/docs/_static/000077500000000000000000000000001501211554500173715ustar00rootroot00000000000000fritzconnection-1.15.0/docs/_static/fritzconnection.css000066400000000000000000000010311501211554500233140ustar00rootroot00000000000000 h1 { font-size: 2.0em; margin-bottom: 1.5rem; } h2 { border-top: 2px solid #EBEBEB; border-radius: 0; margin-top: 3.0rem; margin-bottom: 1.0rem; padding-top: 1.5rem; font-size: 1.5em; } h3 { font-size: 1.2em; margin-top: 1.75rem; } .sidebar-brand-text { font-size: 1.4em; } .theme-toggle-container { display: none; } .toctree-wrapper { margin-top: 4.0rem; } code.docutils span { color: #941100; font-weight: 800; } section#version-history h2 { font-size: 1.2em; } fritzconnection-1.15.0/docs/conf.py000066400000000000000000000143311501211554500172440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # import os import sys sys.path.insert(0, os.path.abspath('..')) # -- Project information ----------------------------------------------------- # import fritzconnection import re from datetime import date from pathlib import Path def get_version(): path = Path("..") / "fritzconnection" / "__init__.py" path = path.resolve() # make it absolute with open(path) as file: content = file.read() mo = re.search(r'\n\s*__version__\s*=\s*[\'"]([^\'"]*)[\'"]', content) if mo: return mo.group(1) raise RuntimeError(f"Unable to find version string in {path}") project = 'fritzconnection' copyright = '2013 - {}, Klaus Bremer'.format(date.today().year) author = 'Klaus Bremer' # release: the fritzconnection.__version__ as is, including alpha/beta/rc tags # version: The short X.Y major project version release = get_version() version = '.'.join(release.split('.')[:-1]) html_title = f"{project}
{release}" # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = ['Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "default" # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'furo' #html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = { "light_css_variables": { "admonition-font-size": "0.9375em", "color-link": "#005493", "color-link-underline": "#005493", "color-link--hover": "#941100", "color-link-underline--hover": "#941100", "color-sidebar-link-text--top-level": "#941100", "color-toc-item-text--active": "#941100", } } # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # # html_sidebars = {} html_css_files = ['fritzconnection.css'] html_show_sphinx = True # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'fritzconnectiondoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'fritzconnection.tex', 'fritzconnection Documentation', 'Klaus Bremer', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'fritzconnection', 'fritzconnection Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'fritzconnection', 'fritzconnection Documentation', author, 'fritzconnection', 'One line description of project.', 'Miscellaneous'), ] # -- Options for Epub output ------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project # The unique identifier of the text. This can be a ISBN number # or the project homepage. # # epub_identifier = '' # A unique identification for the text. # # epub_uid = '' # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] # -- Extension configuration ------------------------------------------------- fritzconnection-1.15.0/docs/fritzconnection-360x76.png000066400000000000000000000251601501211554500225460ustar00rootroot00000000000000PNG  IHDRhL@-A*7IDATx]ytUսݛf% )jg>B]P{oo2eʔ)|fA E )A+((( R(VPPPP0HZAAAaB "hA E )A+((( R(VPP(B:HDzljj*r~b(N6~NAAA2#v'G!!!fi[p8>, ݄K``u"hˉa;dLr_pRss;vLJKKq 6*%%e+~ia^сx"hˁ|e Քn+py~vJZZ :TRSS}YYYn8' 2yZAA?1䖖 P$g_ ΗSNɉ'4]UUuSSn8 b@Yk!{N:$V?e"ރcT k(( 0"mmm<'ptsgۃL"K}}FǏ׬NOusx-=NKfFqa vö|A6X$l2`#-9Y;;!W>yw2PvO )( 0\'.4cBCC8$t$c={V#i*lZMMFⸯvExH;55UA''EA P߷ANvW6ð/{Izlߥt`Cc)++ۅaXr~~ć:S l3´ɿ\&wm$lZrccZ:K%hKmISR7xc]ՙڤPtawpQBwg+{իPkO,^^غCm+,\wE+[Ar&1Ӭ\Z6əm*iokg^H1B\ * <ҭio>os& H϶zW~$cc.((rz31|D3!a?}2c߬꯯ZGN-YI  AӭL@uq\>8AƖ;wn,vDoy4JlDe b=44EwD="7uVv,u^'h gTU/'7DAfBW+G{w?\wЭ VTX\\} C=$E*\ ?X; 9dǥ`ݥxM`>sk5,S\JKBE6Q 94 ÚcE  k`0Jop6:pBEcG1~-CMߴB_p3ރAj_3$rI0{09t+7M&8I:9rXt:6C>EU'QQDzzBfgg{@:&::%%.M{^!mv<~sQEx=xPbhrnnuI]CM=$p֎Ȉ(n' d$}C$a`,263_>'rqGpl8SkQV\9lٲނu]l8&55>*p3Áȁ}s2PtO01LxLxa_ߜ} {Vl ?_䆕 `Ud7|m(FtF0*Ds?0#19sFS$lixT0|m! ,Y7A8=zG~[ܶcڽQ~Y3t7\*awu˅Mm6Got#BH_%ϙ.3ֆe%}@9 A'{3*jps\󊫭C!n ;M?=OFS[, 'qϫ My,}e¯Xn ΜDG> >=ޤI.\X^g8-?LxWN'Eպ=p/[w]:uk߾}O]vQ,`~ uM7ɼy~boٹsg*-1bDݢE^Yl>_04r畘CP ;+**߈{r8NGC;CMV3|vw+\E#ZD +|Q]5Ϻڑpwz 1J$:: G"#'tҧ>:@)iC\QA~W#`7{8u{wKYl8yc8+rϔ$ImmO}ٻw7cƌ˗/?d棏>0))Dرc)uX9{k|ҐO3K !!! cX[gϞ~\\lڴ=\ " iFAma@qOq/4]#t)Y!s=uu׽v677Ђ |ѣqQ"-[SK֢񿄴߽#8zג^G25hDDīx%t#9hA=n޵-eW}go>۷w6$g֏uE؝JYOjcWikZ`|?s%…mf5k^0ꉠy|wjxX}IgDnXv{$3%AbN@~T~ {{}pP{rcҋ0 ѧ@0|p 97tmA(_b/ZAs?u#z?FVV>)'ݻ7_i0,w6#yͤIO*VWWG;덗?1+_H!AEhju4sk]v-1s.>.j|NY##8{fSL; L?o'mkOf|;dH0ՂMٕg pUto vQ{,yHqݷdg 1t+Txe_r)}C7Vio?O> 1M`)\46a<b䮆_ qqq刾0ߣeeţ=g򒓓iR7*]}Gjr}X"m ٭DR$<^225EP8pv}AAv^gia^CUJωr3WwGOEObf5g3bwe`'@6J&D>=z̍s32i (mXo( ֯o}r&{->Llc9hw ƺ⎾ 礆-.##N sB4K:y})Z>|p6j$pn,*Igc$1l*hb SvU#fsPv*^X=@kBW˥Iʓ&Mqiqust\|Q3ztp?k`1I;O%f!G>Y;ahp.OGBjGI9>qz춐#:#b6XT6#:G3S*:FaQerE 9}S&LWx8ro1st_DsĉCTuu5>|.4xMMc lQ>a/LIUh2/SF~e_R\-Z={bsUW 11K&\­.̮3Tr-c$E3 S͚uut tGqM<3sIyyy$mFaӅܷG#)ol{\LK6 1! Y5̲u=e+ 8xhak׮}`O,n[~3gb..Bo6{vVo{9YB۷E'lcnl碗=2dH?p^ʿ/6 \͛Wgg>O}W/b]&g±&^ ??onm4`࿴ݙTݼ=e$``NB_C1w!x fb*yHL+r4B;ں]vu8 dƍqd޳u6Mߟ=4z;&e=~Wk6BfL5Y#I# >mw0?.; 8??:iƬYNe?+q-zk"N]fMe$_=g֘bQ9s2oߞFZ0yMƘk4*#>THlSb† V^F+6xwl׭gzrGeG3G/))nMaN=7H~4̍={M2K; *W|?4H|25&i4Hն|ϝif+-O;__\\,[l9sh4[AUe{...B@$K+̂Qhq\4M*pLm̱B&r4˕DA@MtKkQĝ6e=sσs{ =ߙgι9<[i}4i?u%l}o̶wiim}QG3dxיB("eGr#C3BFeg-BahѢުYnIBdz[[[)j n".\(ڼyqrC'1V{[%^{mVChܺxă%"7Q3ry[ҜL(s)Z>Wlo]>H(tuwkZc(Ct 7Xӿdɒ/HMZps(QJe>)WSlٲ>C'\ rP}~+BiPNف C|'RSs]Dyȯj{/as2嚮 %P*;p Y.d3"BB`솪m:v!d ሃ7xJ6΢IVӆmNUtXy| e}mz0QQ\l!<hR.?R^J*r̾BDžG\'I14"\AQm*BCƇLݬCA.骚 Q Poݞi8?l=JJ- 9US-7T3 !LH"".ų (H'͖=ҥӀu RƳ)B 'gvMgB4(.{eecqh&2g;#vB BHvQd/OBûFQ$zi dz CǴ !A;lڭE&wuEz3 ҁXH!ܐvClOG?[Ur> 4ȇ%K509lFvX'?3y+>65d~*IPQFGDWIZ;Ɂ7x˖-tM I/ -a!gjhЪmy z&f`xڐ)5 Iz0DaCI[QbJouj K[kR)´rh\ؿ-"h۞t 0\ۏT A!n[Kw!f ٺb8f˙6"L=lTYDb* S1QܨA¦M.]uUr≞J3xnB׎ 9%#oggB[D~9+,x'IS{Ԭ8%f /Bx'NaÆH AEP͚ך2Hsmzvpkufr} d"BUGj&!hєyVu'DO ZME*A;FAG]2w:ck(Qkؘ9p=9 ~]6[|NNMv]%Yz$̐'x1M*ɼꚾf4Ns*v޺-OǤMZGNn#>'|@8l5 ^\ Us1'4)8N'L39m3N+b ~}TuJs=52CG[Op"&8]lqh]a[)SViF!Oki@ x %=kVdBJi (rsA7GkMOed$gF_Cy?#$?'Ic-dHc q.G\P](6<)vؗjp8p.'d6_B< :`ŋ-Iug$kHYccDF5FTBڔIs&~"rF3h%cynY}zkV7Z>S_)^S}*mu㋾-/G&Γ. _{yi26tC Jhx|m Ӹqف d9s^SHdum=k I gv-|akiT'F{Qv 1 ^֒aNFfh4F1۸h+6볫yN@"ͳoƉ}C7!U3mp1$ckM7';Oe4eASekMBsG&FI؁)193K[Msv8$)S t KFhR 15޴CSځd2 n;]Oj ŃT j8A; J9 -cT0C$Y[ZCltM~326D/mzJȖ3J{8gdpNV@mw"A殲 :ؗBtQ *)& m3()2bق 3+q aҿEp8jㅛR4ȥBQܜ%rqiA1j*gX&!ݼ V)~8)N1]x,Yg&ak(CݎJ5hQ8A;G p8jNQpv8p(Fp858օ.6IENDB`fritzconnection-1.15.0/docs/index.rst000066400000000000000000000067111501211554500176110ustar00rootroot00000000000000.. fritzconnection documentation master file, created by sphinx-quickstart on Tue Mar 19 10:09:48 2019. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. fritzconnection documentation ============================= fritzconnection is a `Python `_ library to communicate with the `AVM Fritz!Box `_ by the TR-064 protocol, the AHA-HTTP-Interface and also provides call-monitoring. This allows to read status-information from the router, read and change configuration settings and state, interact with smart-home-devices and monitor realtime phone calls. .. image:: fritzconnection-360x76.png The available features are depending on the Fritz!Box model and the according system software. Using fritzconnection is as easy as: :: from fritzconnection import FritzConnection fc = FritzConnection(address="192.168.178.1", user="user", password="pw") print(fc) # print router model information # tr-064 interface: reconnect for a new ip fc.call_action("WANIPConn1", "ForceTermination") fc.reconnect() # do the same with a shortcut # http interface: get history data from a device with given 'ain' fc.call_http("getbasicdevicestats", "12345 7891011") FritzConnection provides two basic commands to communicate with the router APIs: *call_action()* for the TR-064-Interface and *call_http()* for the (AHA)-HTTP-Interface. Both APIs can be used on the same FritzConnection instance side by side. With the `call_action()` and `call_http()` methods every service/action-combination and commands documented by the `AVM support-page (Apps/TR-064, HTTP) `_ can get executed. - ``call_action()`` expects a ``TR-064`` service- and an action-name (and optional arguments). In general FritzConnection can execute every service and action provided by the (model-specific) API as documented by AVM. For i.e. this can be network settings, status informations, access to home automation devices and much more. The *call_action()* method returns the response from the router as a dictionary with the values already converted to the matching Python datatypes. - ``call_http()`` expects a command for the ``http-interface`` like "getbasicdevicestats" and, depending on the command, additional arguments like a device "ain" (identifier). A call to the method returns a dictionary with the *content-type*, the *encoding* and the *response* data of the http-response. The content-type of the response-data is typical "text/plain" or "text/xml" and may need further processing. The fritzconnection-package comes with a library to make some common tasks easier and can also serve as example code. For a detailed overview refer to :doc:`sources/getting_started` and the documentation of the :doc:`library `. .. note:: fritzconnection is neither related nor supported by AVM. Also AVM reserves the right to add, modify or remove features of their products at any time without notice. Furthermore the terms "AVM", "Fritz!Box" and "Fritz!OS" are trademarks of `AVM Computersysteme Vertriebs GmbH `_. .. toctree:: :maxdepth: 1 :caption: Contents: sources/installation sources/getting_started sources/fritzconnection_api sources/library_modules sources/call_monitoring sources/further_reading sources/version_history sources/authors sources/license fritzconnection-1.15.0/docs/requirements.txt000066400000000000000000000000541501211554500212260ustar00rootroot00000000000000sphinx<7.4.0 furo<2025.0.0 #fritzconnection fritzconnection-1.15.0/docs/sources/000077500000000000000000000000001501211554500174265ustar00rootroot00000000000000fritzconnection-1.15.0/docs/sources/authors.rst000066400000000000000000000011561501211554500216500ustar00rootroot00000000000000 Authors ======= Additional authors having contributed to this project: * `Philipp Klaus `_ * `malleYay `_ * `Thomas Westfeld `_ * `Christian Fetzer `_ * `David Straub `_ * `Bernd Strebel `_ * Julian Tatsch Since moving from bitbucket to github, an up to date list of contributors is listed here: `https://github.com/kbr/fritzconnection/graphs/contributors `_. fritzconnection-1.15.0/docs/sources/call_monitoring.rst000066400000000000000000000046631501211554500233510ustar00rootroot00000000000000.. _call_monitoring: Call Monitoring --------------- The fritzmonitor-module is a core module of fritzconnection to provide real-time information about incoming and outgoing phone-calls. This functionality is based on a separate socket-connection to the router and does not communicate by TR-064. FritzMonitor provides a queue of type `queue.Queue` for accessing CallMonitor events. To check the events send from the router, fritzconnection comes with a `fritzmonitor` command line tool. The next block shows a typical session: :: $ fritzmonitor -i 192.168.178.1 fritzconnection v1.4.0 start fritzmonitor on address: 192.168.178.1 settings for socket-timeout: 10 [sec] settings for healthcheck-timeout: 10 [sec] (to stop press ^C) 28.11.20 15:17:43;RING;2;;;SIP0; 28.11.20 15:17:47;CONNECT;2;4;; 28.11.20 15:17:50;DISCONNECT;2;4; ... The events are of type `string` in a format defined by AVM. The option :command:`-i` specifies the ip address of the router. The option :command:`-h` provides a help menu. Here is a basic example how to use FritzMonitor in a module to pull events: :: import queue from fritzconnection.core.fritzmonitor import FritzMonitor def process_events(monitor, event_queue, healthcheck_interval=10): while True: try: event = event_queue.get(timeout=healthcheck_interval) except queue.Empty: # check health: if not monitor.is_alive: raise OSError("Error: fritzmonitor connection failed") else: # do event processing here: print(event) def main(): """Entry point: example to use FritzMonitor. """ try: # as a context manager FritzMonitor will shut down the monitor thread with FritzMonitor(address='192.168.178.1') as monitor: event_queue = monitor.start() process_events(monitor, event_queue) except (OSError, KeyboardInterrupt) as err: print(err) if __name__ == "__main__": main() The FritzMonitor API is documented :ref:`here `. .. note :: To do call monitoring, the CallMonitor service of the Fritz!Box has to be activated. This can be done with any registered phone by typing the following codes: :: activate: #96*5* deactivate: #96*4* fritzconnection-1.15.0/docs/sources/exceptions_hierarchy.rst000066400000000000000000000024011501211554500243740ustar00rootroot00000000000000**Exception Hierarchy:** :: FritzConnectionException | |--> ActionError --> FritzActionError |--> ServiceError --> FritzServiceError | |--> FritzAuthorizationError | |--> FritzResourceError | |--> FritzArgumentError | | | |--> FritzArgumentValueError | | | |--> FritzArgumentStringToShortError | |--> FritzArgumentStringToLongError | |--> FritzArgumentCharacterError | |--> FritzInternalError | | | |--> FritzActionFailedError | |--> FritzOutOfMemoryError | |--> FritzSecurityError | |-->|--> FritzLookUpError | | KeyError -------+-->| | | |-->|--> FritzArrayIndexError | IndexError -------->| fritzconnection-1.15.0/docs/sources/fritzconnection_api.rst000066400000000000000000000052051501211554500242310ustar00rootroot00000000000000FritzConnection API =================== fritzconnection is structured into subpackages: :: fritzconnection --|-- cli |-- core --|-- devices | |-- exceptions | |-- fritzconnection | |-- fritzhttp | |-- fritzmonitor | |-- logger | |-- processor | |-- soaper | |-- utils | |-- lib |-- tests The package `cli` implements the entry-points for command line usage, the tests are in the `tests` package and the library modules are in `lib`. The implementation of fritzconnection itself is structured in the `core` package. Public API ---------- The public interface is provided by the FritzConnection class, the fritzmonitor- and the exceptions-module. There are shortcuts to import FritzConnection and FritzMonitor: :: from fritzconnection import FritzConnection from fritzconnection import FritzMonitor fritzconnection ............... .. automodule:: fritzconnection.core.fritzconnection :members: .. _fritzmonitor_api: fritzmonitor ............ .. automodule:: fritzconnection.core.fritzmonitor :members: exceptions .......... Exceptions can get imported by: :: from fritzconnection.core.exceptions import FritzServiceError # or: from fritzconnection.core.exceptions import * The latter style is often discouraged because of possible namespace-pollution, less clarity about the origin of imported objects and potential name clashings. By using a * import fritzconnection will just import exceptions starting with ``Fritz`` in their names. .. include:: exceptions_hierarchy.rst .. automodule:: fritzconnection.core.exceptions :members: **Legathy Exceptions:** .. autoexception:: fritzconnection.core.exceptions.ActionError .. autoexception:: fritzconnection.core.exceptions.ServiceError Internal API ------------ The following core-modules don't provide a public interface (at least it makes no sense) and are used internally. devices ....... .. automodule:: fritzconnection.core.devices :members: fritzhttp ......... .. automodule:: fritzconnection.core.fritzhttp :members: logger ...... .. automodule:: fritzconnection.core.logger :members: processor ......... .. automodule:: fritzconnection.core.processor :members: soaper ...... .. automodule:: fritzconnection.core.soaper :members: utils ..... .. automodule:: fritzconnection.core.utils :members: fritzconnection-1.15.0/docs/sources/further_reading.rst000066400000000000000000000012321501211554500233260ustar00rootroot00000000000000 Further Reading =============== Information about the TR-064 protocol with services and actions as well as AVM-specific extensions are listed at the `AVM support-page `_ (this specific webpage about programming interfaces is mainly in german language, but the detailed documentation-files (PDFs) are in english). This page also provides links to the AHA-HTTP-Interface documentation as well as the mesh-topology format. Everything that can be done by means of these APIs – used by fritzconnection – is documented there. .. note:: Please keep in mind that fritzconnection is neither related nor supported by AVM. fritzconnection-1.15.0/docs/sources/getting_started.rst000066400000000000000000000667371501211554500233720ustar00rootroot00000000000000 Getting Started =============== The Fritz!Box provides several protocols for external applications to interact with the router. FritzConnection makes use of the TR-064 protocol and the HTTP-Interface. Both APIs can be used on a single instance of FritzConnection side by side. The documentation about all services and actions for the TR-064 protocol and also the available commands for the http-interface is available from the vendor AVM (see `Further Reading `_). .. note:: To use the TR-064 interface of the Fritz!Box, the settings for `Allow access for applications` and `Transmit status information over UPnP` in the `Home Network` -> `Network` -> `Network Settings` menu have to be activated. To access the http-interface the router must be configured with a user and a password. Default IP-Address ------------------ To access the router in a local network, fritzconnection uses a default ip-address: :: FRITZ_IP_ADDRESS = '169.254.1.1' This ip-adress is a fallback-address common to every fritzbox-router and repeater, regardless of the individual configuration. If there are multiple devices in the local network, i.e. for building a Mesh, then it is necessary to provide the ip for the requested device, either at the command line with the option :command:`-i` or the keyword-argument `address` for module usage. Otherwise it is not defined which device will respond. Username and password --------------------- For some TR-064 operations and for all http-interface commands a username and/or a password is required. This can be given on the command line as parameters or, by using a module, as arguments. To not present these information in clear text or in the program code, username and password can get stored in the **environment variables** ``FRITZ_USERNAME`` and ``FRITZ_PASSWORD``. If FritzConnection doesn't get the username or password as arguments, then it will check for these environment variables and, if set, will use the corresponding values. For Fritz!OS < 7.24 the username was optional. For newer versions an individual username is required. If a username is not provided, fritzconnection will try to find the username of the last logged in user from the Fritz!Box and will use this username (as AVM recommends for systems >= 7.24). The TR-064 API -------------- The TR-064 protocol uses the concept of ``services`` and ``actions``. A service is a collection of actions for a given topic like WLAN-connections, registered hosts, phone calls, home-automation tasks and so on. An action can have optional ``arguments`` for sending and receiving data. The set of available services and actions may vary by router models and the installed Fritz!OS version. Installing fritzconnection by pip will also install the command line tool `fritzconnection` to inspect the model-specific Fritz!Box TR-064 API. With the option :command:`-h` this will show a help menu: :: $ fritzconnection -h usage: fritzconnection [-h] [-i [ADDRESS]] [--port [PORT]] [-u [USERNAME]] [-p [PASSWORD]] [-e [ENCRYPT]] [-x] [-y] [--cache-format [CACHE_FORMAT]] [--cache-directory [CACHE_DIRECTORY]] [-r] [-R] [-s] [-S SERVICEACTIONS] [-a SERVICEARGUMENTS] [-A ACTIONARGUMENTS ACTIONARGUMENTS] [-c [COMPLETE]] options: -h, --help show this help message and exit -i [ADDRESS], --ip-address [ADDRESS] Specify ip-address of the FritzBox to connect to. Default: 169.254.1.1 --port [PORT] Port of the FritzBox to connect to. Default: 49000 -u [USERNAME], --username [USERNAME] Fritzbox authentication username -p [PASSWORD], --password [PASSWORD] Fritzbox authentication password -e [ENCRYPT], --encrypt [ENCRYPT] Flag: use secure connection (TLS) -x, --use-cache Flag: use api cache (speed-up subsequent instantiations) -y, --suppress-cache-verification Flag: suppress cache verification, implies -x --cache-format [CACHE_FORMAT] cache-file format: json|pickle (default: pickle) --cache-directory [CACHE_DIRECTORY] path to cache directory (default: ~.fritzconnection) -r, --reconnect Reconnect and get a new ip -R, --reboot Reboot the router -s, --services List all available services -S SERVICEACTIONS, --serviceactions SERVICEACTIONS List actions for the given service: -a SERVICEARGUMENTS, --servicearguments SERVICEARGUMENTS List arguments for the actions of a specified service:. -A ACTIONARGUMENTS ACTIONARGUMENTS, --actionarguments ACTIONARGUMENTS ACTIONARGUMENTS List arguments for the given action of a specified service: . Lists also direction and data type of the arguments. -c [COMPLETE], --complete [COMPLETE] List the complete api of the router Services ........ With the option :command:`-s` all available ``services`` are listed. If there are multiple fritz-devices in the network, it is undefined which one will respond. In this case the router-ip must be given with the option :command:`-i`. The number of listed `services` can vary depending on the router model: :: $ fritzconnection -s -i 192.168.178.1 fritzconnection v1.10.0 FRITZ!Box 7590 at http://192.168.178.1 FRITZ!OS: 7.29 Servicenames: any1 WANCommonIFC1 WANDSLLinkC1 WANIPConn1 WANIPv6Firewall1 DeviceInfo1 DeviceConfig1 Layer3Forwarding1 ... X_AVM-DE_OnTel1 X_AVM-DE_Dect1 ... WLANConfiguration1 WLANConfiguration2 WLANConfiguration3 ... WANPPPConnection1 WANIPConnection1 Services starting with `X_AVM` are not covered by the TR-064 standard but AVM-specific extensions. All service-names are ending with a numeric value. In case a service is listed more than once the numeric value allows to select a specific one. Most prominent example is the WLANConfiguration service for accessing the 2.4 GHz and 5 GHz bands as well as the guest-network (given that the router-model provides these services). Actions ....... Every ``service`` has a set of corresponding ``actions``. The actions are listed by the flag :command:`-S` with the servicename as parameter. :: $ fritzconnection -i 192.168.178.1 -S WANIPConnection1 fritzconnection v1.10.0 FRITZ!Box 7590 at http://192.168.178.1 FRITZ!OS: 7.29 Servicename: WANIPConnection1 Actionnames: GetInfo GetConnectionTypeInfo SetConnectionType GetStatusInfo GetNATRSIPStatus SetConnectionTrigger ForceTermination RequestConnection GetGenericPortMappingEntry GetSpecificPortMappingEntry AddPortMapping DeletePortMapping GetExternalIPAddress X_GetDNSServers GetPortMappingNumberOfEntries SetRouteProtocolRx SetIdleDisconnectTime Arguments ......... An ``Action`` can have optional ``Arguments``. A list of all available actions with their corresponding arguments is reported by the flag :command:`-a` with the servicename as parameter: :: $ fritzconnection -i 192.168.178.1 -a WANIPConnection1 This can return a lengthy output. So the arguments for a specific action of a given service can get listed with the option :command:`-A` and the service- and actionname as arguments. For example the output for the service `WANIPConnection1` and the action `GetInfo` will be: :: $ fritzconnection -i 192.168.178.1 -A WANIPConnection1 GetInfo fritzconnection v1.10.0 FRITZ!Box 7590 at http://192.168.178.1 FRITZ!OS: 7.29 Service: WANIPConnection1 Action: GetInfo Parameters: Name direction data type NewEnable out -> boolean NewConnectionStatus out -> string NewPossibleConnectionTypes out -> string NewConnectionType out -> string NewName out -> string NewUptime out -> ui4 NewLastConnectionError out -> string NewRSIPAvailable out -> boolean NewNATEnabled out -> boolean NewExternalIPAddress out -> string NewDNSServers out -> string NewMACAddress out -> string NewConnectionTrigger out -> string NewRouteProtocolRx out -> string NewDNSEnabled out -> boolean NewDNSOverrideAllowed out -> boolean For every action all, arguments are listed with their name, direction and type. (Some arguments for other services may have the direction "in" for sending data to the router.) The API of a FRITZ!Box depends on the model and the installed FritzOS version. To report the complete API of the router, the option :command:`-c` can be used: :: $ fritzconnection -i 192.168.178.1 -c > api.txt In the above example the output is redirected to the file `api.txt`, because the output will be really huge. Module usage ............ FritzConnection works by calling actions on services and can send and receive arguments. A simple example is to reconnect the router with the provider to get a new external ip: :: from fritzconnection import FritzConnection fc = FritzConnection() fc.call_action('WANIPConnection1', 'ForceTermination') At first an instance of `FritzConnection` must be created. There can be a short delay doing this, because fritzconnection has to do a lot of communication with the router to get the router-specific API. .. note :: A FritzConnection instance can be **reused** for all further `call_action()` calls (and also `call_http()` calls) **without side-effects**. For a single device (i.e. the router) an application needs just one instance. Because instantiation can be expensive (time consuming), having a single instance can save memory and speed up things. Update: with the introduction of the `api-cache` in version `1.10` instantiation is much more faster than before. However, reusing an instance is still a good idea. The method `call_action` takes two required arguments: the service- and the action-name as strings. In case that a service is unknown (because of a typo or incompatible router model) fritzconnection will raise a `FritzServiceError`. If the service is known, but not the action, then a `FritzActionError` gets raised. Let's look at another example using an address "192.168.178.1" for the action "GetInfo" on the service "WLANConfiguration" that requires a password: :: from fritzconnection import FritzConnection fc = FritzConnection(address="192.168.178.1", password="the_password") state = fc.call_action("WLANConfiguration1", "GetInfo") Calling the service `WLANConfiguration1` without giving a password (or providing a wrong one) will raise a `FritzConnectionException`. Inspecting the API works without a password, but most of the other API-calls require one. .. note :: The environment variables ``FRITZ_USERNAME`` and ``FRITZ_PASSWORD`` can be used to avoid hardcoding username and password. In case that the servicename is given without a numeric extension (i.e '1') fritzconnection adds the extension '1' by default. So `WLANConfiguration` becomes `WLANConfiguration1`. The extension is required if there are multiple services with the same name. For backward compatibility servicenames like `WLANConfiguration:1` are also accepted. If `call_action()` provides a result, the method returns a dictionary: the keys are corresponding to the `Argument name` as given in the AVM-documentation and the values are the data provided from the router. In the above example `state` will be something like this: :: {'NewAllowedCharsPSK': '0123456789ABCDEFabcdef', 'NewAllowedCharsSSID': '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ' '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~', 'NewBSSID': '98:9B:CB:2B:93:B3', 'NewBasicAuthenticationMode': 'None', 'NewBasicEncryptionModes': 'None', 'NewBeaconType': '11i', 'NewChannel': 6, 'NewEnable': True, 'NewMACAddressControlEnabled': False, 'NewMaxBitRate': 'Auto', 'NewMaxCharsPSK': 64, 'NewMaxCharsSSID': 32, 'NewMinCharsPSK': 64, 'NewMinCharsSSID': 1, 'NewSSID': 'the WLAN name', 'NewStandard': 'n', 'NewStatus': 'Up'} This information provides a lot of details about the WLAN configuration. In this example the network is up and operating on channel 6. If the values are numeric or boolean, ``call_action()`` returns the matching Python datatype. To activate or deactivate a network, the action `SetEnable` can get called. Inspection gives information about the required arguments: :: $ fritzconnection -i 192.168.178.1 -A WLANConfiguration1 SetEnable fritzconnection v1.10.0 FRITZ!Box 7590 at http://192.168.178.1 FRITZ!OS: 7.29 Service: WLANConfiguration1 Action: SetEnable Parameters: Name direction data type NewEnable -> in boolean Here just one argument is listed for the in-direction. That means that this argument has to be send to the router. FritzConnection takes arguments as keyword-parameters for the `call_action`-method, where the keyword is set to the `argument name` (`NewEnable` in this case) : :: from fritzconnection import FritzConnection fc = FritzConnection(address='192.168.178.1', password='the_password') fc.call_action('WLANConfiguration1', 'SetEnable', NewEnable=False) This call will deactivate the network (beware: don't deactivate a wireless network by not having a backup cable connection). As there are no arguments listed for the out-direction, `call_action` will return an empty dictionary. In some cases it can happen that there is a dash in an argument-name. Then this argument-name is not usable as a keyword-parameter. Therefore the `call_action` method also accepts a keyword-only argument with the name `arguments` that must be a dictionary with all input-parameters as key-value pairs (*new in 1.0*): :: arguments = {'NewEnable': False} fc.call_action('WLANConfiguration1', 'SetEnable', arguments=arguments) If `arguments` is given, the values of all further keyword-parameters are ignored; you can use just one way to provide arguments. .. note :: Prior to version 1.3 booleans must be given as numeric values 1 and 0. Since version 1.3 `True` and `False` can get used. Example: report the WLAN status ............................... Let's write a simple module using fritzconnection to report the WLAN status of a router: :: from itertools import count from fritzconnection import FritzConnection from fritzconnection.core.exceptions import FritzServiceError def get_wlan_status(fc): status = [] action = 'GetInfo' for n in count(1): service = f'WLANConfiguration{n}' try: result = fc.call_action(service, action) except FritzServiceError: break status.append((service, result)) return status def get_compact_wlan_status(fc): keys = ('NewSSID', 'NewChannel', 'NewStatus') return [ (service, {key[3:]: status[key] for key in keys}) for service, status in get_wlan_status(fc) ] def main(address, password): fc = FritzConnection(address=address, password=password) for service, status in get_compact_wlan_status(fc): print(f'{service}: {status}') if __name__ == '__main__': main(address='192.168.178.1', password='the_password') Depending on the settings this will give an output like this: :: WLANConfiguration1: {'SSID': 'the_wlan_name', 'Channel': 6, 'Status': 'Up'} WLANConfiguration2: {'SSID': 'the_wlan_name', 'Channel': 100, 'Status': 'Up'} WLANConfiguration3: {'SSID': 'FRITZ!Box Gastzugang', 'Channel': 6, 'Status': 'Disabled'} The modules in the fritzconnection library (modules in the lib-folder) can be used as code-examples of how to use fritzconnection. The HTTP API ------------ This interface (also known as AHA-HTTP-Interface) allows to interact with smart-home devices connected to the router. The functionality partly overlap with the TR-064 interface, which provides a better performance. The interface works by sending a ``command`` with optional arguments like an ``identifier`` (aka ``ain``) as http-request and returns an http-response. Commands are send by the method ``call_http()``. The http-response from this request is converted to a dictionary with the keys `content-type`, `encoding` and `content`. The values are typical "text/plain" or "text/xml" as `content-type`, "utf-8" as `encoding` and a string as `content` that may need further processing. This dictionary gets returned from the `call_http()` method. Here is an example that selects all devices which are switches and report the temperature from these devices (assuming that all switches have temperature sensors). At first create a FritzConnection instance that can get reused (user and password are read from the environment): :: from fritzconnection.core.fritzconnection import FritzConnection fc = FritzConnection(address="192.168.178.1", use_cache=True) Then implement the code using the http-interface to report all temperatures: :: result = fc.call_http("getswitchlist") switch_identifiers = result["content"].split(",") for identifier in switch_identifiers: result = fc.call_http("gettemperature", identifier.strip()) temperature = float(result["content"]) * 0.1 print(temperature) The command "getswitchlist" returns a dictionary as result. The content is a string with a comma separated list of identifiers from devices which are switches. Then for every device `call_http()` gets called with the arguments "gettemperature" as `command` and the corresponding `identifier`. The result again is a dictionary with the temperature as `content`. **The functionalities of the TR-064- and http-interface can overlap.** Here is how to do the same as above by means of the TR-064 API: :: from fritzconnection.lib.fritzhomeauto import FritzHomeAutomation fh = FritzHomeAutomation(fc) # create a list of HomeAutomationDevice instances: devices = [d for d in fh.get_homeautomation_devices() if d.is_switchable] for device in devices: temperatur = device.TemperatureCelsius * 0.1 print(temperature) This example makes use of the fritzhomeauto library-module providing the `FritzHomeAutomation` and `HomeAutomationDevice` classes. At first the instance of FritzConnection gets reused to initialize the FritzHomeAutomation instance 'fh'. On this instance the method `get_homeautomation_devices()` is called, returning a list of all homeautomation-devices known by the router, represented as HomeAutomationDevice-instances. On these instances the `is_switchable` property gets called to filter all devices which are switches. Then the example code iterates over the existing list of HomeAutomationDevice-instances to report the temperature that is already known by the instances and don't need additional calls to the API. .. note:: In general the TR-064 API is faster than the HTTP-API. Whether this is an issue depends on the application. However, for functionalities available by both APIs it makes more sense to use the TR-064 API. Combining the APIs ------------------ For home-automation tasks it can make sense to combine both interfaces. Let's say that the temperature-history of all devices providing a temperature-sensor should get reported. The TR-064 API provides an efficient way to get all devices with energy-sensors and the http-interface provides a command to access the history-data. Again at first `fc` and `fh` are defined and can get reused later: :: from fritzconnection.core.fritzconnection import FritzConnection from fritzconnection.lib.fritzhomeauto import FritzHomeAutomation fc = FritzConnection(address="192.168.178.1", use_cache=True) fh = FritzHomeAutomation(fc) Then the devices are filtered by the property `is_energy_sensor` and are HomeAutomationDevice-instances. As the history of sensor-data is only provided by the http-interface the `call_http()` method is called with the appropriate command "getbasicdevicestats" and the "ain" of the device: :: devices = [d for d in fh.get_homeautomation_devices() if d.is_energy_sensor] for device in devices: # device.identifier provides the ain: response = fc.call_http("getbasicdevicestats", identifier=device.identifier) print(response) The response is a dictionary with the `content` given as xml-data that needs further processing. For this the `HomeAutomationDevice` class (defined in fritzconnection.lib.fritzhomeauto) already provides a method for xml-processing of the "getbasicdevicestats" xml-response: :: devices = [d for d in fh.get_homeautomation_devices() if d.is_energy_sensor] for device in devices: stats = device.get_basic_device_stats() temperatures = stats['temperature']['data'] temperatures = list(map(lambda x: x * 0.1, temperatures)) The code is the same as before, but in the loop the method `get_basic_device_stats()` is called which returns a nested dictionary with the temperature data already extracted from the xml-data. The last line converts the temperatures from a sequence of strings to a list of floating point data (in ºC). There is no restriction to use just ``call_action()`` or ``call_http()``. On a single FritzConnection instance both methods can get combined to best fit the needs. Exceptions ---------- fritzconnection can raise several exceptions. For example using a service not provided by a specific router model will raise a `FritzServiceError`. This and all other errors are defined in `fritzconnection.core.exceptions` and can get imported from this module (i.e. the `FritzServiceError`): :: from fritzconnection.core.exceptions import FritzServiceError .. include:: exceptions_hierarchy.rst All exceptions are inherited from `FritzConnectionException`. `FritzServiceError` and `FritzActionError` are superseding the older `ServiceError` and `ActionError` exceptions (still existing for backward compatibility). These exceptions are raised by calling unknown services and actions. All other exceptions are raised according to errors reported from the router (mirroring FritzOS errors). `FritzLookUpError` and `FritzArrayIndexError` are conceptually the same as Pythons `KeyError` or `IndexError`. Because of this they are also inherited from these Exceptions. API-Cache --------- Stores the router api in an external file (*new in 1.10*). Loading the api-data from the router requires a lot of communication (many slow i/o) and can take up to several seconds. Reading the api-data from a single local file is much faster. The cache is activated by the `use_cache` argument: :: fc = FritzConnection(address=192.168.178.1, use_cache=True) At first run the api gets loaded from the router and stored in a cache-file. On the next runs the api gets loaded from the cache-file. There is a separate cache-file for every ip-address, allowing to cache the api for mutiple devices. With the argument `cache_directory` the location of the cache files can be specified. Default is the `~.fritzconnection` folder in the user home-directory on systems providing this default location. .. note :: The default cache-format is `pickle`, which is compact, fast and can be considered safe as it is your own data. However, the `json` format is also supported. With the argument `cache_format` the format can set to `json`. After loading the api from a cache-file, the data are verified to be still valid for the given router-model and the current installed software version. In case the cache is outdated, the api-data are reloaded from the router and the cache-file gets updated. The verifying step requires a request to the router, which can take some milliseconds. With the argument `verify_cache=False` verifying can turned off, loading the api even faster. .. warning :: On deactivate verifying, the cache data may be outdated if something has changed on the router side. As a consequence these changes may not be visible for the fritzconnection library (Simple solution: turn verifying on or delete the cache-file.) However, chances are that one didn't mention this until strange things happen. Update: since version `1.11` cache verification is much faster than before, so there is no longer a real need to deactivate the cache verification. TLS-Encryption -------------- fritzconnection supports encrypted communication with Fritz!Box devices by providing the option `use_tls` (*new in 1.2*): :: fc = FritzConnection(address=192.168.178.1, password=, use_tls=True) The default setting for `use_tls` is `False`. For the command line tools encryption is provided by the flags :command:`-e` or :command:`--encrypt`. Encryption can be a useful option in a non-private LAN like a company-LAN. .. note :: - Using TLS will slow down the communication with the router. Especially getting a new FritzConnection instance will take longer by setting `use_tls=True`. **Hint: reuse instances**. - Since the router uses a self-signed certificate, currently certificate-verification is disabled. - In case the client communicates with the router by WLAN and WPA is enabled, the communication is already encrypted. - In case the client communicates by VPN there is also no need to add an additional encryption layer. Environment-Variables --------------------- Some arguments given to `FritzConnection` can be stored in the environment. This has the advantage that arguments like `user` and `password` don't have to be provided as hardcoded arguments. The following environment variables are checked in case that a corresponding argument is missing: - ``FRITZ_USERNAME`` – the username - ``FRITZ_PASSWORD`` – the password - ``FRITZ_USECACHE`` – `True` or `False` (default: `False`) - ``FRITZ_CACHEFORMAT`` – `json` or `pickle` (default: `pickle`) - ``FRITZ_CACHEDIRECTORY`` – the cache-directory path (default: `~.fritzconnection`) The default-values are used if neither an argument is given to `fritzconnection()` nor an environment-variable is defined. fritzconnection-1.15.0/docs/sources/installation.rst000066400000000000000000000017741501211554500226720ustar00rootroot00000000000000Installation ------------ The fritzconnection package is available on `PyPi `_ and installable by `pip `_: :: $ pip install fritzconnection To enable the creation of :ref:`QR-codes for wifi login `, install fritzconnection with the `qr`-option: :: $ pip install fritzconnection[qr] .. versionadded:: 1.9.0 This will install an additional dependency `segno `_. The segno-package can also get installed any time later: :: $ pip install segno It is good practice and highly recommended to do the installation in a virtual environment – either by means of `venv `_ or `conda `_ (comes with `miniconda `_ or `anaconda `_). fritzconnection requires Python >= 3.6 fritzconnection-1.15.0/docs/sources/library_modules.rst000066400000000000000000000406121501211554500233570ustar00rootroot00000000000000Library Modules =============== The library is a package with modules on top of FritzConnection to address specific tasks. The library-modules may not serve every need, but should be seen as examples on how to use FritzConnection and how to write more specialised modules. **Performance considerations:** Creating a FritzConnection instance will inspect the Fritz!Box API to get information about all available services and corresponding actions. As this is i/o based it's generally slow. But once an instance is created, it can be reused for all tasks without side-effects. Therefore the library classes can optionally initialised with an existing FritzConnection instance, to not inspect the router-API multiple times: :: from fritzconnection import FritzConnection from fritzconnection.lib.fritzhomeauto import FritzHomeAutomation from fritzconnection.lib.fritzwlan import FritzWLAN fc = FritzConnection(address='192.168.178.1', password=) # library modules can be initialised with an existing FritzConnection instance fw = FritzWLAN(fc) print(fw.total_host_number) fh = FritzHomeAutomation(fc) # same here: use existing instance for initialisation ain = '11657 0240192' # assume the AIN of the switch is known fh.set_switch(ain, on=True) The next sections will describe the library modules in detail. **Inheritance from a common base class:** All library modules inherit from a common abstract base class that should not get instantiated: .. automodule:: fritzconnection.lib.fritzbase :members: FritzCall --------- Can dial phone numbers and allows access to history of phone calls: incoming, outgoing and missed ones. Usage from the command line: :: $ fritzcall -i 192.168.178.1 -p -t in -d 7 FRITZ!Box 7590 at ip 192.168.178.1 FRITZ!OS: 7.12 List of calls: in type number date/time duration ... more entries here ... The flag :command:`-t` indicates the type of calls to get listed: [in | out | missed]. It :command:`-t` is not given, all calls are listed (up to 999). The flag :command:`-d` is the number of days to look back for calls e.g. 1: calls from today and yesterday, 7: calls from the complete last week. FritzCall can dial numbers by the method `dial()`. This method can also invoked by the command line with the flag :command:`-c` or :command:`--call`. *Note:* To make this work it is required to activate the dial-help service of the router first. :: $ fritzcall -i 192.168.178.1 -p -c dialing number: dialing done, please wait for signal. For using a module, here is an example to list all missed calls: :: from fritzconnection.lib.fritzcall import FritzCall fc = FritzCall(address='192.168.178.1', password=) calls = fc.get_missed_calls() for call in calls: print(call) Calling back the last missed call is easy: :: missed_number = calls[0].Caller # Caller attribute holds the number fc.dial(missed_number) # now dial it The module provides some constants that can be used with the `get_calls()` method as arguments for the calltype parameter: :: ALL_CALL_TYPES = 0 RECEIVED_CALL_TYPE = 1 MISSED_CALL_TYPE = 2 OUT_CALL_TYPE = 3 ACTIVE_RECEIVED_CALL_TYPE = 9 REJECTED_CALL_TYPE = 10 ACTIVE_OUT_CALL_TYPE = 11 FritzCall API .............. .. automodule:: fritzconnection.lib.fritzcall :members: FritzHomeAutomation ------------------- This library helps to access Homeautomation devices for reading current states and set the status of switches. Usage from the command line: :: $ fritzhomeauto -i 192.168.178.1 -p FRITZ!Box 7590 at ip 192.168.178.1 FRITZ!OS: 7.12 Status of registered home-automation devices: Device Name AIN Power[W] t[°C] switch FRITZ!DECT 210 #1 '11657 0240192' 0.000 23.5 on The optional :command:`-v` flag will give a verbose report about all device information, including the settings of radiator controls. The :command:`-s` flag can set the state of switches. This flag requires two parameters: the device identifier (AIN) and the state to set [on|off]. The following example will switch off the device with the identifier '11657 0240192': :: $ fritzhomeauto -i 192.168.178.1 -p -s '11657 0240192' off Example on how to get information about the known devices by using a module: :: from fritzconnection.lib.fritzhomeauto import FritzHomeAutomation fha = FritzHomeAutomation(address='192.168.178.1', password=) info = fha.device_information() 'info' is a list of dictionaries describing the devices: :: [{'NewAIN': '11657 0240192', 'NewDeviceId': 16, 'NewDeviceName': 'FRITZ!DECT 210 #1', ... 'NewHkrComfortVentilStatus': 'CLOSED', ... 'NewMultimeterEnergy': 75, 'NewMultimeterIsEnabled': 'ENABLED', ... 'NewSwitchState': 'ON', 'NewTemperatureCelsius': 265, 'NewTemperatureIsEnabled': 'ENABLED', 'NewTemperatureIsValid': 'VALID', 'NewTemperatureOffset': 0}] Depending on the device, different information will get reported. Information about a specific device can get obtained with the identifier *NewAIN*. The next example shows how to get the temperature in °C, taken the *NewAIN* from `device_information()` call: :: ain = '11657 0240192' fha.get_device_information_by_identifier(ain)['NewTemperatureCelsius'] * 0.1 It is also easy to toggle a switch (like a FRITZ!DECT 200/210 device): :: fha.set_switch(ain, on=True) This will turn the switch with the given identifier *on* or *off* depending whether the parameter 'on' is *True* or *False*. Use-cases can be to set a switch depending on the temperature or daytime. FritzHomeAutomation API ........................ .. automodule:: fritzconnection.lib.fritzhomeauto :members: FritzHosts ---------- Utility module for FritzConnection to access and control the known hosts. The command line tool allows to list the current ip, name, the MAC address and the active-state for all registered hosts: :: $ fritzhosts -i 192.168.178.1 -p FritzConnection v1.0 FritzHosts for FRITZ!Box 7590 at ip 192.168.178.1 FRITZ!OS: 7.12: List of registered hosts: n: ip name mac status 1: 192.168.178.36 DE-20HAR90XXXXX 00:E1:8C:9B:DF:98 - 2: 192.168.178.33 HUAWEI-P20-Pro-xxxxxxxxxx B4:CD:27:37:78:E4 - ... 20: 192.168.178.24 fritz.repeater C6:25:06:83:64:C5 active 21: 192.168.178.25 fritzbox4020 C8:0E:14:B8:71:DD active Example how to use FritzHost in a module to get the same output: :: from fritzconnection.lib.fritzhosts import FritzHosts fh = FritzHosts(address='192.168.178.1', password='password') hosts = fh.get_hosts_info() for index, host in enumerate(hosts, start=1): status = 'active' if host['status'] else '-' ip = host['ip'] if host['ip'] else '-' mac = host['mac'] if host['mac'] else '-' hn = host['name'] print(f'{index:>3}: {ip:<16} {hn:<28} {mac:<17} {status}') FritzHosts API .............. .. automodule:: fritzconnection.lib.fritzhosts :members: FritzPhonebook -------------- Allows read-only access to the phonebooks stored in the router (a Fritz!Box router can have more than a single phonebook). The command line interface allows inspection of the phonebooks and search for name and numbers. The flag :command:`-a` will list the content of all phonebooks: :: $ fritzphonebook -i 192.168.178.1 -p -a FritzConnection v1.1 FritzPhonebook for FRITZ!Box 7590 at ip 192.168.178.1 FRITZ!OS: 7.12 Content of phonebook: business good customer 0123456789 another good customer 0987654321 ... more numbers here ... With the flags :command:`--name` and :command:`--number` like :command:`--name "good customer"` and :command:`--number 0987654321` all phonebooks will get searched for the according entry. Here is an example to list the entries of all phonebooks by means of a module: :: from fritzconnection.lib.fritzphonebook import FritzPhonebook fp = FritzPhonebook(address='192.168.178.1', password='password') for phonebook_id in fp.phonebook_ids: contacts = fp.get_all_names(phonebook_id) for name, numbers in contacts.items(): print(name, numbers) FritzPhonebook API .................. .. automodule:: fritzconnection.lib.fritzphonebook :members: FritzStatus ----------- Reports information about the link-status to the service provider. Usage from the command line: :: $ fritzstatus -i 192.168.178.1 -p password fritzconnection v1.8.0 FRITZ!Box 7590 at http://192.168.178.1 FRITZ!OS: 7.29 FritzStatus: is linked : True is connected : True external ip (v4) : 46.xx.xx.xx external ip (v6) : 2003:ee:xx:: internal ipv6-prefix : 2003:ee:xx:: uptime : 321:41:06 bytes send : 6845677353 bytes received : 123858580962 max. bit rate : ('44.3 MBit/s', '113.2 MBit/s') For periodic calls, an instance of FritzStatus (resp. FritzConnection) should only created once: :: import time from fritzconnection.lib.fritzstatus import FritzStatus fc = FritzStatus(address='192.168.178.1', password='password') while True: print(fc.str_transmission_rate) time.sleep(2) This will report an output like this: :: ('992.0 bytes', '23.6 KB') ('0.0 bytes', '0.0 bytes') ('1.3 KB', '25.4 KB') ('3.7 KB', '36.4 KB') ('21.2 KB', '104.6 KB') FritzStatus API ............... .. automodule:: fritzconnection.lib.fritzstatus :members: FritzTopology ------------- Module to access the current Network-Topology information. This can be a cyclic graph with the devices as nodes. The devices do have interfaces and the interfaces provide links to other the interfaces of other devices. Links do have attributes like the current throughput. The following example prints an overview of a topology: :: from fritzconnection import FritzConnection from fritzconnection.lib.fritztopology import FritzMeshTopology # assume user and password are read from the environment: fc = FritzConnection(address="192.168.178.1") # create a topology-instance fm = FritzMeshTopology(fc=fc) # read the topology data (can take some time) fm.load_topology() # print the instance: print(fm) FritzTopology API ................. .. automodule:: fritzconnection.lib.fritztopology :members: FritzWLAN --------- Module for accessing basic WLANConfiguration settings. The command line tool gives an overview of active devices: :: $ fritzwlan -i 192.168.178.1 -p FRITZ!Box 7590 at ip 192.168.178.1 FRITZ!OS: 7.12 Hosts registered at WLANConfiguration1: WLAN name: the wlan name channel : 6 index active mac ip signal speed 0 1 E2:25:06:83:64:C5 192.168.178.24 51 86 Hosts registered at WLANConfiguration2: WLAN name: the wlan name channel : 36 index active mac ip signal speed 0 1 A0:99:9B:10:09:81 192.168.178.28 91 1300 Example to get the total number of known WLAN-devices for all WLANConfigurations: :: from fritzconnection.lib.fritzwlan import FritzWLAN fw = FritzWLAN(address='192.168.178.1', password='password') print(fw.total_host_number) Example: device tracking ........................ A common use-case for wlan-information is device tracking. The following is a basic example how to do this. The example will poll the mac-addresses of all active devices. (For this a fixed tracking duration with a short poll-period is used. This may not be appropriate for real world programs.) :: import time import datetime import itertools from fritzconnection.lib.fritzwlan import FritzWLAN from fritzconnection.core.exceptions import FritzServiceError ADDRESS = '192.168.178.1' PASSWORD = 'the_password' # should not be hardcoded for real usage # short time periods for demonstration purposes TRACKING_DURATION = 20 TRACKING_PERIOD = 5 def get_active_macs(fwlan): """ Gets a FritzWLAN instance and returns a list of mac addresses from the active devices """ active_macs = list() # iterate over all wlans: for n in itertools.count(1): fwlan.service = n try: hosts_info = fwlan.get_hosts_info() except FritzServiceError: break else: active_macs.extend(entry['mac'] for entry in hosts_info) return active_macs def report_devices(fwlan): active_macs = get_active_macs(fwlan) # decide here what to do with this information: # print the mac addresses for mac in active_macs: print(mac) print() # empty line for readability def track_devices(tracking_duration, tracking_period): # instanciate FritzWLAN just once for reusage fwlan = FritzWLAN(address=ADDRESS, password=PASSWORD) stop = datetime.datetime.now() + tracking_duration while datetime.datetime.now() < stop: report_devices(fwlan) time.sleep(tracking_period) def main(): tracking_duration = datetime.timedelta(seconds=TRACKING_DURATION) track_devices(tracking_duration, TRACKING_PERIOD) print('done.') if __name__ == '__main__': main() Example: activate a guest network ................................. This only works with devices providing more than one access point and additionally a guest network. If the latter is not provided the class `FritzGuestWLAN` will just handle the access point with highest internal service id, as this is typically the access point for guests. The following example enables the guest access point and if a password is given will set this as the new password. If the guest access point is already active just a new password is set: :: from fritzconnection.lib.fritzwlan import FritzGuestWLAN def enable_guest_access_point(new_password=None): guest_wlan = FritzGuestWLAN(address="192.168.178.1", user="user", password="password") if not guest_wlan.is_enabled: guest_wlan.enable() if new_password: guest_wlan.set_password(new_password) enable_guest_access_point(new_password="new_strong_password") .. _get_wifi_qr_code_example: Example: create a QR-code for wifi access ......................................... This is a common task for guest networks: give visitors easy access to a public network by providing the access data as a QR-code for scanning. The following example will create a QR-code and stores this code as a svg- and a png-file: :: from fritzconnection.lib.fritzwlan import FritzGuestWLAN def write_qr_code_to_file(filename, kind="svg") guest_wlan = FritzGuestWLAN(address="192.168.178.1", user="user", password="password") qr_code = guest_wlan.get_wifi_qr_code(kind=kind) with open(filename, "wb") as fobj: fobj.write(qr_code.read()) write_qr_code_to_file("qr_code.svg", kind="svg") # do the same as png-file: write_qr_code_to_file("qr_code.png", kind="png") Keep in mind to set the file-suffix to the format of the created QR-code. This is the argument `kind` taking "svg", "png" and "pdf" as allowed values. Default value is "svg". The call of the `get_wifi_qr_code()` method returns a file-like object. Instead of writing the content to a file, the return value can get forwarded to any function accepting a file-like object. .. versionadded:: 1.9.0 .. note:: If the `segno`-package is not available, calling the method will raise an `AttributeError`. Refer to `Installation `_ to install this requirement. FritzWLAN API ............. .. automodule:: fritzconnection.lib.fritzwlan :members: Library-Tools ------------- Helper classes and functions for library-development. fritzbase ......... .. automodule:: fritzconnection.lib.fritzbase :noindex: :members: fritztools .......... .. automodule:: fritzconnection.lib.fritztools :members: fritzconnection-1.15.0/docs/sources/license.rst000066400000000000000000000030611501211554500216020ustar00rootroot00000000000000 License ======= As an open source and non profit software fritzconnection has the liberal MIT-License ("Expat License"). So basically, you can do whatever you want as long as you include the original copyright and license notice in any copy of the software/source. In short that means: * You are allowed to download, install and use the software for free, even for commercial products. * You are **entirely** at your own risk. Here is the long version: Copyright (c) 2012-2022 Klaus Bremer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fritzconnection-1.15.0/docs/sources/version_history.rst000066400000000000000000000436341501211554500234400ustar00rootroot00000000000000 Version History =============== 1.15.0 - 2025-05-17 ------------------- - support added for Python 3.14 - FritzConnection: - additional argument `redact_debug_log` (default: False) for optional redacting response in debug output. (#238) (#241) - new method `get_cpu_temperatures()` providing a list of the last recent cpu-temperatures. (Rewrite of #232). - FritzCall: - new attribute `Path` for the class `Call` to access an optional phone message. (#231) - FritzStatus: - new method `get_avm_device_log()` to access system events. Requires FritzOS 8. (#234) - bugfix: in rare cases a session id of None has prevented a successfull request of the http-interface. - **removed**: - `fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_informations()`, deprecated in 1.9.0 - `fritzconnection.lib.fritzstatus.FritzStatus.uptime()`, deprecated in 1.9.0 - `fritzconnection.lib.fritzwlan.FritzWLAN.channel_infos()`, deprecated in 1.9.0 1.14.0 - 2024-08-12 ------------------- - support added for Python 3.13 - New FritzTopology module: represents the mesh-topology graph. - FritzWLAN: - internal function `_get_beacon_security()` removed and substituted with a mapping. (#224) - added ability to output QR code as string stream with ANSI or unicode. (#223) - new property `is_hidden` for wlan ssid. Internal use of this property to handle hidden SSID in QR codes. Parameter `hidden` removed from `FritzWLAN.get_wifi_qr_code()`. (#221) - bugfix: fixed potential password leak in QR code for an unencrypted connection. (#225, #226) - FritzHomeAutomation: - bugfix: converting data from actors which are reporting missing data as non integer values. Missing data are now represented by `None`. (#215) - bugfix: some devices may not return system-information the propper way, causing errors on the cli output. In these cases the system-information will get ignored. (#214) - documentation: some typos corrected. (#202, #204) - testing: `tox.ini` removed because of change to `nox`. Change from `pylint` to `ruff` for linting. - **deprecation**: use of the `json` cache-format is discouraged. Use the default pickle-format instead. The highly dynamic TR-064 parser may get an ouverhaul in the future and to reduce the complexity of the parser the support of `json` for caching will be removed. 1.13.2 - 2023-09-17 ------------------- - bugfix: fix a crash in the cache-verification in case the cache is activated in combination with the Fritz!Box default-ip and multiple AVM-devices are connected in the local network, so an arbitrary device may respond (which would also be a bug in applications using fritzconnection anyway) (introduced in version 1.10.0). - bugfix: fix broken reconnection of fritzmonitor in case of socket loss. (#196) - cleaner type-hints for public api. - documentation: Style change to "Furo" and minor content improvements. 1.13.1 - 2023-08-20 ------------------- - bugfix: added a missing import to the `/docs/requirements.in` file to generate the API-documentation on readthedocs.org (introduced in version 1.13.0). 1.13.0 - 2023-08-19 ------------------- - support added for Python 3.12 - support removed for Python 3.6 - type-hints added for the public API. - test-tool changed from `tox` to `nox`. - documentation-structure adapted according to changed requirements by `readthedocs.org`. - command-line interface: the check for a given password has been removed and substituted by a meaningfull error message in case of an authorization failure. Not every service is password-protected and passwords can optional provided by the environment. Therefore there is no need to require a password at cli level. (Motivated by #192) - bugfix: unneeded required password removed from the `fritzstatus` command-line interface. (#192) - bugfix: make `fritzwlan.get_beacon_security()` work with older router models not supporting the `NewX_AVM-DE_PossibleBeaconTypes` argument. (#191) - **deprecation**: `fritzconnection.lib.fritzphonebook.list_phonebooks()` 1.12.2 - 2023-07-09 ------------------- - bugfix in 'setup.py`: add `long_description_content_type="text/markdown"`, because it is not used as default. 1.12.1 - 2023-07-09 ------------------- - FritzCall: - New method `hangup()`. (#184) - FritzHosts: - bugfix: removed issues preventing the method `get_hosts_attributes()` to return a list of dictionaries representing the host-attributes. (#190) 1.12.0 - 2023-03-08 ------------------- - FritzConnection: - New method `call_http()` for accessing the (aha-)http-interface. - bugfix: create cache directory if not existing. (#183) - FritzHttp: - New core module to access the (aha-)http-interface. - FritzHomeAutomation: - New class `HomeAutomationDevice`. Represents properties and state of a home-automation device. - New method `get_homeautomation_device()`. - New method `get_homeautomation_devices()`. - New method `get_device_information_list()`. Substitutes the `device_information()` method. - FritzMonitor: - bugfix: create new socket on lost connection. (#179) - **Deprecations**: - `fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_information()` 1.11.0 - 2023-01-28 ------------------- - FritzConnection: - New property `updatecheck` allows access to router attributes without permissions (#168) - Faster cache validation. - Exceptions: - New `FritzAuthorizationError` raised on calling actions without the proper permissions (#170) 1.10.3 - 2022-09-08 ------------------- - upper limit for dependency pinning removed to support installation on more recent environments. 1.10.2 - 2022-09-04 ------------------- - bugfix: missing `self` in `FritzStatus.get_device_info()` (introduced in 1.10.0) (#165) - dependencies pinned for `requests` not supporting Python 3.6 since version 2.28.0 and for `segno` (which still works with EOL versions). 1.10.1 - 2022-09-01 ------------------- - bugfix: cli argument forwarding (introduced in 1.10.0) (#164) - enhancement: cli flag `-y` to suppress cache-verification now implies `-x` (use cache) 1.10.0 - 2022-08-24 ------------------- - FritzConnection: - API cache integration added: for faster start up times the router API can optional get saved in a cache-file. This can save up to several seconds run-time on instantiation. - FritzHosts: - New method `get_hosts_attributes` providing a list of dictionaries with the attribues of all known hosts (#134) - FritzStatus: - New property `update_available` (#156) - New property `connection_service` - New property `has_wan_support` (#162) - New property `has_wan_enabled` (#147) - New property `upnp_enabled()` (#153) - New property `device_has_mesh_support` (#146) - New method `get_default_connection_service` (#146) - New method `get_device_info()` (#155) - FritzWLAN: - QR-code now supports encryption information for the described network by auto-detecting the security settings (which is optional but set to default) (#139) - Testing: - requires opencv to check qr-codes - covering Python 3.11 - New class `ArgumentNamespace` added in `fritzconnection.lib.fritztools` for convenient handling of dictionaries returned from `FritzConnection.call_action()` calls. - Better error message in case application access is disabled (#142) 1.9.1 - 2022-01-17 ------------------ - bugfix: AttributeError in `FritzHomeAutomation.device_information()` removed - bug introduced in 1.9.0 (#138) - enhancement: `FritzWLAN.get_wifi_qr_code()` forwards the optional `security` and `hidden` parameters to `segno`. (#139) 1.9.0 - 2022-01-05 ------------------ - FritzWLAN: - New method `get_wifi_qr_code()` for QR-code creation for wifi-access (#133). Requires `segno` as dependency. See `installation <./install.html>`_ for details. The method is also inherited by FritzGuestWLAN. - New method `channel_info()` (#131) - FritzHomeAutomation: New method `device_information()` (#131) - **Deprecations**: - `fritzconnection.lib.fritzhomeauto.FritzHomeAutomation.device_informations()` - `fritzconnection.lib.fritzstatus.FritzStatus.uptime()` - `fritzconnection.lib.fritzwlan.FritzWLAN.channel_infos()` - Documentation improvements 1.8.0 - 2021-12-27 ------------------ - FritzConnection: new command line option `-R` to reboot the system - FritzHosts: - New method `get_generic_host_entries` returning a generator to iterate over all entries as reported by the method `get_generic_host_entry`. - The methods `get_active_hosts` and `get_hosts_info` provide additional host attributes (#127) - Refactoring of the logging module `fritzconnection.core.logger` (introduced in 1.7.0). Now emitting messages from INFO-level and up by default. - Connection errors with the router raised from the underlying `urllib3` library are caught and raised again as FritzConnectionException preserving the connection error information (#128) 1.7.2 - 2021-11-14 ------------------ - bugfix: logger deactivated by default (#123) 1.7.1 - 2021-10-10 ------------------ - Tests extended for Python 3.10 1.7.0 - 2021-09-25 ------------------ - New FritzWLAN-methods: - `enable` and `disable` to enable and disable a wlan network. - `get_password` and `set_password` to get the current password or set a new one for a wlan network. - New FritzGuestWLAN library class. - New FritzConnection method `reboot`. - New logging module `fritzconnection.core.logger`. 1.6.0 - 2021-07-24 ------------------ - New arguments for FritzConnection: `pool_connections` and `pool_maxsize` to adapt the default urllib3 settings (used by requests). (#114). - New properties `FritzStatus.device_uptime` and `FritzStatus.connection_uptime``; the latter a replacement for `FritzStatus.uptime` – still existing as an alias. (#104) - bugfix: html-escape arguments in case that special characters are allowed by the protocol. (#115) - bugfix: `FritzStatus.bytes_sent` will return the 32 bit value from older Fritz!Box models. (#110) - bugfix: raise `FritzActionError` on accessing the mesh topology information from a device not having accesss to this information. (#107) - adding code-of-conduct and contributing files to the repository. 1.5.0 - 2021-05-01 ------------------ - Compatibility with Fritz!OS 7.24 and newer: takes the last logged in username as default in case that a username is not provided. 1.4.2 - 2021-03-06 ------------------ - bugfix: byte_formatter may return wrong numbers on values < 1 and has raised math domain error on values == 0. (bug introduced with version 1.4.1) (#87) 1.4.1 - 2021-02-13 ------------------ - bugfix: FritzStatus library now returns a 32 bit value for *bytes_received* for older Fritz!OS versions not providing the newer 64 bit information instead of raising an exception. (bug introduced with version 1.3.0) (#82) - change: Output of bitrate changed to log10 based calculation (#45, #52) 1.4.0 - 2020-11-29 ------------------ - New core module fritzmonitor for reporting realtime phone call events (#76). - Library class FritzStatus with additional properties: *attenuation*, *str_attenuation*, *noise_margin* and *str_noise_margin* (#69) - Library class FritzHost with additional method *get_host_name* (#75) - Namespace prefix for xml-arguments removed (#66) - Test extended for Python 3.9 (#73) 1.3.4 - 2020-08-06 ------------------ - bugfix: session ignored timeout settings (#63) 1.3.3 - 2020-07-17 ------------------ - bugfix: soap-xml encoding corrected (#59) - bugfix: soap-xml tag-attribute separation fixed (#60) 1.3.2 - 2020-07-11 ------------------ - bugfix: converting arguments returned from soap calls (#58) 1.3.1 - 2020-06-28 ------------------ - authorisation now supports 'myfritz.net' access (#48) - internal refactorings 1.3.0 - 2020-06-21 ------------------ - Library class FritzStatus reports the sent and received bytes now as 64 bit integers and provides easy access to realtime monitor data. - Library class FritzHost provides more methods to access devices, including *wake on LAN* and net topology information. - Library class FritzPhonebook has a new method *get_all_name_numbers()* to fix a bug of *get_all_names()* reporting just one name in case that a phonebook holds multiple entries of the same name. - Boolean arguments send to the router as *1* and *0* can also be given as the Python datatypes *True* and *False* (#30). - Flag -c added to fritzconnection cli interface to report the complete api. - pip installation no longer includes the tests (#39). - pypi classifier changed to *Development Status :: 5 - Production/Stable* 0.8.5 - 2020-06-01 ------------------ - updates the pinned lxml-dependency from version 4.3.4 to 4.5.1 - last version to support Python 2.7, <=3.5 (no more updates) 1.2.1 - 2020-03-21 ------------------ - Library modules handling complex datatypes (urls) can now reuse fritzconnection sessions. 1.2.0 - 2020-01-07 ------------------ - TLS for router communication added. - Command line tools take the new option -e for encrypted connection. - Sessions added for faster connections (significant speed up for TLS) - Functional tests added addressing a physical router. Skipped if no router present. - Bugfix for rendering the documentation of the FritzPhonebook-API (bug introduced in 1.1.1) 1.1.1 - 2019-12-29 ------------------ - Bugfix in FritzConnection default parameters preventing the usage of library modules (bug introduced in 1.1.0) - Minor bugfix in FritzPhonebook storing image-urls 1.1.0 - 2019-12-28 ------------------ - FritzConnection takes a new optional parameter `timeout` limiting the time waiting for a router response. - FritzPhonebook module rewritten for Python 3 without lxml-dependency and added again to the library (missing in version 1.0). - Library module FritzStatus adapted to Python 3. 1.0.1 - 2019-12-21 ------------------ - Bugfix in fritzinspection for command line based inspection of the Fritz!Box API. 1.0.0 - 2019-12-20 ------------------ - Requires Python 3.6 or newer. The 0.8.x release is the last version supporting Python 2.7 and Python 3 up to 3.5 - The ``lxml`` library is no longer a dependency. - New project layout. Library modules are now located in the new ``lib`` package. - Rewrite of the description parser. - Errors reported by the Fritz!Box are now raising specific exceptions. 0.8.4 - 2019-12-16 ------------------ - Bugfix in connection.reconnect(). This bug has been introduced with version 0.8.0. For versions 0.8.0 to 0.8.3 'reconnect' requires a password because of a changed service call. - Documentation updated. 0.8.3 - 2019-09-09 ------------------ - Fix broken test (new in version 0.8.0) - Minor code enhancements 0.8.2 - 2019-08-27 ------------------ - Unified version numbering of the modules. - ServiceError, ActionError and AuthorizationError are also importable from the package. - Some code cleanup. Changes in the development process: .hgignore removed and .gitignore added, changes in setup.py, readme changed to restructured text. As Atlassian has announced to drop support for mercurial on ``bitbucket`` und will remove the according repositories (in June 2020), development of fritzconnection has converted from ``hg`` to ``git`` and the repository has been transfered to ``github``. Unfortunately the issue- and discussion-history will be lost this way (even by keeping the new git-repository at bitbucket). 0.8.1 - 2019-08-24 ------------------ FritzStatus: bugfix requiring a password in combination with fritzconnection >= 0.8.0 FritzStatus: added the ``external_ipv6`` attribute FritzStatus: added the ``max_linked_bit_rate`` attribute for the physical rate. Also added the ``str_max_linked_bit_rate`` attribute for a more readable output. (password must be provided for these infomations) FritzConnection: added the ``AuthorizationError`` exception. 0.8.0 - 2019-08-20 ------------------ Bugfix how servicenames are extracted from the xml-description files. However, the api has not changed. The requirements are now fixed for lxml (4.3.4) and requests (2.22.0) as these versions are still supporting python 2.7 0.7.1 - 0.7.3 ~ 2019-07-24 -------------------------- Bugfixes, no new features or other changes. 0.7.0 - 2019-07-21 ------------------ FritzConnection does now check for the environment variables ``FRITZ_USER`` and ``FRITZ_PASSWORD`` in case that neither user nor password are given. FritzStatus now accepts user and password as keyword-parameters. Keep in mind, that FritzBoxes may return different information about the status depending whether these are gathered with or without a password. 0.6.5 - 2017-07-12 ------------------ There is a new attribute *package_version*: >>> import fritzconnection >>> fritzconnection.package_version 0.6.5 Because every module of the fritzconnection-package has it's own version, version-history of the package gets confusing over time. From now on every change of the content of the package is indicated by the the package-version. Every unchanged module keeps it's version. So i.e. the recent package-version is 0.6.5 but the fritzconnection-module is still in version 0.6 cause nothing has changed in this module since then. 0.6 --- FritzConnection now uses long qualified names as ``servicename``, i.e. ``WLANConfiguration:1`` or ``WLANConfiguration:2``. So these servicenames can now be used to call actions on different services with the same name: >>> connection = FritzConnection() >>> info = connection.call_action('WANIPConnection:2', 'GetInfo') For backward compatibility servicename-extensions like ':2' can be omitted on calling 'call_action'. In this case FritzConnection will use the extension ':1' as default. On calling unknown services or actions in both cases KeyErrors has been raised. Calling an unknown service (or one unaccessible without a password) will now raise a ``ServiceError``. Calling an invalid action on a service will raise an ``ActionError``. Both Exceptions are Subclasses from the new ``FritzConnectionException``. The Exception classes can get imported from fritzconnection: >>> from fritzconnection import ServiceError, ActionError < 0.6 ----- Continuous update of features and bugfixes since first import at 2013-05-01 on bitbucket using mercurial. fritzconnection-1.15.0/fritzconnection/000077500000000000000000000000001501211554500202315ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/__init__.py000066400000000000000000000007611501211554500223460ustar00rootroot00000000000000""" fritzconnection library to communicate with the AVM Fritz!Box by the TR-064 protocoll and allowes access via the http-interface. Provides also an interface for realtime call-monitoring. for documentation refer: https://avm.de/service/schnittstellen/ https://fritzconnection.readthedocs.io/ """ # unused shortcut import are intended: # ruff: noqa: F401 __version__ = "1.15.0" # import shortcuts from .core.fritzconnection import FritzConnection from .core.fritzmonitor import FritzMonitor fritzconnection-1.15.0/fritzconnection/cli/000077500000000000000000000000001501211554500210005ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/cli/__init__.py000066400000000000000000000002531501211554500231110ustar00rootroot00000000000000# package for command line tools # see: setup.py:entry_points # implement cli access here to separate the core- and lib-packages from # the commandline argument parsing. fritzconnection-1.15.0/fritzconnection/cli/fritzcall.py000066400000000000000000000046671501211554500233610ustar00rootroot00000000000000""" fritzcall.py Module to inspect the FritzBox phone API. CLI interface. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ from ..core.exceptions import FritzAuthorizationError from ..lib.fritzcall import FritzCall from . utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) def report_calls(fc, arguments): print('FritzCall:') days = arguments.days num = arguments.num if not days else None if arguments.type == 'in': calls = fc.get_received_calls(num=num, days=days) elif arguments.type == 'out': calls = fc.get_out_calls(num=num, days=days) elif arguments.type == 'missed': calls = fc.get_missed_calls(num=num, days=days) else: calls = fc.get_calls(num=num, days=days) call_type = arguments.type if arguments.type else 'all' print('List of calls:', call_type, '\n') type_ = 'type' number = 'number' time = 'date/time' duration = 'duration' print(f'{type_:>6} {number:24}{time:>18}{duration:>12}\n') for call in calls: print(call) print() def dial_number(fc, number): print(f'dialing number: {number}') fc.dial(number) print('dialing done, please wait for signal.') def add_arguments(parser): parser.add_argument('-n', '--num', nargs='?', default=None, const=None, help='max number of calls in the call-list') parser.add_argument('-d', '--days', nargs='?', default=None, const=None, help='number of days to look back for calls.') parser.add_argument('-t', '--type', nargs='?', default=None, const=None, help='type of calls: [in|out|missed]') parser.add_argument('-c', '--call', nargs='?', default=None, const=None, help='phone number to call') def execute(arguments): fc = get_instance(FritzCall, arguments) if arguments.call: dial_number(fc, arguments.call) else: print_header(fc) report_calls(fc, arguments) def main(): arguments = get_cli_arguments(add_arguments) try: execute(arguments) except FritzAuthorizationError as err: print_common_exception_message(err) if __name__ == '__main__': main() fritzconnection-1.15.0/fritzconnection/cli/fritzhomeauto.py000066400000000000000000000047131501211554500242570ustar00rootroot00000000000000""" fritzhomeauto.py Module to inspect the FritzBox homeautomation API. CLI interface. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ from ..lib.fritzhomeauto import FritzHomeAutomation from . utils import get_cli_arguments, get_instance, print_header def report_verbose(fh): information = fh.device_information() for info in information: width = len(max(info.keys(), key=lambda x: len(x))) line = f'{{attribute:{width}}} : {{value}}' for attribute in sorted(info.keys()): print(line.format(attribute=attribute, value=info[attribute])) print() # add blank line between devices def report_compact(fh): name = 'Device Name' ain = 'AIN' power = 'Power[W]' temperature = 't[°C]' switch_state = 'switch' print(f'{name:24}{ain:18}{power:>10}{temperature:>8} {switch_state}') for di in fh.device_information(): name = di['NewDeviceName'] ain = di['NewAIN'] ain = f"'{ain}'" power = di['NewMultimeterPower'] * 0.01 temperature = di['NewTemperatureCelsius'] *0.1 switch_state = di['NewSwitchState'].lower() print(f'{name:24}{ain:18}{power:>10.3f}{temperature:>8.1f} {switch_state}') print() def report_status(fh, arguments): print('FritzHomeautomation:') print('Status of registered home-automation devices:\n') if arguments.verbose: report_verbose(fh) else: report_compact(fh) def switch_device(fh, arguments): ain = arguments.switch[0] state = arguments.switch[1].lower() == 'on' fh.set_switch(identifier=ain, on=state) def add_arguments(parser): parser.add_argument('-v', '--verbose', nargs='?', default=False, const=True, help='report in verbose mode') parser.add_argument('-s', '--switch', nargs=2, help='set switch state. requires two parameters: ' 'ain and state [on|off]') def main(): arguments = get_cli_arguments(add_arguments) if not arguments.password: print('Exit: password required.') return fh = get_instance(FritzHomeAutomation, arguments) if arguments.switch: switch_device(fh, arguments) else: print_header(fh) report_status(fh, arguments) if __name__ == '__main__': main() fritzconnection-1.15.0/fritzconnection/cli/fritzhosts.py000066400000000000000000000024271501211554500235760ustar00rootroot00000000000000""" fritzhosts.py Module to inspect the FritzBox API for registered hosts. CLI interface. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ from ..core.exceptions import FritzAuthorizationError from ..lib.fritzhosts import FritzHosts from .utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) def print_status(fh): print('FritzHosts:') print('List of registered hosts:\n') print('{:>3}: {:<16} {:<28} {:<17} {}\n'.format( 'n', 'ip', 'name', 'mac', 'status')) hosts = fh.get_hosts_info() for index, host in enumerate(hosts, start=1): status = 'active' if host['status'] else '-' ip = host['ip'] if host['ip'] else '-' mac = host['mac'] if host['mac'] else '-' hn = host['name'] print(f'{index:>3}: {ip:<16} {hn:<28} {mac:<17} {status}') print('\n') def execute(): args = get_cli_arguments() fh = get_instance(FritzHosts, args) print_header(fh) print_status(fh) def main(): try: execute() except FritzAuthorizationError as err: print_common_exception_message(err) if __name__ == '__main__': main() fritzconnection-1.15.0/fritzconnection/cli/fritzinspection.py000066400000000000000000000140111501211554500246010ustar00rootroot00000000000000""" fritzinspection.py Module to inspect the FritzBox API for available services and actions. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ import datetime from ..core.exceptions import FritzAuthorizationError from ..core.fritzconnection import FritzConnection from .utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) class FritzInspection: """ Class for cli use to inspect available services and according actions of the given device (the Fritz!Box). """ # pylint: disable=invalid-name # self.fc is ok. def __init__(self, fc): self.fc = fc def view_servicenames(self): """Send all known service names to stdout.""" print('Servicenames:') for service_name in self.fc.services: print('{:20}{}'.format('', service_name)) def view_actionnames(self, service_name, view_arguments=False): """Send all action names of the given service to stdout.""" print('\n{:<20}{}'.format('Servicename:', service_name)) print('Actionnames:') try: service = self.fc.services[service_name] except KeyError as err: print(f'Error: Invalid Servicename {err}') else: for action_name in service.actions: print('{:20}{}'.format('', action_name)) if view_arguments: action = service.actions[action_name] for argument in sorted(action.arguments.keys()): print('{:24}- {}'.format('', argument)) print() def view_actionarguments(self, service_name, action_name): """Send all action names of the given service to stdout.""" try: service = self.fc.services[service_name] except KeyError as err: print(f'Error: Invalid Servicename {err}') return try: action = service.actions[action_name] except KeyError as err: print(f'Error: Invalid Actionname {err}') return print('\n{:<20}{}'.format('Service:', service_name)) print('{:<20}{}'.format('Action:', action_name)) print('Parameters:\n') print(' {:38}{:14}{}\n'.format('Name', 'direction', 'data type')) for argument in action.arguments.values(): if argument.direction == 'in': direction = '-> in' else: direction = ' out ->' var = service.state_variables.get(argument.relatedStateVariable, '') line = f' {argument.name:38}{direction:14}{var.dataType}' print(line) def view_complete_api(self): """ Send the complete api to stdout. This can be a lengthy output that may be redirected to a file. """ print() system_info = self.fc.device_manager.system_info # some devices may return None as system_info if system_info: print( f"system : {system_info[-1]}\n" f"build : {system_info[-2]}\n" f"hw-code: {system_info[0]}" ) now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"Report date: {now}") for service_name, service in self.fc.services.items(): if service_name == 'any1': continue print() print('=' * 65) for action_name in service.actions: self.view_actionarguments(service_name, action_name) def add_arguments(parser): parser.add_argument('-r', '--reconnect', action='store_true', help='Reconnect and get a new ip') parser.add_argument('-R', '--reboot', action='store_true', help='Reboot the router') parser.add_argument('-s', '--services', action='store_true', help='List all available services') parser.add_argument('-S', '--serviceactions', nargs=1, help='List actions for the given service: ') parser.add_argument('-a', '--servicearguments', nargs=1, help='List arguments for the actions of a ' 'specified service: .') parser.add_argument('-A', '--actionarguments', nargs=2, help='List arguments for the given action of a ' 'specified service: . ' 'Lists also direction and data type of the ' 'arguments.') parser.add_argument('-c', '--complete', nargs='?', default=False, const=True, help='List the complete api of the router') def run_inspector(inspector, args): print_header(inspector.fc) if args.services: inspector.view_servicenames() elif args.serviceactions: inspector.view_actionnames(args.serviceactions[0]) elif args.servicearguments: inspector.view_actionnames(args.servicearguments[0], view_arguments=True) elif args.actionarguments: inspector.view_actionarguments(args.actionarguments[0], args.actionarguments[1]) elif args.complete: inspector.view_complete_api() elif args.reconnect: inspector.fc.reconnect() print('reconnect the router.') elif args.reboot: inspector.fc.reboot() print('reboot the router.') print() def execute(): args = get_cli_arguments(add_arguments) fc = get_instance(FritzConnection, args) inspector = FritzInspection(fc=fc) run_inspector(inspector, args) def main(): try: execute() except FritzAuthorizationError as err: print_common_exception_message(err) if __name__ == '__main__': main() fritzconnection-1.15.0/fritzconnection/cli/fritzmonitor.py000066400000000000000000000057611501211554500241310ustar00rootroot00000000000000"""" Module to inspect phone-call events in real time. This is the command line interface for the core.fritzmonitor module and should serve as an example how to use an instance of FritzMonitor. To run this, the CallMonitor service of the box has to be activated. This can be done with any registered Phone by typing the following codes: activate: #96*5* deactivate: #96*4* """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer import argparse import queue from ..core.fritzmonitor import ( FritzMonitor, FRITZ_IP_ADDRESS, FRITZ_MONITOR_SOCKET_TIMEOUT, ) from .. import __version__ HEALTHCHECK_TIMEOUT = 10 def print_header(args): print(f"\nfritzconnection v{__version__}") print(f"start fritzmonitor on address: {args.address}") print(f"settings for socket-timeout: {args.timeout} [sec]") print(f"settings for healthcheck-timeout: {args.healthcheck} [sec]") print("(to stop press ^C)\n") def get_cli_arguments(): parser = argparse.ArgumentParser() parser.add_argument( "-i", "--ip-address", nargs="?", default=FRITZ_IP_ADDRESS, const=None, dest="address", help="Specify ip-address of the FritzBox to connect to." "Default: %s" % FRITZ_IP_ADDRESS, ) parser.add_argument( "-t", "--timeout", nargs="?", type=int, default=FRITZ_MONITOR_SOCKET_TIMEOUT, const=None, dest="timeout", help="Setting for socket timeout [sec]." "Default: %s" % FRITZ_MONITOR_SOCKET_TIMEOUT, ) parser.add_argument( "-c", "--healthcheck", nargs="?", type=int, default=HEALTHCHECK_TIMEOUT, const=None, dest="healthcheck", help="Setting for internal health-check interval [sec]." "Default: %s" % HEALTHCHECK_TIMEOUT, ) args = parser.parse_args() return args def process_events(monitor, event_queue, healthcheck_interval): while True: try: event = event_queue.get(timeout=healthcheck_interval) except queue.Empty: # check health: if not monitor.is_alive: raise OSError("Error: fritzmonitor connection failed") else: # do event processing here: print(event) def main(): """ Entry point: example to use FritzMonitor. """ args = get_cli_arguments() print_header(args) # create a FritzMonitor instance and get the event_queue by calling start(). # start() returns the queue for the events. try: with FritzMonitor(address=args.address, timeout=args.timeout) as monitor: event_queue = monitor.start() process_events(monitor, event_queue, healthcheck_interval=args.healthcheck) except (OSError, KeyboardInterrupt) as err: print(err) print("exit fritzmonitor") if __name__ == "__main__": main() fritzconnection-1.15.0/fritzconnection/cli/fritzphonebook.py000066400000000000000000000047501501211554500244230ustar00rootroot00000000000000""" fritzphonebook.py Module to inspect the Fritz!Box phonebooks. CLI interface. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Authors: Klaus Bremer, David M. Straub """ from ..core.exceptions import FritzAuthorizationError from ..lib.fritzphonebook import FritzPhonebook from .utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) def print_phonebooks(fpb): for id in fpb.phonebook_ids: info = fpb.phonebook_info(id) print(f"Content of phonebook: {info['name']} ") for name, numbers in fpb.get_all_names(id).items(): print(f"{name:<30}{', '.join(numbers)}") print() def print_search_name(fpb, arguments): found = False for id in fpb.phonebook_ids: contacts = fpb.get_all_names(id) numbers = contacts.get(arguments.name) if numbers: print(f"{arguments.name:<30}{', '.join(numbers)}") found = True if not found: print(f"name {arguments.name} not found.") def print_search_number(fpb, arguments): found = False for id in fpb.phonebook_ids: numbers = fpb.get_all_numbers(id) if arguments.number in numbers: print(f"{numbers[arguments.number]:<30}{arguments.number}") found = True if not found: print(f'number {arguments.number} not found.') def add_arguments(parser): parser.add_argument('-a', '--all', action='store_true', help='List all phone books ') parser.add_argument('--name', nargs='?', default=0, help='Name for number search') parser.add_argument('--number', nargs='?', default=0, help='Number for name search') def execute(): arguments = get_cli_arguments(add_arguments) fpb = get_instance(FritzPhonebook, arguments) print_header(fpb) print('FritzPhonebook:\n') if arguments.all: print_phonebooks(fpb) elif arguments.name: print_search_name(fpb, arguments) elif arguments.number: print_search_number(fpb, arguments) print() # blank line for better readability def main(): try: execute() except FritzAuthorizationError as err: # should not happen for this service print_common_exception_message(err) if __name__ == '__main__': main() fritzconnection-1.15.0/fritzconnection/cli/fritzstatus.py000066400000000000000000000031671501211554500237630ustar00rootroot00000000000000""" fritzstatus.py Module to inspect the FritzBox API for available services and actions. CLI interface. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ from ..core.exceptions import ( FritzServiceError, FritzActionError, FritzAuthorizationError ) from ..lib.fritzstatus import FritzStatus from .utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) def print_status(fs): print("FritzStatus:\n") status_information = [ ("is linked", "is_linked"), ("is connected", "is_connected"), ("external ip (v4)", "external_ip"), ("external ip (v6)", "external_ipv6"), ("internal ipv6-prefix", "ipv6_prefix"), ("uptime", "str_uptime"), ("bytes send", "bytes_sent"), ("bytes received", "bytes_received"), ("max. bit rate", "str_max_bit_rate"), ] for status, attribute in status_information: try: information = getattr(fs, attribute) except (FritzServiceError, FritzActionError): information = f'unsupported attribute "{attribute}"' print(f" {status:22}: {information}") print() def execute(): arguments = get_cli_arguments() fs = get_instance(FritzStatus, arguments) print_header(fs) print_status(fs) def main(): try: execute() except FritzAuthorizationError as err: # should not happen for this service print_common_exception_message(err) if __name__ == "__main__": main() fritzconnection-1.15.0/fritzconnection/cli/fritzwlan.py000066400000000000000000000043331501211554500233750ustar00rootroot00000000000000""" fritzwlan.py Module to inspect the FritzBox API for wlan devices. CLI interface. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ import itertools from ..core.exceptions import FritzServiceError, FritzAuthorizationError from ..lib.fritzwlan import FritzWLAN, SERVICE from . utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) def get_header(): index = 'index' status = 'active' mac = 'mac' ip = 'ip' signal = 'signal' speed = 'speed' return f'{index:>5}{status:>8}{mac:>20}{ip:>18}{signal:>8}{speed:>8}' def report_wlanconfiguration(fw, extension): fw.service = extension hosts_info = fw.get_hosts_info() if hosts_info: print(f'Hosts registered at {SERVICE}{extension}:') print(f'WLAN name: {fw.ssid}') print(f'channel : {fw.channel}') print(get_header()) for info in hosts_info: index = info['index'] status = info['status'] mac = info['mac'] ip = info['ip'] signal = info['signal'] speed = info['speed'] print(f'{index:>5}{status:>8}{mac:>20}{ip:>18}{signal:>8}{speed:>8}') print() def report_devices(fw, args): if args.service: try: report_wlanconfiguration(fw, args.service) except FritzServiceError as err: print(f'Error: {err}') else: for n in itertools.count(1): try: report_wlanconfiguration(fw, n) except FritzServiceError: break def add_arguments(parser): parser.add_argument('-s', '--service', nargs='?', default=0, const=None, help='WLANConfiguration service number') def execute(): arguments = get_cli_arguments(add_arguments) fritz_wlan = get_instance(FritzWLAN, arguments) print_header(fritz_wlan) report_devices(fritz_wlan, arguments) def main(): try: execute() except FritzAuthorizationError as err: print_common_exception_message(err) if __name__ == '__main__': main() fritzconnection-1.15.0/fritzconnection/cli/utils.py000066400000000000000000000102261501211554500225130ustar00rootroot00000000000000""" utils.py This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ import argparse import os from ..core.fritzconnection import ( FritzConnection, FRITZ_CACHE_FORMAT_PICKLE, FRITZ_IP_ADDRESS, FRITZ_TCP_PORT, FRITZ_ENV_USERNAME, FRITZ_ENV_PASSWORD, FRITZ_ENV_USECACHE, FRITZ_ENV_CACHEDIRECTORY, FRITZ_ENV_CACHE_FORMAT, ) from ..core.utils import get_bool_env from .. import __version__ def print_header(instance): print(f'\nfritzconnection v{__version__}') if isinstance(instance, FritzConnection): print(instance) else: print(instance.fc) print() def print_common_exception_message(error_object): print(error_object) print( "\nSeems you forgot to provide the user and/or the password." "\nYou can provide these with the flag -u and -p or store them" "\nin the environment as FRITZ_USERNAME and FRITZ_PASSWORD." "\n(Environment changes will get recognized by new processes.)\n" ) def get_instance(cls, args): # -y implies -x: if not args.verify_cache: args.use_cache = True return cls( address=args.address, port=args.port, user=args.username, password=args.password, use_tls=args.encrypt, use_cache=args.use_cache, verify_cache=args.verify_cache, cache_directory=args.cache_directory, cache_format=args.cache_format, ) def get_cli_arguments(scan_additional_arguments=None): parser = argparse.ArgumentParser() parser.add_argument('-i', '--ip-address', nargs='?', default=FRITZ_IP_ADDRESS, const=None, dest='address', help='Specify ip-address of the FritzBox to connect to. ' 'Default: %s' % FRITZ_IP_ADDRESS) parser.add_argument('--port', nargs='?', default=None, const=None, help='Port of the FritzBox to connect to. ' 'Default: %s' % FRITZ_TCP_PORT) parser.add_argument('-u', '--username', nargs='?', default=os.getenv(FRITZ_ENV_USERNAME, None), help='Fritzbox authentication username') parser.add_argument('-p', '--password', nargs='?', default=os.getenv(FRITZ_ENV_PASSWORD, None), help='Fritzbox authentication password') parser.add_argument('-e', '--encrypt', nargs='?', default=False, const=True, help='Flag: use secure connection (TLS)') parser.add_argument('-x', '--use-cache', default=get_bool_env(FRITZ_ENV_USECACHE, False), action="store_true", dest='use_cache', help='Flag: use api cache (e[x]cellerate: speed-up subsequent ' 'instantiations)' ) parser.add_argument('-y', '--suppress-cache-verification', action='store_false', default=True, dest='verify_cache', # needs inverted boolean to suppress. help='Flag: suppress cache verification, implies -x' ) parser.add_argument('--cache-format', nargs='?', default=os.getenv( FRITZ_ENV_CACHE_FORMAT, FRITZ_CACHE_FORMAT_PICKLE ), dest='cache_format', help="cache-file format: json|pickle (default: pickle)" ) parser.add_argument('--cache-directory', nargs='?', default=os.getenv(FRITZ_ENV_CACHEDIRECTORY, None), const=None, dest='cache_directory', help="path to cache directory (default: ~.fritzconnection)" ) if scan_additional_arguments: scan_additional_arguments(parser) args = parser.parse_args() return args fritzconnection-1.15.0/fritzconnection/core/000077500000000000000000000000001501211554500211615ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/core/__init__.py000066400000000000000000000000011501211554500232610ustar00rootroot00000000000000 fritzconnection-1.15.0/fritzconnection/core/devices.py000066400000000000000000000073631501211554500231660ustar00rootroot00000000000000""" Implements the DeviceManager for physical and virtual devices. Every physical device (a router) has a set of virtual subdevices. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from .processor import Description from .utils import get_xml_root class DeviceManager: """ Knows all data about the device and the sub-devices, including the available services. Takes an optional `timeout` parameter to limit the time waiting for a router response. The optional parameter `session` is a reusable connection and can speed up the communication with the device. In case `session` is given, `timeout` will not get used. """ def __init__(self, timeout=None, session=None): self.descriptions = [] self.services = {} self.timeout = timeout self.session = session @property def modelname(self): """ Take the root-device of the first description and return the according modelname. This is the name of the Fritz!Box itself. Will raise an IndexError if the method is called before descriptions are added. """ return self.descriptions[0].device_model_name @property def system_version(self): """ Returns the system-version as string with minor- and patch-level. This corresponds to the OS version reported by the router web-interface. Returns None if no system information is available. """ version = None for description in self.descriptions: version = description.system_version if version: return version return None @property def system_info(self): """ Returns a tuple with Hardwarecode, Major-, Minor-, Patch-Level, Buildnumber and Display-String, in this order. Return None if this information is not available. """ system_info = None for description in self.descriptions: system_info = description.system_info if system_info and system_info[0]: return system_info return None def add_description(self, source): """ Adds description data about the devices and the according services. 'source' is a string with the xml-data, like the content of an igddesc- or tr64desc-file. """ root = get_xml_root(source, timeout=self.timeout, session=self.session) self.descriptions.append(Description(root)) def scan(self): """ Scans all available services defined by the description files. Must get called after all xml-descriptions are added. """ for description in self.descriptions: self.services.update(description.services) def load_service_descriptions(self, address, port): """ Triggers the load of the scpd files of the services, so they known their actions. """ for service in self.services.values(): service.load_scpd( address, port, timeout=self.timeout, session=self.session ) def serialize(self): """ Returns a json-serializable list with Python-datastructures representing the known api of the device. """ return [description.serialize() for description in self.descriptions] def deserialize(self, data): """ Fills the collections `self.descriptions` and `self.services` with the content provided by `data` (from a json-source). """ for description_data in data: self.descriptions.append(Description.from_data(description_data)) fritzconnection-1.15.0/fritzconnection/core/exceptions.py000066400000000000000000000133421501211554500237170ustar00rootroot00000000000000""" Module defining fritzconnection specific exceptions. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer # # # Exception Inheritance: # ---------------------- # # FritzConnectionException # | # |--> ActionError --> FritzActionError # |--> ServiceError --> FritzServiceError # | # |--> FritzAuthorizationError # |--> FritzHttpInterfaceError # | # |--> FritzResourceError # | # |--> FritzArgumentError # | | # | |--> FritzArgumentValueError # | | # | |--> FritzArgumentStringToShortError # | |--> FritzArgumentStringToLongError # | |--> FritzArgumentCharacterError # | # |--> FritzInternalError # | | # | |--> FritzActionFailedError # | |--> FritzOutOfMemoryError # | # |--> FritzSecurityError # | # |-->|--> FritzLookUpError # | | # KeyError -------+-->| # | # | # |-->|--> FritzArrayIndexError # | # IndexError -------->| # # # export all Exceptions on * imports __all__ = [ 'FritzConnectionException', 'FritzActionError', 'FritzActionFailedError', 'FritzHttpInterfaceError', 'FritzArgumentCharacterError', 'FritzArgumentError', 'FritzArgumentStringToLongError', 'FritzArgumentStringToShortError', 'FritzArgumentValueError', 'FritzArrayIndexError', 'FritzAuthorizationError', 'FritzInternalError', 'FritzLookUpError', 'FritzOutOfMemoryError', 'FritzResourceError', 'FritzSecurityError', 'FritzServiceError', ] class FritzConnectionException(Exception): """Base Exception for communication errors with the Fritz!Box""" class ActionError(FritzConnectionException): """ Exception raised by calling non-existing actions. Legacy Exception. Use FritzActionError instead. """ class ServiceError(FritzConnectionException): """ Exception raised by calling non-existing services. Legacy Exception. Use FritzServiceError instead. """ class FritzServiceError(ServiceError): """Exception raised by calling non-existing services.""" class FritzActionError(ActionError): """Exception raised by calling non-existing actions.""" class FritzHttpInterfaceError(FritzConnectionException): """ Exception raised on calling the aha-interface and getting an response with a status-code other than 200. """ class FritzResourceError(FritzConnectionException): """ Exception raised if a description file like an igddesc-file is not provided by the router. This Exception is used internally and logged, but not reraised for the user of the library. """ class FritzArgumentError(FritzConnectionException): """Exception raised by invalid arguments.""" class FritzArgumentValueError(FritzArgumentError): """ Exception raised by arguments with invalid values. Inherits from the more generic FritzArgumentError. """ class FritzArgumentStringToShortError(FritzArgumentValueError): """ Exception raised by arguments with invalid string length for the string being to short. Inherits from the more generic FritzArgumentValueError. """ class FritzArgumentStringToLongError(FritzArgumentValueError): """ Exception raised by arguments with invalid string length for the string being to long. Inherits from the more generic FritzArgumentValueError. """ class FritzArgumentCharacterError(FritzArgumentValueError): """ Exception raised by arguments with invalid characters. Inherits from the more generic FritzArgumentValueError. """ class FritzInternalError(FritzConnectionException): """Exception raised by panic in the box.""" class FritzActionFailedError(FritzInternalError): """ Exception raised by the box unable to execute the action properly. Inherits from the more generic FritzInternalError. """ class FritzOutOfMemoryError(FritzInternalError): """ Exception raised by memory shortage of the box. Inherits from the more generic FritzInternalError. """ class FritzSecurityError(FritzConnectionException): """Authorization error or wrong security context.""" class FritzLookUpError(FritzConnectionException, KeyError): """ Lookup for id or entry in existing internal array failed. Inherits from KeyError. So KeyError can also be used for exception handling. """ class FritzArrayIndexError(FritzConnectionException, IndexError): """ Addressing an entry in an internal array by index failed. Inherits from IndexError. So IndexError can also be used for exception handling. """ class FritzAuthorizationError(FritzConnectionException): """ Authentication error. Not allowed to access the box at all. """ # Collection of error codes and corresponding exceptions: # (the error codes are defined by AVM) FRITZ_ERRORS = { '401': FritzActionError, '402': FritzArgumentError, '501': FritzActionFailedError, '600': FritzArgumentValueError, '603': FritzOutOfMemoryError, '606': FritzSecurityError, '713': FritzArrayIndexError, '714': FritzLookUpError, '801': FritzArgumentStringToShortError, '802': FritzArgumentStringToLongError, '803': FritzArgumentCharacterError, '820': FritzInternalError, } fritzconnection-1.15.0/fritzconnection/core/fritzconnection.py000066400000000000000000000656051501211554500247650ustar00rootroot00000000000000""" Module to communicate with the AVM Fritz!Box. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from __future__ import annotations import json import os import pickle import string import xml.etree.ElementTree as ElementTree from pathlib import Path from typing import Any # from typing import Union # for python < 3.10 import requests from requests.auth import HTTPDigestAuth from .devices import DeviceManager from .exceptions import ( FritzConnectionException, FritzResourceError, FritzServiceError, ) from .fritzhttp import FritzHttp from .processor import Service # import for typ-hint from .soaper import Soaper from .utils import ( get_bool_env, get_xml_root, localname ) # disable InsecureRequestWarning from urllib3 # because of skipping certificate verification: import urllib3 urllib3.disable_warnings() # FritzConnection defaults: FRITZ_IP_ADDRESS = "169.254.1.1" FRITZ_TCP_PORT = 49000 FRITZ_TLS_PORT = 49443 FRITZ_USERNAME = "dslf-config" # for Fritz!OS < 7.24 FRITZ_BOXINFO_FILE = "jason_boxinfo.xml" FRITZ_IGD_DESC_FILE = "igddesc.xml" FRITZ_TR64_DESC_FILE = "tr64desc.xml" FRITZ_DESCRIPTIONS = [FRITZ_IGD_DESC_FILE, FRITZ_TR64_DESC_FILE] FRITZ_USERNAME_REQUIRED_VERSION = 7.24 FRITZ_APPLICATION_ACCESS_DISABLED = """\n FRITZ!Box: access for applications disabled. Check: Home Network -> Network -> Network Settings for "Allow access for applications".\n""" FRITZ_CACHE_DIR = ".fritzconnection" FRITZ_CACHE_EXT = "_cache" FRITZ_CACHE_JSON_SUFFIX = "json" FRITZ_CACHE_PICKLE_SUFFIX = "pcl" FRITZ_CACHE_FORMAT_JSON = "json" FRITZ_CACHE_FORMAT_PICKLE = "pickle" FRITZ_CACHE_FORMATS = { FRITZ_CACHE_FORMAT_JSON: FRITZ_CACHE_JSON_SUFFIX, FRITZ_CACHE_FORMAT_PICKLE: FRITZ_CACHE_PICKLE_SUFFIX } FRITZ_CACHE_UNKNOWN_FORMAT_MESSAGE = f"""\ Unknown cache format "{{}}".\n Use one of {tuple(FRITZ_CACHE_FORMATS.keys())}.\n""" FRITZ_ENV_USERNAME = "FRITZ_USERNAME" FRITZ_ENV_PASSWORD = "FRITZ_PASSWORD" FRITZ_ENV_USECACHE = "FRITZ_USECACHE" FRITZ_ENV_CACHE_FORMAT = "FRITZ_CACHEFORMAT" FRITZ_ENV_CACHEDIRECTORY = "FRITZ_CACHEDIRECTORY" # same defaults as used by requests: DEFAULT_POOL_CONNECTIONS = 10 DEFAULT_POOL_MAXSIZE = 10 # supported protocols: PROTOCOLS = ['http://', 'https://'] class FritzConnection: """ Main class to set up a connection to the Fritz!Box router. All parameters are optional. `address` should be the ip of a router, in case that are multiple Fritz!Box routers in a network, the ip must be given. Otherwise, it is undefined which router will respond. If `user` and `password` are not provided, the environment gets checked for FRITZ_USERNAME and FRITZ_PASSWORD settings and taken from there, if found. Basic usage assuming `user` and `password` stored in the environment: >>> fc = FritzConnection(address="192.168.178.1") >>> fc.call_action("WANIPConn1", "ForceTermination", arguments={}) This will reconnect the router with the external network. `arguments` is not necessary here, but in case where arguments must be provided, this is done by `arguments` (see also the documentation for the `call_action()`` method`). The `call_action()` method is used for the TR-064 API and returns a dictionary with the results. For accessing the http-interface (aka AHA-HTTP-Interface) of the router, FritzConnection provides the `call_http()` method (added in version 1.12). As arguments this method takes a required command (like `getswitchlist`) and optional parameters as described in the AVM documentation: >>> fc.call_http("getswitchlist") This method triggers a http response and returns a dictionary with three key-value pairs: the `content-type`, the `encoding` and the `content` itself. The values are all of type string. The content-type is typically "text/plain" or "text/xml", the encoding, typically "utf-8". The method will raise a FritzAuthorizationError in case of missing credentials. In case of an unknown command or identifier a FritzHttpInterfaceError will get raised. .. versionadded:: 1.12 The optional parameter `timeout` is a floating number in seconds limiting the time waiting for a router response. This is a global setting for the internal communication with the router. In case of a timeout a `requests.ConnectTimeout` exception gets raised. .. versionadded:: 1.1 `use_tls` accepts a boolean for using encrypted communication with the Fritz!Box. Default is `False`. .. versionadded:: 1.2 For some actions the Fritz!Box needs a password and since Fritz!OS 7.24 also requires a username, the previous default username is just valid for OS versions < 7.24. In case the username is not given and the system version is 7.24 or newer, FritzConnection uses the last logged-in username as default. .. versionadded:: 1.5 For applications where the urllib3 default connection-pool size should get adapted, the arguments `pool_connections` and `pool_maxsize` can get set explicitly. .. versionadded:: 1.6 The flag `use_cache` activates caching (default `False`). Caching can speed up instantiation significantly. The cached data are specific for the router ip, the router model and the installed FritzOS version. Multiple devices in the network can have separate cache-fies and can get used in parallel. By default the cache files are stored in the user home-directory in a `.fritzconnection` folder. To change this location use the parameter `cache_directory` providing a string or a `pathlib.Path` object. With `cache_format` two formats can specified for data serialization: `json` and `pickle`. These two values are available as constants `FRITZ_CACHE_FORMAT_JSON` and `FRITZ_CACHE_FORMAT_PICKLE`. Default is `pickle`. The flag `verify_cache` will enable cache verification (default is `True`). If set to `False` loading the api-data will be even faster, but the cache will not get renewed in case of FritzOS updates or a router change. All cache-settings can also configured in the environment: FRITZ_USECACHE (True|False), FRITZ_CACHEFORMAT (json|pickle) and FRITZ_CACHEDIRECTORY (a path). .. versionadded:: 1.10 `redact_debug_log` accepts a boolean for enabling redacting sensitiv data (i.e. phone numbers) in debug outputs. Default is `False`. .. versionadded:: 1.15 """ def __init__( self, address: str | None = None, port: int | None = None, user: str | None = None, password: str | None = None, timeout: float | None = None, use_tls: bool = False, use_cache: bool = False, verify_cache: bool = True, cache_directory: str | Path | None = None, cache_format: str | None = None, pool_connections: int = DEFAULT_POOL_CONNECTIONS, pool_maxsize: int = DEFAULT_POOL_MAXSIZE, redact_debug_log: bool = False ): """ Initialisation of FritzConnection: reads all data from the box and also the api-description (the servicenames and according actionnames as well as the parameter-types) that can vary among models and stores the information as instance-attributes. This can be an expensive operation. Because of this an instance of FritzConnection should be created once and reused in an application. All parameters are optional. But if there is more than one FritzBox in the network, an address (ip as string) must be given, otherwise it is not defined which box may respond. If no user is given the Environment gets checked for a FRITZ_USERNAME setting. If there is no entry in the environment the avm-default-username will be used. If no password is given the Environment gets checked for a FRITZ_PASSWORD setting. So password can be used without using configuration-files or even hardcoding. The optional parameter `timeout` is a floating point number in seconds limiting the time waiting for a router response. The timeout can also be a tuple for different values for connection- and read-timeout values: (connect timeout, read timeout). The timeout is a global setting for the internal communication with the router. In case of a timeout a `requests.ConnectTimeout` exception gets raised. `use_tls` accepts a boolean for using encrypted communication with the Fritz!Box. Default is `False`. `use_cache` is a boolean whether a cache should get used for the router api data. By default the api data are loaded from the router at instantiation time what can take several seconds to complete. `cache_directory` is the path to the directory storing the cached data. By default this is a folder named '.fritzconnection' in the users home-directory. `cache_format` supports two file-formats: json and pickle (default). All cache settings can also defined in the environment: FRITZ_USECACHE (True|False), FRITZ_CACHEFORMAT (json|pickle) and FRITZ_CACHEDIRECTORY (a path). If `verify_cache` is `True` it checks whether the model has changed or the system software has got an update. In this case the cache gets renewed. Default is `True`. Deactivating the verification gives another gain in speed, but on updates and other changes you are on your own. `pool_connections` and `pool_maxsize` accept integers for changing the default urllib3 settings in order to modify the number of reusable connections. `redact_debug_log` accepts a boolean for enabling redacting some sensitiv data in debug outputs. Default is `False`. """ if address is None: address = FRITZ_IP_ADDRESS if user is None: user = os.getenv(FRITZ_ENV_USERNAME, FRITZ_USERNAME) if password is None: password = os.getenv(FRITZ_ENV_PASSWORD, "") if use_cache is None: use_cache = get_bool_env(FRITZ_ENV_USECACHE) if cache_format is None: cache_format = os.getenv( FRITZ_ENV_CACHE_FORMAT, FRITZ_CACHE_FORMAT_PICKLE ) if cache_directory is None: cache_directory = os.getenv(FRITZ_ENV_CACHEDIRECTORY, None) if port is None and use_tls: port = FRITZ_TLS_PORT elif port is None: port = FRITZ_TCP_PORT address = self.set_protocol(address, use_tls) # a session will speed up connections (significantly for tls) # and is required to change the default poolsize: session = requests.Session() session.verify = False if password: session.auth = HTTPDigestAuth(user, password) adapter = requests.adapters.HTTPAdapter( pool_connections=pool_connections, pool_maxsize=pool_maxsize) session.mount(PROTOCOLS[use_tls], adapter) # TODO: remove 'self._updatecheck' when 3.7 is no longer supported. # this is a dictionary-based cache self._updatecheck: dict | None = None # store as instance attributes for use by library modules self.address = address self.session = session self.timeout = timeout self.port = port self.soaper = Soaper( address, port, user, password, timeout=timeout, session=session, redact_debug_log=redact_debug_log ) self.device_manager = DeviceManager(timeout=timeout, session=session) self._load_router_api( use_cache, cache_directory, cache_format, verify_cache ) # set default user for FritzOS >= 7.24: self._reset_user(user, password) # provide also the http-interface for more homeautomation tasks self.http_interface = FritzHttp(self) def __repr__(self): """Return a readable representation""" return ( f"{self.modelname} at {self.soaper.address}\n" f"FRITZ!OS: {self.system_version}" ) # TODO: change type-hint to -> dict[str, Service] # when Python 3.8 is no longer supported @property def services(self) -> dict[str, Service]: """ Dictionary of service instances. Keys are the service names. """ return self.device_manager.services @property def modelname(self) -> str: """ Returns the modelname of the router. """ return self.device_manager.modelname @property def system_version(self) -> str: """ Returns system version if known, otherwise None. """ return self.device_manager.system_version @property def device_description(self) -> str: """ Returns a string with the device description. This is a combination of the device model name and the installed software version. """ return self.call_action("DeviceInfo1", "GetInfo")["NewDescription"] # TODO: change to @functools.cached_property # when stopping support for Python 3.7 # in this case the self._updatecheck instance attribute is no longer needed. @property def updatecheck(self) -> dict: """ Dictionary with information about the hard- and software version of the device according to "http://fritz.box/jason_boxinfo.xml". """ if self._updatecheck is None: xml_data = get_xml_root( f"{self.address}/{FRITZ_BOXINFO_FILE}", timeout=self.timeout, session=self.session ) self._updatecheck = { localname(elem): elem.text for elem in xml_data } return self._updatecheck @staticmethod def normalize_name(name: str) -> str: """ Returns the normalized service name. E.g. `WLANConfiguration` and `WLANConfiguration:1` will get converted to `WLANConfiguration1`. """ if ":" in name: name, number = name.split(":", 1) name = name + number elif name[-1] not in string.digits: name = name + "1" return name @staticmethod def set_protocol(url: str, use_tls: bool) -> str: """ Sets the protocol of the `url` according to the `use_tls`-flag and returns the modified `url`. Does not check whether the `url` given as parameter is correct. """ url = url.split("//", 1)[-1] return PROTOCOLS[use_tls] + url def _reset_user(self, user, password): """ For Fritz!OS >= 7.24: if a password is given and the username is the historic FRITZ_USERNAME, then check for the last logged-in username and use this username for the soaper. Also recreate the session used by the soaper and the device_manager. This may not guarantee a valid user/password combination, but is the way AVM recommends setting the required username in case a username is not provided. """ try: sys_version = float(self.system_version) except (ValueError, TypeError): # version not available: don't do anything return if (sys_version >= FRITZ_USERNAME_REQUIRED_VERSION and user == FRITZ_USERNAME and password ): last_user = None response = self.call_action( 'LANConfigSecurity1', 'X_AVM-DE_GetUserList' ) root = ElementTree.fromstring(response['NewX_AVM-DE_UserList']) for node in root: if node.tag == 'Username' and node.attrib['last_user'] == '1': last_user = node.text break if last_user is not None: self.session.auth = HTTPDigestAuth(last_user, password) self.soaper.user = last_user self.soaper.session = self.session self.device_manager.session = self.session # ------------------------------------------- # public api: # ------------------------------------------- # TODO: type-hint for arguments could be # `arguments: Optional[dict[str, Union[str, int, bool]]] = None` # for Python >= 3.9 def call_action( self, service_name: str, action_name: str, *, arguments: dict | None = None, **kwargs ) -> dict[str, Any]: """ Executes the given action of the given service. Both parameters are required. Arguments are optional and can be provided as a dictionary given to 'arguments' or as separate keyword parameters. If 'arguments' is given additional keyword-parameters as further arguments are ignored. The argument values can be of type *str*, *int* or *bool*. (Note: *bool* is provided since 1.3. In former versions booleans must be provided as numeric values: 1, 0). If the service_name does not end with a number-character (like "1""), a "1" gets added by default. If the service_name ends with a colon and a number, the colon gets removed. So i.e. "WLANConfiguration" expands to "WLANConfiguration1" and "WLANConfiguration:2" converts to "WLANConfiguration2"". Invalid service names will raise a ServiceError and invalid action names will raise an ActionError. The method returns a dictionary with argument-names as keys and the corresponding information as values. Numeric and boolean values are converted from strings to Python datatypes. """ arguments = arguments if arguments else dict() if not arguments: arguments.update(kwargs) service_name = self.normalize_name(service_name) try: service = self.device_manager.services[service_name] except KeyError: raise FritzServiceError(f'unknown service: "{service_name}"') return self.soaper.execute(service, action_name, arguments) def call_http( self, command: str, identifier: str | None = None, **kwargs ) -> dict[str, str]: """ Excecutes the given command by means of the http-interface. This can be useful for homeautomation-task currently not provided by the TR-064 interface. The `identifier` represents the `ain` of a target-device. `kwargs` can hold additional parameters depending on the device. The method returns a dictionary of strings with three items: the `content-type`, the `encoding` and the corresponding result (the `content`). The content-type is typically "text/plain" or "text/xml", the encoding, typically "utf-8". The method will raise a FritzAuthorizationError in case of missing credentials. In case of an unknown command or identifier a FritzHttpInterfaceError will get raised. Note: information and interactions with actors provided by TR-064 and the http-interface partly overlap. If response time is an issue, TR-064 should be preferred because at time of writing a call to `call_action` (the TR-064 interface) is about 5 to 6 times faster than calling `call_http` (the http-interface). .. versionadded:: 1.12 """ header, content = self.http_interface.execute( command, identifier, **kwargs ) content_type, charset = [item.strip() for item in header.split(";")] # extract the encoding from the charset-information encoding = charset.split("=")[-1].strip() return { "content-type": content_type, "encoding": encoding, "content": content } def reconnect(self) -> None: """ Terminate the connection and reconnects with a new ip. """ self.call_action("WANIPConn1", "ForceTermination") def reboot(self) -> None: """ Reboot the system. """ self.call_action("DeviceConfig1", "Reboot") def get_cpu_temperatures(self) -> list[int]: """ Returns a list of the last measured cpu-temperatures. The most recent entry is the first one in the list. NOTE: this function call is experimental as it is based on a non-public API. """ url = f"{self.http_interface.router_url}/query.lua" payload = {"CPUTEMP": "cpu:status/StatTemperature"} response = self.http_interface.call_url(url, payload) return list(map(int, response.json()["CPUTEMP"].split(","))) # ------------------------------------------- # internal methods to load router-api: # ------------------------------------------- def _load_router_api( self, use_cache=False, cache_directory=None, cache_format=FRITZ_CACHE_FORMAT_JSON, verify_cache=True, ): """ Load the router api. If `use_cache` is `False`, load the api from the router. If `use_cache` is `True``, the api data are loaded from a file, which is in pickle or json format, according to the setting of `cache_format`. The file location can get set by the argument `cache_directory`. If `cache_directory` is not given, the default-directory is used (which is in most cases a subdirectory of the user home directory). After loading from a file the cached data are checked to detect a software-update or a change of the router model. If this check fails, the api gets reloaded from the router and the cache data are updated. The same happens on errors loading the cache-file. """ def reload_api(): # reset in case of remaining artefacts: self.device_manager.descriptions = [] self.device_manager.services = {} # reload and save again: self._load_api_from_router() self._write_api_to_cache(path, cache_format) if use_cache: path = self._get_cache_path(cache_directory, cache_format) try: self._load_api_from_cache(path, cache_format) except FileNotFoundError: # can happen i.e. on first run reload_api() else: if verify_cache and not self._is_valid_cache(): # can happen on model changes or software updates reload_api() else: self._load_api_from_router() def _is_valid_cache(self): """ Checks whether the cache-data seems to be valid. Returns a booean: `True` if valid, `False` otherwise. """ # system_id is something like ('FRITZ!Box 7590', '154.07.29') which # originates from the device description and is part of the cache data. try: cached_id = ( self.device_manager.modelname, self.device_manager.system_info[-1] ) except TypeError: # this can happen if the default ip is used with multiple # devices in the local network, so an arbitrary device gets # addressed. In case the device is unable to provide # system_info this value is set to `None` and a TypeError gets # raised. To avoid this provide an ip as the address-argument. return False # retrive the same information from the updatecheck property. # If the result is the same, the cache-data can considered as valid. try: device_info = self.updatecheck except FritzConnectionException: # something went wrong, cache data can not be verified: # should never happen with a connected device. return False current_id = ( device_info['Name'], device_info['Version'] ) return cached_id == current_id def _get_cache_path(self, cache_directory, cache_format): """ Returns the path to the cache file (including the filename and extension) as a Path instance. """ # ignore optional scheme: address = self.address.split('//')[-1] address = address.replace(".", "_") try: suffix = FRITZ_CACHE_FORMATS[cache_format] except KeyError: message = FRITZ_CACHE_UNKNOWN_FORMAT_MESSAGE.format(cache_format) raise FritzConnectionException(message) filename = f"{address}{FRITZ_CACHE_EXT}.{suffix}" if cache_directory: path = Path(cache_directory) else: path = Path().home() / FRITZ_CACHE_DIR path.mkdir(exist_ok=True) return path / filename def _write_api_to_cache(self, path, cache_format): """ Stores the api data in a cache-file. """ binary = "wb" text = "wt" mode = binary if cache_format == FRITZ_CACHE_FORMAT_PICKLE else text with open(path, mode) as fobj: if mode == binary: pickle.dump(self.device_manager.descriptions, fobj) else: json.dump(self.device_manager.serialize(), fobj) def _load_api_from_cache(self, path, cache_format): """ Read the api data from a cache-file and forwards the data to the device_manager. Currently two formats are supported: `pickle` and `json`. If `cache_format` is not `pickle` it is assumed that the format is `json`. Raise a FileNotFoundError in case of an invalide path. """ binary = "rb" text = "rt" mode = binary if cache_format == FRITZ_CACHE_FORMAT_PICKLE else text with open(path, mode) as fobj: if mode == binary: self.device_manager.descriptions = pickle.load(fobj) else: self.device_manager.deserialize(json.load(fobj)) self.device_manager.scan() def _load_api_from_router(self): """ Read the api data from the router and forwards the data to the device_manager. """ for description in FRITZ_DESCRIPTIONS: source = f"{self.address}:{self.port}/{description}" try: self.device_manager.add_description(source) except FritzResourceError: # resource not available: # this can happen on devices not providing # an igddesc-file. # ignore this # But if the "tr64desc.xml" file is missing the router # may not have TR-064 activated. In this case raise a # useful error-message. if description == FRITZ_TR64_DESC_FILE: raise FritzConnectionException( FRITZ_APPLICATION_ACCESS_DISABLED ) self.device_manager.scan() self.device_manager.load_service_descriptions(self.address, self.port) fritzconnection-1.15.0/fritzconnection/core/fritzhttp.py000066400000000000000000000151411501211554500235730ustar00rootroot00000000000000""" fritzhttp.py Access the AVM Fritz!Box AHA-HTTP-Interface """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer import hashlib from http import HTTPStatus from http.client import HTTP_PORT from xml.etree import ElementTree as etree from fritzconnection.core.exceptions import ( FritzHttpInterfaceError, FritzAuthorizationError, ) URL_LOGIN = "/login_sid.lua?version=2" URL_HOMEAUTOSWITCH = "/webservices/homeautoswitch.lua" PBKDF2_CHALLENGE_INDICATOR = "2$" class FritzHttp: """ Implementation for the AVM AHA-HTTP-Inferface. The current implementation does not handle a blocktime timeout so far. This is because the communication is based on a fritzconnection-session and the proper credentials are already handled there. There may be the side-effect that someone else messes up with the login of the human web-interface while this script is running. In this case the aha-interface login will not return a valid sid until blocktime runs out. """ def __init__(self, fc): self.fc = fc # the active fritzconnection instance self.sid = None @property def remote_port(self): """ Provides the configurable https port for the aha-interface as int. """ if self.fc.address.startswith("https"): data = self.fc.call_action("X_AVM-DE_RemoteAccess1", "GetInfo") return int(data["NewPort"]) # provide same type as HTTP_PORT return HTTP_PORT @property def router_url(self): """Returns the combination of router address and port.""" return f"{self.fc.address}:{self.remote_port}" @property def login_url(self): """The login-url including protocol and configurable port.""" return f"{self.router_url}{URL_LOGIN}" @property def homeauto_url(self): """The homeauto-url including protocol and configurable port.""" return f"{self.router_url}{URL_HOMEAUTOSWITCH}" def execute(self, command=None, identifier=None, **kwargs): """ Send the command and the optional identifier to the http-interface and returns a tuple with the content-type and the response-text as is. On error raises a FritzAuthorizationError if the error code was 403 otherwise raises a generic FritzConnectionException with the corresponding error-code. The `command` is a string like 'getswitchlist' or 'getbasicdevicestats' according to the AVM AHA documentation. The `identifier` is a string, representing a device-ain. """ payload = {"switchcmd": command, "ain": identifier} payload.update(kwargs) response = self.call_url(self.homeauto_url, payload) return response.headers.get('content-type'), response.text def call_url(self, url, payload): """ Makes a call to the router with the provided url. Returns the request object in case of success. Otherwise a FritzHttpInterfaceError will get raised. Beside the public API documented by AVM this method allows calls to undocumented APIs serving the router web-interface or providing other data. WARNING: For a reliable application it is highly discouraged to use undocumented endpoints because they can change any time without notice. So an application may not survive a router OS update. """ for sid in self._get_sid(): payload['sid'] = sid with self.fc.session.get(url, params=payload) as response: if response.status_code == HTTPStatus.OK: return response msg = f"Request failed: http error code '{response.status_code}'" if response.status_code == HTTPStatus.FORBIDDEN: # can happen if FritzConnection was initialized # without a password. raise FritzAuthorizationError(msg) # This can be from the 400 or 500 error-family. # Most often these errors are triggered by a malformed payload, # therefore include the payload in the message: msg = f"{msg}, payload: {payload}" raise FritzHttpInterfaceError(msg) def _get_sid(self): """ Generator to provide the sid two times in case the first try failed. This can happen on an invalide or expired sid. In this case the sid gets regenerated for the second try. """ if self.sid is None: # a session id of None can lead to irritation self._set_sid_from_box() yield self.sid self._set_sid_from_box() yield self.sid def _set_sid_from_box(self): """ Read a session id from the box and store it in self.sid As long as self.sid holds a valid sid, the user is logged in. """ with self.fc.session.get(self.login_url) as response: challenge = etree.fromstring(response.text).find('Challenge').text if challenge.startswith(PBKDF2_CHALLENGE_INDICATOR): challenge_hash = self._get_pbkdf2_hash(challenge) else: challenge_hash = self._get_md5_hash(challenge) self.sid = self._request_sid(challenge_hash) def _get_pbkdf2_hash(self, challenge): """Returns the vendor-recommended pbkdf2 challenge hash.""" _, iterations_1, salt_1, iterations_2, salt_2 = challenge.split('$') static_hash = hashlib.pbkdf2_hmac( "sha256", self.fc.soaper.password.encode(), bytes.fromhex(salt_1), int(iterations_1) ) dynamic_hash = hashlib.pbkdf2_hmac( "sha256", static_hash, bytes.fromhex(salt_2), int(iterations_2) ) return f"{salt_2}${dynamic_hash.hex()}" def _get_md5_hash(self, challenge): """Returns the legathy md5 challenge hash.""" hash = hashlib.md5( f"{challenge}-{self.fc.soaper.password}".encode("utf-16-le") ) return f"{challenge}-{hash.hexdigest()}" def _request_sid(self, challenge_hash): """ Takes the challenge_hash to request and return a new session id. """ # TODO: handle blocktime with self.fc.session.post( self.login_url, data={"username": self.fc.soaper.user, "response": challenge_hash}, headers={"Content-Type": "application/x-www-form-urlencoded"} ) as response: root = etree.fromstring(response.text) sid_node = root.find("SID") return sid_node.text fritzconnection-1.15.0/fritzconnection/core/fritzmonitor.py000066400000000000000000000230151501211554500243020ustar00rootroot00000000000000""" Module to communicate with the AVM Fritz!Box service providing real time phone-call events. To run fritzmonitor, the CallMonitor service of the box has to be activated. This can be done with any registered Phone by typing the following codes: activate: #96*5* deactivate: #96*4* """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer import queue import socket import threading import time FRITZ_IP_ADDRESS = "169.254.1.1" FRITZ_MONITOR_PORT = 1012 FRITZ_MONITOR_QUEUE_SIZE = 256 FRITZ_MONITOR_CHUNK_SIZE = 1024 * 4 FRITZ_MONITOR_SOCKET_TIMEOUT = 10 MIN_RECONNECT_DELAY = 0.02 # minimum delay in seconds MAX_RECONNECT_DELAY = 60 # maximum delay in seconds RECONNECT_DELAY_FACTOR = 10 # factor to increase delays between reconnection tries RECONNECT_TRIES = 10 # number of tries to reconnect before giving up class EventReporter: """ Takes a Queue and implements a buffer for line-separated data. If at least one line is in the buffer, the line gets put into the Queue for further processing elsewhere (by a routine reading the queue). """ def __init__( self, monitor_queue: queue.Queue, block_on_filled_queue: bool = False ): """ Takes the monitor queue (of type queue.Queue) and a boolean 'block_on_filled_queue'. If 'block_on_filled_queue' is True the thread will wait until a free slot is available blocking the thread reading call_monitor events from the socket connected to the Fritz!Box. """ self.buffer = "" self.monitor_queue = monitor_queue self.block_on_filled_queue = block_on_filled_queue def add(self, data: str) -> None: """ Adds the given 'data' to the buffer. If the buffer holds at least one line (separated by newline-character), the line (or lines) are put into the 'monitor_queue' as events to be processed from a reader elsewhere. """ self.buffer += data *parts, self.buffer = self.buffer.split("\n") for part in parts: try: self.monitor_queue.put(part, block=self.block_on_filled_queue) except queue.Full: # ignore pass class FritzMonitor: """ Monitor Fritz!Box events about started, finished, incoming and outgoing calls. """ def __init__( self, address: str = FRITZ_IP_ADDRESS, port: int = FRITZ_MONITOR_PORT, timeout: int = FRITZ_MONITOR_SOCKET_TIMEOUT, encoding: str = "utf-8", ): self.address = address self.port = port self.timeout = timeout self.encoding = encoding self.stop_flag = threading.Event() self.monitor_thread: threading.Thread | None = None self.mock_socket = None # for testing def __enter__(self): return self def __exit__(self, *args): self.stop() @property def has_monitor_thread(self) -> bool: """ Returns True if a monitor-thread has been created. That should be the case after calling start() and before calling stop(). """ return bool(self.monitor_thread) @property def is_alive(self) -> bool: """ Returns True if there is a monitor-thread and the thread is running. Returns False otherwise. """ return self.has_monitor_thread and self.monitor_thread.is_alive() # type: ignore def start( self, queue_size: int = FRITZ_MONITOR_QUEUE_SIZE, block_on_filled_queue: bool = False, reconnect_delay: float = MAX_RECONNECT_DELAY, reconnect_tries: float = RECONNECT_TRIES, sock=None, ) -> queue.Queue: """ Start the monitor thread and return a Queue instance with the given size to report the call_monitor events. Events are of type string. Raises an `OSError` if the socket can not get connected in a given timeout. Raises a `RuntimeError` if start() get called a second time without calling stop() first. `queue_size` is the number of events the queue can store. If `block_on_filled_queue` is False the event will get discarded in case of no free block (default). On True the EventReporter will block until a slot is available. `reconnect_delay` defines the maximum time interval in seconds between reconnection tries, in case that a socket-connection gets lost. `reconnect_tries` defines the number of consecutive to reconnect a socket before giving up. `sock` is used for testing to inject a mock-socket. """ if self.monitor_thread: # It's an error to create a second thread for monitoring raise RuntimeError("A FritzMonitor thread is already running") self.mock_socket = sock # get socket or raise OSError in main thread: sock = self._get_connected_socket() monitor_queue = queue.Queue(maxsize=queue_size) # type: ignore kwargs = { "monitor_queue": monitor_queue, "sock": sock, "block_on_filled_queue": block_on_filled_queue, "reconnect_delay": reconnect_delay, "reconnect_tries": reconnect_tries, } # clear event object in case the instance gets 'reused': self.stop_flag.clear() self.monitor_thread = threading.Thread(target=self._monitor, kwargs=kwargs) self.monitor_thread.start() return monitor_queue def stop(self) -> None: """ Stop the current running monitor_thread. """ if self.monitor_thread: if self.monitor_thread.is_alive(): self.stop_flag.set() # tell thread to terminate self.monitor_thread.join() # wait for termination without timeout self.monitor_thread = None def _get_connected_socket(self): """ Return a new created socket. In case of failure an OSError is raised. """ # use a mock socket for tests if self.mock_socket: sock = self.mock_socket else: sock = socket.socket() # these options should work on all platforms: sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # socket actions can fail for different reasons, # without a timeout they can hang a long time. sock.settimeout(self.timeout) try: sock.connect((self.address, self.port)) except socket.timeout: # will fail if the address:port is not available (not present or in use) # socket.timeout is subclass of OSError, so it is save to raise an OSError msg = f"Unable to connect to '{self.address}:{self.port}'" raise OSError(msg) return sock def _reconnect_socket( self, max_reconnect_delay=MAX_RECONNECT_DELAY, reconnect_tries=RECONNECT_TRIES, ): """ Try to reconnect a lost connection. Returns a new socket on success and None otherwise. """ reconnect_delay = self._delayer(max_delay=max_reconnect_delay) while reconnect_tries > 0: next(reconnect_delay) try: return self._get_connected_socket() except OSError: reconnect_tries -= 1 return None def _monitor( self, monitor_queue, sock, block_on_filled_queue, reconnect_delay, reconnect_tries, ): """ The internal monitor routine running in a separate thread. """ # Instantiate an EventReporter to push event to the event_queue. event_reporter = EventReporter( monitor_queue=monitor_queue, block_on_filled_queue=block_on_filled_queue ) while not self.stop_flag.is_set(): try: raw_data = sock.recv(FRITZ_MONITOR_CHUNK_SIZE) except socket.timeout: # without a timeout an open socket will never return from a # connection closed by a router (may be of limited resources). # Therefore be sure to set a timeout at socket creation (elsewhere). # So just try again after timeout. continue if not raw_data: # empty response indicates a lost connection. # try to reconnect. sock = self._reconnect_socket( max_reconnect_delay=reconnect_delay, reconnect_tries=reconnect_tries, ) if sock is None: # reconnect has failed: terminate the thread break else: # sock.recv returns a bytearray to decode: response = raw_data.decode(self.encoding) event_reporter.add(response) # clean up on terminating thread: try: sock.close() except (AttributeError, OSError): pass # reset monitor_thread to be able to restart self.monitor_thread = None @staticmethod def _delayer( min_delay=MIN_RECONNECT_DELAY, max_delay=MAX_RECONNECT_DELAY, multiplier=RECONNECT_DELAY_FACTOR, ): """ delay generator with increasing sleep-times. """ delay = min(min_delay, max_delay) while True: time.sleep(delay) yield delay = min(delay * multiplier, max_delay) fritzconnection-1.15.0/fritzconnection/core/logger.py000066400000000000000000000055321501211554500230170ustar00rootroot00000000000000""" Logging module for the fritzconnection library. By default fritzconnection will emit all messages with a log-level of INFO and higher (WARNING, ERROR, CRITICAL). The fritzconnection logger, defined as `fritzlogger`, is an instance of the `logging.Logger` class from the `stdlib` and can get accessed by: >>> from fritzconnection.core.logger import fritzlogger This module provides the additional functions `activate_local_debug_mode` and `reset` (see below) to activate a debug mode, suppressing handler-propagation, and to reset the logger to the initial state. To activate debug logging for fritzconnection call: >>> from fritzconnection.core.logger import activate_local_debug_mode >>> activate_local_debug_mode(handler=logging.StreamHandler()) In this debug mode fritzconnection will additionally log the data transfered between the library and the router and suppress logging-propagation to the parent-handlers. Here the `StreamHandler` will send all data to `stderr`. Because this can be a lot of data a `FileHandler` may be a better choice: >>> activate_local_debug_mode(handler=logging.FileHandler()) To deactivate this mode call `reset()`: >>> from fritzconnection.core.logger import reset >>> reset() Beside this you can do everything with `fritzlogger` as with the `logging.Logger`, because `fritzlogger` is an instance of the latter. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) import logging fritzlogger = logging.getLogger("fritzconnection") fritzlogger.setLevel(logging.INFO) fritzformatter = logging.Formatter(logging.BASIC_FORMAT) def activate_local_debug_mode(handler=None, propagate=False): """ Activates all logging messages on debug level and don't propagate to parent-handlers. If no handler is given the NullHandler will get set, avoiding a call of the lastResort-handler. If the given handler has no formatter, the fritzformatter gets set (which provides the `logging.BASIC_FORMAT`). If propagate is True, all debug information will also get sent to the parent-handlers. Keep in mind, that this can be a lot of data if the parent-handlers are enabled for debug-level records. """ if handler is None: handler = logging.NullHandler() if not handler.formatter: handler.setFormatter(fritzformatter) fritzlogger.addHandler(handler) fritzlogger.propagate = propagate fritzlogger.setLevel(logging.DEBUG) def reset(keep_handlers=False, propagate=True): """ Resets the logger to the initial state, i.e. after calling `activate_local_debug_mode`. All handlers will be removed, except `keep_handlers` is set to True. """ if not keep_handlers: fritzlogger.handlers = [] fritzlogger.propagate = propagate fritzlogger.setLevel(logging.INFO) fritzconnection-1.15.0/fritzconnection/core/processor.py000066400000000000000000000540701501211554500235600ustar00rootroot00000000000000""" Module to parse and store the device description and the service data provided by xml and the scpd protocol based on xml. Names partly violate PEP8 representing node-names from xml description files. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from .utils import ( get_xml_root, localname, ) # --------------------------------------------------------- # processor, decorator and descriptors here: # --------------------------------------------------------- def process_node(obj, root): """ Take an object and a root of nodes. The node.text of nodes with the same name as an instance-attribute of 'obj' are set as values for the corresponding instance-attribute. If the attribute is a callable, processing the node gets delegated to the callable (which in turn calls process_node). """ for node in root: node_name = localname(node) try: attr = getattr(obj, node_name) except AttributeError: # ignore unknown nodes continue if callable(attr): # attribute is a callable: delegate further attr(node) else: # node is an attribute: set value if isinstance(node.text, str): value = node.text.strip() else: value = node.text setattr(obj, node_name, value) def processor(cls): """ Class decorator to add the functionality of calling 'process_node' on invoking an instance as a callable. """ cls.__call__ = lambda obj, root: process_node(obj, root) return cls class ValueSequencer: """ Data descriptor storing a value (assigned as attribute value) in a given sequence. """ def __init__(self, sequence_name): self.sequence_name = sequence_name def __get__(self, obj, objtype): # kind of set only attribute return NotImplemented def __set__(self, obj, value): sequence = getattr(obj, self.sequence_name) sequence.append(value) class InstanceAttributeFactory: """ Non data descriptor returning instances of 'cls' and registering these instances in the '_storage' attribute of the calling instance. """ def __init__(self, cls): self.cls = cls def __get__(self, obj, objtype): instance = self.cls() obj._storage.append(instance) return instance class Storage: """ Baseclass for classes working with InstanceAttributeFactory. """ def __init__(self, storage): self._storage = storage # --------------------------------------------------------- # Processors for reading the device specific FritzOS api: # Node- and root-classes. Root classes are entry-points. # Root classes are Scpd and Description. # Description is the only public class. # --------------------------------------------------------- class Serializer: """ Simple abstract Serializer base class. This class and should not get instanciated. """ def __eq__(self, other): if set(self.__dict__.keys()) ^ set(other.__dict__.keys()): # self and other have not the same set of instance attributes: return False # both instances must have all the same attribute values: return self._compare_attributes(other, self.__dict__.keys()) def _compare_attributes(self, other, attributes): # check for the same values in the attributes of self and other: for attribute in attributes: if getattr(self, attribute) != getattr(other, attribute): return False return True def serialize(self, exclude=None): if exclude is None: exclude = [] attribute_names = set(self.__dict__.keys()) - set(exclude) return self.get_sorted_dict( {name: getattr(self, name) for name in attribute_names} ) def deserialize(self, data): self.__dict__.update(data) @staticmethod def get_sorted_dict(dictionary): """ Takes a dictionary and returns another one with all keys in alphabetical order. """ sorted_keys = sorted(dictionary.keys()) return {key: dictionary[key] for key in sorted_keys} @classmethod def from_data(cls, data): """ Return a new instance with attributes initialized from data. """ try: instance = cls() except TypeError: # will happen on classes expecting a list of nodes: instance = cls(root=[]) instance.deserialize(data) return instance @processor class SpecVersion(Serializer): """ Specification version from the schema device or service information. """ def __init__(self): # attributes are case sensitive node names: self.major = None self.minor = None @property def version(self): return f'{self.major}.{self.minor}' @processor class SystemVersion(Serializer): """ Information about the Fritz!OS version of the Fritz!Box. Information is just provided by the 'tr64desc.xml' file. """ def __init__(self): # attributes are case sensitive node names self.HW = None self.Major = None self.Minor = None self.Patch = None self.Buildnumber = None self.Display = None @property def version(self): """ Returns system version as string like '7.10' or None if system version is unknown. """ if self.Minor and self.Patch: return f'{self.Minor}.{self.Patch}' return None @property def info(self): """ Returns a tuple with all instance attributes 'HW, Major, Minor, Patch, Buildnumber, Display' in this order. """ return ( self.HW, self.Major, self.Minor, self.Patch, self.Buildnumber, self.Display, ) @processor class Argument(Serializer): """ An argument with name, direction and relatedStateVariable attributes. """ def __init__(self): # attributes are case sensitive node names self.name = None self.direction = None self.relatedStateVariable = None @processor class ArgumentList(Storage): """ Collects the arguments for an action. """ # case sensitive node argument = InstanceAttributeFactory(Argument) @processor class Action(Serializer): """ Every Action has a name and a list of arguments. """ def __init__(self): self._arguments = list() self._arguments_storage = None # attributes are case sensitive node names: self.name = None self.argumentList = ArgumentList(self._arguments) def __eq__(self, other): # for testing: Action is equal to another if the name is the same # and the arguments in self._arguments are the same and in the # same order (because of the implementation). if self.name == other.name: for arg1, arg2 in zip(self._arguments, other._arguments): if arg1 != arg2: return False return True return False @property def arguments(self): """ Returns the action-arguments as a dict. argument-names are the keys and the argument objects are the values. The dictionary gets cached. """ if not self._arguments_storage: self._arguments_storage = {arg.name: arg for arg in self._arguments} return self._arguments_storage def serialize(self): """ Return a dictionary with json serializable data: the name of the instance and a list of the serialized argument-instances in self._arguments. """ exclude = ["_arguments", "_arguments_storage", "argumentList"] data = super().serialize(exclude=exclude) data['arguments'] = [arg.serialize() for arg in self._arguments] return data def deserialize(self, data): """ Deserialize the data back to an Action instance with a given name and defined Argument-instances. """ self.name = data['name'] self._arguments = [Argument.from_data(d) for d in data['arguments']] @processor class ActionList(Storage): """ Collection of actions of a service. The Action instances are stored in the Scpd.actions attribute. """ # case sensitive node action = InstanceAttributeFactory(Action) @processor class ValueRange(Serializer): def __init__(self): # attributes are case sensitive node names: self.minimum = None self.maximum = None self.step = None @processor class StateVariable(Serializer): """ Represents a stateVariable with the attributes name, dataType, defaultValue, allowedValueList and allowedValueRange. """ # case sensitive node allowedValue = ValueSequencer('allowed_values') def __init__(self): # attributes are case sensitive node names: self.name = None self.dataType = None self.defaultValue = None self.allowed_values = list() # list of values as strings self.allowedValueList = self self.allowedValueRange = ValueRange() def __eq__(self, other): # two instances are equal on having the same attribute values. attributes = ["name", "dataType", "defaultValue", "allowed_values"] if not self._compare_attributes(other, attributes): return False return self.allowedValueRange == other.allowedValueRange def serialize(self): """ Returns a dictionary with json serializable attribute data. """ exclude = ["allowedValueList", "allowedValueRange"] data = {"attributes": super().serialize(exclude=exclude)} data["allowedValueRange"] = self.allowedValueRange.serialize() return data def deserialize(self, data): """ Deserialize the data back to a former state of a StateVariable instance. """ super().deserialize(data['attributes']) self.allowedValueRange.deserialize(data['allowedValueRange']) @processor class ServiceStateTable(Storage): """ Collection of stateVariables. """ # case sensitive node stateVariable = InstanceAttributeFactory(StateVariable) class Scpd(Serializer): """ Provides information about the Service Control Point Definitions for every Service. Every Service has one instance of this class for accessing the description of its own actions and the according parameters. Root class for processing the content of an scpd-file. """ def __init__(self, root): """ Starts interpreting the scpd-data. 'root' must be a xml.Element objects as returned from 'utils.get_xml_root'. """ self._actions = list() self._state_variables = list() # attributes are case sensitive node names: self.specVersion = SpecVersion() self.actionList = ActionList(self._actions) self.serviceStateTable = ServiceStateTable(self._state_variables) # start node processing: process_node(self, root) def __eq__(self, other): attributes = ["_actions", "_state_variables", "specVersion"] return self._compare_attributes(other, attributes) @property def spec_version(self): return self.specVersion.version @property def actions(self): """ Returns a dictionary with the actions from the actions-list. The action-names are the keys and the actions themselves are the values. """ return {action.name: action for action in self._actions} @property def state_variables(self): """ Returns a dictionary with the state_variable name as keys and the StateVariable itself as value. """ return {sv.name: sv for sv in self._state_variables} def serialize(self): data = {"actions": [action.serialize() for action in self._actions]} data['state_variables'] = [sv.serialize() for sv in self._state_variables] data['specVersion'] = self.specVersion.serialize() return self.get_sorted_dict(data) def deserialize(self, data): self._actions = [Action.from_data(d) for d in data['actions']] self._state_variables = [StateVariable.from_data(d) for d in data['state_variables']] self.specVersion.deserialize(data['specVersion']) @processor class Service(Serializer): """ Class describing a service. """ def __init__(self): self._scpd = None self._actions = None self._state_variables = None # attributes are case sensitive node names: self.serviceType = None self.serviceId = None self.controlURL = None self.eventSubURL = None self.SCPDURL = None @property def name(self): if self.serviceId: return self.serviceId.split(':')[-1] return None @property def actions(self): """ Returns all known actions of this service as a dictionary. Action names are keys, the action objects are the values. Caches the dictionary once retrieved from _scpd. """ if self._actions is None: self._actions = self._scpd.actions return self._actions @property def state_variables(self): """ Returns all known stateVariables of this service as a dictionary. Names are keys, the stateVariables objects are the values. Caches the dictionary once retrieved from _scpd. """ if self._state_variables is None: self._state_variables = self._scpd.state_variables return self._state_variables def load_scpd(self, address, port, timeout=None, session=None): """Loads the scpd data""" url = f'{address}:{port}{self.SCPDURL}' root = get_xml_root(url, timeout=timeout, session=session) self._scpd = Scpd(root) def serialize(self): """ Serialize the service instance attributes. Returns a dictionary with data that can be converted to json. """ exclude = ['_scpd', '_actions', '_state_variables'] return { "attributes": super().serialize(exclude=exclude), "scpd": self._scpd.serialize() } def deserialize(self, data): """ Inverse method for `serialize`. Takes the data (a dictionary) and populates the instance attributes extracted by `serialize`. """ super().deserialize(data['attributes']) self._scpd = Scpd.from_data(data['scpd']) @processor class ServiceList(Storage): """ Collection of Service instances for a device. The service instances are stored in the device.services attribute. """ # case sensitive node service = InstanceAttributeFactory(Service) @processor class Device(Serializer): """ Storage for devices attributes and device sub-nodes. Sub-nodes are the serviceList and the deviceList. The services provided by a device are collected in services. Sub-devices are collected in devices. All instance attributes are public for read only use. """ def __init__(self): self._services = list() self.devices = list() # attributes are case sensitive node names: self.deviceType = None self.friendlyName = None self.manufacturer = None self.manufacturerURL = None self.modelDescription = None self.modelName = None self.modelNumber = None self.modelURL = None self.UDN = None self.UPC = None self.presentationURL = None self.serviceList = ServiceList(self._services) self.deviceList = DeviceList(self.devices) def __eq__(self, other): attributes = [ "deviceType", "friendlyName", "manufacturer", "manufacturerURL", "modelDescription", "modelName", "modelNumber", "modelURL", "UDN", "UPC", "presentationURL", ] return self._compare_attributes(other, attributes) @property def services(self): services = {service.name: service for service in self._services} for device in self.devices: services.update(device.services) return services def serialize(self): """ Returns a dictionary with a subset of the instance attributes and a list of serialized services that can be transformed to json-format. """ exclude = ["_services", "devices", "serviceList", "deviceList",] data = {'attributes': super().serialize(exclude=exclude)} data['services'] = [service.serialize() for service in self._services] data['devices'] = [device.serialize() for device in self.devices] return self.get_sorted_dict(data) def deserialize(self, data): """ Loads the data into the instance attributes. This is the reverse-function for serialize. No return value. """ super().deserialize(data['attributes']) self._services.extend([Service.from_data(d) for d in data['services']]) self.devices.extend([Device.from_data(d) for d in data['devices']]) @processor class DeviceList(Storage): """ Collection of sub-devices of a device. The Device instances are stored in the device.devices attribute of the parent device. """ # case sensitive node device = InstanceAttributeFactory(Device) class Description(Serializer): """ Root class for a given description information as the content from the files igddesc.xml or tr64desc.xml. """ def __init__(self, root): """ Starts data-processing. 'root' must be a xml.Element object as returned from 'utils.get_xml_root'. """ # attributes are case sensitive node names: self.device = Device() self.specVersion = SpecVersion() self.systemVersion = SystemVersion() # start node processing: process_node(self, root) @property def device_model_name(self): return self.device.modelName @property def spec_version(self): return self.specVersion.version @property def system_version(self): """ Returns the system version of the Fritz!Box as a string like '7.10' or None. This information is only available by the 'tr64desc.xml' file. """ return self.systemVersion.version @property def system_info(self): """ Returns the systemVersion attributes as a tuple: (HW, Major, Minor, Patch, Buildnumber, Display). This information is only available by the 'tr64desc.xml' file. """ return self.systemVersion.info @property def system_buildnumber(self): """ Returns the buildnumber or None. This information is only available by the 'tr64desc.xml' file. """ return self.systemVersion.Buildnumber @property def system_display(self): """ Returns the system display-string or None. This information is only available by the 'tr64desc.xml' file. """ return self.systemVersion.Display @property def services(self): """ Returns dictionary with the known services as values and the according service-names as keys. """ return self.device.services def serialize(self): """ Return serialized instance attributes as dictionary. """ return { 'device': self.device.serialize(), 'specVersion': self.specVersion.serialize(), 'systemVersion': self.systemVersion.serialize(), } def deserialize(self, data): """ Sets the instance attributes according to data. """ self.device.deserialize(data['device']) self.specVersion.deserialize(data['specVersion']) self.systemVersion.deserialize(data['systemVersion']) # --------------------------------------------------------- # Processors to interpret the information returned from # the "X_AVM-DE_GetHostListPath" action. # --------------------------------------------------------- @processor class Host: """ Host class providing every requested attribute """ _int_values = {'Index', 'X_AVM-DE_Port', 'X_AVM-DE_Speed'} _bool_values = { 'Active', 'X_AVM-DE_UpdateAvailable', 'X_AVM-DE_Guest', 'X_AVM-DE_VPN', 'X_AVM-DE_Disallow', } def __getattr__(self, attr_name): # do the magic of not raising an AttributeError: setattr(self, attr_name, None) return getattr(self, attr_name) @property def attributes(self): """ Provide all attributes of the instance as a dictionary with the attribute names as keys and the values converted to python datatypes. """ attrs = {} for name, value in self.__dict__.items(): if name in self._int_values: attrs[name] = int(value) elif name in self._bool_values: attrs[name] = bool(int(value)) else: attrs[name] = value return attrs @processor class HostStorage(Storage): """ Storage class collection all Item-nodes describing the hosts. The Item-nodes are converted to _Host instances. """ Item = InstanceAttributeFactory(Host) # 'Item' must match node-name def __init__(self, root): self._hosts = list() super().__init__(self._hosts) self(root) # start process_node() @property def hosts_attributes(self): """ Provide a list of dictionaries with the attributes of all hosts. The list is sorted with the lowest Index number first. """ # list is already sorted from FritzOS, # but don't trust this for any time in the future. return sorted( [host.attributes for host in self._hosts], key = lambda attrs: attrs["Index"] ) fritzconnection-1.15.0/fritzconnection/core/soaper.py000066400000000000000000000260751501211554500230360ustar00rootroot00000000000000""" Module handling the SOAP based communication with the router. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer import datetime from logging import DEBUG import html import re import requests from requests.auth import HTTPDigestAuth from xml.etree import ElementTree as etree from .exceptions import ( FritzAuthorizationError, FritzConnectionException, FRITZ_ERRORS, ) from .logger import fritzlogger from .utils import localname SOAP_NS = "http://schemas.xmlsoap.org/soap/envelope/" STATUS_UNAUTHORIZED = 401 def datetime_convert(value): """ Converts a string in ISO 8601 format to a datetime-object. Raise ValueError if value does not match ISO 8601. """ return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S") def boolean_convert(value): """ Converts a string like '1' or '0' to a boolean value. Raise ValueError if it is something else than '1' or '0', because this violates the data_type according to the AVM documentation. """ if value == "1" or value == "0": return bool(int(value)) msg = f"value '{value}' does not match '1' or '0'." raise ValueError(msg) def uuid_convert(value): """Strips the leading 'uuid:' part from the string.""" return value.split(":")[-1] CONVERSION_TABLE = { "datetime": datetime_convert, "boolean": boolean_convert, "uuid": uuid_convert, "i4": int, "ui1": int, "ui2": int, "ui4": int, } def get_converted_value(data_type, value): """ Try to convert the value from string to the given data_type. The data_type is used as key in the CONVERSION_TABLE dictionary. In case the data_type is unknown, the original value is returned. """ try: return CONVERSION_TABLE[data_type](value) except KeyError: return value def encode_boolean(value): """ Returns 1 or 0 if the value is True or False. None gets interpreted as False. Otherwise, the original value is returned. """ if value is True: return 1 if value is False or value is None: return 0 return value def get_html_safe_value(value): """ Returns a xml `encoded value` if it's an encodable value. `value` can be of any type. If it is a boolean or None it gets converted to the integer 1 or 0. If it is a string the characters in the set `&<>'"` are converted to html-safe sequences. Any other datatype gets returned as is. """ value = encode_boolean(value) if isinstance(value, str): value = html.escape(value) return value def preprocess_arguments(arguments): """ Takes a dictionary with arguments for a soap call and converts all values which are True, False or None to the according integers: 1, 0, 0. Returns a new dictionary with the processed values. """ return {k: get_html_safe_value(v) for k, v in arguments.items()} def get_argument_value(root, argument_name): """ Takes an etree-root object, which is a parsed soap-response from the Fritz!Box, and an argument_name, which corresponds to a node-name in the element-tree hierarchy. Returns the text-attribute of the node as a string. Raise an AttributeError in case that a node is not found. """ # root.find will() raise the AttributeError on unknown nodes value = root.find(f".//{argument_name}").text if value is None: # this will be the case on empty tags: value = "" return value def is_html_response(text): """ Returns a boolean whether the raw response text starts with an html-tag. """ return text.casefold().startswith("", " ", text) return re.sub(r" +", " ", tag_free).strip() # make it nice def raise_fritzconnection_error(response): """ Handles all responses with status codes other than 200. Will raise a FritzConnectionException with the error code and description if available. Can also raise a FritzAuthorizationError in case of 401 html-response status code. """ parts = [] error_code = None if is_html_response(response.text): # if it is an html response, the error is described in the # body part: remove all tags and provide the result as # error-message: detail = remove_html_tags(response.text) msg = f"Unable to perform operation. {detail}" if response.status_code == STATUS_UNAUTHORIZED: raise FritzAuthorizationError(msg) raise FritzConnectionException(msg) # otherwise the content is xml and the error-description # is part of the structured xml info: try: root = etree.fromstring(response.content) except etree.ParseError as err: # should not happen (at least not observed so far) raise FritzConnectionException(str(err)) # extract error information from the provided xml data detail = root.find(".//detail") children = detail.iter() next(children) # skip detail itself for node in children: tag = localname(node) text = node.text.strip() if tag == "errorCode": error_code = text parts.append(f"{tag}: {text}") message = "\n".join(parts) # try except:KeyError not possible, # because one of the raised Exceptions may inherit from KeyError. exception = FRITZ_ERRORS.get(error_code, FritzConnectionException) raise exception(message) def redact_response(redact: bool, input: str): # avoid expansive regex matching, when not neccessary if fritzlogger.level != DEBUG or not redact: return input # redact possible phone numbers # numbers with len of 5 or more, sourounded by white spaces or bracket redacted = re.sub(r"([\s\[\(])\d{5,}([\s\]\)])", r"\1******\2", input) # redact external ip addresses ext_ip_keys = 'New(ExternalIPAddress|ExternalIPv6Address)' redacted = re.sub(r"(<{0}>)(.*)()".format(ext_ip_keys), r"\1******\4", redacted) # redact wifi passwords wifi_pwd_keys = 'New(WEPKey\d+|PreSharedKey|KeyPassphrase)' redacted = re.sub(r"(<{0}>)(.*)()".format(wifi_pwd_keys), r"\1******\4", redacted) return redacted class Soaper: """ Class making the soap on its own to communicate with the FritzBox. Instead of ham, spam and eggs, it's hopelessly addicted to soap. For accessing the Fritz!Box the parameters `address` for the router ip, `port`, `user`, `password` and `session` are required. (These parameters will get set by FritzConnection.) """ headers = {"soapaction": "", "content-type": "text/xml", "charset": "utf-8"} envelope = re.sub( r"\s +", "", """ {body} """, ).replace('/"xmlns:', '/" xmlns:') body_template = re.sub( r"\s +", "", """ {arguments} """, ) argument_template = "<{name}>{value}" method = "post" conversion_table = { "datetime": datetime_convert, "boolean": boolean_convert, "uuid": uuid_convert, "i4": int, "ui1": int, "ui2": int, "ui4": int, } def __init__(self, address, port, user, password, timeout=None, session=None, redact_debug_log=False): self.address = address self.port = port self.user = user self.password = password self.timeout = timeout self.session = session self.redact_debug_log = redact_debug_log def get_body(self, service, action_name, arguments): """Returns the body by template substitution.""" return self.body_template.format( service_type=service.serviceType, action_name=action_name, arguments=arguments, ) def execute(self, service, action_name, arguments): """ Builds the soap request and returns the response as dictionary. Numeric and boolean values are converted from strings to Python datatypes. """ def handle_response(response): fritzlogger.debug(f"response status: {response.status_code}") fritzlogger.debug(redact_response(self.redact_debug_log, response.text)) if response.status_code != 200: raise_fritzconnection_error(response) return self.parse_response(response, service, action_name) headers = self.headers.copy() headers["soapaction"] = f"{service.serviceType}#{action_name}" arguments = preprocess_arguments(arguments) arguments = "".join( self.argument_template.format(name=k, value=v) for k, v in arguments.items() ) body = self.get_body(service, action_name, arguments) envelope = self.envelope.format(body=body).encode("utf-8") url = f"{self.address}:{self.port}{service.controlURL}" fritzlogger.debug(f"\n{url}") fritzlogger.debug(envelope) if self.session: with self.session.post( url, data=envelope, headers=headers, timeout=self.timeout ) as response: return handle_response(response) else: if self.password: auth = HTTPDigestAuth(self.user, self.password) else: auth = None response = requests.post( url, data=envelope, headers=headers, auth=auth, timeout=self.timeout, verify=False, ) return handle_response(response) def parse_response(self, response, service, action_name): """ Extracts all known parameters of the given action from the response and returns this as a dictionary with the out-parameter names as keys and the corresponding response as values. Will raise an ActionError on unknown action_name. """ result = dict() action = service.actions[action_name] root = etree.fromstring(response.content) for argument_name in action.arguments: try: value = get_argument_value(root, argument_name) except AttributeError: continue state_variable_name = action.arguments[argument_name].relatedStateVariable state_variable = service.state_variables[state_variable_name] data_type = state_variable.dataType.lower() try: value = get_converted_value(data_type, value) except ValueError: # ignore malformed value and return 'as is'. pass result[argument_name] = value return result fritzconnection-1.15.0/fritzconnection/core/utils.py000066400000000000000000000101671501211554500227000ustar00rootroot00000000000000""" Common functions for other core-modules. """ import os import re from xml.etree import ElementTree as etree import requests from .exceptions import FritzConnectionException, FritzResourceError from .logger import fritzlogger NS_REGEX = re.compile("({(?P.*)})?(?P.*)") VALUES_TRUE = {"true", "on", "1"} VALUES_FALSE = {"false", "off", "0"} def localname(node): if callable(node.tag): return "comment" m = NS_REGEX.match(node.tag) return m.group('localname') def get_content_from(url, timeout=None, session=None): """ Returns text from a get-request for the given url. In case of a secure request (using TLS) the parameter verify is set to False, in order to disable certificate verifications. As the Fritz!Box creates a self-signed certificate for use in the LAN, encryption will work but verification will fail. """ def handle_response(response): fritzlogger.debug(response.text) ct = response.headers.get("Content-type") if ct == "text/html": message = f"Unable to retrieve resource '{url}' from the device." # this error will get catched, because it may happen depending # on the used router model, without doing any harm. # However it's logged on INFO level: fritzlogger.info(message) raise FritzResourceError(message) return response.text def do_request(): fritzlogger.debug(f"requesting: {url}") if session: with session.get(url, timeout=timeout) as response: return handle_response(response) response = requests.get(url, timeout=timeout, verify=False) return handle_response(response) try: return do_request() except requests.exceptions.ConnectionError as err: message = f"Unable to get a connection: {err}" # that's an error worth logging: fritzlogger.error(message) # raise from None because the message holds the # proper information about the connection failure: raise FritzConnectionException(message) from None def get_xml_root(source, timeout=None, session=None): """ Function to help migrate from lxml to the standard-library xml-package. 'source' must be a string and can be a xml-string, a uri or a file name. `timeout` is an optional parameter limiting the time waiting for a router response. In all cases this function returns a xml.etree.Element instance which is the root of the parsed tree. """ if source.startswith("http://") or source.startswith("https://"): # it's an uri, use requests to get the content source = get_content_from(source, timeout=timeout, session=session) elif not source.startswith("<"): # assume it's a filename with open(source) as fobj: source = fobj.read() return etree.fromstring(source) def boolean_from_string(value): """ Takes a value as a string and converts it to a boolean or None. The string could be "true" or "false" in upper-, lower- and mixed-case. Also "on", "off" and "0", "1" are converted. If the value can not converted a ValueError gets raised. If the value does not support the .lower() method, an AttributeError gets raised. """ lower_value = value.lower() if lower_value in VALUES_TRUE: return True if lower_value in VALUES_FALSE: return False raise ValueError(f"can't convert '{lower_value}' to a boolean.") def get_boolean_from_string(value, default=None): """ Same as `boolean_from_string` but returns the `default` argument instead of raising an exception. """ try: return boolean_from_string(value) except (AttributeError, ValueError): return default def get_bool_env(key, default=None): """ Return the value of the environment variable key converted to a boolean if it exists, or default if it doesn’t or can't get converted to a boolean. keys convertable to a boolean are "true", "on", "1" and "false", "off", "0". """ value = os.getenv(key) return get_boolean_from_string(value, default) fritzconnection-1.15.0/fritzconnection/lib/000077500000000000000000000000001501211554500207775ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/lib/__init__.py000066400000000000000000000003231501211554500231060ustar00rootroot00000000000000# fritzconnection library: # # The modules in the lib folder are helper modules to access some services # of the FritzBox. They can also be used as examples on how to write # applications using fritzconnection. fritzconnection-1.15.0/fritzconnection/lib/fritzbase.py000066400000000000000000000027161501211554500233500ustar00rootroot00000000000000""" Abstract base class for all library classes. An internal module providing the `AbstractLibraryBase` class. This is an abstract class that should not get instantiated but should serve as a base class for library classes providing a common initialisation. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from __future__ import annotations from ..core.fritzconnection import FritzConnection class AbstractLibraryBase: """ Abstract base class for library classes. Implements the common initialisation. The first argument `fc` can be a FritzConnection instance. If this argument is given no further arguments are needed. If the argument `fc` is not given, all other arguments are forwarded to get a FritzConnection instance. These arguments have the same meaning as for `FritzConnection.__init__()`. Using positional arguments is strongly discouraged. Use keyword arguments instead. """ def __init__( self, fc: FritzConnection | None = None, *args, **kwargs ): if fc is None: fc = FritzConnection(*args, **kwargs) self.fc = fc @property def modelname(self) -> str: """ The device modelname. Every library module derived from `AbstractLibraryBase` inherits this property. """ return self.fc.modelname fritzconnection-1.15.0/fritzconnection/lib/fritzcall.py000066400000000000000000000171501501211554500233470ustar00rootroot00000000000000""" Module to access lists of recent phone calls: incoming, outgoing and missed ones. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from __future__ import annotations import datetime from ..core.processor import ( processor, process_node, InstanceAttributeFactory, Storage, ) from ..core.utils import get_xml_root from .fritzbase import AbstractLibraryBase __all__ = ['FritzCall', 'Call'] ALL_CALL_TYPES = 0 RECEIVED_CALL_TYPE = 1 MISSED_CALL_TYPE = 2 OUT_CALL_TYPE = 3 ACTIVE_RECEIVED_CALL_TYPE = 9 REJECTED_CALL_TYPE = 10 ACTIVE_OUT_CALL_TYPE = 11 SERVICE = 'X_AVM-DE_OnTel1' def datetime_converter(date_string): if not date_string: return date_string return datetime.datetime.strptime(date_string, '%d.%m.%y %H:%M') def timedelta_converter(duration_string): if not duration_string: return duration_string hours, minutes = [int(part) for part in duration_string.split(':', 1)] return datetime.timedelta(hours=hours, minutes=minutes) class FritzCall(AbstractLibraryBase): """ Can dial phone numbers and gives access to lists of recent phone calls: incoming, outgoing and missed ones. All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.calls = None # Instance of CallCollection to store Call-instances def _update_calls(self, num=None, days=None): result = self.fc.call_action(SERVICE, 'GetCallList') url = result['NewCallListURL'] if days: url += f'&days={days}' elif num: url += f'&max={num}' root = get_xml_root(url, session=self.fc.session) self.calls = CallCollection(root) def get_calls( self, calltype: int = ALL_CALL_TYPES, update: bool = True, num: int | None = None, days: int | None = None ) -> list[Call]: """ Return a list of Call instances of type calltypes. If calltype is 0 all calls are listed. If *update* is True, all calls are reread from the router. *num* maximum number of entries in call list. *days* number of days to look back for calls e.g. 1: calls from today and yesterday, 7: calls from the complete last week. """ if not self.calls: update = True if update: self._update_calls(num, days) if calltype == ALL_CALL_TYPES: return self.calls.calls return [call for call in self.calls if call.type == calltype] def get_received_calls( self, update: bool = True, num: int | None = None, days: int | None = None ) -> list[Call]: """ Return a list of Call instances of received calls. If *update* is True, all calls are reread from the router. *num*: maximum number of entries in call list. *days*: number of days to look back for calls e.g. 1: calls from today and yesterday, 7: calls from the complete last week. """ return self.get_calls(RECEIVED_CALL_TYPE, update, num, days) def get_missed_calls( self, update: bool = True, num: int | None = None, days: int | None = None ) -> list[Call]: """ Return a list of Call instances of missed calls. If *update* is True, all calls are reread from the router. *num* maximum number of entries in call list. *days* number of days to look back for calls e.g. 1: calls from today and yesterday, 7: calls from the complete last week. """ return self.get_calls(MISSED_CALL_TYPE, update, num, days) def get_out_calls( self, update: bool = True, num: int | None = None, days: int | None = None ) -> list[Call]: """ Return a list of Call instances of outgoing calls. If *update* is True, all calls are reread from the router. *num* maximum number of entries in call list. *days* number of days to look back for calls e.g. 1: calls from today and yesterday, 7: calls from the complete last week. """ return self.get_calls(OUT_CALL_TYPE, update, num, days) def dial(self, number: str) -> None: """ Dials the given *number* (number must be a string, as phone numbers are allowed to start with leading zeros). This method has no return value, but will raise an error reported from the Fritz!Box on failure. **Note:** The dial-help of the Fritz!Box must be activated to make this work. """ arg = {'NewX_AVM-DE_PhoneNumber': number} self.fc.call_action('X_VoIP1', 'X_AVM-DE_DialNumber', arguments=arg) def hangup(self) -> None: """ Terminates the dialling process initiated by the dial function. """ self.fc.call_action('X_VoIP1', 'X_AVM-DE_DialHangup') class AttributeConverter: """ Data descriptor returning converted attribute values. """ def __init__(self, attribute_name, converter=str): self.attribute_name = attribute_name self.converter = converter def __set__(self, obj, value): return NotImplemented def __get__(self, obj, objtype): attr = getattr(obj, self.attribute_name) try: attr = self.converter(attr) except (TypeError, ValueError): pass return attr @processor class Call: """ Represents a call with the attributes provided by AVM. Instance attributes are *Id*, *Type*, *Called*, *Caller*, *CallerNumber*, *CalledNumber*, *Name*, *Device*, *Port*, *Date*, *Duration*, *Count* and *Path* which can be set in case of an optional phone message. The spelling represents the original xml-node names. Additionally, the following attributes can be accessed by lowercase names: *id* returning the Id as integer, *type* returning the Type as integer, *date* returning the Date as datetime-instance, *duration* returning the Duration as timedelta-instance. """ id = AttributeConverter('Id', int) type = AttributeConverter('Type', int) date = AttributeConverter('Date', datetime_converter) duration = AttributeConverter('Duration', timedelta_converter) def __init__(self): self.Id = None self.Type = None self.Called = None self.Caller = None self.CallerNumber = None self.CalledNumber = None self.Name = None self.Device = None self.Port = None self.Date = None self.Duration = None self.Count = None self.Path = None def __str__(self): number = self.Called if self.type == 3 else self.Caller duration = self.Duration if self.type != 2 else "-" if not number: number = "-" return f'{self.Type:>6} {number:24}{self.Date:>18}{duration:>12}' class CallCollection(Storage): """ Container for a sequence of Call instances. """ Call = InstanceAttributeFactory(Call) def __init__(self, root): self.timestamp = None self.calls = list() super().__init__(self.calls) process_node(self, root) def __iter__(self): return iter(self.calls) fritzconnection-1.15.0/fritzconnection/lib/fritzhomeauto.py000066400000000000000000000330021501211554500242470ustar00rootroot00000000000000""" Module to access home-automation devices by the TR-064 and the AHA-HTTP-Interface. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from __future__ import annotations import datetime import itertools from warnings import warn from xml.etree import ElementTree as etree from .fritzbase import AbstractLibraryBase # tr-064 homeautomation service SERVICE = 'X_AVM-DE_Homeauto1' # Constants describing the possible capabilities of a device. # Values are bit positions in the AVM-FunctionBitMask: HAN_FUN_UNIT_1 = 0 UNKNOWN_1= 1 LIGHT_BULB = 2 UNKNOWN_2 = 3 ALARM_SENSOR = 4 AVM_BUTTON = 5 RADIATOR_CONTROL = 6 ENERGY_SENSOR = 7 TEMPERATURE_SENSOR = 8 PLUGGABLE = 9 AVM_DECT_REPEATER = 10 MICROPHONE = 11 UNKNOWN_3 = 12 HAN_FUN_UNIT_2 = 13 UNKNOWN_4 = 14 SWITCHABLE = 15 ADJUSTABLE = 16 COLOR_BULB = 17 BLIND = 18 UNKNOWN_5 = 19 HUMIDITY_SENSOR = 20 # offset for removing the prefix "New" from the tr-064 avm-keys KEY_OFFSET = len("New") class FritzHomeAutomation(AbstractLibraryBase): """ Interface for fritzbox homeauto service. All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ def _action(self, actionname, *, arguments=None, **kwargs): if arguments is None: arguments = kwargs return self.fc.call_action(SERVICE, actionname, arguments=arguments) @property def get_info(self) -> dict: """ Return a dictionary with a single key-value pair: 'NewAllowedCharsAIN': string with all allowed chars for state variable AIN """ return self._action('GetInfo') def get_device_information_by_index( self, index: int ) -> dict: """ Return a dictionary with all device arguments according to the AVM documentation (x_homeauto) at the given internal index. Raise a FritzArrayIndexError (subclass of IndexError) on invalid index values. """ return self._action('GetGenericDeviceInfos', NewIndex=index) def get_device_information_by_identifier( self, identifier: str ) -> dict: """ Returns a dictionary with all device arguments according to the AVM documentation (x_homeauto) with the given identifier (AIN). Raise an FritzArgumentError on invalid identifier. """ return self._action('GetSpecificDeviceInfos', NewAIN=identifier) def device_information(self) -> list[dict]: """ .. deprecated:: 1.12.0 Use :func:`get_device_information_list` instead. """ warn('This method is deprecated. Use "get_device_information_list" instead.', DeprecationWarning) return self.get_device_information_list() def get_device_information_list(self) -> list[dict]: """ Returns a list of dictionaries for all known homeauto-devices. """ info = list() for n in itertools.count(): try: device_information = self.get_device_information_by_index(n) except IndexError: break info.append(device_information) return info def get_homeautomation_device( self, identifier: str | None = None, index: int | None = None ) -> HomeAutomationDevice | None: """ Returns a HomeAutomationDevice instance. The device can be identified by the `identifier` (ain) or the `index` in the internal router device list. If both arguments are given, `identifier` takes preference. If neither `identifier` nor `index` are given `None` gets returned. """ if identifier: information = self.get_device_information_by_identifier(identifier) elif index: information = self.get_device_information_by_index(index) else: return None return HomeAutomationDevice(self, information, identifier) def get_homeautomation_devices(self) -> list[HomeAutomationDevice]: """ Returns a list with HomeAutomationDevice instances of all known home-automation devices. The list is ordered in the way the router provided the data. """ return [ HomeAutomationDevice(self, information) for information in self.get_device_information_list() ] def set_switch(self, identifier: str, on: bool = True) -> None: """ Sets a switch state on devices providing a switch state. 'identifier' must be the AIN of the device. 'on' is a boolean whether the switch should be on (True) or off (False). This method has no return value. Raise a FritzArgumentError on invalid identifier. """ arguments = { 'NewAIN': identifier, 'NewSwitchState': 'ON' if on else 'OFF' } self._action('SetSwitch', arguments=arguments) class HomeAutomationDevice: """ Represents a device for homeautomation. `fh` is a FritzHomeAutomation instance. `device_information` is a dictionary like the ones returned from FritzHomeAutomation methods 'get_device_information_by_index()', 'get_device_information_by_identifier()' or an item from the list of dictionaries returned from 'get_device_information_list()'. This dictionary returned from the 'get_device_information_by_identifier()' has no 'NewAIN' entry. In this case the argument `identifier` must be provided with the missing 'ain'. If both `identifier` is provided and `device_information` has a 'NewAIN' entry the latter takes preference. Instances will have the folloing dynamic created attributes: AIN DeviceId FunctionBitMask FirmwareVersion Manufacturer ProductName DeviceName Present MultimeterIsEnabled MultimeterIsValid MultimeterPower MultimeterEnergy TemperatureIsEnabled TemperatureIsValid TemperatureCelsius TemperatureOffset SwitchIsEnabled SwitchIsValid SwitchState SwitchMode SwitchLock HkrIsEnabled HkrIsValid HkrIsTemperature HkrSetVentilStatus HkrSetTemperature HkrReduceVentilStatus HkrReduceTemperature HkrComfortVentilStatus HkrComfortTemperature Depending on the device not all attributes will have a meaning. """ def __init__( self, fh: FritzHomeAutomation, device_information: dict, identifier: str | None = None ): self.fh = fh self.AIN = identifier self._extraxt_device_information_as_attributes(device_information) def __repr__(self): """ Provide some basic information about the device. """ return f"ain: {self.AIN}, {self.Manufacturer} - {self.ProductName}" def _extraxt_device_information_as_attributes(self, device_information): """ Takes the device_information, which is a dictionary returned from a call like 'FritzHomeAutomation.get_device_information_by_index()' and updates the instance-attributes with the key-value pairs of this dictionary. The key-names are changed by stripping the prefix 'New'. All keys updated by this automatic process are in MixedCase style - as provided from the router - while all other attributes are snake_case. """ for key, value in device_information.items(): self.__dict__[key[KEY_OFFSET:]] = value def _bitmatch(self, value: int) -> bool: """ Returns a boolean whether the `value` bit is set in `self.FunctionBitMask`. """ feature_bit = 1 << value return feature_bit & self.FunctionBitMask == feature_bit # type: ignore def call_http(self, command: str, **kwargs) -> dict[str, str]: """ Shortcut to access the http-interface of the router. Used to send a `command` with the given keyword-arguments to _this_ device. Raises a FritzHttpInterfaceError if the device does not support the command or arguments. On missing rights a FritzAuthorizationError is raised. """ return self.fh.fc.call_http(command, self.identifier, **kwargs) @property def identifier(self) -> str: return self.AIN # type: ignore @property def is_han_fun_unit(self) -> bool: return self._bitmatch(HAN_FUN_UNIT_1) or self._bitmatch(HAN_FUN_UNIT_2) @property def is_bulb(self) -> bool: return self._bitmatch(LIGHT_BULB) @property def is_alarm_sensor(self) -> bool: return self._bitmatch(ALARM_SENSOR) @property def is_avm_button(self) -> bool: return self._bitmatch(AVM_BUTTON) @property def is_radiator_control(self) -> bool: return self._bitmatch(RADIATOR_CONTROL) @property def is_energy_sensor(self) -> bool: return self._bitmatch(ENERGY_SENSOR) @property def is_temperature_sensor(self) -> bool: return self._bitmatch(TEMPERATURE_SENSOR) @property def is_pluggable(self) -> bool: return self._bitmatch(PLUGGABLE) @property def is_avm_dect_repeater(self) -> bool: return self._bitmatch(AVM_DECT_REPEATER) @property def is_microphone(self) -> bool: return self._bitmatch(MICROPHONE) @property def is_switchable(self) -> bool: return self._bitmatch(SWITCHABLE) @property def is_adjustable(self) -> bool: return self._bitmatch(ADJUSTABLE) @property def is_color_bulb(self) -> bool: return self._bitmatch(COLOR_BULB) @property def is_blind(self) -> bool: return self._bitmatch(BLIND) @property def is_humidity_sensor(self) -> bool: return self._bitmatch(HUMIDITY_SENSOR) def update_device_information(self) -> None: """ Triggers the router to update the device dependent instance-attributes. """ self._extraxt_device_information_as_attributes( self.fh.get_device_information_by_identifier(self.identifier) ) def get_basic_device_stats(self) -> dict: """ Returns a dictionary of device statistics. The content depends on the actors supported by a device. The keys can be: key: on actor: temperature temperature sensor humidity humidity sensor voltage energy sensor power energy sensor energy energy sensor The corresponding values are also dictionaries having a common structure: key: value: count int: number of data points grid int: time resolution in seconds datatime datetime: timestamp of last data update data list of data points (integers) The application can inspect the keys or use the properties like `is_energy_sensor` to check for actors provided by the device. If the usecase is just about the actors and not the data, the properties are much(!) faster. """ response = self.call_http("getbasicdevicestats") return self.extract_basicdevicestats_response(response) @staticmethod def extract_basicdevicestats_response(response: dict) -> dict: """ Converts the xml `response` and returns a dictionary with a datastructure described in the method `get_basic_device_stats()` """ # implemented separately for testing. # 'stats' and 'datatime' are defined in the AVM xml-protocol # some types are dynamic therefore some 'type: ignore'. elements = {} content = response['content'] root = etree.fromstring(content) for element in root: content = {} stats: etree.Element | None = element.find("stats") if stats is None: continue for key, value in stats.attrib.items(): value = int(value) # type: ignore if key == "datatime": value = datetime.datetime.fromtimestamp(value) # type: ignore content[key] = value # convert the csv-list of returned values from text to int. # on missing data dashes (-) may get returned. # this get catched and missing data are represented as `None`. content["data"] = [] for item in stats.text.split(","): # type: ignore try: value = int(item) # type: ignore except ValueError: value = None # type: ignore content["data"].append(value) elements[element.tag] = content return elements def get_switch_state(self) -> bool: """ Returns a boolean indicating whether a switchable device is set to on (True) or off (False). """ self.update_device_information() return self.SwitchState.lower() == 'on' # type: ignore def set_switch(self, on: bool = True) -> None: """ Set a switchable device to 'on' (True) or 'off' (False). """ self.fh.set_switch(self.identifier, on) fritzconnection-1.15.0/fritzconnection/lib/fritzhosts.py000066400000000000000000000202611501211554500235710ustar00rootroot00000000000000""" Module to access and control the known hosts. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Klaus Bremer from __future__ import annotations import itertools try: from typing import Generator except ImportError: from collections.abc import Generator from ..core.exceptions import ( FritzActionError, FritzArgumentError, FritzLookUpError, ) from ..core.processor import HostStorage from ..core.utils import get_xml_root from .fritzbase import AbstractLibraryBase SERVICE = "Hosts1" class FritzHosts(AbstractLibraryBase): """ Class to access the registered hosts. All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ def _action(self, actionname, *, arguments=None, **kwargs): return self.fc.call_action(SERVICE, actionname, arguments=arguments, **kwargs) @property def host_numbers(self) -> int: """The number of known hosts.""" result = self._action("GetHostNumberOfEntries") return result["NewHostNumberOfEntries"] def get_generic_host_entry(self, index: int) -> dict: """ Returns a dictionary with information about a device internally registered by the position *index*. Index-positions are zero-based. """ return self._action("GetGenericHostEntry", NewIndex=index) def get_generic_host_entries(self) -> Generator[dict, None, None]: """ Generator returning a dictionary for every host as provided by `get_generic_host_entry()`. (See also `get_hosts_info()` that returns a list of dictionaries with different key-names.) """ for index in itertools.count(): try: yield self.get_generic_host_entry(index) except IndexError: break def get_specific_host_entry(self, mac_address: str) -> dict: """ Returns a dictionary with information about a device addressed by the MAC-address. """ return self._action("GetSpecificHostEntry", NewMACAddress=mac_address) def get_specific_host_entry_by_ip(self, ip: str) -> dict: """ Returns a dictionary with information about a device addressed by the ip-address. Provides additional information about connection speed and system-updates for AVM devices. """ return self._action("X_AVM-DE_GetSpecificHostEntryByIP", NewIPAddress=ip) def get_host_status(self, mac_address: str) -> bool | None: """ Provides status information about the device with the given `mac_address`. Returns `True` if the device is active or `False` otherwise. Returns `None` if the device is not known or the `mac_address` is invalid. """ try: result = self.get_specific_host_entry(mac_address) except (FritzArgumentError, FritzLookUpError): return None return result["NewActive"] def get_active_hosts(self) -> list[dict]: """ Returns a list of dicts with information about the active devices. The dict-keys are: 'ip', 'name', 'mac', 'status', 'interface_type', 'address_source', 'lease_time_remaining' """ return [host for host in self.get_hosts_info() if host["status"]] def get_hosts_info(self) -> list[dict]: """ Returns a list of dicts with information about the known hosts. The dict-keys are: 'ip', 'name', 'mac', 'status', 'interface_type', 'address_source', 'lease_time_remaining'. """ result = [] for index in itertools.count(): try: host = self.get_generic_host_entry(index) except IndexError: # no more host entries: break result.append( { "ip": host["NewIPAddress"], "name": host["NewHostName"], "mac": host["NewMACAddress"], "status": host["NewActive"], "interface_type": host["NewInterfaceType"], "address_source": host["NewAddressSource"], "lease_time_remaining": host["NewLeaseTimeRemaining"], } ) return result def get_mesh_topology(self, raw=False) -> dict | str: """ Returns information about the mesh network topology. If `raw` is `False` the topology gets returned as a dictionary with a list of nodes. If `raw` is `True` the data are returned as text in json format. Default is `False`. """ result = self._action("X_AVM-DE_GetMeshListPath") path = result["NewX_AVM-DE_MeshListPath"] url = f"{self.fc.address}:{self.fc.port}{path}" with self.fc.session.get(url) as response: if not response.ok: message = f"Error {response.status_code}: Device has no access to topology information." raise FritzActionError(message) return response.text if raw else response.json() def get_wakeonlan_status(self, mac_address: str) -> bool: """ Returns a boolean whether wake on LAN signal gets send to the device with the given `mac_address` in case of a remote access. """ info = self._action( "X_AVM-DE_GetAutoWakeOnLANByMACAddress", NewMACAddress=mac_address ) return info["NewAutoWOLEnabled"] def set_wakeonlan_status(self, mac_address: str, status: bool = False) -> None: """ Sets whether a wake on LAN signal should get send send to the device with the given `mac_address` in case of a remote access. `status` is a boolean, default value is `False`. This method has no return value. """ args = { "NewMACAddress": mac_address, "NewAutoWOLEnabled": status, } self._action("X_AVM-DE_SetAutoWakeOnLANByMACAddress", arguments=args) def set_host_name(self, mac_address: str, name: str) -> None: """ Sets the hostname of the device with the given `mac_address` to the new `name`. """ args = { "NewMACAddress": mac_address, "NewHostName": name, } self._action("X_AVM-DE_SetHostNameByMACAddress", arguments=args) def get_host_name(self, mac_address: str) -> str: """ Returns a String with the host_name of the device with the given mac_address """ return self.get_specific_host_entry(mac_address)["NewHostName"] def run_host_update(self, mac_address: str) -> None: """ Triggers the host with the given `mac_address` to run a system update. The method returns immediately, but for the device it takes some time to do the OS update. All vendor warnings about running a system update apply, like not turning power off during a system update. So run this command with caution. """ self._action("X_AVM-DE_HostDoUpdate", NewMACAddress=mac_address) def get_hosts_attributes(self) -> list[dict]: """ Returns a list of dictionaries with information about all hosts. This differs from `get_hosts_info` as the information origins from a different FritzOS call: the information about the current host stats is provided by a Lua script returning an xml-stream. `get_hosts_attributes` triggers the Lua script and converts the returned data in a list of dictionaries describing the known hosts. .. versionadded:: 1.10 """ result = self._action("X_AVM-DE_GetHostListPath") path = result["NewX_AVM-DE_HostListPath"] url = f"{self.fc.address}:{self.fc.port}{path}" storage = HostStorage(get_xml_root(source=url, session=self.fc.session)) return storage.hosts_attributes fritzconnection-1.15.0/fritzconnection/lib/fritzphonebook.py000066400000000000000000000146431501211554500244240ustar00rootroot00000000000000""" Module for read-only access to the contents of the Fritz!Box phonebooks. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Authors: Klaus Bremer, David M. Straub from __future__ import annotations from warnings import warn from ..core.processor import ( processor, process_node, InstanceAttributeFactory, Storage, ValueSequencer, ) from ..core.utils import get_xml_root from .fritzbase import AbstractLibraryBase __all__ = ['FritzPhonebook'] SERVICE = 'X_AVM-DE_OnTel1' class FritzPhonebook(AbstractLibraryBase): """ Interface to access the Fritz!Box phonebooks. All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.phonebook = None def _action(self, actionname, **kwargs): return self.fc.call_action(SERVICE, actionname, **kwargs) @property def phonebook_ids(self) -> list[int]: """ List of integers identifying the phonebooks. This property is defined as `phonebook_ids` and as `list_phonebooks` for backward compatibility. The property `list_phonebooks` is deprecated and may get removed in the future. """ result = self._action('GetPhonebookList') try: res = result['NewPhonebookList'].split(',') res = [int(x) for x in res] except KeyError: return [] return res # legathy api name for backward compatibility def list_phonebooks(self) -> list[int]: """ .. deprecated:: 1.13.0 Use :func:`phonebook_ids` instead. """ warn('This method is deprecated. Use "phonebook_ids" instead.', DeprecationWarning) return self.phonebook_ids def phonebook_info(self, id: int) -> dict: """ Get the `name`, `url` and an optional `extra id` of the phonebook with integer `id`. Returns a dictionary with the keys `name`, `url` and `xid`. """ result = self._action('GetPhonebook', NewPhonebookId=id) return { 'name': result.get('NewPhonebookName'), 'url': result.get('NewPhonebookURL'), 'xid': result.get('NewPhonebookExtraID') } def get_all_name_numbers(self, id: int) -> list[tuple]: """ Returns all entries from the phonebook with the given id as a list of tuples. The first item of every tuple is the contact name and the second item is the list of numbers for this contact. """ url = self.phonebook_info(id)['url'] self._read_phonebook(url) return [ (contact.name, contact.numbers) for contact in self.phonebook.contacts ] def get_all_names(self, id: int) -> dict: """ Get a dictionary with all names and their phone numbers for the phonebook with `id`. If a name is given more than once in a single phonebook, the last entry will overwrite the previous entries. (That's because the names are the keys in the dictionary returned from this method. In this case use the method 'get_all_name_numbers()' to get all entries as a list of tuples.) """ return {name: number for name, number in self.get_all_name_numbers(id)} def get_all_numbers(self, id: int) -> dict: """ Get a dictionary with all phone numbers and the according names for the phonebook with `id`. This method is based on the method 'get_all_names()' and has the same limitations. """ reverse_contacts = dict() for name, numbers in self.get_all_names(id).items(): for number in numbers: reverse_contacts[number] = name return reverse_contacts def lookup_numbers(self, id: int, name: str) -> list[str]: """ Look up the phone numbers of contact `name` in the phonebook with `id`. Returns a list of numbers. Will raise a KeyError if the name is unknown. """ return self.get_all_names(id)[name] def lookup_names(self, id: int, number: str) -> str: """ Look up the names of the contacts with phone number `number` in the phonebook with `id`. Will raise a KeyError if the number is unknown. """ return self.get_all_numbers(id)[number] def _read_phonebook(self, url): """ Read the content of the phonebook with the given `url`. This method sets the phone book instance attribute and has no return value. """ root = get_xml_root(url, session=self.fc.session) self.phonebook = Phonebook() process_node(self, root) @processor class Services: """ Services container. So far just for an associated email-address. """ def __init__(self): self.email = None @processor class Person: """ Data storage for a contact name and an image. """ def __init__(self): self.realName = None self.imageURL = None @processor class Telephony: """ Data storage for the phone numbers of the contact and services. """ number = ValueSequencer('numbers') def __init__(self): self.numbers = list() self.services = Services() @processor class Contact: """ Represents a contact with `category`- and `uniqueid`-attributes as well as `person`- and telephony-sub-nodes. """ def __init__(self): self.category = None self.uniqueid = None self.person = Person() self.telephony = Telephony() @property def name(self): return self.person.realName @property def numbers(self): return self.telephony.numbers @processor class Phonebook(Storage): """ Represents a phonebook with a timestamp indicating the last modification and a list of Contact instances. """ contact = InstanceAttributeFactory(Contact) def __init__(self): self.timestamp = None self.contacts = list() super().__init__(self.contacts) fritzconnection-1.15.0/fritzconnection/lib/fritzstatus.py000066400000000000000000000370171501211554500237630ustar00rootroot00000000000000""" Module to read status-information from an AVM FritzBox. """ from __future__ import annotations import datetime from collections import namedtuple from fritzconnection.core.processor import ( Storage, InstanceAttributeFactory, processor, process_node, ) from fritzconnection.core.utils import get_xml_root from .fritzbase import AbstractLibraryBase from .fritztools import ( ArgumentNamespace, format_dB, format_num, format_rate, ) DefaultConnectionService = namedtuple( "DefaultConnectionService", "prefix connection_service postfix" ) def _integer_or_original(value): """ Tries to convert value to an integer. Returns this integer on success, otherwise returns the original value. """ try: return int(value) except ValueError: return value @processor class Event: """ Represents an AVM DeviceLog entry with the subnodes given as class-attributes. The default types are strings as extracted from the xml-source. """ id = None group = None date = None time = None msg = None @property def datetime(self): return datetime.datetime.strptime(f"{self.date}{self.time}", "%d.%m.%y%H:%M:%S") class DeviceLog(Storage): """ The AVM DeviceLog is a list of Event-nodes stored in the `events` instance attribute. But instances of DeviceLog are also iterables for the events. """ Event = InstanceAttributeFactory(Event) def __init__(self, root): self.events = list() super().__init__(self.events) process_node(self, root) def __iter__(self): for event in self.events: yield event class FritzStatus(AbstractLibraryBase): """ Class for requesting status-information: up, down, ip, activity (bytes per second send/received). All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ @property def is_linked(self) -> bool: """ A boolean whether the FritzBox is physically linked to the provider. """ status = self.fc.call_action("WANCommonIFC", "GetCommonLinkProperties") return status["NewPhysicalLinkStatus"] == "Up" @property def is_connected(self) -> bool: """ A boolean whether the FritzBox has established an internet-connection. """ status = self.fc.call_action("WANIPConn", "GetStatusInfo") return status["NewConnectionStatus"] == "Connected" @property def external_ip(self) -> str: """The external v4 ip-address.""" return self.fc.call_action("WANIPConn", "GetExternalIPAddress")[ "NewExternalIPAddress" ] @property def external_ipv6(self) -> str: """The external v6 ip-address.""" return self.external_ipv6_info["NewExternalIPv6Address"] @property def external_ipv6_info(self) -> dict: """ Returns the ipv6 external address information as a dictionary with the keys: NewExternalIPv6Address out -> string NewPrefixLength out -> ui1 NewValidLifetime out -> ui4 NewPreferedLifetime out -> ui4 """ return self.fc.call_action("WANIPConn", "X_AVM_DE_GetExternalIPv6Address") @property def ipv6_prefix(self): """The internal v6 prefix.""" return self.ipv6_prefix_info["NewIPv6Prefix"] @property def ipv6_prefix_info(self) -> dict: """ Returns the ipv6 prefix information as a dictionary with the keys: NewIPv6Prefix out -> string NewPrefixLength out -> ui1 NewValidLifetime out -> ui4 NewPreferedLifetime out -> ui4 """ return self.fc.call_action("WANIPConn", "X_AVM_DE_GetIPv6Prefix") @property def connection_uptime(self) -> int: """Connection uptime in seconds.""" status = self.fc.call_action("WANIPConn", "GetStatusInfo") return status["NewUptime"] @property def device_uptime(self) -> int: """Device uptime in seconds.""" status = self.fc.call_action("DeviceInfo1", "GetInfo") return status["NewUpTime"] @property def str_uptime(self) -> str: """Connection uptime in human-readable format.""" mins, secs = divmod(self.connection_uptime, 60) hours, mins = divmod(mins, 60) return "%02d:%02d:%02d" % (hours, mins, secs) @property def bytes_sent(self) -> int | str: """ Total number of sent bytes. Returns an integer or, in case of failure, the original value which would be a string. """ try: status = self.fc.call_action("WANCommonIFC1", "GetAddonInfos") value = status["NewX_AVM_DE_TotalBytesSent64"] except KeyError: # fallback for older FritzOS Versions not providing a 64 bit value: status = self.fc.call_action("WANCommonIFC1", "GetTotalBytesSent") value = status["NewTotalBytesSent"] return _integer_or_original(value) @property def bytes_received(self) -> int | str: """ Total number of received bytes. Returns an integer or, in case of failure, the original value which would be a string. """ try: status = self.fc.call_action("WANCommonIFC1", "GetAddonInfos") value = status["NewX_AVM_DE_TotalBytesReceived64"] except KeyError: # fallback for older FritzOS Versions not providing a 64 bit value: status = self.fc.call_action("WANCommonIFC1", "GetTotalBytesReceived") value = status["NewTotalBytesReceived"] return _integer_or_original(value) @property def transmission_rate(self) -> tuple[int, int]: """ The upstream and downstream values as a tuple in bytes per second. Use this for periodical calling. """ status = self.fc.call_action("WANCommonIFC1", "GetAddonInfos") upstream = status["NewByteSendRate"] downstream = status["NewByteReceiveRate"] return upstream, downstream @property def str_transmission_rate(self) -> tuple[str, str]: """ Tuple of human-readable transmission rate in bytes. First item is upstream, second item downstream. """ upstream, downstream = self.transmission_rate return format_num(upstream), format_num(downstream) @property def max_linked_bit_rate(self) -> tuple[int, int]: """ Tuple with the maximum upstream- and downstream-rate of the physical link. The rate is given in bits/sec. """ return self._get_max_bit_rate("WANCommonInterfaceConfig") @property def max_bit_rate(self) -> tuple[int, int]: """ Tuple with the maximum upstream- and downstream-rate of the given connection. The rate is given in bits/sec. """ return self._get_max_bit_rate("WANCommonIFC") def _get_max_bit_rate(self, servicename: str) -> tuple[int, int]: """ internal method to get the upstream and downstream-rates for different services of the WANCommonInterfaceConfig1 ServiceType. """ status = self.fc.call_action(servicename, "GetCommonLinkProperties") downstream = status["NewLayer1DownstreamMaxBitRate"] upstream = status["NewLayer1UpstreamMaxBitRate"] return upstream, downstream @property def max_byte_rate(self) -> tuple[float, float]: """ Same as max_bit_rate but rate is given in bytes/sec. """ upstream, downstream = self.max_bit_rate return upstream / 8.0, downstream / 8.0 @property def str_max_linked_bit_rate(self) -> tuple[str, str]: """ Human-readable maximum of the physical upstream- and downstream-rate in bits/sec. Value is a tuple, first item is upstream, second item is downstream. """ upstream, downstream = self.max_linked_bit_rate return ( format_rate(upstream, unit="bits"), format_rate(downstream, unit="bits"), ) @property def str_max_bit_rate(self) -> tuple[str, str]: """ Human-readable maximum of the upstream- and downstream-rate in bits/sec, as given by the provider. Value is a tuple, first item is upstream, second item is downstream. """ upstream, downstream = self.max_bit_rate return ( format_rate(upstream, unit="bits"), format_rate(downstream, unit="bits"), ) def get_monitor_data(self, sync_group_index=0) -> dict: """ Returns a dictionary with realtime data about the current up- and downstream rates. """ monitor_data = self.fc.call_action( "WANCommonInterfaceConfig1", "X_AVM-DE_GetOnlineMonitor", NewSyncGroupIndex=sync_group_index, ) for key, value in monitor_data.items(): if isinstance(value, str) and "," in value: try: items = [int(v) for v in value.split(",")] except (AttributeError, ValueError): # ignore and keep value as is: pass else: monitor_data[key] = items # type: ignore return monitor_data def reconnect(self) -> None: """Makes a reconnection with a new external ip.""" self.fc.reconnect() @property def noise_margin(self) -> tuple[int, int]: """ Tuple of noise margin. First item is upstream, second item downstream. """ status = self.fc.call_action("WANDSLInterfaceConfig1", "GetInfo") upstream = status["NewUpstreamNoiseMargin"] downstream = status["NewDownstreamNoiseMargin"] return upstream, downstream @property def str_noise_margin(self) -> tuple[str, str]: """ Human-readable noise margin in dB. Value is a tuple, first item is upstream, second item downstream. """ upstream, downstream = self.noise_margin return format_dB(upstream), format_dB(downstream) @property def attenuation(self) -> tuple[int, int]: """ Tuple of attenuation. First item is upstream, second item downstream. """ status = self.fc.call_action("WANDSLInterfaceConfig1", "GetInfo") upstream = status["NewUpstreamAttenuation"] downstream = status["NewDownstreamAttenuation"] return upstream, downstream @property def str_attenuation(self) -> tuple[str, str]: """ Human-readable attenuation in dB. Value is a tuple, first item is upstream, second item downstream. """ upstream, downstream = self.attenuation return format_dB(upstream), format_dB(downstream) @property def upnp_enabled(self) -> bool: """ Returns a boolean whether upnp is enabled or raises a FritzServiceError in case the service is not available. """ status = self.fc.call_action("X_AVM-DE_UPnP1", "GetInfo") return status["NewEnable"] @property def device_has_mesh_support(self) -> bool: """ True if the device supports mesh, otherwise False. """ # check for the corresponding action # whether mesh is supported try: return "X_AVM-DE_GetMeshListPath" in self.fc.services["Hosts1"].actions except KeyError: # can happen if "Hosts1" is not known return False def get_device_info(self) -> ArgumentNamespace: """ Returns an ArgumentNamespace with the attributes: manufacturer_name, manufacturer_oui, model_name, description, product_class, serial_number, software_version, hardware_version, spec_version, provisioning_code, up_time, device_log .. versionadded:: 1.10 """ return ArgumentNamespace(self.fc.call_action("DeviceInfo1", "GetInfo")) def get_avm_device_log(self, filter: str | None = None) -> DeviceLog: """ The avm device log is a list of events with the attributes `id`, `group`, `date`, `time` and `msg` holding information like "DSL synchronization starting (training)" and other system messages. The Method returns a DeviceLog instance holding a list of Event instances. The DeviceLog instance is an iterable and can be used on a FritzStatus instance like: >>> device_log = fritzstatus.get_avm_device_log() >>> for event in device_log: >>> print(event.datetime, event.msg) The returned events can be filtered by groups like 'sys', 'net', 'fon', 'wlan' or 'usb'. To filter by a group provide the group-name as filter-argument. """ result = self.fc.call_action("DeviceInfo1", "X_AVM-DE_GetDeviceLogPath") path = result["NewDeviceLogPath"] if filter: path = f"{path}&filter={filter}" url = f"{self.fc.address}:{self.fc.port}{path}" root_node = get_xml_root(url, session=self.fc.session) return DeviceLog(root_node) def get_cpu_temperatures(self) -> list[int]: """ Returns a list of the last measured cpu-temperatures (Celsius). The most recent entry is the first one in the list. NOTE: this function call is experimental as it is based on a non-public API. """ url = f"{self.fc.http_interface.router_url}/query.lua" payload = {"CPUTEMP": "cpu:status/StatTemperature"} response = self.fc.http_interface.call_url(url, payload) return list(map(int, response.json()["CPUTEMP"].split(","))) def get_default_connection_service(self) -> DefaultConnectionService: """ Returns a namedtuple of type DefaultConnectionService: `prefix` -> str `device_connection` -> str (like "WANPPPConnection") `postfix` -> str """ result = self.fc.call_action("Layer3Forwarding1", "GetDefaultConnectionService") prefix, connection_service, postfix = result[ "NewDefaultConnectionService" ].split(".", 2) return DefaultConnectionService(prefix, connection_service, postfix) @property def connection_service(self) -> str: """ The extracted connection_service from get_default_connection_service(). """ result = self.get_default_connection_service() return result.connection_service @property def update_available(self) -> str: """ The new version number (as a string) if an update is available or an empty string if no update is avilable. """ return self.fc.call_action("UserInterface1", "GetInfo")["NewX_AVM-DE_Version"] @property def has_wan_enabled(self) -> bool: """ True if wan is enabled otherwise False. """ return self.fc.call_action(self.connection_service, "GetInfo")["NewEnable"] @property def has_wan_support(self) -> bool: """ True if the device supports a WAN interface. False otherwise. """ return "Layer3Forwarding1" in self.fc.services fritzconnection-1.15.0/fritzconnection/lib/fritztools.py000066400000000000000000000134531501211554500235760ustar00rootroot00000000000000""" Some helpers for the library. """ import math import re from types import SimpleNamespace RE_UPPER_CASE = re.compile(r"([A-Z]+)") def byte_formatter(value): """ Gets a large integer als value and returns a tuple with the value as float and the matching dimension as string, i.e. >>> byte_formatter(242981246) (242.981246, 'MB') Expects positive integer as input. Negative numbers are interpreted as positive numbers. values < 1 are interpreted as 0. """ dim = ['B', 'KB', 'MB', 'GB', 'TB'] value = abs(value) if value < 1: log = 0 num = 0 else: log = min(int(math.log10(value) / 3), len(dim)) num = value / 1000 ** log try: dimension = dim[log] except IndexError: dimension = 'PB' return num, dimension def format_num(num, unit='bytes'): """ Returns a human-readable string of a byte-value. If 'num' is bits, set unit='bits'. """ num, dim = byte_formatter(num) if unit != 'bytes': dim += 'it' # then its Bit by default return f'{num:3.1f} {dim}' def format_rate(num, unit='bytes'): """ Returns a human-readable string of a byte/bits per second. If 'num' is bits, set unit='bits'. """ return format_num(num, unit=unit) + '/s' def format_dB(num): """ Returns a human-readable string of dB. The value is divided by 10 to get first decimal digit """ num /= 10 return f'{num:3.1f} {"dB"}' class ArgumentNamespace(SimpleNamespace): """ Namespace object that also behaves like a dictionary, but is not iterable. Usecase is as a wrapper for the dictionary returned from `FritzConnection.call_action()`. This dictionary has keys named "arguments" as described by the AVM documentation, combined with values as the corresponding return values. Instances of `ArgumentNamespace` can get used to extract a subset of this dictionary and transfer the Argument-names to more readable ones. For example consider that `fc` is a FritzConnection instance. Then the following call: :: >>> result = fc.call_action("DeviceInfo1", "GetInfo") will return a dictionary like: :: {'NewManufacturerName': 'AVM', 'NewManufacturerOUI': '00040E', 'NewModelName': 'FRITZ!Box 7590', 'NewDescription': 'FRITZ!Box 7590 154.07.29', 'NewProductClass': 'AVMFB7590', 'NewSerialNumber': '989BCB2xxxxx', 'NewSoftwareVersion': '154.07.29', 'NewHardwareVersion': 'FRITZ!Box 7590', 'NewSpecVersion': '1.0', 'NewProvisioningCode': '000.044.004.000', 'NewUpTime': 9516949, 'NewDeviceLog': 'long string here ...'} In case that just the model name and serial number are of interest, and should have better names, first define a mapping: :: mapping = { "modelname": "NewModelName", "serialnumber": "NewSerialNumber" } and use this `mapping` with the dictionary `result` to create an `ArgumentNamespace` instance: :: >>> info = ArgumentNamespace(result, mapping) The `info` instance can now get used like a namespace object and like a dictionary: :: >>> info.serialnumber '989BCB2xxxxx' >>> info['modelname'] 'FRITZ!Box 7590' If no mapping is given, then `ArgumentNamespace` will consume the provided dictionary converting all keys from "MixedCase" style to "snake_case" (PEP 8) and removes the leading "new" originating from the AVM "New" prefix for all keys: :: >>> info = ArgumentNamespace(result) >>> info.up_time 9516949 Setting the flag `suppress_new` to `False` will keep the prefix: :: >>> info = ArgumentNamespace(result, suppress_new=False) >>> info.new_up_time 9516949 To just extract a subset of `result` provide a sequence of key-names for the `extract` argument: :: >>> extract = "NewSerialNumber", "NewModelName" >>> info = ArgumentNamespace(result, extract=extract) >>> info.serial_number '989BCB2xxxxx' >>> info.model_name 'FRITZ!Box 7590' If both arguments `mapping` and `extract` are given, `mapping` has precedence and `extract` gets ignored. .. versionadded:: 1.10 """ def __init__(self, source, mapping=None, extract=None, suppress_new=True): if mapping is None: keys = extract if extract else source.keys() mapping = { self.rewrite_argument(key, suppress_new): key for key in keys } super().__init__( **{name: source[attribute] for name, attribute in mapping.items()} ) def __getitem__(self, key): return getattr(self, key) def __setitem__(self, key, value): setattr(self, key, value) def __len__(self): # should provide len() as dict-like object return len(self.__dict__) @staticmethod def rewrite_argument(name: str, suppress_new: bool = True) -> str: """ Rewrite `name` from MixedCase to snake_case (PEP 8). So i.e. "MixedCase" gets converted to "mixed_case". AVM standard argument names starting with "New" like "NewMixedCase" will get converted to "new_mixed_case". If `suppress_new` is `True` (the default) the "new"-prefix will get removed, so "NewMixedCased" will get converted to "mixed_case". Consecutive upper-case characters are handled as a group: "ManufacturerOUI" -> "manufacturer_oui". .. versionadded:: 1.10 """ new = "new_" result = RE_UPPER_CASE.sub(r"_\1", name).lower() if result.startswith("_"): result = result[1:] if suppress_new and result.startswith(new): result = result[len(new):] return result fritzconnection-1.15.0/fritzconnection/lib/fritztopology.py000066400000000000000000000224301501211554500243050ustar00rootroot00000000000000""" Module to access to the Mesh Topology See https://avm.de/service/schnittstellen/ "Mesh-Topologie" """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Authors: Klaus Bremer # code partly to dynamic for a useful mypy run: # mypy: disable-error-code="attr-defined" from __future__ import annotations from .fritzhosts import FritzHosts from .fritzbase import AbstractLibraryBase class Connection: """ Represents a connection from one device to another device. This is basically a convenience wrapper for InterfaceLink exposing the devices and some instance attributes in a more comfortable way. self.source is the origin device self.target is the connected device self.type is the connection type (like "WLAN") self.state is the connection state (like "DISCONNECTED", "CONNECTED") self.max_rx, max_tx, cur_rx and cur_tx are the maximum and current throughput data rates in kbit/sec. tx is the upload-throughput from source to target, even if the source is represented by the interface-link node 2. """ def __init__(self, source, target, interface_link): self.source = source self.target = target self.interface_link = interface_link @property def type(self) -> str | None: return self._get_interface_attribute("type") @property def state(self) -> str | None: return self._get_interface_attribute("state") @property def max_rx(self) -> int | None: return self._get_transfer_rate("max_data_rate_rx") @property def max_tx(self) -> int | None: return self._get_transfer_rate("max_data_rate_tx") @property def cur_rx(self) -> int | None: return self._get_transfer_rate("cur_data_rate_rx") @property def cur_tx(self) -> int | None: return self._get_transfer_rate("cur_data_rate_tx") def _get_transfer_rate(self, name): """ Adapt the rate to the link direction: 'tx' is the transfer rate from node 1 to node 2 which is ok, if node 1 represents the 'source' node. In case it is the other way around the commands 'tx' and 'rx' must get exchanged. """ if self.interface_link.source_index == 2: name, direction = name.rsplit("_", 1) direction = "rx" if direction == "tx" else "tx" name = f"{name}_{direction}" return self._get_interface_attribute(name) def _get_interface_attribute(self, name, default=None): return getattr(self.interface_link, name, default) class InterfaceLink: """ Represents a node-link from an Interface of a device to another Interface of another device. (These are the vertexes of the mesh.) Instance attributes are all elements described as "node_links.properties" in the AVM documentation and accessible by their names, i.e. like 'self.last_connected' in case the UNIX timestamp is requested. """ def __init__(self, data: dict, interface: Interface): self.__dict__.update(data) self.interface = interface # The starting point is assumed to be the device, which is # the owner of self.interface. if self.node_interface_1_uid == self.interface.uid: self.source_index = 1 self.target_index = 2 else: self.source_index = 2 self.target_index = 1 def __repr__(self) -> str: return f"InterfaceLink: {self.uid:<8}target-interface: {self.node_interface_2_uid}" def __str__(self) -> str: connection = Connection(self.source, self.target, self) if connection.cur_tx is not None: throughput = connection.cur_tx // 1000 # from kB/s to MB/s else: throughput = None # not known return f"from {self.source.name} to {self.target.name} (-> {throughput} MBit/s)" @property def source(self) -> Device: return self._get_connected_device(target=False) @property def target(self) -> Device: return self._get_connected_device(target=True) def get_connection(self) -> Connection: """ Returns a connection instance describing a connection from one device to another device. """ return Connection(self.source, self.target, self) def _get_connected_device(self, target=True): """ Returns the device connected by this link, either the target or source device. """ index = self.target_index if target else self.source_index device_id = getattr(self, f"node_{index}_uid") return self.interface.device.mesh.get_device_by_id(device_id) class Interface: """ An interface represents a physical infrastructure of a device to connect with other devices. An interface is part of a device and able to connect to another interface of another device. A connection is represented by the InterfaceLink class. """ def __init__(self, data: dict, device: Device): self.__dict__.update(data) self.interface_links = [ InterfaceLink(link, self) for link in self.node_links ] self.device = device def __repr__(self) -> str: representation = ( f"Interface: mac={self.mac:<20}" f"uid={self.uid:<8}" f"type={self.type:<8}" ) if self.name: representation = f"{representation}name={self.name}" return representation def __str__(self) -> str: interface = repr(self) if self.interface_links: space = " " * 8 links = f"\n{space}".join(str(link) for link in self.interface_links) interface = f"{interface}\n{space}{links}" return interface @property def mac(self) -> str: """mac address of the interface""" return self.mac_address def get_connections(self): """ Returns a list of Connection objects describing all devices connected by this interface. """ return [link.get_connection() for link in self.interface_links] class Device: """ A Device represents a physical item in the mesh, like a router, repeater, a laptop, a cell phone and other devices. (This is a node of the mesh.) Instance attributes created dynamical according to the AVM mesh topology schema: https://avm.de/service/schnittstellen/ For convenience there are some properties and methods to access the data in a more mnemonic way. """ def __init__(self, data: dict, mesh: FritzMeshTopology): self.__dict__.update(data) self.interfaces = [ Interface(interface_data, self) for interface_data in self.node_interfaces ] self.mesh = mesh def __repr__(self) -> str: return f"Device: mac={self.mac:<20}uid={self.uid:<8}{self.name}" def __str__(self) -> str: representation = repr(self) space = " " * 4 interfaces = f"\n{space}".join(str(interface) for interface in self.interfaces) return f"{representation}\n{space}{interfaces}" @property def name(self) -> str: return self.device_name @property def model(self) -> str: return self.device_model @property def vendor(self) -> str: return self.device_manufacturer @property def mac(self) -> str: return self.device_mac_address def get_connections(self): """ Returns a list of Connection objects describing all devices connected to this device. """ connections = [] for interface in self.interfaces: connections.extend(interface.get_connections()) return connections class FritzMeshTopology(AbstractLibraryBase): """ Represents the mesh topology with nodes representing the devices. """ def __init__(self, fc=None, *args, **kwargs): super().__init__(fc, *args, **kwargs) self._fritzhosts = FritzHosts(self.fc) self.topology = {} self.nodes = {} def __repr__(self) -> str: return ( f"{self.__class__.__name__}: " f"schema_version={self.schema_version}, " f"registered Devices: {self.number_of_devices}" ) def __str__(self) -> str: nodes = "\n\n".join(str(device) for device in self.devices) return f"{repr(self)}\n{nodes}" @property def schema_version(self) -> str: return self.topology.get("schema_version", "unknown") @property def number_of_devices(self) -> int: return len(self.nodes) @property def devices(self) -> list[Device]: return list(self.nodes.values()) def get_device_by_id(self, uid: str) -> Device: """ Returns a device by id. The id is the node-uid like "n-1". The node-uids are fixed to devices after calling `load_topology()` but may change if `load_topology()` gets called again. """ return self.nodes[uid] def load_topology(self): """ Load the topology from the router. """ self.topology = self._fritzhosts.get_mesh_topology(raw=False) self.nodes = { node["uid"]: Device(node, self) for node in self.topology.get("nodes", ()) } fritzconnection-1.15.0/fritzconnection/lib/fritzwlan.py000066400000000000000000000315011501211554500233710ustar00rootroot00000000000000""" Module to get information about WLAN devices. """ # This module is part of the FritzConnection package. # https://github.com/kbr/fritzconnection # License: MIT (https://opensource.org/licenses/MIT) # Author: Bernd Strebel, Klaus Bremer from __future__ import annotations import io import itertools import random import string from ..core.exceptions import FritzServiceError from .fritzbase import AbstractLibraryBase try: import segno.helpers except ImportError: SEGNO_INSTALLED = False else: SEGNO_INSTALLED = True # important: don't set an extension number here: SERVICE = 'WLANConfiguration' DEFAULT_PASSWORD_LENGTH = 12 _QR_SECURITY_WPA = 'WPA' _QR_SECURITY_WEP = 'WEP' _QR_SECURITY_NO_PASS = 'nopass' _BEACONTYPE_TO_QR_SECURITY = { 'WPA': _QR_SECURITY_WPA, '11i': _QR_SECURITY_WPA, 'WPAand11i': _QR_SECURITY_WPA, 'WPA3': _QR_SECURITY_WPA, '11iandWPA3': _QR_SECURITY_WPA, 'Basic': _QR_SECURITY_WEP, 'OWE': _QR_SECURITY_NO_PASS, 'OWETrans': _QR_SECURITY_NO_PASS, 'None': _QR_SECURITY_NO_PASS, } def _get_wifi_qr_code(instance, kind='svg', security=None, scale=4, border=0): """ Returns a file-like object providing a bytestring representing a qr-code for wlan access. `instance` is a FritzWLAN or FritzGuestWLAN instance. `kind` describes the type of the qr-code. Supported types are: 'svg', 'png', 'pdf', 'text' and 'text-compact'. Default is 'svg'. This function is not intended to get called directly. Instead it is available as a method on FritzWLAN instances (as well as on subclasses like FritzGuestWLAN) if the third party package `segno` is installed. Consider `guest_wlan` is a FritzGuestWLAN instance, then the following code will return a file like object with the qr-code image data in png-format: :: stream = guest_wlan.get_wifi_qr_code(kind='png') The stream can get used anywhere, where a file like object is expected, i.e. writing the content to a file (Note: the suffix must match the kind of the qr-code format): :: with open('qr_code.png', 'wb') as fobj: fobj.write(stream.read()) The stream can be printed out if qr-code is represented as text: :: stream = guest_wlan.get_wifi_qr_code(kind='text') print(stream.getvalue()) If `segno` is not installed the call will trigger an AttributeError when called on an instance and a NameError when called directly. .. versionadded:: 1.9.0 The parameters `security` and `hidden` allow to forward these informations to the `segno` library. `security` is `None` or a string like `WPA`. `hidden` is a boolean value indicating the visibility of the network . .. versionadded:: 1.9.1 If the `security` is `None` (default) the beacontype of the network is used to set the WLAN-Type accordingly. If the value of `security` is something else, this value gets used. `scale` defines the size of the produced qr-code. Default value is 4. .. versionadded:: 1.10 """ if not security: # if beacon type is something unknown, assume a "no pass" connection: security = _BEACONTYPE_TO_QR_SECURITY.get(instance.beacontype, _QR_SECURITY_NO_PASS) password = instance.get_password() if security != _QR_SECURITY_NO_PASS else None qr_code = segno.helpers.make_wifi( ssid=instance.ssid, password=password, security=security, hidden=instance.is_hidden ) if kind in ['text', 'text-compact']: stream = io.StringIO() compact = kind != 'text' qr_code.terminal(out=stream, border=border, compact=compact) else: stream = io.BytesIO() qr_code.save(out=stream, kind=kind, scale=scale, border=border) stream.seek(0) return stream def _qr_code_enabler(cls): """Classdecorator to inject qr-capabilities at import time.""" if SEGNO_INSTALLED: cls.get_wifi_qr_code = _get_wifi_qr_code return cls @_qr_code_enabler class FritzWLAN(AbstractLibraryBase): """ Class to list all known wlan devices. All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). The *service* parameter specifies the configuration in use. Typically this is 1 for 2.4 GHz, 2 for 5 GHz and 3 for a guest network. This can vary depending on the router model and change with future standards. """ def __init__(self, *args, service=1, **kwargs): super().__init__(*args, **kwargs) self.service = service def _action(self, actionname, **kwargs): service = f'{SERVICE}{self.service}' return self.fc.call_action(service, actionname, **kwargs) @property def host_number(self) -> int: """ Number of registered wlan devices for the active WLANConfiguration. """ result = self._action('GetTotalAssociations') return result['NewTotalAssociations'] @property def total_host_number(self) -> int: """ Total NewAssociatedDeviceIndexNumber of registered wlan devices for all WLANConfigurations. """ total = 0 _service = self.service for service in itertools.count(1): self.service = service try: total += self.host_number except FritzServiceError: break self.service = _service return total @property def ssid(self) -> str: """The WLAN SSID""" result = self._action('GetSSID') return result['NewSSID'] @ssid.setter def ssid(self, value: str) -> None: self._action('SetSSID', NewSSID=value) @property def beacontype(self) -> str: """ Represents the beacontype for the network as string. At time of writing (OS 7.29) possible values are: `None, 11i, WPAand11i, 11iandWPA3` for the private WiFi-security settings and `None, 11i, 11iandWPA3, OWETrans` for the guest network. """ return self.get_info()['NewBeaconType'] @property def is_hidden(self) -> bool: """Returns True if the SSID hidden (not advertised through beacons).""" return not self._action('GetBeaconAdvertisement')['NewBeaconAdvertisementEnabled'] @property def channel(self) -> int: """The WLAN channel in use""" return self.channel_info()['NewChannel'] @property def alternative_channels(self) -> str: """Alternative channels (as string)""" return self.channel_info()['NewPossibleChannels'] def channel_info(self) -> dict: """ Return a dictionary with the keys *NewChannel* and *NewPossibleChannels* indicating the active channel and alternative ones. """ return self._action('GetChannelInfo') def set_channel(self, number: int) -> None: """ Set a new channel. *number* must be a valid channel number for the active WLAN. (Valid numbers are listed by *alternative_channels*.) """ self._action('SetChannel', NewChannel=number) def get_generic_host_entry(self, index: int) -> dict: """ Return a dictionary with information about the device internally stored at the position 'index'. """ result = self._action( 'GetGenericAssociatedDeviceInfo', NewAssociatedDeviceIndex=index ) return result def get_specific_host_entry(self, mac_address: str) -> dict: """ Return a dictionary with information about the device with the given 'mac_address'. """ result = self._action( 'GetSpecificAssociatedDeviceInfo', NewAssociatedDeviceMACAddress=mac_address ) return result def get_hosts_info(self) -> list[dict]: """ Returns a list of dictionaries with information about the known hosts. The dict-keys are: 'service', 'index', 'status', 'mac', 'ip', 'signal', 'speed' """ information = [] for index in itertools.count(): try: host = self.get_generic_host_entry(index) except IndexError: break information.append({ 'service': self.service, 'index': index, 'status': host['NewAssociatedDeviceAuthState'], 'mac': host['NewAssociatedDeviceMACAddress'], 'ip': host['NewAssociatedDeviceIPAddress'], 'signal': host['NewX_AVM-DE_SignalStrength'], 'speed': host['NewX_AVM-DE_Speed'] }) return information def get_info(self) -> dict: """ Returns a dictionary with general internal information about the current wlan network according to the AVM documentation. """ return self._action("GetInfo") @property def is_enabled(self) -> bool: """Returns whether the network is enabled.""" return self.get_info()["NewEnable"] def enable(self) -> None: """Enables the associated network.""" self._set_enable(True) def disable(self) -> None: """Disables the associated network.""" self._set_enable(False) def _set_enable(self, status): """Helper function for enable|disable.""" self._action("SetEnable", arguments={"NewEnable": status}) def get_password(self) -> str: """Returns the current password of the associated wlan.""" return self._action("GetSecurityKeys")["NewKeyPassphrase"] def set_password( self, password: str | None = None, length: int = DEFAULT_PASSWORD_LENGTH ) -> None: """ Sets a new password for the associated wlan. If no password is given a new one is created with the given length (the new password can get read with a subsequent call of `get_password`). Also creates a new pre-shared key. """ preshared_key = self._create_preshared_key() password = password or self._create_password(length) arguments = { "NewKeyPassphrase": password, "NewPreSharedKey": preshared_key, "NewWEPKey0": "", "NewWEPKey1": "", "NewWEPKey2": "", "NewWEPKey3": "", } self._action("SetSecurityKeys", arguments=arguments) def _create_preshared_key(self): """ Returns a new pre-shared key for setting a new password. The sequence is of uppercase characters as this is default on FritzOS at time of writing. """ info = self.get_info() characters = info["NewAllowedCharsPSK"] length = info["NewMaxCharsPSK"] return "".join(random.choices(characters, k=length)).upper() @staticmethod def _create_password(length): """ Returns a human-readable password with the given length. """ # add just two human-readable special characters. # password strength increases with the length. # character permutations are: 64**length characters = string.ascii_letters + string.digits + "@#" return "".join(random.choices(characters, k=length)) class FritzGuestWLAN(FritzWLAN): """ Inherits from FritzWLAN and provides all the same methods but for the guest network. On devices not providing a guest network this class will not fail, but handle the wlan network with the highest internal service number (which is by default the guest network on guest network providing devices). All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ def __init__(self, *args, **kwargs): """ Initialize the guest wlan instance. All parameters are optional. If given, they have the following meaning: `fc` is an instance of FritzConnection, `address` the ip of the Fritz!Box, `port` the port to connect to, `user` the username, `password` the password, `timeout` a timeout as floating point number in seconds, `use_tls` a boolean indicating to use TLS (default False). """ super().__init__(*args, **kwargs) for n in itertools.count(1): service = self.fc.services.get(f"{SERVICE}{n}") if service is None: self.service = n - 1 break fritzconnection-1.15.0/fritzconnection/tests/000077500000000000000000000000001501211554500213735ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/tests/__init__.py000066400000000000000000000000001501211554500234720ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/tests/conftest.py000066400000000000000000000004601501211554500235720ustar00rootroot00000000000000from pathlib import Path import pytest @pytest.fixture def datadir(): """ Simple fixture for getting data files """ here = Path(__file__).parent / "xml" return here def pytest_configure(config): config.addinivalue_line("markers", "routertest: mark test accessing the router") fritzconnection-1.15.0/fritzconnection/tests/test_core_utils.py000066400000000000000000000026471501211554500251650ustar00rootroot00000000000000 import pytest from ..core.utils import ( boolean_from_string, get_boolean_from_string, ) @pytest.mark.parametrize( "value, expected_result", [ ("True", True), ("TRUE", True), ("false", False), ("fAlSe", False), ("On", True), ("Off", False), ("1", True), ("0", False), ] ) def test_boolean_from_string(value, expected_result): """ Test to get a real boolean and not a string. """ result = boolean_from_string(value) assert result == expected_result @pytest.mark.parametrize( "value", [ "wahr", "falsch", "l", "10", "01", "", "None", ] ) def test_boolean_from_string_valueerror(value): with pytest.raises(ValueError): boolean_from_string(value) @pytest.mark.parametrize( "value", [ True, False, None, 42, ] ) def test_boolean_from_string_typeerror(value): with pytest.raises(AttributeError): boolean_from_string(value) @pytest.mark.parametrize( "value, expected_result", [ ("true", True), ("false", False), ("wahr", None), ("falsch", None), ("None", None), (42, None), ("", None), (None, None), ] ) def test_get_boolean_from_string(value, expected_result): result = get_boolean_from_string(value) assert result == expected_result fritzconnection-1.15.0/fritzconnection/tests/test_devices.py000066400000000000000000000054431501211554500244340ustar00rootroot00000000000000import json import os import pytest from ..core.devices import DeviceManager @pytest.mark.parametrize("filename", [ "igddesc.xml", "tr64desc.xml", ] ) def test_DeviceManager_load_descriptions(device_manager, datadir, filename): """test loading of two description files.""" os.chdir(datadir) device_manager.add_description(filename) assert device_manager.modelname == 'FRITZ!Box 7590' @pytest.fixture() def device_manager(datadir): os.chdir(datadir) manager = DeviceManager() manager.add_description('igddesc.xml') manager.add_description('tr64desc.xml') return manager @pytest.mark.parametrize( "name", ['WANIPConn1', 'DeviceConfig1', 'WLANConfiguration1'] ) def test_DeviceManager_get_service(name, device_manager): """ test services dict of the DeviceManager. Should find nested services (from sub devices) and from different files. """ device_manager.scan() # should not raise a KeyError service = device_manager.services[name] assert service.name == name @pytest.fixture() def device_manager_from_data(datadir): device_manager = DeviceManager() os.chdir(datadir) with open("description.json") as fobj: data = json.load(fobj) device_manager.deserialize(data) return device_manager def test_DeviceManager_load_json_check_descriptions(device_manager_from_data): """ test build up of a DeviceManager from json data. """ dm = device_manager_from_data assert len(dm.descriptions) == 2 # based on the test-data def test_DeviceManager_load_json_check_services_01(device_manager_from_data): """ check for loaded services after calling .scan() """ dm = device_manager_from_data assert dm.services == {} # still empty # run scan() should fill the services: dm.scan() assert dm.services != {} def test_DeviceManager_load_json_check_services_02(device_manager_from_data): """ check for matching services after calling .scan() """ dm = device_manager_from_data dm.scan() # "description_service_names.txt" corresponds to "description.json" with open("description_service_names.txt") as fobj: service_names = list(map(str.strip, fobj)) known_services = dm.services.keys() # check for same number of services: assert len(known_services) == len(service_names) # check for same service names: for name in service_names: assert name in known_services def test_DeviceManager_load_json_check_actions(device_manager_from_data): """ Simple test whether actions are available from the services (which in turn get the actions from the _scpd attribute). """ dm = device_manager_from_data dm.scan() for service in dm.services.values(): assert service.actions is not None fritzconnection-1.15.0/fritzconnection/tests/test_fritzconnection.py000066400000000000000000000151411501211554500262240ustar00rootroot00000000000000 import os from pathlib import Path from types import SimpleNamespace import pytest from ..core.devices import DeviceManager from ..core.exceptions import FritzConnectionException from ..core.fritzconnection import ( FritzConnection, FRITZ_CACHE_DIR, FRITZ_CACHE_FORMAT_JSON, FRITZ_CACHE_FORMAT_PICKLE, FRITZ_CACHE_JSON_SUFFIX, FRITZ_CACHE_PICKLE_SUFFIX, ) @pytest.mark.parametrize( "name, expected", [ ('WANIPConn', 'WANIPConn1'), ('WANIPConn1', 'WANIPConn1'), ('WANIPConn:1', 'WANIPConn1'), ('WANIPConn2', 'WANIPConn2'), ('WANIPConn:2', 'WANIPConn2'), ('WANIPConn21', 'WANIPConn21'), ('WANIPConn:21', 'WANIPConn21'), ] ) def test_normalize_name(name, expected): result = FritzConnection.normalize_name(name) assert result == expected @pytest.mark.parametrize( "url, use_tls, expected", [ ('192.168.178.1', False, 'http://192.168.178.1'), ('192.168.178.1', True, 'https://192.168.178.1'), ('http://192.168.178.1', False, 'http://192.168.178.1'), ('http://192.168.178.1', True, 'https://192.168.178.1'), ('https://192.168.178.1', False, 'http://192.168.178.1'), ('https://192.168.178.1', True, 'https://192.168.178.1'), ] ) def test_set_protocol(url, use_tls, expected): result = FritzConnection.set_protocol(url, use_tls) assert result == expected @pytest.mark.parametrize( "address, port, cache_directory, cache_format, expected_result", [ ('192.168.178.1', 49000, 'some_path', FRITZ_CACHE_FORMAT_PICKLE, Path("some_path") / f'192_168_178_1_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('192.168.178.1', 49000, '', FRITZ_CACHE_FORMAT_PICKLE, Path().home() / FRITZ_CACHE_DIR / f'192_168_178_1_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('192.168.178.1', 49000, None, FRITZ_CACHE_FORMAT_PICKLE, Path().home() / FRITZ_CACHE_DIR / f'192_168_178_1_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('192.168.178.6', 49000, None, FRITZ_CACHE_FORMAT_PICKLE, Path().home() / FRITZ_CACHE_DIR / f'192_168_178_6_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('192.168.1.15', 49000, None, FRITZ_CACHE_FORMAT_PICKLE, Path().home() / FRITZ_CACHE_DIR / f'192_168_1_15_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('http://192.168.1.15', 49000, None, FRITZ_CACHE_FORMAT_PICKLE, Path().home() / FRITZ_CACHE_DIR / f'192_168_1_15_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('https://192.168.1.15', 49000, None, FRITZ_CACHE_FORMAT_PICKLE, Path().home() / FRITZ_CACHE_DIR / f'192_168_1_15_cache.{FRITZ_CACHE_PICKLE_SUFFIX}'), ('192.168.178.1', 49000, 'some_path', FRITZ_CACHE_FORMAT_JSON, Path("some_path") / f'192_168_178_1_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ('192.168.178.1', 49000, '', FRITZ_CACHE_FORMAT_JSON, Path().home() / FRITZ_CACHE_DIR / f'192_168_178_1_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ('192.168.178.1', 49000, None, FRITZ_CACHE_FORMAT_JSON, Path().home() / FRITZ_CACHE_DIR / f'192_168_178_1_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ('192.168.178.6', 49000, None, FRITZ_CACHE_FORMAT_JSON, Path().home() / FRITZ_CACHE_DIR / f'192_168_178_6_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ('192.168.1.15', 49000, None, FRITZ_CACHE_FORMAT_JSON, Path().home() / FRITZ_CACHE_DIR / f'192_168_1_15_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ('http://192.168.1.15', 49000, None, FRITZ_CACHE_FORMAT_JSON, Path().home() / FRITZ_CACHE_DIR / f'192_168_1_15_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ('https://192.168.1.15', 49000, None, FRITZ_CACHE_FORMAT_JSON, Path().home() / FRITZ_CACHE_DIR / f'192_168_1_15_cache.{FRITZ_CACHE_JSON_SUFFIX}'), ] ) def test_get_cache_path(address, port, cache_directory, cache_format, expected_result): # port parameter intentionally unused mock = SimpleNamespace(address=address, port=port) result = FritzConnection._get_cache_path(mock, cache_directory, cache_format) assert result == expected_result def test_invalide_cache_format(): mock = SimpleNamespace(address='192.168.178.1', port=49000) with pytest.raises(FritzConnectionException): _ = FritzConnection._get_cache_path(mock, None, 'weird') @pytest.mark.parametrize( "file_name, cache_format", [ ("description.json", FRITZ_CACHE_FORMAT_JSON), ("description.pcl", FRITZ_CACHE_FORMAT_PICKLE), ] ) def test_load_api_from_cache(file_name, cache_format, datadir): """ Load the api from a cache file and check whether all known services are available. """ os.chdir(datadir) mock = SimpleNamespace(device_manager=DeviceManager()) FritzConnection._load_api_from_cache(mock, file_name, cache_format) with open("description_service_names.txt") as fobj: service_names = list(map(str.strip, fobj)) known_services = mock.device_manager.services.keys() # check for same number of services: assert len(known_services) == len(service_names) # check for same service names: for name in service_names: assert name in known_services @pytest.mark.parametrize( "file_name, cache_format", [ ("description.json", FRITZ_CACHE_FORMAT_JSON), ("description.pcl", FRITZ_CACHE_FORMAT_PICKLE), ] ) def test_write_api_to_cache(file_name, cache_format, datadir): """ Tests writing the api data. For writing there must be some data first. If the test `test_load_api_from_cache` succeeds, the data can safely loaded to a FritzConnection mock object. The data are then exported to a file and loaded again to another FritzConnection mock object. Then the Decription objects are compared. """ os.chdir(datadir) # 1. load the api data mock = SimpleNamespace(device_manager=DeviceManager()) FritzConnection._load_api_from_cache(mock, file_name, cache_format) # 2. save the api data cache_filename = f"x_tmp_cache_{file_name}" cache_file = Path(cache_filename) # TODO: (potentially) # code for Python >= 3.8: # cache_file.unlink(missing_ok=True) # in case of artefacts # code for Python < 3.8: try: cache_file.unlink() except FileNotFoundError: pass # ignore FritzConnection._write_api_to_cache(mock, cache_filename, cache_format) assert cache_file.exists() is True # 3. read the api data to another mock other_mock = SimpleNamespace(device_manager=DeviceManager()) FritzConnection._load_api_from_cache(other_mock, cache_filename, cache_format) # 4. the Descriptions are serializable and therefore comparable objects: for desc1, desc2 in zip( mock.device_manager.descriptions, other_mock.device_manager.descriptions ): assert desc1 == desc2 # clean up cache_file.unlink() assert cache_file.exists() is False fritzconnection-1.15.0/fritzconnection/tests/test_fritzhomeauto.py000066400000000000000000000072731501211554500257150ustar00rootroot00000000000000 from ..lib.fritzhomeauto import HomeAutomationDevice # take some real data from a switch DEVICE_INFORMATION = { 'NewAIN': '11657 0240192', 'NewDeviceId': 16, 'NewFunctionBitMask': 35712, 'NewFirmwareVersion': '04.25', 'NewManufacturer': 'AVM', 'NewProductName': 'FRITZ!DECT 210', 'NewDeviceName': 'FRITZ!DECT 210 #1', 'NewPresent': 'CONNECTED', 'NewMultimeterIsEnabled': 'ENABLED', 'NewMultimeterIsValid': 'VALID', 'NewMultimeterPower': 0, 'NewMultimeterEnergy': 16659, 'NewTemperatureIsEnabled': 'ENABLED', 'NewTemperatureIsValid': 'VALID', 'NewTemperatureCelsius': 195, 'NewTemperatureOffset': 0, 'NewSwitchIsEnabled': 'ENABLED', 'NewSwitchIsValid': 'VALID', 'NewSwitchState': 'OFF', 'NewSwitchMode': 'AUTO', 'NewSwitchLock': False, 'NewHkrIsEnabled': 'DISABLED', 'NewHkrIsValid': 'INVALID', 'NewHkrIsTemperature': 0, 'NewHkrSetVentilStatus': 'CLOSED', 'NewHkrSetTemperature': 0, 'NewHkrReduceVentilStatus': 'CLOSED', 'NewHkrReduceTemperature': 0, 'NewHkrComfortVentilStatus': 'CLOSED', 'NewHkrComfortTemperature': 0 } BASICDEVICESTATS_RESPONSE_FILENAME = "basicdevicestats_response.txt" def test_homeautomation_device_properties(): """ Test whether a switch provides a property of a switch, but not other properties. A switch as 'FRITZ!DECT 210' is - an energy sensor - a temperature sensor - pluggable - and has a microphone """ dp = HomeAutomationDevice(None, DEVICE_INFORMATION) assert dp.is_han_fun_unit is False assert dp.is_bulb is False assert dp.is_alarm_sensor is False assert dp.is_avm_button is False assert dp.is_radiator_control is False assert dp.is_energy_sensor is True assert dp.is_temperature_sensor is True assert dp.is_pluggable is True assert dp.is_avm_dect_repeater is False assert dp.is_microphone is True assert dp.is_switchable is True assert dp.is_adjustable is False assert dp.is_color_bulb is False assert dp.is_blind is False assert dp.is_humidity_sensor is False def test_homeautomation_device_properties_with_ain(): """ Provides an additional ain to the one already in DEVICE_INFORMATION. The one in DEVICE_INFORMATION should be preserved. """ original_ain = DEVICE_INFORMATION['NewAIN'] other_ain = '00000 1111111' dp = HomeAutomationDevice(None, DEVICE_INFORMATION , identifier=other_ain) assert dp.identifier == original_ain def test_homeautomation_device_properties_without_ain(): """ Provides an ain because the entry in DEVICE_INFORMATION is missing. """ # don't modify the constant DEVICE_INFORMATION device_information = { k: v for k, v in DEVICE_INFORMATION.items() if k != "NewAIN" } other_ain = '00000 1111111' dp = HomeAutomationDevice(None, device_information , identifier=other_ain) assert dp.identifier == other_ain def test_extract_basicdevicestats_response(datadir): """ Inject some data from a real device with an energy sensor. """ expected_counts = { "temperature": 96, "voltage": 360, "power": 360, "energy": 12 } file = datadir / BASICDEVICESTATS_RESPONSE_FILENAME text = file.read_text(encoding="utf-8") response = { "content-type": "text/xml", "encoding": "charset=utf-8", "content": text.strip() } result = HomeAutomationDevice.extract_basicdevicestats_response(response) for key in ("temperature", "voltage", "power", "energy"): assert key in result count = result[key]['count'] assert count == expected_counts[key] assert count == len(result[key]['data']) fritzconnection-1.15.0/fritzconnection/tests/test_fritzhosts.py000066400000000000000000000064271501211554500252340ustar00rootroot00000000000000import os import pytest from ..core.utils import get_xml_root from ..core.processor import HostStorage @pytest.fixture() def devicehostlist_source(datadir): os.chdir(datadir) return get_xml_root('devicehostlist.xml') @pytest.mark.parametrize( "idx, attribute, expected_value", [ (1, "Index", 1), (1, "IPAddress", "192.168.178.54"), (1, "MACAddress", "F8:4D:89:7C:0A:32"), (1, "Active", True), (1, "HostName", "MacBook"), (1, "InterfaceType", "802.11"), (1, "X_AVM-DE_Port", 0), (1, "X_AVM-DE_Speed", 866), (1, "X_AVM-DE_UpdateAvailable", False), (1, "X_AVM-DE_UpdateSuccessful", "unknown"), (1, "X_AVM-DE_InfoURL", None), (1, "X_AVM-DE_Model", None), (1, "X_AVM-DE_URL", None), (1, "X_AVM-DE_Guest", False), (1, "X_AVM-DE_VPN", False), (1, "X_AVM-DE_WANAccess", "granted"), (1, "X_AVM-DE_Disallow", False), (2, "Index", 2), (2, "IPAddress", "192.168.178.34"), (2, "MACAddress", "C2:39:6F:FB:A3:E8"), (2, "Active", True), (2, "HostName", "fritz.repeater"), (2, "InterfaceType", "Ethernet"), (2, "X_AVM-DE_Port", 3), (2, "X_AVM-DE_Speed", 100), (2, "X_AVM-DE_UpdateAvailable", False), (2, "X_AVM-DE_UpdateSuccessful", "succeeded"), (2, "X_AVM-DE_InfoURL", None), (2, "X_AVM-DE_Model", "FRITZ!Repeater 1200"), (2, "X_AVM-DE_URL", "http://192.168.178.34"), (2, "X_AVM-DE_Guest", False), (2, "X_AVM-DE_VPN", False), (2, "X_AVM-DE_WANAccess", "granted"), (2, "X_AVM-DE_Disallow", False), (3, "Index", 3), (3, "IPAddress", "192.168.178.49"), (3, "MACAddress", "B8:27:EB:D1:DC:06"), (3, "Active", True), (3, "HostName", "raspberrypi"), (3, "InterfaceType", "Ethernet"), (3, "X_AVM-DE_Port", 1), (3, "X_AVM-DE_Speed", 1000), (3, "X_AVM-DE_UpdateAvailable", False), (3, "X_AVM-DE_UpdateSuccessful", "unknown"), (3, "X_AVM-DE_InfoURL", None), (3, "X_AVM-DE_Model", None), (3, "X_AVM-DE_URL", None), (3, "X_AVM-DE_Guest", False), (3, "X_AVM-DE_VPN", False), (3, "X_AVM-DE_WANAccess", "granted"), (3, "X_AVM-DE_Disallow", False), (4, "Index", 4), (4, "IPAddress", "192.168.178.32"), (4, "MACAddress", "B4:CD:27:37:78:E4"), (4, "Active", False), (4, "HostName", "someones-HUAWEI"), (4, "InterfaceType", "802.11"), (4, "X_AVM-DE_Port", 0), (4, "X_AVM-DE_Speed", 0), (4, "X_AVM-DE_UpdateAvailable", False), (4, "X_AVM-DE_UpdateSuccessful", "unknown"), (4, "X_AVM-DE_InfoURL", None), (4, "X_AVM-DE_Model", None), (4, "X_AVM-DE_URL", None), (4, "X_AVM-DE_Guest", False), (4, "X_AVM-DE_VPN", False), (4, "X_AVM-DE_WANAccess", "granted"), (4, "X_AVM-DE_Disallow", False), ]) def test_readhostlist(idx, attribute, expected_value, devicehostlist_source): """ Check for node-extraction and type conversion. """ storage = HostStorage(devicehostlist_source) attrs = storage.hosts_attributes[idx-1] # list is sorted but host-index is 1 based assert attrs[attribute] == expected_value fritzconnection-1.15.0/fritzconnection/tests/test_fritzmonitor.py000066400000000000000000000276751501211554500255730ustar00rootroot00000000000000import queue import socket import threading import time import pytest from ..core.fritzmonitor import FritzMonitor, EventReporter class MockSocket: """ A socket dummy to simulate receiving data and optional timeouts. """ def __init__(self, mock_data=None, timeout=None, raise_connect_timeout=False): self.mock_data = mock_data self.timeout = timeout self.raise_connect_timeout = raise_connect_timeout def connect(self, *args): if self.raise_connect_timeout: raise socket.timeout("mock failed socket.connect") def close(self): pass def recv(self, chunk_size=None): if not self.mock_data: if self.timeout: time.sleep(self.timeout) raise socket.timeout("mock timeout") if chunk_size is None: chunk = self.mock_data.encode("utf-8") else: chunk = self.mock_data[:chunk_size] self.mock_data = self.mock_data[chunk_size:] return chunk.encode("utf-8") class MockReconnectSocket(MockSocket): """ Dummy socket to simulate a single reconnect. """ def __init__(self, mock_data=None): self.data_provider = self._returner(mock_data) self.connect_called_num = 0 def connect(self, *args): self.connect_called_num += 1 def recv(self, chuck_size=None): try: data = next(self.data_provider) except StopIteration: data = " " return data.encode("utf-8") @staticmethod def _returner(mock_data): for data in mock_data: yield data class MockReconnectFailSocket(MockReconnectSocket): """ Dummy socket to simulate multiple faild reconnections. """ def __init__(self, mock_data=None, timeouts=0): super().__init__(mock_data) self._connector = self.connector(timeouts) def connect(self, *args): super().connect(*args) if not next(self._connector): raise socket.timeout("mock reconnect timeout") @staticmethod def connector(timeouts): yield True for _ in range(timeouts): yield False while True: yield True def test_init_fritzmonitor(): fm = FritzMonitor() assert fm.monitor_thread is None assert fm.stop_flag.is_set() is False @pytest.mark.parametrize( "data, expected", [ ("some data", None), ("some_data\nmore_data", "some_data"), ("some\nmore\ndata", "some more"), ("2019;10\n11:30\ncall\n123\nmore", "2019;10 11:30 call 123"), ], ) def test_event_reporter(data, expected): q = queue.Queue() ep = EventReporter(q) ep.add(data) if expected is None: # no data should be in the queue assert pytest.raises(queue.Empty, q.get_nowait) else: for event in expected.split(): item = q.get_nowait() assert item == event def test_start_stop(): mock_socket = MockSocket(timeout=0.01) fm = FritzMonitor() assert fm.monitor_thread is None fm.start(sock=mock_socket) assert fm.monitor_thread is not None assert fm.monitor_thread.is_alive() is True thread = fm.monitor_thread fm.stop() assert thread.is_alive() is False assert fm.monitor_thread is None def test_start_stop_properties(): mock_socket = MockSocket(timeout=0.01) fm = FritzMonitor() assert fm.has_monitor_thread is False assert fm.is_alive is False _ = fm.start(sock=mock_socket) assert fm.has_monitor_thread is True assert fm.is_alive is True fm.stop() assert fm.has_monitor_thread is False assert fm.is_alive is False def test_queue_and_threading_instances(): mock_socket = MockSocket(timeout=0.01) fm = FritzMonitor() event_queue = fm.start(sock=mock_socket) assert isinstance(event_queue, queue.Queue) assert isinstance(fm.monitor_thread, threading.Thread) fm.stop() def test_start_twice(): """ It is a failure to start a running instance again. """ mock_socket = MockSocket(timeout=0.01) fm = FritzMonitor() fm.start(sock=mock_socket) with pytest.raises(RuntimeError): # start running instance again: should raise a RuntimeError fm.start(sock=mock_socket) fm.stop() # but starting now again should work: fm.start(sock=mock_socket) fm.stop() def test_failed_connection(): mock_socket = MockSocket(raise_connect_timeout=True) fm = FritzMonitor() pytest.raises(OSError, fm.start, sock=mock_socket) @pytest.mark.parametrize( "mock_data, chunk_size, expected_events", [ ("simple string of words\n", None, "simple string of words"), ("event;call\nnumber\n12345\n", None, "event;call|number|12345"), ( "CALL;20201031;12;34\nINC;20-10-31;09;76\n", None, "CALL;20201031;12;34|INC;20-10-31;09;76", ), ("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", None, "1|2|3|4|5|6|7|8|9|10|11"), ("simple string of words\n", 2048, "simple string of words"), ("event;call\nnumber\n12345\n", 2048, "event;call|number|12345"), ( "CALL;20201031;12;34\nINC;20-10-31;09;76\n", 2048, "CALL;20201031;12;34|INC;20-10-31;09;76", ), ("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", 2048, "1|2|3|4|5|6|7|8|9|10|11"), ("simple string of words\n", 20, "simple string of words"), ("event;call\nnumber\n12345\n", 20, "event;call|number|12345"), ( "CALL;20201031;12;34\nINC;20-10-31;09;76\n", 20, "CALL;20201031;12;34|INC;20-10-31;09;76", ), ("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", 20, "1|2|3|4|5|6|7|8|9|10|11"), ("simple string of words\n", 2, "simple string of words"), ("event;call\nnumber\n12345\n", 2, "event;call|number|12345"), ( "CALL;20201031;12;34\nINC;20-10-31;09;76\n", 2, "CALL;20201031;12;34|INC;20-10-31;09;76", ), ("1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", 2, "1|2|3|4|5|6|7|8|9|10|11"), ], ) def test_get_events(mock_data, chunk_size, expected_events): mock_socket = MockSocket(mock_data=mock_data, timeout=0.01) fm = FritzMonitor() event_queue = fm.start(sock=mock_socket) thread = fm.monitor_thread received_event_num = 0 for n, expected_event in enumerate(expected_events.split("|"), start=1): try: assert event_queue.get(timeout=0.1) == expected_event received_event_num += 1 except queue.Empty: pass # check if alle expected events have been received assert received_event_num == n fm.stop() assert thread.is_alive() is False def test_reconnect(): data = ["first\n", "", "second\n"] mock_socket = MockReconnectSocket(data) fm = FritzMonitor() event_queue = fm.start(sock=mock_socket, reconnect_delay=0.001) for expected in [data[0], data[2]]: # should not raise _queue.Empty: assert event_queue.get(timeout=0.1) == expected.strip() fm.stop() assert mock_socket.connect_called_num == 2 @pytest.mark.parametrize( "timeouts, tries, expected_result", [ (0, 0, True), (0, 1, True), (1, 1, False), (1, 2, True), (4, 5, True), (5, 5, False), (6, 5, False), ], ) def test_MockReconnectFailSocket(timeouts, tries, expected_result): """ Internal test to check whether the MockReconnectFailSocket class works as expected. """ sock = MockReconnectFailSocket(timeouts=timeouts) assert sock.connect_called_num == 0 sock.connect() assert sock.connect_called_num == 1 result = True # got connection for cycle in range(tries): try: sock.connect() except OSError: result = False else: result = True break finally: assert ( sock.connect_called_num == cycle + 2 ) # cycle is zero based plus initional connection assert result == expected_result @pytest.mark.parametrize( "timeouts", list(range(6)), ) def test_get_connected_socket(timeouts): socket = MockReconnectFailSocket(timeouts=timeouts) fm = FritzMonitor() fm.mock_socket = socket s = fm._get_connected_socket() # make initional connection assert s is socket for _ in range(timeouts): with pytest.raises(OSError): fm._get_connected_socket() s = fm._get_connected_socket() assert s is socket @pytest.mark.parametrize( "timeouts, tries, expected_result", [ (0, 0, None), (0, 1, True), (1, 0, None), (1, 1, None), (1, 2, True), (4, 5, True), (5, 5, None), (6, 5, None), ], ) def test_reconnect_socket(timeouts, tries, expected_result): mock_socket = MockReconnectFailSocket(timeouts=timeouts) fm = FritzMonitor() fm.mock_socket = mock_socket _ = fm._get_connected_socket() # make initional connection result = fm._reconnect_socket( max_reconnect_delay=0.001, reconnect_tries=tries ) if expected_result is None: assert result is expected_result else: assert result is mock_socket def test_shut_down_monitor_thread(): data = ["first_block\n", "second_block\n", ""] mock_socket = MockReconnectFailSocket(data, timeouts=1) fm = FritzMonitor() q = fm.start(sock=mock_socket, reconnect_delay=0.001, reconnect_tries=0) for d in data[:-1]: time.sleep(0.1) value = q.get(timeout=0.1) assert value == d.strip() assert fm.is_alive is False assert fm.has_monitor_thread is False @pytest.mark.parametrize( "data, timeouts, tries, success", [ (["first\n", "second\n"], 0, 0, True), (["first\n", "", "second\n"], 1, 0, False), (["first\n", "", "second\n"], 0, 1, True), (["first\n", "", "second\n"], 1, 1, False), (["first\n", "", "second\n"], 1, 2, True), # default for tries: 5 (["first\n", "", "second\n"], 3, 5, True), (["first\n", "", "second\n"], 4, 5, True), (["first\n", "", "second\n"], 5, 5, False), ], ) def test_terminate_thread_on_failed_reconnection( data, timeouts, tries, success ): """ Check for thread-termination in case reconnection fails. If the tries are lower than the timeouts, the the start of the monitor has failed and the Thread must terminate itself. """ mock_socket = MockReconnectFailSocket(data, timeouts=timeouts) fm = FritzMonitor() fm.start(sock=mock_socket, reconnect_delay=0.001, reconnect_tries=tries) # give thread some time: time.sleep(0.01) if success: assert fm.is_alive is True else: assert fm.is_alive is False assert fm.monitor_thread is None fm.stop() def test_restart_failed_monitor(): """ Check whether a fritzmonitor instance with a lost connection can get started again. Starting the same instance twice does (and should) not work. See test_start_twice(). But after a failed reconnect (a lost connection) the same instance without calling stop() """ socket = MockReconnectFailSocket( mock_data=["first\n", "", "second\n"], timeouts=16 ) # just some timeouts fm = FritzMonitor() fm.start( sock=socket, reconnect_delay=0.001, reconnect_tries=5 ) # set default explicit for clarity # give socket some time to lose connection: time.sleep(0.01) assert fm.is_alive is False assert fm.stop_flag.is_set() is False # dont' call stop here! # fm.stop() socket = MockSocket(timeout=0.01) # socket not losing connection # should not trigger a RuntimeError fm.start( sock=socket, reconnect_delay=0.001, reconnect_tries=5 ) # set default explicit for clarity assert fm.is_alive is True fm.stop() def test_context_manager(): sock = MockSocket(timeout=0.01) with FritzMonitor() as fm: fm.start(sock=sock) assert fm.is_alive is True assert fm.is_alive is False fritzconnection-1.15.0/fritzconnection/tests/test_fritztools.py000066400000000000000000000120751501211554500252300ustar00rootroot00000000000000import pytest from ..lib.fritztools import ( ArgumentNamespace, byte_formatter, format_num, ) @pytest.mark.parametrize( "value, result, dimension", [ (1, 1.0, 'B'), (123, 123.0, 'B'), (1230, 1.230, 'KB'), (12345, 12.345, 'KB'), (242981246, 242.981246, 'MB'), (24298124612, 24.298124612, 'GB'), (2429812461200, 2.4298124612, 'TB'), (42e3, 42.0, 'KB'), (42e6, 42.0, 'MB'), (42e9, 42.0, 'GB'), (42e12, 42.0, 'TB'), (42e15, 42.0, 'PB'), (42e18, 42000.0, 'PB'), (1.0, 1.0, 'B'), (0.1, 0, 'B'), (0.01, 0, 'B'), (0.001, 0, 'B'), (0, 0, 'B'), (-10, 10, 'B'), ] ) def test_byte_formatter(value, result, dimension): num, dim = byte_formatter(value) assert num == result assert dim == dimension @pytest.mark.parametrize( "num, formated_num", [ (300, '300.0 B'), (2000, '2.0 KB'), (3500, '3.5 KB'), (32500, '32.5 KB'), (242911246, '242.9 MB'), (242981246, '243.0 MB'), (45e6, '45.0 MB'), (45e9, '45.0 GB'), (45e12, '45.0 TB'), (45e15, '45.0 PB'), (45e18, '45000.0 PB'), ] ) def test_format_num(num, formated_num): assert formated_num == format_num(num) def test_format_num_bits(): result = format_num(1234, unit='bits') assert result == '1.2 KBit' def test_argument_namespace(): source = { 'NewManufacturerName': 'AVM', 'NewManufacturerOUI': '00040E', 'NewModelName': 'FRITZ!Box 7590', 'NewDescription': 'FRITZ!Box 7590 154.07.29', 'NewProductClass': 'AVMFB7590', 'NewSerialNumber': '989BCB2B93B0', 'NewSoftwareVersion': '154.07.29', 'NewHardwareVersion': 'FRITZ!Box 7590', 'NewSpecVersion': '1.0', 'NewProvisioningCode': '000.044.004.000', 'NewUpTime': 9516949, 'NewDeviceLog': 'long string here ...' } mapping = { "serial_number": "NewSerialNumber", "model_name": "NewModelName", } info = ArgumentNamespace(source, mapping) assert info.serial_number == '989BCB2B93B0' assert info['model_name'] == 'FRITZ!Box 7590' @pytest.mark.parametrize( "name, expected_result", [ ("description", "description"), ("Description", "description"), ("ModelName", "model_name"), ("NewUpTime", "new_up_time"), ("new_up_time", "new_up_time"), ("NewManufacturerOUI", "new_manufacturer_oui"), ] ) def test_argument_namespace_rewrite(name, expected_result): result = ArgumentNamespace.rewrite_argument(name, suppress_new=False) assert result == expected_result @pytest.mark.parametrize( "name, expected_result", [ ("NewUpTime", "up_time"), ("UpTime", "up_time"), ("upTime", "up_time"), ("up_time", "up_time"), ("uptime", "uptime"), ("newuptime", "newuptime"), ("Newuptime", "newuptime"), ("New_uptime", "uptime"), ("NewManufacturerOUI", "manufacturer_oui"), ] ) def test_argument_namespace_rewrite_no_new(name, expected_result): result = ArgumentNamespace.rewrite_argument(name) assert result == expected_result @pytest.fixture() def avm_source(): source = { 'NewModelName': 'FRITZ!Box 7590', 'NewDescription': 'FRITZ!Box 7590 154.07.29', 'NewProductClass': 'AVMFB7590', 'NewSerialNumber': '989BCB2B93B0', } return source def test_argument_namespace_no_mapping(avm_source): """ In case of a missing mapping, all values from source should get transfered to the ArgumentNamespace and the key should get converted to snake_case. """ info = ArgumentNamespace(avm_source) assert info.model_name == 'FRITZ!Box 7590' assert info['model_name'] == 'FRITZ!Box 7590' def test_argument_namespace_no_mapping_no_suppress(avm_source): """ In case of a missing mapping, all values from source should get transfered to the ArgumentNamespace and the key should get converted to snake_case. """ info = ArgumentNamespace(avm_source, suppress_new=False) assert info.new_serial_number == '989BCB2B93B0' assert info['new_serial_number'] == '989BCB2B93B0' assert info.new_model_name == 'FRITZ!Box 7590' assert info['new_model_name'] == 'FRITZ!Box 7590' def test_argument_namespace_has_len(avm_source): info = ArgumentNamespace(avm_source) assert len(info) == len(avm_source) def test_argument_namespace_assignment(avm_source): info = ArgumentNamespace(avm_source) info.new_value = 42 assert info.new_value == 42 assert len(info) == len(avm_source) + 1 info["minus"] = -3 assert info["minus"] == -3 assert info.minus == -3 assert len(info) == len(avm_source) + 2 def test_argument_namespace_extract(avm_source): extract = "NewModelName", "NewProductClass" info = ArgumentNamespace(avm_source, extract=extract) assert len(info) == len(extract) assert info.model_name == avm_source['NewModelName'] assert info.product_class == avm_source['NewProductClass'] fritzconnection-1.15.0/fritzconnection/tests/test_fritzwlan.py000066400000000000000000000110621501211554500250240ustar00rootroot00000000000000""" tests for qr-code creation """ import io import os import tempfile import pytest try: import cv2 import segno.helpers except ImportError: OPENCV_NOT_AVAILABLE = True else: OPENCV_NOT_AVAILABLE = False from fritzconnection.lib.fritzwlan import _get_wifi_qr_code as get_wifi_qr_code @pytest.mark.skipif(OPENCV_NOT_AVAILABLE, reason="requires opencv") def test_tools(): """ basic test whether opencv is able to read the output provided by segno. The tempfile is needed because opencv can not read from a file-like object but needs a path to the image-file. """ ssid = 'xenon' password = 'the_strange_one' security = 'WPA' kind = 'png' # create qr-code and store it in a persistent temporary file stream = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix=f'.{kind}') fname = stream.name qr_code = segno.helpers.make_wifi( ssid=ssid, password=password, security=security, hidden=False ) qr_code.save(out=stream, kind=kind, scale=4) stream.close() assert os.path.exists(fname) is True # test qr-code reading expected_result = f'WIFI:T:{security};S:{ssid};P:{password};;' img = cv2.imread(fname) detector = cv2.QRCodeDetector() result, _, _ = detector.detectAndDecode(img) assert result == expected_result # remove the tempfile os.unlink(fname) assert os.path.exists(fname) is False def write_stream_to_tempfile(stream, kind='png'): """ Helper function to store a segno stream in a persistent tempfile. Takes the stream (BytesIO) and returns the filepath (as string). """ fobj = tempfile.NamedTemporaryFile(mode='wb', delete=False, suffix=f'.{kind}') fname = fobj.name fobj.write(stream.read()) fobj.close() return fname def get_content_from_qr_file(fname): """Helper function for qr-code reading.""" img = cv2.imread(fname) detector = cv2.QRCodeDetector() result, _, _ = detector.detectAndDecode(img) return result @pytest.mark.skipif(OPENCV_NOT_AVAILABLE, reason="requires opencv") def test_helper_functions(): ssid = 'xenon' password = 'another_strange_one' security = 'WPA' kind = 'png' stream = io.BytesIO() qr_code = segno.helpers.make_wifi( ssid=ssid, password=password, security=security, hidden=False ) qr_code.save(out=stream, kind=kind, scale=4) stream.seek(0) # delegate stream to helper: fname = write_stream_to_tempfile(stream) # file must exist: assert os.path.exists(fname) is True # read qr-code: result = get_content_from_qr_file(fname) # check and clean up: expected_result = f'WIFI:T:{security};S:{ssid};P:{password};;' assert result == expected_result os.unlink(fname) assert os.path.exists(fname) is False class WLANConfigMock: """ Mocking class to provide the result of a WLANConfiguration.get_info() call, provide a get_password() method and a ssid attribute. All returned value must be part of the mock_data dictionary. The values in the dictionary are all strings. """ def __init__(self, mock_data): self.mock_data = mock_data def get_info(self): return self.mock_data def get_password(self): # original from the action "GetSecurityKeys" return self.mock_data["NewKeyPassphrase"] @property def ssid(self): return self.mock_data["NewSSID"] @pytest.mark.skipif(OPENCV_NOT_AVAILABLE, reason="requires opencv") @pytest.mark.parametrize( "current_beacontype, security, expected_security", [ ('11i', None, 'WPA'), ('11i', '', 'WPA'), ('11i', 'WPA3', 'WPA3'), ('WPAand11i', None, 'WPA'), ('11iandWPA3', None, 'WPA'), ('Basic', None, 'WEP'), ('None', None, 'nopass'), ('OWETrans', None, 'nopass'), ] ) def test_get_wifi_qr_code(current_beacontype, security, expected_security): """ Check for correct qr-code creation depending on the WLAN-settings. """ ssid = "the_wlan_name" password = "the_password" expected_result = f"WIFI:T:{expected_security};S:{ssid};P:{password};;" mock_data = { 'NewBeaconType': current_beacontype, 'NewX_AVM-DE_PossibleBeaconTypes': 'None,11i,WPAand11i,11iandWPA3', 'NewSSID': ssid, 'NewKeyPassphrase': password, } instance = WLANConfigMock(mock_data) stream = get_wifi_qr_code(instance, kind="png", security=security) fname = write_stream_to_tempfile(stream) result = get_content_from_qr_file(fname) os.unlink(fname) # do this asap assert result == expected_result fritzconnection-1.15.0/fritzconnection/tests/test_functional.py000066400000000000000000000075501501211554500251550ustar00rootroot00000000000000""" Running functional tests against a router - if the router is present. """ import pytest from ..core.exceptions import ( FritzConnectionException, FritzServiceError, ) from ..core.fritzconnection import FritzConnection from ..lib.fritzcall import FritzCall from ..lib.fritzhomeauto import FritzHomeAutomation from ..lib.fritzhosts import FritzHosts from ..lib.fritzphonebook import FritzPhonebook from ..lib.fritzstatus import FritzStatus from ..lib.fritzwlan import FritzWLAN TIMEOUT = 2.0 # give older models some time @pytest.fixture(scope="module") def get_fc_instance(): return FritzConnection(timeout=TIMEOUT) @pytest.fixture(scope="module") def get_fc_tls_instance(): return FritzConnection(timeout=TIMEOUT, use_tls=True) @pytest.mark.routertest @pytest.mark.parametrize("use_tls", [False, True]) def test_access_model_name(use_tls): """ Check whether description files are accessible. In this case there is some modelname available (a string). """ fc = FritzConnection(use_tls=use_tls) # on success the modelname should be a string: assert isinstance(fc.modelname, str) @pytest.mark.routertest @pytest.mark.parametrize("use_tls", [False, True]) def test_soap_access(use_tls, get_fc_instance, get_fc_tls_instance): """ Test whether a soap access returns successful. The Service 'DeviceInfo1' with the action 'GetInfo' should be provided by all router models – including repeaters - and provides access to the model name. The service must be accessible without a password. As the model is unknown, the service should be available on all models. In practice that's not the case because routers and repeaters will have different service sets. So this will test a soap-call if """ fc = FritzConnection(use_tls=use_tls) try: info = fc.call_action('DeviceInfo1', 'GetInfo') except FritzConnectionException: # successful call but access not allowed # (password required) # so at least the soap request has worked: assert True except FritzServiceError: # this should not happen with the known product range. # skip this: pass else: # on success the modelname should be a string: assert isinstance(info['NewModelName'], str) try: info = fc.call_action('WANIPConn1', 'GetStatusInfo') except FritzServiceError: # some devices (like repeaters) may not have this service. # skip this: pass else: assert isinstance(info['NewConnectionStatus'], str) # do at least one assert: assert True @pytest.mark.routertest @pytest.mark.parametrize( "cls, use_tls", [ (FritzCall, False), (FritzCall, True), (FritzHomeAutomation, False), (FritzHomeAutomation, True), (FritzHosts, False), (FritzHosts, True), (FritzPhonebook, False), (FritzPhonebook, True), (FritzStatus, False), (FritzStatus, True), (FritzWLAN, False), (FritzWLAN, True), ]) def test_library_api_arguments(cls, use_tls): obj = cls(timeout=TIMEOUT, use_tls=use_tls) # on success the modelname should be a string: assert isinstance(obj.modelname, str) @pytest.mark.routertest @pytest.mark.parametrize( "cls", [ FritzCall, FritzHomeAutomation, FritzHosts, FritzPhonebook, FritzStatus, FritzWLAN ]) def test_init_cls_with_instance(cls, get_fc_instance): obj = cls(fc=get_fc_instance) assert isinstance(obj.modelname, str) @pytest.mark.routertest @pytest.mark.parametrize( "cls", [ FritzCall, FritzHomeAutomation, FritzHosts, FritzPhonebook, FritzStatus, FritzWLAN ]) def test_init_cls_with_tls_instance(cls, get_fc_tls_instance): obj = cls(fc=get_fc_tls_instance) assert isinstance(obj.modelname, str) fritzconnection-1.15.0/fritzconnection/tests/test_logger.py000066400000000000000000000051701501211554500242660ustar00rootroot00000000000000import io import logging import pytest from ..core.logger import ( fritzlogger, activate_local_debug_mode, reset, ) stream = io.StringIO() stream_handler = logging.StreamHandler(stream=stream) formatter = logging.Formatter("%(levelname)s:%(message)s") stream_handler.setFormatter(formatter) def get_last_log_entry(): lines = stream_handler.stream.getvalue().splitlines() if lines: return lines[-1] return '' def expected_log_entry(message): # helper function for formatting return f"{message.upper()}:{message}" def delete_log_entries(): stream_handler.stream.close() stream_handler.stream = io.StringIO() @pytest.mark.parametrize( "message, log_call, should_log", [ ("debug", fritzlogger.debug, False), ("info", fritzlogger.info, True), ("warning", fritzlogger.warning, True), ("error", fritzlogger.error, True), ("critical", fritzlogger.critical, True), ]) def test_default_logging(message, log_call, should_log): fritzlogger.addHandler(stream_handler) delete_log_entries() log_call(message) last_message = get_last_log_entry() if should_log: expected = expected_log_entry(message) else: expected = "" assert last_message == expected def test_local_debug_mode_no_propagate_no_handler(): delete_log_entries() reset() activate_local_debug_mode() message = "debug" fritzlogger.debug(message) # no handler (NullHandler), no propagate: assert get_last_log_entry() == "" def test_local_debug_mode_no_propagate_with_handler(): delete_log_entries() reset() activate_local_debug_mode(handler=stream_handler) message = "debug" fritzlogger.debug(message) assert get_last_log_entry() == expected_log_entry(message) def test_local_debug_mode_no_handler(): delete_log_entries() reset() activate_local_debug_mode(propagate=True) message = "debug" fritzlogger.debug(message) # no handler, but propagate: assert get_last_log_entry() == "" def test_local_debug_mode_no_handler_but_propagate_and_warning(): # if emitted as warning, the message gets logged from the # parent-handlers (in this case root) # in this case the RootLogger needs a handler delete_log_entries() reset() activate_local_debug_mode(propagate=True) message = "warning" fritzlogger.warning(message) assert get_last_log_entry() == "" # provide a handler for root: logging.root.addHandler(stream_handler) fritzlogger.warning(message) assert get_last_log_entry() == expected_log_entry(message) logging.root.removeHandler(stream_handler) fritzconnection-1.15.0/fritzconnection/tests/test_processor.py000066400000000000000000000157441501211554500250360ustar00rootroot00000000000000 import os import pytest from ..core.processor import ( Description, Device, Service, Scpd, ) from ..core.utils import get_xml_root @pytest.fixture() def igddesc_source(datadir): os.chdir(datadir) return get_xml_root('igddesc.xml') @pytest.fixture() def tr64desc_source(datadir): os.chdir(datadir) return get_xml_root('tr64desc.xml') @pytest.fixture() def igdconn_scpd_source(datadir): os.chdir(datadir) return get_xml_root('igdconnSCPD.xml') @pytest.fixture() def scpd_instance(igdconn_scpd_source): return Scpd(igdconn_scpd_source) @pytest.mark.parametrize( "attribute, value", [ ('spec_version', '1.0'), ('device_model_name', 'FRITZ!Box 7590'), ]) def test_igd_description_specversion(attribute, value, igddesc_source): d = Description(igddesc_source) assert d.spec_version == '1.0' @pytest.mark.parametrize( "attribute, value", [ ('deviceType', 'urn:schemas-upnp-org:device:InternetGatewayDevice:1'), ('friendlyName', 'FRITZ!Box 7590'), ('manufacturer', 'AVM Berlin'), ('manufacturerURL', 'http://www.avm.de'), ('modelDescription', 'FRITZ!Box 7590'), ('modelName', 'FRITZ!Box 7590'), ('modelNumber', 'avm'), ('modelURL', 'http://www.avm.de'), ('UDN', 'uuid:75802409-bccb-just-a-test-udn'), ]) def test_igd_device(attribute, value, igddesc_source): d = Description(igddesc_source) device = d.device assert getattr(device, attribute) == value def test_igd_device_services(igddesc_source): # the device should have one service instance in services. d = Description(igddesc_source) services = d.device._services assert len(services) == 1 assert isinstance(services[0], Service) @pytest.mark.parametrize( "attribute, value", [ ('serviceType', 'urn:schemas-any-com:service:Any:1'), ('serviceId', 'urn:any-com:serviceId:any1'), ('controlURL', '/igdupnp/control/any'), ('eventSubURL', '/igdupnp/control/any'), ('SCPDURL', '/any.xml'), ]) def test_igd_device_service(attribute, value, igddesc_source): d = Description(igddesc_source) service = d.device._services[0] assert getattr(service, attribute) == value def test_igd_device_service_name(igddesc_source): """ Every service has a name. First (and only) service of the main device has the name 'any1'. """ d = Description(igddesc_source) service = d.device._services[0] assert service.name == 'any1' def test_igd_device_devices(igddesc_source): # the device should have one device instance in devices. d = Description(igddesc_source) devices = d.device.devices assert len(devices) == 1 assert isinstance(devices[0], Device) def test_idg_nested_services_part1(igddesc_source): """ The main device should have a sub-device with another subdevice. The first sub-device should have a sublist with one service. """ d = Description(igddesc_source) sub_device = d.device.devices[0] assert len(sub_device._services) == 1 def test_idg_nested_services_part2(igddesc_source): """ The main device should have a sub-device with another subdevice. The sub-sub-device should have a sublist with three service. """ d = Description(igddesc_source) sub_device = d.device.devices[0].devices[0] assert len(sub_device._services) == 3 @pytest.mark.parametrize( "name", [ 'WANCommonIFC1', 'WANDSLLinkC1', 'WANIPConn1' ]) def test_igd_description_services(name, igddesc_source): """ Find services by name from nested devices (igddesc.xml) """ d = Description(igddesc_source) service = d.services[name] assert service.name == name @pytest.mark.parametrize( "name", [ 'DeviceInfo1', 'X_AVM-DE_Homeauto1', 'WLANConfiguration1', 'WANCommonInterfaceConfig1', 'WANIPConnection1', ]) def test_tr64_description_services(name, tr64desc_source): """ Find services by name from nested devices (tr64desc.xml) """ d = Description(tr64desc_source) service = d.services[name] assert service.name == name def test_system_version_igd(igddesc_source): d = Description(igddesc_source) assert d.system_version is None def test_system_version_tr64(tr64desc_source): d = Description(tr64desc_source) assert d.system_version == '7.10' def test_system_buildnumber_tr64(tr64desc_source): d = Description(tr64desc_source) assert d.system_buildnumber == '67453' def test_scpd_specversion(scpd_instance): assert scpd_instance.spec_version == '1.0' def test_scpd_actionlist(scpd_instance): # 18 actions are defined by 'igdconnSCPD.xml': assert len(scpd_instance._actions) == 18 def test_scpd_actiondict(scpd_instance): # 18 actions are defined by 'igdconnSCPD.xml': assert len(scpd_instance.actions) == 18 @pytest.mark.parametrize( "name", [ 'SetConnectionType', 'ForceTermination', 'X_AVM_DE_GetIPv6DNSServer' ]) def test_scpd_action_names(name, scpd_instance): # find some action names actions = scpd_instance.actions print(actions) action = actions[name] assert action.name == name @pytest.mark.parametrize( "action_name, argument_name, direction, relatedStateVariable", [ ('GetStatusInfo', 'NewConnectionStatus', 'out', 'ConnectionStatus'), ('GetStatusInfo', 'NewLastConnectionError', 'out', 'LastConnectionError'), ('GetStatusInfo', 'NewUptime', 'out', 'Uptime') ]) def test_scpd_action_argument_names( action_name, argument_name, direction, relatedStateVariable, scpd_instance ): """ Test action arguments """ action = scpd_instance.actions[action_name] argument = action.arguments[argument_name] assert argument.name == argument_name assert argument.direction == direction assert argument.relatedStateVariable == relatedStateVariable def test_scpd_service_state_variables(scpd_instance): # 30 stateVariables are defined by 'igdconnSCPD.xml': assert len(scpd_instance._state_variables) == 30 @pytest.mark.parametrize( "name, data_type, default_value, allowed_values_num", [ ('LastConnectionError', 'string', 'ERROR_NONE', 23), ('AutoDisconnectTime', 'ui4', '0', 0), ]) def test_scpd_service_state_variables_by_name( name, data_type, default_value, allowed_values_num, scpd_instance ): sv = scpd_instance.state_variables[name] assert sv.name == name assert sv.dataType == data_type assert sv.defaultValue == default_value assert len(sv.allowed_values) == allowed_values_num def test_scpd_statevariable_allowed_value(scpd_instance): sv = scpd_instance.state_variables['LastConnectionError'] assert 'ERROR_NO_CARRIER' in sv.allowed_values def test_scpd_statevariable_allowed_range(scpd_instance): sv = scpd_instance.state_variables['Uptime'] allowed_range = sv.allowedValueRange assert allowed_range.minimum == '0' assert allowed_range.maximum == '4294967295' assert allowed_range.step == '1' fritzconnection-1.15.0/fritzconnection/tests/test_serialize.py000066400000000000000000000366601501211554500250060ustar00rootroot00000000000000""" tests for serialization and deserialization data from the processor classes. """ import json from fritzconnection.core.processor import ( Action, Argument, Description, Device, Scpd, Serializer, Service, SpecVersion, StateVariable, SystemVersion, ValueRange, ) # some test data. # data can be anything but take some real data from an existing router: DATA_SPEC_MAJOR_VERSION = "1" DATA_SPEC_MINOR_VERSION = "0" DATA_SYS_MAJOR = "154" DATA_SYS_MINOR = "7" DATA_SYS_PATCH = "29" DATA_SYS_DISPLAY = "154.07.29" DATA_ARGUMENT_NAME = "NewManufacturerName" DATA_ARGUMENT_DIRECTION = "out" DATA_ARGUMENT_RELATEDSTATEVARIABLE = "ManufacturerName" DATA_ACTION_NAME = "GetInfo" DATA_VALUERANGE_MINIMUM = None DATA_VALUERANGE_MAXIMUM = None DATA_VALUERANGE_STEP = "1" # for not having all the default values DATA_STATEVARIABLE_NAME = "LastConnectionError" DATA_STATEVARIABLE_DATATYPE = "string" DATA_STATEVARIABLE_DEFAULTVALUE = "ERROR_NONE" DATA_STATEVARIABLE_ALLOWED_VALUES = ["ERROR_NONE", "ERROR_ISP_TIME_OUT", "ERROR_COMMAND_ABORTED"] DATA_DEVICE_DEVICETYPE = "urn:schemas-upnp-org:device:InternetGatewayDevice:1" DATA_DEVICE_FRIENDLYNAME = "FRITZ!Box 7590" DATA_DEVICE_MANUFACTURER = "AVM Berlin" DATA_DEVICE_MANUFACTURERURL = "http://www.avm.de" DATA_DEVICE_MODELDESCRIPTION = "FRITZ!Box 7590" DATA_DEVICE_MODELNAME = "FRITZ!Box 7590" DATA_DEVICE_MODELNUMBER = "avm" DATA_DEVICE_MODELURL = "http://www.avm.de" DATA_DEVICE_PRESENTATIONURL = "http://fritz.box" DATA_DEVICE_UDN = "uuid:75802409-bccb-40e7-8e6c-989BCB2B93B0" DATA_SERVICE_SERVICETYPE = "urn:dslforum-org:service:DeviceInfo:1" DATA_SERVICE_SERVICEID = "urn:DeviceInfo-com:serviceId:DeviceInfo1" DATA_SERVICE_CONTROLURL = "/upnp/control/deviceinfo" DATA_SERVICE_EVENTSUBURL = "/upnp/control/deviceinfo" DATA_SERVICE_SCPDURL = "/deviceinfoSCPD.xml" JSON_RESULT_TEST_SERIALIZE_SPECVERSION = f"""{{"major": "{DATA_SPEC_MAJOR_VERSION}", "minor": "{DATA_SPEC_MINOR_VERSION}"}}""" JSON_RESULT_TEST_SERIALIZE_SYSTEMVERSION = f"""{{"Buildnumber": null, "Display": "{DATA_SYS_DISPLAY}", "HW": null, "Major": "{DATA_SYS_MAJOR}", "Minor": "{DATA_SYS_MINOR}", "Patch": "{DATA_SYS_PATCH}"}}""" JSON_RESULT_TEST_SERIALIZE_ARGUMENT = f"""{{"direction": "{DATA_ARGUMENT_DIRECTION}", "name": "{DATA_ARGUMENT_NAME}", "relatedStateVariable": "{DATA_ARGUMENT_RELATEDSTATEVARIABLE}"}}""" JSON_RESULT_TEST_SERIALIZE_VALUERANGE = f"""{{"maximum": null, "minimum": null, "step": "{DATA_VALUERANGE_STEP}"}}""" JSON_RESULT_TEST_SERIALIZE_ACTION = f"""{{"name": "{DATA_ACTION_NAME}", "arguments": [{JSON_RESULT_TEST_SERIALIZE_ARGUMENT}, {JSON_RESULT_TEST_SERIALIZE_ARGUMENT}]}}""" # weird but f-strings substitute lists of strings different than json.dumps: JSON_RESULT_TEST_SERIALIZE_STATEVARIABLE = f"""{{"attributes": {{"allowed_values": """ + json.dumps(DATA_STATEVARIABLE_ALLOWED_VALUES) + f""", "dataType": "{DATA_STATEVARIABLE_DATATYPE}", "defaultValue": "{DATA_STATEVARIABLE_DEFAULTVALUE}", "name": "{DATA_STATEVARIABLE_NAME}"}}, "allowedValueRange": {JSON_RESULT_TEST_SERIALIZE_VALUERANGE}}}""" # noqa: F541 JSON_RESULT_TEST_SERIALIZE_SCPD = f"""{{"actions": [{JSON_RESULT_TEST_SERIALIZE_ACTION}, {JSON_RESULT_TEST_SERIALIZE_ACTION}], "specVersion": {JSON_RESULT_TEST_SERIALIZE_SPECVERSION}, "state_variables": [{JSON_RESULT_TEST_SERIALIZE_STATEVARIABLE}, {JSON_RESULT_TEST_SERIALIZE_STATEVARIABLE}]}}""" JSON_RESULT_TEST_SERIALIZE_SERVICE = f"""{{"attributes": {{"SCPDURL": "{DATA_SERVICE_SCPDURL}", "controlURL": "{DATA_SERVICE_CONTROLURL}", "eventSubURL": "{DATA_SERVICE_EVENTSUBURL}", "serviceId": "{DATA_SERVICE_SERVICEID}", "serviceType": "{DATA_SERVICE_SERVICETYPE}"}}, "scpd": {JSON_RESULT_TEST_SERIALIZE_SCPD}}}""" JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC = f"""{{"attributes": {{"UDN": "{DATA_DEVICE_UDN}", "UPC": null, "deviceType": "{DATA_DEVICE_DEVICETYPE}", "friendlyName": "{DATA_DEVICE_FRIENDLYNAME}", "manufacturer": "{DATA_DEVICE_MANUFACTURER}", "manufacturerURL": "{DATA_DEVICE_MANUFACTURERURL}", "modelDescription": "{DATA_DEVICE_MODELDESCRIPTION}", "modelName": "{DATA_DEVICE_MODELNAME}", "modelNumber": "{DATA_DEVICE_MODELNUMBER}", "modelURL": "{DATA_DEVICE_MODELURL}", "presentationURL": "{DATA_DEVICE_PRESENTATIONURL}"}}""" JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC_SERVICE = f""", "services": [{JSON_RESULT_TEST_SERIALIZE_SERVICE}, {JSON_RESULT_TEST_SERIALIZE_SERVICE}]}}""" JSON_RESULT_TEST_SERIALIZE_DEVICE = JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC + f""", "devices": [], "services": []}}""" # noqa: F541 JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES = JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC + ', "devices": []' + JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC_SERVICE # subdevices don't provide services and further devices JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES_AND_SUBDEVICES = JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC + f""", "devices": [{JSON_RESULT_TEST_SERIALIZE_DEVICE}, {JSON_RESULT_TEST_SERIALIZE_DEVICE}]""" + JSON_RESULT_TEST_SERIALIZE_DEVICE_BASIC_SERVICE JSON_RESULT_TEST_SERIALIZE_DESCRIPTION = f"""{{"device": {JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES_AND_SUBDEVICES}, "specVersion": {JSON_RESULT_TEST_SERIALIZE_SPECVERSION}, "systemVersion": {JSON_RESULT_TEST_SERIALIZE_SYSTEMVERSION}}}""" # JSON_RESULT_TEST_SERIALIZE_DESCRIPTION = f"""{{"systemVersion": {JSON_RESULT_TEST_SERIALIZE_SYSTEMVERSION}}}""" def make_spec_version(): spec_version = SpecVersion() spec_version.major = DATA_SPEC_MAJOR_VERSION spec_version.minor = DATA_SPEC_MINOR_VERSION return spec_version def make_system_version(): system_version = SystemVersion() system_version.HW = None system_version.Major = DATA_SYS_MAJOR system_version.Minor = DATA_SYS_MINOR system_version.Patch = DATA_SYS_PATCH system_version.Buildnumber = None system_version.Display = DATA_SYS_DISPLAY return system_version def make_argument(): argument = Argument() argument.name = DATA_ARGUMENT_NAME argument.direction = DATA_ARGUMENT_DIRECTION argument.relatedStateVariable = DATA_ARGUMENT_RELATEDSTATEVARIABLE return argument def make_valuerange(): valuerange = ValueRange() valuerange.minimum = DATA_VALUERANGE_MINIMUM valuerange.maximum = DATA_VALUERANGE_MAXIMUM valuerange.step = DATA_VALUERANGE_STEP return valuerange def make_action(): # an Action has a name and a list of arguments. # make an Action with two arguments. action = Action() action.name = DATA_ACTION_NAME action._arguments.append(make_argument()) action._arguments.append(make_argument()) return action def make_statevariable(): # a StateVariable has a name like 'WANAccessType' # a dataType like 'string' or 'ui2' # a defaultValue # a list of strings of allowed_values like 'DSL', 'Cable' etc. # an allowedValueRange # Not all Atrributes must be defined. statevariable = StateVariable() statevariable.name = DATA_STATEVARIABLE_NAME statevariable.dataType = DATA_STATEVARIABLE_DATATYPE statevariable.defaultValue = DATA_STATEVARIABLE_DEFAULTVALUE statevariable.allowed_values = DATA_STATEVARIABLE_ALLOWED_VALUES statevariable.allowedValueRange = make_valuerange() return statevariable def make_scpd(): # a service control point definition has a list of Actions, # a list of StateVariables and a SpecVersion. scpd = Scpd(root=[]) scpd._actions = [make_action(), make_action()] scpd._state_variables = [make_statevariable(), make_statevariable()] scpd.specVersion = make_spec_version() return scpd def make_service(): service = Service() service._scpd = make_scpd() service.serviceType = DATA_SERVICE_SERVICETYPE service.serviceId = DATA_SERVICE_SERVICEID service.controlURL = DATA_SERVICE_CONTROLURL service.eventSubURL = DATA_SERVICE_EVENTSUBURL service.SCPDURL = DATA_SERVICE_SCPDURL return service def make_device(with_services=True, with_subdevices=True): device = Device() device.deviceType = DATA_DEVICE_DEVICETYPE device.friendlyName = DATA_DEVICE_FRIENDLYNAME device.manufacturer = DATA_DEVICE_MANUFACTURER device.manufacturerURL = DATA_DEVICE_MANUFACTURERURL device.modelDescription = DATA_DEVICE_MODELDESCRIPTION device.modelName = DATA_DEVICE_MODELNAME device.modelNumber = DATA_DEVICE_MODELNUMBER device.modelURL = DATA_DEVICE_MODELURL device.UDN = DATA_DEVICE_UDN device.UPC = None device.presentationURL = DATA_DEVICE_PRESENTATIONURL if with_services: device._services = [make_service(), make_service()] if with_subdevices: device.devices = [ make_device(with_services=False, with_subdevices=False), make_device(with_services=False, with_subdevices=False) ] return device def make_description(): description = Description(root=[]) description.device = make_device() description.specVersion = make_spec_version() description.systemVersion = make_system_version() return description class Check(Serializer): """ Simple Subclass for Serializer for testing. """ def __init__(self, one=1, two=2): self.one = one self.two = two def test_serializer(): """ Test the Serializer superclass. """ check = Check() data = check.serialize() one_three = Check(one=3) assert check != one_three one_three.deserialize(data) assert check == one_three def test_serializer_02(): """ Test for same set of attributes. """ small = Check() big = Check() assert small == big assert big == small big.three = 3 assert small != big assert big != small def test_serialize_exclude(): """ Test Serializer superclass with exclude argument """ check = Check() data = check.serialize(exclude=['one']) one_three = Check(one=3) assert check != one_three one_three.deserialize(data) assert check != one_three one_three.one = 1 assert check == one_three def test_serialize_spec_version(): """ Serialize a SpecVersion instance to json. """ spec_version = make_spec_version() result = spec_version.serialize() json_result = json.dumps(result) assert json_result == JSON_RESULT_TEST_SERIALIZE_SPECVERSION def test_deserialize_spec_version(): """ Deserialize a SpecVersion instance from json. """ data = json.loads(JSON_RESULT_TEST_SERIALIZE_SPECVERSION) sv = SpecVersion() sv.deserialize(data) assert sv == make_spec_version() def test_serialize_system_version(): """ Serialize a SystemVersion instance to json. """ system_version = make_system_version() result = system_version.serialize() json_result = json.dumps(result) assert json_result == JSON_RESULT_TEST_SERIALIZE_SYSTEMVERSION def test_deserialize_system_version(): """ Deserialize a SystemVersion instance from json. """ system_version = make_system_version() data = json.loads(JSON_RESULT_TEST_SERIALIZE_SYSTEMVERSION) sv = SystemVersion() assert sv != system_version sv.deserialize(data) assert sv == system_version def test_serialize_argument(): """Serialize an Argument to json.""" argument = make_argument() result = argument.serialize() json_result = json.dumps(result) assert json_result == JSON_RESULT_TEST_SERIALIZE_ARGUMENT def test_deserialize_argument(): """Deserialize an Argument from json.""" argument = make_argument() data = json.loads(JSON_RESULT_TEST_SERIALIZE_ARGUMENT) a = Argument() assert a != argument a.deserialize(data) assert a == argument def test_serialize_valuerange(): """Serialize a ValueRange to json.""" valuerange = make_valuerange() result = json.dumps(valuerange.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_VALUERANGE def test_deserialize_valuerange(): """Deserialize a ValueRange from json.""" valuerange = make_valuerange() vr = ValueRange() assert vr != valuerange vr.deserialize(json.loads(JSON_RESULT_TEST_SERIALIZE_VALUERANGE)) assert vr == valuerange def test_serialize_action(): """ Serialize an Action with a name and two Argument instances in _arguments """ action = make_action() result = json.dumps(action.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_ACTION def test_deserialize_action(): """ Deerialize an Action with a name and two Argument instances in _arguments from json. """ action = make_action() ac = Action() ac.deserialize(json.loads(JSON_RESULT_TEST_SERIALIZE_ACTION)) assert ac == action def test_serialize_statevariable(): statevariable = make_statevariable() result = json.dumps(statevariable.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_STATEVARIABLE def test_deserialize_statevariable(): statevariable = make_statevariable() sv = StateVariable() assert sv != statevariable sv.deserialize(json.loads(JSON_RESULT_TEST_SERIALIZE_STATEVARIABLE)) assert sv == statevariable def test_serialize_scpd(): scpd = make_scpd() result = json.dumps(scpd.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_SCPD def test_deserialize_scpd(): scpd = make_scpd() s = Scpd(root=[]) s.deserialize(json.loads(JSON_RESULT_TEST_SERIALIZE_SCPD)) assert s == scpd def test_serialize_service(): """ Serialize a Service Instance. """ service = make_service() result = json.dumps(service.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_SERVICE def test_deserialize_service(): """ Deserialize a Service Instance. """ service = make_service() data = json.loads(JSON_RESULT_TEST_SERIALIZE_SERVICE) s = Service() s.deserialize(data) assert s == service def test_serialize_device(): device = make_device(with_services=False, with_subdevices=False) result = json.dumps(device.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_DEVICE def test_deserialize_device(): device = make_device(with_services=False, with_subdevices=False) d = Device() d.deserialize(json.loads(JSON_RESULT_TEST_SERIALIZE_DEVICE)) assert d == device def test_serialize_device_with_services(): device = make_device(with_services=True, with_subdevices=False) result = json.dumps(device.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES def test_deserialize_device_with_services(): device = make_device(with_services=True, with_subdevices=False) d = Device() d.deserialize(json.loads(JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES)) assert d == device def test_serialize_device_with_services_and_subdevices(): device = make_device(with_services=True, with_subdevices=True) result = json.dumps(device.serialize()) assert ( result == JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES_AND_SUBDEVICES ) def test_deserialize_device_with_services_and_subdevices(): device = make_device(with_services=True, with_subdevices=True) d = Device() d.deserialize( json.loads( JSON_RESULT_TEST_SERIALIZE_DEVICE_WITH_SERVICES_AND_SUBDEVICES ) ) assert d == device def test_serialize_description(): description = make_description() result = json.dumps(description.serialize()) assert result == JSON_RESULT_TEST_SERIALIZE_DESCRIPTION def test_deserialize_description(): description = make_description() data = json.loads(JSON_RESULT_TEST_SERIALIZE_DESCRIPTION) d = Description(root=[]) d.deserialize(data) assert d == description d = Description.from_data(data) assert d == description fritzconnection-1.15.0/fritzconnection/tests/test_soaper.py000066400000000000000000000355141501211554500243050ustar00rootroot00000000000000import datetime import types from xml.etree import ElementTree as etree import pytest from ..core.exceptions import ( ActionError, FritzAuthorizationError, FritzConnectionException, FritzActionError, FritzArgumentError, FritzActionFailedError, FritzArgumentValueError, FritzOutOfMemoryError, FritzSecurityError, FritzArrayIndexError, FritzLookUpError, FritzArgumentStringToShortError, FritzArgumentStringToLongError, FritzArgumentCharacterError, FritzInternalError, ) from ..core.soaper import ( boolean_convert, encode_boolean, get_argument_value, get_converted_value, get_html_safe_value, is_html_response, raise_fritzconnection_error, redact_response, remove_html_tags, ) content_template = """ s:Client UPnPError {error_code} Invalid Action """ @pytest.mark.parametrize( "error_code, status_code, exception", [ ('401', 500, FritzActionError), ('402', 500, FritzArgumentError), ('501', 500, FritzActionFailedError), ('600', 500, FritzArgumentValueError), ('603', 500, FritzOutOfMemoryError), ('606', 500, FritzSecurityError), ('713', 500, FritzArrayIndexError), ('714', 500, FritzLookUpError), ('801', 500, FritzArgumentStringToShortError), ('802', 500, FritzArgumentStringToLongError), ('803', 500, FritzArgumentCharacterError), ('820', 500, FritzInternalError), ('713', 500, IndexError), ('714', 500, KeyError), ('401', 500, ActionError), (None, 401, FritzAuthorizationError), (None, 500, FritzConnectionException), ] ) def test_raise_fritzconnection_error(error_code, status_code, exception): """check for exception raising depending on the error_code""" if error_code: content = content_template.format(error_code=error_code) else: content = 'some content' response = types.SimpleNamespace() response.text = content response.content = content.encode() response.status_code = status_code pytest.raises(exception, raise_fritzconnection_error, response) def test_raise_fritzauthorization_error(): """check for exception raising depending on the html status code.""" response = types.SimpleNamespace() response.content = b'401 Unauthorized (ERR_NONE)

401 Unauthorized


ERR_NONE
Webserver Sat, 01 Oct 2022 09:46:22 GMT' response.text = '401 Unauthorized (ERR_NONE)

401 Unauthorized


ERR_NONE
Webserver Sat, 01 Oct 2022 09:46:22 GMT' response.status_code = 401 pytest.raises(FritzAuthorizationError, raise_fritzconnection_error, response) # simulate a http/500 response.content = b'500 internal error

500 internal error


ERR_NONE
Webserver Sat, 01 Oct 2022 09:46:22 GMT' response.text = '500 internal error

500 internal error


ERR_NONE
Webserver Sat, 01 Oct 2022 09:46:22 GMT' response.status_code = 500 pytest.raises(FritzConnectionException, raise_fritzconnection_error, response) @pytest.mark.parametrize( "value, expected_result", [ ('0', False), ('1', True), ] ) def test_boolean_convert(value, expected_result): result = boolean_convert(value) assert result == expected_result @pytest.mark.parametrize( "value", ['2', 'x', '3.1'] ) def test_boolean_convert_fails(value): with pytest.raises(ValueError): boolean_convert(value) @pytest.mark.parametrize( "text, expected_result", [ ('something', True), ('here", "here"), ("ham spam
and eggs
", "ham spam and eggs"), ( "failuresomething very
strange", "failure something very strange", ) ] ) def test_remove_html_tags(text, expected_result): result = remove_html_tags(text) assert result == expected_result long_error = """ s:Client UPnPError 401 Invalid Action """ def test_long_error_message(): response = types.SimpleNamespace() response.text = long_error response.content = long_error.encode() with pytest.raises(ActionError) as exc: raise_fritzconnection_error(response) assert exc.value.args[0] == "\n".join( ["UPnPError: ", "errorCode: 401", "errorDescription: Invalid Action", ] ) @pytest.mark.parametrize( "value, expected_type", [ ("text", str), (0, int), (1, int), (None, int), (False, int), (True, int), ] ) def test_encode_boolean(value, expected_type): result = encode_boolean(value) assert isinstance(result, expected_type) @pytest.mark.parametrize( "value, expected_results", [ (True, 1), (False, 0), (None, 0), (3.141, 3.141), ("hello test", "hello test"), ("2021-07-17T12:00:00", "2021-07-17T12:00:00"), # redundant, but ISO ;) ("ham, spam & eggs", "ham, spam & eggs"), ("5 > 3", "5 > 3"), ("3 < 5", "3 < 5"), ('say "hello"', "say "hello""), ("let's test again", ["let' test again", "let's test again"]) ] ) def test_get_html_safe_value(value, expected_results): if not isinstance(expected_results, list): expected_results = [expected_results] result = get_html_safe_value(value) assert result in expected_results @pytest.mark.parametrize( "value, not_expected_type", [ (False, bool), # should be int after encoding, not bool (True, bool), ] ) def test_encode_boolean2(value, not_expected_type): result = encode_boolean(value) assert not isinstance(result, not_expected_type) soap_root = etree.fromstring(""" 2010 message text 3.141 """) @pytest.mark.parametrize( "argument_name, expected_value", [ ('year', '2010'), ('msg', 'message text'), ('number', '3.141'), ('ip', ''), ] ) def test_get_argument_value(argument_name, expected_value): value = get_argument_value(soap_root, argument_name) assert value == expected_value @pytest.mark.parametrize( "data_type, value, expected_value", [ ('datetime', '2020-02-02T10:10:10', datetime.datetime(2020, 2, 2, 10, 10, 10)), ('boolean', '1', True), ('boolean', '0', False), ('uuid', 'uuid:123', '123'), ('uuid', '123', '123'), ('i4', '42', 42), ('ui1', '42', 42), ('ui2', '42', 42), ('ui4', '42', 42), ] ) def test_get_converted_value(data_type, value, expected_value): result = get_converted_value(data_type, value) assert result == expected_value @pytest.mark.parametrize( "data_type, value", [ ('datetime', '2010.02.02-10:10:10'), # not ISO 8601 ('boolean', ''), # neither '1' nor '0' ] ) def test_get_converted_value_fails(data_type, value): with pytest.raises(ValueError): get_converted_value(data_type, value) def test_redact_debug_log_phone_numbers(): response = """ AVM 00040E FRITZ!Box 7530 AX FRITZ!Box 7530 AX Release 256.08.00 FRITZ!Box aabbccddeeff 256.08.00 FRITZ!Box 7530 AX 1.0 86446 23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567890 war nicht erfolgreich. Ursache: DNS-Fehler 23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567891 war nicht erfolgreich. Ursache: DNS-Fehler 23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567892 war nicht erfolgreich. Ursache: DNS-Fehler 23.11.24 12:28:10 Anmeldung der Internetrufnummer 491234567893 war nicht erfolgreich. Ursache: DNS-Fehler """ result = redact_response(False, response) assert result == response result = redact_response(True, response) assert result == """ AVM 00040E FRITZ!Box 7530 AX FRITZ!Box 7530 AX Release 256.08.00 FRITZ!Box aabbccddeeff 256.08.00 FRITZ!Box 7530 AX 1.0 86446 23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht erfolgreich. Ursache: DNS-Fehler 23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht erfolgreich. Ursache: DNS-Fehler 23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht erfolgreich. Ursache: DNS-Fehler 23.11.24 12:28:10 Anmeldung der Internetrufnummer ****** war nicht erfolgreich. Ursache: DNS-Fehler """ def test_redact_debug_log_external_ip_addresses(): response = """ 12.34.56.78 0011:2233:4455:6677::0abcd 64 0 0 """ result = redact_response(False, response) assert result == response result = redact_response(True, response) assert result == """ ****** ****** 64 0 0 """ def test_redact_debug_log_wifi_passwords(): response = """ 0123456789 01234 6789 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF MY_GREAT_WIFI_PSK """ result = redact_response(False, response) assert result == response result = redact_response(True, response) assert result == """ ****** ****** ****** ****** ****** ****** """ fritzconnection-1.15.0/fritzconnection/tests/xml/000077500000000000000000000000001501211554500221735ustar00rootroot00000000000000fritzconnection-1.15.0/fritzconnection/tests/xml/basicdevicestats_response.txt000066400000000000000000000101131501211554500301660ustar00rootroot00000000000000190,190,190,190,190,190,195,190,190,195,195,195,195,195,195,195,195,190,190,190,190,190,190,190,190,190,195,200,195,205,205,210,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195,195236541,236541,236541,236541,236541,236541,236541,236541,236541,236541,236541,236541,236459,236459,236459,236459,236459,236459,236459,236459,236459,236459,236459,236459,237041,237041,237041,237041,237041,237041,237041,237041,237041,237041,237041,237041,236888,236888,236888,236888,236888,236888,236888,236888,236888,236888,236888,236888,237630,237630,237630,237630,237630,237630,237630,237630,237630,237630,237630,237630,236837,236837,236837,236837,236837,236837,236837,236837,236837,236837,236837,236837,237934,237934,237934,237934,237934,237934,237934,237934,237934,237934,237934,237934,237505,237505,237505,237505,237505,237505,237505,237505,237505,237505,237505,237505,236729,236729,236729,236729,236729,236729,236729,236729,236729,236729,236729,236729,236346,236346,236346,236346,236346,236346,236346,236346,236346,236346,236346,236346,237497,237497,237497,237497,237497,237497,237497,237497,237497,237497,237497,237497,237430,237430,237430,237430,237430,237430,237430,237430,237430,237430,237430,237430,237648,237648,237648,237648,237648,237648,237648,237648,237648,237648,237648,237648,237811,237811,237811,237811,237811,237811,237811,237811,237811,237811,237811,237811,237570,237570,237570,237570,237570,237570,237570,237570,237570,237570,237570,237570,237836,237836,237836,237836,237836,237836,237836,237836,237836,237836,237836,237836,237939,237939,237939,237939,237939,237939,237939,237939,237939,237939,237939,237939,237812,237812,237812,237812,237812,237812,237812,237812,237812,237812,237812,237812,237516,237516,237516,237516,237516,237516,237516,237516,237516,237516,237516,237516,237775,237775,237775,237775,237775,237775,237775,237775,237775,237775,237775,237775,237775,237612,237612,237612,237612,237612,237612,237612,237612,237612,237612,237612,237612,237723,237723,237723,237723,237723,237723,237723,237723,237723,237723,237723,237723,237053,237053,237053,237053,237053,237053,237053,237053,237053,237053,237053,237053,236641,236641,236641,236641,236641,236641,236641,236641,236641,236641,236641,236641,235523,235523,235523,235523,235523,235523,235523,235523,235523,235523,235523,235523,234987,234987,234987,234987,234987,234987,234987,234987,234987,234987,234987,234987,235365,235365,235365,235365,235365,235365,235365,235365,235365,235365,235365,235365,235673,235673,235673,235673,235673,235673,235673,235673,235673,235673,235673,235673,235897,235897,235897,235897,235897,235897,235897,235897,235897,235897,235897,235897,236058,236058,236058,236058,236058,236058,236058,236058,236058,236058,2360580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,08301,3256,1455,0,0,2,0,0,0,6,0,0343,343,347,349,348,345,345,346,348,347,346,346,344,345,346,349,346,345,348,346,345,0,0,0,344,346,344,342,0,0,0 fritzconnection-1.15.0/fritzconnection/tests/xml/description.json000066400000000000000000012401431501211554500254160ustar00rootroot00000000000000[{"device": {"attributes": {"UDN": "uuid:75802409-bccb-40e7-8e6c-989BCB2B93B0", "UPC": null, "deviceType": "urn:schemas-upnp-org:device:InternetGatewayDevice:1", "friendlyName": "FRITZ!Box 7590", "manufacturer": "AVM Berlin", "manufacturerURL": "http://www.avm.de", "modelDescription": "FRITZ!Box 7590", "modelName": "FRITZ!Box 7590", "modelNumber": "avm", "modelURL": "http://www.avm.de", "presentationURL": "http://fritz.box"}, "devices": [{"attributes": {"UDN": "uuid:76802409-bccb-40e7-8e6b-989BCB2B93B0", "UPC": "AVM IGD", "deviceType": "urn:schemas-upnp-org:device:WANDevice:1", "friendlyName": "WANDevice - FRITZ!Box 7590", "manufacturer": "AVM Berlin", "manufacturerURL": "www.avm.de", "modelDescription": "WANDevice - FRITZ!Box 7590", "modelName": "WANDevice - FRITZ!Box 7590", "modelNumber": "avm", "modelURL": "www.avm.de", "presentationURL": null}, "devices": [{"attributes": {"UDN": "uuid:76802409-bccb-40e7-8e6a-989BCB2B93B0", "UPC": "AVM IGD", "deviceType": "urn:schemas-upnp-org:device:WANConnectionDevice:1", "friendlyName": "WANConnectionDevice - FRITZ!Box 7590", "manufacturer": "AVM Berlin", "manufacturerURL": "www.avm.de", "modelDescription": "WANConnectionDevice - FRITZ!Box 7590", "modelName": "WANConnectionDevice - FRITZ!Box 7590", "modelNumber": "avm", "modelURL": "www.avm.de", "presentationURL": null}, "devices": [], "services": [{"attributes": {"SCPDURL": "/igddslSCPD.xml", "controlURL": "/igdupnp/control/WANDSLLinkC1", "eventSubURL": "/igdupnp/control/WANDSLLinkC1", "serviceId": "urn:upnp-org:serviceId:WANDSLLinkC1", "serviceType": "urn:schemas-upnp-org:service:WANDSLLinkConfig:1"}, "scpd": {"actions": [{"name": "SetDSLLinkType", "arguments": [{"direction": "in", "name": "NewLinkType", "relatedStateVariable": "LinkType"}]}, {"name": "GetDSLLinkInfo", "arguments": [{"direction": "out", "name": "NewLinkType", "relatedStateVariable": "LinkType"}, {"direction": "out", "name": "NewLinkStatus", "relatedStateVariable": "LinkStatus"}]}, {"name": "GetAutoConfig", "arguments": [{"direction": "out", "name": "NewAutoConfig", "relatedStateVariable": "AutoConfig"}]}, {"name": "GetModulationType", "arguments": [{"direction": "out", "name": "NewModulationType", "relatedStateVariable": "ModulationType"}]}, {"name": "SetDestinationAddress", "arguments": [{"direction": "in", "name": "NewDestinationAddress", "relatedStateVariable": "DestinationAddress"}]}, {"name": "GetDestinationAddress", "arguments": [{"direction": "out", "name": "NewDestinationAddress", "relatedStateVariable": "DestinationAddress"}]}, {"name": "SetATMEncapsulation", "arguments": [{"direction": "in", "name": "NewATMEncapsulation", "relatedStateVariable": "ATMEncapsulation"}]}, {"name": "GetATMEncapsulation", "arguments": [{"direction": "out", "name": "NewATMEncapsulation", "relatedStateVariable": "ATMEncapsulation"}]}, {"name": "SetFCSPreserved", "arguments": [{"direction": "in", "name": "NewFCSPreserved", "relatedStateVariable": "FCSPreserved"}]}, {"name": "GetFCSPreserved", "arguments": [{"direction": "out", "name": "NewFCSPreserved", "relatedStateVariable": "FCSPreserved"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": ["EoA", "IPoA", "CIP", "PPPoA", "PPPoE", "Unconfigured"], "dataType": "string", "defaultValue": null, "name": "LinkType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Down", "Initializing", "Unavailable"], "dataType": "string", "defaultValue": null, "name": "LinkStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["ADSL G.lite", "G.shdsl", "IDSL", "HDSL", "SDSL", "VDSL"], "dataType": "string", "defaultValue": null, "name": "ModulationType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DestinationAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["LLC", "VCMUX"], "dataType": "string", "defaultValue": null, "name": "ATMEncapsulation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "FCSPreserved"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AutoConfig"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/igdconnSCPD.xml", "controlURL": "/igdupnp/control/WANIPConn1", "eventSubURL": "/igdupnp/control/WANIPConn1", "serviceId": "urn:upnp-org:serviceId:WANIPConn1", "serviceType": "urn:schemas-upnp-org:service:WANIPConnection:1"}, "scpd": {"actions": [{"name": "SetConnectionType", "arguments": [{"direction": "in", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}]}, {"name": "GetConnectionTypeInfo", "arguments": [{"direction": "out", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}, {"direction": "out", "name": "NewPossibleConnectionTypes", "relatedStateVariable": "PossibleConnectionTypes"}]}, {"name": "GetAutoDisconnectTime", "arguments": [{"direction": "out", "name": "NewAutoDisconnectTime", "relatedStateVariable": "AutoDisconnectTime"}]}, {"name": "GetIdleDisconnectTime", "arguments": [{"direction": "out", "name": "NewIdleDisconnectTime", "relatedStateVariable": "IdleDisconnectTime"}]}, {"name": "RequestConnection", "arguments": []}, {"name": "RequestTermination", "arguments": []}, {"name": "ForceTermination", "arguments": []}, {"name": "GetStatusInfo", "arguments": [{"direction": "out", "name": "NewConnectionStatus", "relatedStateVariable": "ConnectionStatus"}, {"direction": "out", "name": "NewLastConnectionError", "relatedStateVariable": "LastConnectionError"}, {"direction": "out", "name": "NewUptime", "relatedStateVariable": "Uptime"}]}, {"name": "GetNATRSIPStatus", "arguments": [{"direction": "out", "name": "NewRSIPAvailable", "relatedStateVariable": "RSIPAvailable"}, {"direction": "out", "name": "NewNATEnabled", "relatedStateVariable": "NATEnabled"}]}, {"name": "GetGenericPortMappingEntry", "arguments": [{"direction": "in", "name": "NewPortMappingIndex", "relatedStateVariable": "PortMappingNumberOfEntries"}, {"direction": "out", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "out", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "out", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "out", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "out", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "out", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "out", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "GetSpecificPortMappingEntry", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "out", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "out", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "out", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "out", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "AddPortMapping", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "in", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "in", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "in", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "in", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "in", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "DeletePortMapping", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}]}, {"name": "GetExternalIPAddress", "arguments": [{"direction": "out", "name": "NewExternalIPAddress", "relatedStateVariable": "ExternalIPAddress"}]}, {"name": "X_AVM_DE_GetExternalIPv6Address", "arguments": [{"direction": "out", "name": "NewExternalIPv6Address", "relatedStateVariable": "ExternalIPv6Address"}, {"direction": "out", "name": "NewPrefixLength", "relatedStateVariable": "PrefixLength"}, {"direction": "out", "name": "NewValidLifetime", "relatedStateVariable": "ValidLifetime"}, {"direction": "out", "name": "NewPreferedLifetime", "relatedStateVariable": "PreferedLifetime"}]}, {"name": "X_AVM_DE_GetIPv6Prefix", "arguments": [{"direction": "out", "name": "NewIPv6Prefix", "relatedStateVariable": "IPv6Prefix"}, {"direction": "out", "name": "NewPrefixLength", "relatedStateVariable": "PrefixLength"}, {"direction": "out", "name": "NewValidLifetime", "relatedStateVariable": "ValidLifetime"}, {"direction": "out", "name": "NewPreferedLifetime", "relatedStateVariable": "PreferedLifetime"}]}, {"name": "X_AVM_DE_GetDNSServer", "arguments": [{"direction": "out", "name": "NewIPv4DNSServer1", "relatedStateVariable": "IPv4DNSServer1"}, {"direction": "out", "name": "NewIPv4DNSServer2", "relatedStateVariable": "IPv4DNSServer2"}]}, {"name": "X_AVM_DE_GetIPv6DNSServer", "arguments": [{"direction": "out", "name": "NewIPv6DNSServer1", "relatedStateVariable": "IPv6DNSServer1"}, {"direction": "out", "name": "NewValidLifetime1", "relatedStateVariable": "ValidLifetime1"}, {"direction": "out", "name": "NewIPv6DNSServer2", "relatedStateVariable": "IPv6DNSServer2"}, {"direction": "out", "name": "NewValidLifetime", "relatedStateVariable": "ValidLifetime2"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "Unconfigured", "name": "ConnectionType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "IP_Routed", "IP_Bridged"], "dataType": "string", "defaultValue": null, "name": "PossibleConnectionTypes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "Connecting", "Authenticating", "Connected", "PendingDisconnect", "Disconnecting", "Disconnected"], "dataType": "string", "defaultValue": "Unconfigured", "name": "ConnectionStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Uptime"}, "allowedValueRange": {"maximum": "4294967295", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "RSIPAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "NATEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["ERROR_NONE", "ERROR_ISP_TIME_OUT", "ERROR_COMMAND_ABORTED", "ERROR_NOT_ENABLED_FOR_INTERNET", "ERROR_BAD_PHONE_NUMBER", "ERROR_USER_DISCONNECT", "ERROR_ISP_DISCONNECT", "ERROR_IDLE_DISCONNECT", "ERROR_FORCED_DISCONNECT", "ERROR_SERVER_OUT_OF_RESOURCES", "ERROR_RESTRICTED_LOGON_HOURS", "ERROR_ACCOUNT_DISABLED", "ERROR_ACCOUNT_EXPIRED", "ERROR_PASSWORD_EXPIRED", "ERROR_AUTHENTICATION_FAILURE", "ERROR_NO_DIALTONE", "ERROR_NO_CARRIER", "ERROR_NO_ANSWER", "ERROR_LINE_BUSY", "ERROR_UNSUPPORTED_BITSPERSECOND", "ERROR_TOO_MANY_LINE_ERRORS", "ERROR_IP_CONFIGURATION", "ERROR_UNKNOWN"], "dataType": "string", "defaultValue": "ERROR_NONE", "name": "LastConnectionError"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "AutoDisconnectTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "IdleDisconnectTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ExternalIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ExternalIPv6Address"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ValidLifetime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PreferedLifetime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv6Prefix"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "PrefixLength"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv4DNSServer1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv4DNSServer2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv6DNSServer1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv6DNSServer2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ValidLifetime1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ValidLifetime2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "RemoteHost"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "ExternalPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "InternalPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["TCP", "UDP"], "dataType": "string", "defaultValue": null, "name": "PortMappingProtocol"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "InternalClient"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PortMappingDescription"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "PortMappingEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PortMappingLeaseDuration"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "PortMappingNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/igd2ipv6fwcSCPD.xml", "controlURL": "/igd2upnp/control/WANIPv6Firewall1", "eventSubURL": "/igd2upnp/control/WANIPv6Firewall1", "serviceId": "urn:upnp-org:serviceId:WANIPv6Firewall1", "serviceType": "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"}, "scpd": {"actions": [{"name": "GetFirewallStatus", "arguments": [{"direction": "out", "name": "FirewallEnabled", "relatedStateVariable": "FirewallEnabled"}, {"direction": "out", "name": "InboundPinholeAllowed", "relatedStateVariable": "InboundPinholeAllowed"}]}, {"name": "GetOutboundPinholeTimeout", "arguments": [{"direction": "in", "name": "RemoteHost", "relatedStateVariable": "A_ARG_TYPE_IPv6Address"}, {"direction": "in", "name": "RemotePort", "relatedStateVariable": "A_ARG_TYPE_Port"}, {"direction": "in", "name": "InternalClient", "relatedStateVariable": "A_ARG_TYPE_IPv6Address"}, {"direction": "in", "name": "InternalPort", "relatedStateVariable": "A_ARG_TYPE_Port"}, {"direction": "in", "name": "Protocol", "relatedStateVariable": "A_ARG_TYPE_Protocol"}, {"direction": "out", "name": "OutboundPinholeTimeout", "relatedStateVariable": "A_ARG_TYPE_OutboundPinholeTimeout"}]}, {"name": "AddPinhole", "arguments": [{"direction": "in", "name": "RemoteHost", "relatedStateVariable": "A_ARG_TYPE_IPv6Address"}, {"direction": "in", "name": "RemotePort", "relatedStateVariable": "A_ARG_TYPE_Port"}, {"direction": "in", "name": "InternalClient", "relatedStateVariable": "A_ARG_TYPE_IPv6Address"}, {"direction": "in", "name": "InternalPort", "relatedStateVariable": "A_ARG_TYPE_Port"}, {"direction": "in", "name": "Protocol", "relatedStateVariable": "A_ARG_TYPE_Protocol"}, {"direction": "in", "name": "LeaseTime", "relatedStateVariable": "A_ARG_TYPE_LeaseTime"}, {"direction": "out", "name": "UniqueID", "relatedStateVariable": "A_ARG_TYPE_UniqueID"}]}, {"name": "UpdatePinhole", "arguments": [{"direction": "in", "name": "UniqueID", "relatedStateVariable": "A_ARG_TYPE_UniqueID"}, {"direction": "in", "name": "NewLeaseTime", "relatedStateVariable": "A_ARG_TYPE_LeaseTime"}]}, {"name": "DeletePinhole", "arguments": [{"direction": "in", "name": "UniqueID", "relatedStateVariable": "A_ARG_TYPE_UniqueID"}]}, {"name": "GetPinholePackets", "arguments": [{"direction": "in", "name": "UniqueID", "relatedStateVariable": "A_ARG_TYPE_UniqueID"}, {"direction": "out", "name": "PinholePackets", "relatedStateVariable": "A_ARG_TYPE_PinholePackets"}]}, {"name": "CheckPinholeWorking", "arguments": [{"direction": "in", "name": "UniqueID", "relatedStateVariable": "A_ARG_TYPE_UniqueID"}, {"direction": "out", "name": "IsWorking", "relatedStateVariable": "A_ARG_TYPE_Boolean"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "FirewallEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "InboundPinholeAllowed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "120", "name": "A_ARG_TYPE_OutboundPinholeTimeout"}, "allowedValueRange": {"maximum": "86400", "minimum": "120", "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "A_ARG_TYPE_IPv6Address"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "A_ARG_TYPE_Port"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "65535", "name": "A_ARG_TYPE_Protocol"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "3600", "name": "A_ARG_TYPE_LeaseTime"}, "allowedValueRange": {"maximum": "86400", "minimum": "1", "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "A_ARG_TYPE_UniqueID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "A_ARG_TYPE_PinholePackets"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "A_ARG_TYPE_Boolean"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}], "services": [{"attributes": {"SCPDURL": "/igdicfgSCPD.xml", "controlURL": "/igdupnp/control/WANCommonIFC1", "eventSubURL": "/igdupnp/control/WANCommonIFC1", "serviceId": "urn:upnp-org:serviceId:WANCommonIFC1", "serviceType": "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"}, "scpd": {"actions": [{"name": "GetCommonLinkProperties", "arguments": [{"direction": "out", "name": "NewWANAccessType", "relatedStateVariable": "WANAccessType"}, {"direction": "out", "name": "NewLayer1UpstreamMaxBitRate", "relatedStateVariable": "Layer1UpstreamMaxBitRate"}, {"direction": "out", "name": "NewLayer1DownstreamMaxBitRate", "relatedStateVariable": "Layer1DownstreamMaxBitRate"}, {"direction": "out", "name": "NewPhysicalLinkStatus", "relatedStateVariable": "PhysicalLinkStatus"}]}, {"name": "GetTotalBytesSent", "arguments": [{"direction": "out", "name": "NewTotalBytesSent", "relatedStateVariable": "TotalBytesSent"}]}, {"name": "GetTotalBytesReceived", "arguments": [{"direction": "out", "name": "NewTotalBytesReceived", "relatedStateVariable": "TotalBytesReceived"}]}, {"name": "GetTotalPacketsSent", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}]}, {"name": "GetTotalPacketsReceived", "arguments": [{"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetAddonInfos", "arguments": [{"direction": "out", "name": "NewByteSendRate", "relatedStateVariable": "ByteSendRate"}, {"direction": "out", "name": "NewByteReceiveRate", "relatedStateVariable": "ByteReceiveRate"}, {"direction": "out", "name": "NewPacketSendRate", "relatedStateVariable": "PacketSendRate"}, {"direction": "out", "name": "NewPacketReceiveRate", "relatedStateVariable": "PacketReceiveRate"}, {"direction": "out", "name": "NewTotalBytesSent", "relatedStateVariable": "TotalBytesSent"}, {"direction": "out", "name": "NewTotalBytesReceived", "relatedStateVariable": "TotalBytesReceived"}, {"direction": "out", "name": "NewAutoDisconnectTime", "relatedStateVariable": "AutoDisconnectTime"}, {"direction": "out", "name": "NewIdleDisconnectTime", "relatedStateVariable": "IdleDisconnectTime"}, {"direction": "out", "name": "NewDNSServer1", "relatedStateVariable": "DNSServer1"}, {"direction": "out", "name": "NewDNSServer2", "relatedStateVariable": "DNSServer2"}, {"direction": "out", "name": "NewVoipDNSServer1", "relatedStateVariable": "VoipDNSServer1"}, {"direction": "out", "name": "NewVoipDNSServer2", "relatedStateVariable": "VoipDNSServer2"}, {"direction": "out", "name": "NewUpnpControlEnabled", "relatedStateVariable": "UpnpControlEnabled"}, {"direction": "out", "name": "NewRoutedBridgedModeBoth", "relatedStateVariable": "RoutedBridgedModeBoth"}, {"direction": "out", "name": "NewX_AVM_DE_TotalBytesSent64", "relatedStateVariable": "X_AVM_DE_TotalBytesSent64"}, {"direction": "out", "name": "NewX_AVM_DE_TotalBytesReceived64", "relatedStateVariable": "X_AVM_DE_TotalBytesReceived64"}, {"direction": "out", "name": "NewX_AVM_DE_WANAccessType", "relatedStateVariable": "X_AVM_DE_WANAccessType"}]}, {"name": "X_AVM_DE_GetDsliteStatus", "arguments": [{"direction": "out", "name": "NewX_AVM_DE_DsliteStatus", "relatedStateVariable": "X_AVM_DE_DsliteStatus"}]}, {"name": "X_AVM_DE_GetIPTVInfos", "arguments": [{"direction": "out", "name": "NewX_AVM_DE_IPTV_Enabled", "relatedStateVariable": "X_AVM_DE_IPTV_Enabled"}, {"direction": "out", "name": "NewX_AVM_DE_IPTV_Provider", "relatedStateVariable": "X_AVM_DE_IPTV_Provider"}, {"direction": "out", "name": "NewX_AVM_DE_IPTV_URL", "relatedStateVariable": "X_AVM_DE_IPTV_URL"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": ["DSL", "ATA", "USB-Tethering", "Cable", "LTE", "Serial", "WLAN", "ISDN", "IP-Client", "Fiber", "Other"], "dataType": "string", "defaultValue": null, "name": "X_AVM_DE_WANAccessType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM_DE_IPTV_URL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM_DE_IPTV_Provider"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM_DE_IPTV_Enabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM_DE_TotalBytesSent64"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM_DE_TotalBytesReceived64"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM_DE_DsliteStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["DSL", "POTS", "Cable", "Ethernet", "Other"], "dataType": "string", "defaultValue": null, "name": "WANAccessType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Layer1UpstreamMaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Layer1DownstreamMaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Down", "Initializing", "Unavailable"], "dataType": "string", "defaultValue": null, "name": "PhysicalLinkStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WANAccessProvider"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "MaximumActiveConnections"}, "allowedValueRange": {"maximum": "4294967295", "minimum": "1", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalBytesSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalBytesReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ByteSendRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ByteReceiveRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PacketSendRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PacketReceiveRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "AutoDisconnectTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "IdleDisconnectTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DNSServer1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DNSServer2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoipDNSServer1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoipDNSServer2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "UpnpControlEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "RoutedBridgedModeBoth"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}], "services": [{"attributes": {"SCPDURL": "/any.xml", "controlURL": "/igdupnp/control/any", "eventSubURL": "/igdupnp/control/any", "serviceId": "urn:any-com:serviceId:any1", "serviceType": "urn:schemas-any-com:service:Any:1"}, "scpd": {"actions": [], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Dummy"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}, "specVersion": {"major": "1", "minor": "0"}, "systemVersion": {"Buildnumber": null, "Display": null, "HW": null, "Major": null, "Minor": null, "Patch": null}}, {"device": {"attributes": {"UDN": "uuid:739f2409-bccb-40e7-8e6c-989BCB2B93B0", "UPC": null, "deviceType": "urn:dslforum-org:device:InternetGatewayDevice:1", "friendlyName": "FRITZ!Box 7590", "manufacturer": "AVM", "manufacturerURL": "www.avm.de", "modelDescription": "FRITZ!Box 7590", "modelName": "FRITZ!Box 7590", "modelNumber": "- avm", "modelURL": "www.avm.de", "presentationURL": "http://fritz.box"}, "devices": [{"attributes": {"UDN": "uuid:75802409-bccb-40e7-8e6b-989BCB2B93B0", "UPC": "AVM TR-064", "deviceType": "urn:dslforum-org:device:LANDevice:1", "friendlyName": "LANDevice - FRITZ!Box 7590", "manufacturer": "AVM", "manufacturerURL": "www.avm.de", "modelDescription": "LANDevice - FRITZ!Box 7590", "modelName": "LANDevice - FRITZ!Box 7590", "modelNumber": "- avm", "modelURL": "www.avm.de", "presentationURL": null}, "devices": [], "services": [{"attributes": {"SCPDURL": "/wlanconfigSCPD.xml", "controlURL": "/upnp/control/wlanconfig1", "eventSubURL": "/upnp/control/wlanconfig1", "serviceId": "urn:WLANConfiguration-com:serviceId:WLANConfiguration1", "serviceType": "urn:dslforum-org:service:WLANConfiguration:1"}, "scpd": {"actions": [{"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewX_AVM-DE_PossibleBeaconTypes", "relatedStateVariable": "X_AVM-DE_PossibleBeaconTypes"}, {"direction": "out", "name": "NewMACAddressControlEnabled", "relatedStateVariable": "MACAddressControlEnabled"}, {"direction": "out", "name": "NewStandard", "relatedStateVariable": "Standard"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "out", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}, {"direction": "out", "name": "NewMaxCharsSSID", "relatedStateVariable": "MaxCharsSSID"}, {"direction": "out", "name": "NewMinCharsSSID", "relatedStateVariable": "MinCharsSSID"}, {"direction": "out", "name": "NewAllowedCharsSSID", "relatedStateVariable": "AllowedCharsSSID"}, {"direction": "out", "name": "NewMinCharsPSK", "relatedStateVariable": "MinCharsPSK"}, {"direction": "out", "name": "NewMaxCharsPSK", "relatedStateVariable": "MaxCharsPSK"}, {"direction": "out", "name": "NewAllowedCharsPSK", "relatedStateVariable": "AllowedCharsPSK"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "in", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "in", "name": "NewMACAddressControlEnabled", "relatedStateVariable": "MACAddressControlEnabled"}, {"direction": "in", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "in", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "SetSecurityKeys", "arguments": [{"direction": "in", "name": "NewWEPKey0", "relatedStateVariable": "WEPKey0"}, {"direction": "in", "name": "NewWEPKey1", "relatedStateVariable": "WEPKey1"}, {"direction": "in", "name": "NewWEPKey2", "relatedStateVariable": "WEPKey2"}, {"direction": "in", "name": "NewWEPKey3", "relatedStateVariable": "WEPKey3"}, {"direction": "in", "name": "NewPreSharedKey", "relatedStateVariable": "PreSharedKey"}, {"direction": "in", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}]}, {"name": "GetSecurityKeys", "arguments": [{"direction": "out", "name": "NewWEPKey0", "relatedStateVariable": "WEPKey0"}, {"direction": "out", "name": "NewWEPKey1", "relatedStateVariable": "WEPKey1"}, {"direction": "out", "name": "NewWEPKey2", "relatedStateVariable": "WEPKey2"}, {"direction": "out", "name": "NewWEPKey3", "relatedStateVariable": "WEPKey3"}, {"direction": "out", "name": "NewPreSharedKey", "relatedStateVariable": "PreSharedKey"}, {"direction": "out", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}]}, {"name": "SetDefaultWEPKeyIndex", "arguments": [{"direction": "in", "name": "NewDefaultWEPKeyIndex", "relatedStateVariable": "WEPKeyIndex"}]}, {"name": "GetDefaultWEPKeyIndex", "arguments": [{"direction": "out", "name": "NewDefaultWEPKeyIndex", "relatedStateVariable": "WEPKeyIndex"}]}, {"name": "SetBasBeaconSecurityProperties", "arguments": [{"direction": "in", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "in", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "GetBasBeaconSecurityProperties", "arguments": [{"direction": "out", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "out", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "GetStatistics", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}, {"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetPacketStatistics", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}, {"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetBSSID", "arguments": [{"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}]}, {"name": "GetSSID", "arguments": [{"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}]}, {"name": "SetSSID", "arguments": [{"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}]}, {"name": "GetBeaconType", "arguments": [{"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewX_AVM-DE_PossibleBeaconTypes", "relatedStateVariable": "X_AVM-DE_PossibleBeaconTypes"}]}, {"name": "SetBeaconType", "arguments": [{"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}]}, {"name": "GetChannelInfo", "arguments": [{"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewPossibleChannels", "relatedStateVariable": "PossibleChannels"}]}, {"name": "SetChannel", "arguments": [{"direction": "in", "name": "NewChannel", "relatedStateVariable": "Channel"}]}, {"name": "GetBeaconAdvertisement", "arguments": [{"direction": "out", "name": "NewBeaconAdvertisementEnabled", "relatedStateVariable": "BeaconAdvertisementEnabled"}]}, {"name": "SetBeaconAdvertisement", "arguments": [{"direction": "in", "name": "NewBeaconAdvertisementEnabled", "relatedStateVariable": "BeaconAdvertisementEnabled"}]}, {"name": "GetTotalAssociations", "arguments": [{"direction": "out", "name": "NewTotalAssociations", "relatedStateVariable": "TotalAssociations"}]}, {"name": "GetGenericAssociatedDeviceInfo", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceIndex", "relatedStateVariable": "TotalAssociations"}, {"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "GetSpecificAssociatedDeviceInfo", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "X_AVM-DE_GetSpecificAssociatedDeviceInfoByIp", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "X_AVM-DE_GetWLANDeviceListPath", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_WLANDeviceListPath", "relatedStateVariable": "X_AVM-DE_WLANDeviceListPath"}]}, {"name": "X_AVM-DE_SetStickSurfEnable", "arguments": [{"direction": "in", "name": "NewStickSurfEnable", "relatedStateVariable": "StickSurfEnable"}]}, {"name": "X_AVM-DE_GetIPTVOptimized", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_IPTVoptimize", "relatedStateVariable": "X_AVM-DE_IPTVoptimize"}]}, {"name": "X_AVM-DE_SetIPTVOptimized", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_IPTVoptimize", "relatedStateVariable": "X_AVM-DE_IPTVoptimize"}]}, {"name": "X_AVM-DE_GetNightControl", "arguments": [{"direction": "out", "name": "NewNightControl", "relatedStateVariable": "NightControl"}, {"direction": "out", "name": "NewNightTimeControlNoForcedOff", "relatedStateVariable": "NightTimeControlNoForcedOff"}]}, {"name": "X_AVM-DE_GetWLANHybridMode", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewTrafficMode", "relatedStateVariable": "TrafficMode"}, {"direction": "out", "name": "NewManualSpeed", "relatedStateVariable": "ManualSpeed"}, {"direction": "out", "name": "NewMaxSpeedDS", "relatedStateVariable": "MaxSpeedDS"}, {"direction": "out", "name": "NewMaxSpeedUS", "relatedStateVariable": "MaxSpeedUS"}]}, {"name": "X_AVM-DE_SetWLANHybridMode", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "in", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}, {"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "in", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "in", "name": "NewTrafficMode", "relatedStateVariable": "TrafficMode"}, {"direction": "in", "name": "NewManualSpeed", "relatedStateVariable": "ManualSpeed"}, {"direction": "in", "name": "NewMaxSpeedDS", "relatedStateVariable": "MaxSpeedDS"}, {"direction": "in", "name": "NewMaxSpeedUS", "relatedStateVariable": "MaxSpeedUS"}]}, {"name": "X_AVM-DE_GetWLANExtInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_APEnabled", "relatedStateVariable": "X_AVM-DE_APEnabled"}, {"direction": "out", "name": "NewX_AVM-DE_APType", "relatedStateVariable": "X_AVM-DE_APType"}, {"direction": "out", "name": "NewX_AVM-DE_TimeoutActive", "relatedStateVariable": "X_AVM-DE_TimeoutActive"}, {"direction": "out", "name": "NewX_AVM-DE_Timeout", "relatedStateVariable": "X_AVM-DE_Timeout"}, {"direction": "out", "name": "NewX_AVM-DE_TimeRemain", "relatedStateVariable": "X_AVM-DE_TimeRemain"}, {"direction": "out", "name": "NewX_AVM-DE_NoForcedOff", "relatedStateVariable": "X_AVM-DE_NoForcedOff"}, {"direction": "out", "name": "NewX_AVM-DE_UserIsolation", "relatedStateVariable": "X_AVM-DE_UserIsolation"}, {"direction": "out", "name": "NewX_AVM-DE_EncryptionMode", "relatedStateVariable": "X_AVM-DE_EncryptionMode"}, {"direction": "out", "name": "NewX_AVM-DE_LastChangedStamp", "relatedStateVariable": "X_AVM-DE_LastChangedStamp"}]}, {"name": "X_AVM-DE_GetWPSInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_WPSMode", "relatedStateVariable": "X_AVM-DE_WPSMode"}, {"direction": "out", "name": "NewX_AVM-DE_WPSStatus", "relatedStateVariable": "X_AVM-DE_WPSStatus"}]}, {"name": "X_AVM-DE_SetWPSConfig", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WPSMode", "relatedStateVariable": "X_AVM-DE_WPSMode"}, {"direction": "out", "name": "NewX_AVM-DE_WPSStatus", "relatedStateVariable": "X_AVM-DE_WPSStatus"}]}, {"name": "X_AVM-DE_SetWPSEnable", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WPSEnable", "relatedStateVariable": "X_AVM-DE_WPSEnable"}]}, {"name": "X_AVM-DE_SetWLANGlobalEnable", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WLANGlobalEnable", "relatedStateVariable": "X_AVM-DE_WLANGlobalEnable"}]}, {"name": "X_AVM-DE_GetWLANConnectionInfo", "arguments": [{"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewStandard", "relatedStateVariable": "Standard"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedRX", "relatedStateVariable": "X_AVM-DE_SpeedRX"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedMax", "relatedStateVariable": "X_AVM-DE_SpeedMax"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedRXMax", "relatedStateVariable": "X_AVM-DE_SpeedRXMax"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Disabled"], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "Channel"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PossibleChannels"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["none", "Basic", "WPA", "11i", "WPAand11i", "WPA3", "11iandWPA3", "OWE", "OWETrans"], "dataType": "string", "defaultValue": null, "name": "BeaconType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "MACAddressControlEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["b", "g", "n", "ac", "ax", null], "dataType": "string", "defaultValue": null, "name": "Standard"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BasicEncryptionModes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BasicAuthenticationMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey0"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey3"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "WEPKeyIndex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "KeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "32", "name": "MaxCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "1", "name": "MinCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "64", "name": "MinCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "64", "name": "MaxCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFabcdef", "name": "AllowedCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "8", "name": "MinCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "63", "name": "MaxCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "BeaconAdvertisementEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "TotalAssociations"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AssociatedDeviceMACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AssociatedDeviceIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AssociatedDeviceAuthState"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "StickSurfEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_IPTVoptimize"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "X_AVM-DE_SignalStrength"}, "allowedValueRange": {"maximum": "100", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "X_AVM-DE_Speed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "NightControl"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "NightTimeControlNoForcedOff"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "TrafficMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "ManualSpeed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MaxSpeedDS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MaxSpeedUS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_APEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_APType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_TimeoutActive"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Timeout"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_TimeRemain"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_NoForcedOff"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UserIsolation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_EncryptionMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_LastChangedStamp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_PossibleBeaconTypes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["other", "stop", "pbc"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WPSMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["off", "inactive", "active", "success", "err_common", "err_timeout", "err_reconfig", "err_internal", "err_abort", null], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WPSStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_WPSEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WLANDeviceListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedRX"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedMax"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedRXMax"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_WLANGlobalEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/wlanconfigSCPD.xml", "controlURL": "/upnp/control/wlanconfig2", "eventSubURL": "/upnp/control/wlanconfig2", "serviceId": "urn:WLANConfiguration-com:serviceId:WLANConfiguration2", "serviceType": "urn:dslforum-org:service:WLANConfiguration:2"}, "scpd": {"actions": [{"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewX_AVM-DE_PossibleBeaconTypes", "relatedStateVariable": "X_AVM-DE_PossibleBeaconTypes"}, {"direction": "out", "name": "NewMACAddressControlEnabled", "relatedStateVariable": "MACAddressControlEnabled"}, {"direction": "out", "name": "NewStandard", "relatedStateVariable": "Standard"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "out", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}, {"direction": "out", "name": "NewMaxCharsSSID", "relatedStateVariable": "MaxCharsSSID"}, {"direction": "out", "name": "NewMinCharsSSID", "relatedStateVariable": "MinCharsSSID"}, {"direction": "out", "name": "NewAllowedCharsSSID", "relatedStateVariable": "AllowedCharsSSID"}, {"direction": "out", "name": "NewMinCharsPSK", "relatedStateVariable": "MinCharsPSK"}, {"direction": "out", "name": "NewMaxCharsPSK", "relatedStateVariable": "MaxCharsPSK"}, {"direction": "out", "name": "NewAllowedCharsPSK", "relatedStateVariable": "AllowedCharsPSK"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "in", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "in", "name": "NewMACAddressControlEnabled", "relatedStateVariable": "MACAddressControlEnabled"}, {"direction": "in", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "in", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "SetSecurityKeys", "arguments": [{"direction": "in", "name": "NewWEPKey0", "relatedStateVariable": "WEPKey0"}, {"direction": "in", "name": "NewWEPKey1", "relatedStateVariable": "WEPKey1"}, {"direction": "in", "name": "NewWEPKey2", "relatedStateVariable": "WEPKey2"}, {"direction": "in", "name": "NewWEPKey3", "relatedStateVariable": "WEPKey3"}, {"direction": "in", "name": "NewPreSharedKey", "relatedStateVariable": "PreSharedKey"}, {"direction": "in", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}]}, {"name": "GetSecurityKeys", "arguments": [{"direction": "out", "name": "NewWEPKey0", "relatedStateVariable": "WEPKey0"}, {"direction": "out", "name": "NewWEPKey1", "relatedStateVariable": "WEPKey1"}, {"direction": "out", "name": "NewWEPKey2", "relatedStateVariable": "WEPKey2"}, {"direction": "out", "name": "NewWEPKey3", "relatedStateVariable": "WEPKey3"}, {"direction": "out", "name": "NewPreSharedKey", "relatedStateVariable": "PreSharedKey"}, {"direction": "out", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}]}, {"name": "SetDefaultWEPKeyIndex", "arguments": [{"direction": "in", "name": "NewDefaultWEPKeyIndex", "relatedStateVariable": "WEPKeyIndex"}]}, {"name": "GetDefaultWEPKeyIndex", "arguments": [{"direction": "out", "name": "NewDefaultWEPKeyIndex", "relatedStateVariable": "WEPKeyIndex"}]}, {"name": "SetBasBeaconSecurityProperties", "arguments": [{"direction": "in", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "in", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "GetBasBeaconSecurityProperties", "arguments": [{"direction": "out", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "out", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "GetStatistics", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}, {"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetPacketStatistics", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}, {"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetBSSID", "arguments": [{"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}]}, {"name": "GetSSID", "arguments": [{"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}]}, {"name": "SetSSID", "arguments": [{"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}]}, {"name": "GetBeaconType", "arguments": [{"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewX_AVM-DE_PossibleBeaconTypes", "relatedStateVariable": "X_AVM-DE_PossibleBeaconTypes"}]}, {"name": "SetBeaconType", "arguments": [{"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}]}, {"name": "GetChannelInfo", "arguments": [{"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewPossibleChannels", "relatedStateVariable": "PossibleChannels"}]}, {"name": "SetChannel", "arguments": [{"direction": "in", "name": "NewChannel", "relatedStateVariable": "Channel"}]}, {"name": "GetBeaconAdvertisement", "arguments": [{"direction": "out", "name": "NewBeaconAdvertisementEnabled", "relatedStateVariable": "BeaconAdvertisementEnabled"}]}, {"name": "SetBeaconAdvertisement", "arguments": [{"direction": "in", "name": "NewBeaconAdvertisementEnabled", "relatedStateVariable": "BeaconAdvertisementEnabled"}]}, {"name": "GetTotalAssociations", "arguments": [{"direction": "out", "name": "NewTotalAssociations", "relatedStateVariable": "TotalAssociations"}]}, {"name": "GetGenericAssociatedDeviceInfo", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceIndex", "relatedStateVariable": "TotalAssociations"}, {"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "GetSpecificAssociatedDeviceInfo", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "X_AVM-DE_GetSpecificAssociatedDeviceInfoByIp", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "X_AVM-DE_GetWLANDeviceListPath", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_WLANDeviceListPath", "relatedStateVariable": "X_AVM-DE_WLANDeviceListPath"}]}, {"name": "X_AVM-DE_SetStickSurfEnable", "arguments": [{"direction": "in", "name": "NewStickSurfEnable", "relatedStateVariable": "StickSurfEnable"}]}, {"name": "X_AVM-DE_GetIPTVOptimized", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_IPTVoptimize", "relatedStateVariable": "X_AVM-DE_IPTVoptimize"}]}, {"name": "X_AVM-DE_SetIPTVOptimized", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_IPTVoptimize", "relatedStateVariable": "X_AVM-DE_IPTVoptimize"}]}, {"name": "X_AVM-DE_GetNightControl", "arguments": [{"direction": "out", "name": "NewNightControl", "relatedStateVariable": "NightControl"}, {"direction": "out", "name": "NewNightTimeControlNoForcedOff", "relatedStateVariable": "NightTimeControlNoForcedOff"}]}, {"name": "X_AVM-DE_GetWLANHybridMode", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewTrafficMode", "relatedStateVariable": "TrafficMode"}, {"direction": "out", "name": "NewManualSpeed", "relatedStateVariable": "ManualSpeed"}, {"direction": "out", "name": "NewMaxSpeedDS", "relatedStateVariable": "MaxSpeedDS"}, {"direction": "out", "name": "NewMaxSpeedUS", "relatedStateVariable": "MaxSpeedUS"}]}, {"name": "X_AVM-DE_SetWLANHybridMode", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "in", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}, {"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "in", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "in", "name": "NewTrafficMode", "relatedStateVariable": "TrafficMode"}, {"direction": "in", "name": "NewManualSpeed", "relatedStateVariable": "ManualSpeed"}, {"direction": "in", "name": "NewMaxSpeedDS", "relatedStateVariable": "MaxSpeedDS"}, {"direction": "in", "name": "NewMaxSpeedUS", "relatedStateVariable": "MaxSpeedUS"}]}, {"name": "X_AVM-DE_GetWLANExtInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_APEnabled", "relatedStateVariable": "X_AVM-DE_APEnabled"}, {"direction": "out", "name": "NewX_AVM-DE_APType", "relatedStateVariable": "X_AVM-DE_APType"}, {"direction": "out", "name": "NewX_AVM-DE_TimeoutActive", "relatedStateVariable": "X_AVM-DE_TimeoutActive"}, {"direction": "out", "name": "NewX_AVM-DE_Timeout", "relatedStateVariable": "X_AVM-DE_Timeout"}, {"direction": "out", "name": "NewX_AVM-DE_TimeRemain", "relatedStateVariable": "X_AVM-DE_TimeRemain"}, {"direction": "out", "name": "NewX_AVM-DE_NoForcedOff", "relatedStateVariable": "X_AVM-DE_NoForcedOff"}, {"direction": "out", "name": "NewX_AVM-DE_UserIsolation", "relatedStateVariable": "X_AVM-DE_UserIsolation"}, {"direction": "out", "name": "NewX_AVM-DE_EncryptionMode", "relatedStateVariable": "X_AVM-DE_EncryptionMode"}, {"direction": "out", "name": "NewX_AVM-DE_LastChangedStamp", "relatedStateVariable": "X_AVM-DE_LastChangedStamp"}]}, {"name": "X_AVM-DE_GetWPSInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_WPSMode", "relatedStateVariable": "X_AVM-DE_WPSMode"}, {"direction": "out", "name": "NewX_AVM-DE_WPSStatus", "relatedStateVariable": "X_AVM-DE_WPSStatus"}]}, {"name": "X_AVM-DE_SetWPSConfig", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WPSMode", "relatedStateVariable": "X_AVM-DE_WPSMode"}, {"direction": "out", "name": "NewX_AVM-DE_WPSStatus", "relatedStateVariable": "X_AVM-DE_WPSStatus"}]}, {"name": "X_AVM-DE_SetWPSEnable", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WPSEnable", "relatedStateVariable": "X_AVM-DE_WPSEnable"}]}, {"name": "X_AVM-DE_SetWLANGlobalEnable", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WLANGlobalEnable", "relatedStateVariable": "X_AVM-DE_WLANGlobalEnable"}]}, {"name": "X_AVM-DE_GetWLANConnectionInfo", "arguments": [{"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewStandard", "relatedStateVariable": "Standard"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedRX", "relatedStateVariable": "X_AVM-DE_SpeedRX"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedMax", "relatedStateVariable": "X_AVM-DE_SpeedMax"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedRXMax", "relatedStateVariable": "X_AVM-DE_SpeedRXMax"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Disabled"], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "Channel"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PossibleChannels"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["none", "Basic", "WPA", "11i", "WPAand11i", "WPA3", "11iandWPA3", "OWE", "OWETrans"], "dataType": "string", "defaultValue": null, "name": "BeaconType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "MACAddressControlEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["b", "g", "n", "ac", "ax", null], "dataType": "string", "defaultValue": null, "name": "Standard"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BasicEncryptionModes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BasicAuthenticationMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey0"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey3"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "WEPKeyIndex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "KeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "32", "name": "MaxCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "1", "name": "MinCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "64", "name": "MinCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "64", "name": "MaxCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFabcdef", "name": "AllowedCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "8", "name": "MinCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "63", "name": "MaxCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "BeaconAdvertisementEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "TotalAssociations"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AssociatedDeviceMACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AssociatedDeviceIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AssociatedDeviceAuthState"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "StickSurfEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_IPTVoptimize"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "X_AVM-DE_SignalStrength"}, "allowedValueRange": {"maximum": "100", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "X_AVM-DE_Speed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "NightControl"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "NightTimeControlNoForcedOff"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "TrafficMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "ManualSpeed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MaxSpeedDS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MaxSpeedUS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_APEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_APType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_TimeoutActive"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Timeout"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_TimeRemain"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_NoForcedOff"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UserIsolation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_EncryptionMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_LastChangedStamp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_PossibleBeaconTypes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["other", "stop", "pbc"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WPSMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["off", "inactive", "active", "success", "err_common", "err_timeout", "err_reconfig", "err_internal", "err_abort", null], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WPSStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_WPSEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WLANDeviceListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedRX"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedMax"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedRXMax"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_WLANGlobalEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/wlanconfigSCPD.xml", "controlURL": "/upnp/control/wlanconfig3", "eventSubURL": "/upnp/control/wlanconfig3", "serviceId": "urn:WLANConfiguration-com:serviceId:WLANConfiguration3", "serviceType": "urn:dslforum-org:service:WLANConfiguration:3"}, "scpd": {"actions": [{"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewX_AVM-DE_PossibleBeaconTypes", "relatedStateVariable": "X_AVM-DE_PossibleBeaconTypes"}, {"direction": "out", "name": "NewMACAddressControlEnabled", "relatedStateVariable": "MACAddressControlEnabled"}, {"direction": "out", "name": "NewStandard", "relatedStateVariable": "Standard"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "out", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}, {"direction": "out", "name": "NewMaxCharsSSID", "relatedStateVariable": "MaxCharsSSID"}, {"direction": "out", "name": "NewMinCharsSSID", "relatedStateVariable": "MinCharsSSID"}, {"direction": "out", "name": "NewAllowedCharsSSID", "relatedStateVariable": "AllowedCharsSSID"}, {"direction": "out", "name": "NewMinCharsPSK", "relatedStateVariable": "MinCharsPSK"}, {"direction": "out", "name": "NewMaxCharsPSK", "relatedStateVariable": "MaxCharsPSK"}, {"direction": "out", "name": "NewAllowedCharsPSK", "relatedStateVariable": "AllowedCharsPSK"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "in", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "in", "name": "NewMACAddressControlEnabled", "relatedStateVariable": "MACAddressControlEnabled"}, {"direction": "in", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "in", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "SetSecurityKeys", "arguments": [{"direction": "in", "name": "NewWEPKey0", "relatedStateVariable": "WEPKey0"}, {"direction": "in", "name": "NewWEPKey1", "relatedStateVariable": "WEPKey1"}, {"direction": "in", "name": "NewWEPKey2", "relatedStateVariable": "WEPKey2"}, {"direction": "in", "name": "NewWEPKey3", "relatedStateVariable": "WEPKey3"}, {"direction": "in", "name": "NewPreSharedKey", "relatedStateVariable": "PreSharedKey"}, {"direction": "in", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}]}, {"name": "GetSecurityKeys", "arguments": [{"direction": "out", "name": "NewWEPKey0", "relatedStateVariable": "WEPKey0"}, {"direction": "out", "name": "NewWEPKey1", "relatedStateVariable": "WEPKey1"}, {"direction": "out", "name": "NewWEPKey2", "relatedStateVariable": "WEPKey2"}, {"direction": "out", "name": "NewWEPKey3", "relatedStateVariable": "WEPKey3"}, {"direction": "out", "name": "NewPreSharedKey", "relatedStateVariable": "PreSharedKey"}, {"direction": "out", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}]}, {"name": "SetDefaultWEPKeyIndex", "arguments": [{"direction": "in", "name": "NewDefaultWEPKeyIndex", "relatedStateVariable": "WEPKeyIndex"}]}, {"name": "GetDefaultWEPKeyIndex", "arguments": [{"direction": "out", "name": "NewDefaultWEPKeyIndex", "relatedStateVariable": "WEPKeyIndex"}]}, {"name": "SetBasBeaconSecurityProperties", "arguments": [{"direction": "in", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "in", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "GetBasBeaconSecurityProperties", "arguments": [{"direction": "out", "name": "NewBasicEncryptionModes", "relatedStateVariable": "BasicEncryptionModes"}, {"direction": "out", "name": "NewBasicAuthenticationMode", "relatedStateVariable": "BasicAuthenticationMode"}]}, {"name": "GetStatistics", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}, {"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetPacketStatistics", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}, {"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "GetBSSID", "arguments": [{"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}]}, {"name": "GetSSID", "arguments": [{"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}]}, {"name": "SetSSID", "arguments": [{"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}]}, {"name": "GetBeaconType", "arguments": [{"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewX_AVM-DE_PossibleBeaconTypes", "relatedStateVariable": "X_AVM-DE_PossibleBeaconTypes"}]}, {"name": "SetBeaconType", "arguments": [{"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}]}, {"name": "GetChannelInfo", "arguments": [{"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewPossibleChannels", "relatedStateVariable": "PossibleChannels"}]}, {"name": "SetChannel", "arguments": [{"direction": "in", "name": "NewChannel", "relatedStateVariable": "Channel"}]}, {"name": "GetBeaconAdvertisement", "arguments": [{"direction": "out", "name": "NewBeaconAdvertisementEnabled", "relatedStateVariable": "BeaconAdvertisementEnabled"}]}, {"name": "SetBeaconAdvertisement", "arguments": [{"direction": "in", "name": "NewBeaconAdvertisementEnabled", "relatedStateVariable": "BeaconAdvertisementEnabled"}]}, {"name": "GetTotalAssociations", "arguments": [{"direction": "out", "name": "NewTotalAssociations", "relatedStateVariable": "TotalAssociations"}]}, {"name": "GetGenericAssociatedDeviceInfo", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceIndex", "relatedStateVariable": "TotalAssociations"}, {"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "GetSpecificAssociatedDeviceInfo", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "X_AVM-DE_GetSpecificAssociatedDeviceInfoByIp", "arguments": [{"direction": "in", "name": "NewAssociatedDeviceIPAddress", "relatedStateVariable": "AssociatedDeviceIPAddress"}, {"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewAssociatedDeviceAuthState", "relatedStateVariable": "AssociatedDeviceAuthState"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}]}, {"name": "X_AVM-DE_GetWLANDeviceListPath", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_WLANDeviceListPath", "relatedStateVariable": "X_AVM-DE_WLANDeviceListPath"}]}, {"name": "X_AVM-DE_SetStickSurfEnable", "arguments": [{"direction": "in", "name": "NewStickSurfEnable", "relatedStateVariable": "StickSurfEnable"}]}, {"name": "X_AVM-DE_GetIPTVOptimized", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_IPTVoptimize", "relatedStateVariable": "X_AVM-DE_IPTVoptimize"}]}, {"name": "X_AVM-DE_SetIPTVOptimized", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_IPTVoptimize", "relatedStateVariable": "X_AVM-DE_IPTVoptimize"}]}, {"name": "X_AVM-DE_GetNightControl", "arguments": [{"direction": "out", "name": "NewNightControl", "relatedStateVariable": "NightControl"}, {"direction": "out", "name": "NewNightTimeControlNoForcedOff", "relatedStateVariable": "NightTimeControlNoForcedOff"}]}, {"name": "X_AVM-DE_GetWLANHybridMode", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewTrafficMode", "relatedStateVariable": "TrafficMode"}, {"direction": "out", "name": "NewManualSpeed", "relatedStateVariable": "ManualSpeed"}, {"direction": "out", "name": "NewMaxSpeedDS", "relatedStateVariable": "MaxSpeedDS"}, {"direction": "out", "name": "NewMaxSpeedUS", "relatedStateVariable": "MaxSpeedUS"}]}, {"name": "X_AVM-DE_SetWLANHybridMode", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "in", "name": "NewKeyPassphrase", "relatedStateVariable": "KeyPassphrase"}, {"direction": "in", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "in", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "in", "name": "NewTrafficMode", "relatedStateVariable": "TrafficMode"}, {"direction": "in", "name": "NewManualSpeed", "relatedStateVariable": "ManualSpeed"}, {"direction": "in", "name": "NewMaxSpeedDS", "relatedStateVariable": "MaxSpeedDS"}, {"direction": "in", "name": "NewMaxSpeedUS", "relatedStateVariable": "MaxSpeedUS"}]}, {"name": "X_AVM-DE_GetWLANExtInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_APEnabled", "relatedStateVariable": "X_AVM-DE_APEnabled"}, {"direction": "out", "name": "NewX_AVM-DE_APType", "relatedStateVariable": "X_AVM-DE_APType"}, {"direction": "out", "name": "NewX_AVM-DE_TimeoutActive", "relatedStateVariable": "X_AVM-DE_TimeoutActive"}, {"direction": "out", "name": "NewX_AVM-DE_Timeout", "relatedStateVariable": "X_AVM-DE_Timeout"}, {"direction": "out", "name": "NewX_AVM-DE_TimeRemain", "relatedStateVariable": "X_AVM-DE_TimeRemain"}, {"direction": "out", "name": "NewX_AVM-DE_NoForcedOff", "relatedStateVariable": "X_AVM-DE_NoForcedOff"}, {"direction": "out", "name": "NewX_AVM-DE_UserIsolation", "relatedStateVariable": "X_AVM-DE_UserIsolation"}, {"direction": "out", "name": "NewX_AVM-DE_EncryptionMode", "relatedStateVariable": "X_AVM-DE_EncryptionMode"}, {"direction": "out", "name": "NewX_AVM-DE_LastChangedStamp", "relatedStateVariable": "X_AVM-DE_LastChangedStamp"}]}, {"name": "X_AVM-DE_GetWPSInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_WPSMode", "relatedStateVariable": "X_AVM-DE_WPSMode"}, {"direction": "out", "name": "NewX_AVM-DE_WPSStatus", "relatedStateVariable": "X_AVM-DE_WPSStatus"}]}, {"name": "X_AVM-DE_SetWPSConfig", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WPSMode", "relatedStateVariable": "X_AVM-DE_WPSMode"}, {"direction": "out", "name": "NewX_AVM-DE_WPSStatus", "relatedStateVariable": "X_AVM-DE_WPSStatus"}]}, {"name": "X_AVM-DE_SetWPSEnable", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WPSEnable", "relatedStateVariable": "X_AVM-DE_WPSEnable"}]}, {"name": "X_AVM-DE_SetWLANGlobalEnable", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_WLANGlobalEnable", "relatedStateVariable": "X_AVM-DE_WLANGlobalEnable"}]}, {"name": "X_AVM-DE_GetWLANConnectionInfo", "arguments": [{"direction": "out", "name": "NewAssociatedDeviceMACAddress", "relatedStateVariable": "AssociatedDeviceMACAddress"}, {"direction": "out", "name": "NewSSID", "relatedStateVariable": "SSID"}, {"direction": "out", "name": "NewBSSID", "relatedStateVariable": "BSSID"}, {"direction": "out", "name": "NewBeaconType", "relatedStateVariable": "BeaconType"}, {"direction": "out", "name": "NewChannel", "relatedStateVariable": "Channel"}, {"direction": "out", "name": "NewStandard", "relatedStateVariable": "Standard"}, {"direction": "out", "name": "NewX_AVM-DE_SignalStrength", "relatedStateVariable": "X_AVM-DE_SignalStrength"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedRX", "relatedStateVariable": "X_AVM-DE_SpeedRX"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedMax", "relatedStateVariable": "X_AVM-DE_SpeedMax"}, {"direction": "out", "name": "NewX_AVM-DE_SpeedRXMax", "relatedStateVariable": "X_AVM-DE_SpeedRXMax"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Disabled"], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "Channel"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PossibleChannels"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["none", "Basic", "WPA", "11i", "WPAand11i", "WPA3", "11iandWPA3", "OWE", "OWETrans"], "dataType": "string", "defaultValue": null, "name": "BeaconType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "MACAddressControlEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["b", "g", "n", "ac", "ax", null], "dataType": "string", "defaultValue": null, "name": "Standard"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BasicEncryptionModes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BasicAuthenticationMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey0"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WEPKey3"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "WEPKeyIndex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "KeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "32", "name": "MaxCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "1", "name": "MinCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsSSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "64", "name": "MinCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "64", "name": "MaxCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFabcdef", "name": "AllowedCharsPSK"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "8", "name": "MinCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "63", "name": "MaxCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsKeyPassphrase"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "BeaconAdvertisementEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "TotalAssociations"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AssociatedDeviceMACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AssociatedDeviceIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AssociatedDeviceAuthState"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "StickSurfEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_IPTVoptimize"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "X_AVM-DE_SignalStrength"}, "allowedValueRange": {"maximum": "100", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "X_AVM-DE_Speed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "NightControl"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "NightTimeControlNoForcedOff"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "TrafficMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "ManualSpeed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MaxSpeedDS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MaxSpeedUS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_APEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_APType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_TimeoutActive"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Timeout"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_TimeRemain"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_NoForcedOff"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UserIsolation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_EncryptionMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_LastChangedStamp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_PossibleBeaconTypes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["other", "stop", "pbc"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WPSMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["off", "inactive", "active", "success", "err_common", "err_timeout", "err_reconfig", "err_internal", "err_abort", null], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WPSStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_WPSEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WLANDeviceListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedRX"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedMax"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_SpeedRXMax"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_WLANGlobalEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/hostsSCPD.xml", "controlURL": "/upnp/control/hosts", "eventSubURL": "/upnp/control/hosts", "serviceId": "urn:LanDeviceHosts-com:serviceId:Hosts1", "serviceType": "urn:dslforum-org:service:Hosts:1"}, "scpd": {"actions": [{"name": "GetHostNumberOfEntries", "arguments": [{"direction": "out", "name": "NewHostNumberOfEntries", "relatedStateVariable": "HostNumberOfEntries"}]}, {"name": "GetSpecificHostEntry", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewIPAddress", "relatedStateVariable": "IPAddress"}, {"direction": "out", "name": "NewAddressSource", "relatedStateVariable": "AddressSource"}, {"direction": "out", "name": "NewLeaseTimeRemaining", "relatedStateVariable": "LeaseTimeRemaining"}, {"direction": "out", "name": "NewInterfaceType", "relatedStateVariable": "InterfaceType"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewHostName", "relatedStateVariable": "HostName"}]}, {"name": "GetGenericHostEntry", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "HostNumberOfEntries"}, {"direction": "out", "name": "NewIPAddress", "relatedStateVariable": "IPAddress"}, {"direction": "out", "name": "NewAddressSource", "relatedStateVariable": "AddressSource"}, {"direction": "out", "name": "NewLeaseTimeRemaining", "relatedStateVariable": "LeaseTimeRemaining"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewInterfaceType", "relatedStateVariable": "InterfaceType"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewHostName", "relatedStateVariable": "HostName"}]}, {"name": "X_AVM-DE_GetChangeCounter", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_ChangeCounter", "relatedStateVariable": "X_AVM-DE_ChangeCounter"}]}, {"name": "X_AVM-DE_SetHostNameByMACAddress", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "in", "name": "NewHostName", "relatedStateVariable": "HostName"}]}, {"name": "X_AVM-DE_GetAutoWakeOnLANByMACAddress", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewAutoWOLEnabled", "relatedStateVariable": "AutoWOLEnabled"}]}, {"name": "X_AVM-DE_SetAutoWakeOnLANByMACAddress", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "in", "name": "NewAutoWOLEnabled", "relatedStateVariable": "AutoWOLEnabled"}]}, {"name": "X_AVM-DE_WakeOnLANByMACAddress", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}]}, {"name": "X_AVM-DE_GetSpecificHostEntryByIP", "arguments": [{"direction": "in", "name": "NewIPAddress", "relatedStateVariable": "IPAddress"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewHostName", "relatedStateVariable": "HostName"}, {"direction": "out", "name": "NewInterfaceType", "relatedStateVariable": "InterfaceType"}, {"direction": "out", "name": "NewX_AVM-DE_Port", "relatedStateVariable": "X_AVM-DE_Port"}, {"direction": "out", "name": "NewX_AVM-DE_Speed", "relatedStateVariable": "X_AVM-DE_Speed"}, {"direction": "out", "name": "NewX_AVM-DE_UpdateAvailable", "relatedStateVariable": "X_AVM-DE_UpdateAvailable"}, {"direction": "out", "name": "NewX_AVM-DE_UpdateSuccessful", "relatedStateVariable": "X_AVM-DE_UpdateSuccessful"}, {"direction": "out", "name": "NewX_AVM-DE_InfoURL", "relatedStateVariable": "X_AVM-DE_InfoURL"}, {"direction": "out", "name": "NewX_AVM-DE_Model", "relatedStateVariable": "X_AVM-DE_Model"}, {"direction": "out", "name": "NewX_AVM-DE_URL", "relatedStateVariable": "X_AVM-DE_URL"}]}, {"name": "X_AVM-DE_HostsCheckUpdate", "arguments": []}, {"name": "X_AVM-DE_HostDoUpdate", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}]}, {"name": "X_AVM-DE_GetHostListPath", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_HostListPath", "relatedStateVariable": "X_AVM-DE_HostListPath"}]}, {"name": "X_AVM-DE_GetMeshListPath", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_MeshListPath", "relatedStateVariable": "X_AVM-DE_MeshListPath"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "HostNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AddressSource"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "LeaseTimeRemaining"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "InterfaceType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Active"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "HostName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_ChangeCounter"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AutoWOLEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_Disallow"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_Port"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_Speed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_URL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_UpdateAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["unknown", "failed", "succeeded"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UpdateSuccessful"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_InfoURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Model"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_HostListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_MeshListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["error", "granted", "denied"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_WANAccess"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/ethifconfigSCPD.xml", "controlURL": "/upnp/control/lanethernetifcfg", "eventSubURL": "/upnp/control/lanethernetifcfg", "serviceId": "urn:LANEthernetIfCfg-com:serviceId:LANEthernetInterfaceConfig1", "serviceType": "urn:dslforum-org:service:LANEthernetInterfaceConfig:1"}, "scpd": {"actions": [{"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewMaxBitRate", "relatedStateVariable": "MaxBitRate"}, {"direction": "out", "name": "NewDuplexMode", "relatedStateVariable": "DuplexMode"}]}, {"name": "GetStatistics", "arguments": [{"direction": "out", "name": "NewBytesSent", "relatedStateVariable": "Stats.BytesSent"}, {"direction": "out", "name": "NewBytesReceived", "relatedStateVariable": "Stats.BytesReceived"}, {"direction": "out", "name": "NewPacketsSent", "relatedStateVariable": "Stats.PacketsSent"}, {"direction": "out", "name": "NewPacketsReceived", "relatedStateVariable": "Stats.PacketsReceived"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DuplexMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.BytesSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.BytesReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.PacketsSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.PacketsReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/lanhostconfigmgmSCPD.xml", "controlURL": "/upnp/control/lanhostconfigmgm", "eventSubURL": "/upnp/control/lanhostconfigmgm", "serviceId": "urn:LANHCfgMgm-com:serviceId:LANHostConfigManagement1", "serviceType": "urn:dslforum-org:service:LANHostConfigManagement:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewDHCPServerConfigurable", "relatedStateVariable": "DHCPServerConfigurable"}, {"direction": "out", "name": "NewDHCPRelay", "relatedStateVariable": "DHCPRelay"}, {"direction": "out", "name": "NewMinAddress", "relatedStateVariable": "MinAddress"}, {"direction": "out", "name": "NewMaxAddress", "relatedStateVariable": "MaxAddress"}, {"direction": "out", "name": "NewReservedAddresses", "relatedStateVariable": "ReservedAddresses"}, {"direction": "out", "name": "NewDHCPServerEnable", "relatedStateVariable": "DHCPServerEnable"}, {"direction": "out", "name": "NewDNSServers", "relatedStateVariable": "DNSServers"}, {"direction": "out", "name": "NewDomainName", "relatedStateVariable": "DomainName"}, {"direction": "out", "name": "NewIPRouters", "relatedStateVariable": "IPRouters"}, {"direction": "out", "name": "NewSubnetMask", "relatedStateVariable": "SubnetMask"}]}, {"name": "SetDHCPServerEnable", "arguments": [{"direction": "in", "name": "NewDHCPServerEnable", "relatedStateVariable": "DHCPServerEnable"}]}, {"name": "SetIPInterface", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewIPAddress", "relatedStateVariable": "IPInterfaceIPAddress"}, {"direction": "in", "name": "NewSubnetMask", "relatedStateVariable": "IPInterfaceSubnetMask"}, {"direction": "in", "name": "NewIPAddressingType", "relatedStateVariable": "IPInterfaceIPAddressingType"}]}, {"name": "GetAddressRange", "arguments": [{"direction": "out", "name": "NewMinAddress", "relatedStateVariable": "MinAddress"}, {"direction": "out", "name": "NewMaxAddress", "relatedStateVariable": "MaxAddress"}]}, {"name": "SetAddressRange", "arguments": [{"direction": "in", "name": "NewMinAddress", "relatedStateVariable": "MinAddress"}, {"direction": "in", "name": "NewMaxAddress", "relatedStateVariable": "MaxAddress"}]}, {"name": "GetIPRoutersList", "arguments": [{"direction": "out", "name": "NewIPRouters", "relatedStateVariable": "IPRouters"}]}, {"name": "SetIPRouter", "arguments": [{"direction": "in", "name": "NewIPRouters", "relatedStateVariable": "IPRouters"}]}, {"name": "GetSubnetMask", "arguments": [{"direction": "out", "name": "NewSubnetMask", "relatedStateVariable": "SubnetMask"}]}, {"name": "SetSubnetMask", "arguments": [{"direction": "in", "name": "NewSubnetMask", "relatedStateVariable": "SubnetMask"}]}, {"name": "GetDNSServers", "arguments": [{"direction": "out", "name": "NewDNSServers", "relatedStateVariable": "DNSServers"}]}, {"name": "GetIPInterfaceNumberOfEntries", "arguments": [{"direction": "out", "name": "NewIPInterfaceNumberOfEntries", "relatedStateVariable": "IPInterfaceNumberOfEntries"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DHCPServerConfigurable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DHCPRelay"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MinAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MaxAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ReservedAddresses"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DHCPServerEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPInterfaceIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SubnetMask"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPInterfaceIPAddressingType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DNSServers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DomainName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPRouters"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPInterfaceSubnetMask"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "IPInterfaceNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}, {"attributes": {"UDN": "uuid:75802409-bccb-40e7-8e6a-989BCB2B93B0", "UPC": "AVM TR-064", "deviceType": "urn:dslforum-org:device:WANDevice:1", "friendlyName": "WANDevice - FRITZ!Box 7590", "manufacturer": "AVM", "manufacturerURL": "www.avm.de", "modelDescription": "WANDevice - FRITZ!Box 7590", "modelName": "WANDevice - FRITZ!Box 7590", "modelNumber": "- avm", "modelURL": "www.avm.de", "presentationURL": null}, "devices": [{"attributes": {"UDN": "uuid:75802409-bccb-40e7-8e69-989BCB2B93B0", "UPC": "AVM TR-064", "deviceType": "urn:dslforum-org:device:WANConnectionDevice:1", "friendlyName": "WANConnectionDevice - FRITZ!Box 7590", "manufacturer": "AVM", "manufacturerURL": "www.avm.de", "modelDescription": "WANConnectionDevice - FRITZ!Box 7590", "modelName": "WANConnectionDevice - FRITZ!Box 7590", "modelNumber": "- avm", "modelURL": "www.avm.de", "presentationURL": null}, "devices": [], "services": [{"attributes": {"SCPDURL": "/wandsllinkconfigSCPD.xml", "controlURL": "/upnp/control/wandsllinkconfig1", "eventSubURL": "/upnp/control/wandsllinkconfig1", "serviceId": "urn:WANDSLLinkConfig-com:serviceId:WANDSLLinkConfig1", "serviceType": "urn:dslforum-org:service:WANDSLLinkConfig:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewLinkStatus", "relatedStateVariable": "LinkStatus"}, {"direction": "out", "name": "NewLinkType", "relatedStateVariable": "LinkType"}, {"direction": "out", "name": "NewDestinationAddress", "relatedStateVariable": "DestinationAddress"}, {"direction": "out", "name": "NewATMEncapsulation", "relatedStateVariable": "ATMEncapsulation"}, {"direction": "out", "name": "NewAutoConfig", "relatedStateVariable": "AutoConfig"}, {"direction": "out", "name": "NewATMQoS", "relatedStateVariable": "ATMQoS"}, {"direction": "out", "name": "NewATMPeakCellRate", "relatedStateVariable": "ATMPeakCellRate"}, {"direction": "out", "name": "NewATMSustainableCellRate", "relatedStateVariable": "ATMSustainableCellRate"}]}, {"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "GetAutoConfig", "arguments": [{"direction": "out", "name": "NewAutoConfig", "relatedStateVariable": "AutoConfig"}]}, {"name": "SetDSLLinkType", "arguments": [{"direction": "in", "name": "NewLinkType", "relatedStateVariable": "LinkType"}]}, {"name": "GetDSLLinkInfo", "arguments": [{"direction": "out", "name": "NewLinkType", "relatedStateVariable": "LinkType"}, {"direction": "out", "name": "NewLinkStatus", "relatedStateVariable": "LinkStatus"}]}, {"name": "SetDestinationAddress", "arguments": [{"direction": "in", "name": "NewDestinationAddress", "relatedStateVariable": "DestinationAddress"}]}, {"name": "GetDestinationAddress", "arguments": [{"direction": "out", "name": "NewDestinationAddress", "relatedStateVariable": "DestinationAddress"}]}, {"name": "SetATMEncapsulation", "arguments": [{"direction": "in", "name": "NewATMEncapsulation", "relatedStateVariable": "ATMEncapsulation"}]}, {"name": "GetATMEncapsulation", "arguments": [{"direction": "out", "name": "NewATMEncapsulation", "relatedStateVariable": "ATMEncapsulation"}]}, {"name": "GetStatistics", "arguments": [{"direction": "out", "name": "NewATMTransmittedBlocks", "relatedStateVariable": "ATMTransmittedBlocks"}, {"direction": "out", "name": "NewATMReceivedBlocks", "relatedStateVariable": "ATMReceivedBlocks"}, {"direction": "out", "name": "NewAAL5CRCErrors", "relatedStateVariable": "AAL5CRCErrors"}, {"direction": "out", "name": "NewATMCRCErrors", "relatedStateVariable": "ATMCRCErrors"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["EoA", "PPPoA", "PPPoE", "Unconfigured"], "dataType": "string", "defaultValue": null, "name": "LinkType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Down", "Initializing", "Unavailable"], "dataType": "string", "defaultValue": null, "name": "LinkStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DestinationAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["LLC", "VCMUX"], "dataType": "string", "defaultValue": null, "name": "ATMEncapsulation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AutoConfig"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ATMQoS"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ATMPeakCellRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ATMSustainableCellRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ATMTransmittedBlocks"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ATMReceivedBlocks"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "AAL5CRCErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "ATMCRCErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/wanethlinkconfigSCPD.xml", "controlURL": "/upnp/control/wanethlinkconfig1", "eventSubURL": "/upnp/control/wanethlinkconfig1", "serviceId": "urn:WANEthernetLinkConfig-com:serviceId:WANEthernetLinkConfig1", "serviceType": "urn:dslforum-org:service:WANEthernetLinkConfig:1"}, "scpd": {"actions": [{"name": "GetEthernetLinkStatus", "arguments": [{"direction": "out", "name": "NewEthernetLinkStatus", "relatedStateVariable": "EthernetLinkStatus"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "EthernetLinkStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/wanpppconnSCPD.xml", "controlURL": "/upnp/control/wanpppconn1", "eventSubURL": "/upnp/control/wanpppconn1", "serviceId": "urn:WANPPPConnection-com:serviceId:WANPPPConnection1", "serviceType": "urn:dslforum-org:service:WANPPPConnection:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewConnectionStatus", "relatedStateVariable": "ConnectionStatus"}, {"direction": "out", "name": "NewPossibleConnectionTypes", "relatedStateVariable": "PossibleConnectionTypes"}, {"direction": "out", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewUptime", "relatedStateVariable": "Uptime"}, {"direction": "out", "name": "NewUpstreamMaxBitRate", "relatedStateVariable": "UpstreamMaxBitRate"}, {"direction": "out", "name": "NewDownstreamMaxBitRate", "relatedStateVariable": "DownstreamMaxBitRate"}, {"direction": "out", "name": "NewLastConnectionError", "relatedStateVariable": "LastConnectionError"}, {"direction": "out", "name": "NewIdleDisconnectTime", "relatedStateVariable": "IdleDisconnectTime"}, {"direction": "out", "name": "NewRSIPAvailable", "relatedStateVariable": "RSIPAvailable"}, {"direction": "out", "name": "NewUserName", "relatedStateVariable": "UserName"}, {"direction": "out", "name": "NewNATEnabled", "relatedStateVariable": "NATEnabled"}, {"direction": "out", "name": "NewExternalIPAddress", "relatedStateVariable": "ExternalIPAddress"}, {"direction": "out", "name": "NewDNSServers", "relatedStateVariable": "DNSServers"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewConnectionTrigger", "relatedStateVariable": "ConnectionTrigger"}, {"direction": "out", "name": "NewLastAuthErrorInfo", "relatedStateVariable": "LastAuthErrorInfo"}, {"direction": "out", "name": "NewMaxCharsUsername", "relatedStateVariable": "MaxCharsUsername"}, {"direction": "out", "name": "NewMinCharsUsername", "relatedStateVariable": "MinCharsUsername"}, {"direction": "out", "name": "NewAllowedCharsUsername", "relatedStateVariable": "AllowedCharsUsername"}, {"direction": "out", "name": "NewMaxCharsPassword", "relatedStateVariable": "MaxCharsPassword"}, {"direction": "out", "name": "NewMinCharsPassword", "relatedStateVariable": "MinCharsPassword"}, {"direction": "out", "name": "NewAllowedCharsPassword", "relatedStateVariable": "AllowedCharsPassword"}, {"direction": "out", "name": "NewTransportType", "relatedStateVariable": "TransportType"}, {"direction": "out", "name": "NewRouteProtocolRx", "relatedStateVariable": "RouteProtocolRx"}, {"direction": "out", "name": "NewPPPoEServiceName", "relatedStateVariable": "PPPoEServiceName"}, {"direction": "out", "name": "NewRemoteIPAddress", "relatedStateVariable": "RemoteIPAddress"}, {"direction": "out", "name": "NewPPPoEACName", "relatedStateVariable": "PPPoEACName"}, {"direction": "out", "name": "NewDNSEnabled", "relatedStateVariable": "DNSEnabled"}, {"direction": "out", "name": "NewDNSOverrideAllowed", "relatedStateVariable": "DNSOverrideAllowed"}]}, {"name": "GetConnectionTypeInfo", "arguments": [{"direction": "out", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}, {"direction": "out", "name": "NewPossibleConnectionTypes", "relatedStateVariable": "PossibleConnectionTypes"}]}, {"name": "SetConnectionType", "arguments": [{"direction": "in", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}]}, {"name": "GetStatusInfo", "arguments": [{"direction": "out", "name": "NewConnectionStatus", "relatedStateVariable": "ConnectionStatus"}, {"direction": "out", "name": "NewLastConnectionError", "relatedStateVariable": "LastConnectionError"}, {"direction": "out", "name": "NewUptime", "relatedStateVariable": "Uptime"}]}, {"name": "GetUserName", "arguments": [{"direction": "out", "name": "NewUserName", "relatedStateVariable": "UserName"}]}, {"name": "SetUserName", "arguments": [{"direction": "in", "name": "NewUserName", "relatedStateVariable": "UserName"}]}, {"name": "SetPassword", "arguments": [{"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}]}, {"name": "GetNATRSIPStatus", "arguments": [{"direction": "out", "name": "NewRSIPAvailable", "relatedStateVariable": "RSIPAvailable"}, {"direction": "out", "name": "NewNATEnabled", "relatedStateVariable": "NATEnabled"}]}, {"name": "SetConnectionTrigger", "arguments": [{"direction": "in", "name": "NewConnectionTrigger", "relatedStateVariable": "ConnectionTrigger"}]}, {"name": "ForceTermination", "arguments": []}, {"name": "RequestConnection", "arguments": []}, {"name": "GetGenericPortMappingEntry", "arguments": [{"direction": "in", "name": "NewPortMappingIndex", "relatedStateVariable": "PortMappingNumberOfEntries"}, {"direction": "out", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "out", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "out", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "out", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "out", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "out", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "out", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "GetSpecificPortMappingEntry", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "out", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "out", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "out", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "out", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "AddPortMapping", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "in", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "in", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "in", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "in", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "in", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "DeletePortMapping", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}]}, {"name": "GetExternalIPAddress", "arguments": [{"direction": "out", "name": "NewExternalIPAddress", "relatedStateVariable": "ExternalIPAddress"}]}, {"name": "X_GetDNSServers", "arguments": [{"direction": "out", "name": "NewDNSServers", "relatedStateVariable": "DNSServers"}]}, {"name": "GetLinkLayerMaxBitRates", "arguments": [{"direction": "out", "name": "NewUpstreamMaxBitRate", "relatedStateVariable": "UpstreamMaxBitRate"}, {"direction": "out", "name": "NewDownstreamMaxBitRate", "relatedStateVariable": "DownstreamMaxBitRate"}]}, {"name": "GetPortMappingNumberOfEntries", "arguments": [{"direction": "out", "name": "NewPortMappingNumberOfEntries", "relatedStateVariable": "PortMappingNumberOfEntries"}]}, {"name": "SetRouteProtocolRx", "arguments": [{"direction": "in", "name": "NewRouteProtocolRx", "relatedStateVariable": "RouteProtocolRx"}]}, {"name": "SetIdleDisconnectTime", "arguments": [{"direction": "in", "name": "NewIdleDisconnectTime", "relatedStateVariable": "IdleDisconnectTime"}]}, {"name": "X_AVM-DE_GetAutoDisconnectTimeSpan", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_DisconnectPreventionEnable", "relatedStateVariable": "X_AVM-DE_DisconnectPreventionEnable"}, {"direction": "out", "name": "NewX_AVM-DE_DisconnectPreventionHour", "relatedStateVariable": "X_AVM-DE_DisconnectPreventionHour"}]}, {"name": "X_AVM-DE_SetAutoDisconnectTimeSpan", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_DisconnectPreventionEnable", "relatedStateVariable": "X_AVM-DE_DisconnectPreventionEnable"}, {"direction": "in", "name": "NewX_AVM-DE_DisconnectPreventionHour", "relatedStateVariable": "X_AVM-DE_DisconnectPreventionHour"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "IP_Routed", "IP_Bridged"], "dataType": "string", "defaultValue": "Unconfigured", "name": "ConnectionType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "IP_Routed", "IP_Bridged"], "dataType": "string", "defaultValue": null, "name": "PossibleConnectionTypes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "Connecting", "Authenticating", "PendingDisconnect", "Disconnecting", "Disconnected", "Connected"], "dataType": "string", "defaultValue": "Unconfigured", "name": "ConnectionStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "UpstreamMaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "DownstreamMaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Uptime"}, "allowedValueRange": {"maximum": "4294967295", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "NATEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["ERROR_NONE", "ERROR_ISP_TIME_OUT", "ERROR_COMMAND_ABORTED", "ERROR_NOT_ENABLED_FOR_INTERNET", "ERROR_BAD_PHONE_NUMBER", "ERROR_USER_DISCONNECT", "ERROR_ISP_DISCONNECT", "ERROR_IDLE_DISCONNECT", "ERROR_FORCED_DISCONNECT", "ERROR_SERVER_OUT_OF_RESOURCES", "ERROR_RESTRICTED_LOGON_HOURS", "ERROR_ACCOUNT_DISABLED", "ERROR_ACCOUNT_EXPIRED", "ERROR_PASSWORD_EXPIRED", "ERROR_AUTHENTICATION_FAILURE", "ERROR_NO_DIALTONE", "ERROR_NO_CARRIER", "ERROR_NO_ANSWER", "ERROR_LINE_BUSY", "ERROR_UNSUPPORTED_BITSPERSECOND", "ERROR_TOO_MANY_LINE_ERRORS", "ERROR_IP_CONFIGURATION", "ERROR_UNKNOWN"], "dataType": "string", "defaultValue": "ERROR_NONE", "name": "LastConnectionError"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "IdleDisconnectTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "UserName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DNSServers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "TransportType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ConnectionTrigger"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ExternalIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "LastAuthErrorInfo"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "RemoteHost"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "ExternalPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "InternalPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["TCP", "UDP"], "dataType": "string", "defaultValue": null, "name": "PortMappingProtocol"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "InternalClient"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PortMappingDescription"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "PortMappingEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PortMappingLeaseDuration"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "PortMappingNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "128", "name": "MaxCharsUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "3", "name": "MinCharsUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._@()#/%[]{}*+\u00c2\u00a7$&=?!:;,", "name": "AllowedCharsUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "64", "name": "MaxCharsPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "3", "name": "MinCharsPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._@()#/%[]{}*+\u00c2\u00a7$&=?!:;,", "name": "AllowedCharsPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "RSIPAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "Off", "name": "RouteProtocolRx"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PPPoEServiceName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PPPoEACName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DNSOverrideAllowed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "RemoteIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "DNSEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "X_AVM-DE_DisconnectPreventionEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "2", "name": "X_AVM-DE_DisconnectPreventionHour"}, "allowedValueRange": {"maximum": "23", "minimum": "0", "step": null}}]}}, {"attributes": {"SCPDURL": "/wanipconnSCPD.xml", "controlURL": "/upnp/control/wanipconnection1", "eventSubURL": "/upnp/control/wanipconnection1", "serviceId": "urn:WANIPConnection-com:serviceId:WANIPConnection1", "serviceType": "urn:dslforum-org:service:WANIPConnection:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewConnectionStatus", "relatedStateVariable": "ConnectionStatus"}, {"direction": "out", "name": "NewPossibleConnectionTypes", "relatedStateVariable": "PossibleConnectionTypes"}, {"direction": "out", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewUptime", "relatedStateVariable": "Uptime"}, {"direction": "out", "name": "NewLastConnectionError", "relatedStateVariable": "LastConnectionError"}, {"direction": "out", "name": "NewRSIPAvailable", "relatedStateVariable": "RSIPAvailable"}, {"direction": "out", "name": "NewNATEnabled", "relatedStateVariable": "NATEnabled"}, {"direction": "out", "name": "NewExternalIPAddress", "relatedStateVariable": "ExternalIPAddress"}, {"direction": "out", "name": "NewDNSServers", "relatedStateVariable": "DNSServers"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewConnectionTrigger", "relatedStateVariable": "ConnectionTrigger"}, {"direction": "out", "name": "NewRouteProtocolRx", "relatedStateVariable": "RouteProtocolRx"}, {"direction": "out", "name": "NewDNSEnabled", "relatedStateVariable": "DNSEnabled"}, {"direction": "out", "name": "NewDNSOverrideAllowed", "relatedStateVariable": "DNSOverrideAllowed"}]}, {"name": "GetConnectionTypeInfo", "arguments": [{"direction": "out", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}, {"direction": "out", "name": "NewPossibleConnectionTypes", "relatedStateVariable": "PossibleConnectionTypes"}]}, {"name": "SetConnectionType", "arguments": [{"direction": "in", "name": "NewConnectionType", "relatedStateVariable": "ConnectionType"}]}, {"name": "GetStatusInfo", "arguments": [{"direction": "out", "name": "NewConnectionStatus", "relatedStateVariable": "ConnectionStatus"}, {"direction": "out", "name": "NewLastConnectionError", "relatedStateVariable": "LastConnectionError"}, {"direction": "out", "name": "NewUptime", "relatedStateVariable": "Uptime"}]}, {"name": "GetNATRSIPStatus", "arguments": [{"direction": "out", "name": "NewRSIPAvailable", "relatedStateVariable": "RSIPAvailable"}, {"direction": "out", "name": "NewNATEnabled", "relatedStateVariable": "NATEnabled"}]}, {"name": "SetConnectionTrigger", "arguments": [{"direction": "in", "name": "NewConnectionTrigger", "relatedStateVariable": "ConnectionTrigger"}]}, {"name": "ForceTermination", "arguments": []}, {"name": "RequestConnection", "arguments": []}, {"name": "GetGenericPortMappingEntry", "arguments": [{"direction": "in", "name": "NewPortMappingIndex", "relatedStateVariable": "PortMappingNumberOfEntries"}, {"direction": "out", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "out", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "out", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "out", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "out", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "out", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "out", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "GetSpecificPortMappingEntry", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "out", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "out", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "out", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "out", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "AddPortMapping", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}, {"direction": "in", "name": "NewInternalPort", "relatedStateVariable": "InternalPort"}, {"direction": "in", "name": "NewInternalClient", "relatedStateVariable": "InternalClient"}, {"direction": "in", "name": "NewEnabled", "relatedStateVariable": "PortMappingEnabled"}, {"direction": "in", "name": "NewPortMappingDescription", "relatedStateVariable": "PortMappingDescription"}, {"direction": "in", "name": "NewLeaseDuration", "relatedStateVariable": "PortMappingLeaseDuration"}]}, {"name": "DeletePortMapping", "arguments": [{"direction": "in", "name": "NewRemoteHost", "relatedStateVariable": "RemoteHost"}, {"direction": "in", "name": "NewExternalPort", "relatedStateVariable": "ExternalPort"}, {"direction": "in", "name": "NewProtocol", "relatedStateVariable": "PortMappingProtocol"}]}, {"name": "GetExternalIPAddress", "arguments": [{"direction": "out", "name": "NewExternalIPAddress", "relatedStateVariable": "ExternalIPAddress"}]}, {"name": "X_GetDNSServers", "arguments": [{"direction": "out", "name": "NewDNSServers", "relatedStateVariable": "DNSServers"}]}, {"name": "GetPortMappingNumberOfEntries", "arguments": [{"direction": "out", "name": "NewPortMappingNumberOfEntries", "relatedStateVariable": "PortMappingNumberOfEntries"}]}, {"name": "SetRouteProtocolRx", "arguments": [{"direction": "in", "name": "NewRouteProtocolRx", "relatedStateVariable": "RouteProtocolRx"}]}, {"name": "SetIdleDisconnectTime", "arguments": [{"direction": "in", "name": "NewIdleDisconnectTime", "relatedStateVariable": "IdleDisconnectTime"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "IP_Routed", "IP_Bridged"], "dataType": "string", "defaultValue": "Unconfigured", "name": "ConnectionType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "IP_Routed", "IP_Bridged"], "dataType": "string", "defaultValue": null, "name": "PossibleConnectionTypes"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Unconfigured", "Connecting", "Authenticating", "PendingDisconnect", "Disconnecting", "Disconnected", "Connected"], "dataType": "string", "defaultValue": "Unconfigured", "name": "ConnectionStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Uptime"}, "allowedValueRange": {"maximum": "4294967295", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "NATEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["ERROR_NONE", "ERROR_ISP_TIME_OUT", "ERROR_COMMAND_ABORTED", "ERROR_NOT_ENABLED_FOR_INTERNET", "ERROR_BAD_PHONE_NUMBER", "ERROR_USER_DISCONNECT", "ERROR_ISP_DISCONNECT", "ERROR_IDLE_DISCONNECT", "ERROR_FORCED_DISCONNECT", "ERROR_SERVER_OUT_OF_RESOURCES", "ERROR_RESTRICTED_LOGON_HOURS", "ERROR_ACCOUNT_DISABLED", "ERROR_ACCOUNT_EXPIRED", "ERROR_PASSWORD_EXPIRED", "ERROR_AUTHENTICATION_FAILURE", "ERROR_NO_DIALTONE", "ERROR_NO_CARRIER", "ERROR_NO_ANSWER", "ERROR_LINE_BUSY", "ERROR_UNSUPPORTED_BITSPERSECOND", "ERROR_TOO_MANY_LINE_ERRORS", "ERROR_IP_CONFIGURATION", "ERROR_UNKNOWN"], "dataType": "string", "defaultValue": "ERROR_NONE", "name": "LastConnectionError"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "IdleDisconnectTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DNSServers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ConnectionTrigger"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ExternalIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "RemoteHost"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "ExternalPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "InternalPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["TCP", "UDP"], "dataType": "string", "defaultValue": null, "name": "PortMappingProtocol"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "InternalClient"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PortMappingDescription"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "PortMappingEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PortMappingLeaseDuration"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "PortMappingNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "RSIPAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "Off", "name": "RouteProtocolRx"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DNSOverrideAllowed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "DNSEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}], "services": [{"attributes": {"SCPDURL": "/wancommonifconfigSCPD.xml", "controlURL": "/upnp/control/wancommonifconfig1", "eventSubURL": "/upnp/control/wancommonifconfig1", "serviceId": "urn:WANCIfConfig-com:serviceId:WANCommonInterfaceConfig1", "serviceType": "urn:dslforum-org:service:WANCommonInterfaceConfig:1"}, "scpd": {"actions": [{"name": "GetCommonLinkProperties", "arguments": [{"direction": "out", "name": "NewWANAccessType", "relatedStateVariable": "WANAccessType"}, {"direction": "out", "name": "NewLayer1UpstreamMaxBitRate", "relatedStateVariable": "Layer1UpstreamMaxBitRate"}, {"direction": "out", "name": "NewLayer1DownstreamMaxBitRate", "relatedStateVariable": "Layer1DownstreamMaxBitRate"}, {"direction": "out", "name": "NewPhysicalLinkStatus", "relatedStateVariable": "PhysicalLinkStatus"}]}, {"name": "GetTotalBytesSent", "arguments": [{"direction": "out", "name": "NewTotalBytesSent", "relatedStateVariable": "TotalBytesSent"}]}, {"name": "GetTotalBytesReceived", "arguments": [{"direction": "out", "name": "NewTotalBytesReceived", "relatedStateVariable": "TotalBytesReceived"}]}, {"name": "GetTotalPacketsSent", "arguments": [{"direction": "out", "name": "NewTotalPacketsSent", "relatedStateVariable": "TotalPacketsSent"}]}, {"name": "GetTotalPacketsReceived", "arguments": [{"direction": "out", "name": "NewTotalPacketsReceived", "relatedStateVariable": "TotalPacketsReceived"}]}, {"name": "X_AVM-DE_SetWANAccessType", "arguments": [{"direction": "in", "name": "NewAccessType", "relatedStateVariable": "AccessType"}]}, {"name": "X_AVM-DE_GetOnlineMonitor", "arguments": [{"direction": "in", "name": "NewSyncGroupIndex", "relatedStateVariable": "SyncGroupIndex"}, {"direction": "out", "name": "NewTotalNumberSyncGroups", "relatedStateVariable": "TotalNumberSyncGroups"}, {"direction": "out", "name": "NewSyncGroupName", "relatedStateVariable": "SyncGroupName"}, {"direction": "out", "name": "NewSyncGroupMode", "relatedStateVariable": "SyncGroupMode"}, {"direction": "out", "name": "Newmax_ds", "relatedStateVariable": "max_ds"}, {"direction": "out", "name": "Newmax_us", "relatedStateVariable": "max_us"}, {"direction": "out", "name": "Newds_current_bps", "relatedStateVariable": "ds_current_bps"}, {"direction": "out", "name": "Newmc_current_bps", "relatedStateVariable": "mc_current_bps"}, {"direction": "out", "name": "Newus_current_bps", "relatedStateVariable": "us_current_bps"}, {"direction": "out", "name": "Newprio_realtime_bps", "relatedStateVariable": "prio_realtime_bps"}, {"direction": "out", "name": "Newprio_high_bps", "relatedStateVariable": "prio_high_bps"}, {"direction": "out", "name": "Newprio_default_bps", "relatedStateVariable": "prio_default_bps"}, {"direction": "out", "name": "Newprio_low_bps", "relatedStateVariable": "prio_low_bps"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "WANAccessType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Layer1UpstreamMaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Layer1DownstreamMaxBitRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhysicalLinkStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalBytesSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalBytesReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsSent"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalPacketsReceived"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AccessType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "SyncGroupIndex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "TotalNumberSyncGroups"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SyncGroupName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SyncGroupMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "max_ds"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "max_us"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ds_current_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "mc_current_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "us_current_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "prio_realtime_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "prio_high_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "prio_default_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "prio_low_bps"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/wandslifconfigSCPD.xml", "controlURL": "/upnp/control/wandslifconfig1", "eventSubURL": "/upnp/control/wandslifconfig1", "serviceId": "urn:WANDSLIfConfig-com:serviceId:WANDSLInterfaceConfig1", "serviceType": "urn:dslforum-org:service:WANDSLInterfaceConfig:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewDataPath", "relatedStateVariable": "DataPath"}, {"direction": "out", "name": "NewUpstreamCurrRate", "relatedStateVariable": "UpstreamCurrRate"}, {"direction": "out", "name": "NewDownstreamCurrRate", "relatedStateVariable": "DownstreamCurrRate"}, {"direction": "out", "name": "NewUpstreamMaxRate", "relatedStateVariable": "UpstreamMaxRate"}, {"direction": "out", "name": "NewDownstreamMaxRate", "relatedStateVariable": "DownstreamMaxRate"}, {"direction": "out", "name": "NewUpstreamNoiseMargin", "relatedStateVariable": "UpstreamNoiseMargin"}, {"direction": "out", "name": "NewDownstreamNoiseMargin", "relatedStateVariable": "DownstreamNoiseMargin"}, {"direction": "out", "name": "NewUpstreamAttenuation", "relatedStateVariable": "UpstreamAttenuation"}, {"direction": "out", "name": "NewDownstreamAttenuation", "relatedStateVariable": "DownstreamAttenuation"}, {"direction": "out", "name": "NewATURVendor", "relatedStateVariable": "ATURVendor"}, {"direction": "out", "name": "NewATURCountry", "relatedStateVariable": "ATURCountry"}, {"direction": "out", "name": "NewUpstreamPower", "relatedStateVariable": "UpstreamPower"}, {"direction": "out", "name": "NewDownstreamPower", "relatedStateVariable": "DownstreamPower"}]}, {"name": "GetStatisticsTotal", "arguments": [{"direction": "out", "name": "NewReceiveBlocks", "relatedStateVariable": "Stats.Total.ReceiveBlocks"}, {"direction": "out", "name": "NewTransmitBlocks", "relatedStateVariable": "Stats.Total.TransmitBlocks"}, {"direction": "out", "name": "NewCellDelin", "relatedStateVariable": "Stats.Total.CellDelin"}, {"direction": "out", "name": "NewLinkRetrain", "relatedStateVariable": "Stats.Total.LinkRetrain"}, {"direction": "out", "name": "NewInitErrors", "relatedStateVariable": "Stats.Total.InitErrors"}, {"direction": "out", "name": "NewInitTimeouts", "relatedStateVariable": "Stats.Total.InitTimeouts"}, {"direction": "out", "name": "NewLossOfFraming", "relatedStateVariable": "Stats.Total.LossOfFraming"}, {"direction": "out", "name": "NewErroredSecs", "relatedStateVariable": "Stats.Total.ErroredSecs"}, {"direction": "out", "name": "NewSeverelyErroredSecs", "relatedStateVariable": "Stats.Total.SeverelyErroredSecs"}, {"direction": "out", "name": "NewFECErrors", "relatedStateVariable": "Stats.Total.FECErrors"}, {"direction": "out", "name": "NewATUCFECErrors", "relatedStateVariable": "Stats.Total.ATUCFECErrors"}, {"direction": "out", "name": "NewHECErrors", "relatedStateVariable": "Stats.Total.HECErrors"}, {"direction": "out", "name": "NewATUCHECErrors", "relatedStateVariable": "Stats.Total.ATUCHECErrors"}, {"direction": "out", "name": "NewCRCErrors", "relatedStateVariable": "Stats.Total.CRCErrors"}, {"direction": "out", "name": "NewATUCCRCErrors", "relatedStateVariable": "Stats.Total.ATUCCRCErrors"}]}, {"name": "X_AVM-DE_GetDSLDiagnoseInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_DSLDiagnoseState", "relatedStateVariable": "X_AVM-DE_DSLDiagnoseState"}, {"direction": "out", "name": "NewX_AVM-DE_CableNokDistance", "relatedStateVariable": "X_AVM-DE_CableNokDistance"}, {"direction": "out", "name": "NewX_AVM-DE_DSLLastDiagnoseTime", "relatedStateVariable": "X_AVM-DE_DSLLastDiagnoseTime"}, {"direction": "out", "name": "NewX_AVM-DE_DSLSignalLossTime", "relatedStateVariable": "X_AVM-DE_DSLSignalLossTime"}, {"direction": "out", "name": "NewX_AVM-DE_DSLActive", "relatedStateVariable": "X_AVM-DE_DSLActive"}, {"direction": "out", "name": "NewX_AVM-DE_DSLSync", "relatedStateVariable": "X_AVM-DE_DSLSync"}]}, {"name": "X_AVM-DE_GetDSLInfo", "arguments": [{"direction": "out", "name": "NewSNRGds", "relatedStateVariable": "SNRGds"}, {"direction": "out", "name": "NewSNRGus", "relatedStateVariable": "SNRGus"}, {"direction": "out", "name": "NewSNRpsds", "relatedStateVariable": "SNRpsds"}, {"direction": "out", "name": "NewSNRpsus", "relatedStateVariable": "SNRpsus"}, {"direction": "out", "name": "NewSNRMTds", "relatedStateVariable": "SNRMTds"}, {"direction": "out", "name": "NewSNRMTus", "relatedStateVariable": "SNRMTus"}, {"direction": "out", "name": "NewLATNds", "relatedStateVariable": "LATNds"}, {"direction": "out", "name": "NewLATNus", "relatedStateVariable": "LATNus"}, {"direction": "out", "name": "NewFECErrors", "relatedStateVariable": "Stats.Total.FECErrors"}, {"direction": "out", "name": "NewCRCErrors", "relatedStateVariable": "Stats.Total.CRCErrors"}, {"direction": "out", "name": "NewLinkStatus", "relatedStateVariable": "LinkStatus"}, {"direction": "out", "name": "NewModulationType", "relatedStateVariable": "ModulationType"}, {"direction": "out", "name": "NewCurrentProfile", "relatedStateVariable": "CurrentProfile"}, {"direction": "out", "name": "NewUpstreamCurrRate", "relatedStateVariable": "UpstreamCurrRate"}, {"direction": "out", "name": "NewDownstreamCurrRate", "relatedStateVariable": "DownstreamCurrRate"}, {"direction": "out", "name": "NewUpstreamMaxRate", "relatedStateVariable": "UpstreamMaxRate"}, {"direction": "out", "name": "NewDownstreamMaxRate", "relatedStateVariable": "DownstreamMaxRate"}, {"direction": "out", "name": "NewUpstreamNoiseMargin", "relatedStateVariable": "UpstreamNoiseMargin"}, {"direction": "out", "name": "NewDownstreamNoiseMargin", "relatedStateVariable": "DownstreamNoiseMargin"}, {"direction": "out", "name": "NewUpstreamAttenuation", "relatedStateVariable": "UpstreamAttenuation"}, {"direction": "out", "name": "NewDownstreamAttenuation", "relatedStateVariable": "DownstreamAttenuation"}, {"direction": "out", "name": "NewATURVendor", "relatedStateVariable": "ATURVendor"}, {"direction": "out", "name": "NewATURCountry", "relatedStateVariable": "ATURCountry"}, {"direction": "out", "name": "NewUpstreamPower", "relatedStateVariable": "UpstreamPower"}, {"direction": "out", "name": "NewDownstreamPower", "relatedStateVariable": "DownstreamPower"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DataPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "UpstreamCurrRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "DownstreamCurrRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "UpstreamMaxRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "DownstreamMaxRate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "UpstreamNoiseMargin"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "DownstreamNoiseMargin"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "UpstreamAttenuation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "DownstreamAttenuation"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ATURVendor"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ATURCountry"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "UpstreamPower"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "DownstreamPower"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.ReceiveBlocks"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.TransmitBlocks"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.CellDelin"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.LinkRetrain"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.InitErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.InitTimeouts"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.LossOfFraming"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.ErroredSecs"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.SeverelyErroredSecs"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.FECErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.ATUCFECErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.HECErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.ATUCHECErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.CRCErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Stats.Total.ATUCCRCErrors"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_DSLDiagnoseState"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "X_AVM-DE_CableNokDistance"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_DSLLastDiagnoseTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "X_AVM-DE_DSLSignalLossTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_DSLActive"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_DSLSync"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "1", "name": "SNRGds"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "1", "name": "SNRGus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SNRpsds"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SNRpsus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "SNRMTds"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "SNRMTus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "LATNds"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "LATNus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["ADSL G.lite", "G.shdsl", "IDSL", "HDSL", "SDSL", "VDSL"], "dataType": "string", "defaultValue": null, "name": "ModulationType"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Up", "Down", "Initializing", "Unavailable"], "dataType": "string", "defaultValue": null, "name": "LinkStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "CurrentProfile"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}], "services": [{"attributes": {"SCPDURL": "/deviceinfoSCPD.xml", "controlURL": "/upnp/control/deviceinfo", "eventSubURL": "/upnp/control/deviceinfo", "serviceId": "urn:DeviceInfo-com:serviceId:DeviceInfo1", "serviceType": "urn:dslforum-org:service:DeviceInfo:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewManufacturerName", "relatedStateVariable": "ManufacturerName"}, {"direction": "out", "name": "NewManufacturerOUI", "relatedStateVariable": "ManufacturerOUI"}, {"direction": "out", "name": "NewModelName", "relatedStateVariable": "ModelName"}, {"direction": "out", "name": "NewDescription", "relatedStateVariable": "Description"}, {"direction": "out", "name": "NewProductClass", "relatedStateVariable": "ProductClass"}, {"direction": "out", "name": "NewSerialNumber", "relatedStateVariable": "SerialNumber"}, {"direction": "out", "name": "NewSoftwareVersion", "relatedStateVariable": "SoftwareVersion"}, {"direction": "out", "name": "NewHardwareVersion", "relatedStateVariable": "HardwareVersion"}, {"direction": "out", "name": "NewSpecVersion", "relatedStateVariable": "SpecVersion"}, {"direction": "out", "name": "NewProvisioningCode", "relatedStateVariable": "ProvisioningCode"}, {"direction": "out", "name": "NewUpTime", "relatedStateVariable": "UpTime"}, {"direction": "out", "name": "NewDeviceLog", "relatedStateVariable": "DeviceLog"}]}, {"name": "SetProvisioningCode", "arguments": [{"direction": "in", "name": "NewProvisioningCode", "relatedStateVariable": "ProvisioningCode"}]}, {"name": "GetDeviceLog", "arguments": [{"direction": "out", "name": "NewDeviceLog", "relatedStateVariable": "DeviceLog"}]}, {"name": "GetSecurityPort", "arguments": [{"direction": "out", "name": "NewSecurityPort", "relatedStateVariable": "SecurityPort"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "AVM", "name": "ManufacturerName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ManufacturerOUI"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ModelName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Description"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ProductClass"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SerialNumber"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "HardwareVersion"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SoftwareVersion"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SpecVersion"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ProvisioningCode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "UpTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DeviceLog"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "SecurityPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/deviceconfigSCPD.xml", "controlURL": "/upnp/control/deviceconfig", "eventSubURL": "/upnp/control/deviceconfig", "serviceId": "urn:DeviceConfig-com:serviceId:DeviceConfig1", "serviceType": "urn:dslforum-org:service:DeviceConfig:1"}, "scpd": {"actions": [{"name": "GetPersistentData", "arguments": [{"direction": "out", "name": "NewPersistentData", "relatedStateVariable": "PersistentData"}]}, {"name": "SetPersistentData", "arguments": [{"direction": "in", "name": "NewPersistentData", "relatedStateVariable": "PersistentData"}]}, {"name": "ConfigurationStarted", "arguments": [{"direction": "in", "name": "NewSessionID", "relatedStateVariable": "A_ARG_TYPE_UUID"}]}, {"name": "ConfigurationFinished", "arguments": [{"direction": "out", "name": "NewStatus", "relatedStateVariable": "A_ARG_TYPE_Status"}]}, {"name": "FactoryReset", "arguments": []}, {"name": "Reboot", "arguments": []}, {"name": "X_GenerateUUID", "arguments": [{"direction": "out", "name": "NewUUID", "relatedStateVariable": "UUID"}]}, {"name": "X_AVM-DE_GetConfigFile", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_Password", "relatedStateVariable": "X_AVM-DE_Password"}, {"direction": "out", "name": "NewX_AVM-DE_ConfigFileUrl", "relatedStateVariable": "X_AVM-DE_ConfigFileUrl"}]}, {"name": "X_AVM-DE_SetConfigFile", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_Password", "relatedStateVariable": "X_AVM-DE_Password"}, {"direction": "in", "name": "NewX_AVM-DE_ConfigFileUrl", "relatedStateVariable": "X_AVM-DE_ConfigFileUrl"}]}, {"name": "X_AVM-DE_CreateUrlSID", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_UrlSID", "relatedStateVariable": "X_AVM-DE_UrlSID"}]}, {"name": "X_AVM-DE_SendSupportData", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_SupportDataMode", "relatedStateVariable": "X_AVM-DE_SupportDataMode"}]}, {"name": "X_AVM-DE_GetSupportDataInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_SupportDataMode", "relatedStateVariable": "X_AVM-DE_SupportDataMode"}, {"direction": "out", "name": "NewX_AVM-DE_SupportDataID", "relatedStateVariable": "X_AVM-DE_SupportDataID"}, {"direction": "out", "name": "NewX_AVM-DE_SupportDataTimestamp", "relatedStateVariable": "X_AVM-DE_SupportDataTimestamp"}, {"direction": "out", "name": "NewX_AVM-DE_SupportDataStatus", "relatedStateVariable": "X_AVM-DE_SupportDataStatus"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PersistentData"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "A_ARG_TYPE_UUID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "A_ARG_TYPE_Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "uuid", "defaultValue": null, "name": "UUID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_ConfigFileUrl"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UrlSID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["normal", "mesh", "unknown"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_SupportDataMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_SupportDataID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "X_AVM-DE_SupportDataTimestamp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["unknown", "ok", "preparing", "error", "creating"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_SupportDataStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/layer3forwardingSCPD.xml", "controlURL": "/upnp/control/layer3forwarding", "eventSubURL": "/upnp/control/layer3forwarding", "serviceId": "urn:Layer3Forwarding-com:serviceId:Layer3Forwarding1", "serviceType": "urn:dslforum-org:service:Layer3Forwarding:1"}, "scpd": {"actions": [{"name": "SetDefaultConnectionService", "arguments": [{"direction": "in", "name": "NewDefaultConnectionService", "relatedStateVariable": "DefaultConnectionService"}]}, {"name": "GetDefaultConnectionService", "arguments": [{"direction": "out", "name": "NewDefaultConnectionService", "relatedStateVariable": "DefaultConnectionService"}]}, {"name": "GetForwardNumberOfEntries", "arguments": [{"direction": "out", "name": "NewForwardNumberOfEntries", "relatedStateVariable": "ForwardNumberOfEntries"}]}, {"name": "AddForwardingEntry", "arguments": [{"direction": "in", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "in", "name": "NewDestIPAddress", "relatedStateVariable": "DestIPAddress"}, {"direction": "in", "name": "NewDestSubnetMask", "relatedStateVariable": "DestSubnetMask"}, {"direction": "in", "name": "NewSourceIPAddress", "relatedStateVariable": "SourceIPAddress"}, {"direction": "in", "name": "NewSourceSubnetMask", "relatedStateVariable": "SourceSubnetMask"}, {"direction": "in", "name": "NewGatewayIPAddress", "relatedStateVariable": "GatewayIPAddress"}, {"direction": "in", "name": "NewInterface", "relatedStateVariable": "Interface"}, {"direction": "in", "name": "NewForwardingMetric", "relatedStateVariable": "ForwardingMetric"}]}, {"name": "DeleteForwardingEntry", "arguments": [{"direction": "in", "name": "NewDestIPAddress", "relatedStateVariable": "DestIPAddress"}, {"direction": "in", "name": "NewDestSubnetMask", "relatedStateVariable": "DestSubnetMask"}, {"direction": "in", "name": "NewSourceIPAddress", "relatedStateVariable": "SourceIPAddress"}, {"direction": "in", "name": "NewSourceSubnetMask", "relatedStateVariable": "SourceSubnetMask"}]}, {"name": "GetSpecificForwardingEntry", "arguments": [{"direction": "in", "name": "NewDestIPAddress", "relatedStateVariable": "DestIPAddress"}, {"direction": "in", "name": "NewDestSubnetMask", "relatedStateVariable": "DestSubnetMask"}, {"direction": "in", "name": "NewSourceIPAddress", "relatedStateVariable": "SourceIPAddress"}, {"direction": "in", "name": "NewSourceSubnetMask", "relatedStateVariable": "SourceSubnetMask"}, {"direction": "out", "name": "NewGatewayIPAddress", "relatedStateVariable": "GatewayIPAddress"}, {"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "out", "name": "NewInterface", "relatedStateVariable": "Interface"}, {"direction": "out", "name": "NewForwardingMetric", "relatedStateVariable": "ForwardingMetric"}]}, {"name": "GetGenericForwardingEntry", "arguments": [{"direction": "in", "name": "NewForwardingIndex", "relatedStateVariable": "ForwardNumberOfEntries"}, {"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "out", "name": "NewDestIPAddress", "relatedStateVariable": "DestIPAddress"}, {"direction": "out", "name": "NewDestSubnetMask", "relatedStateVariable": "DestSubnetMask"}, {"direction": "out", "name": "NewSourceIPAddress", "relatedStateVariable": "SourceIPAddress"}, {"direction": "out", "name": "NewSourceSubnetMask", "relatedStateVariable": "SourceSubnetMask"}, {"direction": "out", "name": "NewGatewayIPAddress", "relatedStateVariable": "GatewayIPAddress"}, {"direction": "out", "name": "NewInterface", "relatedStateVariable": "Interface"}, {"direction": "out", "name": "NewForwardingMetric", "relatedStateVariable": "ForwardingMetric"}]}, {"name": "SetForwardingEntryEnable", "arguments": [{"direction": "in", "name": "NewDestIPAddress", "relatedStateVariable": "DestIPAddress"}, {"direction": "in", "name": "NewDestSubnetMask", "relatedStateVariable": "DestSubnetMask"}, {"direction": "in", "name": "NewSourceIPAddress", "relatedStateVariable": "SourceIPAddress"}, {"direction": "in", "name": "NewSourceSubnetMask", "relatedStateVariable": "SourceSubnetMask"}, {"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DefaultConnectionService"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "ForwardNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Type"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DestIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DestSubnetMask"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SourceIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SourceSubnetMask"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "GatewayIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Interface"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "ForwardingMetric"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/lanconfigsecuritySCPD.xml", "controlURL": "/upnp/control/lanconfigsecurity", "eventSubURL": "/upnp/control/lanconfigsecurity", "serviceId": "urn:LANConfigSecurity-com:serviceId:LANConfigSecurity1", "serviceType": "urn:dslforum-org:service:LANConfigSecurity:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewMaxCharsPassword", "relatedStateVariable": "MaxCharsPassword"}, {"direction": "out", "name": "NewMinCharsPassword", "relatedStateVariable": "MinCharsPassword"}, {"direction": "out", "name": "NewAllowedCharsPassword", "relatedStateVariable": "AllowedCharsPassword"}]}, {"name": "X_AVM-DE_GetCurrentUser", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_CurrentUsername", "relatedStateVariable": "X_AVM-DE_CurrentUsername"}, {"direction": "out", "name": "NewX_AVM-DE_CurrentUserRights", "relatedStateVariable": "X_AVM-DE_CurrentUserRights"}]}, {"name": "X_AVM-DE_GetAnonymousLogin", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_AnonymousLoginEnabled", "relatedStateVariable": "X_AVM-DE_AnonymousLoginEnabled"}, {"direction": "out", "name": "NewX_AVM-DE_ButtonLoginEnabled", "relatedStateVariable": "X_AVM-DE_ButtonLoginEnabled"}]}, {"name": "SetConfigPassword", "arguments": [{"direction": "in", "name": "NewPassword", "relatedStateVariable": "ConfigPassword"}]}, {"name": "X_AVM-DE_GetUserList", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_UserList", "relatedStateVariable": "X_AVM-DE_UserList"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "32", "name": "MaxCharsPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "MinCharsPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ConfigPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_AnonymousLoginEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_ButtonLoginEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_CurrentUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_CurrentUserRights"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UserList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/mgmsrvSCPD.xml", "controlURL": "/upnp/control/mgmsrv", "eventSubURL": "/upnp/control/mgmsrv", "serviceId": "urn:ManagementServer-com:serviceId:ManagementServer1", "serviceType": "urn:dslforum-org:service:ManagementServer:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewURL", "relatedStateVariable": "URL"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewPeriodicInformEnable", "relatedStateVariable": "PeriodicInformEnable"}, {"direction": "out", "name": "NewPeriodicInformInterval", "relatedStateVariable": "PeriodicInformInterval"}, {"direction": "out", "name": "NewPeriodicInformTime", "relatedStateVariable": "PeriodicInformTime"}, {"direction": "out", "name": "NewParameterKey", "relatedStateVariable": "ParameterKey"}, {"direction": "out", "name": "NewParameterHash", "relatedStateVariable": "ParameterHash"}, {"direction": "out", "name": "NewConnectionRequestURL", "relatedStateVariable": "ConnectionRequestURL"}, {"direction": "out", "name": "NewConnectionRequestUsername", "relatedStateVariable": "ConnectionRequestUsername"}, {"direction": "out", "name": "NewUpgradesManaged", "relatedStateVariable": "UpgradesManaged"}]}, {"name": "SetManagementServerURL", "arguments": [{"direction": "in", "name": "NewURL", "relatedStateVariable": "URL"}]}, {"name": "SetManagementServerUsername", "arguments": [{"direction": "in", "name": "NewUsername", "relatedStateVariable": "Username"}]}, {"name": "SetManagementServerPassword", "arguments": [{"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}]}, {"name": "SetPeriodicInform", "arguments": [{"direction": "in", "name": "NewPeriodicInformEnable", "relatedStateVariable": "PeriodicInformEnable"}, {"direction": "in", "name": "NewPeriodicInformInterval", "relatedStateVariable": "PeriodicInformInterval"}, {"direction": "in", "name": "NewPeriodicInformTime", "relatedStateVariable": "PeriodicInformTime"}]}, {"name": "SetConnectionRequestAuthentication", "arguments": [{"direction": "in", "name": "NewConnectionRequestUsername", "relatedStateVariable": "ConnectionRequestUsername"}, {"direction": "in", "name": "NewConnectionRequestPassword", "relatedStateVariable": "ConnectionRequestPassword"}]}, {"name": "SetUpgradeManagement", "arguments": [{"direction": "in", "name": "NewUpgradesManaged", "relatedStateVariable": "UpgradesManaged"}]}, {"name": "X_SetTR069Enable", "arguments": [{"direction": "in", "name": "NewTR069Enabled", "relatedStateVariable": "TR069Enabled"}]}, {"name": "X_AVM-DE_GetTR069FirmwareDownloadEnabled", "arguments": [{"direction": "out", "name": "NewTR069FirmwareDownloadEnabled", "relatedStateVariable": "TR069FirmwareDownloadEnabled"}]}, {"name": "X_AVM-DE_SetTR069FirmwareDownloadEnabled", "arguments": [{"direction": "in", "name": "NewTR069FirmwareDownloadEnabled", "relatedStateVariable": "TR069FirmwareDownloadEnabled"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "URL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Username"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "PeriodicInformEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PeriodicInformInterval"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "PeriodicInformTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ParameterKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ParameterHash"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ConnectionRequestURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ConnectionRequestUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "UpgradesManaged"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ConnectionRequestPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "TR069Enabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "TR069FirmwareDownloadEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/timeSCPD.xml", "controlURL": "/upnp/control/time", "eventSubURL": "/upnp/control/time", "serviceId": "urn:Time-com:serviceId:Time1", "serviceType": "urn:dslforum-org:service:Time:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewNTPServer1", "relatedStateVariable": "NTPServer1"}, {"direction": "out", "name": "NewNTPServer2", "relatedStateVariable": "NTPServer2"}, {"direction": "out", "name": "NewCurrentLocalTime", "relatedStateVariable": "CurrentLocalTime"}, {"direction": "out", "name": "NewLocalTimeZone", "relatedStateVariable": "LocalTimeZone"}, {"direction": "out", "name": "NewLocalTimeZoneName", "relatedStateVariable": "LocalTimeZoneName"}, {"direction": "out", "name": "NewDaylightSavingsUsed", "relatedStateVariable": "DaylightSavingsUsed"}, {"direction": "out", "name": "NewDaylightSavingsStart", "relatedStateVariable": "DaylightSavingsStart"}, {"direction": "out", "name": "NewDaylightSavingsEnd", "relatedStateVariable": "DaylightSavingsEnd"}]}, {"name": "SetNTPServers", "arguments": [{"direction": "in", "name": "NewNTPServer1", "relatedStateVariable": "NTPServer1"}, {"direction": "in", "name": "NewNTPServer2", "relatedStateVariable": "NTPServer2"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "NTPServer1"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "NTPServer2"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "CurrentLocalTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "LocalTimeZone"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "LocalTimeZoneName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DaylightSavingsUsed"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "DaylightSavingsStart"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "DaylightSavingsEnd"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/userifSCPD.xml", "controlURL": "/upnp/control/userif", "eventSubURL": "/upnp/control/userif", "serviceId": "urn:UserInterface-com:serviceId:UserInterface1", "serviceType": "urn:dslforum-org:service:UserInterface:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewUpgradeAvailable", "relatedStateVariable": "UpgradeAvailable"}, {"direction": "out", "name": "NewPasswordRequired", "relatedStateVariable": "PasswordRequired"}, {"direction": "out", "name": "NewPasswordUserSelectable", "relatedStateVariable": "PasswordUserSelectable"}, {"direction": "out", "name": "NewWarrantyDate", "relatedStateVariable": "WarrantyDate"}, {"direction": "out", "name": "NewX_AVM-DE_Version", "relatedStateVariable": "X_AVM-DE_Version"}, {"direction": "out", "name": "NewX_AVM-DE_DownloadURL", "relatedStateVariable": "X_AVM-DE_DownloadURL"}, {"direction": "out", "name": "NewX_AVM-DE_InfoURL", "relatedStateVariable": "X_AVM-DE_InfoURL"}, {"direction": "out", "name": "NewX_AVM-DE_UpdateState", "relatedStateVariable": "X_AVM-DE_UpdateState"}, {"direction": "out", "name": "NewX_AVM-DE_LaborVersion", "relatedStateVariable": "X_AVM-DE_LaborVersion"}]}, {"name": "X_AVM-DE_CheckUpdate", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_LaborVersion", "relatedStateVariable": "X_AVM-DE_LaborVersion"}]}, {"name": "X_AVM-DE_DoUpdate", "arguments": [{"direction": "out", "name": "NewUpgradeAvailable", "relatedStateVariable": "UpgradeAvailable"}, {"direction": "out", "name": "NewX_AVM-DE_UpdateState", "relatedStateVariable": "X_AVM-DE_UpdateState"}]}, {"name": "X_AVM-DE_DoPrepareCGI", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_CGI", "relatedStateVariable": "X_AVM-DE_CGI"}, {"direction": "out", "name": "NewX_AVM-DE_SessionID", "relatedStateVariable": "X_AVM-DE_SessionID"}]}, {"name": "X_AVM-DE_DoManualUpdate", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_AllowDowngrade", "relatedStateVariable": "X_AVM-DE_AllowDowngrade"}, {"direction": "in", "name": "NewX_AVM-DE_DownloadURL", "relatedStateVariable": "X_AVM-DE_DownloadURL"}]}, {"name": "X_AVM-DE_GetInternationalConfig", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_Language", "relatedStateVariable": "X_AVM-DE_Language"}, {"direction": "out", "name": "NewX_AVM-DE_Country", "relatedStateVariable": "X_AVM-DE_Country"}, {"direction": "out", "name": "NewX_AVM-DE_Annex", "relatedStateVariable": "X_AVM-DE_Annex"}, {"direction": "out", "name": "NewX_AVM-DE_LanguageList", "relatedStateVariable": "X_AVM-DE_LanguageList"}, {"direction": "out", "name": "NewX_AVM-DE_CountryList", "relatedStateVariable": "X_AVM-DE_CountryList"}, {"direction": "out", "name": "NewX_AVM-DE_AnnexList", "relatedStateVariable": "X_AVM-DE_AnnexList"}]}, {"name": "X_AVM-DE_SetInternationalConfig", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_Language", "relatedStateVariable": "X_AVM-DE_Language"}, {"direction": "in", "name": "NewX_AVM-DE_Country", "relatedStateVariable": "X_AVM-DE_Country"}, {"direction": "in", "name": "NewX_AVM-DE_Annex", "relatedStateVariable": "X_AVM-DE_Annex"}]}, {"name": "X_AVM-DE_GetInfo", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_AutoUpdateMode", "relatedStateVariable": "X_AVM-DE_AutoUpdateMode"}, {"direction": "out", "name": "NewX_AVM-DE_UpdateTime", "relatedStateVariable": "X_AVM-DE_UpdateTime"}, {"direction": "out", "name": "NewX_AVM-DE_LastFwVersion", "relatedStateVariable": "X_AVM-DE_LastFwVersion"}, {"direction": "out", "name": "NewX_AVM-DE_LastInfoUrl", "relatedStateVariable": "X_AVM-DE_InfoURL"}, {"direction": "out", "name": "NewX_AVM-DE_CurrentFwVersion", "relatedStateVariable": "X_AVM-DE_Version"}, {"direction": "out", "name": "NewX_AVM-DE_UpdateSuccessful", "relatedStateVariable": "X_AVM-DE_UpdateSuccessful"}]}, {"name": "X_AVM-DE_SetConfig", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_AutoUpdateMode", "relatedStateVariable": "X_AVM-DE_AutoUpdateMode"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "UpgradeAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "PasswordRequired"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "PasswordUserSelectable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "WarrantyDate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Version"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_AllowDowngrade"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_DownloadURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_InfoURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_LaborVersion"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["Started", "Stopped", "Error", "NoUpdate", "UpdateAvailable", "Unknown"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UpdateState"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Language"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Country"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_Annex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_LanguageList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_CountryList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_AnnexList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_CGI"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_SessionID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["off", "all", "important", "check"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_AutoUpdateMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "X_AVM-DE_UpdateTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_LastFwVersion"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["unknown", "failed", "succeeded"], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_UpdateSuccessful"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_storageSCPD.xml", "controlURL": "/upnp/control/x_storage", "eventSubURL": "/upnp/control/x_storage", "serviceId": "urn:X_AVM-DE_Storage-com:serviceId:X_AVM-DE_Storage1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Storage:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewFTPEnable", "relatedStateVariable": "FTPEnable"}, {"direction": "out", "name": "NewFTPStatus", "relatedStateVariable": "FTPStatus"}, {"direction": "out", "name": "NewSMBEnable", "relatedStateVariable": "SMBEnable"}, {"direction": "out", "name": "NewFTPWANEnable", "relatedStateVariable": "FTPWANEnable"}, {"direction": "out", "name": "NewFTPWANSSLOnly", "relatedStateVariable": "FTPWANSSLOnly"}, {"direction": "out", "name": "NewFTPWANPort", "relatedStateVariable": "FTPWANPort"}]}, {"name": "RequestFTPServerWAN", "arguments": [{"direction": "out", "name": "NewFTPWANPort", "relatedStateVariable": "FTPWANPort"}, {"direction": "out", "name": "NewFTPWANLifetime", "relatedStateVariable": "FTPWANLifetime"}]}, {"name": "SetFTPServer", "arguments": [{"direction": "in", "name": "NewFTPEnable", "relatedStateVariable": "FTPEnable"}]}, {"name": "SetFTPServerWAN", "arguments": [{"direction": "in", "name": "NewFTPWANEnable", "relatedStateVariable": "FTPWANEnable"}, {"direction": "in", "name": "NewFTPWANSSLOnly", "relatedStateVariable": "FTPWANSSLOnly"}]}, {"name": "SetSMBServer", "arguments": [{"direction": "in", "name": "NewSMBEnable", "relatedStateVariable": "SMBEnable"}]}, {"name": "GetUserInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewX_AVM-DE_NetworkAccessReadOnly", "relatedStateVariable": "X_AVM-DE_NetworkAccessReadOnly"}]}, {"name": "SetUserConfig", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}, {"direction": "in", "name": "NewX_AVM-DE_NetworkAccessReadOnly", "relatedStateVariable": "X_AVM-DE_NetworkAccessReadOnly"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "FTPEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "FTPStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "SMBEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Username"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_NetworkAccessReadOnly"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "FTPWANEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "FTPWANSSLOnly"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "FTPWANPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "FTPWANLifetime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_webdavSCPD.xml", "controlURL": "/upnp/control/x_webdav", "eventSubURL": "/upnp/control/x_webdav", "serviceId": "urn:X_AVM-DE_WebDAV-com:serviceId:X_AVM-DE_WebDAVClient1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_WebDAVClient:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewHostURL", "relatedStateVariable": "HostURL"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewMountpointName", "relatedStateVariable": "MountpointName"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewHostURL", "relatedStateVariable": "HostURL"}, {"direction": "in", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}, {"direction": "in", "name": "NewMountpointName", "relatedStateVariable": "MountpointName"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "HostURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Username"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MountpointName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_upnpSCPD.xml", "controlURL": "/upnp/control/x_upnp", "eventSubURL": "/upnp/control/x_upnp", "serviceId": "urn:X_AVM-DE_UPnP-com:serviceId:X_AVM-DE_UPnP1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_UPnP:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewUPnPMediaServer", "relatedStateVariable": "UPnPMediaServer"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewUPnPMediaServer", "relatedStateVariable": "UPnPMediaServer"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "UPnPMediaServer"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_speedtestSCPD.xml", "controlURL": "/upnp/control/x_speedtest", "eventSubURL": "/upnp/control/x_speedtest", "serviceId": "urn:X_AVM-DE_Speedtest-com:serviceId:X_AVM-DE_Speedtest1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Speedtest:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnableTcp", "relatedStateVariable": "EnableTcp"}, {"direction": "out", "name": "NewEnableUdp", "relatedStateVariable": "EnableUdp"}, {"direction": "out", "name": "NewEnableUdpBidirect", "relatedStateVariable": "EnableUdpBidirect"}, {"direction": "out", "name": "NewWANEnableTcp", "relatedStateVariable": "WANEnableTcp"}, {"direction": "out", "name": "NewWANEnableUdp", "relatedStateVariable": "WANEnableUdp"}, {"direction": "out", "name": "NewPortTcp", "relatedStateVariable": "PortTcp"}, {"direction": "out", "name": "NewPortUdp", "relatedStateVariable": "PortUdp"}, {"direction": "out", "name": "NewPortUdpBidirect", "relatedStateVariable": "PortUdpBidirect"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewEnableTcp", "relatedStateVariable": "EnableTcp"}, {"direction": "in", "name": "NewEnableUdp", "relatedStateVariable": "EnableUdp"}, {"direction": "in", "name": "NewEnableUdpBidirect", "relatedStateVariable": "EnableUdpBidirect"}, {"direction": "in", "name": "NewWANEnableTcp", "relatedStateVariable": "WANEnableTcp"}, {"direction": "in", "name": "NewWANEnableUdp", "relatedStateVariable": "WANEnableUdp"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "EnableTcp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "EnableUdp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "EnableUdpBidirect"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "WANEnableTcp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "WANEnableUdp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "4711", "name": "PortTcp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "4711", "name": "PortUdp"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "4712", "name": "PortUdpBidirect"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_remoteSCPD.xml", "controlURL": "/upnp/control/x_remote", "eventSubURL": "/upnp/control/x_remote", "serviceId": "urn:X_AVM-DE_RemoteAccess-com:serviceId:X_AVM-DE_RemoteAccess1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_RemoteAccess:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "out", "name": "NewPort", "relatedStateVariable": "Port"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "in", "name": "NewPort", "relatedStateVariable": "Port"}, {"direction": "in", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}]}, {"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "out", "name": "NewPort", "relatedStateVariable": "Port"}]}, {"name": "GetDDNSInfo", "arguments": [{"direction": "out", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "out", "name": "NewProviderName", "relatedStateVariable": "ProviderName"}, {"direction": "out", "name": "NewUpdateURL", "relatedStateVariable": "UpdateURL"}, {"direction": "out", "name": "NewDomain", "relatedStateVariable": "Domain"}, {"direction": "out", "name": "NewStatusIPv4", "relatedStateVariable": "StatusIPv4"}, {"direction": "out", "name": "NewStatusIPv6", "relatedStateVariable": "StatusIPv6"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewMode", "relatedStateVariable": "Mode"}, {"direction": "out", "name": "NewServerIPv4", "relatedStateVariable": "ServerIPv4"}, {"direction": "out", "name": "NewServerIPv6", "relatedStateVariable": "ServerIPv6"}]}, {"name": "GetDDNSProviders", "arguments": [{"direction": "out", "name": "NewProviderList", "relatedStateVariable": "ProviderList"}]}, {"name": "SetDDNSConfig", "arguments": [{"direction": "in", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "in", "name": "NewProviderName", "relatedStateVariable": "ProviderName"}, {"direction": "in", "name": "NewUpdateURL", "relatedStateVariable": "UpdateURL"}, {"direction": "in", "name": "NewDomain", "relatedStateVariable": "Domain"}, {"direction": "in", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "in", "name": "NewMode", "relatedStateVariable": "Mode"}, {"direction": "in", "name": "NewServerIPv4", "relatedStateVariable": "ServerIPv4"}, {"direction": "in", "name": "NewServerIPv6", "relatedStateVariable": "ServerIPv6"}, {"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Domain"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "InfoURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["ddns_v4", "ddns_v6", "ddns_both", "ddns_together"], "dataType": "string", "defaultValue": "ddns_v4", "name": "Mode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Port"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ProviderList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ProviderName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ServerIPv4"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ServerIPv6"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "StatusIPv4"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "StatusIPv6"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "UpdateURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Username"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_myfritzSCPD.xml", "controlURL": "/upnp/control/x_myfritz", "eventSubURL": "/upnp/control/x_myfritz", "serviceId": "urn:X_AVM-DE_MyFritz-com:serviceId:X_AVM-DE_MyFritz1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_MyFritz:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "out", "name": "NewDeviceRegistered", "relatedStateVariable": "DeviceRegistered"}, {"direction": "out", "name": "NewDynDNSName", "relatedStateVariable": "DynDNSName"}, {"direction": "out", "name": "NewPort", "relatedStateVariable": "Port"}]}, {"name": "GetNumberOfServices", "arguments": [{"direction": "out", "name": "NewNumberOfServices", "relatedStateVariable": "NumberOfServices"}]}, {"name": "GetServiceByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "NumberOfServices"}, {"direction": "out", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewScheme", "relatedStateVariable": "Scheme"}, {"direction": "out", "name": "NewPort", "relatedStateVariable": "Port"}, {"direction": "out", "name": "NewURLPath", "relatedStateVariable": "URLPath"}, {"direction": "out", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "out", "name": "NewIPv4ForwardingWarning", "relatedStateVariable": "IPv4ForwardingWarning"}, {"direction": "out", "name": "NewIPv4Addresses", "relatedStateVariable": "IPv4Addresses"}, {"direction": "out", "name": "NewIPv6Addresses", "relatedStateVariable": "IPv6Addresses"}, {"direction": "out", "name": "NewIPv6InterfaceIDs", "relatedStateVariable": "IPv6InterfaceIDs"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewHostName", "relatedStateVariable": "HostName"}, {"direction": "out", "name": "NewDynDnsLabel", "relatedStateVariable": "DynDnsLabel"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}]}, {"name": "SetServiceByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "NumberOfServices"}, {"direction": "in", "name": "NewEnabled", "relatedStateVariable": "Enabled"}, {"direction": "in", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "in", "name": "NewScheme", "relatedStateVariable": "Scheme"}, {"direction": "in", "name": "NewPort", "relatedStateVariable": "Port"}, {"direction": "in", "name": "NewURLPath", "relatedStateVariable": "URLPath"}, {"direction": "in", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "in", "name": "NewIPv4Address", "relatedStateVariable": "IPv4Addresses"}, {"direction": "in", "name": "NewIPv6Address", "relatedStateVariable": "IPv6Addresses"}, {"direction": "in", "name": "NewIPv6InterfaceID", "relatedStateVariable": "IPv6InterfaceIDs"}, {"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "in", "name": "NewHostName", "relatedStateVariable": "HostName"}]}, {"name": "DeleteServiceByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "NumberOfServices"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "DeviceRegistered"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DynDnsLabel"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DynDNSName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "HostName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui1", "defaultValue": "0", "name": "IPv4ForwardingWarning"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv4Addresses"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv6Addresses"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv6InterfaceIDs"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "NumberOfServices"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Port"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Scheme"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Type"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "URLPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_voipSCPD.xml", "controlURL": "/upnp/control/x_voip", "eventSubURL": "/upnp/control/x_voip", "serviceId": "urn:X_VoIP-com:serviceId:X_VoIP1", "serviceType": "urn:dslforum-org:service:X_VoIP:1"}, "scpd": {"actions": [{"name": "GetInfoEx", "arguments": [{"direction": "out", "name": "NewVoIPNumberMinChars", "relatedStateVariable": "VoIPNumberMinChars"}, {"direction": "out", "name": "NewVoIPNumberMaxChars", "relatedStateVariable": "VoIPNumberMaxChars"}, {"direction": "out", "name": "NewVoIPNumberAllowedChars", "relatedStateVariable": "VoIPNumberAllowedChars"}, {"direction": "out", "name": "NewVoIPUsernameMinChars", "relatedStateVariable": "VoIPUsernameMinChars"}, {"direction": "out", "name": "NewVoIPUsernameMaxChars", "relatedStateVariable": "VoIPUsernameMaxChars"}, {"direction": "out", "name": "NewVoIPUsernameAllowedChars", "relatedStateVariable": "VoIPUsernameAllowedChars"}, {"direction": "out", "name": "NewVoIPPasswordMinChars", "relatedStateVariable": "VoIPPasswordMinChars"}, {"direction": "out", "name": "NewVoIPPasswordMaxChars", "relatedStateVariable": "VoIPPasswordMaxChars"}, {"direction": "out", "name": "NewVoIPPasswordAllowedChars", "relatedStateVariable": "VoIPPasswordAllowedChars"}, {"direction": "out", "name": "NewVoIPRegistrarMinChars", "relatedStateVariable": "VoIPRegistrarMinChars"}, {"direction": "out", "name": "NewVoIPRegistrarMaxChars", "relatedStateVariable": "VoIPRegistrarMaxChars"}, {"direction": "out", "name": "NewVoIPRegistrarAllowedChars", "relatedStateVariable": "VoIPRegistrarAllowedChars"}, {"direction": "out", "name": "NewVoIPSTUNServerMinChars", "relatedStateVariable": "VoIPSTUNServerMinChars"}, {"direction": "out", "name": "NewVoIPSTUNServerMaxChars", "relatedStateVariable": "VoIPSTUNServerMaxChars"}, {"direction": "out", "name": "NewVoIPSTUNServerAllowedChars", "relatedStateVariable": "VoIPSTUNServerAllowedChars"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsernameMinChars", "relatedStateVariable": "X_AVM-DE_ClientUsernameMinChars"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsernameMaxChars", "relatedStateVariable": "X_AVM-DE_ClientUsernameMaxChars"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsernameAllowedChars", "relatedStateVariable": "X_AVM-DE_ClientUsernameAllowedChars"}, {"direction": "out", "name": "NewX_AVM-DE_ClientPasswordMinChars", "relatedStateVariable": "X_AVM-DE_ClientPasswordMinChars"}, {"direction": "out", "name": "NewX_AVM-DE_ClientPasswordMaxChars", "relatedStateVariable": "X_AVM-DE_ClientPasswordMaxChars"}, {"direction": "out", "name": "NewX_AVM-DE_ClientPasswordAllowedChars", "relatedStateVariable": "X_AVM-DE_ClientPasswordAllowedChars"}]}, {"name": "X_AVM-DE_AddVoIPAccount", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}, {"direction": "in", "name": "NewVoIPRegistrar", "relatedStateVariable": "VoIPRegistrar"}, {"direction": "in", "name": "NewVoIPNumber", "relatedStateVariable": "VoIPNumber"}, {"direction": "in", "name": "NewVoIPUsername", "relatedStateVariable": "VoIPUsername"}, {"direction": "in", "name": "NewVoIPPassword", "relatedStateVariable": "VoIPPassword"}, {"direction": "in", "name": "NewVoIPOutboundProxy", "relatedStateVariable": "VoIPOutboundProxy"}, {"direction": "in", "name": "NewVoIPSTUNServer", "relatedStateVariable": "VoIPSTUNServer"}]}, {"name": "X_AVM-DE_GetVoIPAccount", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}, {"direction": "out", "name": "NewVoIPRegistrar", "relatedStateVariable": "VoIPRegistrar"}, {"direction": "out", "name": "NewVoIPNumber", "relatedStateVariable": "VoIPNumber"}, {"direction": "out", "name": "NewVoIPUsername", "relatedStateVariable": "VoIPUsername"}, {"direction": "out", "name": "NewVoIPPassword", "relatedStateVariable": "VoIPPassword"}, {"direction": "out", "name": "NewVoIPOutboundProxy", "relatedStateVariable": "VoIPOutboundProxy"}, {"direction": "out", "name": "NewVoIPSTUNServer", "relatedStateVariable": "VoIPSTUNServer"}]}, {"name": "X_AVM-DE_DelVoIPAccount", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}]}, {"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewFaxT38Enable", "relatedStateVariable": "FaxT38Enable"}, {"direction": "out", "name": "NewVoiceCoding", "relatedStateVariable": "VoiceCoding"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewFaxT38Enable", "relatedStateVariable": "FaxT38Enable"}, {"direction": "in", "name": "NewVoiceCoding", "relatedStateVariable": "VoiceCoding"}]}, {"name": "GetMaxVoIPNumbers", "arguments": [{"direction": "out", "name": "NewMaxVoIPNumbers", "relatedStateVariable": "MaxVoIPNumbers"}]}, {"name": "GetExistingVoIPNumbers", "arguments": [{"direction": "out", "name": "NewExistingVoIPNumbers", "relatedStateVariable": "ExistingVoIPNumbers"}]}, {"name": "X_AVM-DE_GetNumberOfClients", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_NumberOfClients", "relatedStateVariable": "X_AVM-DE_NumberOfClients"}]}, {"name": "X_AVM-DE_GetClient", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsername", "relatedStateVariable": "X_AVM-DE_ClientUsername"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrar", "relatedStateVariable": "X_AVM-DE_ClientRegistrar"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrarPort", "relatedStateVariable": "X_AVM-DE_ClientRegistrarPort"}, {"direction": "out", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "out", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}]}, {"name": "X_AVM-DE_GetClient2", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsername", "relatedStateVariable": "X_AVM-DE_ClientUsername"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrar", "relatedStateVariable": "X_AVM-DE_ClientRegistrar"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrarPort", "relatedStateVariable": "X_AVM-DE_ClientRegistrarPort"}, {"direction": "out", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "out", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "out", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}, {"direction": "out", "name": "NewX_AVM-DE_InternalNumber", "relatedStateVariable": "X_AVM-DE_InternalNumber"}]}, {"name": "X_AVM-DE_SetClient", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "in", "name": "NewX_AVM-DE_ClientPassword", "relatedStateVariable": "X_AVM-DE_ClientPassword"}, {"direction": "in", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "in", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}]}, {"name": "X_AVM-DE_SetClient2", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "in", "name": "NewX_AVM-DE_ClientPassword", "relatedStateVariable": "X_AVM-DE_ClientPassword"}, {"direction": "in", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "in", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "in", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}]}, {"name": "X_AVM-DE_GetClient3", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsername", "relatedStateVariable": "X_AVM-DE_ClientUsername"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrar", "relatedStateVariable": "X_AVM-DE_ClientRegistrar"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrarPort", "relatedStateVariable": "X_AVM-DE_ClientRegistrarPort"}, {"direction": "out", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "out", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "out", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}, {"direction": "out", "name": "NewX_AVM-DE_InComingNumbers", "relatedStateVariable": "X_AVM-DE_InComingNumbers"}, {"direction": "out", "name": "NewX_AVM-DE_ExternalRegistration", "relatedStateVariable": "X_AVM-DE_ExternalRegistration"}, {"direction": "out", "name": "NewX_AVM-DE_InternalNumber", "relatedStateVariable": "X_AVM-DE_InternalNumber"}, {"direction": "out", "name": "NewX_AVM-DE_DelayedCallNotification", "relatedStateVariable": "X_AVM-DE_DelayedCallNotification"}]}, {"name": "X_AVM-DE_GetClientByClientId", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "out", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "out", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "out", "name": "NewX_AVM-DE_ClientUsername", "relatedStateVariable": "X_AVM-DE_ClientUsername"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrar", "relatedStateVariable": "X_AVM-DE_ClientRegistrar"}, {"direction": "out", "name": "NewX_AVM-DE_ClientRegistrarPort", "relatedStateVariable": "X_AVM-DE_ClientRegistrarPort"}, {"direction": "out", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "out", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}, {"direction": "out", "name": "NewX_AVM-DE_InComingNumbers", "relatedStateVariable": "X_AVM-DE_InComingNumbers"}, {"direction": "out", "name": "NewX_AVM-DE_ExternalRegistration", "relatedStateVariable": "X_AVM-DE_ExternalRegistration"}, {"direction": "out", "name": "NewX_AVM-DE_InternalNumber", "relatedStateVariable": "X_AVM-DE_InternalNumber"}, {"direction": "out", "name": "NewX_AVM-DE_DelayedCallNotification", "relatedStateVariable": "X_AVM-DE_DelayedCallNotification"}]}, {"name": "X_AVM-DE_SetClient3", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "in", "name": "NewX_AVM-DE_ClientPassword", "relatedStateVariable": "X_AVM-DE_ClientPassword"}, {"direction": "in", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "in", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "in", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}, {"direction": "in", "name": "NewX_AVM-DE_InComingNumbers", "relatedStateVariable": "X_AVM-DE_InComingNumbers"}, {"direction": "in", "name": "NewX_AVM-DE_ExternalRegistration", "relatedStateVariable": "X_AVM-DE_ExternalRegistration"}]}, {"name": "X_AVM-DE_SetClient4", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "in", "name": "NewX_AVM-DE_ClientPassword", "relatedStateVariable": "X_AVM-DE_ClientPassword"}, {"direction": "in", "name": "NewX_AVM-DE_ClientUsername", "relatedStateVariable": "X_AVM-DE_ClientUsername"}, {"direction": "in", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}, {"direction": "in", "name": "NewX_AVM-DE_ClientId", "relatedStateVariable": "X_AVM-DE_ClientId"}, {"direction": "in", "name": "NewX_AVM-DE_OutGoingNumber", "relatedStateVariable": "X_AVM-DE_OutGoingNumber"}, {"direction": "in", "name": "NewX_AVM-DE_InComingNumbers", "relatedStateVariable": "X_AVM-DE_InComingNumbers"}, {"direction": "out", "name": "NewX_AVM-DE_InternalNumber", "relatedStateVariable": "X_AVM-DE_InternalNumber"}]}, {"name": "X_AVM-DE_GetClients", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_ClientList", "relatedStateVariable": "X_AVM-DE_ClientList"}]}, {"name": "X_AVM-DE_GetNumberOfNumbers", "arguments": [{"direction": "out", "name": "NewNumberOfNumbers", "relatedStateVariable": "NumberOfNumbers"}]}, {"name": "X_AVM-DE_GetNumbers", "arguments": [{"direction": "out", "name": "NewNumberList", "relatedStateVariable": "NumberList"}]}, {"name": "X_AVM-DE_DeleteClient", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}]}, {"name": "X_AVM-DE_DialGetConfig", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}]}, {"name": "X_AVM-DE_DialSetConfig", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}]}, {"name": "X_AVM-DE_DialNumber", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_PhoneNumber", "relatedStateVariable": "X_AVM-DE_PhoneNumber"}]}, {"name": "X_AVM-DE_DialHangup", "arguments": []}, {"name": "X_AVM-DE_GetPhonePort", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "out", "name": "NewX_AVM-DE_PhoneName", "relatedStateVariable": "X_AVM-DE_PhoneName"}]}, {"name": "X_AVM-DE_SetDelayedCallNotification", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_ClientIndex", "relatedStateVariable": "X_AVM-DE_ClientIndex"}, {"direction": "in", "name": "NewX_AVM-DE_DelayedCallNotification", "relatedStateVariable": "X_AVM-DE_DelayedCallNotification"}]}, {"name": "GetVoIPCommonCountryCode", "arguments": [{"direction": "out", "name": "NewVoIPCountryCode", "relatedStateVariable": "VoIPCountryCode"}]}, {"name": "X_AVM-DE_GetVoIPCommonCountryCode", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_LKZ", "relatedStateVariable": "X_AVM-DE_LKZ"}, {"direction": "out", "name": "NewX_AVM-DE_LKZPrefix", "relatedStateVariable": "X_AVM-DE_LKZPrefix"}]}, {"name": "SetVoIPCommonCountryCode", "arguments": [{"direction": "in", "name": "NewVoIPCountryCode", "relatedStateVariable": "VoIPCountryCode"}]}, {"name": "X_AVM-DE_SetVoIPCommonCountryCode", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_LKZ", "relatedStateVariable": "X_AVM-DE_LKZ"}, {"direction": "in", "name": "NewX_AVM-DE_LKZPrefix", "relatedStateVariable": "X_AVM-DE_LKZPrefix"}]}, {"name": "GetVoIPEnableCountryCode", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}, {"direction": "out", "name": "NewVoIPEnableCountryCode", "relatedStateVariable": "VoIPEnableCountryCode"}]}, {"name": "SetVoIPEnableCountryCode", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}, {"direction": "in", "name": "NewVoIPEnableCountryCode", "relatedStateVariable": "VoIPEnableCountryCode"}]}, {"name": "GetVoIPCommonAreaCode", "arguments": [{"direction": "out", "name": "NewVoIPAreaCode", "relatedStateVariable": "VoIPAreaCode"}]}, {"name": "X_AVM-DE_GetVoIPCommonAreaCode", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_OKZ", "relatedStateVariable": "X_AVM-DE_OKZ"}, {"direction": "out", "name": "NewX_AVM-DE_OKZPrefix", "relatedStateVariable": "X_AVM-DE_OKZPrefix"}]}, {"name": "SetVoIPCommonAreaCode", "arguments": [{"direction": "in", "name": "NewVoIPAreaCode", "relatedStateVariable": "VoIPAreaCode"}]}, {"name": "X_AVM-DE_SetVoIPCommonAreaCode", "arguments": [{"direction": "in", "name": "NewX_AVM-DE_OKZ", "relatedStateVariable": "X_AVM-DE_OKZ"}, {"direction": "in", "name": "NewX_AVM-DE_OKZPrefix", "relatedStateVariable": "X_AVM-DE_OKZPrefix"}]}, {"name": "GetVoIPEnableAreaCode", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}, {"direction": "out", "name": "NewVoIPEnableAreaCode", "relatedStateVariable": "VoIPEnableAreaCode"}]}, {"name": "SetVoIPEnableAreaCode", "arguments": [{"direction": "in", "name": "NewVoIPAccountIndex", "relatedStateVariable": "VoIPAccountIndex"}, {"direction": "in", "name": "NewVoIPEnableAreaCode", "relatedStateVariable": "VoIPEnableAreaCode"}]}, {"name": "X_AVM-DE_GetAlarmClock", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "out", "name": "NewX_AVM-DE_AlarmClockEnable", "relatedStateVariable": "X_AVM-DE_AlarmClockEnable"}, {"direction": "out", "name": "NewX_AVM-DE_AlarmClockName", "relatedStateVariable": "X_AVM-DE_AlarmClockName"}, {"direction": "out", "name": "NewX_AVM-DE_AlarmClockTime", "relatedStateVariable": "X_AVM-DE_AlarmClockTime"}, {"direction": "out", "name": "NewX_AVM-DE_AlarmClockWeekdays", "relatedStateVariable": "X_AVM-DE_AlarmClockWeekdays"}, {"direction": "out", "name": "NewX_AVM-DE_AlarmClockPhoneName", "relatedStateVariable": "X_AVM-DE_AlarmClockPhoneName"}]}, {"name": "X_AVM-DE_SetAlarmClockEnable", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "in", "name": "NewX_AVM-DE_AlarmClockEnable", "relatedStateVariable": "X_AVM-DE_AlarmClockEnable"}]}, {"name": "X_AVM-DE_GetNumberOfAlarmClocks", "arguments": [{"direction": "out", "name": "NewX_AVM-DE_NumberOfAlarmClocks", "relatedStateVariable": "X_AVM-DE_NumberOfAlarmClocks"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "VoIPAccountIndex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPRegistrar"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPOutboundProxy"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPNumber"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "MaxVoIPNumbers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "ExistingVoIPNumbers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "VoIPNumberMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "128", "name": "VoIPNumberMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789+", "name": "VoIPNumberAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPCountryCode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "VoIPEnableCountryCode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPAreaCode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "VoIPEnableAreaCode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "VoIPSTUNServer"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "4", "name": "VoIPUsernameMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "128", "name": "VoIPUsernameMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._@", "name": "VoIPUsernameAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "3", "name": "VoIPPasswordMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "64", "name": "VoIPPasswordMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._", "name": "VoIPPasswordAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "VoIPRegistrarMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "64", "name": "VoIPRegistrarMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._", "name": "VoIPRegistrarAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "VoIPSTUNServerMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "255", "name": "VoIPSTUNServerMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._:", "name": "VoIPSTUNServerAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "FaxT38Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["auto", "fixed", "compressed", "autocompressed"], "dataType": "string", "defaultValue": null, "name": "VoiceCoding"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "8", "name": "X_AVM-DE_ClientPasswordMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "64", "name": "X_AVM-DE_ClientPasswordMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._", "name": "X_AVM-DE_ClientPasswordAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "4", "name": "X_AVM-DE_ClientUsernameMinChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "64", "name": "X_AVM-DE_ClientUsernameMaxChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._", "name": "X_AVM-DE_ClientUsernameAllowedChars"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_ClientUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_ClientPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_ClientRegistrar"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "X_AVM-DE_ClientRegistrarPort"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "X_AVM-DE_NumberOfClients"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "X_AVM-DE_ClientIndex"}, "allowedValueRange": {"maximum": "9", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_OutGoingNumber"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_PhoneName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_ClientId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_PhoneNumber"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Index"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_ClientList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_InComingNumbers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "NumberOfNumbers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "NumberList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_ExternalRegistration"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_InternalNumber"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_DelayedCallNotification"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_LKZ"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_LKZPrefix"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_OKZ"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_OKZPrefix"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_AlarmClockPhoneName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_AlarmClockTime"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_AlarmClockWeekdays"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "X_AVM-DE_AlarmClockName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "X_AVM-DE_AlarmClockEnable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "3", "name": "X_AVM-DE_NumberOfAlarmClocks"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_contactSCPD.xml", "controlURL": "/upnp/control/x_contact", "eventSubURL": "/upnp/control/x_contact", "serviceId": "urn:X_AVM-DE_OnTel-com:serviceId:X_AVM-DE_OnTel1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_OnTel:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewLastConnect", "relatedStateVariable": "LastConnect"}, {"direction": "out", "name": "NewUrl", "relatedStateVariable": "Url"}, {"direction": "out", "name": "NewServiceId", "relatedStateVariable": "ServiceId"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}]}, {"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewUrl", "relatedStateVariable": "Url"}, {"direction": "in", "name": "NewServiceId", "relatedStateVariable": "ServiceId"}, {"direction": "in", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}, {"direction": "in", "name": "NewName", "relatedStateVariable": "Name"}]}, {"name": "GetInfoByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewLastConnect", "relatedStateVariable": "LastConnect"}, {"direction": "out", "name": "NewUrl", "relatedStateVariable": "Url"}, {"direction": "out", "name": "NewServiceId", "relatedStateVariable": "ServiceId"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}]}, {"name": "SetEnableByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "SetConfigByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "in", "name": "NewUrl", "relatedStateVariable": "Url"}, {"direction": "in", "name": "NewServiceId", "relatedStateVariable": "ServiceId"}, {"direction": "in", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "in", "name": "NewPassword", "relatedStateVariable": "Password"}, {"direction": "in", "name": "NewName", "relatedStateVariable": "Name"}]}, {"name": "DeleteByIndex", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}]}, {"name": "GetNumberOfEntries", "arguments": [{"direction": "out", "name": "NewOnTelNumberOfEntries", "relatedStateVariable": "OnTelNumberOfEntries"}]}, {"name": "GetCallList", "arguments": [{"direction": "out", "name": "NewCallListURL", "relatedStateVariable": "CallListURL"}]}, {"name": "GetPhonebookList", "arguments": [{"direction": "out", "name": "NewPhonebookList", "relatedStateVariable": "PhonebookList"}]}, {"name": "GetPhonebook", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "out", "name": "NewPhonebookName", "relatedStateVariable": "PhonebookName"}, {"direction": "out", "name": "NewPhonebookExtraID", "relatedStateVariable": "PhonebookExtraID"}, {"direction": "out", "name": "NewPhonebookURL", "relatedStateVariable": "PhonebookURL"}]}, {"name": "AddPhonebook", "arguments": [{"direction": "in", "name": "NewPhonebookExtraID", "relatedStateVariable": "PhonebookExtraID"}, {"direction": "in", "name": "NewPhonebookName", "relatedStateVariable": "PhonebookName"}]}, {"name": "DeletePhonebook", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookExtraID", "relatedStateVariable": "PhonebookExtraID"}]}, {"name": "GetPhonebookEntry", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookEntryID", "relatedStateVariable": "PhonebookEntryID"}, {"direction": "out", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}]}, {"name": "GetPhonebookEntryUID", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookEntryUniqueID", "relatedStateVariable": "PhonebookEntryUniqueID"}, {"direction": "out", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}]}, {"name": "SetPhonebookEntry", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookEntryID", "relatedStateVariable": "PhonebookEntryID"}, {"direction": "in", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}]}, {"name": "SetPhonebookEntryUID", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}, {"direction": "out", "name": "NewPhonebookEntryUniqueID", "relatedStateVariable": "PhonebookEntryUniqueID"}]}, {"name": "DeletePhonebookEntry", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookEntryID", "relatedStateVariable": "PhonebookEntryID"}]}, {"name": "DeletePhonebookEntryUID", "arguments": [{"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}, {"direction": "in", "name": "NewPhonebookEntryUniqueID", "relatedStateVariable": "PhonebookEntryUniqueID"}]}, {"name": "GetCallBarringEntry", "arguments": [{"direction": "in", "name": "NewPhonebookEntryID", "relatedStateVariable": "PhonebookEntryID"}, {"direction": "out", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}]}, {"name": "GetCallBarringEntryByNum", "arguments": [{"direction": "in", "name": "NewNumber", "relatedStateVariable": "Number"}, {"direction": "out", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}]}, {"name": "GetCallBarringList", "arguments": [{"direction": "out", "name": "NewPhonebookURL", "relatedStateVariable": "PhonebookURL"}]}, {"name": "SetCallBarringEntry", "arguments": [{"direction": "in", "name": "NewPhonebookEntryData", "relatedStateVariable": "PhonebookEntryData"}, {"direction": "out", "name": "NewPhonebookEntryUniqueID", "relatedStateVariable": "PhonebookEntryUniqueID"}]}, {"name": "DeleteCallBarringEntryUID", "arguments": [{"direction": "in", "name": "NewPhonebookEntryUniqueID", "relatedStateVariable": "PhonebookEntryUniqueID"}]}, {"name": "GetDECTHandsetList", "arguments": [{"direction": "out", "name": "NewDectIDList", "relatedStateVariable": "DectIDList"}]}, {"name": "GetDECTHandsetInfo", "arguments": [{"direction": "in", "name": "NewDectID", "relatedStateVariable": "DectID"}, {"direction": "out", "name": "NewHandsetName", "relatedStateVariable": "HandsetName"}, {"direction": "out", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}]}, {"name": "SetDECTHandsetPhonebook", "arguments": [{"direction": "in", "name": "NewDectID", "relatedStateVariable": "DectID"}, {"direction": "in", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}]}, {"name": "GetNumberOfDeflections", "arguments": [{"direction": "out", "name": "NewNumberOfDeflections", "relatedStateVariable": "NumberOfDeflections"}]}, {"name": "GetDeflection", "arguments": [{"direction": "in", "name": "NewDeflectionId", "relatedStateVariable": "DeflectionId"}, {"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "out", "name": "NewNumber", "relatedStateVariable": "Number"}, {"direction": "out", "name": "NewDeflectionToNumber", "relatedStateVariable": "DeflectionToNumber"}, {"direction": "out", "name": "NewMode", "relatedStateVariable": "Mode"}, {"direction": "out", "name": "NewOutgoing", "relatedStateVariable": "Outgoing"}, {"direction": "out", "name": "NewPhonebookID", "relatedStateVariable": "PhonebookID"}]}, {"name": "GetDeflections", "arguments": [{"direction": "out", "name": "NewDeflectionList", "relatedStateVariable": "DeflectionList"}]}, {"name": "SetDeflectionEnable", "arguments": [{"direction": "in", "name": "NewDeflectionId", "relatedStateVariable": "DeflectionId"}, {"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Url"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ServiceId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Username"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Password"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "LastConnect"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "OnTelNumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Index"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "CallListURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhonebookList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "PhonebookID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhonebookName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhonebookEntryData"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhonebookExtraID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PhonebookEntryID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "PhonebookEntryUniqueID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhonebookURL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DectIDList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "DectID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "HandsetName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "NumberOfDeflections"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "DeflectionId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["unknown", "toAny", "toPOTS", "toVoIP", "toMSN", "fromAnonymous", "fromAll", "fromNumber", "fromVIP", "fromNotVIP", "fromPB", "fon1", "fon2", "fon3", "fon4"], "dataType": "string", "defaultValue": "unknown", "name": "Type"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Number"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DeflectionToNumber"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["eUnknown", "eImmediately", "eShortDelayed", "eLongDelayed", "eBusy", "eParallelCall", "eNoSignal", "eVIP", "eDelayed", "eDelayedOrBusy", "eBellBlockade", "eDirectCall", "eOff"], "dataType": "string", "defaultValue": "eUnknown", "name": "Mode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Outgoing"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DeflectionList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_dectSCPD.xml", "controlURL": "/upnp/control/x_dect", "eventSubURL": "/upnp/control/x_dect", "serviceId": "urn:X_AVM-DE_Dect-com:serviceId:X_AVM-DE_Dect1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Dect:1"}, "scpd": {"actions": [{"name": "GetNumberOfDectEntries", "arguments": [{"direction": "out", "name": "NewNumberOfEntries", "relatedStateVariable": "NumberOfEntries"}]}, {"name": "GetGenericDectEntry", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "NumberOfEntries"}, {"direction": "out", "name": "NewID", "relatedStateVariable": "ID"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewModel", "relatedStateVariable": "Model"}, {"direction": "out", "name": "NewUpdateAvailable", "relatedStateVariable": "UpdateAvailable"}, {"direction": "out", "name": "NewUpdateSuccessful", "relatedStateVariable": "UpdateSuccessful"}, {"direction": "out", "name": "NewUpdateInfo", "relatedStateVariable": "UpdateInfo"}]}, {"name": "GetSpecificDectEntry", "arguments": [{"direction": "in", "name": "NewID", "relatedStateVariable": "ID"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewModel", "relatedStateVariable": "Model"}, {"direction": "out", "name": "NewUpdateAvailable", "relatedStateVariable": "UpdateAvailable"}, {"direction": "out", "name": "NewUpdateSuccessful", "relatedStateVariable": "UpdateSuccessful"}, {"direction": "out", "name": "NewUpdateInfo", "relatedStateVariable": "UpdateInfo"}]}, {"name": "DectDoUpdate", "arguments": [{"direction": "in", "name": "NewID", "relatedStateVariable": "ID"}]}, {"name": "GetDectListPath", "arguments": [{"direction": "out", "name": "NewDectListPath", "relatedStateVariable": "DectListPath"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "NumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Active"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Model"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "UpdateAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["unknown", "failed", "succeeded"], "dataType": "string", "defaultValue": null, "name": "UpdateSuccessful"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "UpdateInfo"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DectListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_tamSCPD.xml", "controlURL": "/upnp/control/x_tam", "eventSubURL": "/upnp/control/x_tam", "serviceId": "urn:X_AVM-DE_TAM-com:serviceId:X_AVM-DE_TAM1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_TAM:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "out", "name": "NewEnable", "relatedStateVariable": "Enable"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewTAMRunning", "relatedStateVariable": "TAMRunning"}, {"direction": "out", "name": "NewStick", "relatedStateVariable": "Stick"}, {"direction": "out", "name": "NewStatus", "relatedStateVariable": "Status"}, {"direction": "out", "name": "NewCapacity", "relatedStateVariable": "Capacity"}, {"direction": "out", "name": "NewMode", "relatedStateVariable": "Mode"}, {"direction": "out", "name": "NewRingSeconds", "relatedStateVariable": "RingSeconds"}, {"direction": "out", "name": "NewPhoneNumbers", "relatedStateVariable": "PhoneNumbers"}]}, {"name": "SetEnable", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "in", "name": "NewEnable", "relatedStateVariable": "Enable"}]}, {"name": "GetMessageList", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "out", "name": "NewURL", "relatedStateVariable": "URL"}]}, {"name": "MarkMessage", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "in", "name": "NewMessageIndex", "relatedStateVariable": "MessageIndex"}, {"direction": "in", "name": "NewMarkedAsRead", "relatedStateVariable": "MarkedAsRead"}]}, {"name": "DeleteMessage", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "in", "name": "NewMessageIndex", "relatedStateVariable": "MessageIndex"}]}, {"name": "GetList", "arguments": [{"direction": "out", "name": "NewTAMList", "relatedStateVariable": "TAMList"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Index"}, "allowedValueRange": {"maximum": "4", "minimum": "0", "step": "1"}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "TAMRunning"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Stick"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Status"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "Capacity"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "MessageIndex"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "URL"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "1", "name": "MarkedAsRead"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "TAMList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["play_announcement", "record_message", "timeprofile"], "dataType": "string", "defaultValue": null, "name": "Mode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "PhoneNumbers"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "RingSeconds"}, "allowedValueRange": {"maximum": "255", "minimum": "0", "step": "1"}}]}}, {"attributes": {"SCPDURL": "/x_appsetupSCPD.xml", "controlURL": "/upnp/control/x_appsetup", "eventSubURL": "/upnp/control/x_appsetup", "serviceId": "urn:X_AVM-DE_AppSetup-com:serviceId:X_AVM-DE_AppSetup1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_AppSetup:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewMinCharsAppId", "relatedStateVariable": "MinCharsAppId"}, {"direction": "out", "name": "NewMaxCharsAppId", "relatedStateVariable": "MaxCharsAppId"}, {"direction": "out", "name": "NewAllowedCharsAppId", "relatedStateVariable": "AllowedCharsAppId"}, {"direction": "out", "name": "NewMinCharsAppDisplayName", "relatedStateVariable": "MinCharsAppDisplayName"}, {"direction": "out", "name": "NewMaxCharsAppDisplayName", "relatedStateVariable": "MaxCharsAppDisplayName"}, {"direction": "out", "name": "NewMinCharsAppUsername", "relatedStateVariable": "MinCharsAppUsername"}, {"direction": "out", "name": "NewMaxCharsAppUsername", "relatedStateVariable": "MaxCharsAppUsername"}, {"direction": "out", "name": "NewAllowedCharsAppUsername", "relatedStateVariable": "AllowedCharsAppUsername"}, {"direction": "out", "name": "NewMinCharsAppPassword", "relatedStateVariable": "MinCharsAppPassword"}, {"direction": "out", "name": "NewMaxCharsAppPassword", "relatedStateVariable": "MaxCharsAppPassword"}, {"direction": "out", "name": "NewAllowedCharsAppPassword", "relatedStateVariable": "AllowedCharsAppPassword"}, {"direction": "out", "name": "NewMinCharsIPSecIdentifier", "relatedStateVariable": "MinCharsIPSecIdentifier"}, {"direction": "out", "name": "NewMaxCharsIPSecIdentifier", "relatedStateVariable": "MaxCharsIPSecIdentifier"}, {"direction": "out", "name": "NewAllowedCharsIPSecIdentifier", "relatedStateVariable": "AllowedCharsIPSecIdentifier"}, {"direction": "out", "name": "NewAllowedCharsCryptAlgos", "relatedStateVariable": "AllowedCharsCryptAlgos"}, {"direction": "out", "name": "NewAllowedCharsAppAVMAddress", "relatedStateVariable": "AllowedCharsAppAVMAddress"}, {"direction": "out", "name": "NewMinCharsFilter", "relatedStateVariable": "MinCharsFilter"}, {"direction": "out", "name": "NewMaxCharsFilter", "relatedStateVariable": "MaxCharsFilter"}, {"direction": "out", "name": "NewAllowedCharsFilter", "relatedStateVariable": "AllowedCharsFilter"}, {"direction": "out", "name": "NewMinCharsIPSecPreSharedKey", "relatedStateVariable": "MinCharsIPSecPreSharedKey"}, {"direction": "out", "name": "NewMaxCharsIPSecPreSharedKey", "relatedStateVariable": "MaxCharsIPSecPreSharedKey"}, {"direction": "out", "name": "NewAllowedCharsIPSecPreSharedKey", "relatedStateVariable": "AllowedCharsIPSecPreSharedKey"}, {"direction": "out", "name": "NewMinCharsIPSecXauthUsername", "relatedStateVariable": "MinCharsIPSecXauthUsername"}, {"direction": "out", "name": "NewMaxCharsIPSecXauthUsername", "relatedStateVariable": "MaxCharsIPSecXauthUsername"}, {"direction": "out", "name": "NewAllowedCharsIPSecXauthUsername", "relatedStateVariable": "AllowedCharsIPSecXauthUsername"}, {"direction": "out", "name": "NewMinCharsIPSecXauthPassword", "relatedStateVariable": "MinCharsIPSecXauthPassword"}, {"direction": "out", "name": "NewMaxCharsIPSecXauthPassword", "relatedStateVariable": "MaxCharsIPSecXauthPassword"}, {"direction": "out", "name": "NewAllowedCharsIPSecXauthPassword", "relatedStateVariable": "AllowedCharsIPSecXauthPassword"}]}, {"name": "GetConfig", "arguments": [{"direction": "out", "name": "NewConfigRight", "relatedStateVariable": "ConfigRight"}, {"direction": "out", "name": "NewAppRight", "relatedStateVariable": "AppRight"}, {"direction": "out", "name": "NewNasRight", "relatedStateVariable": "NasRight"}, {"direction": "out", "name": "NewPhoneRight", "relatedStateVariable": "PhoneRight"}, {"direction": "out", "name": "NewDialRight", "relatedStateVariable": "DialRight"}, {"direction": "out", "name": "NewHomeautoRight", "relatedStateVariable": "HomeautoRight"}, {"direction": "out", "name": "NewInternetRights", "relatedStateVariable": "InternetRights"}, {"direction": "out", "name": "NewAccessFromInternet", "relatedStateVariable": "AccessFromInternet"}]}, {"name": "GetAppMessageFilter", "arguments": [{"direction": "in", "name": "NewAppId", "relatedStateVariable": "AppId"}, {"direction": "out", "name": "NewFilterList", "relatedStateVariable": "FilterList"}]}, {"name": "RegisterApp", "arguments": [{"direction": "in", "name": "NewAppId", "relatedStateVariable": "AppId"}, {"direction": "in", "name": "NewAppDisplayName", "relatedStateVariable": "AppDisplayName"}, {"direction": "in", "name": "NewAppDeviceMAC", "relatedStateVariable": "AppDeviceMAC"}, {"direction": "in", "name": "NewAppUsername", "relatedStateVariable": "AppUsername"}, {"direction": "in", "name": "NewAppPassword", "relatedStateVariable": "AppPassword"}, {"direction": "in", "name": "NewAppRight", "relatedStateVariable": "AppRight"}, {"direction": "in", "name": "NewNasRight", "relatedStateVariable": "NasRight"}, {"direction": "in", "name": "NewPhoneRight", "relatedStateVariable": "PhoneRight"}, {"direction": "in", "name": "NewHomeautoRight", "relatedStateVariable": "HomeautoRight"}, {"direction": "in", "name": "NewAppInternetRights", "relatedStateVariable": "AppInternetRights"}]}, {"name": "SetAppVPN", "arguments": [{"direction": "in", "name": "NewAppId", "relatedStateVariable": "AppId"}, {"direction": "in", "name": "NewIPSecIdentifier", "relatedStateVariable": "IPSecIdentifier"}, {"direction": "in", "name": "NewIPSecPreSharedKey", "relatedStateVariable": "IPSecPreSharedKey"}, {"direction": "in", "name": "NewIPSecXauthUsername", "relatedStateVariable": "IPSecXauthUsername"}, {"direction": "in", "name": "NewIPSecXauthPassword", "relatedStateVariable": "IPSecXauthPassword"}]}, {"name": "SetAppVPNwithPFS", "arguments": [{"direction": "in", "name": "NewAppId", "relatedStateVariable": "AppId"}, {"direction": "in", "name": "NewIPSecIdentifier", "relatedStateVariable": "IPSecIdentifier"}, {"direction": "in", "name": "NewIPSecPreSharedKey", "relatedStateVariable": "IPSecPreSharedKey"}, {"direction": "in", "name": "NewIPSecXauthUsername", "relatedStateVariable": "IPSecXauthUsername"}, {"direction": "in", "name": "NewIPSecXauthPassword", "relatedStateVariable": "IPSecXauthPassword"}]}, {"name": "SetAppMessageFilter", "arguments": [{"direction": "in", "name": "NewAppId", "relatedStateVariable": "AppId"}, {"direction": "in", "name": "NewType", "relatedStateVariable": "Type"}, {"direction": "in", "name": "NewFilter", "relatedStateVariable": "Filter"}]}, {"name": "SetAppMessageReceiver", "arguments": [{"direction": "in", "name": "NewAppId", "relatedStateVariable": "AppId"}, {"direction": "in", "name": "NewCryptAlgos", "relatedStateVariable": "CryptAlgos"}, {"direction": "in", "name": "NewAppAVMAddress", "relatedStateVariable": "AppAVMAddress"}, {"direction": "in", "name": "NewAppAVMPasswordHash", "relatedStateVariable": "AppAVMPasswordHash"}, {"direction": "out", "name": "EncryptionSecret", "relatedStateVariable": "EncryptionSecret"}, {"direction": "out", "name": "BoxSenderId", "relatedStateVariable": "BoxSenderId"}]}, {"name": "ResetEvent", "arguments": [{"direction": "in", "name": "NewEventId", "relatedStateVariable": "EventId"}]}, {"name": "GetAppRemoteInfo", "arguments": [{"direction": "out", "name": "NewSubnetMask", "relatedStateVariable": "SubnetMask"}, {"direction": "out", "name": "NewIPAddress", "relatedStateVariable": "IPAddress"}, {"direction": "out", "name": "NewExternalIPAddress", "relatedStateVariable": "ExternalIPAddress"}, {"direction": "out", "name": "NewExternalIPv6Address", "relatedStateVariable": "ExternalIPv6Address"}, {"direction": "out", "name": "NewRemoteAccessDDNSEnabled", "relatedStateVariable": "RemoteAccessDDNSEnabled"}, {"direction": "out", "name": "NewRemoteAccessDDNSDomain", "relatedStateVariable": "RemoteAccessDDNSDomain"}, {"direction": "out", "name": "NewMyFritzEnabled", "relatedStateVariable": "MyFritzEnabled"}, {"direction": "out", "name": "NewMyFritzDynDNSName", "relatedStateVariable": "MyFritzDynDNSName"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsAppId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "256", "name": "MaxCharsAppId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "name": "AllowedCharsAppId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsAppDisplayName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "256", "name": "MaxCharsAppDisplayName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsAppUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "32", "name": "MaxCharsAppUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "name": "AllowedCharsAppUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "8", "name": "MinCharsAppPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "32", "name": "MaxCharsAppPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", "name": "AllowedCharsAppPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsIPSecIdentifier"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "256", "name": "MaxCharsIPSecIdentifier"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "name": "AllowedCharsIPSecIdentifier"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsIPSecPreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "64", "name": "MaxCharsIPSecPreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "name": "AllowedCharsIPSecPreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsIPSecXauthUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "256", "name": "MaxCharsIPSecXauthUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "name": "AllowedCharsIPSecXauthUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsIPSecXauthPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "128", "name": "MaxCharsIPSecXauthPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "name": "AllowedCharsIPSecXauthPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["NO", "RO", "RW", "UNDEFINED"], "dataType": "string", "defaultValue": "NO", "name": "ConfigRight"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["NO", "RO", "RW", "UNDEFINED"], "dataType": "string", "defaultValue": "NO", "name": "AppRight"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["NO", "RO", "RW", "UNDEFINED"], "dataType": "string", "defaultValue": "NO", "name": "NasRight"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["NO", "RO", "RW", "UNDEFINED"], "dataType": "string", "defaultValue": "NO", "name": "PhoneRight"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["NO", "RO", "RW", "UNDEFINED"], "dataType": "string", "defaultValue": "NO", "name": "DialRight"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["NO", "RO", "RW", "UNDEFINED"], "dataType": "string", "defaultValue": "NO", "name": "HomeautoRight"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "InternetRights"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AccessFromInternet"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppDisplayName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppDeviceMAC"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "AppInternetRights"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPSecIdentifier"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPSecPreSharedKey"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPSecXauthUsername"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPSecXauthPassword"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "CryptAlgos"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppAVMAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AppAVMPasswordHash"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.", "name": "AllowedCharsCryptAlgos"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.", "name": "AllowedCharsAppAVMAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "MinCharsFilter"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1024", "name": "MaxCharsFilter"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,+:-_", "name": "AllowedCharsFilter"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "EncryptionSecret"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "BoxSenderId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "EventId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Filter"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["aha_ident", "tel_local_number"], "dataType": "string", "defaultValue": null, "name": "Type"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "FilterList"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "SubnetMask"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ExternalIPAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ExternalIPv6Address"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "RemoteAccessDDNSEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "RemoteAccessDDNSDomain"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "MyFritzEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MyFritzDynDNSName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_homeautoSCPD.xml", "controlURL": "/upnp/control/x_homeauto", "eventSubURL": "/upnp/control/x_homeauto", "serviceId": "urn:X_AVM-DE_Homeauto-com:serviceId:X_AVM-DE_Homeauto1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Homeauto:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewAllowedCharsAIN", "relatedStateVariable": "AllowedCharsAIN"}, {"direction": "out", "name": "NewMaxCharsAIN", "relatedStateVariable": "MaxCharsAIN"}, {"direction": "out", "name": "NewMinCharsAIN", "relatedStateVariable": "MinCharsAIN"}, {"direction": "out", "name": "NewMaxCharsDeviceName", "relatedStateVariable": "MaxCharsDeviceName"}, {"direction": "out", "name": "NewMinCharsDeviceName", "relatedStateVariable": "MinCharsDeviceName"}]}, {"name": "GetGenericDeviceInfos", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "Index"}, {"direction": "out", "name": "NewAIN", "relatedStateVariable": "AIN"}, {"direction": "out", "name": "NewDeviceId", "relatedStateVariable": "DeviceId"}, {"direction": "out", "name": "NewFunctionBitMask", "relatedStateVariable": "FunctionBitMask"}, {"direction": "out", "name": "NewFirmwareVersion", "relatedStateVariable": "FirmwareVersion"}, {"direction": "out", "name": "NewManufacturer", "relatedStateVariable": "Manufacturer"}, {"direction": "out", "name": "NewProductName", "relatedStateVariable": "ProductName"}, {"direction": "out", "name": "NewDeviceName", "relatedStateVariable": "DeviceName"}, {"direction": "out", "name": "NewPresent", "relatedStateVariable": "Present"}, {"direction": "out", "name": "NewMultimeterIsEnabled", "relatedStateVariable": "MultimeterIsEnabled"}, {"direction": "out", "name": "NewMultimeterIsValid", "relatedStateVariable": "MultimeterIsValid"}, {"direction": "out", "name": "NewMultimeterPower", "relatedStateVariable": "MultimeterPower"}, {"direction": "out", "name": "NewMultimeterEnergy", "relatedStateVariable": "MultimeterEnergy"}, {"direction": "out", "name": "NewTemperatureIsEnabled", "relatedStateVariable": "TemperatureIsEnabled"}, {"direction": "out", "name": "NewTemperatureIsValid", "relatedStateVariable": "TemperatureIsValid"}, {"direction": "out", "name": "NewTemperatureCelsius", "relatedStateVariable": "TemperatureCelsius"}, {"direction": "out", "name": "NewTemperatureOffset", "relatedStateVariable": "TemperatureOffset"}, {"direction": "out", "name": "NewSwitchIsEnabled", "relatedStateVariable": "SwitchIsEnabled"}, {"direction": "out", "name": "NewSwitchIsValid", "relatedStateVariable": "SwitchIsValid"}, {"direction": "out", "name": "NewSwitchState", "relatedStateVariable": "SwitchState"}, {"direction": "out", "name": "NewSwitchMode", "relatedStateVariable": "SwitchMode"}, {"direction": "out", "name": "NewSwitchLock", "relatedStateVariable": "SwitchLock"}, {"direction": "out", "name": "NewHkrIsEnabled", "relatedStateVariable": "HkrIsEnabled"}, {"direction": "out", "name": "NewHkrIsValid", "relatedStateVariable": "HkrIsValid"}, {"direction": "out", "name": "NewHkrIsTemperature", "relatedStateVariable": "HkrIsTemperature"}, {"direction": "out", "name": "NewHkrSetVentilStatus", "relatedStateVariable": "HkrSetVentilStatus"}, {"direction": "out", "name": "NewHkrSetTemperature", "relatedStateVariable": "HkrSetTemperature"}, {"direction": "out", "name": "NewHkrReduceVentilStatus", "relatedStateVariable": "HkrReduceVentilStatus"}, {"direction": "out", "name": "NewHkrReduceTemperature", "relatedStateVariable": "HkrReduceTemperature"}, {"direction": "out", "name": "NewHkrComfortVentilStatus", "relatedStateVariable": "HkrComfortVentilStatus"}, {"direction": "out", "name": "NewHkrComfortTemperature", "relatedStateVariable": "HkrComfortTemperature"}]}, {"name": "GetSpecificDeviceInfos", "arguments": [{"direction": "in", "name": "NewAIN", "relatedStateVariable": "AIN"}, {"direction": "out", "name": "NewDeviceId", "relatedStateVariable": "DeviceId"}, {"direction": "out", "name": "NewFunctionBitMask", "relatedStateVariable": "FunctionBitMask"}, {"direction": "out", "name": "NewFirmwareVersion", "relatedStateVariable": "FirmwareVersion"}, {"direction": "out", "name": "NewManufacturer", "relatedStateVariable": "Manufacturer"}, {"direction": "out", "name": "NewProductName", "relatedStateVariable": "ProductName"}, {"direction": "out", "name": "NewDeviceName", "relatedStateVariable": "DeviceName"}, {"direction": "out", "name": "NewPresent", "relatedStateVariable": "Present"}, {"direction": "out", "name": "NewMultimeterIsEnabled", "relatedStateVariable": "MultimeterIsEnabled"}, {"direction": "out", "name": "NewMultimeterIsValid", "relatedStateVariable": "MultimeterIsValid"}, {"direction": "out", "name": "NewMultimeterPower", "relatedStateVariable": "MultimeterPower"}, {"direction": "out", "name": "NewMultimeterEnergy", "relatedStateVariable": "MultimeterEnergy"}, {"direction": "out", "name": "NewTemperatureIsEnabled", "relatedStateVariable": "TemperatureIsEnabled"}, {"direction": "out", "name": "NewTemperatureIsValid", "relatedStateVariable": "TemperatureIsValid"}, {"direction": "out", "name": "NewTemperatureCelsius", "relatedStateVariable": "TemperatureCelsius"}, {"direction": "out", "name": "NewTemperatureOffset", "relatedStateVariable": "TemperatureOffset"}, {"direction": "out", "name": "NewSwitchIsEnabled", "relatedStateVariable": "SwitchIsEnabled"}, {"direction": "out", "name": "NewSwitchIsValid", "relatedStateVariable": "SwitchIsValid"}, {"direction": "out", "name": "NewSwitchState", "relatedStateVariable": "SwitchState"}, {"direction": "out", "name": "NewSwitchMode", "relatedStateVariable": "SwitchMode"}, {"direction": "out", "name": "NewSwitchLock", "relatedStateVariable": "SwitchLock"}, {"direction": "out", "name": "NewHkrIsEnabled", "relatedStateVariable": "HkrIsEnabled"}, {"direction": "out", "name": "NewHkrIsValid", "relatedStateVariable": "HkrIsValid"}, {"direction": "out", "name": "NewHkrIsTemperature", "relatedStateVariable": "HkrIsTemperature"}, {"direction": "out", "name": "NewHkrSetVentilStatus", "relatedStateVariable": "HkrSetVentilStatus"}, {"direction": "out", "name": "NewHkrSetTemperature", "relatedStateVariable": "HkrSetTemperature"}, {"direction": "out", "name": "NewHkrReduceVentilStatus", "relatedStateVariable": "HkrReduceVentilStatus"}, {"direction": "out", "name": "NewHkrReduceTemperature", "relatedStateVariable": "HkrReduceTemperature"}, {"direction": "out", "name": "NewHkrComfortVentilStatus", "relatedStateVariable": "HkrComfortVentilStatus"}, {"direction": "out", "name": "NewHkrComfortTemperature", "relatedStateVariable": "HkrComfortTemperature"}]}, {"name": "SetDeviceName", "arguments": [{"direction": "in", "name": "NewAIN", "relatedStateVariable": "AIN"}, {"direction": "in", "name": "NewDeviceName", "relatedStateVariable": "DeviceName"}]}, {"name": "SetSwitch", "arguments": [{"direction": "in", "name": "NewAIN", "relatedStateVariable": "AIN"}, {"direction": "in", "name": "NewSwitchState", "relatedStateVariable": "SwitchState"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Index"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "AIN"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": "0123456789ABCDEFabcdef :-grptmp", "name": "AllowedCharsAIN"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "19", "name": "MaxCharsAIN"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsAIN"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "DeviceId"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "DeviceName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "79", "name": "MaxCharsDeviceName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "1", "name": "MinCharsDeviceName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "FunctionBitMask"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "FirmwareVersion"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Manufacturer"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ProductName"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["DISCONNECTED", "REGISTRERED", "CONNECTED", "UNKNOWN"], "dataType": "string", "defaultValue": null, "name": "Present"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["DISABLED", "ENABLED", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "MultimeterIsEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["INVALID", "VALID", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "MultimeterIsValid"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MultimeterPower"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui4", "defaultValue": "0", "name": "MultimeterEnergy"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["DISABLED", "ENABLED", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "TemperatureIsEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["INVALID", "VALID", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "TemperatureIsValid"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "TemperatureCelsius"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "TemperatureOffset"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["DISABLED", "ENABLED", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "SwitchIsEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["INVALID", "VALID", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "SwitchIsValid"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["OFF", "ON", "TOGGLE", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "SwitchState"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["AUTO", "MANUAL", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "SwitchMode"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "SwitchLock"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["DISABLED", "ENABLED", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "HkrIsEnabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["INVALID", "VALID", "UNDEFINED"], "dataType": "string", "defaultValue": null, "name": "HkrIsValid"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "HkrIsTemperature"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["CLOSED", "OPEN", "TEMP"], "dataType": "string", "defaultValue": null, "name": "HkrSetVentilStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "HkrSetTemperature"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["CLOSED", "OPEN", "TEMP"], "dataType": "string", "defaultValue": null, "name": "HkrReduceVentilStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "HkrReduceTemperature"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["CLOSED", "OPEN", "TEMP"], "dataType": "string", "defaultValue": null, "name": "HkrComfortVentilStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "i4", "defaultValue": "0", "name": "HkrComfortTemperature"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_homeplugSCPD.xml", "controlURL": "/upnp/control/x_homeplug", "eventSubURL": "/upnp/control/x_homeplug", "serviceId": "urn:X_AVM-DE_Homeplug-com:serviceId:X_AVM-DE_Homeplug1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Homeplug:1"}, "scpd": {"actions": [{"name": "GetNumberOfDeviceEntries", "arguments": [{"direction": "out", "name": "NewNumberOfEntries", "relatedStateVariable": "NumberOfEntries"}]}, {"name": "GetGenericDeviceEntry", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "NumberOfEntries"}, {"direction": "out", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewModel", "relatedStateVariable": "Model"}, {"direction": "out", "name": "NewUpdateAvailable", "relatedStateVariable": "UpdateAvailable"}, {"direction": "out", "name": "NewUpdateSuccessful", "relatedStateVariable": "UpdateSuccessful"}]}, {"name": "GetSpecificDeviceEntry", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}, {"direction": "out", "name": "NewActive", "relatedStateVariable": "Active"}, {"direction": "out", "name": "NewName", "relatedStateVariable": "Name"}, {"direction": "out", "name": "NewModel", "relatedStateVariable": "Model"}, {"direction": "out", "name": "NewUpdateAvailable", "relatedStateVariable": "UpdateAvailable"}, {"direction": "out", "name": "NewUpdateSuccessful", "relatedStateVariable": "UpdateSuccessful"}]}, {"name": "DeviceDoUpdate", "arguments": [{"direction": "in", "name": "NewMACAddress", "relatedStateVariable": "MACAddress"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "NumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "MACAddress"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Active"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Name"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Model"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "UpdateAvailable"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["unknown", "failed", "succeeded"], "dataType": "string", "defaultValue": null, "name": "UpdateSuccessful"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_filelinksSCPD.xml", "controlURL": "/upnp/control/x_filelinks", "eventSubURL": "/upnp/control/x_filelinks", "serviceId": "urn:X_AVM-DE_Filelinks-com:serviceId:X_AVM-DE_Filelinks1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Filelinks:1"}, "scpd": {"actions": [{"name": "GetNumberOfFilelinkEntries", "arguments": [{"direction": "out", "name": "NewNumberOfEntries", "relatedStateVariable": "NumberOfEntries"}]}, {"name": "GetGenericFilelinkEntry", "arguments": [{"direction": "in", "name": "NewIndex", "relatedStateVariable": "NumberOfEntries"}, {"direction": "out", "name": "NewID", "relatedStateVariable": "ID"}, {"direction": "out", "name": "NewValid", "relatedStateVariable": "Valid"}, {"direction": "out", "name": "NewPath", "relatedStateVariable": "Path"}, {"direction": "out", "name": "NewIsDirectory", "relatedStateVariable": "IsDirectory"}, {"direction": "out", "name": "NewUrl", "relatedStateVariable": "Url"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewAccessCountLimit", "relatedStateVariable": "AccessCountLimit"}, {"direction": "out", "name": "NewAccessCount", "relatedStateVariable": "AccessCount"}, {"direction": "out", "name": "NewExpire", "relatedStateVariable": "Expire"}, {"direction": "out", "name": "NewExpireDate", "relatedStateVariable": "ExpireDate"}]}, {"name": "GetSpecificFilelinkEntry", "arguments": [{"direction": "in", "name": "NewID", "relatedStateVariable": "ID"}, {"direction": "out", "name": "NewValid", "relatedStateVariable": "Valid"}, {"direction": "out", "name": "NewPath", "relatedStateVariable": "Path"}, {"direction": "out", "name": "NewIsDirectory", "relatedStateVariable": "IsDirectory"}, {"direction": "out", "name": "NewUrl", "relatedStateVariable": "Url"}, {"direction": "out", "name": "NewUsername", "relatedStateVariable": "Username"}, {"direction": "out", "name": "NewAccessCountLimit", "relatedStateVariable": "AccessCountLimit"}, {"direction": "out", "name": "NewAccessCount", "relatedStateVariable": "AccessCount"}, {"direction": "out", "name": "NewExpire", "relatedStateVariable": "Expire"}, {"direction": "out", "name": "NewExpireDate", "relatedStateVariable": "ExpireDate"}]}, {"name": "NewFilelinkEntry", "arguments": [{"direction": "in", "name": "NewPath", "relatedStateVariable": "Path"}, {"direction": "in", "name": "NewAccessCountLimit", "relatedStateVariable": "AccessCountLimit"}, {"direction": "in", "name": "NewExpire", "relatedStateVariable": "Expire"}, {"direction": "out", "name": "NewID", "relatedStateVariable": "ID"}]}, {"name": "SetFilelinkEntry", "arguments": [{"direction": "in", "name": "NewID", "relatedStateVariable": "ID"}, {"direction": "in", "name": "NewAccessCountLimit", "relatedStateVariable": "AccessCountLimit"}, {"direction": "in", "name": "NewExpire", "relatedStateVariable": "Expire"}]}, {"name": "DeleteFilelinkEntry", "arguments": [{"direction": "in", "name": "NewID", "relatedStateVariable": "ID"}]}, {"name": "GetFilelinkListPath", "arguments": [{"direction": "out", "name": "NewFilelinkListPath", "relatedStateVariable": "FilelinkListPath"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "NumberOfEntries"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "ID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Valid"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Path"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "IsDirectory"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Url"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Username"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "AccessCountLimit"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "AccessCount"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "ui2", "defaultValue": "0", "name": "Expire"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "dateTime", "defaultValue": "0001-01-01T00:00:00", "name": "ExpireDate"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "FilelinkListPath"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_authSCPD.xml", "controlURL": "/upnp/control/x_auth", "eventSubURL": "/upnp/control/x_auth", "serviceId": "urn:X_AVM-DE_Auth-com:serviceId:X_AVM-DE_Auth1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_Auth:1"}, "scpd": {"actions": [{"name": "GetInfo", "arguments": [{"direction": "out", "name": "NewEnabled", "relatedStateVariable": "Enabled"}]}, {"name": "GetState", "arguments": [{"direction": "out", "name": "NewState", "relatedStateVariable": "State"}]}, {"name": "SetConfig", "arguments": [{"direction": "in", "name": "NewAction", "relatedStateVariable": "Action"}, {"direction": "out", "name": "NewState", "relatedStateVariable": "State"}, {"direction": "out", "name": "NewToken", "relatedStateVariable": "Token"}, {"direction": "out", "name": "NewMethods", "relatedStateVariable": "Methods"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Enabled"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "State"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Action"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Token"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "Methods"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}, {"attributes": {"SCPDURL": "/x_hostfilterSCPD.xml", "controlURL": "/upnp/control/x_hostfilter", "eventSubURL": "/upnp/control/x_hostfilter", "serviceId": "urn:X_AVM-DE_HostFilter-com:serviceId:X_AVM-DE_HostFilter1", "serviceType": "urn:dslforum-org:service:X_AVM-DE_HostFilter:1"}, "scpd": {"actions": [{"name": "MarkTicket", "arguments": [{"direction": "out", "name": "NewTicketID", "relatedStateVariable": "TicketID"}]}, {"name": "GetTicketIDStatus", "arguments": [{"direction": "in", "name": "NewTicketID", "relatedStateVariable": "TicketID"}, {"direction": "out", "name": "NewTicketIDStatus", "relatedStateVariable": "TicketIDStatus"}]}, {"name": "DiscardAllTickets", "arguments": []}, {"name": "DisallowWANAccessByIP", "arguments": [{"direction": "in", "name": "NewIPv4Address", "relatedStateVariable": "IPv4Address"}, {"direction": "in", "name": "NewDisallow", "relatedStateVariable": "Disallow"}]}, {"name": "GetWANAccessByIP", "arguments": [{"direction": "in", "name": "NewIPv4Address", "relatedStateVariable": "IPv4Address"}, {"direction": "out", "name": "NewDisallow", "relatedStateVariable": "Disallow"}, {"direction": "out", "name": "NewWANAccess", "relatedStateVariable": "WANAccess"}]}], "specVersion": {"major": "1", "minor": "0"}, "state_variables": [{"attributes": {"allowed_values": [], "dataType": "boolean", "defaultValue": "0", "name": "Disallow"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "IPv4Address"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": [], "dataType": "string", "defaultValue": null, "name": "TicketID"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["error", "denied", "granted"], "dataType": "string", "defaultValue": null, "name": "WANAccess"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}, {"attributes": {"allowed_values": ["marked", "unmarked", "invalid"], "dataType": "string", "defaultValue": null, "name": "TicketIDStatus"}, "allowedValueRange": {"maximum": null, "minimum": null, "step": null}}]}}]}, "specVersion": {"major": "1", "minor": "0"}, "systemVersion": {"Buildnumber": "92051", "Display": "154.07.29", "HW": "226", "Major": "154", "Minor": "7", "Patch": "29"}}]fritzconnection-1.15.0/fritzconnection/tests/xml/description.pcl000066400000000000000000006200761501211554500252310ustar00rootroot00000000000000](fritzconnection.core.processor Description)}(devicehDevice)}( _services]hService)}(_scpdhScpd)}(_actions]_state_variables]h StateVariable)}(nameDummydataTypestring defaultValueNallowed_values]allowedValueListhallowedValueRangeh ValueRange)}(minimumNmaximumNstepNububa specVersionh SpecVersion)}(major1minor0ub actionListh ActionList)}_storagehsbserviceStateTablehServiceStateTable)}h?@[\]^_`{|}~h#]h%j' h&h()}(h+Nh,Nh-Nububh)}(hConfigPasswordh stringh"Nh#]h%j/ h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_AnonymousLoginEnabledh booleanh"h6h#]h%j6 h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ButtonLoginEnabledh booleanh"h6h#]h%j= h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_CurrentUsernameh stringh"Nh#]h%jD h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_CurrentUserRightsh stringh"Nh#]h%jK h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_UserListh stringh"Nh#]h%jR h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}hurn:X_AVM-DE_RemoteAccess-com:serviceId:X_AVM-DE_RemoteAccess1hF/upnp/control/x_remotehH/upnp/control/x_remotehJ/x_remoteSCPD.xmlubh)}(hh)}(h](hW)}(hZ](h])}(h NewEnabledhaouthcEnabledubh])}(hNewDeviceRegisteredhaouthcDeviceRegisteredubh])}(h NewDynDNSNamehaouthc DynDNSNameubh])}(hNewPorthaouthcPortubehtNhGetInfohvhx)}hsbubhW)}(hZ](h])}(hNewX_AVM-DE_LKZhainhc X_AVM-DE_LKZubh])}(hNewX_AVM-DE_LKZPrefixhainhcX_AVM-DE_LKZPrefixubehtNh!X_AVM-DE_SetVoIPCommonCountryCodehvhx)}hh&h()}(h+Nh,Nh-Nububh)}(hVoIPNumberMinCharsh ui2h"h4h#]h%jEh&h()}(h+Nh,Nh-Nububh)}(hVoIPNumberMaxCharsh ui2h"128h#]h%jLh&h()}(h+Nh,Nh-Nububh)}(hVoIPNumberAllowedCharsh stringh" 0123456789+h#]h%jTh&h()}(h+Nh,Nh-Nububh)}(hVoIPCountryCodeh stringh"Nh#]h%j\h&h()}(h+Nh,Nh-Nububh)}(hVoIPEnableCountryCodeh booleanh"h6h#]h%jch&h()}(h+Nh,Nh-Nububh)}(h VoIPAreaCodeh stringh"Nh#]h%jjh&h()}(h+Nh,Nh-Nububh)}(hVoIPEnableAreaCodeh booleanh"h6h#]h%jqh&h()}(h+Nh,Nh-Nububh)}(hVoIPSTUNServerh stringh"Nh#]h%jxh&h()}(h+Nh,Nh-Nububh)}(hVoIPUsernameMinCharsh ui2h"4h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPUsernameMaxCharsh ui2h"128h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPUsernameAllowedCharsh stringh"B0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._@h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPPasswordMinCharsh ui2h"3h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPPasswordMaxCharsh ui2h"64h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPPasswordAllowedCharsh stringh"A0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPRegistrarMinCharsh ui2h"h4h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPRegistrarMaxCharsh ui2h"64h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPRegistrarAllowedCharsh stringh"A0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPSTUNServerMinCharsh ui2h"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPSTUNServerMaxCharsh ui2h"255h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hVoIPSTUNServerAllowedCharsh stringh"B0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._:h#]h%jh&h()}(h+Nh,Nh-Nububh)}(h FaxT38Enableh booleanh"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(h VoiceCodingh stringh"Nh#](autofixed compressedautocompressedeh%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientPasswordMinCharsh ui2h"8h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientPasswordMaxCharsh ui2h"64h#]h%jh&h()}(h+Nh,Nh-Nububh)}(h#X_AVM-DE_ClientPasswordAllowedCharsh stringh"A0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientUsernameMinCharsh ui2h"jh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientUsernameMaxCharsh ui2h"64h#]h%jh&h()}(h+Nh,Nh-Nububh)}(h#X_AVM-DE_ClientUsernameAllowedCharsh stringh"A0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientUsernameh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientPasswordh stringh"Nh#]h%j%h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientRegistrarh stringh"Nh#]h%j,h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientRegistrarPorth ui2h"h6h#]h%j3h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_NumberOfClientsh ui2h"h6h#]h%j:h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientIndexh ui2h"h6h#]h%jAh&h()}(h+h6h,9h-h4ububh)}(hX_AVM-DE_OutGoingNumberh stringh"Nh#]h%jIh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_PhoneNameh stringh"Nh#]h%jPh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientIdh stringh"Nh#]h%jWh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_PhoneNumberh stringh"Nh#]h%j^h&h()}(h+Nh,Nh-Nububh)}(hIndexh ui2h"h6h#]h%jeh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ClientListh stringh"Nh#]h%jlh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_InComingNumbersh stringh"Nh#]h%jsh&h()}(h+Nh,Nh-Nububh)}(hNumberOfNumbersh ui4h"h6h#]h%jzh&h()}(h+Nh,Nh-Nububh)}(h NumberListh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ExternalRegistrationh booleanh"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_InternalNumberh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(h X_AVM-DE_DelayedCallNotificationh booleanh"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(h X_AVM-DE_LKZh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_LKZPrefixh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(h X_AVM-DE_OKZh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_OKZPrefixh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_AlarmClockPhoneNameh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_AlarmClockTimeh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_AlarmClockWeekdaysh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_AlarmClockNameh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_AlarmClockEnableh booleanh"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_NumberOfAlarmClocksh ui2h"jh#]h%jh&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}h0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hMinCharsAppDisplayNameh ui2h"h4h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hMaxCharsAppDisplayNameh ui2h"256h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hMinCharsAppUsernameh ui2h"h4h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hMaxCharsAppUsernameh ui2h"32h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsAppUsernameh stringh">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hMinCharsAppPasswordh ui2h"jh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hMaxCharsAppPasswordh ui2h"32h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsAppPasswordh stringh"_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~h#]h%j&h&h()}(h+Nh,Nh-Nububh)}(hMinCharsIPSecIdentifierh ui2h"h4h#]h%j.h&h()}(h+Nh,Nh-Nububh)}(hMaxCharsIPSecIdentifierh ui2h"256h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsIPSecIdentifierh stringh">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzh#]h%j=h&h()}(h+Nh,Nh-Nububh)}(hMinCharsIPSecPreSharedKeyh ui2h"h4h#]h%jEh&h()}(h+Nh,Nh-Nububh)}(hMaxCharsIPSecPreSharedKeyh ui2h"64h#]h%jLh&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsIPSecPreSharedKeyh stringh">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzh#]h%jTh&h()}(h+Nh,Nh-Nububh)}(hMinCharsIPSecXauthUsernameh ui2h"h4h#]h%j\h&h()}(h+Nh,Nh-Nububh)}(hMaxCharsIPSecXauthUsernameh ui2h"256h#]h%jch&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsIPSecXauthUsernameh stringh">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzh#]h%jkh&h()}(h+Nh,Nh-Nububh)}(hMinCharsIPSecXauthPasswordh ui2h"h4h#]h%jsh&h()}(h+Nh,Nh-Nububh)}(hMaxCharsIPSecXauthPasswordh ui2h"128h#]h%jzh&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsIPSecXauthPasswordh stringh">0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzh#]h%jh&h()}(h+Nh,Nh-Nububh)}(h ConfigRighth stringh"NOh#](NORORW UNDEFINEDeh%jh&h()}(h+Nh,Nh-Nububh)}(hAppRighth stringh"NOh#](NORORW UNDEFINEDeh%jh&h()}(h+Nh,Nh-Nububh)}(hNasRighth stringh"NOh#](NORORW UNDEFINEDeh%jh&h()}(h+Nh,Nh-Nububh)}(h PhoneRighth stringh"NOh#](NORORW UNDEFINEDeh%jh&h()}(h+Nh,Nh-Nububh)}(h DialRighth stringh"NOh#](NORORW UNDEFINEDeh%jh&h()}(h+Nh,Nh-Nububh)}(h HomeautoRighth stringh"NOh#](NORORW UNDEFINEDeh%jh&h()}(h+Nh,Nh-Nububh)}(hInternetRightsh booleanh"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hAccessFromInterneth booleanh"h6h#]h%jh&h()}(h+Nh,Nh-Nububh)}(hAppIdh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hAppDisplayNameh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(h AppDeviceMACh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(h AppUsernameh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(h AppPasswordh stringh"Nh#]h%jh&h()}(h+Nh,Nh-Nububh)}(hAppInternetRightsh booleanh"h6h#]h%j h&h()}(h+Nh,Nh-Nububh)}(hIPSecIdentifierh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hIPSecPreSharedKeyh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hIPSecXauthUsernameh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hIPSecXauthPasswordh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(h CryptAlgosh stringh"Nh#]h%j& h&h()}(h+Nh,Nh-Nububh)}(h AppAVMAddressh stringh"Nh#]h%j- h&h()}(h+Nh,Nh-Nububh)}(hAppAVMPasswordHashh stringh"Nh#]h%j4 h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsCryptAlgosh stringh"A0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.h#]h%j; h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsAppAVMAddressh stringh"A0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.h#]h%jC h&h()}(h+Nh,Nh-Nububh)}(hMinCharsFilterh ui2h"h6h#]h%jK h&h()}(h+Nh,Nh-Nububh)}(hMaxCharsFilterh ui2h"1024h#]h%jR h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsFilterh stringh"C0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz,+:-_h#]h%jZ h&h()}(h+Nh,Nh-Nububh)}(hEncryptionSecreth stringh"Nh#]h%jb h&h()}(h+Nh,Nh-Nububh)}(h BoxSenderIdh stringh"Nh#]h%ji h&h()}(h+Nh,Nh-Nububh)}(hEventIdh ui4h"h6h#]h%jp h&h()}(h+Nh,Nh-Nububh)}(hFilterh stringh"Nh#]h%jw h&h()}(h+Nh,Nh-Nububh)}(hTypeh stringh"Nh#]( aha_identtel_local_numbereh%j~ h&h()}(h+Nh,Nh-Nububh)}(h FilterListh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(h SubnetMaskh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(h IPAddressh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hExternalIPAddressh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hExternalIPv6Addressh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hRemoteAccessDDNSEnabledh booleanh"h6h#]h%j h&h()}(h+Nh,Nh-Nububh)}(hRemoteAccessDDNSDomainh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububh)}(hMyFritzEnabledh booleanh"h6h#]h%j h&h()}(h+Nh,Nh-Nububh)}(hMyFritzDynDNSNameh stringh"Nh#]h%j h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}h?@[\]^_`{|}~h#]h%jB*h&h()}(h+Nh,Nh-Nububh)}(h MinCharsPSKh ui1h"64h#]h%jJ*h&h()}(h+Nh,Nh-Nububh)}(h MaxCharsPSKh ui1h"64h#]h%jR*h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsPSKh stringh"0123456789ABCDEFabcdefh#]h%jZ*h&h()}(h+Nh,Nh-Nububh)}(hMinCharsKeyPassphraseh ui1h"jh#]h%jb*h&h()}(h+Nh,Nh-Nububh)}(hMaxCharsKeyPassphraseh ui1h"63h#]h%ji*h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsKeyPassphraseh stringh"_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~h#]h%jq*h&h()}(h+Nh,Nh-Nububh)}(hBeaconAdvertisementEnabledh booleanh"h6h#]h%jy*h&h()}(h+Nh,Nh-Nububh)}(hTotalAssociationsh ui2h"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceMACAddressh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceIPAddressh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceAuthStateh booleanh"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hStickSurfEnableh booleanh"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hTotalPacketsSenth ui4h"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hTotalPacketsReceivedh ui4h"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_IPTVoptimizeh booleanh"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SignalStrengthh ui1h"h6h#]h%j*h&h()}(h+h6h,100h-h4ububh)}(hX_AVM-DE_Speedh ui2h"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(h NightControlh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hNightTimeControlNoForcedOffh booleanh"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(h TrafficModeh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(h ManualSpeedh booleanh"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(h MaxSpeedDSh ui4h"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(h MaxSpeedUSh ui4h"h6h#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_APEnabledh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_APTypeh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_TimeoutActiveh stringh"Nh#]h%j*h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_Timeouth stringh"Nh#]h%j+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_TimeRemainh stringh"Nh#]h%j +h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_NoForcedOffh stringh"Nh#]h%j+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_UserIsolationh stringh"Nh#]h%j+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_EncryptionModeh stringh"Nh#]h%j"+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_LastChangedStamph ui4h"h6h#]h%j)+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_PossibleBeaconTypesh stringh"Nh#]h%j0+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSModeh stringh"Nh#](otherstoppbceh%j7+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSStatush stringh"Nh#](offinactiveactivesuccess err_common err_timeout err_reconfig err_internal err_abortNeh%jA+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSEnableh booleanh"h6h#]h%jQ+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WLANDeviceListPathh stringh"Nh#]h%jX+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedRXh ui4h"h6h#]h%j_+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedMaxh ui4h"h6h#]h%jf+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedRXMaxh ui4h"h6h#]h%jm+h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WLANGlobalEnableh booleanh"h6h#]h%jt+h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}h?@[\]^_`{|}~h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(h MinCharsPSKh ui1h"64h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(h MaxCharsPSKh ui1h"64h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsPSKh stringh"0123456789ABCDEFabcdefh#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hMinCharsKeyPassphraseh ui1h"jh#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hMaxCharsKeyPassphraseh ui1h"63h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsKeyPassphraseh stringh"_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hBeaconAdvertisementEnabledh booleanh"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hTotalAssociationsh ui2h"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceMACAddressh stringh"Nh#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceIPAddressh stringh"Nh#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceAuthStateh booleanh"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hStickSurfEnableh booleanh"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hTotalPacketsSenth ui4h"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hTotalPacketsReceivedh ui4h"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_IPTVoptimizeh booleanh"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SignalStrengthh ui1h"h6h#]h%j/h&h()}(h+h6h,100h-h4ububh)}(hX_AVM-DE_Speedh ui2h"h6h#]h%j/h&h()}(h+Nh,Nh-Nububh)}(h NightControlh stringh"Nh#]h%j0h&h()}(h+Nh,Nh-Nububh)}(hNightTimeControlNoForcedOffh booleanh"h6h#]h%j 0h&h()}(h+Nh,Nh-Nububh)}(h TrafficModeh stringh"Nh#]h%j0h&h()}(h+Nh,Nh-Nububh)}(h ManualSpeedh booleanh"h6h#]h%j0h&h()}(h+Nh,Nh-Nububh)}(h MaxSpeedDSh ui4h"h6h#]h%j"0h&h()}(h+Nh,Nh-Nububh)}(h MaxSpeedUSh ui4h"h6h#]h%j)0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_APEnabledh stringh"Nh#]h%j00h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_APTypeh stringh"Nh#]h%j70h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_TimeoutActiveh stringh"Nh#]h%j>0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_Timeouth stringh"Nh#]h%jE0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_TimeRemainh stringh"Nh#]h%jL0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_NoForcedOffh stringh"Nh#]h%jS0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_UserIsolationh stringh"Nh#]h%jZ0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_EncryptionModeh stringh"Nh#]h%ja0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_LastChangedStamph ui4h"h6h#]h%jh0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_PossibleBeaconTypesh stringh"Nh#]h%jo0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSModeh stringh"Nh#](otherstoppbceh%jv0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSStatush stringh"Nh#](offinactiveactivesuccess err_common err_timeout err_reconfig err_internal err_abortNeh%j0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSEnableh booleanh"h6h#]h%j0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WLANDeviceListPathh stringh"Nh#]h%j0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedRXh ui4h"h6h#]h%j0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedMaxh ui4h"h6h#]h%j0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedRXMaxh ui4h"h6h#]h%j0h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WLANGlobalEnableh booleanh"h6h#]h%j0h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}h?@[\]^_`{|}~h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(h MinCharsPSKh ui1h"64h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(h MaxCharsPSKh ui1h"64h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsPSKh stringh"0123456789ABCDEFabcdefh#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hMinCharsKeyPassphraseh ui1h"jh#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hMaxCharsKeyPassphraseh ui1h"63h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hAllowedCharsKeyPassphraseh stringh"_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hBeaconAdvertisementEnabledh booleanh"h6h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hTotalAssociationsh ui2h"h6h#]h%j4h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceMACAddressh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceIPAddressh stringh"Nh#]h%j 5h&h()}(h+Nh,Nh-Nububh)}(hAssociatedDeviceAuthStateh booleanh"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hStickSurfEnableh booleanh"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hTotalPacketsSenth ui4h"h6h#]h%j!5h&h()}(h+Nh,Nh-Nububh)}(hTotalPacketsReceivedh ui4h"h6h#]h%j(5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_IPTVoptimizeh booleanh"h6h#]h%j/5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SignalStrengthh ui1h"h6h#]h%j65h&h()}(h+h6h,100h-h4ububh)}(hX_AVM-DE_Speedh ui2h"h6h#]h%j>5h&h()}(h+Nh,Nh-Nububh)}(h NightControlh stringh"Nh#]h%jE5h&h()}(h+Nh,Nh-Nububh)}(hNightTimeControlNoForcedOffh booleanh"h6h#]h%jL5h&h()}(h+Nh,Nh-Nububh)}(h TrafficModeh stringh"Nh#]h%jS5h&h()}(h+Nh,Nh-Nububh)}(h ManualSpeedh booleanh"h6h#]h%jZ5h&h()}(h+Nh,Nh-Nububh)}(h MaxSpeedDSh ui4h"h6h#]h%ja5h&h()}(h+Nh,Nh-Nububh)}(h MaxSpeedUSh ui4h"h6h#]h%jh5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_APEnabledh stringh"Nh#]h%jo5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_APTypeh stringh"Nh#]h%jv5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_TimeoutActiveh stringh"Nh#]h%j}5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_Timeouth stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_TimeRemainh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_NoForcedOffh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_UserIsolationh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_EncryptionModeh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_LastChangedStamph ui4h"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_PossibleBeaconTypesh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSModeh stringh"Nh#](otherstoppbceh%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSStatush stringh"Nh#](offinactiveactivesuccess err_common err_timeout err_reconfig err_internal err_abortNeh%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WPSEnableh booleanh"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WLANDeviceListPathh stringh"Nh#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedRXh ui4h"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedMaxh ui4h"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_SpeedRXMaxh ui4h"h6h#]h%j5h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WLANGlobalEnableh booleanh"h6h#]h%j5h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}h7h&h()}(h+Nh,Nh-Nububh)}(hActiveh booleanh"h6h#]h%jE7h&h()}(h+Nh,Nh-Nububh)}(hHostNameh stringh"Nh#]h%jL7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_ChangeCounterh ui4h"h6h#]h%jS7h&h()}(h+Nh,Nh-Nububh)}(hAutoWOLEnabledh booleanh"h6h#]h%jZ7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_Disallowh booleanh"h6h#]h%ja7h&h()}(h+Nh,Nh-Nububh)}(h X_AVM-DE_Porth ui4h"h6h#]h%jh7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_Speedh ui4h"h6h#]h%jo7h&h()}(h+Nh,Nh-Nububh)}(h X_AVM-DE_URLh stringh"Nh#]h%jv7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_UpdateAvailableh booleanh"h6h#]h%j}7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_UpdateSuccessfulh stringh"Nh#](unknownfailed succeededeh%j7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_InfoURLh stringh"Nh#]h%j7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_Modelh stringh"Nh#]h%j7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_HostListPathh stringh"Nh#]h%j7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_MeshListPathh stringh"Nh#]h%j7h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_WANAccessh stringh"Nh#](errorgranteddeniedeh%j7h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}hurn:LANEthernetIfCfg-com:serviceId:LANEthernetInterfaceConfig1hF/upnp/control/lanethernetifcfghH/upnp/control/lanethernetifcfghJ/ethifconfigSCPD.xmlubh)}(hh)}(h](hW)}(hZ](h])}(hNewDHCPServerConfigurablehaouthcDHCPServerConfigurableubh])}(h NewDHCPRelayhaouthc DHCPRelayubh])}(h NewMinAddresshaouthc MinAddressubh])}(h NewMaxAddresshaouthc MaxAddressubh])}(hNewReservedAddresseshaouthcReservedAddressesubh])}(hNewDHCPServerEnablehaouthcDHCPServerEnableubh])}(h NewDNSServershaouthc DNSServersubh])}(h NewDomainNamehaouthc DomainNameubh])}(h NewIPRoutershaouthc IPRoutersubh])}(h NewSubnetMaskhaouthc SubnetMaskubehtNhGetInfohvhx)}h<h&h()}(h+Nh,Nh-Nububh)}(hUpstreamCurrRateh i4h"h6h#]h%jE<h&h()}(h+Nh,Nh-Nububh)}(hDownstreamCurrRateh ui4h"h6h#]h%jL<h&h()}(h+Nh,Nh-Nububh)}(hUpstreamMaxRateh ui4h"h6h#]h%jS<h&h()}(h+Nh,Nh-Nububh)}(hDownstreamMaxRateh ui4h"h6h#]h%jZ<h&h()}(h+Nh,Nh-Nububh)}(hUpstreamNoiseMarginh ui4h"h6h#]h%ja<h&h()}(h+Nh,Nh-Nububh)}(hDownstreamNoiseMarginh ui4h"h6h#]h%jh<h&h()}(h+Nh,Nh-Nububh)}(hUpstreamAttenuationh ui4h"h6h#]h%jo<h&h()}(h+Nh,Nh-Nububh)}(hDownstreamAttenuationh ui4h"h6h#]h%jv<h&h()}(h+Nh,Nh-Nububh)}(h ATURVendorh stringh"Nh#]h%j}<h&h()}(h+Nh,Nh-Nububh)}(h ATURCountryh stringh"Nh#]h%j<h&h()}(h+Nh,Nh-Nububh)}(h UpstreamPowerh ui2h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hDownstreamPowerh ui2h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.ReceiveBlocksh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.TransmitBlocksh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.CellDelinh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.LinkRetrainh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.InitErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.InitTimeoutsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.LossOfFramingh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.ErroredSecsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.SeverelyErroredSecsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.FECErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.ATUCFECErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.HECErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.ATUCHECErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.CRCErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hStats.Total.ATUCCRCErrorsh ui4h"h6h#]h%j<h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_DSLDiagnoseStateh stringh"Nh#]h%j=h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_CableNokDistanceh i4h"h6h#]h%j =h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_DSLLastDiagnoseTimeh ui4h"h6h#]h%j=h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_DSLSignalLossTimeh ui4h"h6h#]h%j=h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_DSLActiveh booleanh"h6h#]h%j=h&h()}(h+Nh,Nh-Nububh)}(hX_AVM-DE_DSLSynch booleanh"h6h#]h%j%=h&h()}(h+Nh,Nh-Nububh)}(hSNRGdsh ui4h"h4h#]h%j,=h&h()}(h+Nh,Nh-Nububh)}(hSNRGush ui4h"h4h#]h%j3=h&h()}(h+Nh,Nh-Nububh)}(hSNRpsdsh stringh"Nh#]h%j:=h&h()}(h+Nh,Nh-Nububh)}(hSNRpsush stringh"Nh#]h%jA=h&h()}(h+Nh,Nh-Nububh)}(hSNRMTdsh ui4h"h6h#]h%jH=h&h()}(h+Nh,Nh-Nububh)}(hSNRMTush ui4h"h6h#]h%jO=h&h()}(h+Nh,Nh-Nububh)}(hLATNdsh stringh"Nh#]h%jV=h&h()}(h+Nh,Nh-Nububh)}(hLATNush stringh"Nh#]h%j]=h&h()}(h+Nh,Nh-Nububh)}(hModulationTypeh stringh"Nh#]( ADSL G.liteG.shdslIDSLHDSLSDSLVDSLeh%jd=h&h()}(h+Nh,Nh-Nububh)}(h LinkStatush stringh"Nh#](UpDown Initializing Unavailableeh%jq=h&h()}(h+Nh,Nh-Nububh)}(hCurrentProfileh stringh"Nh#]h%j|=h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}hsbubhW)}(hZ]h])}(hNewATMEncapsulationhainhcATMEncapsulationubahtNhSetATMEncapsulationhvhx)}hsbubhW)}(hZ]h])}(hNewATMEncapsulationhaouthcATMEncapsulationubahtNhGetATMEncapsulationhvhx)}hsbubhW)}(hZ](h])}(hNewATMTransmittedBlockshaouthcATMTransmittedBlocksubh])}(hNewATMReceivedBlockshaouthcATMReceivedBlocksubh])}(hNewAAL5CRCErrorshaouthc AAL5CRCErrorsubh])}(hNewATMCRCErrorshaouthc ATMCRCErrorsubehtNh GetStatisticshvhx)}hsbubeh](h)}(hEnableh booleanh"h6h#]h%jB>h&h()}(h+Nh,Nh-Nububh)}(hLinkTypeh stringh"Nh#](EoAPPPoAPPPoE Unconfiguredeh%jI>h&h()}(h+Nh,Nh-Nububh)}(h LinkStatush stringh"Nh#](UpDown Initializing Unavailableeh%jT>h&h()}(h+Nh,Nh-Nububh)}(hDestinationAddressh stringh"Nh#]h%j_>h&h()}(h+Nh,Nh-Nububh)}(hATMEncapsulationh stringh"Nh#](LLCVCMUXeh%jf>h&h()}(h+Nh,Nh-Nububh)}(h AutoConfigh booleanh"h6h#]h%jo>h&h()}(h+Nh,Nh-Nububh)}(hATMQoSh stringh"Nh#]h%jv>h&h()}(h+Nh,Nh-Nububh)}(hATMPeakCellRateh ui4h"h6h#]h%j}>h&h()}(h+Nh,Nh-Nububh)}(hATMSustainableCellRateh ui4h"h6h#]h%j>h&h()}(h+Nh,Nh-Nububh)}(hATMTransmittedBlocksh ui4h"h6h#]h%j>h&h()}(h+Nh,Nh-Nububh)}(hATMReceivedBlocksh ui4h"h6h#]h%j>h&h()}(h+Nh,Nh-Nububh)}(h AAL5CRCErrorsh ui4h"h6h#]h%j>h&h()}(h+Nh,Nh-Nububh)}(h ATMCRCErrorsh ui4h"h6h#]h%j>h&h()}(h+Nh,Nh-Nububeh.h0)}(h3h4h5h6ubh7h9)}hsbubhNhNhB+urn:dslforum-org:service:WANDSLLinkConfig:1hD4urn:WANDSLLinkConfig-com:serviceId:WANDSLLinkConfig1hF/upnp/control/wandsllinkconfig1hH/upnp/control/wandsllinkconfig1hJ/wandsllinkconfigSCPD.xmlubh)}(hh)}(h]hW)}(hZ]h])}(hNewEthernetLinkStatushaouthcEthernetLinkStatusubahtNhGetEthernetLinkStatushvhx)}hsbubah]h)}(hEthernetLinkStatush stringh"Nh#]h%j>h&h()}(h+Nh,Nh-Nububah.h0)}(h3h4h5h6ubh7h9)}hsbh=h?)}hsbubhNhNhB0urn:dslforum-org:service:WANEthernetLinkConfig:1hD>urn:WANEthernetLinkConfig-com:serviceId:WANEthernetLinkConfig1hF/upnp/control/wanethlinkconfig1hH/upnp/control/wanethlinkconfig1hJ/wanethlinkconfigSCPD.xmlubh)}(hh)}(h](hW)}(hZ](h])}(h NewEnablehaouthcEnableubh])}(hNewConnectionStatushaouthcConnectionStatusubh])}(hNewPossibleConnectionTypeshaouthcPossibleConnectionTypesubh])}(hNewConnectionTypehaouthcConnectionTypeubh])}(hNewNamehaouthcNameubh])}(h NewUptimehaouthcUptimeubh])}(hNewUpstreamMaxBitRatehaouthcUpstreamMaxBitRateubh])}(hNewDownstreamMaxBitRatehaouthcDownstreamMaxBitRateubh])}(hNewLastConnectionErrorhaouthcLastConnectionErrorubh])}(hNewIdleDisconnectTimehaouthcIdleDisconnectTimeubh])}(hNewRSIPAvailablehaouthc RSIPAvailableubh])}(h NewUserNamehaouthcUserNameubh])}(h NewNATEnabledhaouthc NATEnabledubh])}(hNewExternalIPAddresshaouthcExternalIPAddressubh])}(h NewDNSServershaouthc DNSServersubh])}(h NewMACAddresshaouthc MACAddressubh])}(hNewConnectionTriggerhaouthcConnectionTriggerubh])}(hNewLastAuthErrorInfohaouthcLastAuthErrorInfoubh])}(hNewMaxCharsUsernamehaouthcMaxCharsUsernameubh])}(hNewMinCharsUsernamehaouthcMinCharsUsernameubh])}(hNewAllowedCharsUsernamehaouthcAllowedCharsUsernameubh])}(hNewMaxCharsPasswordhaouthcMaxCharsPasswordubh])}(hNewMinCharsPasswordhaouthcMinCharsPasswordubh])}(hNewAllowedCharsPasswordhaouthcAllowedCharsPasswordubh])}(hNewTransportTypehaouthc TransportTypeubh])}(hNewRouteProtocolRxhaouthcRouteProtocolRxubh])}(hNewPPPoEServiceNamehaouthcPPPoEServiceNameubh])}(hNewRemoteIPAddresshaouthcRemoteIPAddressubh])}(hNewPPPoEACNamehaouthc PPPoEACNameubh])}(h NewDNSEnabledhaouthc DNSEnabledubh])}(hNewDNSOverrideAllowedhaouthcDNSOverrideAllowedubehtNhGetInfohvhx)}hsbubhW)}(hZ](h])}(hNewConnectionTypehaouthcConnectionTypeubh])}(hNewPossibleConnectionTypeshaouthcPossibleConnectionTypesubehtNhGetConnectionTypeInfohvhx)}hsbh=h?)}h 1 192.168.178.54 F8:4D:89:7C:0A:32 1 MacBook 802.11 0 866 0 unknown 0 0 granted 0 2 192.168.178.34 C2:39:6F:FB:A3:E8 1 fritz.repeater Ethernet 3 100 0 succeeded FRITZ!Repeater 1200 http://192.168.178.34 0 0 granted 0 4 192.168.178.32 B4:CD:27:37:78:E4 0 someones-HUAWEI 802.11 0 0 0 unknown 0 0 granted 0 3 192.168.178.49 B8:27:EB:D1:DC:06 1 raspberrypi Ethernet 1 1000 0 unknown 0 0 granted 0 fritzconnection-1.15.0/fritzconnection/tests/xml/igdconnSCPD.xml000066400000000000000000000347351501211554500250240ustar00rootroot00000000000000 1 0 SetConnectionType NewConnectionType in ConnectionType GetConnectionTypeInfo NewConnectionType out ConnectionType NewPossibleConnectionTypes out PossibleConnectionTypes GetAutoDisconnectTime NewAutoDisconnectTime out AutoDisconnectTime GetIdleDisconnectTime NewIdleDisconnectTime out IdleDisconnectTime RequestConnection RequestTermination ForceTermination GetStatusInfo NewConnectionStatus out ConnectionStatus NewLastConnectionError out LastConnectionError NewUptime out Uptime GetNATRSIPStatus NewRSIPAvailable out RSIPAvailable NewNATEnabled out NATEnabled GetGenericPortMappingEntry NewPortMappingIndex in PortMappingNumberOfEntries NewRemoteHost out RemoteHost NewExternalPort out ExternalPort NewProtocol out PortMappingProtocol NewInternalPort out InternalPort NewInternalClient out InternalClient NewEnabled out PortMappingEnabled NewPortMappingDescription out PortMappingDescription NewLeaseDuration out PortMappingLeaseDuration GetSpecificPortMappingEntry NewRemoteHost in RemoteHost NewExternalPort in ExternalPort NewProtocol in PortMappingProtocol NewInternalPort out InternalPort NewInternalClient out InternalClient NewEnabled out PortMappingEnabled NewPortMappingDescription out PortMappingDescription NewLeaseDuration out PortMappingLeaseDuration AddPortMapping NewRemoteHost in RemoteHost NewExternalPort in ExternalPort NewProtocol in PortMappingProtocol NewInternalPort in InternalPort NewInternalClient in InternalClient NewEnabled in PortMappingEnabled NewPortMappingDescription in PortMappingDescription NewLeaseDuration in PortMappingLeaseDuration DeletePortMapping NewRemoteHost in RemoteHost NewExternalPort in ExternalPort NewProtocol in PortMappingProtocol GetExternalIPAddress NewExternalIPAddress out ExternalIPAddress X_AVM_DE_GetExternalIPv6Address NewExternalIPv6Address out ExternalIPv6Address NewPrefixLength out PrefixLength NewValidLifetime out ValidLifetime NewPreferedLifetime out PreferedLifetime X_AVM_DE_GetIPv6Prefix NewIPv6Prefix out IPv6Prefix NewPrefixLength out PrefixLength NewValidLifetime out ValidLifetime NewPreferedLifetime out PreferedLifetime X_AVM_DE_GetDNSServer NewIPv4DNSServer1 out IPv4DNSServer1 NewIPv4DNSServer2 out IPv4DNSServer2 X_AVM_DE_GetIPv6DNSServer NewIPv6DNSServer1 out IPv6DNSServer1 NewValidLifetime1 out ValidLifetime1 NewIPv6DNSServer2 out IPv6DNSServer2 NewValidLifetime out ValidLifetime2 ConnectionType string Unconfigured PossibleConnectionTypes string Unconfigured IP_Routed IP_Bridged ConnectionStatus string Unconfigured Unconfigured Connecting Authenticating Connected PendingDisconnect Disconnecting Disconnected Uptime ui4 0 0 4294967295 1 RSIPAvailable boolean 0 NATEnabled boolean 1 LastConnectionError string ERROR_NONE ERROR_NONE ERROR_ISP_TIME_OUT ERROR_COMMAND_ABORTED ERROR_NOT_ENABLED_FOR_INTERNET ERROR_BAD_PHONE_NUMBER ERROR_USER_DISCONNECT ERROR_ISP_DISCONNECT ERROR_IDLE_DISCONNECT ERROR_FORCED_DISCONNECT ERROR_SERVER_OUT_OF_RESOURCES ERROR_RESTRICTED_LOGON_HOURS ERROR_ACCOUNT_DISABLED ERROR_ACCOUNT_EXPIRED ERROR_PASSWORD_EXPIRED ERROR_AUTHENTICATION_FAILURE ERROR_NO_DIALTONE ERROR_NO_CARRIER ERROR_NO_ANSWER ERROR_LINE_BUSY ERROR_UNSUPPORTED_BITSPERSECOND ERROR_TOO_MANY_LINE_ERRORS ERROR_IP_CONFIGURATION ERROR_UNKNOWN AutoDisconnectTime ui4 0 IdleDisconnectTime ui4 0 ExternalIPAddress string ExternalIPv6Address string ValidLifetime ui4 0 PreferedLifetime ui4 0 IPv6Prefix string PrefixLength ui1 0 IPv4DNSServer1 string IPv4DNSServer2 string IPv6DNSServer1 string IPv6DNSServer2 string ValidLifetime1 ui4 0 ValidLifetime2 ui4 0 RemoteHost string ExternalPort ui2 0 InternalPort ui2 0 PortMappingProtocol string TCP UDP InternalClient string PortMappingDescription string PortMappingEnabled boolean 0 PortMappingLeaseDuration ui4 0 PortMappingNumberOfEntries ui2 0 fritzconnection-1.15.0/fritzconnection/tests/xml/igddesc.xml000066400000000000000000000065121501211554500243230ustar00rootroot00000000000000 1 0 urn:schemas-upnp-org:device:InternetGatewayDevice:1 FRITZ!Box 7590 AVM Berlin http://www.avm.de FRITZ!Box 7590 FRITZ!Box 7590 avm http://www.avm.de uuid:75802409-bccb-just-a-test-udn image/gif 118 119 8 /ligd.gif urn:schemas-any-com:service:Any:1 urn:any-com:serviceId:any1 /igdupnp/control/any /igdupnp/control/any /any.xml urn:schemas-upnp-org:device:WANDevice:1 WANDevice - FRITZ!Box 7590 AVM Berlin www.avm.de WANDevice - FRITZ!Box 7590 WANDevice - FRITZ!Box 7590 avm www.avm.de uuid:76802409-bccb-40e7-8e6b-989BCB2B93B0 AVM IGD urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1 urn:upnp-org:serviceId:WANCommonIFC1 /igdupnp/control/WANCommonIFC1 /igdupnp/control/WANCommonIFC1 /igdicfgSCPD.xml urn:schemas-upnp-org:device:WANConnectionDevice:1 WANConnectionDevice - FRITZ!Box 7590 AVM Berlin www.avm.de WANConnectionDevice - FRITZ!Box 7590 WANConnectionDevice - FRITZ!Box 7590 avm www.avm.de uuid:76802409-bccb-40e7-8e6a-989BCB2B93B0 AVM IGD urn:schemas-upnp-org:service:WANDSLLinkConfig:1 urn:upnp-org:serviceId:WANDSLLinkC1 /igdupnp/control/WANDSLLinkC1 /igdupnp/control/WANDSLLinkC1 /igddslSCPD.xml urn:schemas-upnp-org:service:WANIPConnection:1 urn:upnp-org:serviceId:WANIPConn1 /igdupnp/control/WANIPConn1 /igdupnp/control/WANIPConn1 /igdconnSCPD.xml urn:schemas-upnp-org:service:WANIPv6FirewallControl:1 urn:upnp-org:serviceId:WANIPv6Firewall1 /igd2upnp/control/WANIPv6Firewall1 /igd2upnp/control/WANIPv6Firewall1 /igd2ipv6fwcSCPD.xml http://fritz.box fritzconnection-1.15.0/fritzconnection/tests/xml/tr64desc.xml000066400000000000000000000313241501211554500243560ustar00rootroot00000000000000 1 0 226 154 7 10 67453 154.07.10 urn:dslforum-org:device:InternetGatewayDevice:1 FRITZ!Box 7590 AVM www.avm.de FRITZ!Box 7590 FRITZ!Box 7590 - avm www.avm.de uuid:739f2409-bccb-40e7-8e6c-989BCB2B93B0 image/gif 118 119 8 /ligd.gif urn:dslforum-org:service:DeviceInfo:1 urn:DeviceInfo-com:serviceId:DeviceInfo1 /upnp/control/deviceinfo /upnp/control/deviceinfo /deviceinfoSCPD.xml urn:dslforum-org:service:DeviceConfig:1 urn:DeviceConfig-com:serviceId:DeviceConfig1 /upnp/control/deviceconfig /upnp/control/deviceconfig /deviceconfigSCPD.xml urn:dslforum-org:service:Layer3Forwarding:1 urn:Layer3Forwarding-com:serviceId:Layer3Forwarding1 /upnp/control/layer3forwarding /upnp/control/layer3forwarding /layer3forwardingSCPD.xml urn:dslforum-org:service:LANConfigSecurity:1 urn:LANConfigSecurity-com:serviceId:LANConfigSecurity1 /upnp/control/lanconfigsecurity /upnp/control/lanconfigsecurity /lanconfigsecuritySCPD.xml urn:dslforum-org:service:ManagementServer:1 urn:ManagementServer-com:serviceId:ManagementServer1 /upnp/control/mgmsrv /upnp/control/mgmsrv /mgmsrvSCPD.xml urn:dslforum-org:service:Time:1 urn:Time-com:serviceId:Time1 /upnp/control/time /upnp/control/time /timeSCPD.xml urn:dslforum-org:service:UserInterface:1 urn:UserInterface-com:serviceId:UserInterface1 /upnp/control/userif /upnp/control/userif /userifSCPD.xml urn:dslforum-org:service:X_AVM-DE_Storage:1 urn:X_AVM-DE_Storage-com:serviceId:X_AVM-DE_Storage1 /upnp/control/x_storage /upnp/control/x_storage /x_storageSCPD.xml urn:dslforum-org:service:X_AVM-DE_WebDAVClient:1 urn:X_AVM-DE_WebDAV-com:serviceId:X_AVM-DE_WebDAVClient1 /upnp/control/x_webdav /upnp/control/x_webdav /x_webdavSCPD.xml urn:dslforum-org:service:X_AVM-DE_UPnP:1 urn:X_AVM-DE_UPnP-com:serviceId:X_AVM-DE_UPnP1 /upnp/control/x_upnp /upnp/control/x_upnp /x_upnpSCPD.xml urn:dslforum-org:service:X_AVM-DE_Speedtest:1 urn:X_AVM-DE_Speedtest-com:serviceId:X_AVM-DE_Speedtest1 /upnp/control/x_speedtest /upnp/control/x_speedtest /x_speedtestSCPD.xml urn:dslforum-org:service:X_AVM-DE_RemoteAccess:1 urn:X_AVM-DE_RemoteAccess-com:serviceId:X_AVM-DE_RemoteAccess1 /upnp/control/x_remote /upnp/control/x_remote /x_remoteSCPD.xml urn:dslforum-org:service:X_AVM-DE_MyFritz:1 urn:X_AVM-DE_MyFritz-com:serviceId:X_AVM-DE_MyFritz1 /upnp/control/x_myfritz /upnp/control/x_myfritz /x_myfritzSCPD.xml urn:dslforum-org:service:X_VoIP:1 urn:X_VoIP-com:serviceId:X_VoIP1 /upnp/control/x_voip /upnp/control/x_voip /x_voipSCPD.xml urn:dslforum-org:service:X_AVM-DE_OnTel:1 urn:X_AVM-DE_OnTel-com:serviceId:X_AVM-DE_OnTel1 /upnp/control/x_contact /upnp/control/x_contact /x_contactSCPD.xml urn:dslforum-org:service:X_AVM-DE_Dect:1urn:X_AVM-DE_Dect-com:serviceId:X_AVM-DE_Dect1/upnp/control/x_dect/upnp/control/x_dect/x_dectSCPD.xml urn:dslforum-org:service:X_AVM-DE_TAM:1urn:X_AVM-DE_TAM-com:serviceId:X_AVM-DE_TAM1/upnp/control/x_tam/upnp/control/x_tam/x_tamSCPD.xml urn:dslforum-org:service:X_AVM-DE_AppSetup:1 urn:X_AVM-DE_AppSetup-com:serviceId:X_AVM-DE_AppSetup1 /upnp/control/x_appsetup /upnp/control/x_appsetup /x_appsetupSCPD.xml urn:dslforum-org:service:X_AVM-DE_Homeauto:1 urn:X_AVM-DE_Homeauto-com:serviceId:X_AVM-DE_Homeauto1 /upnp/control/x_homeauto /upnp/control/x_homeauto /x_homeautoSCPD.xml urn:dslforum-org:service:X_AVM-DE_Homeplug:1 urn:X_AVM-DE_Homeplug-com:serviceId:X_AVM-DE_Homeplug1 /upnp/control/x_homeplug /upnp/control/x_homeplug /x_homeplugSCPD.xml urn:dslforum-org:service:X_AVM-DE_Filelinks:1 urn:X_AVM-DE_Filelinks-com:serviceId:X_AVM-DE_Filelinks1 /upnp/control/x_filelinks /upnp/control/x_filelinks /x_filelinksSCPD.xml urn:dslforum-org:service:X_AVM-DE_Auth:1 urn:X_AVM-DE_Auth-com:serviceId:X_AVM-DE_Auth1 /upnp/control/x_auth /upnp/control/x_auth /x_authSCPD.xml urn:dslforum-org:device:LANDevice:1 LANDevice - FRITZ!Box 7590 AVM www.avm.de LANDevice - FRITZ!Box 7590 LANDevice - FRITZ!Box 7590 - avm www.avm.de uuid:75802409-bccb-40e7-8e6b-989BCB2B93B0 AVM TR-064 urn:dslforum-org:service:WLANConfiguration:1 urn:WLANConfiguration-com:serviceId:WLANConfiguration1 /upnp/control/wlanconfig1 /upnp/control/wlanconfig1 /wlanconfigSCPD.xml urn:dslforum-org:service:WLANConfiguration:2urn:WLANConfiguration-com:serviceId:WLANConfiguration2/upnp/control/wlanconfig2/upnp/control/wlanconfig2/wlanconfigSCPD.xmlurn:dslforum-org:service:WLANConfiguration:3urn:WLANConfiguration-com:serviceId:WLANConfiguration3/upnp/control/wlanconfig3/upnp/control/wlanconfig3/wlanconfigSCPD.xml urn:dslforum-org:service:Hosts:1 urn:LanDeviceHosts-com:serviceId:Hosts1 /upnp/control/hosts /upnp/control/hosts /hostsSCPD.xml urn:dslforum-org:service:LANEthernetInterfaceConfig:1 urn:LANEthernetIfCfg-com:serviceId:LANEthernetInterfaceConfig1 /upnp/control/lanethernetifcfg /upnp/control/lanethernetifcfg /ethifconfigSCPD.xml urn:dslforum-org:service:LANHostConfigManagement:1 urn:LANHCfgMgm-com:serviceId:LANHostConfigManagement1 /upnp/control/lanhostconfigmgm /upnp/control/lanhostconfigmgm /lanhostconfigmgmSCPD.xml urn:dslforum-org:device:WANDevice:1 WANDevice - FRITZ!Box 7590 AVM www.avm.de WANDevice - FRITZ!Box 7590 WANDevice - FRITZ!Box 7590 - avm www.avm.de uuid:75802409-bccb-40e7-8e6a-989BCB2B93B0 AVM TR-064 urn:dslforum-org:service:WANCommonInterfaceConfig:1 urn:WANCIfConfig-com:serviceId:WANCommonInterfaceConfig1 /upnp/control/wancommonifconfig1 /upnp/control/wancommonifconfig1 /wancommonifconfigSCPD.xml urn:dslforum-org:service:WANDSLInterfaceConfig:1 urn:WANDSLIfConfig-com:serviceId:WANDSLInterfaceConfig1 /upnp/control/wandslifconfig1 /upnp/control/wandslifconfig1 /wandslifconfigSCPD.xml urn:dslforum-org:device:WANConnectionDevice:1 WANConnectionDevice - FRITZ!Box 7590 AVM www.avm.de WANConnectionDevice - FRITZ!Box 7590 WANConnectionDevice - FRITZ!Box 7590 - avm www.avm.de uuid:75802409-bccb-40e7-8e69-989BCB2B93B0 AVM TR-064 urn:dslforum-org:service:WANDSLLinkConfig:1 urn:WANDSLLinkConfig-com:serviceId:WANDSLLinkConfig1 /upnp/control/wandsllinkconfig1 /upnp/control/wandsllinkconfig1 /wandsllinkconfigSCPD.xml urn:dslforum-org:service:WANEthernetLinkConfig:1 urn:WANEthernetLinkConfig-com:serviceId:WANEthernetLinkConfig1 /upnp/control/wanethlinkconfig1 /upnp/control/wanethlinkconfig1 /wanethlinkconfigSCPD.xml urn:dslforum-org:service:WANPPPConnection:1 urn:WANPPPConnection-com:serviceId:WANPPPConnection1 /upnp/control/wanpppconn1 /upnp/control/wanpppconn1 /wanpppconnSCPD.xml urn:dslforum-org:service:WANIPConnection:1 urn:WANIPConnection-com:serviceId:WANIPConnection1 /upnp/control/wanipconnection1 /upnp/control/wanipconnection1 /wanipconnSCPD.xml http://fritz.box fritzconnection-1.15.0/noxfile.py000066400000000000000000000040451501211554500170340ustar00rootroot00000000000000import nox PYTHON_TEST_VERSIONS = ("3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14") PYTHON_DEVELOPMENT_VERSION = "3.11" @nox.session(python=PYTHON_TEST_VERSIONS) def test(session): session.install("-e", ".") session.install("requests", "pytest") session.run("pytest", "-m", "not routertest") @nox.session(python=PYTHON_TEST_VERSIONS) def test_router(session): session.install("-e", ".") session.install("requests", "pytest") session.run("pytest", "-m", "routertest") @nox.session(python=PYTHON_TEST_VERSIONS) def test_all(session): session.install("-e", ".") session.install("requests", "pytest") session.run("pytest") @nox.session(name="check") def ruff_check(session): session.run("ruff", "check", "fritzconnection", external=True) @nox.session def mypy(session): session.install("-e", ".") session.install("mypy==1.11.1", "types-requests", "segno") session.run("mypy", "fritzconnection/core/fritzconnection.py") session.run("mypy", "fritzconnection/core/fritzmonitor.py") session.run("mypy", "fritzconnection/lib") @nox.session def sphinx(session): session.install("-e", ".") session.install("pip-tools==7.3.0") session.run( "pip-compile", "--strip-extras", "-q", "--output-file=docs/requirements.out", "docs/requirements.txt" #"docs/requirements.local.in" ) session.install("-r", "docs/requirements.out") session.run("sphinx-build", "docs", "docs_out") @nox.session(python=PYTHON_DEVELOPMENT_VERSION) def build(session): session.install("-e", ".") session.run("python", "setup.py", "sdist", "bdist_wheel") @nox.session(name="check-twine", python=PYTHON_DEVELOPMENT_VERSION) def check_twine(session): session.install("-e", ".") session.install("twine") session.run("twine", "check", "dist/*") @nox.session(name="upload-to-pypi", python=PYTHON_DEVELOPMENT_VERSION) def upload_to_pypi(session): session.install("-e", ".") session.install("twine") session.run("twine", "upload", "dist/*") fritzconnection-1.15.0/pytest.ini000066400000000000000000000001561501211554500170460ustar00rootroot00000000000000[pytest] addopts = -l --strict -p no:warnings norecursedirs = lib include .tox local python_files = test_*.py fritzconnection-1.15.0/setup.py000066400000000000000000000047061501211554500165340ustar00rootroot00000000000000import os import re from setuptools import setup, find_packages def get_long_description(): with open("README.md") as file: return file.read() def get_version(): path = os.path.join("fritzconnection", "__init__.py") with open(path) as file: content = file.read() mo = re.search(r'\n\s*__version__\s*=\s*[\'"]([^\'"]*)[\'"]', content) if mo: return mo.group(1) raise RuntimeError(f"Unable to find version string in {path}") setup( name="fritzconnection", version=get_version(), packages=find_packages(exclude=["*.tests"]), license="MIT", description="Communicate with the AVM FRITZ!Box", long_description_content_type="text/markdown", long_description=get_long_description(), author="Klaus Bremer", author_email="bremer@bremer-media.com", url="https://github.com/kbr/fritzconnection", classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries :: Python Modules", ], keywords="AVM FRITZ!Box fritzbox fritz TR-064 AHA-HTTP homeautomation", python_requires=">= 3.7", install_requires=["requests>=2.22.0",], extras_require={ "qr": ["segno>=1.4.1",], }, entry_points={ "console_scripts": [ "fritzconnection = fritzconnection.cli.fritzinspection:main", "fritzcall = fritzconnection.cli.fritzcall:main", "fritzhomeauto = fritzconnection.cli.fritzhomeauto:main", "fritzhosts = fritzconnection.cli.fritzhosts:main", "fritzmonitor = fritzconnection.cli.fritzmonitor:main", "fritzphonebook = fritzconnection.cli.fritzphonebook:main", "fritzstatus = fritzconnection.cli.fritzstatus:main", "fritzwlan = fritzconnection.cli.fritzwlan:main", ] }, )