Browse Source

initial

main
Alexander Couzens 1 week ago
commit
ef4901c1fd
  1. 2
      .gitignore
  2. 18
      Pipfile
  3. 224
      Pipfile.lock
  4. 61
      README.md
  5. 161
      app.py
  6. 0
      cache/.empty
  7. 67
      config/femtocells.ini
  8. 2
      config/flask.py
  9. 0
      data/.empty
  10. 1719
      example_xml/1_nano_1_inform.xml
  11. 11
      example_xml/1_nano_1_inform_response.xml
  12. 141
      example_xml/2_acs_request.xml
  13. 11
      example_xml/2_acs_response.xml
  14. 12
      templates/inform.jinja.xml
  15. 19
      templates/setparams.jinja.xml
  16. 77
      xmlutils.py

2
.gitignore

@ -0,0 +1,2 @@
cache/
data/

18
Pipfile

@ -0,0 +1,18 @@
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
eventlet = "==0.30.0"
flask-kvsession = "*"
flask-caching = "*"
[dev-packages]
[requires]
python_version = "3.9"
[packages.gunicorn]
extras = [ "eventlet",]

224
Pipfile.lock

@ -0,0 +1,224 @@
{
"_meta": {
"hash": {
"sha256": "5ce87c57866033b7e0c426501f92344a953847e9b0835420d884b4d9485cd04d"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.9"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
},
"default": {
"click": {
"hashes": [
"sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3",
"sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"
],
"version": "==8.0.3"
},
"dnspython": {
"hashes": [
"sha256:36c5e8e38d4369a08b6780b7f27d790a292b2b08eea01607865bf0936c558e01",
"sha256:f69c21288a962f4da86e56c4905b49d11aba7938d3d740e80d9e366ee4f1632d"
],
"version": "==1.16.0"
},
"eventlet": {
"hashes": [
"sha256:19d6f3aa9525221ba60d0ec31b570508021af7ad5497fb77f77501fe9a7c34d3",
"sha256:b33f31ae8d87eb2838dcb8467449211852374ee6dea97113c158fc84d9acff9b"
],
"index": "pypi",
"version": "==0.30.0"
},
"flask": {
"hashes": [
"sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2",
"sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"
],
"index": "pypi",
"version": "==2.0.2"
},
"flask-caching": {
"hashes": [
"sha256:bcda8acbc7508e31e50f63e9b1ab83185b446f6b6318bd9dd1d45626fba2e903",
"sha256:cf19b722fcebc2ba03e4ae7c55b532ed53f0cbf683ce36fafe5e881789a01c00"
],
"index": "pypi",
"version": "==1.10.1"
},
"flask-kvsession": {
"hashes": [
"sha256:9c0ee93fae089c45baeda0a3fd3ae32a96ee81c34996017749f8b3fd06df936c"
],
"index": "pypi",
"version": "==0.6.2"
},
"greenlet": {
"hashes": [
"sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711",
"sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd",
"sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073",
"sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708",
"sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67",
"sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23",
"sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1",
"sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08",
"sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd",
"sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa",
"sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8",
"sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40",
"sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab",
"sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6",
"sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc",
"sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b",
"sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e",
"sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963",
"sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3",
"sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d",
"sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d",
"sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28",
"sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3",
"sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e",
"sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c",
"sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d",
"sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0",
"sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497",
"sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee",
"sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713",
"sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58",
"sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a",
"sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06",
"sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88",
"sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4",
"sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5",
"sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c",
"sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a",
"sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1",
"sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43",
"sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627",
"sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b",
"sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168",
"sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d",
"sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5",
"sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478",
"sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf",
"sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce",
"sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c",
"sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b"
],
"version": "==1.1.2"
},
"gunicorn": {
"hashes": [
"sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
"sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
],
"index": "pypi",
"version": "==20.1.0"
},
"itsdangerous": {
"hashes": [
"sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c",
"sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"
],
"version": "==2.0.1"
},
"jinja2": {
"hashes": [
"sha256:827a0e32839ab1600d4eb1c4c33ec5a8edfbc5cb42dafa13b81f182f97784b45",
"sha256:8569982d3f0889eed11dd620c706d39b60c36d6d25843961f33f77fb6bc6b20c"
],
"version": "==3.0.2"
},
"markupsafe": {
"hashes": [
"sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298",
"sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64",
"sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b",
"sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567",
"sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff",
"sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724",
"sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74",
"sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646",
"sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35",
"sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6",
"sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6",
"sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad",
"sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26",
"sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38",
"sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac",
"sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7",
"sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6",
"sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75",
"sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f",
"sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135",
"sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8",
"sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a",
"sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a",
"sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9",
"sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864",
"sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914",
"sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18",
"sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8",
"sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2",
"sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d",
"sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b",
"sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b",
"sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f",
"sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb",
"sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833",
"sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28",
"sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415",
"sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902",
"sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d",
"sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9",
"sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d",
"sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145",
"sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066",
"sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c",
"sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1",
"sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f",
"sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53",
"sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134",
"sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85",
"sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5",
"sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94",
"sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509",
"sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51",
"sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"
],
"version": "==2.0.1"
},
"simplekv": {
"hashes": [
"sha256:8953a36cb3741ea821c9de1962b5313bf6fe1b927f6ced2a55266eb8ce2cd0f6",
"sha256:af91a50af41a286a8b7b93292b21dd1af37f38e9513fea0eb4fa75ce778c1683",
"sha256:fcee8d972d092de0dc83732084e389c9b95839503537ef85c1a2eeb07182f2f5"
],
"version": "==0.14.1"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"version": "==1.16.0"
},
"werkzeug": {
"hashes": [
"sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f",
"sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"
],
"version": "==2.0.2"
}
},
"develop": {}
}

61
README.md

@ -0,0 +1,61 @@
# femto-acs for femtocells
This is a *hack* to get ip.access nano3g femtocells configured without using a huge tr069/ACS server like (geniacs, ...).
This simplified version only reacts on *Inform* and tries to set values from the configuration file without checking the state of the femto cell.
It further does not create or delete objects if they don't exist. Neither does it check if the values in the ini file are valid. E.g. by getting both values and type from the device itself.
## Installation
### debian
Ensure python3 with pipenv is installed
`apt-get install python3 pipenv`
```sh
pipenv install
```
## Configuration
### config/flask.cfg
Please change the `SECRET_KEY` by generating your own. The `SECRET_KEY` is used to sign cookies.
### config/femtocells.ini
The main configuration file for the femtocells. The *Common* section is used as default values which can be overriden by a specific
femtocell configuration.
To override values for a specific femtocell create a section with the serialnumber including leading zeros as shown for femtocell *0000123456*.
**IMPORTANT** ensure the **Device.ManagementServer.URL=http://10.0.11.184:7547/acs|xsd:string** matches this server including the /acs.
After changing values in the femtocells.ini the femto cell can be either rebooted or wait until the femto cell is informing us again (see periodic inform / tr069).
## Running
From within the repository call:
```
pipenv install
pipenv shell
gunicorn -k eventlet --keep-alive 600 --bind 0.0.0.0:7547 app:app
```
gunicorn is used to allow keep-alive connections.
## Troubleshooting
### femto cell stops reacting on ACS data
Ensure the xml files contain an extra newline (ascii 0xa) on the end of the request.
## Bugs / Limitations
* It doesn't use any external database (mysql) or cache system (redis) to reduce the amount of external dependencies and simplify the setup.
## Thanks
Thanks to:
* [Thomas Steen 'tykling' Rasmussen](https://github.com/tykling/)
* [pentonet for their genieacs setup](https://github.com/Pentonet/pentonet-genieacs-package)

161
app.py

@ -0,0 +1,161 @@
#!/usr/bin/env python3
# Author: Alexander Couzens <lynxis@fe80.eu>
# (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
import configparser
import logging
from xml.etree.ElementTree import fromstring
from flask import Flask, make_response, render_template, request, session
from flask_caching import Cache
from flask_kvsession import KVSessionExtension
from simplekv.fs import FilesystemStore
from xmlutils import *
LOG = logging.getLogger("acs_emu")
STORE = FilesystemStore('./data')
app = Flask("acs_emu")
KVSessionExtension(STORE, app)
app.config.from_pyfile('./config/flask.py')
cache = Cache()
cache.init_app(app=app, config={"CACHE_TYPE": 'FileSystemCache', "CACHE_DIR": "./cache"})
cache.clear()
def send_configuration(serial, push):
""" write to the 'database' if this serial needs a configuration """
cache.set(serial, push)
def need_configuration(serial):
""" does this device needs a new configuration? """
need = cache.get(serial)
if need is None:
cache.set(serial, True)
return True
return need
def generate_config(params=None, serial=None, config_file='./config/femtocells.ini'):
""" return a params dict for setparams from the config file """
if params is None:
params = {}
config = configparser.ConfigParser()
config.optionxform=str
config.read(config_file)
def read_config_to_params(section):
for key in config[section]:
try:
val, xmltype = config[section][key].split('|')
params[key] = {'value': val, 'xmltype': xmltype}
except:
LOG.error("Failed to parse %s key %s with value %s", section, key, config[section][key])
read_config_to_params('Common')
if serial and serial in config:
read_config_to_params(serial)
return params
@app.route('/', methods=['GET', 'POST'])
def root():
return 'This is a femto-acs/tr069 server'
def inform(tree, node):
""" handle a device Inform request """
cwmpid = get_cwmp_id(tree)
serial = get_cwmp_inform_serial(node)
events = get_cwmp_inform_events(node)
session['serial'] = serial
if '0 BOOTSTRAP' in events or '1 BOOT' in events:
send_configuration(serial, True)
LOG.error("Device %s booted", serial)
LOG.error("Device %s informed us. cwmpipd %s. Events %s", serial, cwmpid, ", ".join(events))
response = make_response(render_template('inform.jinja.xml', cwmpid=cwmpid))
response.headers['Content-Type'] = 'text/xml; charset="utf-8"'
response.headers['SOAPServer'] = 'femto-acs/1.1.1'
response.headers['Server'] = 'femto-acs/1.1.1'
return response
def send_setparams():
""" request a setparams """
# e.g. params are {name: "arfcn", xmltype: "xsd:int", value: "23"}
serial = session['serial']
params = {}
params = generate_config(params, serial)
# keep track if we already sent out a response
LOG.error("Device %s sending configuration", serial)
send_configuration(serial, True)
response = make_response(render_template('setparams.jinja.xml',
cwmpid=23, params=params, length_params=len(params)))
response.headers['Content-Type'] = 'text/xml'
return response
def setparams_response(tree, node):
""" handle the setparams response """
serial = session['serial']
status = get_cwmp_setresponse_status(node)
if status is not None:
if status == '0':
LOG.error("Device %s applied configuration changes without reboot", serial)
elif status == '1':
LOG.error("Device %s applied configuration changes but require a reboot", serial)
else:
LOG.error("Device %s returned unknown status value (%s)", serial)
send_configuration(serial, False)
response = make_response()
response.headers['Content-Type'] = 'text/xml'
return response
@app.route('/acs', methods=['GET', 'POST'])
def acs():
""" main tr069/acs entry point """
if request.method == 'GET':
return 'This is a femoto-acs/tr069 server'
if request.method != 'POST':
return 'There is nothing to show'
# POST requests
if request.content_type != 'text/xml':
return 'Wrong content type'
# when the client doesn't send us any data, it's ready for our request
if not request.content_length:
if 'serial' not in session:
LOG.error("Received an empty request from an unknown device. Can not generate configuration!")
return make_response()
if need_configuration(session['serial']):
return send_setparams()
LOG.error("Device %s already configured", session['serial'])
return make_response()
# some request content data
try:
tree = fromstring(request.data)
except:
return 'Could not parse the request as XML'
method = get_cwmp_method(tree)
if not method:
return 'Failed to get the cwmp method'
method, node = method
if method == "Inform":
return inform(tree, node)
if method == "SetParameterValuesResponse":
return setparams_response(tree, node)
return 'This is a femto-acs/tr069 server'
if __name__ == '__main__':
app.run()

0
cache/.empty

67
config/femtocells.ini

@ -0,0 +1,67 @@
[0000123456]
Device.Services.FAPService.e.AccessMgmt.UMTS.HNBName=000295-0000123456@ipaccess.com|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.CN.PLMNID=00101|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.CN.LACRAC=64000:210|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.CN.SAC=210|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.CN.SAI_LAC=64000|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellID=210|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RNCID=210|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RF.MaxFAPTxPowerExpanded=50|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RF.MaxULTxPower=24|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RF.PrimaryScramblingCode=13|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RF.UARFCNDL=1007|xsd:string
Device.Services.FAPService.1.FAPControl.UMTS.AdminState=true|xsd:boolean
Device.Services.FAPService.1.FAPControl.UMTS.Gateway.FAPGWServer1=10.70.0.2|xsd:string
Device.Services.FAPService.1.REM.X_000295_RFParamsCandidateList=1007-13|xsd:string
[Common]
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RNCID=0|xsd:unsignedInt
Device.ManagementServer.URL=http://10.0.11.184:7547/acs|xsd:string
Device.Services.FAPService.1.FAPControl.UMTS.Gateway.FAPGWServer1=10.70.0.2|xsd:string
Device.Time.NTPServer1=0.ipaccess.pool.ntp.org|xsd:string
Device.Time.NTPServer2=1.ipaccess.pool.ntp.org|xsd:string
Device.Time.NTPServer3=2.ipaccess.pool.ntp.org|xsd:string
Device.Time.NTPServer4=3.ipaccess.pool.ntp.org|xsd:string
Device.IPsec.Enable=false|xsd:boolean
Device.ManagementServer.PeriodicInformEnable=true|xsd:boolean
Device.ManagementServer.PeriodicInformInterval=60|xsd:unsignedInt
Device.Services.FAPService.1.AccessMgmt.UMTS.AccessMode=Open Access|xsd:string
Device.Services.FAPService.1.AccessMgmt.UMTS.NonCSGUEAccessDecision=Local|xsd:string
Device.Services.FAPService.1.AccessMgmt.UMTS.X_000295_AccessDecisionMode=Legacy Mode|xsd:string
Device.Services.FAPService.1.AccessMgmt.UMTS.X_000295_DefaultUERejectCause=Roaming not allowed in this location area|xsd:string
Device.Services.FAPService.1.AccessMgmt.UMTS.X_000295_DefaultUERejectMethod=AUTO|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.CN.CSDomain.IMSIAttachDetachEnable=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.CN.PSDomain.NetworkModeOperationCombined=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.CN.X_000295_IuUpInitNoDataSupported=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellRestriction.CellBarred=false|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellRestriction.CellReservedForOperatorUse=false|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellRestriction.IntraFreqCellReselectionIndicator=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.RF.PCPICHPower=10.0|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_CellBroadcastDefaultMessage=|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_CellBroadcastEnable=false|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_CellBroadcastMode=CB_MODE_DEFAULT_MESSAGE|xsd:string
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_HandoverEnabled=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_IntraFrequencyHandoutEnabled=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_PSHandoverEnabled=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_PSInactivityTimeout=30|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_DataOnFACHEnable=true|xsd:boolean
Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_FdEnabled=false|xsd:boolean
Device.Services.FAPService.1.REM.UMTS.WCDMA.ScanOnBoot=false|xsd:boolean
Device.Services.FAPService.1.REM.UMTS.WCDMA.ScanPeriodically=false|xsd:boolean
Device.Services.FAPService.1.REM.UMTS.WCDMA.ScanTimeout=0|xsd:unsignedInt
Device.Services.FAPService.1.REM.X_000295_CellParameterSelectionMethod=CONFIGURED|xsd:string
Device.Services.FAPService.1.REM.X_000295_NeighbourListPopulation=0|xsd:unsignedInt
Device.Services.FAPService.1.REM.X_000295_ScanBands=|xsd:string
Device.Time.LocalTimeZone=GMT|xsd:string
Device.Time.X_000295_NTPFrequencyDisciplineEnabled=false|xsd:boolean
Device.Services.FAPService.1.REM.X_000295_ExternalPaGain=0|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.HCSPrio=0|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.QHCS=0|xsd:unsignedInt
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.SHCSRAT=-105|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.SIntersearch=8|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.SIntrasearch=10|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.SLimitSearchRAT=0|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.SSearchHCS=-100|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.SSearchRAT=8|xsd:int
Device.Services.FAPService.1.CellConfig.UMTS.RAN.CellSelection.UseOfHCS=false|xsd:boolean

2
config/flask.py

@ -0,0 +1,2 @@
# flask configuration file
SECRET_KEY=b'j;\x9fq&\xfe\x04\xe1\xc3\xb5F\xc9\xa6~a\xdd'

0
data/.empty

1719
example_xml/1_nano_1_inform.xml
File diff suppressed because it is too large
View File

11
example_xml/1_nano_1_inform_response.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
<soap-env:Header>
<cwmp:ID soap-env:mustUnderstand="1">2</cwmp:ID>
</soap-env:Header>
<soap-env:Body>
<cwmp:InformResponse>
<MaxEnvelopes>1</MaxEnvelopes>
</cwmp:InformResponse>
</soap-env:Body>
</soap-env:Envelope>

141
example_xml/2_acs_request.xml

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
<soap-env:Header>
<cwmp:ID soap-env:mustUnderstand="1">17c0fe79e0c0113</cwmp:ID>
</soap-env:Header>
<soap-env:Body>
<cwmp:SetParameterValues>
<ParameterList soap-enc:arrayType="cwmp:ParameterValueStruct[32]">
<ParameterValueStruct>
<Name>Device.ManagementServer.URL</Name>
<Value xsi:type="xsd:string">http://10.0.11.184:7547/acs</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.ManagementServer.PeriodicInformEnable</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.ManagementServer.PeriodicInformInterval</Name>
<Value xsi:type="xsd:unsignedInt">60</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.AccessMgmt.UMTS.NonCSGUEAccessDecision</Name>
<Value xsi:type="xsd:string">Local</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.FAPControl.UMTS.Gateway.FAPGWServer1</Name>
<Value xsi:type="xsd:string">10.70.0.2</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.REM.UMTS.WCDMA.ScanPeriodically</Name>
<Value xsi:type="xsd:boolean">false</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.REM.UMTS.WCDMA.ScanOnBoot</Name>
<Value xsi:type="xsd:boolean">false</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.REM.X_000295_ExternalPaGain</Name>
<Value xsi:type="xsd:int">0</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.CN.X_000295_IuUpInitNoDataSupported</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.CN.PSDomain.NetworkModeOperationCombined</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.CN.CSDomain.IMSIAttachDetachEnable</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_CellBroadcastEnable</Name>
<Value xsi:type="xsd:boolean">false</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_HandoverEnabled</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_IntraFrequencyHandoutEnabled</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_PSHandoverEnabled</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_DataOnFACHEnable</Name>
<Value xsi:type="xsd:boolean">true</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.X_000295_FdEnabled</Name>
<Value xsi:type="xsd:boolean">false</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.X_000295_TxDiversityIndicator</Name>
<Value xsi:type="xsd:unsignedInt">1</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.PLMNID</Name>
<Value xsi:type="xsd:string">00101</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.CID</Name>
<Value xsi:type="xsd:unsignedInt">210</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.UARFCNDL</Name>
<Value xsi:type="xsd:unsignedInt">1007</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.LAC</Name>
<Value xsi:type="xsd:unsignedInt">64000</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.RAC</Name>
<Value xsi:type="xsd:unsignedInt">210</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.RNCID</Name>
<Value xsi:type="xsd:unsignedInt">210</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.1.PCPICHScramblingCode</Name>
<Value xsi:type="xsd:unsignedInt">123</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.PLMNID</Name>
<Value xsi:type="xsd:string">25001</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.X_000295_TxDiversityIndicator</Name>
<Value xsi:type="xsd:unsignedInt">1</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.PCPICHScramblingCode</Name>
<Value xsi:type="xsd:unsignedInt">123</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.RAC</Name>
<Value xsi:type="xsd:unsignedInt">210</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.LAC</Name>
<Value xsi:type="xsd:unsignedInt">64000</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.UARFCNDL</Name>
<Value xsi:type="xsd:unsignedInt">10753</Value>
</ParameterValueStruct>
<ParameterValueStruct>
<Name>Device.Services.FAPService.1.CellConfig.UMTS.RAN.NeighborList.InterFreqCell.2.CID</Name>
<Value xsi:type="xsd:unsignedInt">10</Value>
</ParameterValueStruct>
</ParameterList>
<ParameterKey/>
</cwmp:SetParameterValues>
</soap-env:Body>
</soap-env:Envelope>

11
example_xml/2_acs_response.xml

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
<soap-env:Header>
<cwmp:ID soap-env:mustUnderstand="1">17c0fe79e0c0113</cwmp:ID>
</soap-env:Header>
<soap-env:Body>
<cwmp:SetParameterValuesResponse>
<Status>0</Status>
</cwmp:SetParameterValuesResponse>
</soap-env:Body>
</soap-env:Envelope>

12
templates/inform.jinja.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
<soap-env:Header>
<cwmp:ID soap-env:mustUnderstand="1">{{ cwmpid }}</cwmp:ID>
</soap-env:Header>
<soap-env:Body>
<cwmp:InformResponse>
<MaxEnvelopes>1</MaxEnvelopes>
</cwmp:InformResponse>
</soap-env:Body>
</soap-env:Envelope>

19
templates/setparams.jinja.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
<soap-env:Header>
<cwmp:ID soap-env:mustUnderstand="1">{{ cwmpip }}</cwmp:ID>
</soap-env:Header>
<soap-env:Body>
<cwmp:SetParameterValues>
<ParameterList soap-enc:arrayType="cwmp:ParameterValueStruct[{{ length_params }}]">
{% for obj in params %}
<ParameterValueStruct><Name>{{ obj }}</Name>
<Value xsi:type="{{ params[obj]['xmltype'] }}">{{ params[obj]['value'] }}</Value>
</ParameterValueStruct>
{% endfor %}
</ParameterList>
<ParameterKey/>
</cwmp:SetParameterValues>
</soap-env:Body>
</soap-env:Envelope>

77
xmlutils.py

@ -0,0 +1,77 @@
#!/usr/bin/env python3
# Author: Alexander Couzens <lynxis@fe80.eu>
# (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
XML_NS = {
'soap-env': 'http://schemas.xmlsoap.org/soap/envelope/',
'cwmp': 'urn:dslforum-org:cwmp-1-0'
}
def get_cwmp_method(root):
""" retrieve the cwmp method from the xml root Node """
body = root.find('soap-env:Body', XML_NS)
if body is None:
return None
for child in body:
if child.tag == '{urn:dslforum-org:cwmp-1-0}Inform':
return ('Inform', child)
if child.tag == '{urn:dslforum-org:cwmp-1-0}SetParameterValuesResponse':
return ('SetParameterValuesResponse', child)
return None
def get_cwmp_id(root):
""" retrieve the cwmp id """
header = root.find('soap-env:Header', XML_NS)
if header is None:
return None
cwmpid = header.find('{urn:dslforum-org:cwmp-1-0}ID', XML_NS)
if cwmpid is not None:
return cwmpid.text
return None
def get_cwmp_inform_events(inform):
""" return a list of Inform Events """
eventnode = inform.find('Event')
if eventnode is None:
return None
events = []
""" parse
<Event soap-enc:arrayType="cwmp:EventStruct[2]"
<EventStruct>
<EventCode>4 VALUE CHANGE</EventCode>
<CommandKey></CommandKey>
</EventStruct>
<EventStruct>
<EventCode>0 BOOTSTRAP</EventCode>
<CommandKey></CommandKey>
</EventStruct>
</Event>
"""
for ev in eventnode:
if ev.tag != "EventStruct":
continue
evcodenode = ev.find('EventCode')
events.append(evcodenode.text)
return events
def get_cwmp_inform_serial(inform):
""" retrieve the serial from an inform node """
device_id = inform.find('DeviceId')
if device_id is None:
return None
serial = device_id.find('SerialNumber')
if serial is None:
return None
return serial.text
def get_cwmp_setresponse_status(setparametervaluesresponse):
""" retrieve the status from a setparametervaluesresponse node """
statusnode = setparametervaluesresponse.find('Status')
if statusnode is None:
return None
return statusnode.text
Loading…
Cancel
Save