From 2276345748dfeb97946a542be09c441b89ccb392 Mon Sep 17 00:00:00 2001 From: Amin Ben Romdhane Date: Tue, 28 Mar 2023 17:02:14 +0200 Subject: [PATCH] Delete unused repos/files --- .gitlab-ci.yml | 2 +- README.md | 1 - bbfd/LICENSE | 308 - bbfd/Makefile | 65 +- bbfd/README.md | 100 - bbfd/{src => }/add_delete.c | 0 bbfd/{src => }/add_delete.h | 0 bbfd/{src => }/common.c | 0 bbfd/{src => }/common.h | 0 bbfd/docs/.pages | 7 - bbfd/docs/api/.pages | 6 - bbfd/docs/api/ubus/.pages | 4 - bbfd/docs/api/ubus/usp.md | 3162 ---------- bbfd/docs/api/ubus/usp.raw.md | 4694 --------------- bbfd/docs/api/uci/.pages | 4 - bbfd/docs/api/uci/uspd.md | 216 - bbfd/docs/css/assets/fonts/Madera-Bold.eot | Bin 97980 -> 0 bytes bbfd/docs/css/assets/fonts/Madera-Bold.svg | 5301 ----------------- bbfd/docs/css/assets/fonts/Madera-Bold.ttf | Bin 101180 -> 0 bytes bbfd/docs/css/assets/fonts/Madera-Bold.woff | Bin 49636 -> 0 bytes bbfd/docs/css/assets/fonts/Madera-Bold.woff2 | Bin 30852 -> 0 bytes bbfd/docs/css/assets/fonts/Madera-Regular.eot | Bin 85883 -> 0 bytes bbfd/docs/css/assets/fonts/Madera-Regular.svg | 5284 ---------------- bbfd/docs/css/assets/fonts/Madera-Regular.ttf | Bin 101784 -> 0 bytes .../docs/css/assets/fonts/Madera-Regular.woff | Bin 49024 -> 0 bytes .../css/assets/fonts/Madera-Regular.woff2 | Bin 31156 -> 0 bytes bbfd/docs/css/colors.css | 124 - bbfd/docs/css/extra.css | 2601 -------- bbfd/docs/css/iopsys-white.svg | 28 - bbfd/docs/css/pdf.css | 17 - bbfd/docs/guide/.pages | 4 - bbfd/docs/guide/data_model_integration.md | 326 - bbfd/docs/guide/ubus_errors.md | 115 - bbfd/docs/guide/ubus_example.md | 205 - bbfd/docs/guide/ubus_methods.md | 874 --- bbfd/docs/guide/ubus_parallel_call.md | 20 - bbfd/docs/mkdocs.yml | 90 - bbfd/docs/preview.sh | 10 - bbfd/docs/requirements.txt | 7 - bbfd/docs/spec/.pages | 4 - bbfd/docs/spec/functionspec.md | 336 -- bbfd/docs/spec/testspec.md | 464 -- bbfd/{src => }/events.c | 0 bbfd/{src => }/events.h | 0 bbfd/{src => }/get.c | 0 bbfd/{src => }/get.h | 0 bbfd/{src => }/get_helper.c | 0 bbfd/{src => }/get_helper.h | 0 bbfd/gitlab-ci/functional-api-test.sh | 63 - bbfd/gitlab-ci/functional-test.sh | 111 - bbfd/gitlab-ci/install-dependencies.sh | 56 - bbfd/gitlab-ci/iopsys-supervisord.conf | 15 - bbfd/gitlab-ci/setup.sh | 14 - bbfd/gitlab-ci/shared.sh | 44 - bbfd/gitlab-ci/unit-test.sh | 22 - bbfd/{src => }/ipc.h | 0 bbfd/openwrt/uspd/Makefile | 43 - bbfd/openwrt/uspd/files/uspd.config | 2 - bbfd/openwrt/uspd/files/uspd.init | 25 - bbfd/openwrt/uspd/git-src | 1 - bbfd/{src => }/operate.c | 0 bbfd/{src => }/operate.h | 0 bbfd/{src => }/pretty_print.c | 0 bbfd/{src => }/pretty_print.h | 0 bbfd/schemas/ubus/usp.json | 791 --- bbfd/schemas/ubus/usp.raw.json | 1420 ----- bbfd/schemas/uci/uspd.json | 74 - bbfd/{src => }/set.c | 0 bbfd/{src => }/set.h | 0 bbfd/src/Makefile | 58 - bbfd/test/Makefile | 16 - bbfd/test/Readme.md | 39 - bbfd/test/api/json/usp.raw.validation.json | 157 - bbfd/test/api/json/usp.validation.json | 117 - bbfd/test/cmocka/Makefile | 23 - bbfd/test/cmocka/test_utils.h | 9 - bbfd/test/cmocka/unit_test_uspd.c | 980 --- .../etc/bbfdm/json/transferComplete.json | 132 - bbfd/test/files/etc/board-db/config/device | 11 - bbfd/test/files/etc/config/firewall | 185 - bbfd/test/files/etc/config/network | 123 - bbfd/test/files/etc/config/users | 7 - bbfd/test/files/etc/config/uspd | 6 - bbfd/test/files/etc/config/wireless | 56 - bbfd/test/files/etc/init.d/uspd | 25 - bbfd/test/funl/json/gran/gran.validation.json | 13 - bbfd/test/funl/json/usp.raw.validation.json | 350 -- bbfd/test/funl/json/usp.validation.json | 463 -- .../funl/schema/usp.raw_test_negative.json | 1183 ---- .../funl/schema/usp.raw_test_positive.json | 1383 ----- bbfd/test/funl/schema/usp_test_negative.json | 338 -- bbfd/test/funl/schema/usp_test_positive.json | 315 - .../usp.raw.validation.negative.json | 64 - .../usp.raw.validation.positive.json | 368 -- .../validation/usp.validation.negative.json | 62 - .../validation/usp.validation.positive.json | 323 - bbfd/test/libuspd_test.c | 52 - bbfd/test/python/validate_3272.py | 27 - bbfd/test/python/validate_3536.py | 29 - bbfd/test/python/validate_device.py | 26 - bbfd/test/python/validate_fault_code.py | 32 - .../python/validate_invalid_transaction_id.py | 45 - .../validate_invalid_transaction_id_fault.py | 46 - bbfd/test/python/validate_schema_notify.py | 31 - bbfd/test/python/validate_serial.py | 20 - bbfd/test/python/validate_ubus_event.py | 30 - bbfd/test/python/validate_uspd.py | 49 - bbfd/{src => }/usp.c | 0 bbfd/{src => }/usp.h | 0 docs/guide/tools.md | 3 +- .../dmtree/vendor/openwrt/tr181/deviceinfo.c | 208 - .../dmtree/vendor/openwrt/tr181/deviceinfo.h | 10 - libbbf_dm/dmtree/vendor/openwrt/tr181/qos.c | 575 -- libbbf_dm/dmtree/vendor/openwrt/tr181/qos.h | 23 - .../dmtree/vendor/openwrt/tr181/vendor.c | 90 - .../dmtree/vendor/openwrt/tr181/vendor.h | 20 - libbbf_dm/dmtree/vendor/vendor.c | 12 - openwrt/bbf/Config_bbfdm.in | 35 - openwrt/bbf/Makefile | 101 - openwrt/bbf/git-src | 1 - schemas/dmtest.json | 621 -- schemas/dmtest.md | 1933 ------ 122 files changed, 51 insertions(+), 37834 deletions(-) delete mode 100644 bbfd/LICENSE delete mode 100644 bbfd/README.md rename bbfd/{src => }/add_delete.c (100%) rename bbfd/{src => }/add_delete.h (100%) rename bbfd/{src => }/common.c (100%) rename bbfd/{src => }/common.h (100%) delete mode 100644 bbfd/docs/.pages delete mode 100644 bbfd/docs/api/.pages delete mode 100644 bbfd/docs/api/ubus/.pages delete mode 100644 bbfd/docs/api/ubus/usp.md delete mode 100644 bbfd/docs/api/ubus/usp.raw.md delete mode 100644 bbfd/docs/api/uci/.pages delete mode 100644 bbfd/docs/api/uci/uspd.md delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Bold.eot delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Bold.svg delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Bold.ttf delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Bold.woff delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Bold.woff2 delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Regular.eot delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Regular.svg delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Regular.ttf delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Regular.woff delete mode 100644 bbfd/docs/css/assets/fonts/Madera-Regular.woff2 delete mode 100755 bbfd/docs/css/colors.css delete mode 100755 bbfd/docs/css/extra.css delete mode 100644 bbfd/docs/css/iopsys-white.svg delete mode 100644 bbfd/docs/css/pdf.css delete mode 100644 bbfd/docs/guide/.pages delete mode 100644 bbfd/docs/guide/data_model_integration.md delete mode 100644 bbfd/docs/guide/ubus_errors.md delete mode 100644 bbfd/docs/guide/ubus_example.md delete mode 100644 bbfd/docs/guide/ubus_methods.md delete mode 100644 bbfd/docs/guide/ubus_parallel_call.md delete mode 100755 bbfd/docs/mkdocs.yml delete mode 100755 bbfd/docs/preview.sh delete mode 100755 bbfd/docs/requirements.txt delete mode 100644 bbfd/docs/spec/.pages delete mode 100644 bbfd/docs/spec/functionspec.md delete mode 100644 bbfd/docs/spec/testspec.md rename bbfd/{src => }/events.c (100%) rename bbfd/{src => }/events.h (100%) rename bbfd/{src => }/get.c (100%) rename bbfd/{src => }/get.h (100%) rename bbfd/{src => }/get_helper.c (100%) rename bbfd/{src => }/get_helper.h (100%) delete mode 100755 bbfd/gitlab-ci/functional-api-test.sh delete mode 100755 bbfd/gitlab-ci/functional-test.sh delete mode 100755 bbfd/gitlab-ci/install-dependencies.sh delete mode 100644 bbfd/gitlab-ci/iopsys-supervisord.conf delete mode 100755 bbfd/gitlab-ci/setup.sh delete mode 100644 bbfd/gitlab-ci/shared.sh delete mode 100755 bbfd/gitlab-ci/unit-test.sh rename bbfd/{src => }/ipc.h (100%) delete mode 100644 bbfd/openwrt/uspd/Makefile delete mode 100644 bbfd/openwrt/uspd/files/uspd.config delete mode 100644 bbfd/openwrt/uspd/files/uspd.init delete mode 120000 bbfd/openwrt/uspd/git-src rename bbfd/{src => }/operate.c (100%) rename bbfd/{src => }/operate.h (100%) rename bbfd/{src => }/pretty_print.c (100%) rename bbfd/{src => }/pretty_print.h (100%) delete mode 100644 bbfd/schemas/ubus/usp.json delete mode 100644 bbfd/schemas/ubus/usp.raw.json delete mode 100644 bbfd/schemas/uci/uspd.json rename bbfd/{src => }/set.c (100%) rename bbfd/{src => }/set.h (100%) delete mode 100644 bbfd/src/Makefile delete mode 100644 bbfd/test/Makefile delete mode 100644 bbfd/test/Readme.md delete mode 100644 bbfd/test/api/json/usp.raw.validation.json delete mode 100644 bbfd/test/api/json/usp.validation.json delete mode 100644 bbfd/test/cmocka/Makefile delete mode 100644 bbfd/test/cmocka/test_utils.h delete mode 100644 bbfd/test/cmocka/unit_test_uspd.c delete mode 100644 bbfd/test/files/etc/bbfdm/json/transferComplete.json delete mode 100644 bbfd/test/files/etc/board-db/config/device delete mode 100644 bbfd/test/files/etc/config/firewall delete mode 100644 bbfd/test/files/etc/config/network delete mode 100644 bbfd/test/files/etc/config/users delete mode 100644 bbfd/test/files/etc/config/uspd delete mode 100644 bbfd/test/files/etc/config/wireless delete mode 100755 bbfd/test/files/etc/init.d/uspd delete mode 100644 bbfd/test/funl/json/gran/gran.validation.json delete mode 100644 bbfd/test/funl/json/usp.raw.validation.json delete mode 100644 bbfd/test/funl/json/usp.validation.json delete mode 100644 bbfd/test/funl/schema/usp.raw_test_negative.json delete mode 100644 bbfd/test/funl/schema/usp.raw_test_positive.json delete mode 100644 bbfd/test/funl/schema/usp_test_negative.json delete mode 100644 bbfd/test/funl/schema/usp_test_positive.json delete mode 100644 bbfd/test/funl/validation/usp.raw.validation.negative.json delete mode 100644 bbfd/test/funl/validation/usp.raw.validation.positive.json delete mode 100644 bbfd/test/funl/validation/usp.validation.negative.json delete mode 100644 bbfd/test/funl/validation/usp.validation.positive.json delete mode 100644 bbfd/test/libuspd_test.c delete mode 100755 bbfd/test/python/validate_3272.py delete mode 100755 bbfd/test/python/validate_3536.py delete mode 100755 bbfd/test/python/validate_device.py delete mode 100755 bbfd/test/python/validate_fault_code.py delete mode 100755 bbfd/test/python/validate_invalid_transaction_id.py delete mode 100755 bbfd/test/python/validate_invalid_transaction_id_fault.py delete mode 100755 bbfd/test/python/validate_schema_notify.py delete mode 100755 bbfd/test/python/validate_serial.py delete mode 100755 bbfd/test/python/validate_ubus_event.py delete mode 100755 bbfd/test/python/validate_uspd.py rename bbfd/{src => }/usp.c (100%) rename bbfd/{src => }/usp.h (100%) delete mode 100644 libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.c delete mode 100644 libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.h delete mode 100644 libbbf_dm/dmtree/vendor/openwrt/tr181/qos.c delete mode 100644 libbbf_dm/dmtree/vendor/openwrt/tr181/qos.h delete mode 100644 libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.c delete mode 100644 libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.h delete mode 100644 openwrt/bbf/Config_bbfdm.in delete mode 100644 openwrt/bbf/Makefile delete mode 120000 openwrt/bbf/git-src delete mode 100644 schemas/dmtest.json delete mode 100644 schemas/dmtest.md diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 77a75f99..028e766f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,7 +10,7 @@ variables: DEBUG: 'TRUE' SOURCE_FOLDER: "." COMMON_IMAGE: dev.iopsys.eu:5050/iopsys/gitlab-ci-pipeline/code-analysis:0.27 - RUN_CPPCHECK: "cppcheck --enable=information --error-exitcode=1 -DBBFDM_ENABLE_DOTSO_PLUGIN -DBBFDM_ENABLE_DOTSO_PLUGIN -DBBF_TR181 -DBBF_VENDOR_IOPSYS -DBBF_VENDOR_OPENWRT --inline-suppr -i test/" + RUN_CPPCHECK: "cppcheck --enable=information --error-exitcode=1 -DBBFDM_ENABLE_DOTSO_PLUGIN -DBBFDM_ENABLE_DOTSO_PLUGIN -DBBF_TR181 -DBBF_VENDOR_IOPSYS --inline-suppr -i test/" stages: - static_code_analysis diff --git a/README.md b/README.md index 2f38b745..2c00e9b6 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ This package comprises of the below libraries: │   ├── tr181 │   └── vendor │   ├── iopsys -│   ├── openwrt │   └── vendor.h ├── libbbf_api ├── scripts diff --git a/bbfd/LICENSE b/bbfd/LICENSE deleted file mode 100644 index 0d6eff4c..00000000 --- a/bbfd/LICENSE +++ /dev/null @@ -1,308 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - uspd - USP Daemon exposing USP API over uBus - Copyright (C) 2019 iopsys Software Solutions AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/bbfd/Makefile b/bbfd/Makefile index 2df283ce..f1bf9f94 100644 --- a/bbfd/Makefile +++ b/bbfd/Makefile @@ -1,25 +1,58 @@ -all: - make -C src all +PROG = uspd +OBJS =common.o get.o get_helper.o set.o operate.o add_delete.o pretty_print.o usp.o events.o +CP=cp -f -uspd: - make -C src uspd +PROG_CFLAGS = $(CFLAGS) \ + -fstrict-aliasing \ + -Wall -Wextra -Werror \ + -Wformat \ + -Wformat-signedness -fPIC -test: - make -C src test +PROG_LDFLAGS = $(LDFLAGS) +PROG_LDFLAGS += -luci -lubus -lubox -ljson-c -lblobmsg_json -lbbfdm -unit-test: - make -C test/cmocka unit-test USPD_LIB_DIR=$(PWD) +ifeq ($(USE_MBEDTLS),yes) +PROG_LDFLAGS += -lmbedcrypto -lmbedtls +endif -func-test: - make -C src func-test +ifeq ($(USE_OPENSSL),yes) +PROG_LDFLAGS += -lssl -lcrypto +endif +ifeq ($(USE_WOLFSSL),yes) +PROG_LDFLAGS += -lwolfssl +endif + +%.o: %.c + $(CC) $(PROG_CFLAGS) -c -o $@ $< + +all: ${PROG} + +${PROG}: $(OBJS) + $(CC) $(PROG_CFLAGS) -o $@ $^ $(PROG_LDFLAGS) + $(CP) ${PROG} ../${PROG} + +test: PROG_CFLAGS += -fPIC +test: ${OBJS} + ${CC} $(PROG_CFLAGS) -shared -o libuspd.so ${OBJS} $(PROG_LDFLAGS) + $(CP) libuspd.so ../libuspd.so + +unit-test: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage +unit-test: LDFLAGS += --coverage +unit-test: clean_objs +unit-test: test + make -C ../test/cmocka unit-test USPD_LIB_DIR=$(PWD) + +func-test: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage +func-test: LDFLAGS += --coverage +func-test: clean_objs +func-test: ${PROG} + +clean_objs: + rm -f *.o clean: - make -C src clean - make -C test/cmocka clean - rm -f uspd + rm -f *.o libuspd.so $(PROG) + rm -f *.xml *.html find -name '*.gcda' -exec rm {} -fv \; find -name '*.gcno' -exec rm {} -fv \; find -name '*.gcov' -exec rm {} -fv \; - find -name '*.so' -exec rm {} -fv \; - rm -f *.log *.xml - rm -rf report diff --git a/bbfd/README.md b/bbfd/README.md deleted file mode 100644 index e06fc95b..00000000 --- a/bbfd/README.md +++ /dev/null @@ -1,100 +0,0 @@ -# USP Daemon (uspd) - -`uspd` is data-model daemon which exposes data-model objects over ubus as required -by [TR-069/cwmp](https://cwmp-data-models.broadband-forum.org/) or [TR-369/USP](https://usp.technology/), -`uspd` also understand [USP syntax](https://usp.technology/specification/architecture/) as defined in R-ARC.7 - R-ARC.12 -and provide details for data-model queries. - -> Note 1: The command outputs shown in this readme are examples only, actual output may differ based on device and configuration. - -> Note 2: Long command outputs are compressed for better readability - -## Project Components - -Project consists of following components: - -- Application itself written in C programming language -- Documentation in a Markdown format - -## Build Instructions - -`uspd` is written using C programming language and depends on a number of components found in `OpenWrt` for building and running. - -## UCI Config - -`uspd` requires a configuration file to provide more granular objects over `ubus`. -Granularity is an optional feature of `uspd`, it can be skipped or set to level 0. -The configuration file is an `uci` file `/etc/config/uspd`. Sample configuration file is provided below. - -```bash -config uspd 'usp' - option granularitylevel '0' - option debug 'true' - option loglevel '2' - option sock '/tmp/usp.sock' - option transaction_timeout 60 - option subprocess_level '1' - option refresh_time '5' -``` - -In the above uci, loglevel can have below value: - -|loglevel | Meaning | -|---------| -----------------------------------------| -| 0 | Disabled logging | -| 1 | Only errors will be logged | -| 2 | Only errors and warnings will be logged | -| 3 | Log everything except debug | -| 4 | Everything will be logged | - -For more info on the `uspd` UCI configuration visit [uci documentation](./docs/api/uci/uspd.md) OR [raw uci schema](https://dev.iopsys.eu/iopsys/uspd/-/tree/module_docs/schemas/uci/uspd.json) - -## Concepts and Workflow - -`uspd` internally uses `libbbfdm` to get the data-model objects. On startup it parses the uci file to check if the granularity is set and then as per the granularity value it registers the required ubus namespaces. - -When a ubus method is called it first checks the `path` parameter to identify if it has special USP syntax, if present it parses and determine the correct objects from `libbbfdm`, then proceeds with the `Get/Set/Operate/Add/Del` operation on the qualified objects. - -So, `uspd` search for `[[+*]+` in path expression, if it matches then segments the path and get the schema from `libbbfdm` and store it in a link-list, then it proceeds with the next segment to filter out the unneeded schema paths. It keeps on doing so till all the expressions are solved and it finally left with qualified objects. -Once all the expressions are solved, it starts getting the values for qualified objects and store it in a `stack` to print the output in pretty format. - -For operate command, it solve the path expression and then call `bbf_operate` from `libbbfdm` to execute the operate command. - -`uspd` uses `dm_entry_param_method` API from `libbbfdm` to get the device tree schema and it's values. - -In short, it covers/supports the new syntax introduced in `TR-369` by using the existing data-model available with `libbbfdm`. - - -## Important topics -* [UBUS methods](./docs/guide/ubus_methods.md) -* [UBUS Errors](./docs/guide/ubus_errors.md) -* [UBUS examples](./docs/guide/ubus_example.md) -* [Parallel UBUS call](./docs/guide/ubus_parallel_call.md) -* [Third party datamodel integration](./docs/guide/data_model_integration.md) - - -## Dependencies - -### Build-Time Dependencies - -To successfully build uspd, following libraries are needed: - -| Dependency | Link | License | -| ---------- | ------------------------------------------- | -------------- | -| libuci | https://git.openwrt.org/project/uci.git | LGPL 2.1 | -| libubox | https://git.openwrt.org/project/libubox.git | BSD | -| libubus | https://git.openwrt.org/project/ubus.git | LGPL 2.1 | -| libjson-c | https://s3.amazonaws.com/json-c_releases | MIT | -| libbbfdm | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 | - - -### Run-Time Dependencies - -In order to run the `uspd`, following dependencies are needed to be running/available before `uspd`. - -| Dependency | Link | License | -| ---------- | ---------------------------------------- | -------- | -| ubusd | https://git.openwrt.org/project/ubus.git | LGPL 2.1 | -| libbbfdm | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 | - -System daemon `ubusd` is used to expose the USP functionality over `ubus`. diff --git a/bbfd/src/add_delete.c b/bbfd/add_delete.c similarity index 100% rename from bbfd/src/add_delete.c rename to bbfd/add_delete.c diff --git a/bbfd/src/add_delete.h b/bbfd/add_delete.h similarity index 100% rename from bbfd/src/add_delete.h rename to bbfd/add_delete.h diff --git a/bbfd/src/common.c b/bbfd/common.c similarity index 100% rename from bbfd/src/common.c rename to bbfd/common.c diff --git a/bbfd/src/common.h b/bbfd/common.h similarity index 100% rename from bbfd/src/common.h rename to bbfd/common.h diff --git a/bbfd/docs/.pages b/bbfd/docs/.pages deleted file mode 100644 index 0f676761..00000000 --- a/bbfd/docs/.pages +++ /dev/null @@ -1,7 +0,0 @@ -title: "USP Daemon Documentation" - -nav: - - "api" - - "guide" - - "spec" - - "..." diff --git a/bbfd/docs/api/.pages b/bbfd/docs/api/.pages deleted file mode 100644 index 20f788a4..00000000 --- a/bbfd/docs/api/.pages +++ /dev/null @@ -1,6 +0,0 @@ -title: "USP Daemon API" - -nav: - - "ubus" - - "uci" - - "..." diff --git a/bbfd/docs/api/ubus/.pages b/bbfd/docs/api/ubus/.pages deleted file mode 100644 index 853bfe51..00000000 --- a/bbfd/docs/api/ubus/.pages +++ /dev/null @@ -1,4 +0,0 @@ -title: "USP Daemon UBUS" - -nav: - - "..." diff --git a/bbfd/docs/api/ubus/usp.md b/bbfd/docs/api/ubus/usp.md deleted file mode 100644 index 0a357f10..00000000 --- a/bbfd/docs/api/ubus/usp.md +++ /dev/null @@ -1,3162 +0,0 @@ -# usp Schema - -``` -https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/ubus/usp.md -``` - -| Custom Properties | Additional Properties | -| ----------------- | --------------------- | -| Forbidden | Forbidden | - -# usp - -| List of Methods | -| ------------------------------------- | -| [add_object](#add_object) | Method | usp (this schema) | -| [del_object](#del_object) | Method | usp (this schema) | -| [get](#get) | Method | usp (this schema) | -| [get_supported_dm](#get_supported_dm) | Method | usp (this schema) | -| [instances](#instances) | Method | usp (this schema) | -| [list_operate](#list_operate) | Method | usp (this schema) | -| [object_names](#object_names) | Method | usp (this schema) | -| [operate](#operate) | Method | usp (this schema) | -| [set](#set) | Method | usp (this schema) | -| [validate](#validate) | Method | usp (this schema) | - -## add_object - -### Add a new object instance - -Add a new object in multi instance object - -`add_object` - -- type: `Method` - -### add_object Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### path - -Complete object element path as per TR181 - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#add_object-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp add_object {"path":"in dolore nul","proto":"usp","instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "add_object", - { "path": "in dolore nul", "proto": "usp", "instance_mode": 1 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `object[]` - -##### parameters Type - -Array type: `object[]` - -All items must be of the type: `object` with following properties: - -| Property | Type | Required | -| ----------- | ------- | ------------ | -| `fault` | integer | Optional | -| `instance` | string | Optional | -| `parameter` | string | **Required** | -| `status` | boolean | **Required** | - -#### fault - -`fault` - -- is optional -- type: reference - -##### fault Type - -`integer` - -- minimum value: `7000` -- maximum value: `9050` - -#### instance - -`instance` - -- is optional -- type: `string` - -##### instance Type - -`string` - -#### parameter - -Complete object element path as per TR181 - -`parameter` - -- is **required** -- type: reference - -##### parameter Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### parameter Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ - "parameters": [ - { "parameter": "consequat", "status": false, "instance": "occaecat sit con", "fault": 8804 }, - { "parameter": "mollit proident nisi est commodo", "status": false, "instance": "sunt ut nisi", "fault": 7496 }, - { "parameter": "et irure ut incididunt", "status": true, "instance": "minim", "fault": 7873 }, - { "parameter": "occaecat sint eu", "status": false, "instance": "est aliqua voluptate cillum", "fault": 7743 }, - { "parameter": "Ut repr", "status": true, "instance": "velit voluptate in", "fault": 7418 } - ] -} -``` - -## del_object - -### Delete object instance - -Delete a object instance from multi instance object - -`del_object` - -- type: `Method` - -### del_object Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#del_object-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp del_object {"path":"ea amet qui et culp","proto":"usp",instance_mode":0} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "del_object", - { "path": "ea amet qui et culp", "proto": "usp", "instance_mode": 0 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `object[]` - -##### parameters Type - -Array type: `object[]` - -All items must be of the type: `object` with following properties: - -| Property | Type | Required | -| ----------- | ------- | ------------ | -| `fault` | integer | Optional | -| `parameter` | string | **Required** | -| `status` | boolean | **Required** | - -#### fault - -`fault` - -- is optional -- type: reference - -##### fault Type - -`integer` - -- minimum value: `7000` -- maximum value: `9050` - -#### parameter - -Complete object element path as per TR181 - -`parameter` - -- is **required** -- type: reference - -##### parameter Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### parameter Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ - "parameters": [ - { "parameter": "culpaconsectetur proident voluptate", "status": true, "fault": 7084 }, - { "parameter": "auteofficia", "status": false, "fault": 8637 }, - { "parameter": "eu occaecat cillum laborum", "status": true, "fault": 7337 }, - { "parameter": "irure adipisicing", "status": true, "fault": 8214 } - ] -} -``` - -## get - -### Get handler - -Query the datamodel object - -`get` - -- type: `Method` - -### get Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#get-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp get {"path":"adipisicing aliqua","proto":"both","maxdepth":-13721201,"next-level":true,"instance-mode":-25889726} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "get", - { - "path": "adipisicing aliqua", - "proto": "both", - "maxdepth": -13721201, - "next-level": true, - "instance-mode": -25889726 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "type": "object", - "properties": {}, - "examples": [ - "root@iopsys:/tmp# ubus call usp get '{\"path\":\"Device.Users.User.2.\"}'\n{\n\t\"User\": [\n\t\t{\n\t\t\t\"Alias\": \"\",\n\t\t\t\"Enable\": true,\n\t\t\t\"Language\": \"\",\n\t\t\t\"Password\": \"\",\n\t\t\t\"RemoteAccessCapable\": false,\n\t\t\t\"Username\": \"user_2\"\n\t\t}\n\t]\n}", - "root@iopsys:/tmp# ubus call usp get '{\"path\":\"Device.Users.\"}'\n{\n\t\"Users\": {\n\t\t\"User\": [\n\t\t\t{\n\t\t\t\t\"Alias\": \"\",\n\t\t\t\t\"Enable\": true,\n\t\t\t\t\"Language\": \"\",\n\t\t\t\t\"Password\": \"\",\n\t\t\t\t\"RemoteAccessCapable\": true,\n\t\t\t\t\"Username\": \"user\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Alias\": \"\",\n\t\t\t\t\"Enable\": true,\n\t\t\t\t\"Language\": \"\",\n\t\t\t\t\"Password\": \"\",\n\t\t\t\t\"RemoteAccessCapable\": false,\n\t\t\t\t\"Username\": \"user_2\"\n\t\t\t}\n\t\t],\n\t\t\"UserNumberOfEntries\": 2\n\t}\n}" - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":8504},{}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [{ "fault": 8504 }, {}], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## get_supported_dm - -### Get list of supported datamodel parameters - -Schema will have all the nodes/objects supported by libbbf - -`get_supported_dm` - -- type: `Method` - -### get_supported_dm Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| ------------- | ------- | -------- | -| `next-level` | boolean | Optional | -| `path` | string | Optional | -| `schema_type` | integer | Optional | - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is optional -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### schema_type - -0-All, 1-Parameter only 2- Event only 3- operate only - -`schema_type` - -- is optional -- type: `integer` - -##### schema_type Type - -`integer` - -- minimum value: `0` -- maximum value: `3` - -### Ubus CLI Example - -``` -ubus call usp get_supported_dm {"path":"cupidatat mollit do off","next-level":false,"schema_type":0} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "get_supported_dm", - { "path": "cupidatat mollit do off", "next-level": false, "schema_type": 0 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "type", "writable"], - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":8131},{\"parameters\":[{\"parameter\":\"Lorem eu dolor\",\"type\":\"xsd:object\",\"writable\":\"0\",\"cmd_type\":\"async\",\"in\":[\"reprehenderit consectetur mollit dolor\"],\"out\":[\"sed proident et magna pariatur\"]}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 8131 }, - { - "parameters": [ - { - "parameter": "Lorem eu dolor", - "type": "xsd:object", - "writable": "0", - "cmd_type": "async", - "in": ["reprehenderit consectetur mollit dolor"], - "out": ["sed proident et magna pariatur"] - } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## instances - -### Instance query handler - -Get the instances of multi object - -`instances` - -- type: `Method` - -### instances Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#instances-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp instances {"path":"veniam ex fugiat","proto":"cwmp","maxdepth":72958357,"next-level":true,"instance-mode":-75752298} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "instances", - { - "path": "veniam ex fugiat", - "proto": "cwmp", - "maxdepth": 72958357, - "next-level": true, - "instance-mode": -75752298 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/instance_t" - } - } - } - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7958},{\"parameters\":[{\"parameter\":\"magna dolor ess\"},{\"parameter\":\"exidut in cillum\"},{\"parameter\":\"adipisicing Ut\"},{\"parameter\":\"in dolore in irure\"}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 7958 }, - { - "parameters": [ - { "parameter": "magna dolor ess" }, - { "parameter": "exidut in cillum" }, - { "parameter": "adipisicing Ut" }, - { "parameter": "in dolore in irure" } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## list_operate - -### List down supported usp operate commands - -Commands will be shown in schema format - -`list_operate` - -- type: `Method` - -### list_operate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call usp list_operate {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "usp", "list_operate", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `object[]` - -##### parameters Type - -Array type: `object[]` - -All items must be of the type: `object` with following properties: - -| Property | Type | Required | -| ----------- | ------ | ------------ | -| `in` | array | Optional | -| `out` | array | Optional | -| `parameter` | string | **Required** | -| `type` | string | **Required** | - -#### in - -`in` - -- is optional -- type: `string[]` - -##### in Type - -Array type: `string[]` - -All items must be of the type: `string` - -#### out - -`out` - -- is optional -- type: `string[]` - -##### out Type - -Array type: `string[]` - -All items must be of the type: `string` - -#### parameter - -Datamodel object schema path - -`parameter` - -- is **required** -- type: reference - -##### parameter Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### parameter Examples - -```json -Device.DHCPv4.Client.{i}.Renew() -``` - -```json -Device.FactoryReset() -``` - -#### type - -`type` - -- is **required** -- type: reference - -##### type Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#list_operate-known-values). - -##### type Known Values - -| Value | -| ----- | -| async | -| sync | - -### Output Example - -```json -{ - "parameters": [ - { - "parameter": "incididunt occaecat", - "type": "async", - "in": ["sed magna", "in", "exercitation ut culpa"], - "out": ["fugiat eu in officia"] - } - ] -} -``` - -## object_names - -### Get objects names - -Get names of all the objects below input object path - -`object_names` - -- type: `Method` - -### object_names Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#object_names-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp object_names {"path":"ullamco","proto":"cwmp","maxdepth":6964414,"next-level":true,"instance-mode":-14339037} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "object_names", - { "path": "ullamco", "proto": "cwmp", "maxdepth": 6964414, "next-level": true, "instance-mode": -14339037 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": { - "$ref": "#/definitions/type_t" - }, - "required": ["parameter", "type", "writable"], - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - } - } - } - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":8049},{\"parameters\":[{\"type\":\"xsd:int\",\"required\":[\"parameter\",\"type\",\"writable\"],\"writable\":\"0\",\"properties\":{\"parameter\":\"dolore sint\"}},{\"type\":\"xsd:string\",\"required\":[\"parameter\",\"type\",\"writable\"],\"writable\":\"0\",\"properties\":{\"parameter\":\"ipsum Duis do sunt\"}},{\"type\":\"xsd:hexBinary\",\"required\":[\"parameter\",\"type\",\"writable\"],\"writable\":\"1\",\"properties\":{\"parameter\":\"dolore\"}},{\"type\":\"xsd:unsignedLong\",\"required\":[\"parameter\",\"type\",\"writable\"],\"writable\":\"1\",\"properties\":{\"parameter\":\"esse proident aliqua\"}},{\"type\":\"xsd:boolean\",\"required\":[\"parameter\",\"type\",\"writable\"],\"writable\":\"1\",\"properties\":{\"parameter\":\"labore fugiat\"}}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 8049 }, - { - "parameters": [ - { - "type": "xsd:int", - "required": ["parameter", "type", "writable"], - "writable": "0", - "properties": { "parameter": "dolore sint" } - }, - { - "type": "xsd:string", - "required": ["parameter", "type", "writable"], - "writable": "0", - "properties": { "parameter": "ipsum Duis do sunt" } - }, - { - "type": "xsd:hexBinary", - "required": ["parameter", "type", "writable"], - "writable": "1", - "properties": { "parameter": "dolore" } - }, - { - "type": "xsd:unsignedLong", - "required": ["parameter", "type", "writable"], - "writable": "1", - "properties": { "parameter": "esse proident aliqua" } - }, - { - "type": "xsd:boolean", - "required": ["parameter", "type", "writable"], - "writable": "1", - "properties": { "parameter": "labore fugiat" } - } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## operate - -### Operate handler - -Operate on object element provided in path - -`operate` - -- type: `Method` - -### operate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `action` | string | **Required** | | -| `input` | object | Optional | | -| `instance-mode` | integer | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### action - -Opreate command as defined in TR-369, TR-181-2.13 - -`action` - -- is **required** -- type: `string` - -##### action Type - -`string` - -All instances must conform to this regular expression - -```regex -[a-zA-Z]+\(\) -``` - -- test example: - [{&quot;path&quot;:&quot;Device.WiFi.&quot;, &quot;action&quot;:&quot;Reset\(\)&quot;}]() - -##### action Example - -```json -{ "path": "Device.WiFi.", "action": "Reset()" } -``` - -#### input - -Input arguments for the operate command as defined in TR-181-2.13 - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -##### input Example - -```json -{ "path": "Device.IP.Diagnostics", "action": "IPPing()", "input": { "Host": "iopsys.eu" } } -``` - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#operate-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp operate {"path":"nullaea aliquip","action":"MFy()","proto":"usp","instance-mode":21204540,"input":{}} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "operate", - { "path": "nullaea aliquip", "action": "MFy()", "proto": "usp", "instance-mode": 21204540, "input": {} } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "object", - "required": ["Results"], - "properties": { - "Results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "Result": { - "type": "string", - "Description": "Success or Failure" - } - } - } - } - } - } - } - }, - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7934},{\"Results\":[{\"path\":\"nisi quis fugi\",\"result\":[{\"Result\":\"adipisicing consequat sunt laborum\"}]},{\"path\":\"in Excepteur exerci\",\"result\":[{\"Result\":\"aliqua ullamco laborum irure\"},{\"Result\":\"sed\"},{\"Result\":\"ullamco do occae\"}]}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 7934 }, - { - "Results": [ - { "path": "nisi quis fugi", "result": [{ "Result": "adipisicing consequat sunt laborum" }] }, - { - "path": "in Excepteur exerci", - "result": [ - { "Result": "aliqua ullamco laborum irure" }, - { "Result": "sed" }, - { "Result": "ullamco do occae" } - ] - } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## set - -### Set handler - -Set values of datamodel object element - -`set` - -- type: `Method` - -### set Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | -| `value` | string | **Required** | | -| `values` | object | Optional | | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#set-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### value - -value of the object element provided in path, path should contains valid writable object element - -`value` - -- is **required** -- type: `string` - -##### value Type - -`string` - -##### value Examples - -```json -{ "path": "Device.WiFi.SSID.1.SSID", "value": "test_ssid" } -``` - -```json -{ "path": "Device.WiFi.SSID.2.Enable", "value": "true" } -``` - -```json -{ "path": "Device.WiFi.SSID.1.Enable", "value": "0" } -``` - -#### values - -To set multiple values at once, path should be relative to object elements - -`values` - -- is optional -- type: `object` - -##### values Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -##### values Examples - -```json -{ "path": "Device.WiFi.SSID.1", "values": { ".SSID": "test_ssid", ".Name": "test_name" } } -``` - -```json -{ "path": "Device.WiFi.SSID.2", "values": { ".SSID": "test_ssid" } } -``` - -### Ubus CLI Example - -``` -ubus call usp set {"path":"magna voluptate labore","value":"cupidatat","proto":"usp","values":{},"instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "set", - { - "path": "magna voluptate labore", - "value": "cupidatat", - "proto": "usp", - "values": {}, - "key": "quis", - "instance_mode": 1 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "status": { - "const": "0" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"status\":\"1\"},{\"parameters\":[{\"path\":\"nulla ad\",\"status\":\"0\",\"fault\":8453},{\"path\":\"ut non\",\"status\":\"0\",\"fault\":8067},{\"path\":\"exercitation ad\",\"status\":\"0\",\"fault\":7689},{\"path\":\"nostrud\",\"status\":\"0\",\"fault\":8772}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "status": "1" }, - { - "parameters": [ - { "path": "nulla ad", "status": "0", "fault": 8453 }, - { "path": "ut non", "status": "0", "fault": 8067 }, - { "path": "exercitation ad", "status": "0", "fault": 7689 }, - { "path": "nostrud", "status": "0", "fault": 8772 } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## validate - -### Validate a datamodel object - -API to check if a datamodel object is available - -`validate` - -- type: `Method` - -### validate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#validate-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp validate {"path":"et Excepteur ad","proto":"cwmp","maxdepth":2151689,"next-level":true,"instance-mode":-6258066} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp", - "validate", - { "path": "et Excepteur ad", "proto": "cwmp", "maxdepth": 2151689, "next-level": true, "instance-mode": -6258066 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ----------- | ------- | -------- | -| `fault` | integer | Optional | -| `parameter` | string | Optional | - -#### fault - -`fault` - -- is optional -- type: reference - -##### fault Type - -`integer` - -- minimum value: `7000` -- maximum value: `9050` - -#### parameter - -`parameter` - -- is optional -- type: `string` - -##### parameter Type - -`string` - -### Output Example - -```json -{ "parameter": "nisi te", "fault": 8845 } -``` diff --git a/bbfd/docs/api/ubus/usp.raw.md b/bbfd/docs/api/ubus/usp.raw.md deleted file mode 100644 index 5b401fb8..00000000 --- a/bbfd/docs/api/ubus/usp.raw.md +++ /dev/null @@ -1,4694 +0,0 @@ -# usp.raw Schema - -``` -https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/ubus/usp.raw.md -``` - -| Custom Properties | Additional Properties | -| ----------------- | --------------------- | -| Forbidden | Forbidden | - -# usp.raw - -| List of Methods | -| ----------------------------------------- | -| [add_object](#add_object) | Method | usp.raw (this schema) | -| [del_object](#del_object) | Method | usp.raw (this schema) | -| [dump_schema](#dump_schema) | Method | usp.raw (this schema) | -| [get](#get) | Method | usp.raw (this schema) | -| [get_supported_dm](#get_supported_dm) | Method | usp.raw (this schema) | -| [getm_names](#getm_names) | Method | usp.raw (this schema) | -| [getm_values](#getm_values) | Method | usp.raw (this schema) | -| [instances](#instances) | Method | usp.raw (this schema) | -| [list_events](#list_events) | Method | usp.raw (this schema) | -| [list_operate](#list_operate) | Method | usp.raw (this schema) | -| [notify_event](#notify_event) | Method | usp.raw (this schema) | -| [object_names](#object_names) | Method | usp.raw (this schema) | -| [operate](#operate) | Method | usp.raw (this schema) | -| [set](#set) | Method | usp.raw (this schema) | -| [setm_values](#setm_values) | Method | usp.raw (this schema) | -| [transaction_abort](#transaction_abort) | Method | usp.raw (this schema) | -| [transaction_commit](#transaction_commit) | Method | usp.raw (this schema) | -| [transaction_start](#transaction_start) | Method | usp.raw (this schema) | -| [transaction_status](#transaction_status) | Method | usp.raw (this schema) | -| [validate](#validate) | Method | usp.raw (this schema) | - -## add_object - -### Add a new object instance - -Add a new object in multi instance object - -`add_object` - -- type: `Method` - -### add_object Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| ---------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | -| `transaction_id` | integer | **Required** | | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### path - -Complete object element path as per TR181 - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#add_object-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -### Ubus CLI Example - -``` -ubus call usp.raw add_object {"path":"eu sit","transaction_id":13511822,"proto":"both","instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "add_object", - { - "path": "eu sit", - "transaction_id": 13511822, - "proto": "both", - "key": "ut non in qui cupidatat", - "instance_mode": 1 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "status"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - }, - "instance": { - "type": "string" - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ - "parameters": [ - { - "parameter": "exnon sint minim cupidatat anim", - "status": false, - "fault": 8106, - "instance": "exercitation qui culpa ven" - } - ] -} -``` - -## del_object - -### Delete object instance - -Delete a object instance from multi instance object - -`del_object` - -- type: `Method` - -### del_object Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| ---------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | -| `transaction_id` | integer | **Required** | | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#del_object-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -### Ubus CLI Example - -``` -ubus call usp.raw del_object {"path":"ut adipisicing ut nisi","transaction_id":8573124,"proto":"cwmp","instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "del_object", - { - "path": "ut adipisicing ut nisi", - "transaction_id": 8573124, - "proto": "cwmp", - "key": "tempor consectetur veniam laborum", - "instance_mode": 1 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "status"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ "parameters": [{ "parameter": "essein incididunt Duis dolore mollit", "status": true, "fault": 7621 }] } -``` - -## dump_schema - -### Get available datamodel schema from Device - -Schema will have all the nodes/objects supported by data model - -`dump_schema` - -- type: `Method` - -### dump_schema Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call usp.raw dump_schema {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "usp.raw", "dump_schema", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "unique_keys": { - "type": "array", - "uniqueItems": true, - "maxItems": 8, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": ["parameter", "writable", "type"] - }, - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - } - }, - "required": ["parameter", "writable", "type"] - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ - "parameters": [ - { - "parameter": "aliquip adipisicing sed quis", - "writable": "1", - "type": "xsd:unsignedLong", - "unique_keys": ["nisi"] - }, - { "parameter": "reprehenderit occaecat i", "writable": "0", "type": "xsd:object" } - ] -} -``` - -## get - -### Get handler - -Query the datamodel object - -`get` - -- type: `Method` - -### get Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#get-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw get {"path":"etcillum in Duis","proto":"cwmp","maxdepth":-12869241,"next-level":false,"instance-mode":-60814589} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "get", - { - "path": "etcillum in Duis", - "proto": "cwmp", - "maxdepth": -12869241, - "next-level": false, - "instance-mode": -60814589 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "value", "type"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":8248},{\"parameters\":[{\"parameter\":\"in magna et\",\"value\":\"Excepteur\",\"type\":\"xsd:int\"}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 8248 }, - { "parameters": [{ "parameter": "in magna et", "value": "Excepteur", "type": "xsd:int" }] } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## get_supported_dm - -### Get list of supported datamodel parameters - -Schema will have all the nodes/objects supported by libbbf - -`get_supported_dm` - -- type: `Method` - -### get_supported_dm Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| ------------- | ------- | -------- | -| `next-level` | boolean | Optional | -| `path` | string | Optional | -| `schema_type` | integer | Optional | - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is optional -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### schema_type - -0-All, 1-Parameter only 2- Event only 3- operate only - -`schema_type` - -- is optional -- type: `integer` - -##### schema_type Type - -`integer` - -- minimum value: `0` -- maximum value: `3` - -### Ubus CLI Example - -``` -ubus call usp.raw get_supported_dm {"path":"minim occae","next-level":false,"schema_type":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "usp.raw", "get_supported_dm", { "path": "minim occae", "next-level": false, "schema_type": 1 }] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": ["parameter", "type"] - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7018},{\"parameters\":[{\"parameter\":\"sunt Ut nulla labore id\",\"type\":\"xsd:unsignedInt\",\"writable\":\"1\",\"cmd_type\":\"async\",\"in\":[\"minim est\"],\"out\":[\"sed in laborum fugiat\"]}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 7018 }, - { - "parameters": [ - { - "parameter": "sunt Ut nulla labore id", - "type": "xsd:unsignedInt", - "writable": "1", - "cmd_type": "async", - "in": ["minim est"], - "out": ["sed in laborum fugiat"] - } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## getm_names - -### Get multiple object names - -Query multiple object names at once - -`getm_names` - -- type: `Method` - -### getm_names Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `paths` | array | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### paths - -`paths` - -- is **required** -- type: `array` - -##### paths Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ], - "simpletype": "`array`" -} -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#getm_names-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw getm_names {"paths":["sit id"],"proto":"usp","next-level":true,"instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "getm_names", - { "paths": ["sit id"], "proto": "usp", "next-level": true, "instance_mode": 1 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ - "parameters": [ - { "parameter": "incididunt sed et", "value": "consequat incididunt dolore", "type": "xsd:boolean", "fault": 9006 } - ] -} -``` - -## getm_values - -### Get multiple values - -Query multiple paths at once - -`getm_values` - -- type: `Method` - -### getm_values Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `paths` | array | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### paths - -`paths` - -- is **required** -- type: `array` - -##### paths Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ], - "simpletype": "`array`" -} -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#getm_values-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw getm_values {"paths":["nulla esse magna"],"proto":"both","next-level":true,"instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "getm_values", - { "paths": ["nulla esse magna"], "proto": "both", "next-level": true, "instance_mode": 1 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ "parameters": [{ "parameter": "aliqua ullamco", "value": "qui eiusmo", "type": "xsd:string", "fault": 8116 }] } -``` - -## instances - -### Instance query handler - -Get the instances of multi object - -`instances` - -- type: `Method` - -### instances Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | Optional | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#instances-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw instances {"path":"eiusmod","proto":"usp","next-level":true,"maxdepth":-11964632,"instance-mode":9983797} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "instances", - { "path": "eiusmod", "proto": "usp", "next-level": true, "maxdepth": -11964632, "instance-mode": 9983797 } - ] -} -``` - -#### output - -`output` - -- is optional -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "required": ["parameter"], - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/instance_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7620},{\"parameters\":[{\"parameter\":\"doloret minim adi\"}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [{ "fault": 7620 }, { "parameters": [{ "parameter": "doloret minim adi" }] }], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## list_events - -### List down supported usp events - -events will be shown in schema format - -`list_events` - -- type: `Method` - -### list_events Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call usp.raw list_events {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "usp.raw", "list_events", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "type"], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "type": "string", - "pattern": "xsd:event" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ "parameters": [{ "parameter": "in est nostrud ea", "type": "xsd:event", "in": ["labore"] }] } -``` - -## list_operate - -### List down supported usp operate commands - -Commands will be shown in schema format - -`list_operate` - -- type: `Method` - -### list_operate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call usp.raw list_operate {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "usp.raw", "list_operate", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ----- | ------------ | -| `parameters` | array | **Required** | - -#### parameters - -`parameters` - -- is **required** -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "type"], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ - "parameters": [ - { "parameter": "in com", "type": "async", "in": ["fugiat"], "out": ["pariatur ut cillum proident veniam"] } - ] -} -``` - -## notify_event - -### notify occurance of an event on ubus - -`notify_event` - -- type: `Method` - -### notify_event Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | Optional | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | string | Optional | -| `name` | string | **Required** | - -#### input - -`input` - -- is optional -- type: `string` - -##### input Type - -`string` - -#### name - -`name` - -- is **required** -- type: `string` - -##### name Type - -`string` - -### Ubus CLI Example - -``` -ubus call usp.raw notify_event {"name":"deserunt ipsum dolor officia","input":"Lorem consequat commodo in occaecat"} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "notify_event", - { "name": "deserunt ipsum dolor officia", "input": "Lorem consequat commodo in occaecat" } - ] -} -``` - -#### output - -`output` - -- is optional -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## object_names - -### Get objects names - -Get names of all the objects below input object path - -`object_names` - -- type: `Method` - -### object_names Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#object_names-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw object_names {"path":"mollit aliqua dolor Duis elit","proto":"cwmp","next-level":true,"maxdepth":-77404850,"instance-mode":-15946651} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "object_names", - { - "path": "mollit aliqua dolor Duis elit", - "proto": "cwmp", - "next-level": true, - "maxdepth": -77404850, - "instance-mode": -15946651 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "writable", "type"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "writable": { - "type": "integer", - "description": "1 if object is writable, 0 otherwise" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7963},{\"parameters\":[{\"parameter\":\"sint do dolor ex\",\"writable\":-25525336,\"type\":\"xsd:event\"}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 7963 }, - { "parameters": [{ "parameter": "sint do dolor ex", "writable": -25525336, "type": "xsd:event" }] } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## operate - -### Operate handler - -Operate on object element provided in path - -`operate` - -- type: `Method` - -### operate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `action` | string | **Required** | | -| `input` | object | Optional | | -| `instance_mode` | integer | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### action - -Opreate command as defined in TR-369, TR-181-2.13 - -`action` - -- is **required** -- type: `string` - -##### action Type - -`string` - -##### action Example - -```json -{ "path": "Device.WiFi.", "action": "Reset()" } -``` - -#### input - -Input arguments for the operate command as defined in TR-181-2.13 - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -##### input Example - -```json -{ "path": "Device.IP.Diagnostics", "action": "IPPing()", "input": { "Host": "iopsys.eu" } } -``` - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#operate-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw operate {"path":"magna dolor qui","action":"qui in dolore eiusmod","proto":"cwmp","input":{},"instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "operate", - { "path": "magna dolor qui", "action": "qui in dolore eiusmod", "proto": "cwmp", "input": {}, "instance_mode": 1 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| --------- | ----- | ------------ | -| `Results` | array | **Required** | - -#### Results - -`Results` - -- is **required** -- type: `array` - -##### Results Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["path"], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "parameters": { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "type": "string" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ - "Results": [ - { - "path": "minim irure enim exercitation e", - "parameters": [ - { "parameter": "laboris anim commodo", "value": "consequat in veniam", "type": "xsd:boolean", "fault": 8214 } - ] - } - ] -} -``` - -## set - -### Set handler - -Set values of datamodel object element - -`set` - -- type: `Method` - -### set Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| ---------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | -| `transaction_id` | integer | **Required** | | -| `value` | string | **Required** | | -| `values` | object | Optional | | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#set-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -#### value - -value of the object element provided in path, path should contains valid writable object element - -`value` - -- is **required** -- type: `string` - -##### value Type - -`string` - -##### value Examples - -```json -{ "path": "Device.WiFi.SSID.1.SSID", "value": "test_ssid" } -``` - -```json -{ "path": "Device.WiFi.SSID.2.Enable", "value": "true" } -``` - -```json -{ "path": "Device.WiFi.SSID.1.Enable", "value": "0" } -``` - -#### values - -To set multiple values at once, path should be relative to object elements - -`values` - -- is optional -- type: `object` - -##### values Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -##### values Examples - -```json -{ "path": "Device.WiFi.SSID.1", "values": { ".SSID": "test_ssid", ".Name": "test_name" } } -``` - -```json -{ "path": "Device.WiFi.SSID.2", "values": { ".SSID": "test_ssid" } } -``` - -### Ubus CLI Example - -``` -ubus call usp.raw set {"path":"anim ullamco","value":"officia nostrud dolor ad tempor","transaction_id":47775846,"proto":"usp","values":{},"instance_mode":1} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "set", - { - "path": "anim ullamco", - "value": "officia nostrud dolor ad tempor", - "transaction_id": 47775846, - "proto": "usp", - "values": {}, - "key": "dolore aliquip quis nostrud", - "instance_mode": 1 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"status\":\"1\"},{\"parameters\":[{\"parameter\":\"deserunt tempor\",\"status\":false,\"fault\":7042}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [{ "status": "1" }, { "parameters": [{ "parameter": "deserunt tempor", "status": false, "fault": 7042 }] }], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## setm_values - -### Set values of multiple objects at once - -`setm_values` - -- type: `Method` - -### setm_values Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| ---------------- | ------- | ------------ | -------- | -| `instance_mode` | integer | Optional | | -| `key` | string | Optional | | -| `proto` | string | Optional | `"both"` | -| `pv_tuple` | array | **Required** | | -| `transaction_id` | integer | **Required** | | - -#### instance_mode - -`instance_mode` - -- is optional -- type: `integer` - -##### instance_mode Type - -`integer` - -- minimum value: `0` -- maximum value: `1` - -#### key - -`key` - -- is optional -- type: `string` - -##### key Type - -`string` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#setm_values-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### pv_tuple - -`pv_tuple` - -- is **required** -- type: `array` - -##### pv_tuple Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["path", "value"], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "key": { - "type": "string" - } - } - } - ], - "simpletype": "`array`" -} -``` - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `0` - -### Ubus CLI Example - -``` -ubus call usp.raw setm_values {"pv_tuple":[{"path":"exmagna incididunt qui labore","value":"cillum occaecat aliquip anim id"}],"transaction_id":54841604,"proto":"both","instance_mode":0} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "setm_values", - { - "pv_tuple": [ - { - "path": "exmagna incididunt qui labore", - "value": "cillum occaecat aliquip anim id", - "key": "adipisicing reprehenderit" - } - ], - "transaction_id": 54841604, - "proto": "both", - "key": "ad", - "instance_mode": 0 - } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------ | ------- | -------- | -| `parameters` | array | Optional | -| `status` | boolean | Optional | - -#### parameters - -`parameters` - -- is optional -- type: `array` - -##### parameters Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "simpletype": "`array`" -} -``` - -#### status - -`status` - -- is optional -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ "status": false, "parameters": [{ "path": "Excepteur eu quis voluptate", "status": false, "fault": 8080 }] } -``` - -## transaction_abort - -### Aborts an on-going transaction - -`transaction_abort` - -- type: `Method` - -### transaction_abort Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| ---------------- | ------- | ------------ | -| `transaction_id` | integer | **Required** | - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -### Ubus CLI Example - -``` -ubus call usp.raw transaction_abort {"transaction_id":57946802} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "usp.raw", "transaction_abort", { "transaction_id": 57946802 }] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------- | ------------ | -| `error` | string | Optional | -| `status` | boolean | **Required** | - -#### error - -`error` - -- is optional -- type: `string` - -##### error Type - -`string` - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ "status": true, "error": "labore ad id" } -``` - -## transaction_commit - -### Commits an on-going transaction - -`transaction_commit` - -- type: `Method` - -### transaction_commit Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| ------------------ | ------- | ------------ | -| `restart_services` | boolean | Optional | -| `transaction_id` | integer | **Required** | - -#### restart_services - -`restart_services` - -- is optional -- type: `boolean` - -##### restart_services Type - -`boolean` - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -### Ubus CLI Example - -``` -ubus call usp.raw transaction_commit {"transaction_id":86335477,"restart_services":false} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "usp.raw", "transaction_commit", { "transaction_id": 86335477, "restart_services": false }] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ------------------ | ------- | ------------ | -| `error` | string | Optional | -| `status` | boolean | **Required** | -| `updated_services` | array | Optional | - -#### error - -`error` - -- is optional -- type: `string` - -##### error Type - -`string` - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -#### updated_services - -`updated_services` - -- is optional -- type: `array` - -##### updated_services Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "string" - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ "status": true, "error": "mollit id deserunt", "updated_services": ["id pariatur enim ut sunt"] } -``` - -## transaction_start - -### Start a transaction before set/add/del operations - -`transaction_start` - -- type: `Method` - -### transaction_start Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| ------------- | ------- | ------------ | -| `app` | string | **Required** | -| `max_timeout` | integer | Optional | - -#### app - -`app` - -- is **required** -- type: `string` - -##### app Type - -`string` - -#### max_timeout - -`max_timeout` - -- is optional -- type: `integer` - -##### max_timeout Type - -`integer` - -- minimum value: `0` - -### Ubus CLI Example - -``` -ubus call usp.raw transaction_start {"app":"a","max_timeout":76766611} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "usp.raw", "transaction_start", { "app": "a", "max_timeout": 76766611 }] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ---------------- | ------- | ------------ | -| `error` | string | Optional | -| `status` | boolean | **Required** | -| `transaction_id` | integer | Optional | - -#### error - -`error` - -- is optional -- type: `string` - -##### error Type - -`string` - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -#### transaction_id - -`transaction_id` - -- is optional -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -### Output Example - -```json -{ "status": false, "transaction_id": 12109922, "error": "deserunt aliquip consectetur q" } -``` - -## transaction_status - -### Shows status of a transaction - -`transaction_status` - -- type: `Method` - -### transaction_status Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| ---------------- | ------- | ------------ | -| `transaction_id` | integer | **Required** | - -#### transaction_id - -`transaction_id` - -- is **required** -- type: `integer` - -##### transaction_id Type - -`integer` - -- minimum value: `1` - -### Ubus CLI Example - -``` -ubus call usp.raw transaction_status {"transaction_id":55898564} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "usp.raw", "transaction_status", { "transaction_id": 55898564 }] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| ---------------- | ------- | ------------ | -| `app` | string | Optional | -| `remaining_time` | integer | Optional | -| `status` | string | **Required** | - -#### app - -`app` - -- is optional -- type: `string` - -##### app Type - -`string` - -#### remaining_time - -`remaining_time` - -- is optional -- type: `integer` - -##### remaining_time Type - -`integer` - -#### status - -on-going or not-exists - -`status` - -- is **required** -- type: `string` - -##### status Type - -`string` - -### Output Example - -```json -{ "status": "sed ut", "remaining_time": 13818285, "app": "anim" } -``` - -## validate - -### Validate a datamodel path - -Validate a path - -`validate` - -- type: `Method` - -### validate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| --------------- | ------- | ------------ | -------- | -| `instance-mode` | integer | Optional | | -| `maxdepth` | integer | Optional | | -| `next-level` | boolean | Optional | | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### instance-mode - -`instance-mode` - -- is optional -- type: `integer` - -##### instance-mode Type - -`integer` - -#### maxdepth - -Integer to decide the depth of data model to be parsed - -`maxdepth` - -- is optional -- type: `integer` - -##### maxdepth Type - -`integer` - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -DM object path with search queries - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.[SSID=="test_ssid"].BSSID -``` - -```json -Device.WiFi.SSID.*.BSSID -``` - -```json -Device.WiFi.SSID.[SSID!="test_ssid"&&Enable==1].BSSID -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#validate-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call usp.raw validate {"path":"id adipisicing","proto":"both","next-level":true,"maxdepth":232638,"instance-mode":47166958} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "usp.raw", - "validate", - { "path": "id adipisicing", "proto": "both", "next-level": true, "maxdepth": 232638, "instance-mode": 47166958 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "$ref": "#/definitions/path_t" - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7959},{\"parameters\":\"id aute\"}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"query_path_t\":{\"description\":\"DM object path with search queries\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.[SSID==\\\"test_ssid\\\"].BSSID\",\"Device.WiFi.SSID.*.BSSID\",\"Device.WiFi.SSID.[SSID!=\\\"test_ssid\\\"&&Enable==1].BSSID\",\"Device.WiFi.\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [{ "fault": 7959 }, { "parameters": "id aute" }], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` diff --git a/bbfd/docs/api/uci/.pages b/bbfd/docs/api/uci/.pages deleted file mode 100644 index 35a6ea1a..00000000 --- a/bbfd/docs/api/uci/.pages +++ /dev/null @@ -1,4 +0,0 @@ -title: "USP Daemon UCI" - -nav: - - "..." diff --git a/bbfd/docs/api/uci/uspd.md b/bbfd/docs/api/uci/uspd.md deleted file mode 100644 index 50294433..00000000 --- a/bbfd/docs/api/uci/uspd.md +++ /dev/null @@ -1,216 +0,0 @@ -# UCI Config - - - - -
uspd
- - - - - - - - - - - - - - - -
-
section
-
-
description
-
-
multi
-
-
options
-
-
uspd
-
-
USP daemon Settings
-
-
false
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
name
-
-
type
-
-
required
-
-
default
-
-
description
-
-
granularitylevel
-
-
integer
-
-
no
-
-
0
-
-
Creates ubus objects along with object names, depth of object name depends - on granularitylevel
-
-
debug
-
-
boolean
-
-
no
-
-
-
-
Enabled debug logging
-
-
sock
-
-
string
-
-
no
-
-
-
-
Path for ubus socket to register uspd services
-
-
transaction_timeout
-
-
integer
-
-
no
-
-
10
-
-
Transaction timeout value in seconds
-
-
loglevel
-
-
integer
-
-
no
-
-
1
-
-
Internal loglevel for debugging {0: No Logs; 1: Errors only; 2: Errors - and warnings; 3: Error, warning and info; 4: Everything}
-
-
subprocess_level
-
-
integer
-
-
no
-
-
2
-
-
This parameter configures when subprocess can be used for get operation. Level here denotes the Datamodel object depth up-to which subprocess will be used to collect the get data. For example, if this is configured to 1, then only get for 'Device.' shall be called within the subprocess. If configured as level 2, then all the get with up-to depth 2 like 'Device.WiFi.', 'Device.IP.' shall be called in subprocess.
-
-
bbf_caching_time
-
-
integer
-
-
no
-
-
0
-
-
Max caching time in seconds for ubus output used in datamodel parameters. If not configured, output shall be cleared end the end of call.
-
-
dm_version
-
-
string
-
-
no
-
-
-
-
Configures the datamodel version to use for datamodel parameters, if not configured show all defined datamodel
-
-
refresh_time
-
-
integer
-
-
no
-
-
5
-
-
The time period in seconds after which uspd will refresh the datamodel instances in a periodic manner. If configured to '0' then instance updater will be disabled. If not configured at all then after every 5 seconds datamodel instances will be refreshed.
-
-
- - - diff --git a/bbfd/docs/css/assets/fonts/Madera-Bold.eot b/bbfd/docs/css/assets/fonts/Madera-Bold.eot deleted file mode 100644 index 457671d88ef3a24eca85d07579041f9e0f4c703a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 97980 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 - - - -Created by FontForge 20201107 at Thu Jan 11 12:25:57 2018 - By Unknown -Copyright (c) 2018 Monotype Imaging Inc. All rights reserved - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bbfd/docs/css/assets/fonts/Madera-Bold.ttf b/bbfd/docs/css/assets/fonts/Madera-Bold.ttf deleted file mode 100644 index f2727b12398796294222ae79f86f3af28950f57d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101180 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 H{lD{1gc?@) diff --git a/bbfd/docs/css/assets/fonts/Madera-Bold.woff b/bbfd/docs/css/assets/fonts/Madera-Bold.woff deleted file mode 100644 index 4cb26fdb1715777aee16a62d2955c14d2bb3f58a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49636 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 diff --git a/bbfd/docs/css/assets/fonts/Madera-Regular.eot b/bbfd/docs/css/assets/fonts/Madera-Regular.eot deleted file mode 100644 index 33d4788af8428daadd2584ceddaaed359fb114ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85883 zcma%i1yqz<_dX?^f`ot$ARWUD-Q7sHAUSk*cegZ1HwX#{(kb1Yk`mG_NdCrq?{`tZ zZ~fPQu@$igw+ApYgBU=}%&3%(}LI6@$`X*-9CIBgGLneTbr6u66XB>We9$*h~fY>`jj8G{75)f)AcO)2P` z{R0Jx@IO$btc`5|ASkwf0-6{vb6l`&@_J^`oA~mTbWt9{Xe&;Lw+U+faaex{cjV>e?^7$ zFIND7QjYqTW`;u6CYBIrIDWbZ05o$DH*YQ0gTWJ_;XRk)XdPr8sgvpVEfOSzJnn&NdO$|9Di+wSR4KBRiK!)p^eecyaltd z1N80f_1#dRaG(xlV*_|Vf0{wx>E3@jgXY(Q%#D}$d2VPgHD zWd|DBSpH;yf30xBj}1sXz&QvX501~hfEHHADJftCFy zU^ANsXsjGS2TOei(}#yRf$k7{n+KT-Xk-0=nT;9f=<=}21_C;o+CzR>2SXXd>A^*8 zEI?y3=U>)Yfeuh6_>T+N*nkcY=U))Au>=3k<9~N>0Ii{k_wWQK^puv+4E%Qk7u1B6 z+3!krW}xNIMEuVtb`TI^=cNA-VsRX9-y+bK%)e4_$$5teU25V{}3B?HlWah zNp_&{gTMh4c@Q{(q7MQWQ0!lUgBd9PAb@}p4+0n{`5>?Wr5*%Up!9>l29$Xa*ntm; z&%ptF`LMzXlzR}kfb#zeoXkLl2LS|Bd=S9Ehr;1x0V+SNumV*c1U8`RgTM|{dk{E) z>JI`ZP~$=10&4y%a4`e59t053z+T_b0s?KMzZ3x%7-#_1{+^j!EdSa2du?z*W8`3H zW@cz+Z|L+;*j#Ktr=PUtU}$6ikUm`O(75aWl8{^+z=w+A;shEzVB-QB{wqM~4){t1%msWn8MHqG zAMzgr0s$Wi5(EMRZ69nx>Co;Mi52*e?jR7f_I_Do2R{LO+SYyv7dwfb8x0iLFWm;j!TI-Vgu%bq=Euj<8zafLtn$RCb0Od5H|IRWf zu?gA#mfKKv6B7Hy5*JY9PZxrrG$-~uIOu%Q9^OK&k&}lLILAKWuUW#T*|p1q>xfx!>IahO(smAFqW{rTibSh4Q8R|9UNy zIpzN}$O@GIZzNC}wQ{m_G_!@?VEz*&Fo+!}|9kfWLn&4DPdJ=F)j#2I0agDO94O7I z{`b3~bgTJ?0WcV-VrpamKzv{@v>!q2t)K&`f#pMff}zCwv)q1Zgi=mD%Dev) z543Im;T|w_^!*^VgmSh7R%2E7PB+gAVdWX3l26G)FKil*ax@LRKh2 z{{aR%(L4PC20GO{{VyyZvc^70QagB_VXscl+(p-!9jGw_L}+?&Q!r zBI-Y~u^IHX1cA6h3{idI8hBt~90dY#PYo@LwX*K66{;JlndvlDzfi24ayh{C-V_jR zSjIAZ{6uh4q#R+@0Vx^*O!0rT=3o&-kem2SMjxmTUQI&r8;7wR`WAYdWH&UkkE;|c zEo0c0%y{NO6iDBg@CGgG?Z$9HmCD2#Zq8~-}B6u1l zhlDVbY~AJq3pj_7Rt zpwO2YFvO?#>BE^hM-@$Z{GqWx&)TG^+wmMpVISbiaihJHxs)6*!bX*Gdu42Np(`~q z;b|DB$U8xpR_Q=ysrMv#eGxGd%W-P`XyK#af(3imEr!&@r~d5(PyF?tW4YKl(9`N+ z@Dn{DPQk=h6T#sjTw(uFVn7FPUQM<_e!NvA7l>Ak-2SP3WM<;T-lb9nr^kvfOGS$* zx@j^gnOOrTMjx~XP^9#js4g-X*51^x_Om$3PX114&ar^muf^*0gIy2rgt?mWyK%i5 z85^B@2rFzJ_eZDk%2HnYuf>EAOv+`vk2JBA@*)$LN#}FuUGGxmJEl=`^HZxRq&zFR zayoMtLsOLSlWiU=YYfRUBhbUloEhx})Kh^+{mwJ+sMq0fIItfZttOn@RjaDEC;4Zv zz`fCam!g0o|2=)=@&j#;zb0wKEA42!xZ7e~{8Gj8_w04IIgHxX+@|a&m5;ZX3*MU7 zGPL_28Z*iTBvddkGW#F6hB6iHI8Fd1O{wVWIcG})^;iAOdfe%jgr)t@&{VT@F>_^a z9!(|$GBm%@N)2R9o8PED;|6#D-zT7aCCDA-7msv>FwUp?w8H7s;r5dl>;)$~^=DNv zKIhBR?}Ux&oSkj6@kL~dd^`w3nSe1KFtrj^Oy!dP?x@LuqD7hFW8@twF8|nnMIUd4 zpZJG&$YZqm)Sddc&eQX7ENS_S9oE_Bg#ncm*)q#Hkn9S4oTgsb?$u?IRk?u=<4W!k z)cEq;l@PaTQY7y1e$g+|%!E<~0#T-0-g`%+No-}*QTg>lBxQ9< zE5tHZ8zKApO^Lixn53favD%l!g0WC#cF{c@gbrTx4JV?#fQrzMKXQ0#!HJG3FP)~_ zLRt7;eHbF`>~L}|yQ1=GHg>CCwNGf`I_Dc(2O=Xcecl+<<5bK+f%ztNdFNM00~bxj zT=wak&UzL4kGxyRTER}P|FQuBqxrP$G^vB}`OB6cg!pR8Y%}zL;K@dj~Lwx-P$z z4D}PZ=6*t$&?r~`K6)McNve`WVHsrUy0<{ooV7}ocUkpE-`U)SQyGRovyPZx&5Jel z*-IpG1ILl74H)TsK%n`~;8;Dg_VwG?qO$n{p~E~pn?rZf==8d+t0$g7r`T1|^-M?w^rvV8J`Akz4Xz;<)2pw)&h6VJc>SiNtTh2D+Q+HV^B27v+y3+p3uCj{OXt~!c@uWzo z12Bp@Uch4&ugxqiBZys{Y!YrNAeiK^(_211IF!gsSF2q0VmK8wLBZ|O zWiyKNd;AixpE+Sx`}OHYPvfvogqz%tl!(Aqm6jJ@PQ9++sRXOShhR@}?KvCd1ZBLe z2<6a~f4IcWpA?0RSHEEMzmH+-tsC@uj&Uw!og9-Lx|KQmgxz!U`kvd-h=6K4Gx{dk(yZz?>iDHZ703j;=S-(c_qM1O!(8a_$raUNS`gTiLbSK_l2< z9%r+If=+9&y@?29I`aMo>9)yCzDUFPsoz$B(-O8%4qQc4L-yOVuTjHcQFz^!-$7|z z@d`A@QC4KVcvi9LUvF!(j0a_laY8iH>6_IP2F#M`wfA9gZLFHVO}VbSI0rQNTo3hV z^rv=K7`~{_FlN;-sv0;(l>+p{aX!c8f)k*xWt_n6VtX^nCevTNNz%n>|AGO& z7?6wbi4psRe7960@p$SD@GiQ7sa@Q$*)4W0{D9dIc(NaMW+G+Bx(GA=J-e#lhk=a-!qr+u1=DdS}`B5xt8;2O+{fa>Ft8$Wy5c z-&!+HI~hE>YqqJ`@<+S6x+e(G)^$I*xa=}KlJ(s!a!Jkpg!N2#yR)lhA%!@gAWl>O ztA2_bh%ZytO^C31F{f2X#*z#T!{8bR7nLf1Ltq&~A9+eoiF~!)kS{N3y-o16y&8Za z#P)+-Kn?nOQv(yX=n$v}KE6>$`y6gIOWIKj@8SUYtl#vKh>DtpP1>8OQgryTe09w# z@rPRT0sgtUBl(&t*bof>7-Ri@v4nu}oCjd67xfCsgnblNcX)$)emf6$mc zHx~91;T;?)kkJ+!A}JYoT3@ME)h#;D6n%Z}rR4SFVgN^>I?Zlh)PunWHQ*~U`&3DP zN{dvx)K(GS*8`ol%2$JcScW@3W&_Bh<-)c`Y?P>z_E(nFI7hl=hf+KkIXu1C@S3Z} zNEPs8(eVVj_SChh)<>kapVPYzh!=cnVAJayAsn!*J+gG%N9x@k2Cnj1y~)q=$mLV$Ftt_#wcLd}&L#E4Rq5%|oHz(Pxw_II^nEBs-Ig$5WDFx2$6+FI0)aw9@e&`IHTpY8U zDU-WGctPT4{LZ`GN34&{k*#ZpXy@4n1j@R)AsxYXI1AL)eqJI^*ZUO}H09#wC|^}%FO2Hu#k6P9sRTSZ) zy-DU>@wUjOHZPh{A~mY|d!>pt9y6w;VRkp8X*mgWi?g&_yxk*M`tL7$PBXezmkszy z=AZ1JydJ1CK6USQE!7Jb09wBI*lxAcfr=dl`Z|E*o~}+L&$VQ!wP9u4r&Br2jHFyD zc@~4f%wGPTPzWqw#%XoU=O>yH)+s37V-j^HU))^jQAQRl9GmQ;(bpQ-qWo5nUOczB zp_jTFJA{gkXA?I+E_wzwhJeL;4QvZ9v@UUVmG*lm33Q^-oYGv-v6Q6 zR*k1Pf*n#rgg|dMfKMmrXaDuoMUk7L)<@AxnHvdJ6{yXx6?EL6?qQyN6qKA0@K%!T z2vbqfhUl5tVG;NhjZl5no{>{e*hrzmjv_H9o`HYtOe?EJh+F6HnLQEch%CF;iI?vRm$JB~M!eXfA56Eb)Mc0#W{-3v zF4kDK-Z6H_z&Jpil8K~LEE7&!=R8&G6s|IC793pBV^uaYBa1c;vVhI7r@)Ndeyt%q zb?vVDp`GSXbv_ncNnq3sw?20GMiY~#xR%cNw#H0e zL*;ax-mYh;VvpROY4dFq>eH<|Pn2l*j4s1Qb6lTj1dSHa9H`{a1*Unf_#uX) zDd-!mT{#j{1TMn{Z&>q%@<}7=i6UHyFkvx>5Krr`@h^@t27{}q;Cho^8YDj6u^yV% zoxI{ZQ7g_=E9s3@J+?2jCdX+l!{slI4p%(AyfTf+ssBDaz|iP7vBdk%No;|*JB@lB zA2uX^#K5A9iczn$jW2XPF!vxjN~Zacy=j*<;k^lJAlW^?0+($`RTLBcT_evj!)?#3 z*d}RXzWEKJp(wV8szLpMH!tIJowvGQiF}2)`mjDNmaBvM+mARrO)k}CX1Re%U5X~BB&RfT*MR<(uw9VWL_sLQ8Z;t?|WkD3Pd zw#W7Qb;YUGyTVEv80VsJb@-|tAbG<=6Ql@%3&@43)t)U&=~Q5SwG1UQQ+3T7`F`nQ9cLNUL;+JvTwx~qwOjD+5v2qxSjnW<#+cbR zs_j&adNayO@musjYDwx5Z91WU#4Cz6>yy8|tP}TjT z5nh=Jt)1NMO`V_vt3H>V}go=L=Fm$ zJKgqP6}=6ofnQ)i@^23RST}ID2HRaa!$EHVQzyk3MCXp0Nhswp0lsR76_mbi>S^iJ zTszdUXT!53l$@mP9v?gXj^&rX;G_0Z)pMYXtWUu~y<#9#I#hZp4}%cPqZTC~PRB2b zF2dmpzE*+mDDqr>;mNB#(uAg!a{E}*O0DB7 zV|4|i+!108Cd02^ocm^Jv_5}*p6^xp*8cNMNQUMu9r00O=(k`tVKfJLwLfqz~oTFXF>j-_)b!DQF1zm$)l??tyIaFNpZo9VyGbWB! zn@wp9Ls_(SH%xJoN0*>_T2{j?@1rutr+12kn0aX;wga*3?+PA&epa+T+4kzv^ldb6 zmJ_~38I@ra))EgGbfb1L@aap-28yLbuFcEyt#pkqI5DhBe(oLUv?8nw70u(eM(lgktouwz~c2aJJ{CT;hhlEz}K7YV;m5^RRrtvCysUO!iH;^R})-t%&E(Z>b{(w-$8sW z(ZZ9JNT5~h9L-@1%(q3+<0Ve}T=;N(~)P`{qOcw#+B1$3T-6bJweiMb9a^2DO zrJqiemwoADBk*6FTpxt2z-)@da}GE-CwmjcAlA^os6?H4{Y4r-K&uazr;tsAK?+?% zBv6BdH@7B{a#TX<`|L9w{|tP-Sd`6LivUOb^ICWbAf}7xU`Egxr3ZYNP6`fJ)Z3(l zD|XA5l4L4{NtUl*@0=J)(c*!!taND2uV?}Suo@e&0RHt#^ z%#pHD(-qBLN9KglHirl;{TksBgyvnFN$4x>J&6B=`&l@Xt~_b~-LhIdn=p-E#LBuP zsGh({@zRUdaakfx-h*H+6W^_-W-Pp6mB>!<(6a-6;*Q~Lv`{ig!*ze&DKp1?3b90N z!qF_soK7S(#34y$PX}ftL&Ueci&@sPY1QJqVSozj>CjUrWfyzSG;(Ixo2iEP;nE`B zIr@@=-A~B8cne@hj1OHRE?Tn}G_3CEHxcMLLXSTeOxRFv4xY3lxwbYWtN9QIvisAM zeRCTC8o!{@^s9EmT4=%l{zX@2hBGcF+uPb>=-Fzjz7&z)Id|^p69fu%Z3>lVMK*4| zlI-KwWdSEja(MSM8Umb2N<3i&dxhktbICh&<{ZpSzw zkNx01y?XMH&Ba*XqcOQ*&kbnd^(G@k*JV}^L!vM)vKUg_RovqILh`fIyv_b7rP=H4&pCh`( zV^i#A6UlXWLUv{ItjnwV?s%DODr1XpG5&J=NklrFPpdGwjFzmPwb$QUA@_M2ikJ#6 zf@%j*tG><}BNcaYAsmrb~ zI9>SWOt@0wcrw1Z+TTn;f``bZSMiqGHt>wMHrg>Ar_N1JE)0Jpk+`oaJG^gw%Myk~ z<-R)PcK73Pcei~i-U0=~88O~8#u;21A89wUmhoF5pX;uv%TbA{4$W2mgjwBf#CL|3 zqyyji1Jfk~USlhhyw^x3*|KZnE9a;Awv;Aol9r>7#S7a&luQA zG5*$3^NkgMt)V&&g{M=zZfxkTtdk)!8m#8$T)t0_8an(Y+i+;Of|gHoCw;}gxUQO` z2zi6aa9uD1PA1?Li_XMN@Z-brW{$kNsd5oAT~m!Mv)YZ$E5_Q1ZN z*{fN%1U$@t6A z>zA80u1TbBHGrn6I?{ph3megrFcwAMsX{gTy0_4A)y;gi*GHUIfSaC;mp3cSe~_v9 zs*0d&Oi?ZLeWbJ0ecIZNrv3;EPVPH58r-ja$P2Z}TB&`w>;WCJqJ@ziD?OH(_M_e= z-&g1l?kOeX{iyNwvB;jWj-ZZv#A{O$Ucro!0}=*l3V557Ux_$9_K`uX@}Gmpoqx3d z4K1-VbIsxY7<`#Yy1>4qHuAz=p`G=frTPo*6BvzZ$;>?3tdFPV=|Lo$vt`3ODt<2_|#*W0PI34(uRTZg*ZkCvHRV&55Ys_i=hz9ps1k(WcsA>_fP7YTXC z*~N{8C>X4KcSfR|Ipqg$N^8{e>e21T$*+8E+uO1(NLvsIhB^$C9?2V#?5u;a0K%4| ziRSJ1AQhNryT%!=asz7@lSs3CzTWR|M!2v`zA?8!0)zSuk&MfFm~r-z9plJrpO=(E zFUl}y)fuzQ<=&X_WF0l>lE8@ga@FH;pB{yny00k>ieTbMc2Oicj-yh(TjoCH%-Srp zR|QjEZrmiQ&$wM9I*%|v<(=V}V!d%*tp#>W#oJb34A=J3wgT1Bsg#h>pw+miUn zwyF_eI|YoCAbU1SAW_ZZz+~Hz1IOGLoP@6ffND=EFJR$%QJ%3hHT77!*~NGwzrqc= zrl^Xhu1yKm#tE?SnWHZVLgvKlxvj_`X(Xr*iMsQ>>ajzu6G5(0fN`!{;JOL^pjPXg z4R%~F6Ypeo%C)6LKx7N;U@A=UzMS(R$$CLFr)z$1SLpUgh`O+M?UM>>ANo%A=gvhq z2aJz5TV~0N44jfGp)W}AUsU@XUOv&FacC?Rm|m=o&I!>rZl0VaLqlw_p5Ght9b3i9x}lwzQSS^ za!g-pjGdk#J0NH1kwbb&Md;iJ@D6kl>JfqG(p6=9@A~e0xF$(w<*?Dj3}!6#k`3%o zsvcP=Ar8=ll~1tfyB76e_YFRu9`{8_PgbNE>Lt=i0Y%2;!x^7fmvMrD%6M5k1(Y4d2KVS zFpWR8L4Cy>L|j?Eg?lSVDt*!8@l-P}O?hN#ue7P=M@)^dBPq1Byx_na8(l7ECUYVE zO-+H!<4A$F!Ny@jJ7yiqOedaVvDD~%Rf6n%av~-M6XbfYW{2;UWdW5l9N5Y1uALs2 zNN}kdoMpgU3BdN|l4A7>yBhBKNYj@Qd;v(-9s&IkEWxk8I(3Paha4+lZI{1uT%xTZ zM$&2fp)BYRUs6ohV}19)zp^H48CSRq788s ztb>>+78ENNZnWV_*cmn^9a6NW zSMD=ISa<}xZ#N)p(V9)DS2SX7-d|vBUG@fKZ9;G9ZDv2D8GUb_4<6~wjRPJY!aB^T zM+`@vldvraGln_noKgaFwNY5ibDmOpvwustHrM-H?Qi%>p{ZU2l)+~1Cd?HVj`*cI zXbf0Xzkd*kQKhhGc1>uCvC1`=!*w)Sr__&-RS+zg5ve{xoXom?mX2u^>~A?5Vje)a zh82w2LuWft*6~5~@gh4rnl7@ivH=|YaL37MmlLGPi4V}MzlC$>#fd~a{ zts29vy9(A$o^b(#IYzWaJ$ll6FAUHpqJ*MF?Y-KU_Q&msk7-jddN7L%_58*1NM}(} zx#K<=Qoxz;onz%oEsIxwrkdCQ_}~fg8LCu;QeO38V;S+{6J*aR-W1jyj-M82PC{xw z_-b{{ZwO>6Q5LpQtXDGjk9wiom2ha9VDI*~QG3`!K1<-gcH6z$oalf~K6WZ}zh=i~^WI zH}<$-)4h?2_RyoWax;op(rXGudY3T@9!IpS;g;_g{+H`_G>?MMvgQc6a@)P90+@cF zI(ZG&Co;U3nAlQEJ*hF*9UA;l7p6W?Cl7y@p0t@M^mLqysS;wj4#(E{hLz2!#!G$b zLh9Dv?8O+~jUy4ytkgBh8*^dRH=0e=)BxR?v(C_ApX3CV*(-ksxS*}OhQgQ6gvZ`; zepcYMg|BdDj!4|RMXm^4aBh9hxeap=skJVh(l%<1)mRIsWI88u1#gxS6!lq2@GAzW zYx*|#+$Q$j>cGmEq&7DGhFSq*n5HT$kD7D1MY~l}0sJVE=>U)Oyh>c27C$8+jro})8;V%(Tn3Zt&k=8XeRmQ4 z>l=mSEE~;SI_L4_IwC%VZ|*7E@)g#!Pkbf$fj%fEyOK+73Vcx~5X#u@B&{eCE-*uw zoqOVov34YtEbFY{H(M72$4wX=7>N7=*t~PHi&Tn=JhsW-I~Rji(VC5RLiTii8HcU= z?K{(58@G_LPmczV4h!t=M&aqQ_pZnKb%HEq#9vKfoE_e2;E@}d%CO(7qbr5Q-Uw*o zCpW+{P$wvf?-6p5(-E>WeZZ?LbK_;;$DL)9)iZ%QYK+~JAE_1cdjHh&uOweFwHU+Vt zyCq7;;qg#$(S1Bp(UV1S*P?hjvQ*#y=2P8a|3u*|tKK+e4oRbC0-AE@R&+ZK2?`p`vq1p z*uqb%dvV&n<9pkyrqRxUq`Q79Cl<-z_mT z-CjDvT+uoWs<1lMX56nFBIe+yjIaJAnz#si9}!pAR7K9Qzy3N$D8hGtKB#z#!H167 z-6zs*IHFsFKRma0#r-(?&DbKNhk=rsDWiGAD{Zv*KsMH`f}06AR2Hx;Sa@6e$Ttbc@6`sFS9EM=v~HqL3mJj=GbN$t$p=!=nVl%SlFTmOdF`ST zP>=nA{_w3QX0Bvl(+5fCc%Ax`J zgou~-%42Sw(6fyI@5SXB#OAfd<`2>AMc7hlIe^2}M7=PxQ5M!_YbG8*oG{|cWG3cn z-(^;4-`>v6b@--@D!R6VZ3CgEFP9=o@gy3qmEg3u$Rj(wX8#>mW;cYiB)X5rCkS2# z{3tjIGW)SZ(*?Iwg3rmPPGCC2hfsJ@wq*%F4eoh%{_xIoQ&w&gD|YU{jP$GCX?;B9t>ghkU)f$yOg9qq+E=t4)E9VQnSWoA_LZ=j`pK`=di+aJna% zQz~Mx=3|7(e)1cK{Scvr57Ce3YSgixgFm&0D(#e_1rMqzm`zxI>8o)gRs$awr+p^2 zg@`kU3pzi^J5Iw3PAhinp$))b&6jefbxUtHio3n+y$`!k5C))C(_F4jOh3vs(*r7xbn4MA61^O;646(P2K~h~DQ++WPUzt-y=euFgrND=pDxt&;J#N4=N0v~P`3x6ekq zGi16}Ws84Hn1lsft6))^RGuYzhnhsHvCN@QG`7Civ;DmaZjQWv-#ZeSq8z2xVG;C1 z8_Qe6vOnO}_7$8UCz-R3)zA_AvzM+}5okINe2(F7W)A}`{k~4pGkzxJNL-4^`Y3y5 zrX9n!5vC_`5M-WB_9m;xqTj;kxgT4MFfxwV!BMeL+N5VD|sq8JU53Ct71yKu9C5cPJJI0PRN+r04EKn{^c$HT)9Xr zz9jpSOOM+@6yY^*67z;D4fn?g7ysh?s=n_^>uP2vbA1^e{4bhJ-a#AJb8eG9x)SWI!S8pBwE)_}2zy(Q2f zwOUTf@N|v)eKW7iD{(grlR=DPffWsZC(kbeg_%i(AB&F=E7Vm^?UCOc8-3A!>lwu? z05dXtX;ppHR?u^VeEXSVyQQSr9{saM6QE<(!{2Fha+#0ASfH2o;}jwNzx54wHc5U zMdp7-n4FR4cPOo#kvBa1WAvM1BJHO{jrYPaavMiJT6=qgR|k}idSzREm9We66jrIm z=PDmc`Yrdjri^ZRq}r+1oq2g69N)vx&S6?OACsqc9hwY_c$D>^D4ioyQwco{R^pbv zJm2iPbPY)7EE&3)!|Z<)vC;!bws6DpIH{(^C*}2=gpE3PKFdY{KDO23oBS^GlI|71 zF`6NuBL5LYS`lG2ho|ISZ(d2NESEnS(S|r8o<=7o3Cf2NB6Z=Z_uFtx?(c|Hv^;%j zo;fs2$bUJ5H|4>48wFp_Xg&N{>+?Xp(GT>-n#`3HVk`^!tmiKXyo>*%w_I zI))V(bjFdKvnSv5{Wc_<#@^O&3m=%Q!`+PACpy~pq#Wxg(U0lY!zSejsD2E4b~orF z_abdU^Aj@<8Nsp}1$J^WsVNALMXwKgpnx>`E~xy5jHZD=JegV82#a?~50N|`Iu~pO z!xuRWtIU3j@!;)|f>+3(tYNr>?^;sk`ZP<~ceLUh$Jr9~K5@)j6euS!UdqjHF=W_0 zzXS2edUiRd@dat>{?)F)%uHP4CJyC-7Rs)ENx-pE2!%Y#=bI?IS0z9UtZX!E7QHB%GN?#!^Wv2P-0A zj2EuQ={iy*U}|gn5m?(x#O`Y5H7Y~Y$&|wg?u=*xpvQFeX}DzrjRU)vbN=VYLg zH8KU5LB2roqSI2p$L5{`6#?AS!>ijSLp1E9a6NBCCa6N97}l4b?To%QsX&c;-4p+c zq1zc>JX0qQM>_W_j>9yur6|ICv5~DrKekswro>65y zhj}xd#!Dg`LkJ&xHTlHR$|NEDs8g}@ZSV1EEODPHQ9}0KOr~{`JU6)EgVTjZ5MYQ+ zn)WI)iLqOY>Cs>pj=mE2#@8u}Da&GMIRB@tVy9KCn|LkqX&)K9^UCB0(R%P62{*u{ zy_$XJ4e?JjIy7HgV7Brko8llmJcNI5c-ES&?Lu7@?U!z9UILU~oafKUXT6X>dEXUr zj1n3v@>rt6P88&EUy}_JGpzTV>HcH(q>KxO{3i2{MEojEcR0GJXGx9Tnp7%p0!3Vp zVqYvS$GoFKFexlwzf$^u>m==^A9@5l0mpc0dyF7DVWBN~8u6458)u_^^euMsC8Qsz zexUY=o>H? zjQHHMg70e9uIqTymJ;=i0t^!(^HI|zC{cu~;k2S)mY9LeW9kScCFI)~ITN+l*z^=R zi?itNoy&7+-SBy^Fs}YZ6<_W|QP1I&PgD`-0letea!^+jdPIcc`5uUTfG8PW6U|Op zHGlfBV)F`-x|E*AkT9sYZ0b!Tdq2tO3o>P_Hs`UV+14#D{xom$ui~{IhN2;y4O-zN zIxC(bJ$-U-Hrj(p58PNgCNGMsQx>LfhXe+N0{Ke&MK<|wBZkoLwec#Hy%!x+a6SY& z9Bkj@FM7c+*4mws;MEyVb}tf?1)jl%c6hW12rVOIQB9cbILEvxDE*o@`Ps0Azue7;gO}{CtZ{RFFKpg< zn5(OwMn9a_T%~uK#|E92{aWqkR8kSc_LdYJV7|TDyVXoPhpbiR2}VA%mWo=zn4t4+ z#JA^mB2qANV^a*bC^!)COCSxAuugn4RrtLi8E}TI{9boO7j@5 zr~br8KErHcSepcBpUiF3r>*)>wKnSBk)m;SYd?i|@7CNcRP=u`qri&2DO^i;;g4?f zxv{5wxfy%1K9W=;x|=*V<(`Hv>g|}Hf3>#z=v}zHFST;(Rd&fhYU#$Co>Ec_H%Zmh z-BmpaHc^s_DnBvQ4Dn>6<&w_m*;5lG^)j%YuHB%G=hai-6}DJvVOrrUkh z?*{SCU-#6a2A%p)_F4!WP+1b6H!*1(iD(3B{}7I_fYd&&NDyw9H2lV56+Uo|b!lZ0 zPur!0DBRH4+*gPtUDpBqn-&r(Y7FeJ5m)oO45eX~n?D2t_ir$A9t+L;UEVoecda~r zQ-6x|V6y^&>-l@v=^z zFfHQ3GP6u@>TRmAr7k<`q$xV~$~kJ({$yM@_H=rqrtJGx!R8kYq9{hT`nqel1S>rr zdCITOd`Y@GtwdS~zP+Ezv)q9Xv{i2uz_!WE)kOEVoUS`2Gnn?>7FS>s5*9He{afudISpy5FYtW3{|e zo<(No*sCh zluzLMhv@qpT((ryqp(+yGc@W3Vi$Q-J0qJ$OifrX0Z^0&lKgrQtUlGZ$#-l>Kt`Fo z!Z}dQkmME!0vQq;kTlj-EPC&FgvA(q;&11rmDiQ>rjnSfKzoH3RlLZ~rFQ3eZv7>% zNl^DU2t%V9{E+lCyPhLoZ+f!>(paq_(oza-NG%NWd1#^Ed@+Ux^DxA+M>QqHC zq#w+ryj8QR7pcT6mt%AN<8rx@#z5UD%B`;&AB;NMAo|c;I88kfh zWf14#XujvwUz4%eD#8?HC$Z_x>oE(A>Ja@hWhFC6&W)$p$g?yWF%YO#$d}1^M1%a| zVh11c>`6QH%86fJXGpzmKx+7;6=t0}%MkP-^O|yvw1)bQEYGW4lBct1ZpZ+Xe_xzO1d z2|MJ{o?)%{QQ7!QaKfc>W>>yTitbHPzXAW{8Vi{#nJeSUY)(VF%fuQnN$Vc!YY05G zkFaU(>a9bsf`?lbF}UoT%ub3bm5Zn!Y4Ct`RS6_~MF1?Tcp|f~o1(MS>HVMoFxfc# zaCart*D!3%2RH$~Ez{Fs(|P zaztP%Mlm2@KulcfKq6GpnXzf=i~92td(6;8eE9B;^{H6GRIHp5%iGeUe68d9+^5#K z?k!cfq1|a+Ur8J5jiRy5j?fU|vO1qWb)kaW$gO5Cw` zoA?B?llqZhH}5(VGM5?oC}d_XIcsvVnt2_@!*1{>|J}uFj8<1PDyG8ujp+LBlcGC2 zo>Fb`_#&NG zvOi%@Kgp-uy=Y&V6~Pn6;{&!ckwgipPqh5#)_0mz_=+EJ(dK0rn$Ezztz}7lK0AB- zHu$x1#g@`X16Dx?3;A8!7juY?5%c{0j0E)Zy}oS*FdAdG+)8mZ!NMgo88({zPupM0 zj$chx&@a%^nVw|Xx$FWT(lceELQxpQmd+aqNlKJ+g%T}{k&(mpg}Z}jgi^EL1SjUrR?6*OMTM`Xe+X_n z(f(O1QNYn`PG~F^I@XvNJrB86W_E-mJ1Wg?Q2F|!KA0D-R2ah!B$T5=hXn7-S^5U3 zjvt@p_ASf=RQ8y)e+|Zt?@x8TkMZBU==mVx5k7fxI)qN2KbR!;?ozm|!cf?z!xyJq zahjoNpAsC6L+SStz*yeG!8kB%v~#pSbIpL1yukHXRb8gL>(oLmX!{mrQqo%ygF;Qp zFYKF5&wI=ja7A(-VcpwHwH?cR^L9xcqrtqB>K4@T8Yd6vhnYh^XugF~7(Kh>(?Khk zqKQAbhwCs>bR3*z5d1#?O+d20JjPl#__H5nK0N09{PpY|cTKqOPqAC7p;%{#7w)BwgdFoF zy~l%!bMKLZf%U_~y7k8%;pSUJ>;zYam^6t#BIfYX_U})#u{Qo~7!aj{s4^?r-v%ip zZgwFtC~!)KNS|4WzQ#VCHx8pY-VQEO7d}xt*{=KrQ4dD1&7|J62fk=Smdugh%UaLb zX15_C+wqLvO4VgibD^~T{(d;}KO0!KY_!c0idEJVc4R@pfHbLu1_r1r$ieu9V+?+l zWINz6{DT&Na%nBWFll0K%*KCB^(+D(O{yi8O0uVY;NKV)queXT-x+Nm8O^Nl|_bf8py!{Y~Wn z57E0l;Y0~Ty@O5Qp?2r+Wz;c)mLFHKGXM&7LrCd}cdolnD+PSfcTn#O@rgd^m}m7K z)}?3|{s@}$q+1ofy0vyt4hp$O!V)i<9ymfa@(1^-`BBhZ06?U3FD*c%j*SrLzb1u= zDHEE5>MRN;K|LFJ?v4h;~e0ys}GL3no9X4WG^LC?GEb}_3SvC z$^F2id*7)9BMm}zoGlEclZq!45C z-|v^!P*RT9Aq1;!6~lK}aNxdU*-V?uM{3xcTtLA44HO}M&t>PKxS&`b&*KYI1Tb{4 z!BOD${B#enaZ0)7=2frc4{R_K&3pm8ZhnM_9EZ9RRB~F1jW1`QYXcSSM8j|o%LV_% zi5}{o1@SPN9a*`(cddPm$Sd9?7jlyOUk<{)iS_22a~YjtB{{zl>-g-8xGFCfJJ%}Y zL%8cld>Y!

eah74QF)6oGi}`y31<^$MrF3G)VedsvK>zzpjbSK&K*Vm|Y8TsY6r z(;ROr$6mQd6o~{PQjPR~2_jKEh$26}a8n~zLrnHi4*V6Rf}+RCl;s!y3q5jt>;c(z zBwo+B`PT%7`X_gBaYWvLb z-gi_*4IO}zKJ^|6@bC|R09m1pi}ZVmEQ6!%SaFfYyT}#8+n2;y3bT~@XppAZ%@v0? z0P60?KG3l~ep3P#4w`6T(h6&E52SAx=h|g(UiL~>071{jn`bCh?lstww@l$oyO{O~ zwxbcXQP%xjUNwQc-`bhlnPM@(8z2?Bp#0M)uu=_sv;3F{)*l0eqCU~^rAF?$=a*-s zMfa3EvnKMHewE6KR^%?olfz$0b7O?bTrr|Fh$EeP{(cnls8zsymcJo;Y^A z{*?+MILuF<6~Wr4+DNiNM+z~UVfGKCIh=;VbSzY}OYH6Z@gwH-ZKehqgC(6cs&aI( z%4c1+{`5e_z3)XHI^Ye|s?Os*Rz5wz#RI@A=>rv(U6>=oTLJWip6~L|o^zZ2et8g^ zYef>CVg#$;gJyqJ!(JEyYMyrfwOL80tMqs?c^?%@LVc(c0?$#}FQS-l6L74~hOmeF z=gdI_Vj!9UOnRlW>q+Atzh!F1^h?itkLvN6NQ+8)|ci|;9aI~G+=m$F?NIWXkdkV@L z!($N!N8a1ORDMnl8rAasMKMZ8P*0j;Zx1mK8A70-!`cnkhbX0)pBB; zSpFfPWC4G96PG4sicd6EX0}R_e+p;2QX3Gz_^<8WR^aOiHYhi=0+{xZ?idGJ<_3j; zR~?N(-d&J9Pd|L^)`$!}b+CEFNWywT2B9atOL1nAga7QWgI(G+!ZGk{H!(4(fTKi~ z8bs1Lg;L{H-Z*Y5a`~g(AXQ8{)rbWk!L98*K}SVKvPwRN_r63o43obaXiT<`k@}U% zXIqHx5wM3L!&t--b(Er0uDPuc82j+HM?bgn`<q6b33Y@9AJKmtODu;*!ih|GuLK^|DM4&_^^TK`FA% z0d{APzzctCBdq$iTvUZDNRpCuL`uw6k<`9;gif}glQKFqT$D|&;>9(b@$4yubOe{Gjai$z_nQUOrCybq{ z6boNzMLHhqN%g{IAJzM%Xin-Gh2xaD&{7aqhYtF>mp>j!veRfp(Fr+iBq{dU?3NP< zh~y`W-ewm3h78K1Kq4K*w&rO?Ln~~Stj?>hKY58H(K~&WugIg**KZ=#e0mqz`yAFZ zna36E*I9>PlcrA_btyjhMw(lJAZ!>-(Ok-aMM&Qu7QFiu!O?Dp3iq5=kI$^M z63kwLzkDgLDx#wsW(<4~Jws?j#bE?sZI3lv{^C-27`wy7T^zXkRmBJEtWn!}C0*-1 zImqVL>0~m`Gir|@1$1iHND!L!egJQ@mkNLJgvE+iLwK)Wm`&4A2Jq9Mng_;Z~@ zzG>donR{t7;LU;D@g6B0%P`<@$7~kI(kY;ucl)&Xp%**Vs>NW#XX5(W6+Q~F zN%yc24F3&U`~cr%kCtsv^oS7Bu((l{L$wu^eRY3gv)G%A-dc(8Y228}#YpJMgbkSm z93N^tFXOjwT`ubWG zk@LTi}S{5Q;VN+YL|8gb1XvGT&>7?e322svCzresddO{k8`sup6(qJXe%1+yn z{#(kDd>pv={-W{)A^Z6jUs@8YEdE4-SVnsyn3k%u1cxe?br3lL9l1wB&#n3_^|~qE zLEo52CA6hoRv7;8S%z)D6zMC`p!^DL{+G*XlB=BKsRrbTMPCIv*hZu|ELMOzf75q5 z!+J%DKUpFa5W#hXB_?g&ifg54eAapRY6UbAjveSJqWwZP?s~vH+9`<$v=X2S(ktQ{ zD=XoMyhbi4+MpeB?a%sJCUKU33!tTT*7sh}Tyu=M|1WM9v2*#9Rib$jNl|- zwtjJ{2WD0G`f2qj=s>zB!8QKeMd=(G=Pc!c=q_)o&MA`5A{hH|&m3^9sI=R7dNQ}mF3-B79c&SIIFhBgT)mAJ|;g9%Um zmxH?1@kNT&-$3xp*W07DRX9>_2snEBt8$dD+!kz&RkJY4GLQZeSocgbU5W{&Gv4 z11wtGXy8?Kn*6L>2u<1l*rv3D{7A5k2XgR>m1J-}7=I5vL?s14QhJAc$*Jp2`WvT~ zbRPS1Sz(0&+>Go=7!azZM*?$@lb{M6B^E=bym|Gn0`DThlrpbdZ!(?ssu7(<5#x6WFGJ(8E6^66EP5QMums03hExgydC15t zU^jz2`m-WRgX8Ba{;f_+ptu1i0`NhS3c#C0crXT6t#@?CbOtl+89cz9e`W27`73%+ zpybXtOSi(&f-UKiTwuF8Bb z`CQQKU@aTLHolAL67`(^EGHHY3UU`_*8j3mf4eD7D6;{t9QIg$2z%?6SXJ>X^LzI| zLV4&d4~H!`w=QhFHRQW?t>pTDytz!E@t!_!b=hE; z*FihDN$VsQpSX=04S2^TQjzieRA#t%vwuAIpS>qh98iQu*?6H}E{AuNeMj9AXmgPj{KS`C! zfSzH;1K9k{lWHRy&SFL1u8gwd>@HWk7o4*Q>mf#s4?HhcyNtNj5rOBXV6B+55ZS=C7AyDIfY{=W6QT_DDOZllDC_R44E;x;HMbO zMdHJ@ZRAKcN!Py7&6LWw3v(ELTf9}#{~g+l?{6mKXbrPH z*vbN?Uwdq?$*{dTfGUfi(7lcDl~T2}zLgAw#W%EJOJpF#!8^{CGjc!tT2bY(mm@xR{f-eo$lT zL8x@Qu^9IS<~ttCg$9Z?UDCb7`BfQnArwdQ_!1h2!1VcdvZRjgN3NEX0N~OL35OQS zB%`Fbzoh)!JN0TgIsaXy9+SK*n9&AJzXJpaT4|N~;U1{@C4Op!u)2*n!9gS3#6kQz^8J^D zyxhaon6n9|nR`t$E_f2eth{CV1R4khj61*XYI&+`UcR(lI`rN}Alp?_fto{FSS@M% zu%l7SN>`t)thococOUUA`BAt;H{cDuA;>#rrWgS}cc3L|&`B{2(3da{v|mS3E7>~S zl_WGqA~csyC#@YBdazLXGSI#*$o!elhjqeMFls(4UvE_3V@GN1NhK0sN`u_49%ZZ^J3M6zeA7A%Kn^m<@CPxUJQ~M*;`Cvy@`POUUt= z6`lqWNCul!g4Z8qhllr4Z^{P}ZV&U={H;YXYB+rt)G^W)aUN#vWQZPd)snR(cj7CkAG|cOj-nQA!xRhtOQ&4 z;*jCFn4cKA8&$w-rRSChRmnQDk9mGWZIGs^0zEH~wclifV=mlF!d?X`imi_kGC^{$iNizjPqBZVSD z?}$+~k~tvr{`|!Xkd{?>(w!LByzB*P#{9KxhcSt*`SCMk^L$t{=mx|*6}?>>>u}SNBzwOc4L1 z#w*r7;D9r>>L&gGics^ky$$SBfl~cR7$V)l{Q%+4EPB5wdW=lh@`x}o>xhDR?wh+^;Sn&D8#;Fm_m>@%qz876HjMTNHxIBD^ zAXp~*N<8{jjnZRd=oR!aJAPOO5Rl!wq3s*qduV*yQDD_5Si{ljjN&GB<;(6e&Kp@~ zx;@Z>Ma_O&lAN!Z2prbv(jh-_p_`s|KWX*#KE%bsiqPa=VHOrH-gQ(xEK}vLF#~M5 zeeafg-y{z(&(ZSXt4Cj*1GCxY_6PIOU{Fcwm;8GY#v`!~Fz2MFR+sknsA(~q80XLI5MeX^NSO7Rj2sssFGA4+`Gf;n zQar3F4sY{7Vz4XB3H;WzMUapy1qKdDDvwDydcR7d7=Y0>XiV1Y5L|5-CrUKi&m0w(-R|9@?as_vxl zUd)ERT`{Op6AWi~rC*#LFh!VN_97oayNZe;E#-zIvcA^>q%D@xH(c{Z_8qq zW7S4%16y)AeOnEwmsVU>9A*y z9Cfrbn;9WgPUFy`h>47rre;N1F6NWR54-bw~!n z%Ql$6X9Q9x3B23nVOb#wd7EpU`hA(;Ak)o3cwb37hbAl0Btbwy+JKHrWn}5PaF6E| z|Bx@GJ)VotD_KwerBO|!W)r%lfl!6);8}j4*3d{LKWj?F&jLO=HN=BJXWJtFN`iPX zHhVZ-(#cFaLE(a2kl2m%4srKhJ^ue~?5(w5e$bB2ETGCl)lMoDw%WM7qa`QN&fDl% z!1ujcY6d^)RlSmizWlNFTJ+9#_`8Var8Vkcr%-?&Z3fmYgT;NSsQxUn7ZW2xQ_E#g^4EbmJtkX1iBO*7JNa*<@LBNjll$ehDh;5V(9A?macK zi>3*?(7%}~id*ynIAvXFrkeBqa)pj5N1zmB;2%sL(&Y|yWUkzGRCQ(z8vj`LaZTu> z+a3fTdwKlkHsX`p#lRgSjr-kOQO&hB6V9A=57Lr1{6N(ewDt?Zv=p#Cl4nbEiiJ?j zI(QLcu~s!gOh%E`mavk#o$U5X?q{0?>#KaKSUYvS_iewmEmE)8XV7+^RbJ9x7}rbv zM<+os1>~^UPed0SNY8R0+*J4hZ*-IplTKl2f0)#friL)l?g3#hMgieGnyh z?6NW+3Ry6*6PT;k(mPc`FWd!BpC_a9@+L%(TT@$n^kgj4copQjuQOXJ>&J#mR7CQ3 z9VWi6w+}^$04d?j5v9dht&Ko6gPZwnb&zC06f9OLZqktMt0~?4q%eA{ zIJFE8RVHC2p&%A-I3f;*!`lRz@%}fKhu#W%HG8*oN$|!@qKkPQ^60iHL8w~cbjQ>6 z7&n9*UxC<{!&&1Sk7)b)qeNPb6e2KU69Jym>(?7mqjQ7 z>Cp;MfC&|wIQR-RRt@a+oN;W+DGk{XwJK=L`~H3?>alo5N zMp#naC)Ju1h*f32v`QSDkIkosBCkD+K#CRkj*rx;Jd@Zvp}oD1*^_Cjajdc`9R2lD z0!*T^v)DSI`siNCic5x2y;7AFRvoJ5NWKjYj>~bLgh;q4gwCSJ@82_3_%tGwjxv

?Z-w|(kmlO*!j{I5QmEbqW7K> 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 -/// -/// 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 NON-INFRINGEMENT. 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - - - -// Color variables -:root { - - // Default color shades - --md-default-fg-color: hsla(0, 0%, 0%, 0.87); - --md-default-fg-color--light: hsla(0, 0%, 0%, 0.54); - --md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32); - --md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07); - --md-default-bg-color: hsla(0, 0%, 100%, 1); - --md-default-bg-color--light: hsla(0, 0%, 100%, 0.7); - --md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3); - --md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12); - - // Primary color shades - --md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1); - --md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-400)}, 1); - --md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1); - --md-primary-bg-color: hsla(0, 0%, 100%, 1); - --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); - - // Accent color shades - --md-accent-fg-color: hsla(#{hex2hsl($clr-indigo-a200)}, 1); - --md-accent-fg-color--transparent: hsla(#{hex2hsl($clr-indigo-a200)}, 0.1); - --md-accent-bg-color: hsla(0, 0%, 100%, 1); - --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); - - // Light theme (default) - > * { - - // Code color shades - --md-code-fg-color: hsla(200, 18%, 26%, 1); - --md-code-bg-color: hsla(0, 0%, 96%, 1); - - // Code highlighting color shades - --md-code-hl-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5); - --md-code-hl-number-color: hsla(0, 67%, 50%, 1); - --md-code-hl-special-color: hsla(340, 83%, 47%, 1); - --md-code-hl-function-color: hsla(291, 45%, 50%, 1); - --md-code-hl-constant-color: hsla(250, 63%, 60%, 1); - --md-code-hl-keyword-color: hsla(219, 54%, 51%, 1); - --md-code-hl-string-color: hsla(150, 63%, 30%, 1); - --md-code-hl-name-color: var(--md-code-fg-color); - --md-code-hl-operator-color: var(--md-default-fg-color--light); - --md-code-hl-punctuation-color: var(--md-default-fg-color--light); - --md-code-hl-comment-color: var(--md-default-fg-color--light); - --md-code-hl-generic-color: var(--md-default-fg-color--light); - --md-code-hl-variable-color: var(--md-default-fg-color--light); - - // Typeset color shades - --md-typeset-color: var(--md-default-fg-color); - - // Typeset `a` color shades - --md-typeset-a-color: var(--md-primary-fg-color); - - // Typeset `mark` color shades - --md-typeset-mark-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5); - - // Typeset `del` and `ins` color shades - --md-typeset-del-color: hsla(6, 90%, 60%, 0.15); - --md-typeset-ins-color: hsla(150, 90%, 44%, 0.15); - - // Typeset `kbd` color shades - --md-typeset-kbd-color: hsla(0, 0%, 98%, 1); - --md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1); - --md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1); - - // Typeset `table` color shades - --md-typeset-table-color: hsla(0, 0%, 0%, 0.12); - - // Admonition color shades - --md-admonition-fg-color: var(--md-default-fg-color); - --md-admonition-bg-color: var(--md-default-bg-color); - - // Footer color shades - --md-footer-fg-color: hsla(0, 0%, 100%, 1); - --md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7); - --md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.3); - --md-footer-bg-color: hsla(0, 0%, 0%, 0.87); - --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32); - } - - // Shadow depth 1 - --md-shadow-z1: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.05), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); - - // Shadow depth 2 - --md-shadow-z2: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.1), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); - - // Shadow depth 3 - --md-shadow-z3: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); -} diff --git a/bbfd/docs/css/extra.css b/bbfd/docs/css/extra.css deleted file mode 100755 index d3f7b61e..00000000 --- a/bbfd/docs/css/extra.css +++ /dev/null @@ -1,2601 +0,0 @@ -:root { - --md-primary-fg-color: #101010; // Color: Black normal - --md-primary-fg-color--light: rgba(0, 0, 0, 0.54); // Color: Gray - --md-primary-fg-color--dark: #000; // Color: Black dark - --md-primary-bg-color: #007990; // Color: Petrol - --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); - --md-typeset-a-color: #4051b5; // -} - - -ul.md-nav__list { - - font-size: large; - color: #007990; -} - -.md-header__button.md-logo img, .md-header__button.md-logo svg { - width: 8rem; -} - -.md-tabs__link--active { - border-bottom-width: 1px; - border-bottom-style: solid; - border-bottom-color: #007990; - font-weight: bold; -} - - -.md-tabs__link:hover { - color: #007990; - -} - -.md-tabs__item { - display: inline-block; - height: 2.8rem; - padding-left: .6rem; - padding-right: .6rem; -} - - -/* -Theme Name: Iopsys Web 2021 -Theme URI: http://www.wpbeaverbuilder.com -Version: 1.0 -Description: Custom built child theme developed for Iopsys by Crescando and DevHouse. -Author: DevHouse -Author URI: http://devhouse.se -template: bb-theme -*/ - -/* ======================================== - -───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── -─████████████───██████████████─██████──██████─██████──██████─██████████████─██████──██████─██████████████─██████████████─ -─██░░░░░░░░████─██░░░░░░░░░░██─██░░██──██░░██─██░░██──██░░██─██░░░░░░░░░░██─██░░██──██░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─ -─██░░████░░░░██─██░░██████████─██░░██──██░░██─██░░██──██░░██─██░░██████░░██─██░░██──██░░██─██░░██████████─██░░██████████─ -─██░░██──██░░██─██░░██─────────██░░██──██░░██─██░░██──██░░██─██░░██──██░░██─██░░██──██░░██─██░░██─────────██░░██───────── -─██░░██──██░░██─██░░██████████─██░░██──██░░██─██░░██████░░██─██░░██──██░░██─██░░██──██░░██─██░░██████████─██░░██████████─ -─██░░██──██░░██─██░░░░░░░░░░██─██░░██──██░░██─██░░░░░░░░░░██─██░░██──██��░██─██░░██──██░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─ -─██░░██──██░░██─██░░██████████─██░░██──██░░██─██░░██████░░██─██░░██──██░░██─██░░██──██░░██─██████████░░██─██░░██████████─ -─██░░██──██░░██─██░░██─────────██░░░░██░░░░██─██░░██──██░░██─██░░██──██░░██─██░░██──██░░██─────────██░░██─██░░██───────── -─██░░████░░░░██─██░░██████████─████░░░░░░████─██░░██──██░░██─██░░██████░░██─██░░██████░░██─██████████░░██─██░░██████████─ -─██░░░░░░░░████─██░░░░░░░░░░██───████░░████───██░░██──██░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─ -─████████████───██████████████─────██████─────██████──██████─██████████████─██████████████─██████████████─██████████████─ -───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── - - COLORS - - body text # - - gold # - - petrol # - - grey # - - FONTS - - default body text "", , ; - - h1-h4 text "", , ; - - h5-h6 text "", , ; - - buttons "", , ; - - forms "", , ; - - CONTENTS - 1. Fonts - 2. Global - 5. Landing Page - 6. Standard Page - 7. Slick Slider - - ===================================== */ - - -/* ======================================== - FONTS - ===================================== */ - - -@font-face { - font-family: 'Madera'; - src: url('./assets/fonts/Madera-Regular.eot'); - src: local('Madera'), local('Madera-Regular'), - url('./assets/fonts/Madera-Regular.eot?#iefix') format('embedded-opentype'), - url('./assets/fonts/Madera-Regular.woff2') format('woff2'), - url('./assets/fonts/Madera-Regular.woff') format('woff'), - url('./assets/fonts/Madera-Regular.ttf') format('truetype'), - url('./assets/fonts/Madera-Regular.svg#Madera-Regular') format('svg'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'Madera'; - src: url('./assets/fonts/Madera-Bold.eot'); - src: local('Madera Bold'), local('Madera-Bold'), - url('./assets/fonts/Madera-Bold.eot?#iefix') format('embedded-opentype'), - url('./assets/fonts/Madera-Bold.woff2') format('woff2'), - url('./assets/fonts/Madera-Bold.woff') format('woff'), - url('./assets/fonts/Madera-Bold.ttf') format('truetype'), - url('./assets/fonts/Madera-Bold.svg#Madera-Bold') format('svg'); - font-weight: bold; - font-style: normal; -} - -h1, h2, h4, h5 { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - font-weight: bold; - margin-top: 0px; -} - -h3, h6, body { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - font-weight: normal; - margin-top: 0px; -} - -h3, h6 { - margin-top: 0px; -} - -h3 { - padding-bottom: 10px; -} - -h1 { - font-size: 28px; -} - - -@media screen and (min-width: 350px) { - - h1 { - font-size: 30px; - } - -} - -@media screen and (min-width: 768px) { - - h1 { - font-size: 36px; - } - -} - -@media screen and (min-width: 1024px) { - - h1 { - font-size: 42px; - } - -} - - -/* ======================================== - HEADER - ===================================== */ - -.main-menu { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - font-weight: normal; - letter-spacing: 1.2px; -} - -header.fl-builder-content-editing { - background-color: #000; -} - -.header-container .fl-col-content { - display: inline-block; - font-size: 0; -} - -.iopsys-logo { - display: inline-block; - max-width: 165px; - vertical-align: top; -} - -.main-menu { - display: inline-block; - max-width: calc(100% - 165px); - vertical-align: top; -} - -.main-menu .fl-menu-mobile-flyout { - background-color: rgba(0, 0, 0, 0.8); - padding: 0px; -} - -.main-menu li a, -.main-menu li a:hover { - transition: 0.4s; -} - -.main-menu .fl-menu-mobile-toggle { - padding-right: 0px; -} - -.main-menu .fl-menu-mobile-flyout li a { - color: white !important; - background-color: rgba(0, 0, 0, 0.4); - border-top: 0px; - font-weight: 600; - text-transform: uppercase; - font-size: 12px; - padding-top: 18px; - line-height: 1.4; -} - -.main-menu .fl-menu-mobile-flyout li .sub-menu { - border-top: 1px solid transparent; -} - -.main-menu .fl-menu-mobile-flyout li .sub-menu li a { - padding-left: 28px; -} - -.main-menu .fl-menu-mobile-close, .fl-menu-mobile-close { - padding: 14px 16px 14px 14px; -} - -.main-menu .fl-menu-mobile-flyout li .fl-menu-toggle:before { - right: 80% !important; -} - -.main-menu .fl-menu-mobile-flyout li.fl-active .fl-menu-toggle { - right: 17px; -} - -.main-menu .fl-menu-mobile-close, .fl-menu-mobile-close:hover { - font-size: 16px !important; -} - -.main-menu .fl-menu-mobile-close, .fl-menu-mobile-close i { - color: #fff; - float: right; - transition: 0.4s; -} - -.main-menu .fl-menu-mobile-close, .fl-menu-mobile-close:hover i { - color: #00b1d4; - transition: 0.4s; -} - -@media screen and (min-width: 1024px) { - - .main-menu li a { - font-weight: 600; - text-transform: uppercase; - font-size: 11px; - } - - .main-menu li:last-of-type a { - padding-right: 0px !important; - } - - .main-menu li .fl-menu-toggle:before { - width: 7px !important; - height: 7px !important; - } - - .main-menu .fl-menu-horizontal.fl-toggle-arrows .fl-has-submenu-container a { - padding-right: 30px !important; - } - - .main-menu ul.sub-menu { - background-color: rgba(0, 0, 0, 0.6) !important; - box-shadow: none !important; - } - - .main-menu ul.sub-menu li a { - line-height: 1.4; - padding-top: 10px; - padding-bottom: 10px; - text-transform: initial !important; - } - - .main-menu ul.sub-menu li:first-of-type a { - padding-top: 24px; - } - - .main-menu ul.sub-menu li:last-of-type a { - padding-bottom: 24px; - } - -} - -@media screen and (min-width: 1150px) { - - .main-menu li a { - font-size: 13px; - } - -} - -@media screen and (min-width: 1224px) { - - .main-menu li a { - padding-right: 23px !important; - padding-left: 23px !important; - } - -} - - -/* ======================================== - FOOTER - ===================================== */ - -.dividing-line { - display: none; - padding-left: 20px; - padding-right: 20px; -} - -.footer-social-icons { - display: inline-block; -} - -.footer-social-icons .fl-module-content { - max-width: 35px; -} - -.footer-text { - display: block; - width: 100%; - padding-top: 7px; - padding-bottom: 7px; -} - -.main-menu.footer { - display: none; -} - -footer a { - transition: 0.4s; -} - -footer a:hover { - color: #00b1d4 !important; - transition: 0.4s; -} - -.footer-main-section p strong { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - font-weight: normal; -} - -@media screen and (min-width: 768px) { - - .footer-social-icons .fl-module-content { - max-width: 45px; - } - - .footer-text, - .dividing-line { - display: inline-block; - width: auto; - } - - .footer-main-section .fl-col-content { - max-width: 1049px !important; - margin-left: auto; - } - - .main-menu.footer { - display: block; - max-width: 100%; - } - - .main-menu.footer nav { - text-align: left; - } - -} - -@media screen and (min-width: 1024px) { - - .main-menu.footer { - display: inline-block; - max-width: calc(100% - 165px); - } - - .main-menu.footer nav { - text-align: right; - } - -} - -/* ======================================== - GLOBAL - ===================================== */ - -.arrow-icon { - position: absolute; - bottom: 10px; - left: calc(50% - 39px); -} - -.fl-builder-edit .arrow-icon { - position: relative; - bottom: 10px; - left: calc(50% - 39px); -} - -.button-inline-container .fl-col-content { - display: inline-block; - width: 100%; - text-align: center; -} - -.button-inline-container .fl-module { - display: inline-block; -} - -.video-image a { - position: relative; - display: inline-block; - overflow: hidden; -} - -.video-image .fl-photo-content a:after, .video-image > a:after { - content: ""; - display: inline-block; - width: 120px; - height: 120px; - opacity: 1; - position: absolute; - top: calc(50% - 60px); - left: calc(50% - 60px); - z-index: 2; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/play-button.png); - background-size: 120px 120px; - background-repeat: no-repeat; - transition: all 0.4s !important; -} - -.video-image .fl-photo-content a:hover:after, .video-image > a:hover:after { - opacity: 0.7; - transition: all 0.4s !important; -} - -#video-modal-popup { - position: fixed; - width: 100%; - height: 100%; - z-index: 999; - background: rgba(51, 51, 51, 0.9); - line-height: 100vh; - padding: 20px; - box-sizing: border-box; - cursor: pointer; -} - -.video-modal-popup-container { - vertical-align: middle; - display: inline-block; - width: 100%; - text-align: center; -} - -.video-modal-wrapper { - margin: 0 auto; - max-width: 1054px; - position: relative; -} - -#video-modal-popup .video-close { - right: -20px; - top: -20px; - z-index: 99; -} - -.proof-close-btn { - display: inline-block; - position: absolute; - right: -20px; - top: -20px; - z-index: 99; - border-radius: 100px !important; - height: 36px !important; - width: 36px !important; - padding: 2px !important; - background-color: #007990 !important; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/close.png) !important; - background-size: 13px 13px !important; - background-repeat: no-repeat !important; - background-position: 50% 50% !important; - font-size: 0 !important; - transition: all 0.4s; - -webkit-transition: all 0.4s; - cursor: pointer; -} - -.fl-module-rich-text ul { - list-style-type: none; - padding-left: 0px; -} - -.fl-module-rich-text ul li { - padding-left: 25px; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/bullet-point.jpg); - background-repeat: no-repeat; - background-size: 13px 13px; - background-position: 0% 6px; - margin-bottom: 5px; -} - -.full-width-mobile .fl-col { - max-width: 100% !important; -} - -.fl-col { - max-width: 550px; -} - -header .fl-col, -footer .fl-col { - max-width: 100%; -} - -@media screen and (min-width: 768px) { - - .text-left .fl-col { - display: block; - } - - .text-left .fl-col .fl-col-content { - max-width: 650px; - margin-left: auto; - padding-right: 40px; - } - - .text-right .fl-col { - display: block; - } - - .text-right .fl-col .fl-col-content { - max-width: 650px; - margin-right: auto; - padding-left: 40px; - } - - .fl-col { - max-width: 100%; - } - - .inline-buttons { - display: inline-block; - vertical-align: top; - } - - .inline-button-container { - display: inline-block; - } - -} - -/* Search Bar */ - -.search-bar { - position: absolute; - top: calc(50% - 40px); - right: 0px; - width: auto !important; - z-index: 999; -} - -.menu-container .search-bar .fl-search-input { - height: 45px; - width: 45px; - border-radius: 0px; - border: 0px; - background-color: rgba(0, 0, 0, 0); - color: rgba(0, 0, 0, 0); - /*transition: 0.4s;*/ - background-image: url(./assets/images/search-icon.png); - background-size: 23px 23px; - background-position: 11.5px 50%; - background-repeat: no-repeat; - cursor: pointer; - font-size: 0; -} - -.menu-container .search-bar .fl-search-input:hover { - opacity: 0.5; -} - -.menu-container .search-bar .fl-search-input:focus { - opacity: 1 !important; - height: 45px !important; - width: 380px; - max-width: 794px; - color: #ffffff; - background-color: #fff !important; - padding-left: 47px; - cursor: text; - color: #33333a; - background-image: url(./assets/images/search-icon-blue.png); - font-size: 14px; -} - - -@media screen and (min-width: 1024px) { - .search-bar { - position: absolute; - top: calc(50% - 40px); - } -} - -@media screen and (min-width: 1440px) { - - .menu-container .search-bar .fl-search-input:focus { - width: 637px; - } - -} - -@media screen and (max-width: 767px) { - - .menu-container .search-bar { - display: none !important; - } - -} - -/*@media screen and (min-width: 768px) {*/ -/* .home-hero .fl-col-small {*/ -/* width: 70%;*/ -/* max-width: 450px;*/ -/* } */ -/*}*/ - - -/* CTA Buttons */ - -.frm_button_submit { - margin: 0px !important; -} - -.button-blue a { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - font-weight: normal; - min-width: 160px; - text-align: center; - background-color: #007990 !important; - border: 2px solid #007990 !important; - border-radius: 0px !important; - text-transform: uppercase; - padding: 17px 24px 13px !important; - transition: 0.4s; - font-size: 14px !important; - box-shadow: none !important; -} - -.fl-button { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - font-weight: normal; - min-width: 160px; - font-weight: 600 !important; - text-align: center; - border: 2px solid #007990 !important; - border-radius: 0px !important; - text-transform: uppercase; - padding: 17px 24px 13px !important; - transition: 0.4s; - font-size: 14px !important; - box-shadow: none !important; -} - -.frm_button_submit, -.button-blue a span { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - color: #fff !important; - font-weight: 600 !important; - font-size: 14px !important; - transition: 0.4s; -} - -.frm_button_submit { - line-height: 1.2 !important; -} - -.frm_button_submit:hover, -.button-blue a:hover, -a.fl-button:hover { - background-color: rgba(0, 0, 0, 0) !important; - transition: 0.4s; -} - -.frm_button_submit:hover, -.button-blue a:hover span, -a.fl-button:hover, -a.fl-button:hover span { - color: #007990 !important; - transition: 0.4s; -} - -.button-white-border a { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - min-width: 160px; - text-align: center; - background-color: rgba(255, 255, 255, 0) !important; - border: 2px solid #fff !important; - border-radius: 0px !important; - text-transform: uppercase; - padding: 17px 24px 13px !important; - transition: 0.4s; - font-size: 14px !important; -} - -.button-white-border a span { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - font-weight: normal; - color: #fff !important; - font-weight: 600 !important; - font-size: 14px !important; - transition: 0.4s; -} - -.button-white-border a:hover { - background-color: #fff !important; - transition: 0.4s; -} - -.button-white-border a:hover span { - color: #007990 !important; - transition: 0.4s; -} - -.button-blue-border a { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - min-width: 160px; - text-align: center; - background-color: rgba(255, 255, 255, 0) !important; - border: 2px solid #007990 !important; - border-radius: 0px !important; - text-transform: uppercase; - padding: 17px 24px 13px !important; - transition: 0.4s; - font-size: 14px !important; -} - -body .button-blue-border a span { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - color: #007990 !important; - font-weight: 600 !important; - font-size: 14px !important; - transition: 0.4s; -} - -.button-blue-border a:hover { - background-color: #007990 !important; - transition: 0.4s; -} - -.button-blue-border a:hover span { - color: #fff !important; - transition: 0.4s; -} - -.button-red-border a.fl-button { - background-color: rgba(255, 255, 255, 0) !important; - border: 2px solid #f63f00 !important; - color: #f63f00 !important; - border-radius: 0px !important; -} - -.button-red-border a.fl-button:hover { - color: white !important; -} - -.button-red-border a.fl-button span { - color: #f63f00 !important; -} - -.button-red-border a:hover { - background-color: #f63f00 !important; - transition: 0.4s; -} - -.button-red-border a:hover span { - color: #fff !important; - transition: 0.4s; -} - -.frm_button_submit, -.button-red a { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - min-width: 160px; - text-align: center; - background-color: #f63f00 !important; - border: 2px solid #f63f00 !important; - border-radius: 0px !important; - text-transform: uppercase; - padding: 17px 24px 13px !important; - transition: 0.4s; - font-size: 14px !important; - box-shadow: 0 0 !important; -} - -.button-red a span, -a.fl-button span { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - font-weight: normal; - color: #fff !important; - font-weight: 600 !important; - font-size: 14px !important; - transition: 0.4s; -} - -.button-red a.fl-button, .button-red a.fl-button:visited { - background-color: #f63f00 !important; -} - -.button-red a:hover, -.frm_button_submit:hover { - background-color: rgba(255, 88, 77, 0) !important; - color: #f63f00 !important; - transition: 0.4s; -} - -.button-red a:hover span, -.frm_button_submit:hover { - color: #f63f00 !important; - transition: 0.4s; -} - -.fl-button-text { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - font-weight: normal; -} - -@media screen and (min-width: 768px) { - - .frm_button_submit, - a.fl-button, - a.fl-button span, - .cta-inner-container .fl-button, - .cta-inner-container .frm_button_submit, - .white-form .frm_button_submit, - .button-blue-border a, - .button-white-border a, - .button-red a, - .button-blue a, - .button-blue-border a span, - .button-white-border a span, - .button-red a span, - body .button-blue-border a span, - .button-blue a span { - font-size: 15px !important; - } - -} - -@media screen and (min-width: 1024px) { - - .frm_button_submit, - a.fl-button, - a.fl-button span, - .cta-inner-container .fl-button, - .cta-inner-container .frm_button_submit, - .white-form .frm_button_submit, - .button-blue-border a, - .button-white-border a, - .button-red a, - .button-blue a, - .button-blue-border a span, - .button-white-border a span, - .button-red a span, - body .button-blue-border a span, - .button-blue a span { - min-width: 200px; - font-size: 16px !important; - } - -} - -/* Aminations */ - -@-webkit-keyframes fl-slide-in-up { - from { - opacity: 0; - -webkit-transform: translate3d(0, 20%, 0); - transform: translate3d(0, 20%, 0); - visibility: visible; - } - to { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } - -} - -@keyframes fl-slide-in-up { - from { - opacity: 0; - -webkit-transform: translate3d(0, 20%, 0); - transform: translate3d(0, 20%, 0); - visibility: visible; - } - to { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@-webkit-keyframes fl-slide-in-right { - 0% { - opacity: 0; - -webkit-transform: translate3d(5%, 0, 0); - transform: translate3d(5%, 0, 0); - visibility: visible; - } - 100% { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@keyframes fl-slide-in-right { - 0% { - opacity: 0; - -webkit-transform: translate3d(5%, 0, 0); - transform: translate3d(5%, 0, 0); - visibility: visible; - } - 100% { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@-webkit-keyframes fl-fade-left { - 0% { - opacity: 0; - -webkit-transform: translate3d(-5%, 0, 0); - transform: translate3d(-5%, 0, 0) !important; - } - 100% { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - -@keyframes fl-fade-left { - 0% { - opacity: 0; - -webkit-transform: translate3d(-5%, 0, 0); - transform: translate3d(-5%, 0, 0); - } - 100% { - opacity: 1; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} - - -.solutions-page.callout-style .fl-callout-title { - display: none; -} - -.solutions-page.callout-style .fl-callout-text { - margin-bottom: 30px; -} - -.callout-style .fl-callout-text { - padding-bottom: 20px !important; -} - -.full-width-button .fl-callout-button a { - width: calc(100% - 80px); -} - -.callout-container.no-icon .callout-style .fl-callout-title { - padding-top: 0px !important; -} - -.callout-container.no-icon .fl-module-content { - margin-top: 10px !important; -} - -@media screen and (min-width: 768px) { - - .callout-container.no-icon .callout-style .fl-callout-title { - padding-top: 20px !important; - } - - .callout-container.no-icon .fl-module-content { - margin-top: 20px !important; - } - - .callout-container.no-icon .fl-col-content { - padding-top: 0px !important; - } - - .callout-container .fl-col-content { - padding-top: 120px; - padding-bottom: 102px !important; - position: relative; - } - - .callout-style .fl-callout-button { - position: absolute; - bottom: 60px; - width: 100%; - left: 0; - } - - .callout-style .fl-callout-photo .fl-photo { - position: absolute; - top: 60px; - width: 100%; - left: 0; - } - -} - - -/* Inspiration Post Grid */ - -.inspiration-post-grid .fl-post-grid-post { - border: 0px; -} - -.inspiration-post-grid .fl-post-image { - background-size: cover; - background-position: 50%; - height: 0; - padding-bottom: 56.2%; -} - -.inspiration-post-grid .fl-post-text { - padding: 25px 20px 20px; - text-align: center; -} - -.inspiration-post-grid .fl-post-more-link { - padding-top: 0px; -} - -.inspiration-post-grid .fl-post-more-link a { - text-transform: uppercase; - font-weight: 600; -} - -.inspiration-post-grid a, -.inspiration-post-grid a:hover { - transition: 0.4s; -} - -@media screen and (min-width: 768px) { - - .inspiration-post-grid .fl-post-text { - padding: 25px 20px 30px; - text-align: center; - } - -} - - -/* Subscribe Section */ - -.subscribe-text-section p { - font-size: 14px; -} - -.subscribe-form .frm_forms input[type=email] { - margin-bottom: 15px !important; -} - -.frm_submit { - margin-top: 20px; -} - -@media screen and (min-width: 768px) { - - .subscribe-form .frm_button_submit.frm_final_submit { - min-width: 200px; - } - - .frm_submit { - margin-top: 0px; - } - - .subscribe-form .frm_checkbox label { - padding-top: 15px; - } - - .subscribe-form .frm_fields_container { - width: 100%; - font-size: 0; - } - - .subscribe-text-section p { - font-size: 15px; - } - - .subscribe-form .frm_fields_container { - position: relative; - } - - .subscribe-form .frm_fields_container, - .subscribe-form .frm_form_field:first-of-type, - .subscribe-form .frm_submit { - display: inline-block; - vertical-align: top; - } - - .subscribe-form .frm_forms input[type=email] { - margin-bottom: 0px !important; - } - - .subscribe-form .frm_form_field:first-of-type { - max-width: calc(100% - 220px) !important; - } - - .subscribe-form .frm_submit { - margin-left: 20px; - position: absolute; - top: 0px; - right: 0px; - } - -} - -@media screen and (min-width: 1024px) { - - .subscribe-text-section p { - font-size: 16px; - } - - .subscribe-section, - .subscribe-text-section, - .subscribe-form { - display: inline-block; - } - - .subscribe-form, - .subscribe-text-section { - width: 50%; - } - - .subscribe-section { - width: 100%; - font-size: 0; - } - - .subscribe-section, - .subscribe-text-section, - .subscribe-form { - display: inline-block; - vertical-align: middle; - } - -} - -@media screen and (min-width: 1200px) { - .subscribe-section .subscribe-text-section { - width: 600px; - } - - .subscribe-section .subscribe-form { - width: calc(100% - 600px); - min-width: 600px !important; - } -} - -/* Slick Slider */ - -.seliro-slider { - text-align: center; - position: relative; -} - -.seliro-slider ul.slick-dots { - display: inline-block; - padding-left: 0px; - list-style-type: none; -} - -.seliro-slider ul.slick-dots > li { - display: inline-block; -} - -.seliro-slider ul.slick-dots > li > button { - border: 2px solid #007990; - background: #fff; - color: #fff; - font-size: 0; - border-radius: 50%; - margin: 5px; - padding: 0; - height: 22.5px; - width: 22.5px; - -webkit-transition: ease-in-out .2s; - -o-transition: ease-in-out .2s; - transition: ease-in-out .2s; -} - -.seliro-slider ul.slick-dots > li:focus, -.slick-slide:focus { - outline: none; -} - -.seliro-slider ul.slick-dots > li > button:hover, -.seliro-slider ul.slick-dots > li.slick-active > button { - background: #007990; -} - -.seliro-slider ul.slick-dots > li.slick-active > button:active, -.seliro-slider ul.slick-dots > li.slick-active > button:focus { - top: 0 !important; -} - -.slide-text { - position: relative; -} - -.slide-text > h4 { - color: #969696; - font-style: italic; - font-weight: 400; - margin-bottom: 60px; -} - -.slide-image { - margin: 0 auto; - width: 120px; - height: 120px; - background-position: center center; - background-repeat: no-repeat; - background-size: cover; - border-radius: 50%; - margin-bottom: 8px; -} - -.slide-name > h4 { - color: #007990 !important; - margin-bottom: 5px !important; -} - -.white-slider h4, -.white-slider .slide-company, -.white-slider .slide-name h4 a { - color: #fff !important; -} - -.white-slider .seliro-slider ul.slick-dots > li > button:hover, .white-slider .seliro-slider ul.slick-dots > li.slick-active > button { - background: #fff !important; -} - -.white-slider .seliro-slider ul.slick-dots > li > button { - border: 2px solid #fff; - background: rgba(0, 0, 0, 0); -} - -.slide-company { - margin-bottom: 20px; - font-size: 12px; -} - -@media screen and (min-width: 992px) { - .slide-text { - max-width: 50%; - margin-left: auto; - margin-right: auto; - } - - .seliro-slider::before, - .seliro-slider::after { - content: ""; - width: 104px; - height: 85px; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/slider-arrow-gray.png); - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - position: absolute; - top: 45px; - } - - .seliro-slider::before { - left: 12.5%; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/slider-arrow-gray-reverse.png); - } - - .white-slider .seliro-slider::before, - .white-slider .seliro-slider::after { - content: ""; - width: 104px; - height: 85px; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/slider-arrow-dark-gray.png); - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - position: absolute; - top: 45px; - } - - .white-slider .seliro-slider::before { - left: 12.5%; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/slider-arrow-dark-gray-reverse.png); - } - - .seliro-slider::after { - right: 12.5%; - } -} - -/* Seliro Tabs */ -.seliro-tabs .nav-tabs { - border-bottom: none; -} - -.seliro-tabs .nav-tabs > li { - margin-bottom: 0px; - width: 100%; - text-align: center; -} - -.seliro-tabs .nav-tabs > li > a { - border-radius: 0px; - border: 2px solid #ddd; - border-bottom: none; - margin-right: 0; - color: black !important; - font-weight: bold; - padding: 12px 15px; - transition: ease-in-out .2s; -} - -.seliro-tabs .nav-tabs > li > a:hover, -.seliro-tabs .nav-tabs > li > a:active, -.seliro-tabs .nav-tabs > li > a:focus, -.seliro-tabs .nav-tabs > li > a.active { - background-color: #eee; -} - -.seliro-tabs .tab-content { - display: none; -} - -.seliro-tabs .tab-content.active { - border: 2px solid #ddd; - display: block; - padding: 20px; - width: 100%; -} - -.seliro-tabs .tab-content.active .tab-columns { -} - -.seliro-tabs .tab-content.active .tab-columns > ul { - padding-left: 0px; - list-style-type: none; -} - -.seliro-tabs .tab-content .tab-columns > ul { - margin-bottom: 20px; -} - -.seliro-tabs .tab-content .tab-columns > ul > li { - position: relative; - margin-bottom: 8px; - margin-left: 23px; - font-size: 16px; -} - -.seliro-tabs .tab-content .tab-columns ul > h5 { - margin-bottom: 20px; -} - -.seliro-tabs .tab-content .tab-description { - margin-bottom: 20px; -} - -.seliro-tabs .tab-content .tab-download { - position: relative; - margin-left: 23px; - font-weight: bold; - margin-bottom: 20px; - display: block; -} - -.seliro-tabs .tab-content .tab-download::before { /* PDF download */ - content: '\f1c1'; - font-family: 'Font Awesome\ 5 Free'; - font-weight: bold; - font-size: 14px; - position: absolute; - top: 55%; - transform: translateY(-50%); - left: -22px; -} - -.seliro-tabs .tab-content .tab-columns > ul > li::before { - content: '\f140'; - font-family: 'Font Awesome\ 5 Free'; - font-weight: bold; - font-size: 14px; - position: absolute; - top: 14px; - transform: translateY(-50%); - left: -22px; -} - -@media screen and (min-width: 768px) { - - .seliro-tabs .nav-tabs > li > a { - padding: 5px 15px; - } - -} - -@media screen and (min-width: 992px) { - - .seliro-tabs .nav-tabs > li { - width: inherit; - text-align: center; - } - - .seliro-tabs .tab-content.active { - display: inline-block; - padding: 40px; - } - - .seliro-tabs .nav-tabs > li > a.active::after { - content: ''; - height: 6px; - background-color: #fff; - width: 100%; - position: absolute; - bottom: -4px; - left: 0; - } - - .seliro-tabs .nav-tabs > li > a:hover, - .seliro-tabs .nav-tabs > li > a:active, - .seliro-tabs .nav-tabs > li > a:focus, - .seliro-tabs .nav-tabs > li > a.active { - background-color: #fff; - } - - .seliro-tabs .tab-content.active .tab-columns { - } - - .seliro-tabs .tab-content.active .tab-columns > ul { - display: inline-block; - width: 45%; - vertical-align: top; - margin-right: 5%; - margin-bottom: 0px; - } - - .seliro-tabs .nav-tabs > li > a { - padding: 10px 30px; - border-right: 2px solid #ddd !important; - border-left: none; - } - - .seliro-tabs .nav-tabs > li > a.active { - border-bottom: 0; - } - - .seliro-tabs .nav-tabs > li:first-child > a { - border-right: none; - border-left: 2px solid #ddd !important; - } - - .seliro-tabs .nav-tabs > li:last-child > a { - border-right: 2px solid #ddd; - } - -} - -/* Book a Session */ - -.book-a-session-section .fl-row-content-wrap { - background-image: url(/wp-content/themes/bb-theme-child/assets/images/section-arrow.png); - background-position: top center; - background-repeat: no-repeat; - background-size: 58px 29px; - background-color: transparent !important; -} - -.book-a-session-section { - background-color: #e8e8e8; -} - -@media screen and (min-width: 768px) { - - .section-left p { - font-size: 15px; - } - - .book-a-session-section .fl-col-content { - display: inline-block; - font-size: 0; - width: 100%; - } - - .section-left { - width: calc(100% - 240px) !important; - display: inline-block; - vertical-align: middle; - } - - .section-left p { - font-size: 14px; - } - - .section-right { - width: 240px !important; - display: inline-block; - vertical-align: middle; - } - -} - -@media screen and (min-width: 1024px) { - - .section-left p { - font-size: 16px; - } - -} - -/* Steps Section */ - -.step-container { - margin: 0 auto; - max-width: 350px; - vertical-align: top; - text-align: center; - padding: 30px 20px 60px 20px; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/arrow-down.png); - background-position: bottom center; - background-repeat: no-repeat; - background-size: 60px 39px; -} - -.step-container:first-of-type { - padding-top: 0px; -} - -.step-container:last-of-type { - background-image: none !important; - padding-bottom: 0px; -} - -.step-container-img { - margin: 0 auto; - margin-bottom: 15px; - width: 75px; - height: 75px; - background-position: center center; - background-size: contain; - background-repeat: no-repeat; -} - -.step-container p { - font-size: 14px; -} - -.steps-main-container .step-container img { - min-height: 75px; - max-height: 75px; - padding-bottom: 20px; -} - -@media screen and (min-width: 768px) { - - .step-container p { - font-size: 15px; - } - -} - -@media screen and (min-width: 1024px) { - - .steps-main-container { - font-size: 0; - display: inline-block; - } - - .step-container { - display: inline-block; - width: 20%; - vertical-align: top; - text-align: center; - padding: 0px 45px 0px 5px; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/arrow-right.png); - background-position: top right; - background-repeat: no-repeat; - background-size: 39px 60px; - } - - .step-container p { - font-size: 16px; - } - -} - - -/* ======================================== - KNOWLEDGE & INSPIRATION - ===================================== */ - -.breadcrumb-title, -.breadcrumb { - text-transform: uppercase; - font-size: 14px; - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - color: #000; -} - -.breadcrumb { - font-weight: bold; -} - -.breadcrumb-pointer { - font-size: 0; - background-image: url(/wp-content/themes/bb-theme-child/assets/images/breadcrumb-arrow.png); - background-position: calc(50% + 1px) 50%; - background-repeat: no-repeat; - background-size: 5px 9px; - height: 26px; - width: 18px; - display: inline-block; - vertical-align: top; -} - - -.breadcrumb-title:hover, -.breadcrumb a { - color: #000; -} - -.facetwp-pager { - text-align: center; -} - -.facetwp-page { - padding: 7px 12px !important; - border: solid 2px #007990; - margin-right: 5px; - transition: 0.4s; - font-weight: bold; - color: #007990; - height: 41px; - vertical-align: top; - width: 38px; -} - -.facetwp-page:hover { - border: solid 2px #007990; - background-color: #007990; - color: #fff; - transition: 0.4s; - text-decoration: none !important; -} - -.facetwp-page.active { - border: solid 2px #007990; - background-color: #007990; - color: #fff; - font-weight: bold; -} - -.facetwp-page.active:hover { - text-decoration: none !important; - border: solid 2px #007990; - background-color: #007990; - color: #fff; -} - -.facetwp-page.next, -.facetwp-page.prev { - font-size: 0; - height: 41px; - vertical-align: top; - width: 41px; - background-position: center; - background-repeat: no-repeat; - background-size: 8px 12px; -} - -.facetwp-page.next { - background-image: url(/wp-content/themes/bb-theme-child/assets/images/arrow-right-blue.png); -} - -.facetwp-page.next:hover { - background-image: url(/wp-content/themes/bb-theme-child/assets/images/arrow-right-white.png); -} - -.facetwp-page.prev { - background-image: url(/wp-content/themes/bb-theme-child/assets/images/arrow-left-blue.png); -} - -.facetwp-page.prev:hover { - background-image: url(/wp-content/themes/bb-theme-child/assets/images/arrow-left-white.png); -} - -.cta-inner-container { - background-color: #007990 !important; - padding: 40px; - text-align: center; - background-size: cover; - background-repeat: no-repeat; - background-position: center center; -} - -.cta-inner-container p, -.cta-inner-container h4, -.cta-inner-container .frm_checkbox label { - color: #fff !important; -} - -.cta-inner-container * { - text-align: center; -} - -.cta-inner-container .cta-content { - margin-bottom: 20px; -} - -.cta-container, -.cta-inner-container { - height: 100%; -} - -.cta-inner-container img { - margin-bottom: 20px; -} - -.cta-container > a > img:hover { - transition: all 0.6s; - -webkt-transition: all 0.6s; - opacity: 0.7; - -} - -.youtube-embed { - position: relative; - padding-bottom: 56.25%; /* 16:9 */ - height: 0; -} - -.youtube-embed iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; -} - -.facetwp-radio, -.facetwp-radio.checked { - background: none !important; -} - -.facetwp-counter { - display: none; -} - -.facetwp-radio:hover { - text-decoration: none; -} - -.facetwp-radio { - color: #fff; - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - text-transform: uppercase; - font-weight: 600; - padding-left: 15px !important; - padding-right: 15px !important; - display: inline-block; - font-size: 15px; - transition: 0.4s; -} - -.facetwp-radio:hover { - color: #007990; - transition: 0.4s; -} - -.facetwp-radio.checked { - color: #007990; - transition: 0.4s; -} - -.facetwp-facet { - text-align: center; - margin-bottom: 5px !important; - margin-top: 5px !important; -} - -.cta-inner-container .frm_checkbox, -.cta-inner-container .frm_button_submit, -.cta-inner-container .frm_submit { - text-align: center !important; -} - -.cta-inner-container .frm_checkbox { - margin-bottom: 30px; -} - -.cta-inner-container input[type=email] { - margin-bottom: 15px !important; - text-align: left; -} - -#cta-loop .fl-post-grid-post { - margin-bottom: 20px; -} - -.video-container { - margin-bottom: 15px; -} - -.blog-post-container, -.cta-outter-container { - width: 100%; -} - -.blog-post-container { - margin-bottom: 40px; -} - -.blog-post-container .fl-col-content, -.cta-outter-container .fl-col-content { - max-width: 550px; - margin: 0 auto; -} - -.inspiration-post-grid .fl-post-column { - padding-bottom: 20px !important; -} - -.customer-logo img { - max-height: 160px; - max-width: 230px; -} - -@media screen and (min-width: 768px) { - - .inspiration-post-grid .fl-post-column { - padding-bottom: 30px !important; - } - -} - -@media screen and (min-width: 1024px) { - - .cta-outter-container { - width: 35%; - max-width: 100%; - } - - .blog-post-container { - width: 65%; - max-width: 100%; - } - - .blog-post-container .fl-col-content, - .cta-outter-container .fl-col-content { - max-width: 100%; - margin: 0 auto; - } - - .blog-post-container { - margin-bottom: 0px; - } - -} - -/** -* Seliro Image Repeater Styling. -**/ -.seliro-images-repeater { - display: flex; - flex-direction: column; - flex-wrap: nowrap; - justify-content: space-around; - text-align: center; -} - -.image-repeate-image { - text-align: center; - margin: 0 auto; - width: 55px; - height: 55px; - background-position: center center; - background-repeat: no-repeat; - background-size: contain; - margin-bottom: 15px; -} - -.image-repeater-column { - margin-bottom: 30px; -} - -@media screen and (min-width: 992px) { - .seliro-images-repeater { - flex-direction: row; - } - - .image-repeater-column { - margin-bottom: 0px; - } -} - -/** -* Customer Cases Post Grid -**/ - -.customer-cases-container .fl-col { - min-width: 100% !important; -} - -.customer-cases .fl-post-text { - text-align: center; - padding: 35px 20px 60px; -} - -.customer-cases .fl-post-title, -.customer-cases .fl-post-excerpt, -.customer-cases .customer-name { - padding-bottom: 20px -} - -.customer-cases .fl-post-title a, -.customer-cases .fl-post-title a:hover { - transition: 0.4s; -} - -.customer-cases .fl-post-image { - background-size: cover; - background-position: 50%; - min-height: 350px; -} - -.customer-cases .fl-post-more-link { - padding: 20px 0px 14px; -} - -.customer-cases .fl-post-more-link a { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px !important; - min-width: 160px !important; - text-align: center !important; - background-color: #f63f00 !important; - border: 2px solid #f63f00 !important; - border-radius: 0px !important; - text-transform: uppercase !important; - padding: 19px 44px 15px !important; - transition: 0.4s !important; - font-size: 14px !important; - box-shadow: 0 0 !important; - font-size: 16px !important; - font-weight: bold !important; - color: #fff !important; -} - -.customer-cases .fl-post-more-link a:hover { - background-color: rgba(0, 0, 0, 0) !important; - color: #f63f00 !important; - text-decoration: none !important; - transition: 0.4s !important; -} - -@media screen and (min-width: 768px) { - - .customer-cases .fl-post-text { - max-width: 690px; - padding: 100px 60px 100px 60px; - } - - .customer-cases .fl-post-text-container, - .customer-cases .fl-post-image { - flex: 1; - vertical-align: top; - } - - .customer-cases .fl-post-feed-post { - display: flex; - width: 100%; - border: 0px !important; - } - - .customer-cases .fl-post-feed-post:nth-child(odd) { - flex-direction: row-reverse; - } - - .customer-cases .fl-post-feed-post:nth-child(odd) .fl-post-text { - padding: 100px 60px 100px 60px; - margin-left: auto !important; - } - - .customer-cases .fl-post-feed-post:nth-child(even) .fl-post-text { - margin-right: auto !important; - } - -} - - -/** -* Investor Post Grid -**/ - -.investor-post-grid .fl-post-grid-post { - border: 0px !important; -} - -.investor-post-grid .fl-post-image { - background-size: cover; - background-position: center top; - height: 375px; -} - -.customer-logo { - text-align: center; - padding: 20px; -} - -@media screen and (min-width: 768px) { - - .customer-logos-container { - display: inline-block; - width: 100%; - font-size: 0; - } - - .customer-logo { - display: inline-block; - width: 33.333%; - } - -} - - -/* ======================================== - SHARPSPRING FORMS - ===================================== */ - -.sharpspring_form form { - background: none; -} - -.sharpspring_form input[type=text], -.sharpspring_form input[type=email] { - height: 53px; - border: 2px solid #fff; - border-radius: 0px; - background-color: #fff; - padding: 7px 12px 7px 12px; - width: 100%; - margin-bottom: 0 !important; - box-shadow: none !important; - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - font-size: 14px; - -webkit-appearance: none !important; -} - -.sharpspring_form textarea { - height: 126px; - border: 2px solid #fff; - border-radius: 0px; - background-color: #fff; - padding: 10px 12px 10px; - width: 100%; - margin-bottom: 0 !important; - color: #007990; - box-shadow: none !important; - font-size: 14px; - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; -} - -.sharpspring_form label { - display: block; - padding-left: 20px !important; - text-indent: -20px; - font-size: 13px !important; - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; -} - -.sharpspring_form input[type=checkbox] { - -webkit-appearance: none !important; - height: 16px !important; - width: 16px !important; - background-color: #fff; - border-radius: 3px !important; - box-shadow: none !important; - vertical-align: sub !important; - border: 1px solid #717dac; - margin: 4px 5px 0 0; -} - -.sharpspring_form li.field.text label, -.sharpspring_form li.field.email label, -.sharpspring_form li.field.textarea label, -.sharpspring_form li.field.checkbox .required { - display: none; -} - -.sharpspring_form #submit_button { - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - letter-spacing: 1.2px; - min-width: 160px; - text-align: center; - background-color: #f63f00 !important; - border: 2px solid #f63f00 !important; - border-radius: 0px !important; - text-transform: uppercase; - padding: 17px 24px 13px !important; - transition: 0.4s; - font-size: 14px !important; - box-shadow: 0 0 !important; - display: inline-block; - width: auto; - height: auto; - font-size: 16px !important; -} - -@media screen and (min-width: 432px) { - .sharpspring_form #submit_button { - min-width: 200px; - } - - .sharpspring_form li.firstName, - .sharpspring_form li.companyName { - width: 50%; - display: inline-block; - box-sizing: border-box; - } - - .sharpspring_form li.firstName { - padding-right: 5px; - } - - .sharpspring_form li.companyName { - padding-left: 5px; - } -} - - -/* Cookie Consent UK */ - -#cookie-notice .cn-button { - background-color: #007990 !important; - border-radius: 0px !important; - border: 2px solid #007990 !important; - transition: 0.4s; -} - -#cookie-notice .cn-button:hover { - color: #007990 !important; - background-color: rgba(0, 0, 0, 0) !important; - transition: 0.4s; -} - -html.has-cookie-bar.cookie-bar-top-bar { - margin-top: 30px; - -webkit-transition: all 0.25s; - -moz-transition: all 0.25s; - transition: all 0.25s; -} - -#catapult-cookie-bar { - box-sizing: border-box; - max-height: 0; - opacity: 0; - direction: ltr; - padding: 0 20px; - z-index: 99999; - overflow: hidden; - text-align: left; - -webkit-transition: all 0.25s; - -moz-transition: all 0.25s; - transition: all 0.25s; -} - -.ctcc-exclude-AF.geoip-continent-AF #catapult-cookie-bar, -.ctcc-exclude-AN.geoip-continent-AN #catapult-cookie-bar, -.ctcc-exclude-AS.geoip-continent-AS #catapult-cookie-bar, -.ctcc-exclude-EU.geoip-continent-EU #catapult-cookie-bar, -.ctcc-exclude-NA.geoip-continent-NA #catapult-cookie-bar, -.ctcc-exclude-OC.geoip-continent-OC #catapult-cookie-bar, -.ctcc-exclude-SA.geoip-continent-SA #catapult-cookie-bar { - display: none; -} - -.ctcc-exclude-AF.geoip-continent-AF, -.ctcc-exclude-AN.geoip-continent-AN, -.ctcc-exclude-AS.geoip-continent-AS, -.ctcc-exclude-EU.geoip-continent-EU, -.ctcc-exclude-NA.geoip-continent-NA, -.ctcc-exclude-OC.geoip-continent-OC, -.ctcc-exclude-SA.geoip-continent-SA { - margin-top: 0 !important; -} - -#catapult-cookie-bar.rounded-corners { - border-radius: 3px; -} - -#catapult-cookie-bar.drop-shadow { - -webkit-box-shadow: 0px 3px 9px 0px rgba(0, 0, 0, 0.4); - -moz-box-shadow: 0px 3px 9px 0px rgba(0, 0, 0, 0.4); - box-shadow: 0px 3px 9px 0px rgba(0, 0, 0, 0.4); -} - -.cookie-bar-block #catapult-cookie-bar { - max-height: 999px; - -webkit-transition: opacity 0.25s; - -moz-transition: opacity 0.25s; - transition: opacity 0.25s; -} - -.has-cookie-bar #catapult-cookie-bar { - opacity: 1; - max-height: 999px; - min-height: 30px; - padding: 15px 20px 15px; -} - -.cookie-bar-block #catapult-cookie-bar span { - display: block; - margin: 1em 0; -} - -.cookie-bar-bar #catapult-cookie-bar.float-accept span.ctcc-right-side { - float: right; -} - -button#catapultCookie { - cursor: pointer; - margin: 0 20px 0 0; -} - -.cookie-bar-bar button#catapultCookie { - margin: 0 0 0 20px; -} - -.cookie-bar-bar .ctcc-inner { - display: -webkit-flex; - display: flex; - -webkit-align-items: center; - align-items: center; - -webkit-justify-content: center; - justify-content: center; - position: relative; -} - -.cookie-bar-bar .float-accept .ctcc-inner { - -webkit-justify-content: space-between; - justify-content: space-between; -} - -@media screen and (max-width: 991px) { - .ctcc-left-side { - margin-right: 1em; - } -} - -.ctcc-right-side { - -webkit-flex-shrink: 0; - flex-shrink: 0; -} - -.cookie-bar-block #catapult-cookie-bar h3 { - margin: 0.5em 0 0; -} - -.use_x_close .x_close { - position: absolute; - top: 10px; - right: 10px; - cursor: pointer; - font-family: sans-serif; - -webkit-transition-duration: 0.5s; - transition-duration: 0.5s; -} - -.cookie-bar-bar .use_x_close .x_close { - right: 0; - top: 50%; - -webkit-transform: translateY(-50%); - transform: translateY(-50%); -} - -.x_close { - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-transform: translate3d(0px, 0px, 0px); - width: 14px; - height: 30px; - position: relative; - margin: 0 auto; - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - transform: rotate(0deg); - -webkit-transition: .5s ease-in-out; - -moz-transition: .5s ease-in-out; - -o-transition: .5s ease-in-out; - transition: .5s ease-in-out; - cursor: pointer; -} - -.x_close span { - display: block; - position: absolute; - height: 3px; - width: 14px; - background: #000; - border-radius: 6px; - opacity: 1; - left: 0; - -webkit-transform: rotate(0deg); - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - transform: rotate(0deg); - -webkit-transition: .25s ease-in-out; - -moz-transition: .25s ease-in-out; - -o-transition: .25s ease-in-out; - transition: .25s ease-in-out; - transition-delay: .14s; - -webkit-transition-delay: .14s; - -moz-transition-delay: .14s; -} - -.x_close span:nth-child(1), -.x_close span:nth-child(2) { - top: 14px; -} - -.x_close span:nth-child(1) { - -webkit-transform: rotate(45deg); - -moz-transform: rotate(45deg); - -o-transform: rotate(45deg); - transform: rotate(45deg); -} - -.x_close span:nth-child(2) { - -webkit-transform: rotate(-45deg); - -moz-transform: rotate(-45deg); - -o-transform: rotate(-45deg); - transform: rotate(-45deg); -} - -.x_close:hover span:nth-child(1) { - -webkit-transform: rotate(0); - -moz-transform: rotate(0); - -o-transform: rotate(0); - transform: rotate(0); -} - -.x_close:hover span:nth-child(2) { - -webkit-transform: rotate(0); - -moz-transform: rotate(0); - -o-transform: rotate(0); - transform: rotate(0); -} - -/* Email Encoder */ - -span.eeb-nodis { - display: none !important; -} - -span.eeb-rtl { - unicode-bidi: bidi-override !important; - direction: rtl !important; - display: inline !important; -} - -span.eeb-rtl span.eeb-sd, span.eeb-nrtl span.eeb-sd { - display: inline !important; - padding-left: 0 !important; -} - -span.eeb-nrtl { - word-break: break-all !important; -} - -.eeb-encoded { - position: relative; - margin-top: -0.3em; - z-index: 1000; - color: green; -} - - -/* Slick */ - -/* Slider */ -.slick-slider { - position: relative; - - display: block; - box-sizing: border-box; - - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - -webkit-touch-callout: none; - -khtml-user-select: none; - -ms-touch-action: pan-y; - touch-action: pan-y; - -webkit-tap-highlight-color: transparent; -} - -.slick-list { - position: relative; - - display: block; - overflow: hidden; - - margin: 0; - padding: 0; -} - -.slick-list:focus { - outline: none; -} - -.slick-list.dragging { - cursor: pointer; -} - -.slick-slider .slick-track, -.slick-slider .slick-list { - -webkit-transform: translate3d(0, 0, 0); - -moz-transform: translate3d(0, 0, 0); - -ms-transform: translate3d(0, 0, 0); - -o-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); -} - -.slick-track { - position: relative; - top: 0; - left: 0; - - display: block; - margin-left: auto; - margin-right: auto; -} - -.slick-track:before, -.slick-track:after { - display: table; - - content: ''; -} - -.slick-track:after { - clear: both; -} - -.slick-loading .slick-track { - visibility: hidden; -} - -.slick-slide { - display: none; - float: left; - - height: 100%; - min-height: 1px; -} - -[dir='rtl'] .slick-slide { - float: right; -} - -.slick-slide img { - display: block; -} - -.slick-slide.slick-loading img { - display: none; -} - -.slick-slide.dragging img { - pointer-events: none; -} - -.slick-initialized .slick-slide { - display: block; -} - -.slick-loading .slick-slide { - visibility: hidden; -} - -.slick-vertical .slick-slide { - display: block; - - height: auto; - - border: 1px solid transparent; -} - -.slick-arrow.slick-hidden { - display: none; -} - - -.widget_polylang select { - max-width: 400px; - position: relative; - padding: 10px 32px 10px 8px; - display: flex; - cursor: pointer; - width: 100%; - border: 1px solid silver; - -webkit-appearance: none; - border-radius: 0px; - background-color: rgba(0, 0, 0, 0); - text-transform: uppercase; -} - -.widget_polylang select:before { - border-bottom: 1px solid silver !important; - border-right: 1px solid silver !important; - content: ''; - background-size: contain; - height: 12px; - width: 12px; - position: absolute; - right: 12px; - top: 12px; - transition: .2s ease-out; - border-bottom: 1px solid gray; - border-right: 1px solid gray; - transform: rotate(45deg); - color: silver; -} - -#redirect-notice { - position: fixed; - z-index: 999; - background: white; - bottom: 0px; - margin: 20px; - width: calc(100% - 40px); - max-width: 1100px; - padding: 20px; - left: calc(50% - 20px); - transform: translateX(-50%); - box-shadow: 0px 0px 20px -5px rgba(0, 0, 0, 0.3); - -webkit-box-shadow: 0px 0px 20px -5px rgba(0, 0, 0, 0.3); - -moz-box-shadow: 0px 0px 20px -5px rgba(0, 0, 0, 0.3); -} - -.cookies-not-set #redirect-notice { - margin: 20px 20px 80px !important; -} - -#redirect-notice.hide { - display: none !important; -} diff --git a/bbfd/docs/css/iopsys-white.svg b/bbfd/docs/css/iopsys-white.svg deleted file mode 100644 index c201c2b4..00000000 --- a/bbfd/docs/css/iopsys-white.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/bbfd/docs/css/pdf.css b/bbfd/docs/css/pdf.css deleted file mode 100644 index bcae0358..00000000 --- a/bbfd/docs/css/pdf.css +++ /dev/null @@ -1,17 +0,0 @@ -@page { - size: a4 portrait; - margin: 25mm 10mm 25mm 10mm; - counter-increment: page; - font-family: 'Madera', 'Lucida Sans Unicode', 'Lucida Grande', sans-serif; - white-space: pre; - color: grey; - @top-left { - content: '© 2022 IOPSYS'; - } - @top-center { - content: string(chapter); - } - @top-right { - content: 'Page ' counter(page); - } -} \ No newline at end of file diff --git a/bbfd/docs/guide/.pages b/bbfd/docs/guide/.pages deleted file mode 100644 index 0cf2afc8..00000000 --- a/bbfd/docs/guide/.pages +++ /dev/null @@ -1,4 +0,0 @@ -title: "USP Daemon Developer Guide" - -nav: - - "..." diff --git a/bbfd/docs/guide/data_model_integration.md b/bbfd/docs/guide/data_model_integration.md deleted file mode 100644 index 237c12b7..00000000 --- a/bbfd/docs/guide/data_model_integration.md +++ /dev/null @@ -1,326 +0,0 @@ -# Third party data model integration - -It is also possible to itegrate thrid party data model to the uspd to expose it to the ubus. To do so certain APIs in data model library needs to be implemented to make the data model compatible with uspd. APIs are described below. - - -## List of libbbf methods used in uspd to integrate third party data model - -### Refernces -Deatils of bbf data model librabry can be found at [link](https://dev.iopsys.eu/iopsys/bbf/-/tree/devel/docs) - -following are the libbbf methods used in uspd to access the data model defined in libbbf - -``` dm_get_supported_dm - dm_entry_param_method - dm_entry_apply - dm_ctx_init - dm_ctx_init_sub - dm_ctx_clean - dm_ctx_clean_sub - set_bbfdatamodel_type - dm_entry_restart_services - dm_entry_revert_changes - dm_debug_browse_path - get_dm_type - dm_entry_manage_services - dm_config_ubus - - -``` - -## Methods -Description of the methods are given below - -### dm_get_supported_dm - -used to get the complete data model schema in one browse - -``` -int dm_get_supported_dm(struct dmctx *ctx, char *path, bool first_level, schema_type_t schema_type) - -inputs - struct dmctx *ctx - pointer to struct dmctx strunture. The list of parameters will be updated in ctx.list_parameter. each node in the list is of type - struct dm_parameter which contains char *name (name of the parameter), char *data, char *type and char *additional_data; - the content of fields are as follows- - - | Type | Data | Addtional Data | - |------------- |------------ |--------------------- | - |DMT_COMMAND |in parameters |command type(sync/async) | - | |out parameter | | - |DMT_EVENT |in parameters |NA | - |$ref(type) |writable(0/1) |unique keys | - | | | | - - char * path - Complete object element path for which the data model schema is to be read. default path is "Device." - - bool first_level - if true, read only paramters at next level to path - - schem_type_t schema_type - enumeration to type of the schema to be get. Possible values are - ALL_SCHEMA - Complete schema - PARAM_ONLY - Parameters only - EVENT_ONLY - Events only - COMMAND_ONLY - Commands only - -return - int fault - contains the fault code if API is not able to read the data model. -``` -### dm_entry_param_method - -used to read the data model based on the input given - -``` -int dm_entry_param_method(struct dmctx *ctx, int cmd, char *inparam, char *arg1, char *arg2) - -inputs - struct dmctx *ctx - pointer to struct dmctx strunture. The list of parameter will be updated in ctx.list_parameter. each node in the list is of type - struct dm_parameter which contains char *name, char *data, char *type and char *additional_data; - the content of fields are updated based on the cmd and are as follows- - cmd | Name | Type | Data | Addtional Data | - |------------- |------------- |------------- |------------ |--------------------- | - |CMD_GET_VALUE |Parameter |$ref(type) |Value | NA | - |CMD_GET_NAME |Parameter |$ref(type) |writable(0/1) | NA | - |CMD_SET_VALUE |path | NA | NA | NA | - |CMD_ADD_OBJECT |path | NA | NA | NA | - |CMD_DEL_OBJECT |path | NA | NA | NA | - |CMD_USP_OPERATE |path | NA | NA | NA | - |CMD_USP_LIST_OPERATE |parameter |DMT_COMMAND |in/out parameters |cmd type (sync/async) | - |CMD_USP_LIST_EVENT |paramter |DMT_EVENT |in parameters |NA | - |CMD_GET_SCHEMA |paramter ||$ref(type) |writable(0/1) |unique keys | - |CMD_GET_INSTANCES |parameter | NA |NA |NA | - - int cmd - command to API to tell how the data model is to be read, possible values are - CMD_GET_VALUE - Read the values of the parameters from data model - CMD_GET_NAME - Read the names of the parameters from data model - CMD_SET_VALUE - Set value of specified parameters in the data model - CMD_ADD_OBJECT - Add object in a multi instance parameter in the data model - CMD_DEL_OBJECT - Delete object from a multi instance parameter in the data model - CMD_USP_OPERATE - execute the specified command - CMD_USP_LIST_OPERATE - Read all the command type parameter from data model. - CMD_USP_LIST_EVENT - Read all the event type parameter from data model. - CMD_GET_SCHEMA - Read all the parameter type parameter from data model. - CMD_GET_INSTANCES - Read all the instance of multi instance parameter from data model. - - char * inparam - Complete object element path for which the data model schema is to be read. default path is "Device." - - char *arg1 and char *arg2 - arguments specific to commands. - -return - int fault - contains the fault code if API is not able to read the data model. returns 0 on success. -``` -### dm_entry_apply - -This method is called to apply the changes done to data model. used with set_value - -``` -int dm_entry_apply(struct dmctx *ctx, int cmd) - -inputs - struct dmctx *ctx - pointer to struct dmctx strunture. The list of parameter will be updated in ctx.list_parameter - - int cmd - command to API to tell how the data model is to be read, possible values are - - CMD_SET_VALUE - Set value of specified parameters in the data model - - char *arg1 - -return - int fault - contains the fault code if API is not able to read the data model. -``` -### dm_ctx_init - -This method is used to initialize the dmctx structure object to read the data model. - -``` -int dm_ctx_init(struct dmctx *ctx, unsigned int instance_mode) -inputs - struct dmctx *ctx - pointer to struct dmctx strunture to be initialized. - - unsigned int instance_mode - instance mode of the dmctx to be set. -return - int fault - returns 0 on success. -``` - -### dm_ctx_init_sub - -This method is an extension of dm_ctx_init method. only difference it only intializes dmctx structure object and does not intializes other resources used in reading data model - -``` -int dm_ctx_init_sub(struct dmctx *ctx, unsigned int instance_mode) -inputs - struct dmctx *ctx - pointer to struct dmctx strunture to be initialized. - - unsigned int instance_mode - instance mode of the dmctx to be set. -return - int fault - returns 0 on success. -``` - - -### dm_ctx_clean - -This method is used to free the dmctx structure object and other resources post reading the data model. - -``` -int dm_ctx_clean(struct dmctx *ctx) - -input - struct dmctx *ctx - pointer to struct dmctx strunture to be freed. - -return - int fault - returns 0 on success. - -``` - -### dm_ctx_clean_sub - -This method is an extension of dm_ctx_clean method. only difference is it frees the dmctx structure and does not free other resources used in reading data model - -``` -int dm_ctx_clean_sub(struct dmctx *ctx) - -input - struct dmctx *ctx - pointer to struct dmctx strunture to be freed. - -return - int fault - returns 0 on success. - -``` -### set_bbfdatamodel_type - -This method is used to set the type of protocol for which the data model is to be read -``` -int set_bbfdatamodel_type(int bbf_type) - -input - int cmd - the protocol through which the data model is to be read, possible values are - BBFDM_USP - Protocol USP - BBFDM_CWMP - Protocol CWMP - BBFDM_BOTH - Both USP and CWMP - -return - int - returns 0 on success. -``` -### dm_entry_restart_services - -This method is used to restart the state of data model whenever its state is changed - -``` -int dm_entry_restart_services(void) - -input - None - -return - int - returns 0 on success. -``` -### dm_entry_revert_changes - -This method is used to restart the state of data model whenever its state is changed - -``` -int dm_entry_revert_changes(void) - -input - None - -return - int - returns 0 on success. -``` - - -### dm_debug_browse_path - -This method returns the last accessed path in the data model - -``` -int dm_debug_browse_path(char *buff, size_t len) -input - char *buff - pointer to the buffer in which the path will be returned - size_t len - length of the buffer -return - int - returns 0 on success. -``` - - -### get_dm_type - -This method is used to get the type assigned to the data model parameter. - -``` -int get_dm_type(char *dm_str) - -input - char *dm_str - data model parameter type, eg. xsd:string, xsd:unit etc. - -return - int - type of data model assigned to the object eg. DMT_STRING, DMT_UNINT etc. - -``` - -### dm_entry_manage_services - This method is used to commit the changes made to the data model using either ubus call or uci commit. - -``` -int dm_entry_manage_services(struct blob_buf *bb, bool restart) - -input - struct blob_buf *bb - pointer to the struct blob_buf object. contains all the packages updated. - bool restart - if true packages will be updated through ubus call. - if false packages will be updated through uci. - -return - int - returns 0 on success. -``` - -### dm_entry_restart_services - -this method is used to commit all the changes made to the data model. - -``` -int dm_entry_restart_services(void) - -return - int - returns 0 on success. -``` -### dm_config_ubus -This method is used to configure ubus. - -``` -void dm_config_ubus(struct ubus_context *ctx) - -input - struct ubus_context *ctx - pointer to struct ubus_context object to be intialized. diff --git a/bbfd/docs/guide/ubus_errors.md b/bbfd/docs/guide/ubus_errors.md deleted file mode 100644 index 6e137c62..00000000 --- a/bbfd/docs/guide/ubus_errors.md +++ /dev/null @@ -1,115 +0,0 @@ -# UBUS Errors - -## Path syntax and possible error cases - -Please note some error scenerios with the uspd. - -1. The path parameter value must start with 'Device.'. The command below doesn't have Device before path "Users.User." - -```console -root@iopsys:~# ubus call usp.raw get '{"path":"Users.User."}' -{ - "fault": 7026 -} -``` - -2. The path parameter must end with a '.' if the path element is not a leaf element e.g., - Note that first two commands doesn't end with a '.' while the command with Alias is correct, due to Alias - being the leaf element. To find correct schema path user can check with dump_schema option. - -```console -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.4"}' -{ - "fault": 7026 -} -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User"}' -{ - "fault": 9005 -} -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.*"}' -{ - "fault": 7026 -} -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.4.Alias"}' -{ - "Alias": "cpe-4" -} -``` - -3. In path parameter value below, note that, the first search expression 'Type==Normal' is string which should be used as : Type==\"Normal\" - -```console -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==Normal].IPv4Address.[AddressingType==\"Static\"].IPAddress"}' -{ - "fault": 7008 -} -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==\"Normal\"].IPv4Address.[AddressingType==\"Static\"].IPAddress"}' -{ - "Interface": [ - { - "IPv4Address": [ - { - "IPAddress": "2.0.0.3" - } - ] - } - ] -} -``` - -4. The path parameter value must not have an empty search expression - -```console -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.[]."}' -{ - "fault": 9005 -} -``` - -5. The path parameter value must use proper '.' separated path search expression. Note that a '.' is missing between User and * - -```console -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User*."}' -{ - "fault": 7026 -} -``` - -6. The path parameter value must be a valid path schema, in example below SSID is used which is invalid schema element for Device.Users.User.{i}. - -```console -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.1.SSID"}' -{ - "fault": 7026 -} -``` - -7. Please note that in search expression, string comparison only work with "==" or "!=". Whereas in command below its = - -```console -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.[Username=\"user\"].Alias"}' -{ - "fault": 7008 -} -``` - -#### Errors Codes - -| Error Code | Meaning | -|------------|--------------------------------------------------------------| -| 7003 | Message failed due to an internal error. | -| 7004 | Message failed due to invalid values in the request elements and/or failure to update one or more parameters during Add or Set requests. | -| 7005 | Message failed due to memory or processing limitations. | -| 7008 | Requested path was invalid or a reference was invalid. | -| 7010 | Requested Path Name associated with this ParamError did not match any instantiated parameters. | -| 7011 | Unable to convert string value to correct data type. | -| 7012 | Out of range or invalid enumeration. | -| 7022 | Command failed to operate. | -| 7026 | Path is not present in the data model schema. | - - diff --git a/bbfd/docs/guide/ubus_example.md b/bbfd/docs/guide/ubus_example.md deleted file mode 100644 index 8a3efe02..00000000 --- a/bbfd/docs/guide/ubus_example.md +++ /dev/null @@ -1,205 +0,0 @@ -# UBUS examples - -```console - -root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.SSID"}' -{ - "SSID": [ - { - "SSID": "NORRLAND-34E380760120" - }, - { - "SSID": "NORRLAND-34E380760120" - } - ] -} - -root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.BSSID"}' -{ - "SSID": [ - { - "BSSID": "34:E3:80:76:01:22" - }, - { - "BSSID": "34:E3:80:76:01:23" - } - ] -} - -root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.[BSSID==\"34:E3:80:76:01:22\"].SSID"}' -{ - "SSID": [ - { - "SSID": "NORRLAND-34E380760120" - } - ] -} - -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Status==\"Up\"].IPv4Address.[AddressingType==\"DHCP\"].IPAddress"}' -{ - "Interface": [ - { - "IPv4Address": [ - { - "IPAddress": "192.168.0.96" - } - ] - } - ] -} - -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Status==\"Up\"].IPv4Address.[AddressingType==\"DHCP\"&&Status==\"Up\"]."}' -{ - "Interface": [ - { - "IPv4Address": [ - { - "AddressingType": "DHCP", - "Alias": "cpe-2", - "Enable": true, - "IPAddress": "192.168.0.96", - "Status": "Up", - "SubnetMask": "255.255.255.0", - "X_IOPSYS_EU_FirewallEnabled": true - } - ] - } - ] -} - -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Interface.[Type==\"Normal\"&&Stats.PacketsSent<=500].IPv4Address.[AddressingType==\"Static\"].IPAddress"}' -{ - "Interface": [ - { - "IPv4Address": [ - { - "IPAddress": "192.168.1.1" - } - ] - } - ] -} - -root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.AccessPoint.[SSIDReference+.SSID==\"NORRLAND-34E380760120\"].AssociatedDevice.[Noise>15].SignalStrength"} -' -{ - "AccessPoint": [ - { - "AssociatedDevice": [ - { - "SignalStrength": -31 - } - ] - } - ] -} - - -root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.*.LowerLayers#1+.Name"}' -{ - { - "Name": "wlan0", - "Name": "wlan2" - } -} - - - -root@iopsys:~# ubus call usp get '{"path":"Device.Users.User.*.Username"}' -{ - "User": [ - { - "Username": "user" - }, - { - "Username": "support" - }, - { - "Username": "admin" - } - ] -} - -root@iopsys:~# ubus call usp.raw set '{"path":"Device.IP.Diagnostics.IPPing.DiagnosticsState", "value":"Requested", "proto":"cwmp"}' -{ - "parameters": [ - { - "path": "Device.IP.Diagnostics.IPPing.DiagnosticsState", - "status": true, - } - ] -} - -root@iopsys:~# ubus call usp.raw set '{"path":"Device.Users.User.2.Username", "value":"abc", "proto":"cwmp"}' -{ - "parameters": [ - { - "path": "Device.Users.User.2.Username", - "status": true, - } - ] -} - -root@iopsys:~# ubus call usp.raw set '{"path":"Device.Users.User.2.Username", "value":"abc", "proto":"usp"}' -{ - "parameters": [ - { - "path": "Device.Users.User.2.Username", - "status": true - } - ] -} - -root@iopsys:~# ubus call usp.raw set '{"path":"Device.Users.User.2.Username", "value":"abc"}' -{ - "parameters": [ - { - "path": "Device.Users.User.2.Username", - "status": true - } - ] -} - -root@iopsys:~# -root@iopsys:~# ubus call usp set '{"path":"Device.Users.User.[Username==\"xyz1\"].", "values":{"Username":"xyz1", "Enable":"dummy", "Password":"yzssssx"}, "proto":"usp"}' -{ - "parameters": [ - { - "path": "Device.Users.User.2.Username", - "status": true - }, - { - "path": "Device.Users.User.2.Enable", - "status": false, - "fault": 7012 - }, - { - "path": "Device.Users.User.2.Password", - "status": true - } - ] -} -root@iopsys:~# -root@iopsys:~# ubus call usp.raw setm_values '{"pv_tuple":[{"path":"Device.Users.User.2.Username", "value":"xzzz"}, {"path":"Device.Users.User.2.RemoteAccessCapable", "value":"1"}, {"path":"Device.Users.User.2.Password", "value":"zzzzzzz"}], "proto":"usp"}' -{ - "parameters": [ - { - "path": "Device.Users.User.2.Username", - "status": true - }, - { - "path": "Device.Users.User.2.RemoteAccessCapable", - "status": false, - "fault": 7012 - }, - { - "path": "Device.Users.User.2.Password", - "status": true - } - ] -} -``` - -- For more info on the usp ubus API see [link](../api/ubus/usp.md) -- For more info on the usp.raw ubus API see [link](../api/ubus/usp.raw.md) - diff --git a/bbfd/docs/guide/ubus_methods.md b/bbfd/docs/guide/ubus_methods.md deleted file mode 100644 index 8306d1ac..00000000 --- a/bbfd/docs/guide/ubus_methods.md +++ /dev/null @@ -1,874 +0,0 @@ -# UBUS Methods - -`uspd` needs to be started on startup after `ubusd`, as it exposes the data-model -objects over `ubus`. By default(when granularity is not set in `uci`), `uspd` registers -below two namespaces with `ubus`. - -```console -root@iopsys:~# ubus list |grep usp -usp -usp.raw -``` - -`usp` namespace is to provide the output as required by `End User` or in pretty format, -whereas `usp.raw` namespace is to provide output in raw JSON format for easy API integration, -which can be used by other USP front-end applications(like: `obuspa`, `icwmp`). -`usp` namespace has fewer methods defined to provide a simple interface to `end users`, -whereas `usp.raw` has more features/methods to provide more customization options. - -Default namespace with functionalities: - -```console -root@iopsys:~# ubus -v list usp -'usp' @78f3eaca - "list_operate":{} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer"} -root@iopsys:~# -root@iopsys:~# ubus -v list usp.raw -'usp.raw' @08a13407 - "dump_schema":{} - "list_operate":{} - "list_events":{} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "getm_values":{"paths":"Array","proto":"String","next-level":"Boolean","instance_mode":"Integer"} - "getm_names":{"paths":"Array","proto":"String","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "transaction_start":{"app":"String","max_timeout":"Integer"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "setm_values":{"pv_tuple":"Array","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "transaction_commit":{"transaction_id":"Integer"} - "transaction_abort":{"transaction_id":"Integer"} - "transaction_status":{"transaction_id":"Integer"} - "notify_event":{"name":"String","input":"Table"} -root@iopsys:~# -``` - -> Note1: `proto` in each method specify the data-model prototype('cwmp', 'usp') to use, if not provided default data-model will be used. - -> Note2: `instance_mode` could be 0 or 1, for instance number, instance alias respectively. - -> Note3: `next-level` true means only get next level objects and false means get all objects recursively - -> Note4: `maxdepth` is measured on max number of .(Dot) present in object name - -> Note5: `key` is used specifically for cwmp param_key - -The objects registered with the above namespaces can be called with appropriate -parameters to perform a USP `Get/Set/Operate/Add Object/Delete Object` operation as below. - -## Granularity - -Granularity feature is basically exposes the same USP functionality by registering -additional ubus namespaces to reduce the `path` length in ubus parameter. -It is the number of levels(Dots) up to which we want to shorten the length. - -Ex: - - When Granularity is set to 1, exposed ubus namespaces are - -```console -root@iopsys:~# ubus list|grep usp -usp -usp.Device. -usp.raw -``` - - - When Granularity is set to 2, exposed ubus namespaces are - -```console -root@iopsys:~# ubus list|grep usp -usp -usp.Device. -usp.Device.Bridging. -usp.Device.DHCPv4. -usp.Device.DHCPv6. -usp.Device.DNS. -usp.Device.DeviceInfo. -usp.Device.DynamicDNS. -usp.Device.Ethernet. -usp.Device.Firewall. -usp.Device.Hosts. -usp.Device.IP. -usp.raw -root@iopsys:~# -``` - -These granular ubus objects provides the same functionality as of `usp` ubus namespace - -```console -root@iopsys:~# ubus -v list usp.Device.WiFi. -'usp.Device.WiFi.' @6fd43aca - "list_operate":{} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer"} -root@iopsys:~# -``` - -Registered method can be called with appropriate parameters, like: - -```console -root@iopsys:~# ubus call usp.Device. get '{"path":"Users."}' -{ - "Users": { - "User": [ - { - "Alias": "cpe-1", - "Enable": true, - "Language": "", - "Password": "", - "RemoteAccessCapable": true, - "Username": "user" - }, - { - "Alias": "cpe-2", - "Enable": true, - "Language": "", - "Password": "", - "RemoteAccessCapable": true, - "Username": "support" - }, - { - "Alias": "cpe-3", - "Enable": true, - "Language": "", - "Password": "", - "RemoteAccessCapable": true, - "Username": "admin" - } - ], - "UserNumberOfEntries": 3 - } -} -root@iopsys:~# -``` - -## Overview - -`uspd` provides below commands in pretty(usp) or raw(usp.raw) formats, some methods only available for API integration in usp.raw namespace: - - - Get - - Get multiple values - - Get multiple names - - Set - - Operate - - Add object - - Delete object - - Object names - - Instances - - Validate - - List operate - - Dump schema - - Set multiple values - - Transaction start - - Transaction status - - Transaction commit - - Transaction abort - - List supported usp events - - Send notification for an event - -It also provide a granularity layer which can be configured using uci parameter and provide additional ubus objects. - -### Get -API to query the value of a specific object. - -```console -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"usp"}' -{ - "Diagnostics": { - "IPv4DownloadDiagnosticsSupported": true, - "IPv4PingSupported": true, - "IPv4ServerSelectionDiagnosticsSupported": true, - "IPv4TraceRouteSupported": true, - "IPv4UDPEchoDiagnosticsSupported": true, - "IPv4UploadDiagnosticsSupported": true, - "IPv6DownloadDiagnosticsSupported": true, - "IPv6PingSupported": true, - "IPv6ServerSelectionDiagnosticsSupported": true, - "IPv6TraceRouteSupported": true, - "IPv6UDPEchoDiagnosticsSupported": true, - "IPv6UploadDiagnosticsSupported": true - } -} -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.IP.Diagnostics.", "proto":"cwmp"}' -{ - "Diagnostics": { - "DownloadDiagnostics": { - "BOMTime": "0", - "DSCP": 0, - "DiagnosticsState": "None", - "DownloadDiagnosticMaxConnections": 1, - "TotalBytesSent": 0, - "TotalBytesSentUnderFullLoading": 0 - }, - "IPPing": { - "AverageResponseTime": 0, - "AverageResponseTimeDetailed": 0, - "DSCP": 0, - "DataBlockSize": 64, - "ProtocolVersion": "Any", - "SuccessCount": 0, - "Timeout": 1000 - }, - "IPv4DownloadDiagnosticsSupported": true, - "IPv4PingSupported": true, - "IPv4ServerSelectionDiagnosticsSupported": true, - "IPv6UDPEchoDiagnosticsSupported": true, - "IPv6UploadDiagnosticsSupported": true, - } - } -} -root@iopsys:~# -root@iopsys:~# ubus call usp get '{"path":"Device.Users."}' -{ - "Users": { - "User": [ - { - "Alias": "cpe-1", - "Enable": true, - "Language": "", - "Password": "", - "RemoteAccessCapable": true, - "Username": "user" - }, - { - "Alias": "cpe-2", - "Enable": true, - "Language": "", - "Password": "", - "RemoteAccessCapable": true, - "Username": "support" - }, - { - "Alias": "cpe-3", - "Enable": true, - "Language": "", - "Password": "", - "RemoteAccessCapable": true, - "Username": "admin" - } - ], - "UserNumberOfEntries": 3 - } -} -root@iopsys:~# -root@iopsys:~# ubus call usp.raw get '{"path":"Device.Users."}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.1.Alias", - "value": "cpe-1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.Enable", - "value": "1", - "type": "xsd:boolean" - }, - { - "parameter": "Device.Users.User.1.Language", - "value": "", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.Password", - "value": "", - "type": "xsd:string" - } - ] -} - -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md#get) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md#get) - -### Get multiple values -API to get values of multiple objects at once, object name must be provided in `paths` parameter array as below. - -> Note: This method is only available in `usp.raw` namespace. - -```console -root@iopsys:~# ubus call usp.raw getm_values '{"paths":["Device.Users.User.1.Username","Device.DeviceInfo.SerialNumber"]}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.1.Username", - "value": "user", - "type": "xsd:string" - }, - { - "parameter": "Device.DeviceInfo.SerialNumber", - "value": "E40A24H185027824", - "type": "xsd:string" - } - ] -} -``` - -### Get multiple objects -API to get multiple objects from multiple paths at once. - -> Note: This method only available in `usp.raw` namespace - -```console -root@iopsys:~# ubus call usp.raw getm_names '{"paths":["Device.Users.User.1.","Device.DeviceInfo.SerialNumber"]}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.1.", - "value": "1", - "type": "xsd:object" - }, - { - "parameter": "Device.Users.User.1.Alias", - "value": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.Enable", - "value": "1", - "type": "xsd:boolean" - }, - { - "parameter": "Device.Users.User.1.Language", - "value": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.Password", - "value": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.RemoteAccessCapable", - "value": "1", - "type": "xsd:boolean" - }, - { - "parameter": "Device.Users.User.1.Username", - "value": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.DeviceInfo.SerialNumber", - "value": "0", - "type": "xsd:string" - } - ] -} -root@iopsys:~# -``` - -### Set -API to set value to specific object, object name must be provided in `path` parameter and value to be set in `value` option. - -> Note 1: In usp namespace, set method creates a internal transaction before actually setting the value. After set operation it automatically commits the transaction. - -> Note 2: In usp.raw namespace, set method requires a transaction to be created before calling the set method. Please refer to transaction APIs for more details. - -```console -root@iopsys:/tmp# ubus call usp set '{"path":"Device.WiFi.SSID.[BSSID==\"00:22:07:ae:ee:03\"].SSID", "value":"test-2g"}' -{ - "status": true -} -root@iopsys:/tmp# ubus call usp.raw set '{"path":"Device.WiFi.SSID.[BSSID==\"00:22:07:ae:ee:03\"].SSID", "value":"test-2g", "transaction_id":12345}' -{ - "status": true -} -root@iopsys:~# ubus call usp get '{"path":"Device.WiFi.SSID.[BSSID==\"00:22:07:ae:ee:03\"].SSID"}' -{ - "SSID": [ - { - "SSID": "test-2g" - } - ] -} -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md#set) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md#set) - -### Operate -API to run operate/diagnostics commands as defined in TR-369 - -```console -root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Diagnostics.", "action":"IPPing()","input":{"Host":"iopsys.eu"}}' -{ - "Results": [ - { - "path": "Device.IP.Diagnostics.IPPing", - "result": [ - { - "AverageResponseTime": 0, - "AverageResponseTimeDetailed": 0, - "FailureCount": 3, - "MaximumResponseTime": 0, - "MaximumResponseTimeDetailed": 0, - "MinimumResponseTime": 9999, - "MinimumResponseTimeDetailed": 999999999, - "SuccessCount": 0 - } - ] - } - ] -} - -root@iopsys:~# ubus call usp.raw operate '{"path":"Device.IP.Diagnostics.", "action":"IPPing()","input":{"Host":"iopsys.eu"}}' -{ - "Results": [ - { - "path": "Device.IP.Diagnostics.IPPing", - "parameters": [ - { - "parameter": "AverageResponseTime", - "value": "0", - "type": "xsd:unsignedInt" - }, - { - "parameter": "AverageResponseTimeDetailed", - "value": "0", - "type": "xsd:unsignedInt" - }, - { - "parameter": "FailureCount", - "value": "3", - "type": "xsd:unsignedInt" - }, - { - } - ] -} - -root@iopsys:~# ubus call usp operate '{"path":"Device.IP.Interface.[Name==\"wan\"].", "action":"Reset()"}' -{ - "Results": [ - { - "path": "Device.IP.Interface.2.Reset", - "result": [ - { - - } - ] - } - ] -} - -root@iopsys:~# ubus call usp.raw operate '{"path":"Device.IP.Interface.[Name==\"wan\"].", "action":"Reset()"}' -{ - "Results": [ - { - "path": "Device.IP.Interface.2.Reset", - "parameters": [ - - ] - } - ] -} -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md#operate) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md#operate) - -### Add object -API to add new objects in multi-instance object - -> Note 1: In usp namespace, `add_object` method creates a internal transaction before actually setting the value. After set operation it automatically commits the transaction. -> Note 2: In usp.raw namespace, `add_object` method requires a transaction to be created before calling the set method. Please refer to transaction APIs for more details. - -```console -root@iopsys:~# ubus call usp add_object '{"path":"Device.Users.User."}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.", - "status": true, - "instance": "4" - } - ] -} -root@iopsys:~# ubus call usp.raw add_object '{"path":"Device.Users.User.", "transaction_id":12345}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.", - "status": true, - "instance": "5" - } - ] -} -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md#add_object) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md#add_object) - -### Delete object -API to delete an existing object from multi-instance object - -> Note 1: In usp namespace, `del_object` method creates a internal transaction before actually setting the value. After set operation it automatically commits the transaction. -> Note 2: In usp.raw namespace, `del_object` method requires a transaction to be created before calling the set method. Please refer to transaction APIs for more details. - -```console -root@iopsys:/tmp# ubus call usp del_object '{"path":"Device.Users.User.4"}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.4.", - "status": true - } - ] -} -root@iopsys:/tmp# ubus call usp.raw del_object '{"path":"Device.Users.User.3", "transaction_id": 12345}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.3.", - "status": true - } - ] -} -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md#del_object) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md#del_object) - -### Object names -API to get the available list of object names. - -```console -root@iopsys:~# ubus call usp object_names '{"path":"Device.DeviceInfo.SerialNumber"}' -{ - "parameters": [ - { - "parameter": "Device.DeviceInfo.SerialNumber", - "writable": "0", - "type": "xsd:string" - } - ] -} -root@iopsys:~# -root@iopsys:~# ubus call usp.raw object_names '{"path":"Device.Users.User.1."}' -{ - "parameters": [ - { - "parameter": "Device.Users.User.1.", - "writable": "1", - "type": "xsd:object" - }, - { - "parameter": "Device.Users.User.1.Alias", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.Enable", - "writable": "1", - "type": "xsd:boolean" - }, - { - "parameter": "Device.Users.User.1.Language", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.Password", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.Users.User.1.RemoteAccessCapable", - "writable": "1", - "type": "xsd:boolean" - }, - { - "parameter": "Device.Users.User.1.Username", - "writable": "1", - "type": "xsd:string" - } - ] -} -root@iopsys:~# -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md) - -### Instances -API to get the available instances of an multi-instance object. USP Instances method returns the registered instances. - -```console -root@iopsys:~# ubus call usp instances '{"path":"Device.IP.Interface.", "proto":"usp"}' -{ - "parameters": [ - { - "parameter": "Device.IP.Interface.1." - }, - { - "parameter": "Device.IP.Interface.1.IPv4Address.1." - }, - { - "parameter": "Device.IP.Interface.2." - }, - { - "parameter": "Device.IP.Interface.3." - }, - { - "parameter": "Device.IP.Interface.3.IPv4Address.1." - }, - { - "parameter": "Device.IP.Interface.3.IPv6Address.1." - }, - { - "parameter": "Device.IP.Interface.3.IPv6Prefix.1." - } - ] -} -``` - -- For more info on the `usp` ubus API see [link](../api/ubus/usp.md#instances) -- For more info on the `usp.raw` ubus API see [link](../api/ubus/usp.raw.md#instances) - -### Validate -API to validate a object in data-model. This api shall simply return the object name -if present in data-model objects or generates a fault if object not available in -data-model. - -```console -root@iopsys:~# ubus call usp validate '{"path":"Device.DeviceInfo."}' -{ - "parameter": "Device.DeviceInfo" -} -root@iopsys:~# ubus call usp.raw validate '{"path":"invalid.object"}' -{ - "fault": 9005 -} -``` - -### List Operate -API to list all available operate commands with supported input and output parameters - - -```console -root@iopsys:~# ubus call usp list_operate -{ - "parameters": [ - { - "parameter": "Device.DHCPv4.Client.{i}.Renew()", - "type": "sync" - }, - { - "parameter": "Device.DNS.Diagnostics.NSLookupDiagnostics()", - "type": "async", - "in": [ - "HostName", - "Interface", - "DNSServer", - "Timeout", - "NumberOfRepetitions" - ], - "out": [ - "Status", - "AnswerType", - "HostNameReturned", - "IPAddresses", - "DNSServerIP", - "ResponseTime" - ] - }, - { - "parameter": "Device.DeviceInfo.FirmwareImage.{i}.Activate()", - "type": "async" - }, - { - "parameter": "Device.IP.Diagnostics.IPPing()", - "type": "async", - "in": [ - "Interface", - "ProtocolVersion", - "Host", - "NumberOfRepetitions", - "Timeout", - "DataBlockSize", - "DSCP" - ], - "out": [ - "Status", - "IPAddressUsed", - "SuccessCount", - "FailureCount", - "AverageResponseTime", - "MinimumResponseTime", - "MaximumResponseTime", - "AverageResponseTimeDetailed", - "MinimumResponseTimeDetailed", - "MaximumResponseTimeDetailed" - ] - }, - { -``` - -### Dump schema -API to dump all registered schema paths, - -```console -root@iopsys:~# ubus call usp dump_schema -{ - "parameters": [ - { - "parameter": "Device.ATM.Link.{i}.", - "writable": "1", - "type": "xsd:object" - }, - { - "parameter": "Device.ATM.Link.{i}.Alias", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.ATM.Link.{i}.DestinationAddress", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.ATM.Link.{i}.Enable", - "writable": "1", - "type": "xsd:boolean" - }, - { -``` - -### Set multiple values -API to set value of multiple parameters at once. - -> Note: This method only available in usp.raw namespace - -```console -root@iopsys:~# ubus call usp.raw setm_values '{"pv_tuple":[{"path":"Device.Users.User.2.Username", "value":"xzzz"}, {"path":"Device.Users.User.2.RemoteAccessCapable", "value":"true"}, {"path":"Device.Users.User.2.Password", "value":"zzzzzzz"}], "proto":"usp", "transaction_id":1249743667}' -{ - "status": true -} -root@iopsys:~# -root@iopsys:~# -root@iopsys:~# ubus call usp.raw setm_values '{"pv_tuple":[{"path":"Device.Users.User.2.Username", "value":"xzzz"}, {"path":"Device.Users.User.2.RemoteAccessCapable", "value":"dummy"}, {"path":"Device.Users.User.2.Password", "value":"zzzzzzz"}], "proto":"usp", "transaction_id":738335779}' -{ - "parameters": [ - { - "path": "Device.Users.User.2.RemoteAccessCapable", - "status": false, - "fault": 7012 - } - ] -} -``` - -### Transaction start -To support the `allow_partial` and `required` parameters in Add/Del/Set operation as defined in TR-369, transaction_* APIs introduced. -It basically works around data-model objects which has dependent uci config files for each CUD operation. -API to start a transaction in usp.raw namespace for add/del/set operations in usp.raw namespace - -> Note: This API only available in usp.raw namespace - -```console -root@iopsys:~# ubus call usp.raw transaction_start '{"app":"test"}' -{ - "status": true, - "transaction_id": 955001092 -} -``` - -It's sometime required to have a per transaction timeout, which can be defined along with transaction_start -```bash -root@4949e4da3d27:~# ubus call usp.raw transaction_start '{"app":"test", "max_timeout":5000}' -{ - "status": true, - "transaction_id": 491944812 -} -``` -> Note: max_timeout is time in milliseconds, its an optional input argument if not provided, uci default (uspd.usp.transaction_timeout) is used which is defined in seconds -> If uci option uspd.usp.transaction_timeout not set than a default 10 second timeout is used for the transactions. - -### Get status of a transaction -API to get details and check status of a transaction id in usp.raw namespace - -```console -root@iopsys:~# ubus call usp.raw transaction_status '{"transaction_id":955001092}' -{ - "app": "test", - "status": "on-going", - "remaining_time": 634 -} -root@iopsys:~# -root@iopsys:~# ubus call usp.raw transaction_status '{"transaction_id":869066287}' -{ - "status": "not-exists" -} -root@iopsys:~# -``` - -### Transaction commit -API to commit an on-going transaction, on calling this api, uci changes shall -be committed and required services shall be restarted. - -```console -root@iopsys:~# ubus call usp.raw transaction_commit '{"transaction_id":955001092}' -{ - "status": true -} -root@iopsys:~# -``` - -### Transaction abort -API to abort an on-going transaction, on calling this api, staged changes in -uci shall be reverted to earlier values. - -```console -root@iopsys:~# ubus call usp.raw transaction_abort '{"transaction_id":955001092}' -{ - "status": true -} -root@iopsys:~# -``` - -### List supported usp events -API to list down the data-model events for usp notification supported by uspd. - -```console -root@iopsys:~# ubus call usp.raw list_events -{ - "parameters": [ - { - "parameter": "Device.LocalAgent.TransferComplete!", - "in": [ - "Command", - "CommandKey", - "Requestor", - "TransferType", - "Affected", - "TransferURL", - "StartTime", - "CompleteTime", - "FaultCode", - "FaultString" - ] - } - ] -} -``` - diff --git a/bbfd/docs/guide/ubus_parallel_call.md b/bbfd/docs/guide/ubus_parallel_call.md deleted file mode 100644 index 9367e1f3..00000000 --- a/bbfd/docs/guide/ubus_parallel_call.md +++ /dev/null @@ -1,20 +0,0 @@ -# Parallel UBUS calls - -All `operate` operation and `get` operation with a depth up to 'USP_SUBPROCESS_DEPTH(2)' -runs in a parallel subprocess to avoid blocking the next call. - -```console -root@iopsys:~# time ubus call usp.raw get '{"path":"Device."}' >/dev/null & -root@iopsys:~# time ubus call usp.raw get '{"path":"Device.Users."}' >/dev/null -real 0m 0.07s -user 0m 0.00s -sys 0m 0.00s -root@iopsys:~# -real 0m 1.86s -user 0m 0.05s -sys 0m 0.00s - -[1]+ Done time ubus call usp.raw get "{\"path\":\"Device.\"}" >/dev/null -root@iopsys:~# -``` - diff --git a/bbfd/docs/mkdocs.yml b/bbfd/docs/mkdocs.yml deleted file mode 100755 index a49000a6..00000000 --- a/bbfd/docs/mkdocs.yml +++ /dev/null @@ -1,90 +0,0 @@ -site_name: Documentation Instructions -site_url: https://docs.iopsys.se/portal2/uspd/ -edit_uri: "https://dev.iopsys.eu/docs/portal2/uspd" - -site_description: IOWRT Technical Documentation -site_author: IOPSYS - -docs_dir: '.' -site_dir: 'site' - - -theme: - name: material - include_sidebar: true - highlightjs: true - hljs_languages: - - yaml - - python - language: en - font: - text: Roboto - code: Roboto Mono - logo: iopsys-white.svg - icon: - logo: icon.png - repo: fontawesome/brands/gitlab - extra: - social: - - icon: fontawesome/brands/github-alt - link: https://github.com/squidfunk - features: - - toc.autohide - - navigation.tabs - - navigation.tabs.sticky - - navigation.top - - navigation.tracking - - navigation.expand - - palette: - # Primary color used for header, sidebar and links, default: indigo - primary: black - # Accent color for highlighting user interaction, default: indigo - accent: deep orange - -extra_css: - - css/extra.css - - https://unpkg.com/mermaid@8.5.1/dist/mermaid.css - - https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css - -extra_javascript: - - https://unpkg.com/mermaid/dist/mermaid.min.js - - https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js - - https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js - -markdown_extensions: - - meta - - admonition - - pymdownx.arithmatex - - pymdownx.betterem: - smart_enable: all - - pymdownx.caret - - pymdownx.critic - - pymdownx.details - - pymdownx.emoji: - emoji_index: !!python/name:materialx.emoji.twemoji - emoji_generator: !!python/name:materialx.emoji.to_svg - - pymdownx.inlinehilite - - pymdownx.magiclink - - pymdownx.mark - - pymdownx.smartsymbols - - pymdownx.tasklist: - custom_checkbox: true - - pymdownx.tilde - - pymdownx.superfences: - # make exceptions to highlighting of code: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:mermaid2.fence_mermaid - - fontawesome_markdown - -plugins: - - search: - lang: - - en - separator: '[\s\-\.]+' - - awesome-pages: - collapse_single_pages: true - - mermaid2 - - section-index diff --git a/bbfd/docs/preview.sh b/bbfd/docs/preview.sh deleted file mode 100755 index afe20843..00000000 --- a/bbfd/docs/preview.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -# Copy README.md as index.md and change links -pip install -r requirements.txt - -# Copy README.md as index.md and change links -sed -r -e 's![\.\/]*docs[\/]*!./!g' ../README.md > index.md - -# Start mkdocs local server -mkdocs serve -f mkdocs.yml diff --git a/bbfd/docs/requirements.txt b/bbfd/docs/requirements.txt deleted file mode 100755 index bbbcd25a..00000000 --- a/bbfd/docs/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -mkdocs -mkdocs-material -mkdocs-awesome-pages-plugin -mkdocs-section-index -fontawesome_markdown -mkdocs-print-site-plugin -mkdocs-mermaid2-plugin diff --git a/bbfd/docs/spec/.pages b/bbfd/docs/spec/.pages deleted file mode 100644 index 352e417e..00000000 --- a/bbfd/docs/spec/.pages +++ /dev/null @@ -1,4 +0,0 @@ -title: "USP Daemon Specification" - -nav: - - "..." diff --git a/bbfd/docs/spec/functionspec.md b/bbfd/docs/spec/functionspec.md deleted file mode 100644 index ed3bb3b0..00000000 --- a/bbfd/docs/spec/functionspec.md +++ /dev/null @@ -1,336 +0,0 @@ -# Function Specification - -The scope of uspd is to expose the datamodel provided by libbbfdm APIs over ubus, along with provididng the features deinfed by requirements R-ARC.7 to R-ARC.12 of USP protocol. - -``` -root@iopsys:~# ubus -v list usp -'usp' @232da280 - "list_operate":{} - "get_supported_dm":{"path":"String","next-level":"Boolean","schema_type":"Integer"} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer"} - -root@iopsys:~# -root@iopsys:~# ubus -v list usp.raw -'usp.raw' @4c9c3c6e - "dump_schema":{} - "list_operate":{} - "list_events":{} - "get_supported_dm":{"path":"String","next-level":"Boolean","schema_type":"Integer"} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "getm_values":{"paths":"Array","proto":"String","next-level":"Boolean","instance_mode":"Integer"} - "getm_names":{"paths":"Array","proto":"String","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "transaction_start":{"app":"String"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "setm_values":{"pv_tuple":"Array","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "transaction_commit":{"transaction_id":"Integer","restart_services":"Boolean"} - "transaction_abort":{"transaction_id":"Integer"} - "transaction_status":{"transaction_id":"Integer"} - "notify_event":{"name":"String","input":"Table"} - -``` - -# Contents -* [usp](#usp) -* [usp.raw](#uspraw) - -## APIs - -uspd publishes two different types UBUS objects, `usp`, `usp.raw`. USP object is meant for end users/CLI users -usp.raw is meant for API integration -usp.raw has more ganureality in the function to match the third party apllication requiremtns whereas usp obect take cares of cutomization internally to provide simple interface for the end users. - - -### usp - -An object that publishes device information. - -````bash - "list_operate":{} - "get_supported_dm":{"path":"String","next-level":"Boolean","schema_type":"Integer"} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer"} -```` - -| Method |Function ID | -| :--- | :--- | -| [list_operate](#list_operate) | 1 | -| [get_supported_dm](#get_supported_dm) | 2 | -| [get](#get) | 3 | -| [object_names](#object_names) | 4 | -| [instances](#instances) | 5 | -| [validate](#validate) | 6 | -| [set](#set) | 7 | -| [operate](#operate) | 8 | -| [add_object](#add_object) | 9 | -| [del_object](#del_object) | 10 | - -#### Methods - -Below methods are supported in usp methods. Method description of the `usp` object in succeding paragraphs . - - -##### list_operate - -Exposes various sync and async operations supported by datamodel. e.g., IPPing(), NeighbourDiagnostics() etc. - -* [list_operate documentation](../api/ubus/usp.md#list_operate) - -##### get_supported_dm - -This method exposes the all type of objects supported in the data model in one browse. it will expose name, type, cmd_type and writable properties of the object depending on the type of the parameters present in the data model. - -* [get_supported_dm documentation](../api/ubus/usp.md#get_supported_dm) - - -##### get - -This method exposes information regarding various schema parameters registered in the data model. - -* [get documentation](../api/ubus/usp.md#get) - -##### object_names - -This method exposes names of the object registered in the data model. - -* [object_names documentation](../api/ubus/usp.md#object_names) - -##### instances - -This method exposes information of all instances of various objects registered in the data model for specified schema path. - -* [disconnect documentation](../api/ubus/usp.md#instances) - -##### validate - -This method validates whether the path provided is valid as per registerd schema paths. - -* [validate documentation](../api/ubus/usp.md#validate) - -##### set - -This method is used to set information of various registered schema parameters. - -* [set documentation](../api/ubus/usp.md#set) - -##### operate - -This method is used to execute various sync/async operations e.g., IPPing(), NeighbourDiagnostics() etc. - -* [operate documentation](../api/ubus/usp.md#operate) - -##### add_object - -This method is used to add an object to specified multi instance object in registered schema. - -* [add_object neighbor documentation](../api/ubus/usp.md#add_object) - -##### del_object - -This method is used to delete an object from specified multi instance object in registered schema. - -* [del_object documentation](../api/ubus/usp.md#del_object) - - - -### usp.raw - -Object for device functionality. One object per device will be published to -ubus. - -````bash - "dump_schema":{} - "list_operate":{} - "list_events":{} - "get_supported_dm":{"path":"String","next-level":"Boolean","schema_type":"Integer"} - "get":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "getm_values":{"paths":"Array","proto":"String","next-level":"Boolean","instance_mode":"Integer"} - "getm_names":{"paths":"Array","proto":"String","next-level":"Boolean","instance_mode":"Integer"} - "object_names":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "instances":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "validate":{"path":"String","proto":"String","maxdepth":"Integer","next-level":"Boolean","instance_mode":"Integer"} - "transaction_start":{"app":"String"} - "set":{"path":"String","value":"String","values":"Table","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "operate":{"path":"String","action":"String","input":"Table","proto":"String","instance_mode":"Integer"} - "add_object":{"path":"String","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "del_object":{"path":"String","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "setm_values":{"pv_tuple":"Array","proto":"String","instance_mode":"Integer","transaction_id":"Integer"} - "transaction_commit":{"transaction_id":"Integer","restart_services":"Boolean"} - "transaction_abort":{"transaction_id":"Integer"} - "transaction_status":{"transaction_id":"Integer"} - "notify_event":{"name":"String","input":"Table"} - -```` - -| Method |Function ID | -| :--- | :--- | -| [dump_schema](#dump_schema_raw) | 1 | -| [list_operate](#list_operate_raw) | 2 | -| [list_events](#list_events_raw) | 3 | -| [get_supported_dm](#get_supported_dm_raw) | 4 | -| [get](#get_raw) | 5 | -| [getm_values](#getm_values_raw) | 6 | -| [getm_names](#getm_names_raw) | 7 | -| [object_names](#object_names_raw) | 8 | -| [instances](#instances_raw) | 9 | -| [validate](#validate_raw) | 10 | -| [transaction_start](#transaction_start_raw) | 11 | -| [set](#set_raw) | 12 | -| [operate](#operate_raw) | 13 | -| [add_object](#add_object_raw) | 14 | -| [del_object](#del_object_raw) | 15 | -| [setm_values](#setm_values_raw) | 16 | -| [transaction_commit](#transaction_commit_raw) | 17 | -| [transaction_abort](#transaction_abort_raw) | 18 | -| [transaction_status](#transaction_status_raw) | 19 | -| [notify_event](#notify_event_raw) | 20 | - - -#### Methods - -Below methods are supported in usp methods. Method description of the `usp` object in succeding paragraphs . - - -##### dump_schema_raw - -This method exposes schema registered in the data model . - -* [dump_schema documentation](../api/ubus/usp.raw.md#dump_schema) - -##### list_operate_raw - -Exposes various sync and async operations supported by datamodel. e.g., IPPing(), NeighbourDiagnostics() etc. - -* [list_operate documentation](../api/ubus/usp.raw.md#list_operate) - -##### list_events_raw - -Exposes various events registered in the datamodel. - -* [list_events documentation](../api/ubus/usp.raw.md#list_events) - -##### get_supported_dm_raw - -This method exposes the all type of objects supported in the data model in one browse. it will expose name, type, cmd_type and writable properties of the object depending on the type of the parameters present in the data model. - -* [get_supported_dm documentation](../api/ubus/usp.md#get_supported_dm) - - -##### get_raw - -This method exposes information of various schema parameters registered in the data model. - -* [get documentation](../api/ubus/usp.raw.md#get) - -##### getm_values_raw - -This method is an extension to get method, this method can be use to get parameter values for multiple query paths at once. - -* [getm_values documentation](../api/ubus/usp.raw.md#getm_values) - -##### getm_names_raw - -This method is an extension to get method, this method can be use to get parameter names for multiple query paths at once. - -* [getm_names documentation](../api/ubus/usp.raw.md#getm_names) - - -##### object_names_raw - -This method exposes names of the objects in the spectified query path registered in the data model. - -* [object_names documentation](../api/ubus/usp.raw.md#object_names) - -##### instances_raw - -Get all the instances for specified schema path. - -* [disconnect documentation](../api/ubus/usp.raw.md#instances) - -##### validate_raw - -This method validates whether the path provided is valid as per registerd schema paths. - -* [validate documentation](../api/ubus/usp.raw.md#validate) - - -##### transaction_start - -This method starts a transaction with the name provided. - -* [transaction_start documentation](../api/ubus/usp.raw.md#transaction_start) - - -##### set_raw - -This method is used to set information of various registered schema parameters. - -* [set documentation](../api/ubus/usp.raw.md#set) - -##### operate_raw - -This method is used to execute various sync/async operations e.g., IPPing(), NeighbourDiagnostics() etc. - -* [operate documentation](../api/ubus/usp.raw.md#operate) - -##### add_object_raw - -This method is used to add an object to specified multi instance object in registered schema. - -* [add_object neighbor documentation](../api/ubus/usp.raw.md#add_object) - -##### del_object_raw - -This method is used to delete an object from specified multi instance object in registered schema. - -* [del_object documentation](../api/ubus/usp.raw.md#del_object) - -##### setm_values_raw - -This method is an extension to set method, this method can be use to set parameter values for multiple query paths at once. - -* [setm_values documentation](../api/ubus/usp.raw.md#setm_values) - - -##### transaction_commit - -This method commits the changes made by an ongoing transaction. - -* [transaction_commit documentation](../api/ubus/usp.raw.md#transaction_commit) - - -##### transaction_abort - -This method aborts an ongoing transaction. - -* [transaction_abort documentation](../api/ubus/usp.raw.md#transaction_abort) - -##### transaction_status - -This method provides with the status of an ongoing transaction. - -* [transaction_status documentation](../api/ubus/usp.raw.md#transaction_status) - -##### notify_event - -This method is used to get notified whenever the specified event occurs - -* [notify_event documentation](../api/ubus/usp.raw.md#notify_event) diff --git a/bbfd/docs/spec/testspec.md b/bbfd/docs/spec/testspec.md deleted file mode 100644 index 6b35171a..00000000 --- a/bbfd/docs/spec/testspec.md +++ /dev/null @@ -1,464 +0,0 @@ -# Test Specification - -Most of the functionalities in uspd can be tested via its ubus API. Each -API can be broken down into an individual test case to show full coverage is -achieved. - -# Sections -* [Preqreuisites](#prerequisites) -* [Test Suites](#test-suites) -* [Functional API Tests](#functional-api-tests) -* [Unit Tests](#unit-tests) -* [Functional Tests](#functional-tests) - - -## Prerequisites - -The prerequisite for the uspd test suites is that libbbfdm and ubusd has to be -built for the TEST platform, a version prepared to publish dummy data for get -API, and record set API to a test logfile at `/tmp/test.log`. - -| Dependency | Link | License | -| :--- | :--- | :--- | -| ---------- | ---------------------------------------- | -------- | -| ubusd | https://git.openwrt.org/project/ubus.git | LGPL 2.1 | -| libbbfdm | https://dev.iopsys.eu/iopsys/bbf.git | LGPL 2.1 | - - -## Test Suites - -The uspd build pipe has three test suites, a functional-api suite, unit test suite -and functional test suite. - -### Functional API Tests - -The functional API tests consists of two individual test suites, one per object -Ubus under test. The functional API tests use the Ubus-API-validation -command-line interface tool to invoke a method, programmatically through -libubus, and validates it against the objects json-schema. - -#### usp - -| Execution ID | Method | Description | Function ID Coverage | -| :--- | :--- | :--- | :--- | -| 1 | list_operate | No argument | [1](./functionspec.md#list_operate) | -| 2 | get_supported_dm \ with path argument | [2](./functionspec.md#get_supported_dm) | -| 3 | get | With path argument | [3](./functionspec.md#get) | -| 4 | object_names | With path argument | [4](./functionspec.md#object_names) | -| 5 | instances | With path argument | [5](./functionspec.md#instances) | -| 6 | validate | With path argument | [6](./functionspec.md#validate) | -| 7 | set | With path and value arguments | [7](./functionspec.md#set) | -| 8 | operate | With path, action and input arguments | [8](./functionspec.md#operate) | -| 9 | add_object | With path argument | [9](./functionspec.md#add_object) | -| 10 | del_object | With path argument | [10](./functionspec.md#del_object) | - - -#### usp.raw - -| Execution ID | Method | Description | Function ID Coverage | -| :--- | :--- | :--- | :--- | -| 1 | dump_schema | No argument | [15](./functionspec.md#dump_schema_raw) | -| 2 | list_operate | No argument | [16](./functionspec.md#list_operate_raw) | -| 3 | list_events | No argument | [16](./functionspec.md#list_events) | -| 4 | get_supported_dm | with path argument | [2](./functionspec.md#get_supported_dm) | -| 5 | get | With path argument | [17](./functionspec.md#get_raw) | -| 6 | getm_values | With paths array argument | [25](./functionspec.md#getm_values_raw) | -| 7 | getm_name | With paths array argument | [26](./functionspec.md#getm_names_raw) | -| 8 | object_names | With path argument | [18](./functionspec.md#object_names_raw) | -| 9 | instances | With path argument | [19](./functionspec.md#instances_raw) | -| 10 | validate | With path argument | [20](./functionspec.md#validate_raw) | -| 11 | transaction_start | With app argument | [17](./functionspec.md#transaction_start) | -| 12 | set | With path and value arguments | [21](./functionspec.md#set_raw) | -| 13 | operate | With path, action and input arguments | [22](./functionspec.md#operate_raw) | -| 14 | add_object | With path argument | [23](./functionspec.md#add_object_raw) | -| 15 | del_object | With path argument | [24](./functionspec.md#del_object_raw) | -| 16 | setm_values | With pv_tuple and transaction_id argument | [17](./functionspec.md#setm_val) | -| 17 | transaction_commit | With transaction_id argument | [17](./functionspec.md#transaction_commit) | -| 18 | transaction_abort | With transaction_id argument | [17](./functionspec.md#transaction_abort) | -| 19 | transaction_status | With transaction_id argument | [17](./functionspec.md#transaction_status) | -| 20 | notify_event | With ***** argument | [17](./functionspec.md#notify_event) | - - -### Unit Tests - -The uspd unit tests are written in cmocka, invoking the ubus callbacks -directly from the source code, which is compiled into a shared library. -This means mocking the arguments of a cli or libubus invoke in a -`struct blob_attr *`. The results of the call will be logged to the logfile at -`/tmp/test.log`. - -| Execution ID | Method | Test Case Name | Function ID Coverage | -| :--- | :--- | :--- | :--- | -| 1 | dump_schema | [test_api_usp_raw_dump_schema](#test_api_usp_raw_dump_schema) | [1](./functionspec.md#dump_schema_raw) -| 2 | list_operate | [test_api_usp_list_operate](#test_api_usp_list_operate) | [2](./functionspec.md#list_operate) | -| 3 | get | [test_api_usp_get](#test_api_usp_get) | [3](./functionspec.md#get) | -| 4 | object_names | [test_api_usp_object_name](#test_api_usp_object_name) | [4](./functionspec.md#object_names) | -| 5 | instances | [test_api_usp_instances](#test_api_usp_instances) | [5](./functionspec.md#instances) | -| 6 | validate | [test_api_usp_resolve](#test_api_usp_resolve) | [6](./functionspec.md#validate) | -| 7 | set | [test_api_usp_set](#test_api_usp_set) | [7](./functionspec.md#set) | -| 8 | add_object | [test_api_usp_add_object](#test_api_usp_add_object) | [9](./functionspec.md#add_object) | -| 9 | del_object | [test_api_usp_del](#test_api_usp_del_object) | [10](./functionspec.md#del_object) | -| 10 | getm_values | [test_api_usp_get_safe_values](#test_api_usp_get_safe_values) | [11](./functionspec.md#getm_values) | -| 11 | getm_name | [test_api_usp_get_safe_names](#test_api_usp_get_safe_names) | [12](./functionspec.md#getm_names) | - -#### test_api_usp_dump_schema - -##### Description - -Tests the uspd ubus API callback `dump_schema`, publishing the method -[dump_schema](./functionspec.md#dump_schema). - -##### Test Steps - -Issuing a dump_schema to a client from the uspd test platform. - -Read the logfile and verify that the `schema` argument was -accurately logged. - -##### Test Expected Results - -The expected result is for the log file to have recorded a call to the -dump_schema function. - -````bash -{ - "parameters": [ - { - "parameter": "Device.ATM.Link.{i}.", - "writable": "1", - "type": "xsd:object" - }, - { - "parameter": "Device.ATM.Link.{i}.Alias", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.ATM.Link.{i}.DestinationAddress", - "writable": "1", - "type": "xsd:string" - }, - { - "parameter": "Device.ATM.Link.{i}.Enable", - "writable": "1", - "type": "xsd:boolean" - }, - { -... -} -``` - -#### test_api_usp_list_operate - -##### Description - -Tests the uspd ubus API `list_operate`, publishing the method -[list_operate](./functionspec.md#list_operate). - -##### Test Steps - -Issuing a list_operate to a client from the uspd test platform. - -Read the logfile and verify that the `list_operate` argument was -accurately logged. - -##### Test Expected Results - -````bash -{ - "parameters": [ - { - "parameter": "Device.DHCPv4.Client.{i}.Renew()", - "type": "sync" - }, - { - "parameter": "Device.DNS.Diagnostics.NSLookupDiagnostics()", - "type": "async" - }, - { - { - "parameter": "Device.IP.Diagnostics.IPPing()", - "type": "async" - }, - { - "parameter": "Device.IP.Diagnostics.TraceRoute()", - "type": "async" - }, - { - "parameter": "Device.IP.Diagnostics.UDPEchoDiagnostics()", - "type": "async" - }, - { - "parameter": "Device.IP.Interface.{i}.Reset()", - "type": "sync" - }, - { - "parameter": "Device.Reboot()", - "type": "sync" - }, - { - -``` - -#### test_api_usp_get - -##### Description - -Tests the uspd ubus API get, publishing the method -[get](./functionspec.md#get). - -##### Test Steps - -Prepare the arguments as: - -````bash -{"path":"Device.IP.Diagnostics.", "proto":"usp"} -``` - -Requesting the libbfdm with the path `Device.IP.Diagnostics.`. - -Read the logfile and verify that the interface and arguments were accurately -logged. - -##### Test Expected Results - -The expected result is for the log file to have recorded a call to the -`libbbfdm`, through ubus and with the argument `path` as `Device.IP.Diagnostics.` -`proto` as `usp`. - -````bash -{ - "Diagnostics": { - "IPv4DownloadDiagnosticsSupported": true, - "IPv4PingSupported": true, - "IPv4ServerSelectionDiagnosticsSupported": true, - "IPv4TraceRouteSupported": true, - "IPv6UploadDiagnosticsSupported": true, - "UDPEchoConfig": { - "BytesReceived": 0, - "BytesResponded": 0, - "TimeFirstPacketReceived": "0", - "TimeLastPacketReceived": "0", - "UDPPort": 0 - } - } -} -``` - -#### test_api_usp_instances - -##### Description - -Tests the uspd ubus API instances, publishing the method -[instances](./functionspec.md#instances). - -##### Test Steps - -Prepare the arguments as: - -````bash -{"path":"Device.IP.Interface.", "proto":"usp"} -``` - -Requesting the libbfdm with the path `Device.IP.Interface.`. - -Read the logfile and verify that the interface and arguments were accurately -logged. - -##### Test Expected Results - -The expected result is for the log file to have recorded a call to the -`libbbfdm`, through ubus and with the argument `path` as `Device.IP.Interface.` -`proto` as `usp`. - -````bash -{ - "parameters": [ - { - "parameter": "Device.IP.Interface.1." - }, - { - "parameter": "Device.IP.Interface.1.IPv4Address.1." - }, - { - "parameter": "Device.IP.Interface.2." - }, - { - "parameter": "Device.IP.Interface.3." - }, - { - "parameter": "Device.IP.Interface.3.IPv4Address.1." - }, - { - "parameter": "Device.IP.Interface.3.IPv6Address.1." - }, - { - "parameter": "Device.IP.Interface.3.IPv6Prefix.1." - } - ] -} -``` - -#### test_api_usp_instances - -##### Description - -Tests the uspd ubus API instances, publishing the method -[instances](./functionspec.md#instances). - -##### Test Steps - -Prepare the arguments as: - -````bash -{"path":"Device.IP.Interface.", "proto":"usp"} -```` - -Requesting the libbfdm with the path `Device.IP.Interface.`. - -Read the logfile and verify that the interface and arguments were accurately -logged. - -##### Test Expected Results - -The expected result is for the log file to have recorded a call to the -`libbbfdm`, through ubus and with the argument `path` as `Device.IP.Interface.` -`proto` as `usp`. - -```bash -{ - "parameters": [ - { - "parameter": "Device.IP.Interface.1." - }, - { - "parameter": "Device.IP.Interface.1.IPv4Address.1." - }, - { - "parameter": "Device.IP.Interface.2." - }, - { - "parameter": "Device.IP.Interface.3." - }, - { - "parameter": "Device.IP.Interface.3.IPv4Address.1." - }, - { - "parameter": "Device.IP.Interface.3.IPv6Address.1." - }, - { - "parameter": "Device.IP.Interface.3.IPv6Prefix.1." - } - ] -} -``` - - -### Functional Tests - - -#### test_func_ref_follow - -##### Description - -Tests the reference follow for search path. Reference follow is basically -quering a search path, which is referenced by the path queried for. - -##### Test Steps - -Prepare the arguments as: - -````bash -{"path":"Device.WiFi.SSID.1.LowerLayers+.Alias", "proto":"usp"} -``` - -##### Test Expected Results - -The expected result is for the log file to have recorded a call to the -`libbbfdm`, through ubus and with the argument `path` as `Device.WiFi.SSID.1.LowerLayers+.Alias` and `proto` as `usp`. - -````bash -{ - "Device": { - "WiFi": { - "Radio": [ - { - "Alias": "cpe-1" - } - ] - } - } -} -``` - -#### test_func_list_of_ref - -##### Description - -Tests the list of reference following for search path. Reference follow is basically -quering a search path, which is referenced by the path queried for. - -##### Test Steps - -Prepare the arguments as: - -````bash -{"path":"Device.WiFi.SSID.1.LowerLayers#1+.Name"} -``` - -##### Test Expected Results - -The expected result is for the log file to have recorded a call to the -`libbbfdm`, through ubus and with the argument `path` as `Device.WiFi.SSID.1.LowerLayers#1+.Name` and `proto` as `usp`. - -````bash -{ - "Device": { - "WiFi": { - "Radio": [ - { - "Name": "wl0" - } - ] - } - } -} -``` - -#### test_func_search_expr - -##### Description - -Testing search path, this is a path Name that contains search criteria for addressing a -set of Multi-Instance Objects and/or their parameters. A Search path may contain a -Search Expression or Wildcard. - -##### Test Steps - -Prepare the arguments as: - -````bash -{"path":"Device.WiFi.SSID.[Status==\"Up\"].Alias"} -``` - -##### Test Expected Results - -In the above bash parameter path we can identify the square brackets as search path. So basically through this search path we are querying 'Alias' for any WiFi.SSID instance having -`Up` Status. - -The expected result is for the log file to have recorded a call to the -`libbbfdm`, through ubus and with the argument `path` as `Device.WiFi.SSID.1.LowerLayers#1+.Name` and `proto` as `usp`. - -````bash -{ - "SSID": [ - { - "Alias": "cpe-1" - }, - { - "Alias": "cpe-2" - } - ] -} -``` - diff --git a/bbfd/src/events.c b/bbfd/events.c similarity index 100% rename from bbfd/src/events.c rename to bbfd/events.c diff --git a/bbfd/src/events.h b/bbfd/events.h similarity index 100% rename from bbfd/src/events.h rename to bbfd/events.h diff --git a/bbfd/src/get.c b/bbfd/get.c similarity index 100% rename from bbfd/src/get.c rename to bbfd/get.c diff --git a/bbfd/src/get.h b/bbfd/get.h similarity index 100% rename from bbfd/src/get.h rename to bbfd/get.h diff --git a/bbfd/src/get_helper.c b/bbfd/get_helper.c similarity index 100% rename from bbfd/src/get_helper.c rename to bbfd/get_helper.c diff --git a/bbfd/src/get_helper.h b/bbfd/get_helper.h similarity index 100% rename from bbfd/src/get_helper.h rename to bbfd/get_helper.h diff --git a/bbfd/gitlab-ci/functional-api-test.sh b/bbfd/gitlab-ci/functional-api-test.sh deleted file mode 100755 index f9d1c8f8..00000000 --- a/bbfd/gitlab-ci/functional-api-test.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash - -echo "$0 preparation script" -pwd - -source ./gitlab-ci/shared.sh - -trap cleanup EXIT -trap cleanup SIGINT - -# clean and make -make clean -CFLAGS="-g -Os -fprofile-arcs -ftest-coverage -DUSPD_MAX_MSG_LEN=1048576" LDFLAGS="--coverage" make func-test -C ./ -check_ret $? - -supervisorctl update -supervisorctl restart all -supervisorctl status all -exec_cmd ubus wait_for usp.raw usp -supervisorctl status all - -# debug logging -echo "Checking ubus status [$(date '+%d/%m/%Y %H:%M:%S')]" -ubus list -ubus -v list usp.raw -ubus -v list usp - -echo "Checking system resources" -free -h -df -h -sleep 5 -# run functional on usp object validation -if [ -f "/usr/share/rpcd/schemas/usp*.json" ]; then - rm /usr/share/rpcd/schemas/usp*.json -fi - -cp -r ./schemas/ubus/usp.json /usr/share/rpcd/schemas -ubus-api-validator -t 5 -f ./test/api/json/usp.validation.json > ./api-result.log -generate_report usp_api api-result.log - -# run functional on usp object validation -if [ -f "/usr/share/rpcd/schemas/usp*.json" ]; then - rm /usr/share/rpcd/schemas/usp*.json -fi - -cp -r ./schemas/ubus/usp.raw.json /usr/share/rpcd/schemas -ubus-api-validator -t 5 -f ./test/api/json/usp.raw.validation.json >> ./api-result.log -generate_report usp_raw_api api-result.log - -supervisorctl status all -supervisorctl stop all -supervisorctl status - -#report part -date +%s > timestamp.log -gcovr -r . --xml -o ./api-test-coverage.xml -gcovr -r . - -echo "Checking memory leaks..." -grep -q "Leak" memory-report.xml -error_on_zero $? - -echo "Functional ubus API test :: PASS" diff --git a/bbfd/gitlab-ci/functional-test.sh b/bbfd/gitlab-ci/functional-test.sh deleted file mode 100755 index a3bb4504..00000000 --- a/bbfd/gitlab-ci/functional-test.sh +++ /dev/null @@ -1,111 +0,0 @@ -#!/bin/bash - -echo "$0 preparation script" -pwd - -source ./gitlab-ci/shared.sh - -trap cleanup EXIT -trap cleanup SIGINT - -make clean -CFLAGS="-g -Os -fprofile-arcs -ftest-coverage -DUSPD_MAX_MSG_LEN=1048576" LDFLAGS="--coverage" make func-test -C ./ -check_ret $? -ls - -supervisorctl update -supervisorctl restart all -supervisorctl status all -exec_cmd ubus wait_for usp.raw usp -supervisorctl status all - -# debug logging -echo "Checking ubus status [$(date '+%d/%m/%Y %H:%M:%S')]" -ubus list -ubus -v list usp.raw -ubus -v list usp - -echo "Checking system resources" -free -h -df -h - -echo "## Preparing shared library for uspd msglen test ##" -exec_cmd make -C ./test - -echo "## Running python based verification of functionalities ##" -echo > ./funl-result.log -num=0 -for test in `ls -1 ./test/python/*.py` -do - num=$(( num + 1 )) - sleep 1 - $test - if [ $? -eq 0 ]; then - echo "ok ${num} - $test" >> ./funl-result.log - - else - echo "not ok ${num} - $test" >> ./funl-result.log - fi -done - -echo "1..${num}" >> ./funl-result.log -generate_report python_test ./funl-result.log - -# run functional on usp object validation -if [ -f "/usr/share/rpcd/schemas/usp*.json" ]; then - rm /usr/share/rpcd/schemas/usp*.json -fi - -fault=0 -# run functional on usp object validation -cp -r ./test/funl/schema/usp_test_positive.json /usr/share/rpcd/schemas/usp.json -ubus-api-validator -t 5 -f ./test/funl/validation/usp.validation.positive.json > ./funl-result.log -fault=$? -generate_report usp_positive ./funl-result.log - -cp -r ./test/funl/schema/usp_test_negative.json /usr/share/rpcd/schemas/usp.json -ubus-api-validator -t 5 -f ./test/funl/validation/usp.validation.negative.json > ./funl-result.log -fault=$(( $fault + $? )) -generate_report usp_negative ./funl-result.log - -# run functional on usp.raw object validation -rm /usr/share/rpcd/schemas/usp*.json -cp -r ./test/funl/schema/usp.raw_test_positive.json /usr/share/rpcd/schemas/usp.raw.json -ubus-api-validator -t 5 -f ./test/funl/validation/usp.raw.validation.positive.json > ./funl-result.log -fault=$(( $fault + $? )) -generate_report usp_raw_positive ./funl-result.log - -#test usp.raw for negative test cases -cp -r ./test/funl/schema/usp.raw_test_negative.json /usr/share/rpcd/schemas/usp.raw.json -ubus-api-validator -t 5 -f ./test/funl/validation/usp.raw.validation.negative.json > ./funl-result.log -fault=$(( $fault + $? )) -generate_report usp_raw_negative ./funl-result.log - -# TODO: add for granularity ubus objects -#uci set uspd.usp.granularitylevel='1' -#uci commit - -#ubus-api-validator -f ./test/funl/json/gran/gran.validation.json >> ./funl-result.log -#fault=$? - -#uci set uspd.usp.granularitylevel='0' -#uci commit - -supervisorctl stop all -supervisorctl status - -#report part -gcovr -r . --xml -o ./funl-test-coverage.xml -gcovr -r . -date +%s > timestamp.log - -echo "Checking memory leaks..." -grep -q "Leak" memory-report.xml -error_on_zero $? - -if [ "${fault}" -ne 0 ]; then - echo "Failed running ubus-api-validator fault[$fault]" - exit $fault -fi - -echo "Functional Test :: PASS" diff --git a/bbfd/gitlab-ci/install-dependencies.sh b/bbfd/gitlab-ci/install-dependencies.sh deleted file mode 100755 index 820fd4e0..00000000 --- a/bbfd/gitlab-ci/install-dependencies.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -echo "install dependencies of uspd" -pwd - -source ./gitlab-ci/shared.sh - -# install required packages -exec_cmd apt update -exec_cmd apt install -y python3-pip -exec_cmd pip3 install pexpect ubus -git config --global --add safe.directory ${PWD} -branch="$(git branch --show-current)" - -# install libbbf -cd /opt/dev -rm -rf bbf - -if [ -z "${BBF_TAR_URL}" ]; then - if ! git clone -b ${branch} https://dev.iopsys.eu/iopsys/bbf.git; then - exec_cmd git clone https://dev.iopsys.eu/iopsys/bbf.git - fi - - cd bbf - echo "BBF Upstream Hash ${UPSTREAM_BBF_SHA}, uspd branch ${branch}" - if [ -n "${UPSTREAM_BBF_SHA}" ]; then - exec_cmd git checkout ${UPSTREAM_BBF_SHA} - fi - - git log -1 - source ./gitlab-ci/shared.sh - install_libbbf - ./gitlab-ci/setup.sh -else - echo "## Installing upstream libbbf release from [${BBF_TAR_URL}] ##" - mkdir -p bbf - cd bbf - exec_cmd wget -q ${BBF_TAR_URL} -O bbf.sh - chmod +x bbf.sh - ./bbf.sh --prefix=/ --exclude-subdir --skip-license - ldconfig - cd .. -fi - -cd - -# install usermngr plugin -rm -rf /opt/dev/usermngr -exec_cmd git clone https://dev.iopsys.eu/iopsys/usermngr.git /opt/dev/usermngr - -echo "Compiling libusermngr" -make clean -C /opt/dev/usermngr/src -make -C /opt/dev/usermngr/src - -echo "Installing libusermngr" -cp -f /opt/dev/usermngr/src/libusermngr.so /usr/lib/bbfdm - diff --git a/bbfd/gitlab-ci/iopsys-supervisord.conf b/bbfd/gitlab-ci/iopsys-supervisord.conf deleted file mode 100644 index 7426d91c..00000000 --- a/bbfd/gitlab-ci/iopsys-supervisord.conf +++ /dev/null @@ -1,15 +0,0 @@ -[program:ubusd] -autorestart=false -priority=1 -command=/bin/bash -c "/usr/sbin/ubusd" - -[program:rpcd] -autorestart=false -priority=2 -command=/bin/bash -c "/usr/sbin/rpcd" - -[program:uspd] -autorestart=false -priority=3 -command=/bin/bash -c "/usr/bin/valgrind --xml=yes --xml-file=/builds/iopsys/uspd/memory-report.xml --leak-check=full --show-reachable=yes --show-leak-kinds=all --errors-for-leak-kinds=all --error-exitcode=1 --track-origins=yes --leak-resolution=high --show-error-list=yes --child-silent-after-fork=yes /builds/iopsys/uspd/uspd" - diff --git a/bbfd/gitlab-ci/setup.sh b/bbfd/gitlab-ci/setup.sh deleted file mode 100755 index 149eb766..00000000 --- a/bbfd/gitlab-ci/setup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -echo "preparation script" -pwd - -cp -r ./test/files/* / -cp ./gitlab-ci/iopsys-supervisord.conf /etc/supervisor/conf.d/ - -ls /etc/config/ -ls /usr/share/rpcd/schemas/ -ls /etc/supervisor/conf.d/ - -supervisorctl shutdown -supervisord -c /etc/supervisor/supervisord.conf diff --git a/bbfd/gitlab-ci/shared.sh b/bbfd/gitlab-ci/shared.sh deleted file mode 100644 index 43f1275c..00000000 --- a/bbfd/gitlab-ci/shared.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -function cleanup() -{ - echo "" -} - -function check_ret() -{ - ret=$1 - if [ "$ret" -ne 0 ]; then - echo "Validation of last command failed, ret(${ret})" - exit $ret - fi - -} - -function error_on_zero() -{ - ret=$1 - if [ "$ret" -eq 0 ]; then - echo "Validation of last command failed, ret(${ret})" - exit $ret - fi - -} - -function exec_cmd() -{ - echo "executing $@" - $@ >/dev/null 2>&1 - - if [ $? -ne 0 ]; then - echo "Failed to execute $@" - exit 1 - fi -} - -function generate_report() -{ - exec_cmd tap-junit --name "${1}" --input "${2}" --output report - sync -} - diff --git a/bbfd/gitlab-ci/unit-test.sh b/bbfd/gitlab-ci/unit-test.sh deleted file mode 100755 index 73c02462..00000000 --- a/bbfd/gitlab-ci/unit-test.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -echo "preparation script" -pwd -source ./gitlab-ci/shared.sh - -trap cleanup EXIT -trap cleanup SIGINT - -echo "Running the unit test cases" -make clean -make unit-test -C ./src/ -check_ret $? - -#report part -#GitLab-CI output -gcovr -r . -# Artefact -gcovr -r . --xml -o ./unit-test-coverage.xml -date +%s > timestamp.log - -echo "Unit test PASS" diff --git a/bbfd/src/ipc.h b/bbfd/ipc.h similarity index 100% rename from bbfd/src/ipc.h rename to bbfd/ipc.h diff --git a/bbfd/openwrt/uspd/Makefile b/bbfd/openwrt/uspd/Makefile deleted file mode 100644 index 42b2ef25..00000000 --- a/bbfd/openwrt/uspd/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=uspd -PKG_VERSION:=1.0.5 -PKG_RELEASE:=$(PKG_SOURCE_VERSION) - -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/uspd.git -PKG_SOURCE_VERSION=x -PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz - -PKG_MAINTAINER:=IOPSYS Dev - -CONFIG_SRC_TREE_OVERRIDE:=y - -include $(INCLUDE_DIR)/package.mk - -define Package/uspd - SECTION:=iopsys - CATEGORY:=IOPSYS - TITLE:=USP ubus backend - DEPENDS:=+libubox +ubus +libbbfdm -endef - -define Package/uspd/description - Ubus based backend for TR-369/USP which can be used by other USP agents - running on top of it. -endef - -TARGET_CFLAGS += \ - -I$(STAGING_DIR)/usr/include \ - -D_GNU_SOURCE - -define Package/uspd/install - $(INSTALL_DIR) $(1)/etc/init.d - $(INSTALL_DIR) $(1)/etc/config - $(INSTALL_BIN) ./files/uspd.init $(1)/etc/init.d/uspd - $(INSTALL_CONF) ./files/uspd.config $(1)/etc/config/uspd - $(INSTALL_DIR) $(1)/usr/sbin - $(INSTALL_BIN) $(PKG_BUILD_DIR)/uspd $(1)/usr/sbin/ -endef - -$(eval $(call BuildPackage,uspd)) diff --git a/bbfd/openwrt/uspd/files/uspd.config b/bbfd/openwrt/uspd/files/uspd.config deleted file mode 100644 index d8b3621c..00000000 --- a/bbfd/openwrt/uspd/files/uspd.config +++ /dev/null @@ -1,2 +0,0 @@ -config uspd 'usp' - option granularitylevel '0' diff --git a/bbfd/openwrt/uspd/files/uspd.init b/bbfd/openwrt/uspd/files/uspd.init deleted file mode 100644 index 2f788976..00000000 --- a/bbfd/openwrt/uspd/files/uspd.init +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=94 -STOP=10 - -USE_PROCD=1 -PROG=/usr/sbin/uspd - -start_service() { - procd_open_instance - procd_set_param command ${PROG} - procd_set_param respawn - procd_close_instance -} - -reload_service() { - stop - start -} - -service_triggers() -{ - procd_add_reload_trigger "cwmp" - procd_add_config_trigger "config.change" "uspd" /etc/init.d/uspd restart -} diff --git a/bbfd/openwrt/uspd/git-src b/bbfd/openwrt/uspd/git-src deleted file mode 120000 index a49c86c1..00000000 --- a/bbfd/openwrt/uspd/git-src +++ /dev/null @@ -1 +0,0 @@ -../../.git/ \ No newline at end of file diff --git a/bbfd/src/operate.c b/bbfd/operate.c similarity index 100% rename from bbfd/src/operate.c rename to bbfd/operate.c diff --git a/bbfd/src/operate.h b/bbfd/operate.h similarity index 100% rename from bbfd/src/operate.h rename to bbfd/operate.h diff --git a/bbfd/src/pretty_print.c b/bbfd/pretty_print.c similarity index 100% rename from bbfd/src/pretty_print.c rename to bbfd/pretty_print.c diff --git a/bbfd/src/pretty_print.h b/bbfd/pretty_print.h similarity index 100% rename from bbfd/src/pretty_print.h rename to bbfd/pretty_print.h diff --git a/bbfd/schemas/ubus/usp.json b/bbfd/schemas/ubus/usp.json deleted file mode 100644 index d19d5027..00000000 --- a/bbfd/schemas/ubus/usp.json +++ /dev/null @@ -1,791 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/usp.md", - "type": "object", - "title": "usp", - "object": "usp", - "additionalProperties": false, - "properties": { - "get_supported_dm": { - "title": "Get list of supported datamodel parameters", - "description": "Schema will have all the nodes/objects supported by libbbf", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "schema_type": { - "type": "integer", - "minimum": 0, - "maximum": 3, - "description": "0-All, 1-Parameter only 2- Event only 3- operate only" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type", - "writable" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - ] - } - } - }, - "list_operate": { - "title": "List down supported usp operate commands", - "description": "Commands will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "items": { - "type": "string" - } - }, - "out": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "type": "object", - "properties": {}, - "examples": [ - "root@iopsys:/tmp# ubus call usp get '{\"path\":\"Device.Users.User.2.\"}'\n{\n\t\"User\": [\n\t\t{\n\t\t\t\"Alias\": \"\",\n\t\t\t\"Enable\": true,\n\t\t\t\"Language\": \"\",\n\t\t\t\"Password\": \"\",\n\t\t\t\"RemoteAccessCapable\": false,\n\t\t\t\"Username\": \"user_2\"\n\t\t}\n\t]\n}", - "root@iopsys:/tmp# ubus call usp get '{\"path\":\"Device.Users.\"}'\n{\n\t\"Users\": {\n\t\t\"User\": [\n\t\t\t{\n\t\t\t\t\"Alias\": \"\",\n\t\t\t\t\"Enable\": true,\n\t\t\t\t\"Language\": \"\",\n\t\t\t\t\"Password\": \"\",\n\t\t\t\t\"RemoteAccessCapable\": true,\n\t\t\t\t\"Username\": \"user\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"Alias\": \"\",\n\t\t\t\t\"Enable\": true,\n\t\t\t\t\"Language\": \"\",\n\t\t\t\t\"Password\": \"\",\n\t\t\t\t\"RemoteAccessCapable\": false,\n\t\t\t\t\"Username\": \"user_2\"\n\t\t\t}\n\t\t],\n\t\t\"UserNumberOfEntries\": 2\n\t}\n}" - ] - } - ] - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "description": "value of the object element provided in path, path should contains valid writable object element", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1.SSID\", \"value\":\"test_ssid\"}", - "{\"path\":\"Device.WiFi.SSID.2.Enable\", \"value\":\"true\"}", - "{\"path\":\"Device.WiFi.SSID.1.Enable\", \"value\":\"0\"}" - ] - }, - "values": { - "description": "To set multiple values at once, path should be relative to object elements", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1\", \"values\":{\".SSID\":\"test_ssid\",\".Name\":\"test_name\"}}", - "{\"path\":\"Device.WiFi.SSID.2\", \"values\":{\".SSID\":\"test_ssid\"}}" - ], - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "status": { - "const": "0" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - ] - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "instance": { - "type": "string" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - } - }, - "validate": { - "title": "Validate a datamodel object", - "description": "API to check if a datamodel object is available", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "type": "object", - "properties": { - "parameter": { - "type": "string" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - }, - "instances": { - "title": "Instance query handler", - "description": "Get the instances of multi object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/instance_t" - } - } - } - } - } - } - ] - } - } - }, - "object_names": { - "title": "Get objects names", - "description": "Get names of all the objects below input object path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": { - "$ref": "#/definitions/type_t" - }, - "required": [ - "parameter", - "type", - "writable" - ], - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - } - } - } - } - } - } - ] - } - } - }, - "operate": { - "title": "Operate handler", - "description": "Operate on object element provided in path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "action" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance-mode": { - "type": "integer", - "description": "" - }, - "action": { - "description": "Opreate command as defined in TR-369, TR-181-2.13", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.\", \"action\":\"Reset\\(\\)\"}" - ], - "pattern": "[a-zA-Z]+\\(\\)" - }, - "input": { - "description": "Input arguments for the operate command as defined in TR-181-2.13", - "examples": [ - "{\"path\":\"Device.IP.Diagnostics\", \"action\":\"IPPing\\(\\)\", \"input\":{\"Host\":\"iopsys.eu\"}}" - ], - "type": "object", - "properties": {} - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code in fault_t" - } - }, - { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "object", - "required": [ - "Results" - ], - "properties": { - "Results": { - "type": "array", - "items": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "result": { - "type": "array", - "items": { - "type": "object", - "properties": { - "Result": { - "type": "string", - "Description": "Success or Failure" - } - } - } - } - } - } - } - }, - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - ] - } - } - } - } -} diff --git a/bbfd/schemas/ubus/usp.raw.json b/bbfd/schemas/ubus/usp.raw.json deleted file mode 100644 index 3393e1b6..00000000 --- a/bbfd/schemas/ubus/usp.raw.json +++ /dev/null @@ -1,1420 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/usp.raw.md", - "type": "object", - "title": "usp.raw", - "object": "usp.raw", - "additionalProperties": false, - "properties": { - "get_supported_dm": { - "title": "Get list of supported datamodel parameters", - "description": "Schema will have all the nodes/objects supported by libbbf", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "schema_type": { - "type": "integer", - "minimum": 0, - "maximum": 3, - "description": "0-All, 1-Parameter only 2- Event only 3- operate only" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "parameter", - "type" - ] - } - ] - } - } - } - ] - } - } - }, - "dump_schema": { - "title": "Get available datamodel schema from Device", - "description": "Schema will have all the nodes/objects supported by data model", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "unique_keys": { - "type": "array", - "uniqueItems": true, - "maxItems": 8, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "parameter", - "writable", - "type" - ] - }, - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - } - }, - "required": [ - "parameter", - "writable", - "type" - ] - } - ] - } - }, - "required": [ - "parameters" - ] - } - } - }, - "list_operate": { - "title": "List down supported usp operate commands", - "description": "Commands will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - } - }, - "list_events": { - "title": "List down supported usp events", - "description": "events will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "type": "string", - "pattern": "xsd:event" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - } - }, - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "value", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "getm_values": { - "title": "Get multiple values", - "description": "Query multiple paths at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "paths": { - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - } - } - ] - } - } - } - } - }, - "getm_names": { - "title": "Get multiple object names", - "description": "Query multiple object names at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "paths": { - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - } - } - ] - } - } - } - } - }, - "instances": { - "title": "Instance query handler", - "description": "Get the instances of multi object", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "required": [ - "parameter" - ], - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/instance_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "validate": { - "title": "Validate a datamodel path", - "description": "Validate a path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "$ref": "#/definitions/path_t" - } - } - } - ] - } - } - }, - "object_names": { - "title": "Get objects names", - "description": "Get names of all the objects below input object path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "writable", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "writable": { - "type": "integer", - "description": "1 if object is writable, 0 otherwise" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - }, - "instance": { - "type": "string" - } - } - } - ] - } - } - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "value", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "description": "value of the object element provided in path, path should contains valid writable object element", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1.SSID\", \"value\":\"test_ssid\"}", - "{\"path\":\"Device.WiFi.SSID.2.Enable\", \"value\":\"true\"}", - "{\"path\":\"Device.WiFi.SSID.1.Enable\", \"value\":\"0\"}" - ] - }, - "values": { - "description": "To set multiple values at once, path should be relative to object elements", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1\", \"values\":{\".SSID\":\"test_ssid\",\".Name\":\"test_name\"}}", - "{\"path\":\"Device.WiFi.SSID.2\", \"values\":{\".SSID\":\"test_ssid\"}}" - ], - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - } - } - }, - "output": { - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "operate": { - "title": "Operate handler", - "description": "Operate on object element provided in path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "action" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "action": { - "description": "Opreate command as defined in TR-369, TR-181-2.13", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.\", \"action\":\"Reset\\(\\)\"}" - ] - }, - "input": { - "description": "Input arguments for the operate command as defined in TR-181-2.13", - "examples": [ - "{\"path\":\"Device.IP.Diagnostics\", \"action\":\"IPPing\\(\\)\", \"input\":{\"Host\":\"iopsys.eu\"}}" - ], - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "Results" - ], - "properties": { - "Results": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "parameters": { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "type": "string" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - } - } - ] - } - } - } - } - }, - "transaction_start": { - "title": "Start a transaction before set/add/del operations", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "app": { - "type": "string" - }, - "max_timeout": { - "type": "integer", - "minimum":0 - } - }, - "required": [ - "app" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "error": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_abort": { - "title": "Aborts an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "error": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_commit": { - "title": "Commits an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "restart_services": { - "type": "boolean" - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "updated_services": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_status": { - "title": "Shows status of a transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "string", - "description": "on-going or not-exists" - }, - "remaining_time": { - "type": "integer" - }, - "app": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "setm_values": { - "title": "Set values of multiple objects at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "pv_tuple", - "transaction_id" - ], - "properties": { - "pv_tuple": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - } - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - }, - "transaction_id": { - "type": "integer", - "minimum": 0 - } - } - }, - "output": { - "type": "object", - "oneof": [ - { - "required": [ - "status" - ] - }, - { - "required": [ - "parameters" - ] - } - ], - "properties": { - "status": { - "type": "boolean" - }, - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "notify_event": { - "title": "notify occurance of an event on ubus", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "input": { - "type": "string" - } - } - }, - "output": {} - } - } - } -} diff --git a/bbfd/schemas/uci/uspd.json b/bbfd/schemas/uci/uspd.json deleted file mode 100644 index 8c9ea3a8..00000000 --- a/bbfd/schemas/uci/uspd.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "uspd": [ - { - "section": "uspd", - "description": "USP daemon Settings", - "multi": false, - "options": [ - { - "name": "granularitylevel", - "type": "integer", - "required": "no", - "default": "0", - "description": "Creates ubus objects along with object names, depth of object name depends on granularitylevel" - }, - { - "name": "debug", - "type": "boolean", - "required": "no", - "default": "", - "description": "Enabled debug logging" - }, - { - "name": "sock", - "type": "string", - "required": "no", - "default": "", - "description": "Path for ubus socket to register uspd services" - }, - { - "name": "transaction_timeout", - "type": "integer", - "required": "no", - "default": "10", - "description": "Transaction timeout value in seconds" - }, - { - "name": "loglevel", - "type": "integer", - "required": "no", - "default": "1", - "description": "Internal loglevel for debugging {0: No Logs; 1: Errors only; 2: Errors and warnings; 3: Error, warning and info; 4: Everything}" - }, - { - "name": "subprocess_level", - "type": "integer", - "required": "no", - "default": "2", - "description": "This parameter configures when subprocess can be used for get operation. Level here denotes the Datamodel object depth up-to which subprocess will be used to collect the get data. For example, if this is configured to 1, then only get for 'Device.' shall be called within the subprocess. If configured as level 2, then all the get with up-to depth 2 like 'Device.WiFi.', 'Device.IP.' shall be called in subprocess." - }, - { - "name": "bbf_caching_time", - "type": "integer", - "required": "no", - "default": "0", - "description": "Max caching time in seconds for ubus output used in datamodel parameters. If not configured, output shall be cleared end the end of call." - }, - { - "name": "dm_version", - "type": "string", - "required": "no", - "default": "", - "description": "Configures the datamodel version to use for datamodel parameters, if not configured show all defined datamodel" - }, - { - "name": "refresh_time", - "type": "integer", - "required": "no", - "default": "5", - "description": "The time period in seconds after which uspd will refresh the datamodel instances in a periodic manner. If configured to '0' then instance updater will be disabled. If not configured at all then after every 5 seconds datamodel instances will be refreshed." - } - ] - } - ] -} diff --git a/bbfd/src/set.c b/bbfd/set.c similarity index 100% rename from bbfd/src/set.c rename to bbfd/set.c diff --git a/bbfd/src/set.h b/bbfd/set.h similarity index 100% rename from bbfd/src/set.h rename to bbfd/set.h diff --git a/bbfd/src/Makefile b/bbfd/src/Makefile deleted file mode 100644 index f1bf9f94..00000000 --- a/bbfd/src/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -PROG = uspd -OBJS =common.o get.o get_helper.o set.o operate.o add_delete.o pretty_print.o usp.o events.o -CP=cp -f - -PROG_CFLAGS = $(CFLAGS) \ - -fstrict-aliasing \ - -Wall -Wextra -Werror \ - -Wformat \ - -Wformat-signedness -fPIC - -PROG_LDFLAGS = $(LDFLAGS) -PROG_LDFLAGS += -luci -lubus -lubox -ljson-c -lblobmsg_json -lbbfdm - -ifeq ($(USE_MBEDTLS),yes) -PROG_LDFLAGS += -lmbedcrypto -lmbedtls -endif - -ifeq ($(USE_OPENSSL),yes) -PROG_LDFLAGS += -lssl -lcrypto -endif - -ifeq ($(USE_WOLFSSL),yes) -PROG_LDFLAGS += -lwolfssl -endif - -%.o: %.c - $(CC) $(PROG_CFLAGS) -c -o $@ $< - -all: ${PROG} - -${PROG}: $(OBJS) - $(CC) $(PROG_CFLAGS) -o $@ $^ $(PROG_LDFLAGS) - $(CP) ${PROG} ../${PROG} - -test: PROG_CFLAGS += -fPIC -test: ${OBJS} - ${CC} $(PROG_CFLAGS) -shared -o libuspd.so ${OBJS} $(PROG_LDFLAGS) - $(CP) libuspd.so ../libuspd.so - -unit-test: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -unit-test: LDFLAGS += --coverage -unit-test: clean_objs -unit-test: test - make -C ../test/cmocka unit-test USPD_LIB_DIR=$(PWD) - -func-test: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -func-test: LDFLAGS += --coverage -func-test: clean_objs -func-test: ${PROG} - -clean_objs: - rm -f *.o -clean: - rm -f *.o libuspd.so $(PROG) - rm -f *.xml *.html - find -name '*.gcda' -exec rm {} -fv \; - find -name '*.gcno' -exec rm {} -fv \; - find -name '*.gcov' -exec rm {} -fv \; diff --git a/bbfd/test/Makefile b/bbfd/test/Makefile deleted file mode 100644 index 073683af..00000000 --- a/bbfd/test/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -LIB = libuspd_test.so - -LIB_OBJS = libuspd_test.o -LIB_CFLAGS = $(CFLAGS) -Wall -Werror -fPIC -LIB_LDFLAGS = $(LDFLAGS) - -%.o: %.c - $(CC) $(LIB_CFLAGS) -I/usr/local/include/libbbf_api/ -c -o $@ $< - -all: $(LIB) - -$(LIB): $(LIB_OBJS) - $(CC) $(LIB_CFLAGS) $(LIB_LDFLAGS) -shared -o $@ $^ - -clean: - rm -fv *.o $(LIB) diff --git a/bbfd/test/Readme.md b/bbfd/test/Readme.md deleted file mode 100644 index ff2f41be..00000000 --- a/bbfd/test/Readme.md +++ /dev/null @@ -1,39 +0,0 @@ -# USPD Tests -USPD module test is based on `iopsys/code-analysis-dev` docker image. It consists -of below test phases, in each phase different kind of test perform: - -1. Static code analysis -2. Unit Test -3. API Test -4. Functional Test - -## 1. Static code Analysis -In this stage code is being tested for flaws by running static code analysers, -it also runs CPD tests which determine the optimal reusable codes. -Tests running in this phase are: - - - Flaw finder - - CPP Check - - CPD Test - -## 2. Unit Test -In this stage various wrapper functions being tested for memory leaks using -`valgrind`. -Tests running in this phase are: - - Cmocka Test cases - - Coverage report - - memory check using valgrind - -## 3. API Test -In this stage ubus exposed APIs getting tested using `ubus-api-validator` - -## 4. Functional Test -In this stage functionality provided by uspd is getting tested. - -Below tests and verifications done in this stage: -- Compilation check -- Python based bug verification -- Functionality testing based on schema validation - - - diff --git a/bbfd/test/api/json/usp.raw.validation.json b/bbfd/test/api/json/usp.raw.validation.json deleted file mode 100644 index d9998e80..00000000 --- a/bbfd/test/api/json/usp.raw.validation.json +++ /dev/null @@ -1,157 +0,0 @@ -{ - "object": "usp.raw", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "hello", - "rc": 3 - }, - { - "method": "instances", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "transaction_start", - "args": { - "app": "test" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.SSID", - "value": "test-2g", - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "transaction_abort", - "args": { - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"127.0.0.1", - "Timeout":".5" - } - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.USB.", - "next-level":false, - "schema_type":1 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.WiFi." - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.WiFi.", - "next-level":false, - "schema_type":2 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.USB.", - "next-level":false, - "schema_type":3 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.WiFi.", - "schema_type":1 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": {}, - "rc": 0 - }, - { - "method": "dump_schema", - "args": {}, - "rc": 0 - }, - { - "method": "list_operate", - "args": {}, - "rc": 0 - }, - { - "method": "transaction_start", - "args": { - "app": "test" - }, - "rc": 0 - }, - { - "method": "setm_values", - "args": { - "pv_tuple": [{"path":"Device.Users.User.1.Alias", "value":"cpe-1"}, {"path":"Device.Users.User.2.Alias", "value":"cpe-2"}], - "proto": "usp", - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "transaction_commit", - "args": { - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "getm_names", - "args": { - "paths": ["Device.WiFi.SSID.1.SSID","Device.WiFi.SSID.2.SSID"], - "proto": "usp" - }, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/api/json/usp.validation.json b/bbfd/test/api/json/usp.validation.json deleted file mode 100644 index 02e9d630..00000000 --- a/bbfd/test/api/json/usp.validation.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "object": "usp", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "instances", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "validate", - "args": { - "path": "Device.Users.User.1.Alias", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.SSID", - "value": "test-2g" - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"127.0.0.1" - } - }, - "rc": 0 - }, - { - "method": "add_object", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "list_operate", - "args": {}, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.USB.", - "next-level":false, - "schema_type":1 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.WiFi." - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.WiFi.", - "next-level":false, - "schema_type":2 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path":"Device.USB.", - "next-level":false, - "schema_type":3 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "Path":"Device.WiFi.", - "schema_type":1 - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": {}, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/cmocka/Makefile b/bbfd/test/cmocka/Makefile deleted file mode 100644 index 85d22c48..00000000 --- a/bbfd/test/cmocka/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -CC = gcc -USPD_LIB_DIR ?= $(shell dirname $(PWD)) -USPD_LIB = -luspd -L$(USPD_LIB_DIR) -CMOCKA_LIB = -l cmocka -LIBS = $(USPD_LIB) $(CMOCKA_LIB) -luci -pthread -lubus -lubox -ljson-c -lblobmsg_json -lbbfdm -lpthread -CFLAGS = -g -Wall -I../../src -LDFLAGS = $(LIBS) -Wl,-rpath=$(USPD_LIB_DIR) -I$(USPD_LIB_DIR) -UNIT_TESTS = unit_test_uspd - -VALGRIND = valgrind --leak-check=full --show-reachable=no \ - --show-leak-kinds=all --errors-for-leak-kinds=all \ - --error-exitcode=1 --track-origins=yes - -unit_test_uspd: unit_test_uspd.o - $(CC) -o $@ $^ $(LDFLAGS) - -unit-test: $(UNIT_TESTS) - $(foreach testprog, $(UNIT_TESTS), sudo $(VALGRIND) ./$(testprog);) - -.PHONY: clean -clean: - rm $(UNIT_TESTS) *.o -fv - diff --git a/bbfd/test/cmocka/test_utils.h b/bbfd/test/cmocka/test_utils.h deleted file mode 100644 index 07c19276..00000000 --- a/bbfd/test/cmocka/test_utils.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef TEST_UTILS_H -#define TEST_UTILS_H - -#define GET_PATH "Device.DeviceInfo.Manufacturer" -#define GET_PROTO "usp" -#define GET_RAW_PROTO "usp.raw" -#define GET_CWMP_PROTO "cwmp" - -#endif diff --git a/bbfd/test/cmocka/unit_test_uspd.c b/bbfd/test/cmocka/unit_test_uspd.c deleted file mode 100644 index 740a3bbb..00000000 --- a/bbfd/test/cmocka/unit_test_uspd.c +++ /dev/null @@ -1,980 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "usp.h" -#include "get_helper.h" -#include "test_utils.h" - -struct test_ctx { - struct usp_context uspctx; - struct blob_buf bb; - struct ubus_object usp; - struct ubus_object usp_raw; - FILE *fp; - struct ubus_request_data *req; - unsigned long instance; -}; - -// Stub functions to override existing functionalities -void ubus_complete_deferred_request(struct ubus_context *ctx, - struct ubus_request_data *req, int ret) -{ -} - -static int group_setup(void **state) -{ - struct test_ctx *ctx = calloc(1, sizeof(struct test_ctx)); - - if (!ctx) - return -1; - - openlog("unit_test", LOG_CONS| LOG_NDELAY, LOG_LOCAL1); - - memset(&ctx->uspctx, 0, sizeof(struct usp_context)); - - ubus_connect_ctx(&ctx->uspctx.ubus_ctx, NULL); - - INIT_LIST_HEAD(&ctx->uspctx.obj_list); - INIT_LIST_HEAD(&ctx->uspctx.instances); - INIT_LIST_HEAD(&ctx->uspctx.old_instances); - - usp_pre_init(&ctx->uspctx); - - remove("/tmp/test.log"); - ctx->usp.name = "usp"; - ctx->usp_raw.name = "usp.raw"; - memset(&ctx->bb, 0, sizeof(struct blob_buf)); - ctx->req = (struct ubus_request_data *) calloc(1, sizeof(struct ubus_request_data)); - *state = ctx; - - return 0; -} - -static int setup(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - - remove("/tmp/test.log"); - blob_buf_init(&ctx->bb, 0); - - return 0; -} - -static int group_teardown(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - - usp_cleanup(&ctx->uspctx); - blob_buf_free(&ctx->bb); - ubus_shutdown(&ctx->uspctx.ubus_ctx); - free(ctx->req); - free(ctx); - remove("/tmp/test.log"); - - return 0; -} - -static void test_api_usp_get_DeviceInfo_Manufacturer(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "DeviceInfo.Manufacturer"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - //printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "fault", &tmp); - assert_string_equal(json_object_to_json_string(tmp), "7026"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_raw_getm_values_Device_WiFi_SSID_Alias(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct json_object *local; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - void *paths; - paths = blobmsg_open_array(bb, "paths"); - blobmsg_add_string(bb, NULL, "Device.WiFi.SSID.1.Alias"); - blobmsg_close_array(bb, paths); - blobmsg_add_string(bb, "proto", GET_RAW_PROTO); - - usp_getm_values(uctx, obj, req, "getm_values", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "parameters", &tmp); - - if (json_object_get_type(tmp) == json_type_array) { - for (int i = 0; ibb; - struct ubus_object *obj = &ctx->usp_raw; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct json_object *local; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User.1.Username"); - blobmsg_add_string(bb, "proto", GET_RAW_PROTO); - - usp_get_handler(uctx, obj, req, "validate", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "parameters", &tmp); - if (json_object_get_type(tmp) == json_type_array) { - for (int i = 0; ibb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct json_object *local; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User.1.Username"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "validate", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "parameters", &tmp); - if (json_object_get_type(tmp) == json_type_array) { - for (int i = 0; ibb; - struct ubus_object *obj = &ctx->usp_raw; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct json_object *local; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - void *paths; - paths = blobmsg_open_array(bb, "paths"); - blobmsg_add_string(bb, NULL, "Device.WiFi.SSID.1.Alias"); - blobmsg_close_array(bb, paths); - blobmsg_add_string(bb, "proto", GET_RAW_PROTO); - - usp_getm_names(uctx, obj, req, "getm_names", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "parameters", &tmp); - - if (json_object_get_type(tmp) == json_type_array) { - for (int i = 0; iuspctx.ubus_ctx; - struct ubus_object *obj = &ctx->usp_raw; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj; - - usp_list_schema(ubus_ctx, obj, req, "dump_schema", NULL); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - //printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_put(jobj); - return; -} - -static void test_api_usp_list_operate(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct ubus_context *ubus_ctx = &ctx->uspctx.ubus_ctx; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj; - - usp_list_operate(ubus_ctx, obj, req, "list_operate", NULL); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - //printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_wrong_name_Device_IP_Interface(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path","Device.IP._Interface.1.Status"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "fault", &tmp); - assert_string_equal(json_object_to_json_string(tmp), "7026"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_wrong_braces_Device_IP_Interface(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path","Device.IP.Interface.{Type==\"Normal\"}.Status"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "fault", &tmp); - assert_string_equal(json_object_to_json_string(tmp), "7026"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_wrong_exp_Device_IP_Interface(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path","Device.IP.Interface.[Type==\"Normal\"&&IPv4Address.*.AddressingType==\"Static\"].Status"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "fault", &tmp); - assert_string_equal(json_object_to_json_string(tmp), "7011"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_Device_IP_Interface(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.IP.Interface.[]."); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "fault", &tmp); - assert_string_equal(json_object_to_json_string(tmp), "7026"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_search_exp_Device_WiFi_SSID(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp, *array_obj; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.WiFi.SSID.[Status==\"Up\"].Alias"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "SSID"); - if (json_object_get_type(array_obj) == json_type_array) { - for (int i = 0; ibb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp, *array_obj; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.WiFi.SSID.*.Alias"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "SSID"); - - if (json_object_get_type(array_obj) == json_type_array) { - for (int i = 0; i < json_object_array_length(array_obj); ++i) { - char temp[512]; - struct json_object *array_index_obj = json_object_array_get_idx(array_obj, i); - - json_object_object_get_ex(array_index_obj, "Alias", &tmp); - snprintf(temp, 512, "cpe-%d", i+1); - assert_string_equal(json_object_get_string(tmp), temp); - } - } - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_wrong_oper_Device_WiFi_SSID(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct ubus_request_data *req = ctx->req; - struct json_object *jobj, *tmp; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.WiFi.SSID.[Status>Up].Alias"); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "fault", &tmp); - assert_string_equal(json_object_to_json_string(tmp), "7008"); - - json_object_put(jobj); - return; -} - - -static void test_api_usp_get_Device_DeviceInfo_Manufacturer(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", GET_PATH); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "Manufacturer", &tmp); - assert_string_equal(json_object_get_string(tmp), "iopsys"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_add_object_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp, *array_index_obj, *array_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User."); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_add_del_handler(uctx, obj, req, "add_object", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - assert_string_equal(json_object_get_string(tmp), "Device.Users.User."); - json_object_object_get_ex(array_index_obj, "status", &tmp); - assert_string_equal(json_object_get_string(tmp), "true"); - - tmp = NULL; - json_object_object_get_ex(array_index_obj, "instance", &tmp); - assert_non_null(tmp); - ctx->instance = strtoul(json_object_get_string(tmp), NULL, 10); - - assert_int_not_equal((int)ctx->instance, 0); - - json_object_put(jobj); - return; -} - -static void test_api_usp_del_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - assert_int_not_equal((int)ctx->instance, 0); - - char path[1024] = {0}; - snprintf(path, sizeof(path), "Device.Users.User.%lu.", ctx->instance); - blobmsg_add_string(bb, "path", path); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_add_del_handler(uctx, obj, req, "del_object", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - assert_string_equal(json_object_get_string(tmp), path); - - tmp = json_object_object_get(array_index_obj, "status"); - assert_string_equal(json_object_get_string(tmp), "true"); - - ctx->instance = 0; - - json_object_put(jobj); - return; -} - -static void test_api_usp_instances_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User."); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "instances", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - - assert_non_null(jobj); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - - assert_string_equal(json_object_get_string(tmp), "Device.Users.User.1"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_instances_Device(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device."); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "instances", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - - assert_non_null(jobj); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - assert_non_null(array_index_obj); - - json_object_put(jobj); - return; -} - -static void test_api_usp_set_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - assert_int_not_equal((int)ctx->instance, 0); - - char path[1024] = {0}; - snprintf(path, sizeof(path), "Device.Users.User.%lu.Username", ctx->instance); - blobmsg_add_string(bb, "path", path); - blobmsg_add_string(bb, "value", "user2"); - - usp_set(uctx, obj, req, "set", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - tmp = json_object_object_get(jobj, "status"); - assert_string_equal(json_object_get_string(tmp), "true"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_object_name_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User."); - blobmsg_add_string(bb, "proto", GET_PROTO); - blobmsg_add_u8(bb, "next-level", true); - - usp_get_handler(uctx, obj, req, "object_names", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - assert_string_equal(json_object_get_string(tmp), "Device.Users.User.1."); - - json_object_put(jobj); - return; -} - -static void test_api_usp_raw_get_Device_DeviceInfo_Manufacturer(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", GET_PATH); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - - assert_string_equal(json_object_get_string(tmp), "Device.DeviceInfo.Manufacturer"); - - tmp = json_object_object_get(array_index_obj, "value"); - assert_string_equal(json_object_get_string(tmp), "iopsys"); - - json_object_put(jobj); - return; -} - - -static void test_api_usp_raw_add_object_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - int trans_id; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - trans_id = transaction_start("ut", 0); - blobmsg_add_string(bb, "path", "Device.Users.User."); - blobmsg_add_string(bb, "proto", GET_PROTO); - blobmsg_add_u32(bb, "transaction_id", trans_id); - usp_raw_add_del_handler(uctx, obj, req, "add_object", bb->head); - transaction_commit(trans_id, NULL, true); - - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - json_object_object_get_ex(array_index_obj, "status", &tmp); - assert_string_equal(json_object_get_string(tmp), "true"); - - tmp = NULL; - json_object_object_get_ex(array_index_obj, "instance", &tmp); - assert_non_null(tmp); - ctx->instance = strtoul(json_object_get_string(tmp), NULL, 10); - - assert_int_not_equal((int)ctx->instance, 0); - - json_object_put(jobj); - return; -} - - -static void test_api_usp_raw_del_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - int trans_id; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - assert_int_not_equal((int)ctx->instance, 0); - - char path[1024] = {0}; - snprintf(path, sizeof(path), "Device.Users.User.%lu.", ctx->instance); - - trans_id = transaction_start("ut", 0); - blobmsg_add_string(bb, "path", path); - blobmsg_add_string(bb, "proto", GET_PROTO); - blobmsg_add_u32(bb, "transaction_id", trans_id); - usp_raw_add_del_handler(uctx, obj, req, "del_object", bb->head); - transaction_commit(trans_id, NULL, true); - - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - assert_string_equal(json_object_get_string(tmp), path); - - tmp = json_object_object_get(array_index_obj, "status"); - assert_string_equal(json_object_get_string(tmp), "true"); - - ctx->instance = 0; - - json_object_put(jobj); - return; -} - -static void test_api_usp_raw_instances_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User."); - blobmsg_add_string(bb, "proto", GET_PROTO); - - usp_get_handler(uctx, obj, req, "instances", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - - assert_string_equal(json_object_get_string(tmp), "Device.Users.User.1"); - - json_object_put(jobj); - return; -} - -static void test_api_usp_raw_set_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct json_object *jobj, *tmp; - struct ubus_request_data *req = ctx->req; - int trans_id; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - assert_int_not_equal((int)ctx->instance, 0); - - char path[1024] = {0}; - snprintf(path, sizeof(path), "Device.Users.User.%lu.Username", ctx->instance); - - trans_id = transaction_start("ut", 0); - blobmsg_add_string(bb, "path", path); - blobmsg_add_string(bb, "value", "user3"); - blobmsg_add_u32(bb, "transaction_id", trans_id); - usp_raw_set(uctx, obj, req, "set", bb->head); - transaction_commit(trans_id, NULL, true); - - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - tmp = json_object_object_get(jobj, "status"); - if (tmp == NULL) { - json_object_put(jobj); - } - assert_non_null(tmp); - assert_string_equal(json_object_get_string(tmp), "true"); - json_object_put(jobj); - - return; -} - -static void test_api_usp_raw_object_name_Device_Users_User(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp_raw; - struct json_object *jobj, *tmp, *array_obj, *array_index_obj; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", "Device.Users.User."); - blobmsg_add_string(bb, "proto", GET_PROTO); - blobmsg_add_u8(bb, "next-level", true); - - usp_get_handler(uctx, obj, req, "object_names", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - array_obj = json_object_object_get(jobj, "parameters"); - array_index_obj = json_object_array_get_idx(array_obj, 0); - - tmp = json_object_object_get(array_index_obj, "parameter"); - assert_string_equal(json_object_get_string(tmp), "Device.Users.User.1."); - - json_object_put(jobj); - return; -} - -static void test_api_usp_get_cwmp_Device_DeviceInfo_Manufacturer(void **state) -{ - struct test_ctx *ctx = (struct test_ctx *) *state; - struct blob_buf *bb = &ctx->bb; - struct ubus_object *obj = &ctx->usp; - struct json_object *jobj, *tmp; - struct ubus_request_data *req = ctx->req; - struct ubus_context *uctx = &ctx->uspctx.ubus_ctx; - - blobmsg_add_string(bb, "path", GET_PATH); - blobmsg_add_string(bb, "proto", GET_CWMP_PROTO); - - usp_get_handler(uctx, obj, req, "get", bb->head); - jobj = json_object_from_file("/tmp/test.log"); - assert_non_null(jobj); - printf("json(%s)\n", json_object_to_json_string(jobj)); - - json_object_object_get_ex(jobj, "Manufacturer", &tmp); - assert_string_equal(json_object_get_string(tmp), "iopsys"); - - json_object_put(jobj); - return; -} - -// overriding this function -int ubus_send_event(struct ubus_context *ctx, const char *id, - struct blob_attr *data) -{ - char *str; - - str = blobmsg_format_json(data, true); - printf("{\"%s\": %s }", id, str); - - free(str); - - return 0; -} - - -int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, - struct blob_attr *msg) -{ - char *str; - FILE *fp; - - fp = fopen("/tmp/test.log", "w"); - if (!fp) { - printf("failed to open file\n"); - return -1; - } - - if (!msg) { - fclose(fp); - return -1; - } - - str = blobmsg_format_json_indent(msg, true, -1); - fprintf(fp, "%s", str); - - fclose(fp); - free(str); - return 0; -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - // usp object test cases - cmocka_unit_test_setup(test_api_usp_list_operate, setup), - cmocka_unit_test_setup(test_api_usp_get_Device_DeviceInfo_Manufacturer, setup), - cmocka_unit_test_setup(test_api_usp_get_Device_WiFi_SSID, setup), - cmocka_unit_test_setup(test_api_usp_get_search_exp_Device_WiFi_SSID, setup), - cmocka_unit_test_setup(test_api_usp_instances_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_instances_Device, setup), - cmocka_unit_test_setup(test_api_usp_resolve_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_add_object_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_set_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_del_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_object_name_Device_Users_User, setup), - // usp.raw object test cases - cmocka_unit_test_setup(test_api_usp_raw_dump_schema, setup), - cmocka_unit_test_setup(test_api_usp_raw_get_Device_DeviceInfo_Manufacturer, setup), - cmocka_unit_test_setup(test_api_usp_raw_getm_values_Device_WiFi_SSID_Alias, setup), - cmocka_unit_test_setup(test_api_usp_raw_getm_names_Device_WiFi_SSID_Alias, setup), - cmocka_unit_test_setup(test_api_usp_raw_instances_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_raw_resolve_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_raw_add_object_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_raw_set_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_raw_del_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_raw_object_name_Device_Users_User, setup), - cmocka_unit_test_setup(test_api_usp_get_cwmp_Device_DeviceInfo_Manufacturer, setup), - - // -ve scenerios - cmocka_unit_test_setup(test_api_usp_get_DeviceInfo_Manufacturer, setup), - cmocka_unit_test_setup(test_api_usp_get_wrong_oper_Device_WiFi_SSID, setup), - cmocka_unit_test_setup(test_api_usp_get_Device_IP_Interface, setup), - cmocka_unit_test_setup(test_api_usp_get_wrong_exp_Device_IP_Interface, setup), - cmocka_unit_test_setup(test_api_usp_get_wrong_braces_Device_IP_Interface, setup), - cmocka_unit_test_setup(test_api_usp_get_wrong_name_Device_IP_Interface, setup) - }; - - return cmocka_run_group_tests(tests, group_setup, group_teardown); -} - diff --git a/bbfd/test/files/etc/bbfdm/json/transferComplete.json b/bbfd/test/files/etc/bbfdm/json/transferComplete.json deleted file mode 100644 index 078cd9d7..00000000 --- a/bbfd/test/files/etc/bbfdm/json/transferComplete.json +++ /dev/null @@ -1,132 +0,0 @@ -{ - "Device.LocalAgent.": { - "type": "object", - "version": "2.12", - "protocols": [ - "usp" - ], - "access": false, - "array": false, - "TransferComplete!": { - "type": "event", - "version": "2.12", - "protocols": [ - "usp" - ], - "Command": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "string" - }, - "CommandKey": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "string" - }, - "Requestor": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "string" - }, - "TransferType": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "string", - "enumerations": [ - "Download", - "Upload" - ] - }, - "Affected": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "string" - }, - "TransferURL": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "URL", - "range": [ - { - "max": 2048 - } - ] - }, - "StartTime": { - "type": "dateTime", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "dateTime" - }, - "CompleteTime": { - "type": "dateTime", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "dateTime" - }, - "FaultCode": { - "type": "unsignedInt", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "unsignedInt" - }, - "FaultString": { - "type": "string", - "read": true, - "write": true, - "version": "2.12", - "protocols": [ - "usp" - ], - "datatype": "string", - "range": [ - { - "max": 256 - } - ] - } - } - } -} diff --git a/bbfd/test/files/etc/board-db/config/device b/bbfd/test/files/etc/board-db/config/device deleted file mode 100644 index 5c60ca11..00000000 --- a/bbfd/test/files/etc/board-db/config/device +++ /dev/null @@ -1,11 +0,0 @@ -config deviceinfo 'deviceinfo' - option Manufacturer 'iopsys' - option ProductClass 'FirstClass' - option SerialNumber '000000001' - option SoftwareVersion 'IOPSYS-CODE-ANALYSIS' - option HardwareVersion '1.0' - option DeviceCategory 'Gateway' - option ModelName 'ModelName' - option Description 'Iopsys code analysis test simulator' - option ManufacturerOUI 'XXX' - option BaseMACAddress 'feeddeadbeef' diff --git a/bbfd/test/files/etc/config/firewall b/bbfd/test/files/etc/config/firewall deleted file mode 100644 index edf85cd9..00000000 --- a/bbfd/test/files/etc/config/firewall +++ /dev/null @@ -1,185 +0,0 @@ - -config globals 'globals' - option enabled '1' - -config defaults - option syn_flood '1' - option input 'ACCEPT' - option output 'ACCEPT' - option forward 'REJECT' - -config zone - option name 'lan' - list network 'lan' - option input 'ACCEPT' - option output 'ACCEPT' - option forward 'ACCEPT' - -config zone - option name 'wan' - list network 'wan' - list network 'wan6' - option input 'REJECT' - option output 'ACCEPT' - option forward 'REJECT' - option masq '1' - option mtu_fix '1' - -config forwarding - option src 'lan' - option dest 'wan' - -config rule - option name 'Allow-DHCP-Renew' - option src 'wan' - option proto 'udp' - option dest_port '68' - option target 'ACCEPT' - option family 'ipv4' - -config rule - option name 'Allow-Ping' - option src 'wan' - option proto 'icmp' - option icmp_type 'echo-request' - option family 'ipv4' - option target 'ACCEPT' - -config rule - option name 'Allow-IGMP' - option src 'wan' - option proto 'igmp' - option family 'ipv4' - option target 'ACCEPT' - -config rule - option name 'Allow-DHCPv6' - option src 'wan' - option proto 'udp' - option src_ip 'fc00::/6' - option dest_ip 'fc00::/6' - option dest_port '546' - option family 'ipv6' - option target 'ACCEPT' - -config rule - option name 'Allow-MLD' - option src 'wan' - option proto 'icmp' - option src_ip 'fe80::/10' - list icmp_type '130/0' - list icmp_type '131/0' - list icmp_type '132/0' - list icmp_type '143/0' - option family 'ipv6' - option target 'ACCEPT' - -config rule - option name 'Allow-ICMPv6-Input' - option src 'wan' - option proto 'icmp' - list icmp_type 'echo-request' - list icmp_type 'echo-reply' - list icmp_type 'destination-unreachable' - list icmp_type 'packet-too-big' - list icmp_type 'time-exceeded' - list icmp_type 'bad-header' - list icmp_type 'unknown-header-type' - list icmp_type 'router-solicitation' - list icmp_type 'neighbour-solicitation' - list icmp_type 'router-advertisement' - list icmp_type 'neighbour-advertisement' - option limit '1000/sec' - option family 'ipv6' - option target 'ACCEPT' - -config rule - option name 'Allow-ICMPv6-Forward' - option src 'wan' - option dest '*' - option proto 'icmp' - list icmp_type 'echo-request' - list icmp_type 'echo-reply' - list icmp_type 'destination-unreachable' - list icmp_type 'packet-too-big' - list icmp_type 'time-exceeded' - list icmp_type 'bad-header' - list icmp_type 'unknown-header-type' - option limit '1000/sec' - option family 'ipv6' - option target 'ACCEPT' - -config rule - option name 'Allow-IPSec-ESP' - option src 'wan' - option dest 'lan' - option proto 'esp' - option target 'ACCEPT' - -config rule - option name 'Allow-ISAKMP' - option src 'wan' - option dest 'lan' - option dest_port '500' - option proto 'udp' - option target 'ACCEPT' - -config rule - option name 'Support-UDP-Traceroute' - option src 'wan' - option dest_port '33434:33689' - option proto 'udp' - option family 'ipv4' - option target 'REJECT' - option enabled 'false' - -config dmz 'dmz' - option enabled '0' - option exclude_ports '5060 7547' - -config include - option path '/etc/firewall.user' - option reload '1' - -config include 'ddos' - option path '/etc/firewall.ddos' - option reload '1' - -config include 'parental' - option path '/etc/firewall.parental' - option reload '1' - -config include 'qos' - option path '/etc/firewall.qos' - option reload '1' - -config include 'cwmp' - option path '/etc/firewall.cwmp' - option reload '1' - -config include 'miniupnpd' - option type 'script' - option path '/usr/share/miniupnpd/firewall.include' - option family 'any' - option reload '1' - -config include 'sip' - option path '/etc/firewall.sip' - option reload '1' - -config include 'dmzhost' - option path '/etc/firewall.dmz' - option reload '1' - -config redirect 'port_mapping_1' - option enabled '1' - option src 'wan' - option dest 'lan' - option target 'DNAT' - option reflection '1' - option name 'test' - option proto 'tcp' - option dest_ip 'wan' - option src_dport '192.168.3.45' - option src_dport '50:60' - option dest_port '44' diff --git a/bbfd/test/files/etc/config/network b/bbfd/test/files/etc/config/network deleted file mode 100644 index 732377fe..00000000 --- a/bbfd/test/files/etc/config/network +++ /dev/null @@ -1,123 +0,0 @@ -config interface 'loopback' - option device 'lo' - option proto 'static' - option ipaddr '127.0.0.1' - option netmask '255.0.0.0' - -config globals 'globals' - option ula_prefix 'fddb:7949:7caa::/48' - -config device - option name 'br-lan' - option type 'bridge' - list ports 'eth1' - list ports 'eth2' - list ports 'eth3' - list ports 'eth4' - option macaddr '44:D4:37:71:B8:11' - -config interface 'lan' - option device 'br-lan' - option proto 'static' - option ipaddr '192.168.1.1' - option netmask '255.255.255.0' - option ip6assign '60' - option is_lan '1' - option macaddr '44:D4:37:71:B8:11' - -config interface 'wan' - option proto 'dhcp' - option hostname 'iopsysWrt-44D43771B810' - option vendorid 'eg400' - option device 'eth0.1' - option reqopts '12 43' - option sendopts '60:iopsystest 61:iopsys' - option macaddr '44:D4:37:71:B8:12' - -config interface 'wan6' - option proto 'dhcpv6' - option device '@wan' - -config device 'ethwan' - option type 'untagged' - option ifname 'eth0' - option name 'eth0.1' - option macaddr '44:D4:37:71:B8:12' - -config device 'br_test_1' - option name 'br-test' - option type 'bridge' - list ports 'eth1.100' - list ports 'eth2.100' - list ports 'eth3.100' - list ports 'eth4.100' - option macaddr '44:D4:37:71:B8:13' - -config interface 'lan100' - option device 'br-test' - option proto 'static' - option ipaddr '172.32.1.1' - option macaddr '44:D4:37:71:B8:13' - -config device 'eth1_100' - option type 'untagged' - option ifname 'eth1' - option name 'eth1.100' - option vid '100' - -config device 'eth2_100' - option type 'untagged' - option ifname 'eth2' - option name 'eth2.100' - option vid '100' - -config device 'eth3_100' - option type '8021q' - option ifname 'eth3' - option name 'eth3.100' - option vid '100' - -config device 'eth4_100' - option type '8021q' - option ifname 'eth4' - option name 'eth4.100' - option vid '100' - -config interface 'ppp_wan' - option type 'anywan' - option proto 'pppoe' - option username 'iopsyshome@iopsys.eu' - option password 'iopsys' - option device 'eth0.1' - option ipv6 '1' - option macaddr '44:D4:37:71:B8:14' - -config route 'route4' - option interface 'wan' - option target '0.0.0.0/0' - option gateway '10.72.197.110' - -config route6 'route6' - option interface 'wan6' - option target '::/0' - -config interface 'stabridge' - option proto 'relay' - option network 'lan wan' - -config interface 'mygre' - option ipaddr '10.1.1.1' - option peeraddr '10.2.2.1' - option proto 'gre' - -config interface 'mygre_static' - option proto 'static' - option device '@mygre' - option ipaddr '172.16.12.1' - option netmask '255.255.255.252' - -config route 'tunnel' - option interface 'mygre_static' - option target '172.16.2.0' - option netmask '255.255.255.0' - option gateway '172.16.12.2' diff --git a/bbfd/test/files/etc/config/users b/bbfd/test/files/etc/config/users deleted file mode 100644 index ca728026..00000000 --- a/bbfd/test/files/etc/config/users +++ /dev/null @@ -1,7 +0,0 @@ - -config user 'user' - option enabled '1' - option remote_access '1' - list _access_w 'admin' - list _access_w 'support' - list _access_w 'user' diff --git a/bbfd/test/files/etc/config/uspd b/bbfd/test/files/etc/config/uspd deleted file mode 100644 index 2cf09c81..00000000 --- a/bbfd/test/files/etc/config/uspd +++ /dev/null @@ -1,6 +0,0 @@ -config uspd 'usp' - option granularitylevel '0' - option debug '1' - option loglevel '2' - option subprocess_level '1' - option refresh_time '0' diff --git a/bbfd/test/files/etc/config/wireless b/bbfd/test/files/etc/config/wireless deleted file mode 100644 index 1937ae7f..00000000 --- a/bbfd/test/files/etc/config/wireless +++ /dev/null @@ -1,56 +0,0 @@ -config wifi-device 'test1' - option type 'mac80211' - option channel '36' - option hwmode '11a' - option country 'DE' - option htmode 'HE80' - option apsta '0' - option phy 'phy0' - -config wifi-iface 'no_mp_test1' - option device 'test1' - option network 'lan' - option mode 'ap' - option ifname 'test1' - option encryption 'psk2' - option wps_pushbutton '1' - option ieee80211k '1' - option ieee80211v '1' - option bss_transition '1' - option ssid 'NON-MULTI-AP-TEST' - -config wifi-iface 'default_test1' - option device 'test1' - option network 'lan' - option mode 'ap' - option ifname 'test1' - option ssid 'MAP-44D43771B810-BH-5GHz' - option encryption 'psk2' - option wps_pushbutton '1' - option ieee80211k '1' - option ieee80211v '1' - option bss_transition '1' - option multi_ap '3' - -config wifi-device 'test2' - option type 'mac80211' - option channel '11' - option hwmode '11g' - option country 'DE' - option htmode 'HE20' - option apsta '0' - option phy 'phy1' - -config wifi-iface 'default_test2' - option device 'test2' - option network 'lan' - option mode 'ap' - option ifname 'test2' - option ssid 'iopsysWrt-44D43771B810' - option encryption 'psk2' - option key 'MPUEO3L7WHJ45P' - option wps_pushbutton '1' - option ieee80211k '1' - option ieee80211v '1' - option bss_transition '1' - option multi_ap '2' diff --git a/bbfd/test/files/etc/init.d/uspd b/bbfd/test/files/etc/init.d/uspd deleted file mode 100755 index 2f788976..00000000 --- a/bbfd/test/files/etc/init.d/uspd +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=94 -STOP=10 - -USE_PROCD=1 -PROG=/usr/sbin/uspd - -start_service() { - procd_open_instance - procd_set_param command ${PROG} - procd_set_param respawn - procd_close_instance -} - -reload_service() { - stop - start -} - -service_triggers() -{ - procd_add_reload_trigger "cwmp" - procd_add_config_trigger "config.change" "uspd" /etc/init.d/uspd restart -} diff --git a/bbfd/test/funl/json/gran/gran.validation.json b/bbfd/test/funl/json/gran/gran.validation.json deleted file mode 100644 index 7083b195..00000000 --- a/bbfd/test/funl/json/gran/gran.validation.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "object": "usp.Device.", - "methods": [ - { - "method": "get", - "args": { - "path": "Users." - }, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/funl/json/usp.raw.validation.json b/bbfd/test/funl/json/usp.raw.validation.json deleted file mode 100644 index 1efa913b..00000000 --- a/bbfd/test/funl/json/usp.raw.validation.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "object": "usp.raw", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "both" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1", - "next-level": true - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#1+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias" - }, - "rc": 0 - }, - - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#*+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Stats.PacketsSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[BytesSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable==true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable!=true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.[Enable==0].Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.*.Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort==68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort!=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order==1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order!=1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>=8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<=2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference+.Alias==\"cpe-1\"].AssociatedDeviceNumberOfEntries" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference#1+.Alias==\"cpe-1\"].WPS.ConfigMethodsSupported" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.[Enable==0].Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.*.Device." - }, - "rc": 0 - }, - { - "method": "hello", - "rc": 3 - }, - { - "method": "instances", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.SSID", - "value": "test-2g", - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"iopsys.eu" - } - }, - "rc": 0 - }, - { - "method": "dump_schema", - "args": {}, - "rc": 0 - }, - { - "method": "list_operate", - "args": {}, - "rc": 0 - }, - { - "method": "transaction_commit", - "args": { - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "transaction_abort", - "args": { - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "getm_names", - "args": { - "paths": ["Device.WiFi.SSID.1.SSID","Device.WiFi.SSID.2.SSID"], - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "setm_values", - "args": { - "pv_tuple": [{"path":"Device.Users.User.1.Alias", "value":"cpe-1"}, {"path":"Device.Users.User.2.Alias", "value":"cpe-2"}], - "proto": "usp", - "transaction_id": 123 - }, - "rc": 0 - }, - ] -} - diff --git a/bbfd/test/funl/json/usp.validation.json b/bbfd/test/funl/json/usp.validation.json deleted file mode 100644 index 41124d42..00000000 --- a/bbfd/test/funl/json/usp.validation.json +++ /dev/null @@ -1,463 +0,0 @@ -{ - "object": "usp", - "methods": [ - { - "method": "list_operate", - "args": {}, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "both" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1", - "next-level": true - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#1+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias" - }, - "rc": 0 - }, - - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#*+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.IP.Interface.*.IPv4Address.*.AddressingType" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Stats.PacketsSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[BytesSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable==true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable!=true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.[Enable==0].Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.*.Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort==68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort!=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order==1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order!=1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>=8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<=2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Status>\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.{Status==\"Up\"}.Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference+.Alias==\"cpe-1\"].AssociatedDeviceNumberOfEntries" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference#1+.Alias==\"cpe-1\"].WPS.ConfigMethodsSupported" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference#*+.Alias==\"cpe-1\"].WPS.ConfigMethodsSupported" - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.Stats.", - "proto": "usp" - }, - "rc": 0 - }, - - { - "method": "instances", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "instances", - "args": { - "path": "Device.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "instances", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "validate", - "args": { - "path": "Device.Users.User.1.Alias", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "validate", - "args": { - "path": "Device.Users.User.1.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "validate", - "args": { - "path": "Device.Users.User.*.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.SSID", - "value": "test-1g" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.Users.User.1.", - "values": {"username":"funl-test", "password":"ft1234"} - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.Firewall.Chain.1.Rule.1.", - "values": {"DestPortRangeMax":"5"} - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.Firewall.Chain.1.Rule.1.", - "values": {"Order":"7"} - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.Firewall.Chain.1.Rule.1.", - "values": {"DestPortRangeMax":5} - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"iopsys.eu" - } - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"iopsys.eu", - "Host":"localhost" - } - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.WiFi.SSID.1.", - "action":"NeighboringWiFiDiagnostic()" - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.WiFi", - "action":"" - }, - "rc": 0 - }, - { - "method": "add_object", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "del_object", - "args": { - "path": "Device.Users.User.[Username>admin].", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "del_object", - "args": { - "path": "Device.Users.User.2.", - "proto": "usp" - }, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/funl/schema/usp.raw_test_negative.json b/bbfd/test/funl/schema/usp.raw_test_negative.json deleted file mode 100644 index df34d8b3..00000000 --- a/bbfd/test/funl/schema/usp.raw_test_negative.json +++ /dev/null @@ -1,1183 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/usp.raw.md", - "type": "object", - "title": "usp.raw", - "object": "usp.raw", - "additionalProperties": false, - "properties": { - "get_supported_dm": { - "title": "Get list of supported datamodel parameters", - "description": "Schema will have all the nodes/objects supported by libbbf", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "schema_type": { - "type": "integer", - "minimum": 0, - "maximum": 3, - "description": "0-All, 1-Parameter only 2- Event only 3- operate only" - } - } - }, - "output": { - "required": [ - "fault" - ], - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "dump_schema": { - "title": "Get available datamodel schema from Device", - "description": "Schema will have all the nodes/objects supported by data model", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "unique_keys": { - "type": "array", - "uniqueItems": true, - "maxItems": 8, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "parameter", - "writable", - "type" - ] - }, - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - } - }, - "required": [ - "parameter", - "writable", - "type" - ] - } - ] - } - }, - "required": [ - "parameters" - ] - } - } - }, - "list_operate": { - "title": "List down supported usp operate commands", - "description": "Commands will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - } - }, - "list_events": { - "title": "List down supported usp events", - "description": "events will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "type": "string", - "pattern": "xsd:event" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - } - }, - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "required": [ - "fault" - ], - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "getm_values": { - "title": "Get multiple values", - "description": "Query multiple paths at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "paths": { - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "required": [ - "parameters" - ], - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "fault" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "getm_names": { - "title": "Get multiple object names", - "description": "Query multiple object names at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "paths": { - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - - "items": [ - { - "type": "object", - "required": [ - "parameter", - "fault" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "instances": { - "title": "Instance query handler", - "description": "Get the instances of multi object", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "validate": { - "title": "Validate a datamodel path", - "description": "Validate a path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "object_names": { - "title": "Get objects names", - "description": "Get names of all the objects below input object path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "required": [ - "fault" - ], - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - }, - "instance": { - "type": "string" - } - } - } - ] - } - } - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "value", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "type": "string" - }, - "values": { - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - } - } - }, - "output": { - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "operate": { - "title": "Operate handler", - "description": "Operate on object element provided in path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "action" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "action": { - "type": "string", - }, - "input": { - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "required":[ - "fault" - ], - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "transaction_start": { - "title": "Start a transaction before set/add/del operations", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "app": { - "type": "string" - } - }, - "required": [ - "app" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "error": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_abort": { - "title": "Aborts an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "error": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_commit": { - "title": "Commits an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "restart_services": { - "type": "boolean" - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "updated_services": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_status": { - "title": "Shows status of a transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "string", - "description": "on-going or not-exists" - }, - "remaining_time": { - "type": "integer" - }, - "app": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "setm_values": { - "title": "Set values of multiple objects at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "pv_tuple", - "transaction_id" - ], - "properties": { - "pv_tuple": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - } - } - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - }, - "transaction_id": { - "type": "integer", - "minimum": 0 - } - } - }, - "output": { - "type": "object", - "oneof": [ - { - "required": [ - "status" - ] - }, - { - "required": [ - "parameters" - ] - } - ], - "properties": { - "status": { - "type": "boolean" - }, - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "notify_event": { - "title": "notify occurance of an event on ubus", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "input": { - "type": "string" - } - } - }, - "output": {} - } - } - } -} diff --git a/bbfd/test/funl/schema/usp.raw_test_positive.json b/bbfd/test/funl/schema/usp.raw_test_positive.json deleted file mode 100644 index adf51e5f..00000000 --- a/bbfd/test/funl/schema/usp.raw_test_positive.json +++ /dev/null @@ -1,1383 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/usp.raw.md", - "type": "object", - "title": "usp.raw", - "object": "usp.raw", - "additionalProperties": false, - "properties": { - "get_supported_dm": { - "title": "Get list of supported datamodel parameters", - "description": "Schema will have all the nodes/objects supported by libbbf", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "schema_type": { - "type": "integer", - "minimum": 0, - "maximum": 3, - "description": "0-All, 1-Parameter only 2- Event only 3- operate only" - } - } - }, - "output": { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "parameter", - "type" - ] - } - ] - } - } - } - } - }, - "dump_schema": { - "title": "Get available datamodel schema from Device", - "description": "Schema will have all the nodes/objects supported by data model", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "unique_keys": { - "type": "array", - "uniqueItems": true, - "maxItems": 8, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "parameter", - "writable", - "type" - ] - }, - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - } - }, - "required": [ - "parameter", - "writable", - "type" - ] - } - ] - } - }, - "required": [ - "parameters" - ] - } - } - }, - "list_operate": { - "title": "List down supported usp operate commands", - "description": "Commands will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - } - }, - "list_events": { - "title": "List down supported usp events", - "description": "events will be shown in schema format", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/operate_path_t" - }, - "type": { - "type": "string", - "pattern": "xsd:event" - }, - "in": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - } - } - ] - } - } - } - } - }, - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "value", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - } - }, - "getm_values": { - "title": "Get multiple values", - "description": "Query multiple paths at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "paths": { - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - } - }, - "getm_names": { - "title": "Get multiple object names", - "description": "Query multiple object names at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "paths" - ], - "properties": { - "paths": { - "type": "array", - "items": [ - { - "$ref": "#/definitions/path_t" - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "value", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - } - }, - "instances": { - "title": "Instance query handler", - "description": "Get the instances of multi object", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "required": [ - "parameter" - ], - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/instance_t" - } - } - } - ] - } - } - } - } - }, - "validate": { - "title": "Validate a datamodel path", - "description": "Validate a path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "$ref": "#/definitions/path_t" - } - } - } - } - }, - "object_names": { - "title": "Get objects names", - "description": "Get names of all the objects below input object path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "writable", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "writable": { - "type": "string", - "description": "1 if object is writable, 0 otherwise" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - }, - "instance": { - "type": "string" - } - } - } - ] - } - } - } - ] - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "value", - "transaction_id" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "description": "value of the object element provided in path, path should contains valid writable object element", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1.SSID\", \"value\":\"test_ssid\"}", - "{\"path\":\"Device.WiFi.SSID.2.Enable\", \"value\":\"true\"}", - "{\"path\":\"Device.WiFi.SSID.1.Enable\", \"value\":\"0\"}" - ] - }, - "values": { - "description": "To set multiple values at once, path should be relative to object elements", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1\", \"values\":{\".SSID\":\"test_ssid\",\".Name\":\"test_name\"}}", - "{\"path\":\"Device.WiFi.SSID.2\", \"values\":{\".SSID\":\"test_ssid\"}}" - ], - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - } - } - }, - "output": { - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "operate": { - "title": "Operate handler", - "description": "Operate on object element provided in path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "action" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "action": { - "description": "Opreate command as defined in TR-369, TR-181-2.13", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.\", \"action\":\"Reset\\(\\)\"}" - ] - }, - "input": { - "description": "Input arguments for the operate command as defined in TR-181-2.13", - "examples": [ - "{\"path\":\"Device.IP.Diagnostics\", \"action\":\"IPPing\\(\\)\", \"input\":{\"Host\":\"iopsys.eu\"}}" - ], - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "Results" - ], - "properties": { - "Results": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "parameters": { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "type": "string" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - } - } - ] - } - } - } - } - }, - "transaction_start": { - "title": "Start a transaction before set/add/del operations", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "app": { - "type": "string" - } - }, - "required": [ - "app" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "error": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_abort": { - "title": "Aborts an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "error": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_commit": { - "title": "Commits an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - }, - "restart_services": { - "type": "boolean" - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - }, - "error": { - "type": "string" - }, - "updated_services": { - "type": "array", - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "transaction_status": { - "title": "Shows status of a transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": { - "transaction_id": { - "type": "integer", - "minimum": 1 - } - }, - "required": [ - "transaction_id" - ] - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "string", - "description": "on-going or not-exists" - }, - "remaining_time": { - "type": "integer" - }, - "app": { - "type": "string" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "input", - "output" - ] - }, - "setm_values": { - "title": "Set values of multiple objects at once", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "pv_tuple", - "transaction_id" - ], - "properties": { - "pv_tuple": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - } - } - ] - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - }, - "transaction_id": { - "type": "integer", - "minimum": 0 - } - } - }, - "output": { - "type": "object", - "oneof": [ - { - "required": [ - "status" - ] - }, - { - "required": [ - "parameters" - ] - } - ], - "properties": { - "status": { - "type": "boolean" - }, - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - } - }, - "notify_event": { - "title": "notify occurance of an event on ubus", - "type": "object", - "required": [ - "input" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "name" - ], - "properties": { - "name": { - "type": "string" - }, - "input": { - "type": "string" - } - } - }, - "output": {} - } - } - } -} diff --git a/bbfd/test/funl/schema/usp_test_negative.json b/bbfd/test/funl/schema/usp_test_negative.json deleted file mode 100644 index 47eb0261..00000000 --- a/bbfd/test/funl/schema/usp_test_negative.json +++ /dev/null @@ -1,338 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/usp.md", - "type": "object", - "title": "usp", - "object": "usp", - "additionalProperties": false, - "properties": { - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "required": [ - "fault" - ], - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "type": "string" - }, - "values": { - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "fault" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean", - "const": false - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "status", - "fault" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "fault" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - } - } - } - } - } - } -} diff --git a/bbfd/test/funl/schema/usp_test_positive.json b/bbfd/test/funl/schema/usp_test_positive.json deleted file mode 100644 index 5f87794c..00000000 --- a/bbfd/test/funl/schema/usp_test_positive.json +++ /dev/null @@ -1,315 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "query_path_t": { - "description": "DM object path with search queries", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.[SSID==\"test_ssid\"].BSSID", - "Device.WiFi.SSID.*.BSSID", - "Device.WiFi.SSID.[SSID!=\"test_ssid\"&&Enable==1].BSSID", - "Device.WiFi." - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/usp.md", - "type": "object", - "title": "usp", - "object": "usp", - "additionalProperties": false, - "properties": { - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "maxdepth": { - "type": "integer", - "description": "Integer to decide the depth of data model to be parsed" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "instance-mode": { - "type": "integer", - "description": "" - } - } - }, - "output": { - "type": "object", - "properties": {} - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "type": "string" - }, - "values": { - "description": "To set multiple values at once, path should be relative to object elements", - "type": "object", - "properties": {} - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "status" - ], - "properties": { - "status": { - "const": true - } - } - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "status", - "instance" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "instance": { - "type": "string" - } - } - } - } - } - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/query_path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "instance_mode": { - "type": "integer", - "minimum": 0, - "maximum": 1 - } - } - }, - "output": { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean", - "const": true - } - } - } - } - } - } - } - } - } -} diff --git a/bbfd/test/funl/validation/usp.raw.validation.negative.json b/bbfd/test/funl/validation/usp.raw.validation.negative.json deleted file mode 100644 index bc501c7e..00000000 --- a/bbfd/test/funl/validation/usp.raw.validation.negative.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "object": "usp.raw", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.InvalidPath", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path": "Device.DeviceInfo.InvalidPath", - }, - "rc": 0 - }, - { - "method": "instances", - "args": { - "path": "Device.Users.InvalidUser.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.InvalidPath", - "action":"IPPing()", - "input":{ - "Host":"iopsys.eu" - } - }, - "rc": 0 - }, - { - "method": "getm_names", - "args": { - "paths": ["Device.WiFi.SSID.1.Invalid","Device.WiFi.SSID.2.Invalid"], - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.Invalid", - "proto": "usp" - }, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/funl/validation/usp.raw.validation.positive.json b/bbfd/test/funl/validation/usp.raw.validation.positive.json deleted file mode 100644 index 09a1548f..00000000 --- a/bbfd/test/funl/validation/usp.raw.validation.positive.json +++ /dev/null @@ -1,368 +0,0 @@ -{ - "object": "usp.raw", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "both" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1", - "next-level": true - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#1+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias" - }, - "rc": 0 - }, - - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#*+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Stats.PacketsSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[BytesSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable==true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable!=true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.[Enable==0].Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.*.Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort==68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort!=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order==1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order!=1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>=8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<=2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference+.Alias==\"cpe-1\"].AssociatedDeviceNumberOfEntries" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference#1+.Alias==\"cpe-1\"].WPS.ConfigMethodsSupported" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.[Enable==0].Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.*.Device." - }, - "rc": 0 - }, - { - "method": "hello", - "rc": 3 - }, - { - "method": "instances", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.SSID", - "value": "test-2g", - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "object_names", - "args": { - "path": "Device.WiFi.SSID.1.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"iopsys.eu" - } - }, - "rc": 0 - }, - { - "method": "dump_schema", - "args": {}, - "rc": 0 - }, - { - "method": "list_operate", - "args": {}, - "rc": 0 - }, - { - "method": "get_supported_dm", - "args": { - "path": "Device.DeviceInfo.", - }, - "rc": 0 - }, - { - "method": "operate", - "args": { - "path":"Device.IP.Diagnostics.", - "action":"IPPing()", - "input":{ - "Host":"iopsys.eu" - } - }, - "rc": 0 - }, - { - "method": "transaction_commit", - "args": { - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "transaction_abort", - "args": { - "transaction_id": 123 - }, - "rc": 0 - }, - { - "method": "getm_names", - "args": { - "paths": ["Device.WiFi.SSID.1.SSID","Device.WiFi.SSID.2.SSID"], - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "setm_values", - "args": { - "pv_tuple": [{"path":"Device.Users.User.1.Alias", "value":"cpe-1"}, {"path":"Device.Users.User.2.Alias", "value":"cpe-2"}], - "proto": "usp", - "transaction_id": 123 - }, - "rc": 0 - }, - ] -} - diff --git a/bbfd/test/funl/validation/usp.validation.negative.json b/bbfd/test/funl/validation/usp.validation.negative.json deleted file mode 100644 index 5f96f41d..00000000 --- a/bbfd/test/funl/validation/usp.validation.negative.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "object": "usp", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Invalid", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.Invalid", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Invalid", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.Invalid", - "value": "test-1g" - }, - "rc": 0 - }, - { - "method": "add_object", - "args": { - "path": "Device.Users.User.Invalid", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "del_object", - "args": { - "path": "Device.Users.User.Invalid.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "del_object", - "args": { - "path": "Device.Users.User.[Username>admin].", - "proto": "usp" - }, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/funl/validation/usp.validation.positive.json b/bbfd/test/funl/validation/usp.validation.positive.json deleted file mode 100644 index c1aa81ab..00000000 --- a/bbfd/test/funl/validation/usp.validation.positive.json +++ /dev/null @@ -1,323 +0,0 @@ -{ - "object": "usp", - "methods": [ - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias", - "proto": "cwmp" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "both" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path": "Device.DeviceInfo.Manufacturer", - "proto": "usp", - "maxdepth": "1", - "next-level": true - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#1+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Users.User.*.Alias" - }, - "rc": 0 - }, - - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.1.LowerLayers#*+.Name" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.IP.Interface.*.IPv4Address.*.AddressingType" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Status==\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[SSID==\"test-2g\"&&Stats.PacketsSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[BytesSent>0].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable==true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Enable!=true].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.[Enable==0].Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.USB.USBHosts.Host.*.Device." - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort==68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort!=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort>=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[DestPort<=68].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order==1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order!=1].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order>=8].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.Firewall.Chain.1.Rule.[Order<=2].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[Status>\"Up\"].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.{Status==\"Up\"}.Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.SSID.[].Alias" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference+.Alias==\"cpe-1\"].AssociatedDeviceNumberOfEntries" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference#1+.Alias==\"cpe-1\"].WPS.ConfigMethodsSupported" - }, - "rc": 0 - }, - { - "method": "get", - "args": { - "path":"Device.WiFi.AccessPoint.[SSIDReference#*+.Alias==\"cpe-1\"].WPS.ConfigMethodsSupported" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.WiFi.SSID.1.SSID", - "value": "test-1g" - }, - "rc": 0 - }, - { - "method": "set", - "args": { - "path": "Device.Firewall.Chain.1.Rule.1.", - "values": {"Order":"7"} - }, - "rc": 0 - }, - { - "method": "add_object", - "args": { - "path": "Device.Users.User.", - "proto": "usp" - }, - "rc": 0 - }, - - { - "method": "del_object", - "args": { - "path": "Device.Users.User.2.", - "proto": "usp" - }, - "rc": 0 - } - ] -} - diff --git a/bbfd/test/libuspd_test.c b/bbfd/test/libuspd_test.c deleted file mode 100644 index c0de422d..00000000 --- a/bbfd/test/libuspd_test.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Suvendhu Hansa - */ - -/* This file is used for validating USPD max msg len using libbbf APIs */ - -#include -#include -#include - -#ifndef DEF_IPC_DATA_LEN -#define DEF_IPC_DATA_LEN (1024 * 1024 - 128) -#endif - -/************************************************************* -* GET PARAM -**************************************************************/ -static int get_X_IOPSYS_EU_testUSPDParam_TestText(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - char *ptr = (char *)calloc(1, DEF_IPC_DATA_LEN); - if (ptr == NULL) { - *value = ""; - return 0; - } - memset(ptr, 'a', DEF_IPC_DATA_LEN - 1); - dmasprintf(value, ptr); - free(ptr); - return 0; -} - -/********************************************************************************************************************************** -* OBJ & PARAM DEFINITION -***********************************************************************************************************************************/ -/*** Device. ***/ -DMLEAF tX_IOPSYS_EU_testUSPDParam[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{"X_IOPSYS_EU_TestText", &DMREAD, DMT_STRING, get_X_IOPSYS_EU_testUSPDParam_TestText, NULL, BBFDM_BOTH}, -{0} -}; - -/* ********** DynamicObj ********** */ -DM_MAP_OBJ tDynamicObj[] = { -/* parentobj, nextobject, parameter */ -{"Device.", NULL, tX_IOPSYS_EU_testUSPDParam}, -{0} -}; diff --git a/bbfd/test/python/validate_3272.py b/bbfd/test/python/validate_3272.py deleted file mode 100755 index 0abb7e99..00000000 --- a/bbfd/test/python/validate_3272.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/python3 - -import subprocess -import json - -TEST_NAME = "BUG_3272" - -print("Running: " + TEST_NAME) - -def usp_get(path, proto = ""): - path_arg = "{\"path\":\"" + path + "\",\"proto\":\"" + proto + "\"}" - cmd = ['ubus', 'call', 'usp.raw', 'get', path_arg] - - out = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - stdout,stderr = out.communicate() - return stdout - -# check fault code of invalid path -output = json.loads(usp_get("Device.USB.USBHosts.Host.[Enable==0].Device.")) - -for param in enumerate(output["parameters"]): - assert param[1]["parameter"].endswith("DeviceNumberOfEntries") == False, "FAIL" + TEST_NAME - -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_3536.py b/bbfd/test/python/validate_3536.py deleted file mode 100755 index b8732f78..00000000 --- a/bbfd/test/python/validate_3536.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/python3 - -import subprocess -import json - -TEST_NAME = "BUG_3536" - -print("Running: " + TEST_NAME) - -def usp_get(path, proto = ""): - path_arg = "{\"path\":\"" + path + "\",\"proto\":\"" + proto + "\"}" - cmd = ['ubus', 'call', 'usp.raw', 'get', path_arg] - - out = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - stdout,stderr = out.communicate() - return stdout - -# check fault code of invalid path -output = json.loads(usp_get("Device", "usp")) -assert output["fault"] == 7026, "Wrong fault code" - -# check fault code of invalid path -output = json.loads(usp_get("Device", "cwmp")) -assert output["fault"] == 9005, "Wrong fault code for cwmp" - -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_device.py b/bbfd/test/python/validate_device.py deleted file mode 100755 index 3dfaa97e..00000000 --- a/bbfd/test/python/validate_device.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/python3 - -import ubus -import pathlib -import subprocess -import json - -TEST_NAME = "Get Device." - -print("Running: " + TEST_NAME) - -sock = pathlib.Path('/var/run/ubus/ubus.sock') -if sock.exists(): - assert ubus.connect('/var/run/ubus/ubus.sock') -else: - assert ubus.connect() - -out = ubus.call('usp.raw', 'get', {"path":"Device."}) -assert isinstance(out[0]["parameters"][0], dict), "FAIL: get Device. on usp.raw" - -# Check get operation for Device. path succeed -out = ubus.call('usp', 'get', {"path":"Device."}) -assert isinstance(out[0]['Device'], dict), "FAIL: get Device. on usp" - -ubus.disconnect() -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_fault_code.py b/bbfd/test/python/validate_fault_code.py deleted file mode 100755 index 651d2bb2..00000000 --- a/bbfd/test/python/validate_fault_code.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/python3 - -import subprocess -import json - -TEST_NAME = "Invalid path fault test" - -print("Running: " + TEST_NAME) - -def usp_get(path, proto = ""): - path_arg = "{\"path\":\"" + path + "\",\"proto\":\"" + proto + "\"}" - cmd = ['ubus', 'call', 'usp.raw', 'get', path_arg] - - out = subprocess.Popen(cmd, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - stdout,stderr = out.communicate() - return stdout - -# check fault code of invalid path -output = json.loads(usp_get("Device")) -assert output["fault"] == 9005, "FAIL: " + TEST_NAME - -output = json.loads(usp_get("Device", "usp")) -assert output["fault"] == 7026, "FAIL: " + TEST_NAME - -# for cmwp proto fault should be 9005 -output = json.loads(usp_get("Device", "cwmp")) -assert output["fault"] == 9005, "FAIL: " + TEST_NAME - -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_invalid_transaction_id.py b/bbfd/test/python/validate_invalid_transaction_id.py deleted file mode 100755 index 7a399190..00000000 --- a/bbfd/test/python/validate_invalid_transaction_id.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/python3 - -import ubus -import json -import pathlib - -TEST_NAME = "Validate fault on invalid transaction id with usp.raw" - -print("Running: " + TEST_NAME) - -def fault_wrong_transaction(cmd, param, efault): - out = ubus.call("usp.raw", cmd, param) - assert out[0]["fault"] == efault, "FAIL: for " + cmd + str(param) + " output " + str(out) - - -sock = pathlib.Path('/var/run/ubus/ubus.sock') -if sock.exists (): - assert ubus.connect('/var/run/ubus/ubus.sock') -else: - assert ubus.connect() - -fault_wrong_transaction("set", {"path":"Device.Users.User.1.Username", "value":"abc", "transaction_id":1234}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.Username", "value":"abc", "proto":"usp", "transaction_id":1234}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.Username", "value":"abc", "proto":"cwmp", "transaction_id":1234}, 9002) - -fault_wrong_transaction("set", {"path":"Device.Users.User.1.", "values":{"Username":"abc"}, "transaction_id":1234}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.", "values":{"Username":"abc"}, "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.", "values":{"Username":"abc"}, "transaction_id":1234, "proto":"cwmp"}, 9002) - -fault_wrong_transaction("add_object", {"path":"Device.Users.User.", "transaction_id":1234}, 7003) -fault_wrong_transaction("add_object", {"path":"Device.Users.User.", "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("add_object", {"path":"Device.Users.User.", "transaction_id":1234, "proto":"cwmp"}, 9002) - -fault_wrong_transaction("del_object", {"path":"Device.Users.User.1", "transaction_id":1234}, 7003) -fault_wrong_transaction("del_object", {"path":"Device.Users.User.1", "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("del_object", {"path":"Device.Users.User.1", "transaction_id":1234, "proto":"cwmp"}, 9002) - - -fault_wrong_transaction("setm_values", {"pv_tuple":[{"path":"Device.Users.User.1.Username", "value":"abc"}], "transaction_id":1234}, 7003) -fault_wrong_transaction("setm_values", {"pv_tuple":[{"path":"Device.Users.User.1.Username", "value":"abc"}], "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("setm_values", {"pv_tuple":[{"path":"Device.Users.User.1.Username", "value":"abc"}], "transaction_id":1234, "proto":"cwmp"}, 9002) - -ubus.disconnect() - -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_invalid_transaction_id_fault.py b/bbfd/test/python/validate_invalid_transaction_id_fault.py deleted file mode 100755 index eef4be1a..00000000 --- a/bbfd/test/python/validate_invalid_transaction_id_fault.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/python3 - -import ubus -import json -import pathlib - -TEST_NAME = "Validate fault on invalid transaction id with usp.raw" - -print("Running: " + TEST_NAME) - -def fault_wrong_transaction(cmd, param, efault): - out = ubus.call("usp.raw", cmd, param) - assert out[0]["fault"] == efault, "FAIL: for " + cmd + str(param) + " output " + str(out) - - -sock = pathlib.Path('/var/run/ubus/ubus.sock') -if sock.exists (): - assert ubus.connect('/var/run/ubus/ubus.sock') -else: - assert ubus.connect() - -fault_wrong_transaction("set", {"path":"Device.Users.User.1.Username", "value":"abc", "transaction_id":1234}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.Username", "value":"abc", "proto":"usp", "transaction_id":1234}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.Username", "value":"abc", "proto":"cwmp", "transaction_id":1234}, 9002) - -fault_wrong_transaction("set", {"path":"Device.Users.User.1.", "values":{"Username":"abc"}, "transaction_id":1234}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.", "values":{"Username":"abc"}, "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("set", {"path":"Device.Users.User.1.", "values":{"Username":"abc"}, "transaction_id":1234, "proto":"cwmp"}, 9002) - -fault_wrong_transaction("add_object", {"path":"Device.Users.User.", "transaction_id":1234}, 7003) -fault_wrong_transaction("add_object", {"path":"Device.Users.User.", "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("add_object", {"path":"Device.Users.User.", "transaction_id":1234, "proto":"cwmp"}, 9002) - -fault_wrong_transaction("del_object", {"path":"Device.Users.User.1", "transaction_id":1234}, 7003) -fault_wrong_transaction("del_object", {"path":"Device.Users.User.1", "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("del_object", {"path":"Device.Users.User.1", "transaction_id":1234, "proto":"cwmp"}, 9002) - - -fault_wrong_transaction("setm_values", {"pv_tuple":[{"path":"Device.Users.User.1.Username", "value":"abc"}], "transaction_id":1234}, 7003) -fault_wrong_transaction("setm_values", {"pv_tuple":[{"path":"Device.Users.User.1.Username", "value":"abc"}], "transaction_id":1234, "proto":"usp"}, 7003) -fault_wrong_transaction("setm_values", {"pv_tuple":[{"path":"Device.Users.User.1.Username", "value":"abc"}], "transaction_id":1234, "proto":"cwmp"}, 9002) - - -ubus.disconnect() - -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_schema_notify.py b/bbfd/test/python/validate_schema_notify.py deleted file mode 100755 index b8915993..00000000 --- a/bbfd/test/python/validate_schema_notify.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/python3 - -import pexpect -import os - -print("Running: Schema updater notification validation") - -ret = 1 -child = pexpect.spawn('ubus monitor') - -# force change in schema, by removing dependency uci file -os.rename("/etc/config/users", "/etc/config/users_1") - -try: - ret = child.expect('notify', timeout=35) -except: - print("FAIL: Schema updater notification") - -if ret == 0: - try: - ret = child.expect('schema_update_available') - except: - print("FAIL: Schema updater notification") - -# Revert back uci changes -os.rename("/etc/config/users_1", "/etc/config/users") - -if ret == 0: - print("PASS: Schema updater notification") - -exit(ret) diff --git a/bbfd/test/python/validate_serial.py b/bbfd/test/python/validate_serial.py deleted file mode 100755 index d5a9d3f2..00000000 --- a/bbfd/test/python/validate_serial.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/python3 - -import subprocess -import json - -TEST_NAME = "Get serial number" - -print("Running: " + TEST_NAME) - -out = subprocess.Popen(['ubus', 'call', 'usp.raw', 'get', '{"path":"Device.DeviceInfo.SerialNumber"}'], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - -stdout,stderr = out.communicate() - -jout = json.loads(stdout) - -assert jout["parameters"][0]["value"] == "000000001", "FAIL: serial number mismatch" - -print("PASS: " + TEST_NAME) diff --git a/bbfd/test/python/validate_ubus_event.py b/bbfd/test/python/validate_ubus_event.py deleted file mode 100755 index e174fd63..00000000 --- a/bbfd/test/python/validate_ubus_event.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/python3 - -import ubus -import json -import pathlib - -TEST_NAME = "Validate ubus event usp.raw" - -print("Running: " + TEST_NAME) - -def callback(event, data): - print("PASS: " + TEST_NAME) - ubus.disconnect() - exit(0) - -sock = pathlib.Path('/var/run/ubus/ubus.sock') -if sock.exists (): - assert ubus.connect('/var/run/ubus/ubus.sock') -else: - assert ubus.connect() - -ubus.listen(("usp.event", callback)) - -ubus.call("usp.raw", "notify_event", {"name":"Device.LocalAgent.TransferComplete!", "input":{"param1":"val1", "param2":"val2"}}) - -ubus.loop() - -ubus.disconnect() - -print("FAIL: " + TEST_NAME) diff --git a/bbfd/test/python/validate_uspd.py b/bbfd/test/python/validate_uspd.py deleted file mode 100755 index 008c3853..00000000 --- a/bbfd/test/python/validate_uspd.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/python3 - -import ubus -import json -import pathlib -import shutil -import os - -TEST_NAME = "Validate USPD Max MSG Len" -SHARED_LIB = "/builds/iopsys/uspd/test/libuspd_test.so" -DEST_DIR = "/usr/lib/bbfdm/" - -print("Running: " + TEST_NAME) - -sock = pathlib.Path('/var/run/ubus/ubus.sock') -if sock.exists(): - assert ubus.connect('/var/run/ubus/ubus.sock') -else: - assert ubus.connect() - -# Check get operation for Device. path succeed -out = ubus.call('usp.raw', 'get', {"path":"Device."}) -assert isinstance(out[0]["parameters"][0], dict), "FAIL: get Device. on usp" - -# Now copy the shared library -print("Copying shared library to /usr/lib/bbfdm") -try: - shutil.copy(SHARED_LIB, DEST_DIR) -except: - assert False, "FAIL: can't copy shared lib to /usr/lib/bbfdm" - -# Again check get for Device. path should fail due to max msglen crossed -out = ubus.call('usp.raw', 'get', {"path":"Device.", "proto":"usp"}) -fault = out[0]["fault"]; -assert fault == 7003, "FAIL: " + TEST_NAME - -# Now check usp.raw object should still present -out = ubus.objects() -objects = out.keys() -assert "usp.raw" in objects, "Object vanished" - -# Again check get operation with less msglen should succeed -out = ubus.call('usp.raw', 'get', {"path":"Device.DeviceInfo."}) -assert isinstance(out[0]["parameters"][0], dict), "FAIL: get Device. on usp" - -# Now delete the shared library from /usr/lib/bbfdm -os.remove(DEST_DIR + "libuspd_test.so") - -print("PASS: " + TEST_NAME) diff --git a/bbfd/src/usp.c b/bbfd/usp.c similarity index 100% rename from bbfd/src/usp.c rename to bbfd/usp.c diff --git a/bbfd/src/usp.h b/bbfd/usp.h similarity index 100% rename from bbfd/src/usp.h rename to bbfd/usp.h diff --git a/docs/guide/tools.md b/docs/guide/tools.md index 12d74232..44627477 100644 --- a/docs/guide/tools.md +++ b/docs/guide/tools.md @@ -113,7 +113,7 @@ Part of BBF-tools, refer Readme for more examples More examples: ```bash -$ ./generate_dm_excel.py -d tr181 -v iopsys -v openwrt -o datamodel.xls +$ ./generate_dm_excel.py -d tr181 -v iopsys -o datamodel.xls $ ./generate_dm_excel.py -d tr181 -d tr104 -v iopsys -o datamodel.xls $ ./generate_dm_excel.py -d tr181 -v iopsys -p X_IOPSYS_EU_ -r git^https://dev.iopsys.eu/iopsys/xmppc.git^devel -o datamodel_iopsys.xls ``` @@ -165,7 +165,6 @@ The input json file should be defined as follow: "software_version": "1.2.3.4", "vendor_list": [ "iopsys", - "openwrt", "test" ], "dm_json_files": [ diff --git a/libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.c b/libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.c deleted file mode 100644 index 61e4147c..00000000 --- a/libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.c +++ /dev/null @@ -1,208 +0,0 @@ -#include "deviceinfo.h" - -enum fw_image_status { - FW_IMAGE_STATUS_NoImage, - FW_IMAGE_STATUS_Downloading, - FW_IMAGE_STATUS_Validating, - FW_IMAGE_STATUS_Available, - FW_IMAGE_STATUS_DownloadFailed, - FW_IMAGE_STATUS_ValidationFailed, - FW_IMAGE_STATUS_InstallationFailed, - FW_IMAGE_STATUS_ActivationFailed, - __FW_IMAGE_STATUS_MAX -}; - -static const char *fw_image_status_str[__FW_IMAGE_STATUS_MAX] = { - "NoImage", - "Downloading", - "Validating", - "Available", - "DownloadFailed", - "ValidationFailed", - "InstallationFailed", - "ActivationFailed" -}; - -struct fw_image { - const char *name; - enum fw_image_status status; -}; - -static const struct fw_image fw_images[] = { - { .name = "default", .status = FW_IMAGE_STATUS_Available } -}; - -static int openwrt__browseDeviceInfoFirmwareImageInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - char *inst = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(fw_images); i++) { - const struct fw_image *fw_img = &fw_images[i]; - - inst = handle_instance_without_section(dmctx, parent_node, i+1); - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)fw_img, inst) == DM_STOP) - break; - } - return 0; -} - -static char *get_uci_deviceinfo(char *opt) -{ - char *v; - - dmuci_get_option_value_string("cwmp", "@deviceinfo[0]", opt, &v); - return v; -} - -static int openwrt__get_device_manufacturer(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("Manufacturer"); - return 0; -} - -static int openwrt__get_device_manufactureroui(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("ManufacturerOUI"); - return 0; -} - -static int openwrt__get_device_productclass(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("ProductClass"); - return 0; -} - -static int openwrt__get_device_serialnumber(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("SerialNumber"); - return 0; -} - -static int openwrt__get_device_softwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("SoftwareVersion"); - return 0; -} - -static int openwrt__get_device_hardwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("HardwareVersion"); - return 0; -} - -static int openwrt__get_device_devicecategory(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("DeviceCategory"); - return 0; -} - -static int openwrt__get_device_additionalhardwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("AdditionalHardwareVersion"); - return 0; -} - -static int openwrt__get_device_additionalsoftwareversion(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("AdditionalSoftwareVersion"); - return 0; -} - -static int openwrt__get_device_modelname(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("ModelName"); - return 0; -} - -static int openwrt__get_device_description(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = get_uci_deviceinfo("Description"); - return 0; -} - -static int openwrt__get_device_active_fwimage(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = dmstrdup("Device.DeviceInfo.FirmwareImage.1"); - return 0; -} - -static int openwrt__get_device_fwimage_numberofentries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - dmasprintf(value, "%d", ARRAY_SIZE(fw_images)); - return 0; -} - -static int openwrt__get_FirmwareImage_name(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - const struct fw_image *fw_img = data; - - *value = (char *)fw_img->name; - return 0; -} - -static int openwrt__get_FirmwareImage_version(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - return openwrt__get_device_softwareversion(refparam, ctx, data, instance, value); -} - -static int openwrt__get_FirmwareImage_available(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - const struct fw_image *fw_img = data; - - *value = fw_img->status == FW_IMAGE_STATUS_Available ? "1" : "0"; - return 0; -} - -static int openwrt__get_FirmwareImage_status(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - const struct fw_image *fw_img = data; - - *value = (char *)fw_image_status_str[fw_img->status]; - return 0; -} - -static int openwrt__get_FirmwareImage_bootfailurelog(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - *value = 0; - return 0; -} - -/********************************************************************************************************************************** -* OBJ & PARAM DEFINITION -***********************************************************************************************************************************/ -/* *** Device.DeviceInfo. *** */ -DMOBJ tOPENWRT_DeviceInfoObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ -{"FirmwareImage", &DMREAD, NULL, NULL, NULL, openwrt__browseDeviceInfoFirmwareImageInst, NULL, NULL, NULL, tOPENWRT_DeviceInfoFirmwareImageParams, NULL, BBFDM_BOTH, LIST_KEY{"Alias", NULL}}, -{0} -}; - -DMLEAF tOPENWRT_DeviceInfoParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{"DeviceCategory", &DMREAD, DMT_STRING, openwrt__get_device_devicecategory, NULL, BBFDM_BOTH}, -{"Manufacturer", &DMREAD, DMT_STRING, openwrt__get_device_manufacturer, NULL, BBFDM_BOTH}, -{"ManufacturerOUI", &DMREAD, DMT_STRING, openwrt__get_device_manufactureroui, NULL, BBFDM_BOTH}, -{"ModelName", &DMREAD, DMT_STRING, openwrt__get_device_modelname, NULL, BBFDM_BOTH}, -{"Description", &DMREAD, DMT_STRING, openwrt__get_device_description, NULL, BBFDM_BOTH}, -{"ProductClass", &DMREAD, DMT_STRING, openwrt__get_device_productclass, NULL, BBFDM_BOTH}, -{"SerialNumber", &DMREAD, DMT_STRING, openwrt__get_device_serialnumber, NULL, BBFDM_BOTH}, -{"HardwareVersion", &DMREAD, DMT_STRING, openwrt__get_device_hardwareversion, NULL, BBFDM_BOTH}, -{"SoftwareVersion", &DMREAD, DMT_STRING, openwrt__get_device_softwareversion, NULL, BBFDM_BOTH}, -{"AdditionalHardwareVersion", &DMREAD, DMT_STRING, openwrt__get_device_additionalhardwareversion, NULL, BBFDM_BOTH}, -{"AdditionalSoftwareVersion", &DMREAD, DMT_STRING, openwrt__get_device_additionalsoftwareversion, NULL, BBFDM_BOTH}, -{"ActiveFirmwareImage", &DMREAD, DMT_STRING, openwrt__get_device_active_fwimage, NULL, BBFDM_BOTH}, -{"FirmwareImageNumberOfEntries", &DMREAD, DMT_UNINT, openwrt__get_device_fwimage_numberofentries, NULL, BBFDM_BOTH}, -{0} -}; - -/* *** Device.DeviceInfo.FirmwareImage.{i}. *** */ -DMLEAF tOPENWRT_DeviceInfoFirmwareImageParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{"Name", &DMREAD, DMT_STRING, openwrt__get_FirmwareImage_name, NULL, BBFDM_BOTH }, -{"Version", &DMREAD, DMT_STRING, openwrt__get_FirmwareImage_version, NULL, BBFDM_BOTH }, -{"Available", &DMREAD, DMT_BOOL, openwrt__get_FirmwareImage_available, NULL, BBFDM_BOTH }, -{"Status", &DMREAD, DMT_STRING, openwrt__get_FirmwareImage_status, NULL, BBFDM_BOTH }, -{"BootFailureLog", &DMREAD, DMT_STRING, openwrt__get_FirmwareImage_bootfailurelog, NULL, BBFDM_BOTH }, -{0} -}; diff --git a/libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.h b/libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.h deleted file mode 100644 index d3525e69..00000000 --- a/libbbf_dm/dmtree/vendor/openwrt/tr181/deviceinfo.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __OPENWRT_DEVICEINFO_H -#define __OPENWRT_DEVICEINFO_H - -#include "libbbf_api/dmcommon.h" - -extern DMOBJ tOPENWRT_DeviceInfoObj[]; -extern DMLEAF tOPENWRT_DeviceInfoParams[]; -extern DMLEAF tOPENWRT_DeviceInfoFirmwareImageParams[]; - -#endif //__OPENWRT_DEVICEINFO_H diff --git a/libbbf_dm/dmtree/vendor/openwrt/tr181/qos.c b/libbbf_dm/dmtree/vendor/openwrt/tr181/qos.c deleted file mode 100644 index 1e0278a9..00000000 --- a/libbbf_dm/dmtree/vendor/openwrt/tr181/qos.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Omar Kallel - * Author: Amin Ben Ramdhane - */ - -#include "qos.h" - -struct queuestats -{ - struct uci_section *dmsect; - char dev[50]; - char user[50]; - char priomap[50]; - int noqueue; - int pfifo_fast; - int refcnt; - int bands; - int bytes_sent; - int pkt_sent; - int pkt_dropped; - int pkt_overlimits; - int pkt_requeues; - int backlog_b; - int backlog_p; - int backlog_requeues; -}; - -/************************************************************* -* COMMON FUNCTIONS -**************************************************************/ -int command_exec_output_to_array(const char *cmd, char **output, int *length) -{ - char out[2048]; - int i = 0; - - /* Open the command for reading. */ - FILE *fp = popen(cmd, "r"); /* Flawfinder: ignore */ - if (fp == NULL) - return -1; - - /* Read the output line by line and store it in output array. */ - while (fgets(out, sizeof(out)-1, fp) != NULL) - dmasprintf(&output[i++], "%s", out); - - *length = i; - - /* close */ - pclose(fp); - - return 0; -} - -/************************************************************* -* ENTRY METHOD -**************************************************************/ -/*#Device.QoS.Classification.{i}.!UCI:qos/classify/dmmap_qos*/ -static int openwrt__browseQoSClassificationInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - char *inst = NULL; - struct dmmap_dup *p = NULL; - LIST_HEAD(dup_list); - - synchronize_specific_config_sections_with_dmmap("qos", "classify", "dmmap_qos", &dup_list); - list_for_each_entry(p, &dup_list, list) { - - inst = handle_instance(dmctx, parent_node, p->dmmap_section, "classifinstance", "classifalias"); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)p, inst) == DM_STOP) - break; - } - free_dmmap_config_dup_list(&dup_list); - return 0; -} - -static struct uci_section *get_dup_qstats_section_in_dmmap(char *dmmap_package, char *section_type, char *dev) -{ - struct uci_section *s = NULL; - - uci_path_foreach_option_eq(bbfdm, dmmap_package, section_type, "dev_link", dev, s) { - return s; - } - - return NULL; -} - -static int openwrt__browseQoSQueueStatsInst(struct dmctx *dmctx, DMNODE *parent_node, void *prev_data, char *prev_instance) -{ - struct uci_section *dmmap_sect; - char *questatsout[256], *inst = NULL, *max_inst = NULL, *lastinstancestore = NULL, dev[50] = "", user[50] = ""; - int length = 0; - struct queuestats queuests = {0}, emptyquestats = {0}; - regex_t regex1 = {}, regex2 = {}; - int ret = 0; - - regcomp(®ex1, "^qdisc noqueue [0-9]*: dev [[:alnum:]]* [[:alnum:]]* refcnt [0-9]*", 0); - regcomp(®ex2, "^qdisc pfifo_fast [0-9]*: dev [[:alnum:]]* [[:alnum:]]* refcnt [0-9]*", 0); - - command_exec_output_to_array("tc -s qdisc", questatsout, &length); - - for (int i = 0; i < length; i++) { - switch (i%3) { - case 0: - ret = regexec(®ex1, questatsout[i], 0, NULL, 0); - if (ret == 0) - sscanf(questatsout[i], "qdisc noqueue %d: dev %49s %49s refcnt %d\n", &queuests.noqueue, dev, user, &queuests.refcnt); - else { - ret= regexec(®ex2, questatsout[i], 0, NULL, 0); - if (ret == 0) - sscanf(questatsout[i], "qdisc pfifo_fast %d: dev %49s %49s refcnt %d\n", &queuests.pfifo_fast, dev, user, &queuests.refcnt); - } - DM_STRNCPY(queuests.dev, dev, sizeof(queuests.dev)); - break; - case 1: - sscanf(questatsout[i], " Sent %d bytes %d pkt (dropped %d, overlimits %d requeues %d)\n", &queuests.bytes_sent, &queuests.pkt_sent, &queuests.pkt_dropped, &queuests.pkt_overlimits, &queuests.pkt_requeues); - break; - case 2: - sscanf(questatsout[i], " backlog %db %dp requeues %d\n", &queuests.backlog_b, &queuests.backlog_p, &queuests.backlog_requeues); - if ((dmmap_sect = get_dup_qstats_section_in_dmmap("dmmap_qos", "qqueue_stats", queuests.dev)) == NULL) { - dmuci_add_section_bbfdm("dmmap_qos", "qqueue_stats", &dmmap_sect); - dmuci_set_value_by_section_bbfdm(dmmap_sect, "dev_link", queuests.dev); - } - - queuests.dmsect= dmmap_sect; - - if (lastinstancestore != NULL && max_inst != NULL) - max_inst = dmstrdup(lastinstancestore); - - inst = handle_instance(dmctx, parent_node, dmmap_sect, "queuestatsinstance", "queuestatsalias"); - - lastinstancestore = dmstrdup(max_inst); - - if (DM_LINK_INST_OBJ(dmctx, parent_node, (void *)&queuests, inst) == DM_STOP) - goto end; - - queuests = emptyquestats; - break; - } - } - - regfree(®ex1); - regfree(®ex2); -end: - return 0; -} - -/************************************************************* -* ADD & DEL OBJ -**************************************************************/ -static int openwrt__addObjQoSClassification(char *refparam, struct dmctx *ctx, void *data, char **instance) -{ - struct uci_section *s, *dmmap_qclassify; - char qcomment[32]; - - snprintf(qcomment, sizeof(qcomment), "QoS classify %s", *instance); - - dmuci_add_section("qos", "classify", &s); - dmuci_set_value_by_section(s, "comment", qcomment); - - dmuci_add_section_bbfdm("dmmap_qos", "classify", &dmmap_qclassify); - dmuci_set_value_by_section(dmmap_qclassify, "section_name", section_name(s)); - dmuci_set_value_by_section(dmmap_qclassify, "classifinstance", *instance); - return 0; -} - -static int openwrt__delObjQoSClassification(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) -{ - struct uci_section *s = NULL, *stmp = NULL; - - switch (del_action) { - case DEL_INST: - dmuci_delete_by_section(((struct dmmap_dup *)data)->dmmap_section, NULL, NULL); - dmuci_delete_by_section(((struct dmmap_dup *)data)->config_section, NULL, NULL); - break; - case DEL_ALL: - uci_foreach_sections_safe("qos", "classify", stmp, s) { - struct uci_section *dmmap_section = NULL; - - get_dmmap_section_of_config_section("dmmap_qos", "classify", section_name(s), &dmmap_section); - dmuci_delete_by_section(dmmap_section, NULL, NULL); - - dmuci_delete_by_section(s, NULL, NULL); - } - break; - } - return 0; -} - -static int openwrt__addObjQoSQueueStats(char *refparam, struct dmctx *ctx, void *data, char **instance) -{ - return 0; -} - -static int openwrt__delObjQoSQueueStats(char *refparam, struct dmctx *ctx, void *data, char *instance, unsigned char del_action) -{ - return 0; -} - -/************************************************************* -* GET & SET PARAM -**************************************************************/ -/*#Device.QoS.ClassificationNumberOfEntries!UCI:qos/classify/*/ -static int openwrt__get_QClassificationNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - int cnt = get_number_of_entries(ctx, data, instance, openwrt__browseQoSClassificationInst); - dmasprintf(value, "%d", cnt); - return 0; -} - -static int openwrt__get_QQueueStatsNumberOfEntries(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - int cnt = get_number_of_entries(ctx, data, instance, openwrt__browseQoSQueueStatsInst); - dmasprintf(value, "%d", cnt); - return 0; -} - -static int openwrt__get_QoSClassification_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->dmmap_section, "classifalias", value); - if ((*value)[0] == '\0') - dmasprintf(value, "cpe-%s", instance); - return 0; -} - -static int openwrt__set_QoSClassification_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_string(value, -1, 64, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->dmmap_section, "classifalias", value); - break; - } - return 0; -} - -static int openwrt__get_QoSClassification_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p = (struct dmmap_dup *)data; - struct uci_section *s = NULL; - char *classes = NULL, **classesarr = NULL, *classgroup = NULL, *ifaceclassgrp = NULL, *targetclass = NULL; - size_t length; - - dmuci_get_value_by_section_string(p->config_section, "target", &targetclass); - uci_foreach_sections("qos", "classgroup", s) { - dmuci_get_value_by_section_string(s, "classes", &classes); - classesarr = strsplit(classes, " ", &length); - if (classes != NULL && elt_exists_in_array(classesarr, targetclass, length)) { - dmasprintf(&classgroup, "%s", section_name(s)); - break; - } - } - if (classgroup == NULL) - return 0; - uci_foreach_sections("qos", "interface", s) { - dmuci_get_value_by_section_string(s, "classgroup", &ifaceclassgrp); - if (ifaceclassgrp != NULL && DM_STRCMP(ifaceclassgrp, classgroup) == 0) { - adm_entry_get_linker_param(ctx, "Device.IP.Interface.", section_name(s), value); - if (!(*value) || (*value)[0] == 0) - adm_entry_get_linker_param(ctx, "Device.PPP.Interface.", section_name(s), value); - if (!(*value) || (*value)[0] == 0) - adm_entry_get_linker_param(ctx, "Device.Ethernet.Interface.", section_name(s), value); - } - } - return 0; -} - -static int openwrt__set_QoSClassification_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - switch (action) { - case VALUECHECK: - if (dm_validate_string(value, -1, 256, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - break; - } - return 0; -} - -/*#Device.QoS.Classification.{i}.DestIP!UCI:qos/classify,@i-1/dsthost*/ -static int openwrt__get_QoSClassification_DestIP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->config_section, "dsthost", value); - return 0; -} - -static int openwrt__set_QoSClassification_DestIP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_string(value, -1, 45, NULL, IPAddress)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "dsthost", value); - break; - } - return 0; -} - - - -/*#Device.QoS.Classification.{i}.SourceIP!UCI:qos/classify,@i-1/srchost*/ -static int openwrt__get_QoSClassification_SourceIP(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->config_section, "srchost", value); - return 0; -} - -static int openwrt__set_QoSClassification_SourceIP(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_string(value, -1, 45, NULL, IPAddress)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "srchost", value); - break; - } - return 0; -} - -/*#Device.QoS.Classification.{i}.Protocol!UCI:qos/classify,@i-1/proto*/ -static int openwrt__get_QoSClassification_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->config_section, "proto", value); - return 0; -} - -static int openwrt__set_QoSClassification_Protocol(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - switch (action) { - case VALUECHECK: - if (dm_validate_int(value, RANGE_ARGS{{"-1","255"}}, 1)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "proto", value); - break; - } - return 0; -} - -/*#Device.QoS.Classification.{i}.DestPort!UCI:qos/classify,@i-1/dstports*/ -static int openwrt__get_QoSClassification_DestPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->config_section, "dstports", value); - return 0; -} - -static int openwrt__set_QoSClassification_DestPort(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_int(value, RANGE_ARGS{{"-1","65535"}}, 1)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "dstports", value); - break; - } - return 0; -} - -/*#Device.QoS.Classification.{i}.DestPortRangeMax!UCI:qos/classify,@i-1/portrange*/ -static int openwrt__get_QoSClassification_DestPortRangeMax(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->config_section, "portrange", value); - return 0; -} - -static int openwrt__set_QoSClassification_DestPortRangeMax(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_int(value, RANGE_ARGS{{"-1","65535"}}, 1)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "portrange", value); - break; - } - return 0; -} - -/*#Device.QoS.Classification.{i}.SourcePort!UCI:qos/classify,@i-1/srcports*/ -static int openwrt__get_QoSClassification_SourcePort(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p = (struct dmmap_dup*)data; - dmuci_get_value_by_section_string(p->config_section, "srcports", value); - return 0; -} - -static int openwrt__set_QoSClassification_SourcePort(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_int(value, RANGE_ARGS{{"-1","65535"}}, 1)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "srcports", value); - break; - } - return 0; -} - -/*#Device.QoS.Classification.{i}.DSCPMark!UCI:qos/classify,@i-1/dscp*/ -static int openwrt__get_QoSClassification_DSCPMark(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct dmmap_dup *p = (struct dmmap_dup *)data; - dmuci_get_value_by_section_string(p->config_section, "dscp", value); - return 0; -} - -static int openwrt__set_QoSClassification_DSCPMark(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct dmmap_dup *p= (struct dmmap_dup *)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_int(value, RANGE_ARGS{{"-2",NULL}}, 1)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(p->config_section, "dscp", value); - break; - } - return 0; -} - -static int openwrt__get_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct queuestats *qts= (struct queuestats*)data; - dmuci_get_value_by_section_string(qts->dmsect, "queuestatsalias", value); - if ((*value)[0] == '\0') - dmasprintf(value, "cpe-%s", instance); - return 0; -} - -static int openwrt__set_QoSQueueStats_Alias(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - struct queuestats *qts= (struct queuestats*)data; - - switch (action) { - case VALUECHECK: - if (dm_validate_string(value, -1, 64, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - dmuci_set_value_by_section(qts->dmsect, "queuestatsalias", value); - break; - } - return 0; -} - -static int openwrt__get_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct queuestats *qts = (struct queuestats*)data; - - adm_entry_get_linker_param(ctx, "Device.IP.Interface.", qts->dev, value); - if (!(*value) || (*value)[0] == 0) - adm_entry_get_linker_param(ctx, "Device.PPP.Interface.", qts->dev, value); - if (!(*value) || (*value)[0] == 0) - adm_entry_get_linker_param(ctx, "Device.Ethernet.Interface.", qts->dev, value); - if (!(*value) || (*value)[0] == 0) - adm_entry_get_linker_param(ctx, "Device.WiFi.Radio.", qts->dev, value); - return 0; -} - -static int openwrt__set_QoSQueueStats_Interface(char *refparam, struct dmctx *ctx, void *data, char *instance, char *value, int action) -{ - switch (action) { - case VALUECHECK: - if (dm_validate_string(value, -1, 256, NULL, NULL)) - return FAULT_9007; - break; - case VALUESET: - break; - } - return 0; -} - -static int openwrt__get_QoSQueueStats_OutputPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct queuestats *queuests = (struct queuestats*)data; - dmasprintf(value, "%d", queuests->pkt_sent); - return 0; -} - -static int openwrt__get_QoSQueueStats_OutputBytes(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct queuestats *queuests = (struct queuestats*)data; - dmasprintf(value, "%d", queuests->bytes_sent); - return 0; -} - -static int openwrt__get_QoSQueueStats_DroppedPackets(char *refparam, struct dmctx *ctx, void *data, char *instance, char **value) -{ - struct queuestats *queuests = (struct queuestats*)data; - dmasprintf(value, "%d", queuests->pkt_dropped); - return 0; -} - -/********************************************************************************************************************************** -* OBJ & PARAM DEFINITION -***********************************************************************************************************************************/ -/* *** Device.QoS. *** */ -DMOBJ tOPENWRT_QoSObj[] = { -/* OBJ, permission, addobj, delobj, checkdep, browseinstobj, nextdynamicobj, dynamicleaf, nextobj, leaf, linker, bbfdm_type, uniqueKeys*/ -{"Classification", &DMWRITE, openwrt__addObjQoSClassification, openwrt__delObjQoSClassification, NULL, openwrt__browseQoSClassificationInst, NULL, NULL, NULL, tOPENWRT_QoSClassificationParams, NULL, BBFDM_BOTH, LIST_KEY{"Alias", NULL}}, -{"QueueStats", &DMWRITE, openwrt__addObjQoSQueueStats, openwrt__delObjQoSQueueStats, NULL, openwrt__browseQoSQueueStatsInst, NULL, NULL, NULL, tOPENWRT_QoSQueueStatsParams, NULL, BBFDM_BOTH, LIST_KEY{"Alias", "Queue", "Interface", NULL}}, -{0} -}; - -DMLEAF tOPENWRT_QoSParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{"ClassificationNumberOfEntries", &DMREAD, DMT_UNINT, openwrt__get_QClassificationNumberOfEntries, NULL, BBFDM_BOTH}, -{"QueueStatsNumberOfEntries", &DMREAD, DMT_UNINT, openwrt__get_QQueueStatsNumberOfEntries, NULL, BBFDM_BOTH}, -{0} -}; - -/* *** Device.QoS.Classification.{i}. *** */ -DMLEAF tOPENWRT_QoSClassificationParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{"Alias", &DMWRITE, DMT_STRING, openwrt__get_QoSClassification_Alias, openwrt__set_QoSClassification_Alias, BBFDM_BOTH}, -{"Interface", &DMWRITE, DMT_STRING, openwrt__get_QoSClassification_Interface, openwrt__set_QoSClassification_Interface, BBFDM_BOTH}, -{"DestIP", &DMWRITE, DMT_STRING, openwrt__get_QoSClassification_DestIP, openwrt__set_QoSClassification_DestIP, BBFDM_BOTH}, -{"SourceIP", &DMWRITE, DMT_STRING, openwrt__get_QoSClassification_SourceIP, openwrt__set_QoSClassification_SourceIP, BBFDM_BOTH}, -{"Protocol", &DMWRITE, DMT_INT, openwrt__get_QoSClassification_Protocol, openwrt__set_QoSClassification_Protocol, BBFDM_BOTH}, -{"DestPort", &DMWRITE, DMT_INT, openwrt__get_QoSClassification_DestPort, openwrt__set_QoSClassification_DestPort, BBFDM_BOTH}, -{"DestPortRangeMax", &DMWRITE, DMT_INT, openwrt__get_QoSClassification_DestPortRangeMax, openwrt__set_QoSClassification_DestPortRangeMax, BBFDM_BOTH}, -{"SourcePort", &DMWRITE, DMT_INT, openwrt__get_QoSClassification_SourcePort, openwrt__set_QoSClassification_SourcePort, BBFDM_BOTH}, -{"DSCPMark", &DMWRITE, DMT_INT, openwrt__get_QoSClassification_DSCPMark, openwrt__set_QoSClassification_DSCPMark, BBFDM_BOTH}, -{0} -}; - -/* *** Device.QoS.QueueStats.{i}. *** */ -DMLEAF tOPENWRT_QoSQueueStatsParams[] = { -/* PARAM, permission, type, getvalue, setvalue, bbfdm_type*/ -{"Alias", &DMWRITE, DMT_STRING, openwrt__get_QoSQueueStats_Alias, openwrt__set_QoSQueueStats_Alias, BBFDM_BOTH}, -{"Interface", &DMWRITE, DMT_STRING, openwrt__get_QoSQueueStats_Interface, openwrt__set_QoSQueueStats_Interface, BBFDM_BOTH}, -{"OutputPackets", &DMREAD, DMT_UNINT, openwrt__get_QoSQueueStats_OutputPackets, NULL, BBFDM_BOTH}, -{"OutputBytes", &DMREAD, DMT_UNINT, openwrt__get_QoSQueueStats_OutputBytes, NULL, BBFDM_BOTH}, -{"DroppedPackets", &DMREAD, DMT_UNINT, openwrt__get_QoSQueueStats_DroppedPackets, NULL, BBFDM_BOTH}, -{0} -}; diff --git a/libbbf_dm/dmtree/vendor/openwrt/tr181/qos.h b/libbbf_dm/dmtree/vendor/openwrt/tr181/qos.h deleted file mode 100644 index 4731dc07..00000000 --- a/libbbf_dm/dmtree/vendor/openwrt/tr181/qos.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author: Omar Kallel - * Author: Amin Ben Ramdhane - */ - -#ifndef __OPENWRT_QOS_H -#define __OPENWRT_QOS_H - -#include "libbbf_api/dmcommon.h" - -extern DMOBJ tOPENWRT_QoSObj[]; -extern DMLEAF tOPENWRT_QoSParams[]; -extern DMLEAF tOPENWRT_QoSClassificationParams[]; -extern DMLEAF tOPENWRT_QoSQueueStatsParams[]; - -#endif //__OPENWRT_QOS_H - diff --git a/libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.c b/libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.c deleted file mode 100644 index 28c2bc26..00000000 --- a/libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author Amin Ben Ramdhane - * - */ - -#include "deviceinfo.h" -#include "qos.h" -#include "vendor.h" - -DM_MAP_OBJ tVendorExtensionOverwriteOPENWRT[] = { -/* parentobj, nextobject, parameter */ -{"Device.DeviceInfo.", tOPENWRT_DeviceInfoObj, tOPENWRT_DeviceInfoParams}, -{"Device.QoS.", tOPENWRT_QoSObj, tOPENWRT_QoSParams}, -{0} -}; - -char *VendorExtensionExcludeOPENWRT[] = { - "Device.Hosts.", //Object - "Device.WiFi.Radio.{i}.Stats.", //Object - "Device.WiFi.SSID.{i}.Stats.", //Object - "Device.WiFi.AccessPoint.{i}.AssociatedDevice.", //Object - "Device.WiFi.NeighboringWiFiDiagnostic.", //Object - "Device.WiFi.DataElements.Network.", //Object - "Device.DeviceInfo.MemoryStatus.", //Object - "Device.QoS.Policer.{i}.", //Object - "Device.QoS.Queue.{i}.", //Object - "Device.QoS.Shaper.{i}.", //Object - - "Device.Ethernet.Interface.{i}.Stats.MulticastPacketsSent", //Parameter - "Device.Ethernet.Interface.{i}.Stats.UnicastPacketsSent", //Parameter - "Device.Ethernet.Interface.{i}.Stats.UnicastPacketsReceived", //Parameter - "Device.Ethernet.Interface.{i}.Stats.BroadcastPacketsSent", //Parameter - "Device.Ethernet.Interface.{i}.Stats.BroadcastPacketsReceived", //Parameter - "Device.Ethernet.Interface.{i}.Stats.UnknownProtoPacketsReceived", //Parameter - "Device.Ethernet.Link.{i}.Stats.MulticastPacketsSent", //Parameter - "Device.Ethernet.Link.{i}.Stats.UnicastPacketsSent", //Parameter - "Device.Ethernet.Link.{i}.Stats.UnicastPacketsReceived", //Parameter - "Device.Ethernet.Link.{i}.Stats.BroadcastPacketsSent", //Parameter - "Device.Ethernet.Link.{i}.Stats.BroadcastPacketsReceived", //Parameter - "Device.Ethernet.Link.{i}.Stats.UnknownProtoPacketsReceived", //Parameter - "Device.Firewall.Chain.{i}.Rule.{i}.ExpiryDate", //Parameter - "Device.NAT.PortMapping.{i}.LeaseDuration", //Parameter - "Device.WiFi.Radio.{i}.MaxBitRate", //Parameter - "Device.WiFi.Radio.{i}.OperatingFrequencyBand", //Parameter - "Device.WiFi.Radio.{i}.SupportedFrequencyBands", //Parameter - "Device.WiFi.Radio.{i}.SupportedStandards", //Parameter - "Device.WiFi.Radio.{i}.OperatingStandards", //Parameter - "Device.WiFi.Radio.{i}.ChannelsInUse", //Parameter - "Device.WiFi.Radio.{i}.Channel", //Parameter - "Device.WiFi.Radio.{i}.PossibleChannels", //Parameter - "Device.WiFi.Radio.{i}.SupportedOperatingChannelBandwidths", //Parameter - "Device.WiFi.Radio.{i}.CurrentOperatingChannelBandwidth", //Parameter - "Device.WiFi.SSID.{i}.BSSID", //Parameter - "Device.WiFi.AccessPoint.{i}.Status", //Parameter - "Device.WiFi.AccessPoint.{i}.AssociatedDeviceNumberOfEntries", //Parameter - "Device.QoS.ShaperNumberOfEntries", //Parameter - "Device.QoS.QueueNumberOfEntries", //Parameter - "Device.QoS.PolicerNumberOfEntries", //Parameter - "Device.QoS.QueueStats.{i}.Enable", //Parameter - "Device.QoS.QueueStats.{i}.Status", //Parameter - "Device.QoS.QueueStats.{i}.Queue", //Parameter - "Device.QoS.QueueStats.{i}.DroppedBytes", //Parameter - "Device.QoS.Classification.{i}.Enable", //Parameter - "Device.QoS.Classification.{i}.DestMask", //Parameter - "Device.QoS.Classification.{i}.SourceMask", //Parameter - "Device.QoS.Classification.{i}.SourcePortRangeMax", //Parameter - "Device.QoS.Classification.{i}.SourceMACAddress", //Parameter - "Device.QoS.Classification.{i}.DestMACAddress", //Parameter - "Device.QoS.Classification.{i}.Ethertype", //Parameter - "Device.QoS.Classification.{i}.SourceVendorClassID", //Parameter - "Device.QoS.Classification.{i}.DestVendorClassID", //Parameter - "Device.QoS.Classification.{i}.SourceClientID", //Parameter - "Device.QoS.Classification.{i}.DestClientID", //Parameter - "Device.QoS.Classification.{i}.SourceUserClassID", //Parameter - "Device.QoS.Classification.{i}.DestUserClassID", //Parameter - "Device.QoS.Classification.{i}.IPLengthMin", //Parameter - "Device.QoS.Classification.{i}.IPLengthMax", //Parameter - "Device.QoS.Classification.{i}.DSCPCheck", //Parameter - "Device.QoS.Classification.{i}.EthernetPriorityCheck", //Parameter - "Device.QoS.Classification.{i}.VLANIDCheck", //Parameter - "Device.QoS.Classification.{i}.TrafficClass", //Parameter - "Device.QoS.Classification.{i}.Policer", //Parameter - NULL -}; diff --git a/libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.h b/libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.h deleted file mode 100644 index 9143985a..00000000 --- a/libbbf_dm/dmtree/vendor/openwrt/tr181/vendor.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (C) 2021 iopsys Software Solutions AB - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * Author Amin Ben Ramdhane - * - */ - -#ifndef __OPENWRT_VENDOR_H -#define __OPENWRT_VENDOR_H - -#include "libbbf_api/dmcommon.h" - -extern DM_MAP_OBJ tVendorExtensionOverwriteOPENWRT[]; -extern char *VendorExtensionExcludeOPENWRT[]; - -#endif //__OPENWRT_VENDOR_H diff --git a/libbbf_dm/dmtree/vendor/vendor.c b/libbbf_dm/dmtree/vendor/vendor.c index f19627d3..ed17c654 100644 --- a/libbbf_dm/dmtree/vendor/vendor.c +++ b/libbbf_dm/dmtree/vendor/vendor.c @@ -15,10 +15,6 @@ #include "iopsys/tr181/vendor.h" #endif -#ifdef BBF_VENDOR_OPENWRT -#include "openwrt/tr181/vendor.h" -#endif - #ifdef BBF_VENDOR_TEST #include "test/tr181/vendor.h" #endif @@ -42,10 +38,6 @@ DM_MAP_VENDOR tVendorExtension[] = { DM_MAP_VENDOR tVendorExtensionOverwrite[] = { /* customer, tableobject */ -#ifdef BBF_VENDOR_OPENWRT -{"openwrt", tVendorExtensionOverwriteOPENWRT}, -#endif - #ifdef BBF_VENDOR_TEST {"test", tVendorExtensionOverwriteTEST}, #endif @@ -57,10 +49,6 @@ DM_MAP_VENDOR tVendorExtensionOverwrite[] = { DM_MAP_VENDOR_EXCLUDE tVendorExtensionExclude[] = { /* customer, tableobject */ -#ifdef BBF_VENDOR_OPENWRT -{"openwrt", VendorExtensionExcludeOPENWRT}, -#endif - #ifdef BBF_VENDOR_TEST {"test", VendorExtensionExcludeTEST}, #endif diff --git a/openwrt/bbf/Config_bbfdm.in b/openwrt/bbf/Config_bbfdm.in deleted file mode 100644 index d664e1ee..00000000 --- a/openwrt/bbf/Config_bbfdm.in +++ /dev/null @@ -1,35 +0,0 @@ -if PACKAGE_libbbfdm - -config BBF_VENDOR_EXTENSION - bool "Enable Vendor Extension" - default y - -config BBF_VENDOR_LIST - string "Vendor List" - default "openwrt" - -config BBF_VENDOR_PREFIX - string "Vendor Prefix" - default "X_IOPSYS_EU_" - -config BBF_TR181 - bool "Enable TR-181 Data Model Support" - default y - -config BBF_TR104 - bool "Enable TR-104 Data Model Support" - default y - -config BBF_TR143 - bool "Enable TR-143 Data Model Support" - default y - -config BBFDM_ENABLE_JSON_PLUGIN - bool "Enable json plugin to extend datamodel" - default n - -config BBFDM_ENABLE_DOTSO_PLUGIN - bool "Enable shared library plugin to extend datamodel" - default n - -endif diff --git a/openwrt/bbf/Makefile b/openwrt/bbf/Makefile deleted file mode 100644 index 1973dc7b..00000000 --- a/openwrt/bbf/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright (C) 2019 IOPSYS -# - -include $(TOPDIR)/rules.mk - -PKG_NAME:=libbbfdm -PKG_VERSION:=1.0-2020-16-05 -PKG_FIXUP:=autoreconf -PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/bbf.git -PKG_SOURCE_PROTO:=git -PKG_SOURCE_VERSION=x -PKG_RELEASE=$(PKG_SOURCE_VERSION) -PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz -PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -PKG_MAINTAINER:=IOPSYS Dev -CONFIG_SRC_TREE_OVERRIDE:=y - -PKG_LICENSE:=LGPL-2.1 -PKG_LICENSE_FILES:=LICENSE - -include $(INCLUDE_DIR)/package.mk - -define Package/libbbfdm - SECTION:=libs - CATEGORY:=Libraries - TITLE:=Library for broadband-forum data model - DEPENDS:=+libuci +libubox +libubus +libblobmsg-json +libjson-c +libtrace +libcurl -endef - -define Package/libbbfdm/config - source "$(SOURCE)/Config_bbfdm.in" -endef - -define Package/libbbfdm/description - Test description will update later. -endef - -TARGET_CFLAGS += \ - -DBBF_VENDOR_LIST=\\\"$(CONFIG_BBF_VENDOR_LIST)\\\" \ - -DBBF_VENDOR_PREFIX=\\\"$(CONFIG_BBF_VENDOR_PREFIX)\\\" \ - -D_GNU_SOURCE -D_AADJ - -ifeq ($(CONFIG_BBF_TR181),y) -CONFIGURE_ARGS += \ - --enable-tr181 -endif - -ifeq ($(CONFIG_BBF_TR104),y) -CONFIGURE_ARGS += \ - --enable-tr104 -endif - -ifeq ($(CONFIG_BBF_TR143),y) -CONFIGURE_ARGS += \ - --enable-tr143 -endif - -ifeq ($(CONFIG_BBF_VENDOR_EXTENSION),y) -CONFIGURE_ARGS += \ - --enable-vendor-extension - -CONFIGURE_ARGS += \ - BBF_VENDOR_LIST="$(CONFIG_BBF_VENDOR_LIST)" - -endif ##CONFIG_BBF_VENDOR_EXTENSION - -ifeq ($(CONFIG_BBFDM_ENABLE_JSON_PLUGIN),y) -CONFIGURE_ARGS += \ - --enable-json-plugin -endif - -ifeq ($(CONFIG_BBFDM_ENABLE_DOTSO_PLUGIN),y) -CONFIGURE_ARGS += \ - --enable-shared-library -endif - -define Package/libbbfdm/install - $(INSTALL_DIR) $(1)/lib - $(CP) $(PKG_BUILD_DIR)/bin/.libs/libbbfdm.so* $(1)/lib/ - $(CP) $(PKG_BUILD_DIR)/bin/.libs/libbbf_api.so* $(1)/lib/ - $(INSTALL_DIR) $(1)/etc/bbfdm - $(INSTALL_DIR) $(1)/etc/bbfdm/dmmap - $(INSTALL_DIR) $(1)/usr/share/bbfdm - $(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/usr/share/bbfdm -endef - -define Build/InstallDev - $(INSTALL_DIR) $(1)/usr/include - $(INSTALL_DIR) $(1)/usr/include/libbbfdm $(1)/usr/include/libbbf_api - $(CP) $(PKG_BUILD_DIR)/*.h $(1)/usr/include/libbbfdm/ - $(CP) $(PKG_BUILD_DIR)/libbbf_api/*.h $(1)/usr/include/libbbf_api/ - $(INSTALL_DIR) $(1)/usr/lib - $(CP) $(PKG_BUILD_DIR)/bin/.libs/libbbfdm.{a,so*} $(1)/usr/lib/ - $(CP) $(PKG_BUILD_DIR)/bin/.libs/libbbf_api.{a,so*} $(1)/usr/lib/ -endef - -$(eval $(call BuildPackage,libbbfdm)) diff --git a/openwrt/bbf/git-src b/openwrt/bbf/git-src deleted file mode 120000 index a49c86c1..00000000 --- a/openwrt/bbf/git-src +++ /dev/null @@ -1 +0,0 @@ -../../.git/ \ No newline at end of file diff --git a/schemas/dmtest.json b/schemas/dmtest.json deleted file mode 100644 index e362abf3..00000000 --- a/schemas/dmtest.json +++ /dev/null @@ -1,621 +0,0 @@ -{ - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.1.", - "Device.WiFi." - ] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.Bridging.Bridge.{i}.", - "Device.DeviceInfo.Manufacturer", - "Device.WiFi.SSID.{i}.SSID" - ] - }, - "boolean_t": { - "type": "string", - "enum": [ - "0", - "1" - ] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": [ - "Device.DHCPv4.Client.{i}.Renew()", - "Device.FactoryReset()" - ] - }, - "operate_type_t": { - "type": "string", - "enum": [ - "async", - "sync" - ] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": [ - "usp", - "cwmp", - "both" - ] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "https://dev.iopsys.eu/iopsys/uspd/-/blob/devel/docs/api/dmtest.json", - "type": "object", - "title": "dmtest", - "object": "user defined dynamic DM exposed on ubus", - "additionalProperties": false, - "properties": { - "get_supported_dm": { - "title": "Get list of supported datamodel parameters", - "description": "Schema will have all the nodes/objects supported by libbbf", - "type": "object", - "required": [ - "output" - ], - "properties": { - "input": { - "type": "object", - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "next-level": { - "type": "boolean", - "description": "gets only next level objects if true" - }, - "schema_type": { - "type": "integer", - "minimum": 0, - "maximum": 3, - "description": "0-All, 1-Parameter only 2- Event only 3- operate only" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": [ - "parameter", - "type" - ] - } - ] - } - } - } - ] - } - } - }, - "get": { - "title": "Get handler", - "description": "Query the datamodel object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "value", - "type" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "add_object": { - "title": "Add a new object instance", - "description": "Add a new object in multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - }, - "instance": { - "type": "string" - } - } - } - ] - } - } - } - ] - } - } - }, - "del_object": { - "title": "Delete object instance", - "description": "Delete a object instance from multi instance object", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - } - } - }, - "output": { - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter", - "status" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "set": { - "title": "Set handler", - "description": "Set values of datamodel object element", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path", - "value" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "proto": { - "$ref": "#/definitions/proto_t" - }, - "value": { - "description": "value of the object element provided in path, path should contains valid writable object element", - "type": "string", - "examples": [ - "{\"path\":\"Device.WiFi.SSID.1.SSID\", \"value\":\"test_ssid\"}", - "{\"path\":\"Device.WiFi.SSID.2.Enable\", \"value\":\"true\"}", - "{\"path\":\"Device.WiFi.SSID.1.Enable\", \"value\":\"0\"}" - ] - } - } - }, - "output": { - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "required": [ - "parameters" - ], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "parameter" - ], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ] - } - } - }, - "operate": { - "title": "Operate handler", - "description": "Operate on object element provided in path", - "type": "object", - "required": [ - "input", - "output" - ], - "properties": { - "input": { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/operate_path_t" - }, - "input": { - "description": "Input arguments for the operate command as defined in TR-181-2.13", - "examples": [ - "{\"path\":\"Device.IP.Diagnostics.IPPing\\(\\)\", \"input\":{\"Host\":\"iopsys.eu\"}}" - ], - "type": "object", - "properties": {} - } - } - }, - "output": { - "type": "object", - "required": [ - "Results" - ], - "properties": { - "Results": { - "type": "array", - "items": [ - { - "type": "object", - "required": [ - "path" - ], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "parameters": { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "type": "string" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - } - } - ] - } - } - } - } - }, - "transaction_start": { - "title": "Start a transaction before set/add/del operations", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "output" - ] - }, - "transaction_abort": { - "title": "Aborts an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "output" - ] - }, - "transaction_commit": { - "title": "Commits an on-going transaction", - "type": "object", - "properties": { - "input": { - "type": "object", - "properties": {} - }, - "output": { - "type": "object", - "properties": { - "status": { - "type": "boolean" - } - }, - "required": [ - "status" - ] - } - }, - "required": [ - "output" - ] - } - } -} diff --git a/schemas/dmtest.md b/schemas/dmtest.md deleted file mode 100644 index 1fa0dcaf..00000000 --- a/schemas/dmtest.md +++ /dev/null @@ -1,1933 +0,0 @@ -# dmtest Schema - -| Custom Properties | Additional Properties | -| ----------------- | --------------------- | -| Forbidden | Forbidden | - -# dmtest - -| List of Methods | -| ----------------------------------------- | -| [add_object](#add_object) | Method | dmtest (this schema) | -| [del_object](#del_object) | Method | dmtest (this schema) | -| [get](#get) | Method | dmtest (this schema) | -| [get_supported_dm](#get_supported_dm) | Method | dmtest (this schema) | -| [operate](#operate) | Method | dmtest (this schema) | -| [set](#set) | Method | dmtest (this schema) | -| [transaction_abort](#transaction_abort) | Method | dmtest (this schema) | -| [transaction_commit](#transaction_commit) | Method | dmtest (this schema) | -| [transaction_start](#transaction_start) | Method | dmtest (this schema) | - -## add_object - -### Add a new object instance - -Add a new object in multi instance object - -`add_object` - -- type: `Method` - -### add_object Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| -------- | ------ | ------------ | -------- | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### path - -Complete object element path as per TR181 - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#add_object-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call dmtest add_object {"path":"Lorem aliqua laboris","proto":"cwmp"} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "dmtest", "add_object", { "path": "Lorem aliqua laboris", "proto": "cwmp" }] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "status"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be determined by fault code" - }, - "instance": { - "type": "string" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7961},{\"parameters\":[{\"parameter\":\"aliquip ut laborum tempor\",\"status\":true,\"fault\":7103,\"instance\":\"a\"}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 7961 }, - { "parameters": [{ "parameter": "aliquip ut laborum tempor", "status": true, "fault": 7103, "instance": "a" }] } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## del_object - -### Delete object instance - -Delete a object instance from multi instance object - -`del_object` - -- type: `Method` - -### del_object Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| -------- | ------ | ------------ | -------- | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### path - -Complete object element path as per TR181 - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#del_object-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call dmtest del_object {"path":"ut officia pariatur","proto":"cwmp"} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "dmtest", "del_object", { "path": "ut officia pariatur", "proto": "cwmp" }] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "status"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":7423},{\"parameters\":[{\"parameter\":\"laborum consequat elit in\",\"status\":true,\"fault\":8381}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 7423 }, - { "parameters": [{ "parameter": "laborum consequat elit in", "status": true, "fault": 8381 }] } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## get - -### Get handler - -Query the datamodel object - -`get` - -- type: `Method` - -### get Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| -------- | ------ | ------------ | -------- | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | - -#### path - -Complete object element path as per TR181 - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#get-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -### Ubus CLI Example - -``` -ubus call dmtest get {"path":"elit in dolore enim culpa","proto":"both"} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "dmtest", "get", { "path": "elit in dolore enim culpa", "proto": "both" }] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter", "value", "type"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":8800},{\"parameters\":[{\"parameter\":\"cupidatat\",\"value\":\"dolor in pariatur\",\"type\":\"xsd:event\"}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 8800 }, - { "parameters": [{ "parameter": "cupidatat", "value": "dolor in pariatur", "type": "xsd:event" }] } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## get_supported_dm - -### Get list of supported datamodel parameters - -Schema will have all the nodes/objects supported by libbbf - -`get_supported_dm` - -- type: `Method` - -### get_supported_dm Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| ------------- | ------- | -------- | -------- | -| `next-level` | boolean | Optional | | -| `path` | string | Optional | | -| `proto` | string | Optional | `"both"` | -| `schema_type` | integer | Optional | | - -#### next-level - -gets only next level objects if true - -`next-level` - -- is optional -- type: `boolean` - -##### next-level Type - -`boolean` - -#### path - -Complete object element path as per TR181 - -`path` - -- is optional -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#get_supported_dm-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### schema_type - -0-All, 1-Parameter only 2- Event only 3- operate only - -`schema_type` - -- is optional -- type: `integer` - -##### schema_type Type - -`integer` - -- minimum value: `0` -- maximum value: `3` - -### Ubus CLI Example - -``` -ubus call dmtest get_supported_dm {"path":"ut nostrud do e","proto":"usp","next-level":false,"schema_type":2} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": [ - "", - "dmtest", - "get_supported_dm", - { "path": "ut nostrud do e", "proto": "usp", "next-level": false, "schema_type": 2 } - ] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "$ref": "#/definitions/schema_path_t" - }, - "writable": { - "$ref": "#/definitions/boolean_t" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "cmd_type": { - "$ref": "#/definitions/operate_type_t" - }, - "in": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - }, - "out": { - "type": "array", - "uniqueItems": true, - "items": [ - { - "type": "string" - } - ] - } - }, - "required": ["parameter", "type"] - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"fault\":8801},{\"parameters\":[{\"parameter\":\"qui irure au\",\"type\":\"xsd:dateTime\",\"writable\":\"1\",\"cmd_type\":\"async\",\"in\":[\"ipsum occaecat labore Ut\"],\"out\":[\"Excepteur dolore cupidatat aliquip\"]}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "fault": 8801 }, - { - "parameters": [ - { - "parameter": "qui irure au", - "type": "xsd:dateTime", - "writable": "1", - "cmd_type": "async", - "in": ["ipsum occaecat labore Ut"], - "out": ["Excepteur dolore cupidatat aliquip"] - } - ] - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## operate - -### Operate handler - -Operate on object element provided in path - -`operate` - -- type: `Method` - -### operate Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | object | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `path` | string | **Required** | - -#### input - -Input arguments for the operate command as defined in TR-181-2.13 - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -##### input Example - -```json -{ "path": "Device.IP.Diagnostics.IPPing()", "input": { "Host": "iopsys.eu" } } -``` - -#### path - -Datamodel object schema path - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device.DHCPv4.Client.{i}.Renew() -``` - -```json -Device.FactoryReset() -``` - -### Ubus CLI Example - -``` -ubus call dmtest operate {"path":"nonesse nostrud anim","input":{}} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "dmtest", "operate", { "path": "nonesse nostrud anim", "input": {} }] -} -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| --------- | ----- | ------------ | -| `Results` | array | **Required** | - -#### Results - -`Results` - -- is **required** -- type: `array` - -##### Results Type - -Array type: `array` - -All items must be of the type: Unknown type ``. - -```json -{ - "type": "array", - "items": [ - { - "type": "object", - "required": ["path"], - "properties": { - "path": { - "$ref": "#/definitions/path_t" - }, - "parameters": { - "description": "Output will have status for sync commands and for async commands parameters as defined in TR-181-2.13", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "parameter": { - "type": "string" - }, - "value": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/type_t" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ], - "examples": [ - "{\n\t\"status\": true}", - "{\n\t\"AverageResponseTime\": \"0\",\n\t\"AverageResponseTimeDetailed\": \"130\",\n\t\"FailureCount\": \"0\",\n\t\"MaximumResponseTime\": \"0\",\n\t\"MaximumResponseTimeDetailed\": \"140\",\n\t\"MinimumResponseTime\": \"0\",\n\t\"MinimumResponseTimeDetailed\": \"120\",\n\t\"SuccessCount\": \"3\"}" - ] - } - } - } - ], - "simpletype": "`array`" -} -``` - -### Output Example - -```json -{ - "Results": [ - { - "path": "velit sit veniam magna et", - "parameters": [ - { "parameter": "ullamco Duis do eiusmod eu", "value": "aute velit sit", "type": "xsd:event", "fault": 7524 } - ] - } - ] -} -``` - -## set - -### Set handler - -Set values of datamodel object element - -`set` - -- type: `Method` - -### set Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | **Required** | -| `output` | | **Required** | - -#### input - -`input` - -- is **required** -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | Default | -| -------- | ------ | ------------ | -------- | -| `path` | string | **Required** | | -| `proto` | string | Optional | `"both"` | -| `value` | string | **Required** | | - -#### path - -Complete object element path as per TR181 - -`path` - -- is **required** -- type: reference - -##### path Type - -`string` - -- minimum length: 6 characters -- maximum length: 1024 characters - -##### path Examples - -```json -Device. -``` - -```json -Device.DeviceInfo.Manufacturer -``` - -```json -Device.WiFi.SSID.1. -``` - -```json -Device.WiFi. -``` - -#### proto - -`proto` - -- is optional -- type: reference -- default: `"both"` - -##### proto Type - -`string` - -The value of this property **must** be equal to one of the [known values below](#set-known-values). - -##### proto Known Values - -| Value | -| ----- | -| usp | -| cwmp | -| both | - -#### value - -value of the object element provided in path, path should contains valid writable object element - -`value` - -- is **required** -- type: `string` - -##### value Type - -`string` - -##### value Examples - -```json -{ "path": "Device.WiFi.SSID.1.SSID", "value": "test_ssid" } -``` - -```json -{ "path": "Device.WiFi.SSID.2.Enable", "value": "true" } -``` - -```json -{ "path": "Device.WiFi.SSID.1.Enable", "value": "0" } -``` - -### Ubus CLI Example - -``` -ubus call dmtest set {"path":"ea consecte","value":"et ipsum velit","proto":"both"} -``` - -### JSONRPC Example - -```json -{ - "jsonrpc": "2.0", - "id": 0, - "method": "call", - "params": ["", "dmtest", "set", { "path": "ea consecte", "value": "et ipsum velit", "proto": "both" }] -} -``` - -#### output - -`output` - -- is **required** -- type: complex - -##### output Type - -Unknown type ``. - -```json -{ - "oneof": [ - { - "type": "object", - "properties": { - "status": { - "const": "1" - } - } - }, - { - "fault": { - "$ref": "#/definitions/fault_t", - "Description": "Any discrepancy in input will result in fault. The type of fault can be identified by fault code" - } - }, - { - "type": "object", - "required": ["parameters"], - "properties": { - "parameters": { - "type": "array", - "items": [ - { - "type": "object", - "required": ["parameter"], - "properties": { - "parameter": { - "$ref": "#/definitions/path_t" - }, - "status": { - "type": "boolean" - }, - "fault": { - "$ref": "#/definitions/fault_t" - } - } - } - ] - } - } - } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { - "type": "string", - "enum": ["0", "1"] - }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { - "type": "string", - "enum": ["async", "sync"] - }, - "instance_t": { - "description": "Multi object instances", - "type": "string", - "minLength": 6, - "maxLength": 256 - }, - "proto_t": { - "type": "string", - "default": "both", - "enum": ["usp", "cwmp", "both"] - }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { - "type": "integer", - "minimum": 7000, - "maximum": 9050 - } - }, - "out": "{\"oneof\":[{\"status\":\"1\"},{\"fault\":7434},{\"parameters\":[{\"parameter\":\"consequat in et cillum voluptate\",\"status\":true,\"fault\":7297}]}],\"definitions\":{\"path_t\":{\"description\":\"Complete object element path as per TR181\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.1.\",\"Device.WiFi.\"]},\"schema_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.Bridging.Bridge.{i}.\",\"Device.DeviceInfo.Manufacturer\",\"Device.WiFi.SSID.{i}.SSID\"]},\"boolean_t\":{\"type\":\"string\",\"enum\":[\"0\",\"1\"]},\"operate_path_t\":{\"description\":\"Datamodel object schema path\",\"type\":\"string\",\"minLength\":6,\"maxLength\":1024,\"examples\":[\"Device.DHCPv4.Client.{i}.Renew()\",\"Device.FactoryReset()\"]},\"operate_type_t\":{\"type\":\"string\",\"enum\":[\"async\",\"sync\"]},\"instance_t\":{\"description\":\"Multi object instances\",\"type\":\"string\",\"minLength\":6,\"maxLength\":256},\"proto_t\":{\"type\":\"string\",\"default\":\"both\",\"enum\":[\"usp\",\"cwmp\",\"both\"]},\"type_t\":{\"type\":\"string\",\"enum\":[\"xsd:string\",\"xsd:unsignedInt\",\"xsd:int\",\"xsd:unsignedLong\",\"xsd:long\",\"xsd:boolean\",\"xsd:dateTime\",\"xsd:hexBinary\",\"xsd:object\",\"xsd:command\",\"xsd:event\"]},\"fault_t\":{\"type\":\"integer\",\"minimum\":7000,\"maximum\":9050}}}", - "simpletype": "complex" -} -``` - -### Output Example - -```json -{ - "oneof": [ - { "status": "1" }, - { "fault": 7434 }, - { "parameters": [{ "parameter": "consequat in et cillum voluptate", "status": true, "fault": 7297 }] } - ], - "definitions": { - "path_t": { - "description": "Complete object element path as per TR181", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.1.", "Device.WiFi."] - }, - "schema_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.Bridging.Bridge.{i}.", "Device.DeviceInfo.Manufacturer", "Device.WiFi.SSID.{i}.SSID"] - }, - "boolean_t": { "type": "string", "enum": ["0", "1"] }, - "operate_path_t": { - "description": "Datamodel object schema path", - "type": "string", - "minLength": 6, - "maxLength": 1024, - "examples": ["Device.DHCPv4.Client.{i}.Renew()", "Device.FactoryReset()"] - }, - "operate_type_t": { "type": "string", "enum": ["async", "sync"] }, - "instance_t": { "description": "Multi object instances", "type": "string", "minLength": 6, "maxLength": 256 }, - "proto_t": { "type": "string", "default": "both", "enum": ["usp", "cwmp", "both"] }, - "type_t": { - "type": "string", - "enum": [ - "xsd:string", - "xsd:unsignedInt", - "xsd:int", - "xsd:unsignedLong", - "xsd:long", - "xsd:boolean", - "xsd:dateTime", - "xsd:hexBinary", - "xsd:object", - "xsd:command", - "xsd:event" - ] - }, - "fault_t": { "type": "integer", "minimum": 7000, "maximum": 9050 } - } -} -``` - -## transaction_abort - -### Aborts an on-going transaction - -`transaction_abort` - -- type: `Method` - -### transaction_abort Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call dmtest transaction_abort {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "dmtest", "transaction_abort", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------- | ------------ | -| `status` | boolean | **Required** | - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ "status": true } -``` - -## transaction_commit - -### Commits an on-going transaction - -`transaction_commit` - -- type: `Method` - -### transaction_commit Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call dmtest transaction_commit {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "dmtest", "transaction_commit", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------- | ------------ | -| `status` | boolean | **Required** | - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ "status": false } -``` - -## transaction_start - -### Start a transaction before set/add/del operations - -`transaction_start` - -- type: `Method` - -### transaction_start Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------ | ------------ | -| `input` | object | Optional | -| `output` | object | **Required** | - -#### input - -`input` - -- is optional -- type: `object` - -##### input Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ---- | -------- | -| None | None | None | - -### Ubus CLI Example - -``` -ubus call dmtest transaction_start {} -``` - -### JSONRPC Example - -```json -{ "jsonrpc": "2.0", "id": 0, "method": "call", "params": ["", "dmtest", "transaction_start", {}] } -``` - -#### output - -`output` - -- is **required** -- type: `object` - -##### output Type - -`object` with following properties: - -| Property | Type | Required | -| -------- | ------- | ------------ | -| `status` | boolean | **Required** | - -#### status - -`status` - -- is **required** -- type: `boolean` - -##### status Type - -`boolean` - -### Output Example - -```json -{ "status": false } -```

^iO{wbXDOe*A58twRZO=t%x`@-_P!dm9x6jD>#Vdmn^M(pU*_ zWPW3fL%bHbVl;S0!EwWgbqt%aWWl}(CKIrxj==#;Liv>1=z+fBO!yq_TO>L4vZ=k>%CCR zYpoJstN@6xnw?0OZt8HL(A`HdeWKSs3^O(m6oduH{ETNGvo%oD&sVZnb5Sx?%SLqu zSp5sxwVO{j_f2Zx12ISm+!wYf2k+A)0y}~k3GwE{wT)G5A6ph8McrS-KyQm~{Zl7!$B@zK6F5_16-SjHyh#xrZ5(bMJUiH>9>1Ps5X{A0O~R&14AY z_N4(8PTbGPXEV!kT*R?w6D>pwk69bK??Hslhyqg&s?82)Ss8q2Y|WK2zHQ>!Nu|q_ zVw*>ZMy7thF3114sC z)OfPZqvoq)pD9I9bZ1P{GNRo1m^Xs~kAE+H$Ut>V&6j z`Yh}#Ztg%Sm%vlU<&{j)YC1;jdIid)o%coyolL32eiJ5~+1a^Z4^Rm#rDgC@Fd_d-eQwCf;lNL-O^H1^LywJI92#3} zC@ebPk$~>6W4{pZZz)i|?qtH<2LB7DfEqoCl3w+uEKXf8M`^{E6dKyhc9Nl^!?1#~ z|3;@tw!MoKC4UewNh7`M!oInU3*d);4~LIv@i5+8Jsv{lv)JcdyQ($gysr0Pmnq7N z^5TR7OG=*Bh4t?kBrAtb+fGwU^P)AKmjfud#3nZby=|i8A^jYPBjwS@X* z)1r)1w3_ZIJSYLC`dN1fpr`Lb8oaD|T~tRchAW;w2>Q=cQrT_MdE@baLOsT0uaJT| z3pqa+<93CEHf{`+I?c;uT`gj>Rw9PnD3#Xf>ojZw{aqvd)4#gM#IS4OJe-}A{gGj z^g+fwy;j3MsmJV4_FoO0zImE6aJJF{|N*Xbe}Iz^hyP&Ca&0 zkt-}MeRso{W!A{BE7j=_c2SPDZauJ3z1zj1Xpe0X<6mS3MP<;x zb^VLrB~dX(BNy)#9|8wVxqB`;N9)a5`RwC`%YIJdvg4S9wgs(99MNE=5fjGDa#GO2 zH`-zNe&Wsnt47r^7-K}{PdX~>s$`r36~-0S2TWhkX-0ixFii$2rd>jZ%!);&Lh zwb3LTCQ5V2dlmXeQ;JW?Xm`&)V0@?bSa=D6|{+y$0 zMzN%-&MMu?68RVTJzKa=2JX1nHnA3lXkL(8V>*M$$-lnIsO!yaI@cN*MX!hCLnq2} zG6@fAD)RjwJN(P0C8VhdLjW!!w5V)2=3FBI+qtlGU5c`TZx93xrxad!CyX*tFFwXG zB5yX)T|dYK-j@!0M2<-q3@90D4wu?2NGeGN@N~lT#z-q+g5kCq!ba@6-8ZaK6$$VriRj;p#&P z96&X|zW(0_FaPEr7v5!8PU_@ImSSHFfNJXd2uWpW9qv@! zHaj4{gPIlDv(R*EM2dJ9c4Q1Br8ARMFABcD6PTl2v7}8n`3$Lrt|{oJasiqNIX~4V zy99!0?0f!T9*%O#ct`+QriZ;^j`L>!n&#VWdqGRHoh=a&#_VX^H0I^%yt|mecMZAjwkr_%Wq7 zXJk|Bn^5f2v7WQ1FwZGME~;%R7Hd(!vvy{T^8O@f8Y`W;p1-&H?!3#QWx+rIsyG(* z0V|iVxgs161)=-&_8j4!(Rb%dXXZ8v?`$}Q_A&j>GXO8dJHdV^=(>e?9dTDRfd^=L zj($LWBF6pRl^$7p=6A%a+cIT@l4C2H2w%s2aL}|QY&+F%Yr0S|Q^y^loTLjUd}Bxd7jQX)Z>Ewi&2wUOFH=eAR~LPhsWHO#aNYA4N(sCA z9vy7S;;I~cM+I^!$2BL_7c*oN+!m}Ot1!nfSgP$zcP1gg`3_)n8;-VD6NgzSRD%cw zUQZUTXs5Ba%4SVK8r9Le$vTZ=ceCgy3mTra%wfryI4rv8UQ(-}Wq_QN!nbLOiV9GW z6lt9U598D~?CArjbHh?3&PbAyBrUn22BOR)+mrW+>JfW#}e34F{6%+`-S#*FYS0NKppE33c#3>Oc0)9AaAz^Q2L=C%gRt8QJGICL zs`E2nC-NKgoWYou91GeJBM{CY#EFNwuJBQ5KeCP2_{CBfx;dx%6S6riLe(sb@3g>D zR~gY8Fl}n6XOBQz$z<)63t^~sYdX%t>q)t^2>|g^&BqRtU!Aei@BliyW3u1}ph-cJ zA}e;2?Vpe`fAI|cuI}t=RA;6y=O{{_%RY;e^P+XUA%eC-E&Ny5(SDsurE<`uF>Hv-x;Un@cb9~Mh;-;i;4f%Qw{EVE*F&cU|e&DacG({irOdSsH7lL z#LpJ{_!!=Z^XM$JWxCn0#IZr{-x*uwy3wgD?OPEnIILHRsYqj(bFElUt%1gihm=Cz zJ|e3wSDjP?iL`~_-`$6GbQ#8GyS=puMnft}oGF-qDruXLC?KaV4ugm`cd-eKm3R&< z3w3IcrX6xC2ebVC@BH~j#@gG$SX3Loe?2uv8n?doLfOIwnj#%D08?d$F%z&5!`17~ zI1@JSDfl*3yS-=!;(>Jf9jqLcGD#N1-FxHU{*8=?>WYf?3aC7ocg4pV#j_xS;zc?QNU!Zy?f zcq&Zo7?`3L0CE+SSM*6v=STt^ablFWGZ1;JBTJme$9kgPa-HN&eMK7UtvH{!3=G#* zJWQ0PiSrLkY~}DOUT+1sv$>{ysfC9*NJU-$)+IvwQYP|G2Hy!bbuJxz|V+ zAAD9k!qUcJ-}vKfB?6KE3HS8|7UsiS@usEm&6b_|adZXi5wESvI|CE>ra8hst zJeIgDDqCZs;Bmg$EAHF|KIknJJt!KkzcJJ+|jP4HC-SyOEOvQWv`(^1TjHR z?Qep45>W66^tk3%1TB7$j3>ry9H{auPis-#ym{LpV!uC1P+%wz)H|P|>Taju)Bdp=$wS z=%?KRSnvCi*9z;pG|s;3KsP_4|lj;kJX$H1yTIpjC3|iNv%LgjF*z z_PnL4bnYb4iT>V1iyn4zn$MGH@I8Q?k7>c83#|#nIlbqZ@C;!CEmK?D`Pmw^qeWEP z?$Sp2f|v~rF^Nn(O}ee>Qq;6iyNyQxF{n5mci4dMXZ@$NFX6UFXXT*9%GeKfK|1?9 z;Hal4-1k!h`Jw{gB7FHwMH1o!gLcXRi=pa1fzTFIB9&pCGH4W`IgQHdC3E~^TwEyI zM_5L~8yc52Fq$)%AX=5The$7AH-7-t|@4j{$ z_6^^Z?B@f|kZX;^RkQUYu|H|)9BqJ4T}wUrEtnovbLQVWUloDmeAnBXeNQfrJsH-8`dzDZDgAhYq_6E0wani2?~33K6HZsj}oI z)+m;0V^M;JT@T{d2)82w(d+sz&Lx3PHFhgNqNgnRng+fRL?F*Sb;c6Y_p`E}uJB$A z=l9ho?@I7hH@VxOcZ+pTLj6H1KhYi3CAq}(|vn`96XC!ubfoIlZS^47e01Uh^IpM1(bbxb^o zTTN4xP0BB~$Lqd!J}IC+O|tT{3G9`!mPdvcxMmy)XyI~ zbp~~KYMHp04E3kpPbbQ)5uR@we2Z9eLfRFm$Xw&4xBILz%Ol(2YwPU+$Y!PCZhISs zF{3-sKmVJ_>996ulbQ6YLo|M08ah**ek5DG%?UP;RNPjTJ9AHPduqD<%@a0}oou07#gFaWCs&w%4r)?8V!p{*~bSwRe zLgL)*(BI*hN(lZuV~BUr$i;{`Iu@L$Lja4YWmTFrPfaM?T-6-7&5EJW7)M+g@&lO= zZOq^s3~0xoa&*s^c$CXKWz%1`C*ZRSr8+@7UYS4~3&q&MBT+Ls*PB|j;6T8By_k2H zbs&?YpONhym_{b=1VC1g9NITG(l0~5bM&udP}WJ&P)dkMdkhZRw#2~r0a z=|xdBB;oq+?L!Gd%!N^s_i#w6Jrl^#7+P_~Rh7$Pz}Iu0O-b8g8=cg<5zXXn%&WT9WXkqZR=W%|ksoIo}hy&3Zkx#MN-h zVWkD52ltT}qcM~Iqb8{`zY^@e#4SPWyduvjVy%cgdN{Xc;Wg+7n{F6qi%sNfV*acW7?!l#ql0*vJGs zImyMVhfi1JkTW#lYk{^>dJXRtfT@W)Nqv30J0co39xYX2neZ)eO;F6j7-?FEZb?>K zdf+mr=RXzwJz@-=`uVdUCP?gDQ)SR=>8yn#DW`xvW}Va*$vx?IxA`VH1jX~Wz}%^6 zM+H|T3x^41$$^0m@LOq2bAtchLVc>%f=AwNB%}eh)tZQR1qb($gl(6*?1WGg+Knb(mYG3IX$ZA>)HBGSPyiVi?MKOb=$U4-j zjGs0F#@e4TID|C^Q!~vby{nOxtj0#8$)(L;03|m{@v@&+bM<-xCVfTVA6p?z?_O~H z>c=2=alG9X86^ksw@WoHqY4u;sUfqt=_hxTOz#{m;VCje$dtX1OEsZ_F6s8xJDnNy zGl@FVu1JJ|}5Jz3L@biSDbt-t5&-35;7n`Tz!Z(QH@jw7e5` zeVWp5DQV8!)f&mufufzBo*#*11DP26f{8hrk831`*8)bElA^(F1$fiIY|b6Gw-_)e zh%LR-Mz0Ouj6_cXSd%}9R~=Q4wMVmWVCI&b8hJU`&zz%#2TXJ}Tc|V=`2!6QwZ@>J zy$0>p$^zF!QT_H4_AYx3TZtCbkyO%3|H;3^FRaWhToUh8rM&mrvEB4H#CWsW)bD@vPxloQ-ZmBXrH`rsEZ>k}~I9IvE8L8!rrcwpg{rSuYQv ziB=|m2M_359h0fER*183NMe30CKwWx=t#R*P9CetJ^Mt`99HCCiDrE>m9S#DGwW6T3~ZuG^_Z8-b5$5^U4xA=5I9*Y#wL9T377>Q=Wq zKP|*bYYw8vgfDm&MzSyBFJ{|GIl_U&+E%i}!ls1utcQOfIRy7pFD{#`Ovq2|x7?kY zqiT!wi1Up-H;%T#@!?GFaA$ZYmQ$+udXC~i=Bj*{2&+vvJY+r|kYfoW&8(&Tme~BH z{dH`Svigdh0xi#v|Mp|_CP-H)frXQXoEQ;J@bY_dk^y1CC>`4D;7%=Pku|Pm%;Jfa#v?xBMpXo-Zc=t^D26?uPwS*w=BfQv z7;HwHMhO=GsUP@%6T5ha!V68*f`aJecI)T7pUF`7{T*d|F=TF)9NDSFQwkg9KZ(42 z5JS8j3LRlNM4F-@lue7#;R;gqn~&j&A?GBsQzLcaL~z7j$abSsd*eaJPN=d?0-XB? z(7#z%qP!#HEPjnlC(Pb=HO2kg{g;RZVca(lW#Abp5N_(QiyLwe)-ML(32k){Oc=a( zVMUFIFH(w`KHi8|5Jy?Q;Y=}gf_5@beDAJT0|K0E(ijdy1iOIcqEIaX3zM*@31GcE zuvY)({D*kX1RJt{qysk8!NFsV^8RU3awVZ`7ZM1-BCNN}`{oW1hIf=0Vz<(^Un(#S zS$Q7A{3m0N+>4{!e%yx~_kPzX9}9fPcokxT1J9v0p={(VD$EV0Hrjx>_(Jsjfx8ae zLEpaR@9=maY(EAiH#!BnL;!tX#4b?&@pfU7mFul&cE`{oR}ngHpFm5#X+GYOGm)U~JzzWPL36bYa(r0n*`0w9su-@!iftC^ z)Rip%AG%vBV>0zq^0yCNk%%F;i_*pro;^}k@i5AVvk7 zS95b(ju(Ckc<+2VFmUeORL9TBEX8CR0SeZ zvA;wqRANn`GnCDh%dSsl=?hM;K{QbYc68!F`RwKq1NM*o;IrloNzqY!B zBj*gH!1XF$n8~N_y(Q3|tPC?u>f3Wwr%DG`@7MEzo=DV&{c8ZdM^2Ds=uvzyfiusL zg$njZ)jhD-+lcbBlp=vR(nl%i02Uuu5FC1p8R>jZ>I>L9@Y5hm_cJLudeliF2t7|^ z6ZLZ2nw7vLl=0E${Tt9SsRh-UUjhnFuQ^dMTcCtn(H&H)8Zy@&O%p=367xE3g<&@v zVzh(6BQ}rCDapW@C2gvX8d-~46&q%EHNeSLXhqM(dg76?uc)ovs4zWib0f)RbM(jZRU60iz4Mg!4ELkq;Ic63JS_KY19Qi!fXDwobno8 z5Z5egQi=!KBX$v0B7FbpQzyToW%;-g$Rjhte~8{NHNcCv1`v57%eT<(8il@UxSC+A zi~49z*T@~XgzmXVJi@Nv@1U^cIV*b&HhOrTv5Fe$;NI(0#Nok@MvscUV85q&h09#m z9b#8!ZJK=xfBRHQcShzR21)?@+}eO}1`?zDy;m&V3qyx5i$0w>v0y;!=X0B#v4Szo z7A8pRCnKodDZaiN%D6v4|E#R%;NwXJm9H zw4?>q!vO!}Im6(3bQF!PiE}BzGn*JiQ=e?L1$_v--s#0*8j)~PN(*p4&w>GeGjlih zAQEvK@;7@FJTx2e)fhX4GI0ZU#`%r6{JY;#rN$AZiu&j!DO)jrAZB5z=?S|~LG;~T z9w4j2CsxCWP570*NGSYo8(ha(eY%GlrWaC{0jGLXv@e7njygP&d{$<(ifArP^UNHl zv`h*ffk^v4LZIm#WRkuRJZ_sFM3O| z8Fqs3-H7y;Gl{!qw&p+Pz>v+|kgNT>8-t4$xEqQG%{_m0e{@u z|EJa$u6SH_nD4$=>!wDX42zxoV1`?NDN6gbs#2=1J6a&l@bb!7W7PwoNHb`i0z08> z4ArVj&W&HC6?@N@-U=^SC!cH{)cu;uV?^Eyu`|a>l0Zs+%KC@It$Jvz9eAKjl;ltK zJAU|u$@xT934T?oHP9l=d)y-&^sKEfV#!v_~Sn#kBlS89)D zdWe1LMXtAOGV3y9!@q)-Sl=s>Lh5f?CTji{B8=d)ZcB6k`>h1^pCh~yak0Qg1jK-y zK6!=i15`E(96c6$Zn`t*X)iYN`Am)|_*Wdp@^h-_&5}g>|MfMvlT;D*L)$(g!o@UD%eQK4KqW9e@*8Z* zSXXY?=)!IL>x(~k^*Tat3Th?vg_=50R|F>{gNZAaC`8{$)JkZ@Of>BUqe{VdX|+Ikx&RbU?O(Wumg87CGBEq`hy0 zgfttoMtX$yb$}mX73keyRenS%GzS>uP8WFPHbCt+q|!aULuh$J4(l~1jqwqy_`){( z^rCKD#>h@#ytl$We$oQLIi-H+%oq+_!XxlfRWd+{V4mgO>kTaB>|W3xJhu&S%I+q9 ztB!<8aDvnxg3J3^mmuvz;juH0xel?;h}G68A4j+Sfn^IS$B zXJbMDgVzwtPPg(sL75fP=5yaNO5#%EIMt^CUvVVu20ADOLGLN-nX=qQP!Cr{Im&2` zx_?94;26BiOP!+fqRMGc04Y1@z*ElGu6~}+KIl~ZAV9E zVypQ`w}JBH3X5^k9-@<15kQStSShgQTUAEFv^3z<@RaABa~Cxp?yQ$f*ALnoXZP&0 zRu?u_SNj~l&`4`6iK&fdoH&Z8BkdH?h7sEO*lz9n-e(#~lWpQb`D^hum|tKc@0#Ow zSg>tS7`3Vn9kVW0nvG3aIU~urx&(!@3kMEedI>sAJzyDz#=NxuwXJfX*y&l1C9EtA zEJQLplWttQ)%4dwwasznc{pqjrY&YU!9KTo*_ zH`%y+t;T<|u_Thu-#0%;?6;+vZGphZlt7?@d+G!woO0zE%XK!s0u0MLBw(toOum^1 z*Syv>)7&WZ3(A5`=o=GS_hq+%>V|&sl#3F$^Ldh=lb<#>*D=NRG6_kVZYKs8fw+jj z0*PQt83La_{yOi8#89fC25$^tP>im~<&8jN+br^>HJ2Vzn##$>&_nX6c!)^Oeu6DI zdEoz-Sw2VTjk#qdrIiNU&9f!K*eEg$MvR7IJZ%MdjqJKu8 zb5FGRWPQx^2Dcs22bU{1Y?hfeI8Nq1A@eMKCr`j)y$OPAj(!RZBuRW^c2?e68x>$$ zo;o)k2x+)+$2}d8*hq}ZLXTZ-#ay)g$ee>uxd9lg%{h`s(TIy;35mwkYJeNh46AZ> zBXi?tTd>3)=aTt(ByTp5s*{bsY}#U=2x|KR#6Gu86~iJq z&{<~eFi5g+n(8h@Gk*~>GKRImuj18V|b`ZMba5;>}69)?9H?Z7Ze_*=>7+Ym%tU(PzALN z(4m(8m7EGs|By`k_C$|v?Mk`PI}@`WECP}+;OAJ4@Up0>6kv0YVgWUY2q&a9M}2VT zPg9Kh6(qDa>3pQkf~0}HtttEyC#Z^+!WMMU0nj9NB zEoF%0(-v$anRt?6ocMQHr>H`giX1hrJ8cBc1SXhXX#)z_pk^SywmW<3yv2fs<$|?Z za-pi^I#1ieRZZ+ZyB;auZosW(NT@x-ZAXE5;!Mm23{AG+W`(9T7W2zEXoyX^2t_?o z3UmWXq8{pJ=mWC4kt-D~fTF#plR8@E{?*6JN=q_|-4V2s_8yfplXxoC*&G!oU8D-Z z-gYJpP%tLA#T-CT_l#^!RidNL$xvJ^Sk)WgOAujZsBZ-QAB`2`8cx==Nd|t()8os1 z!gH zcH&$|7YU#g30ek1sB`zX{_+alPd%cd0g_fA`eiHpp}YQ{OEW&s$6NGAZorIe2fBt@ zQ|0w|fueB2Z(luvgBn#RHBeZXV!I*$zC<^dU_@K{wj3jzPea*AYd)BV=O1B`Yr0)a zp=+E|j{(3!wflMO zm(i0-U>H3EeZuUEUAk*)g(moB(>?@ngYDr(MD%Mb+Oi;ZgH&rG(6Or;ek9|_C+A=R z^Kt8OO~@0FN>;{c8bP7%g?=}hp`v}xf2Ip9&kv3TmN19Tw1WQOLv2=bat!kJ$+MzQ zYj2H%v26bi1Oc6w3;{%L8bS{z%AofY5@*M3Gm&g!*rhd2JfqEVsh|AOme6cQe3icJ zFenl6l}1E`5nY?e5GxXMuEI$@Srnqn z9_rS~;b#5=eJmpb-j5dCh^$J0-9{$&!^Ik>x49hy57?IM(Jf-DNPpT@4;e^2V0Jhb zZdZD^OxMhw(GXqah_abc{v)_>0=a^) z=t0~G}7O|BR#nF*R0OUX6HJpZ9dweAYz z^>+`Ednm2Ewtif^FZm5bcmJg6r)u_;^WYcR^MjjhgXse?#OsZv&s9As-Od z5!m^adLE@_MD&8$JhDPbCp+9>L}XbWNpyq{5r3$4r#^tWN7((QrT+z3^Gw<-*5mEQ zQ07JU?y{vWGR_TT@WidNti7{HaFQGg|3b7vUAqLlTW3J#Qs?Pp-UOwK(ZnXea}-@f zXgyHeM&|2>8#U(9p(w%9+I*t94{yE}<5v_Rnf#oL@JqvKta?JZib-Ov-b-LrmCzm{0_ zEM!nth90Uli}3K>gYuc+m>x96A2^1VK4s+$!wp|Be^X-$HU1!v)N zb%cqn%_oEjh18c#Z5sPD)6?BABcy64aBDSze5B{@LHF%6=pFuh08UxCWFJXSO}&hG zXf3#d^2#L)CSeWl8-S7*kU$-?+v^VSsFfhq#M$KDMUv>>b&*z6Hr!|tcmQQ#rPevg$GjF3PdeLzh?N6Y*PVMjy zes*}6f|*p6->|q1x7I6n--4@ZaJ`kw?GX}USJ2R#pNJBFnBYSsHrx%YbJDR<^i9|G zp6?%CeJ_Sya9sL#;ooK^Vjl1GFld+@1$j3$FKK1`qDxgDro9=Nn2bXlyE^H)eAQfa ztBd}B5nb5ppDfuzlfj=2pjA}z0l0DOn;GdQnrHd);XvXl>U0KTqiBLwR}gW@Ox41% z@P5a_^DKaYEQZMg2C8Y|o`^x`94%eHw&Z|y7t|OUW~~4Qab4}9*k|Xbk^HSQ-p)IV zLJLI!gS>5D0AK)C=0j3tkT4xukGtoXP?7O-p=i<15Xogy{QWZ{&#JQ z*xS*Bt8(KpOzL2W59B*7?+71p;kOl2xEV(Y4fq{a2^WMS);b1zPirM{85o*CY3Zvp zl(^VY#MLmg=W_4cbld~4)VJ=G*Kz&`kbU%!6|<49hPNqXj$~d8LdH6d>nykV2bKM? zLoXl=xSZ=&N1H2a9K@M035EGq;s*1vf0ZSDo1{VW&!4@{A4WFR_*y8L(B||Hi%HLm zO(2D~_uZ5ULb54OsPo(}Nz9z-@Yf6s*)f|EF0(q|u)h0@lBMtb!cq%874^^5ueQQR z*q^G}1=%97G=2Jz0m<1eSGJ}37id3#P*{2AsPA9CuXCJv%(J@7fVB}p^! zSVnSt!2(N$0@U3RK|``EL3_1`^_mQ`gGZNq2gpGN=~}Q`vro&7EsOsXN6}IY6!X*D zNy&IZrB}H8P4-#=xsjilkw5`v#y%(|xJqQrr#jVaKCKwMFz5>^ps?|X@|?GjxqSv2 z9@4KO!MA$xE&~C{fDtbwQuNX~+aEr35Wb{$G&XQ-qpiLwT=r+LXTue2RATyc|Dg0? z1~J9aGL({s^v2iwF2Fd}tu=Ndr+XjcJHmvrDOWpTGIaNUZ+kb*7D#PFmhcI~yP3+4 zF6>sBtMp0YB^LJdnGhgNcjX*_fDsT4&90oiMVA(d{fG_)KgP#bEBb&~fb)nYxqc7s zs&XuV3_I=$5GTe*nTI#Fbw2@Q@r#fDA@0fbxtz=cJ{KqcasNR3>So2tt^CqGxiVAb zeI`pXC@NewL-P{XzwC3d$YItDHSyYj&%v;>&I_2bM6AQfcP48mk}4}BsX?NFh3EO+ zPS2k7TC>TCQI!6baU>%oq((h^7t#@Q)AlF{UCB*P-J;aIoc1fY$s;9GY;%N&DjiXJ zA~MNe&(D8qg^_cp3K13Ad(GS`nH)3)31Ulbd@c|Z+a5}KQ!nR{>&69?oI1HXi@hm) z42W=0whrzpe=Q$qCYwZPh+W}XmrqHf^h=3n4TR<&nKQ62$qi%}iPn8#$)QNoL=1sl zLS4=K)u}H~~81VmBysSgs1J&Ht_u_h2b6>xrs#43XC31{fyLVC!7X|yInUs=C zZVtFd*ti!gg88(Pi= z9PgCD&7J84dSozVD`hA#)!rewj+^EpTd;Phh=;?T$oz@N6onhA-d%^h7V!+#TQ)+$ zN~ll_saejl%So_I#N*)^WwVU*D+gY^UdPK0zQjNXs&GhO)Gw)0_%Kskpyz@(5jkKR zICm?*IWVoO3CSZ%-CWSTm>J^;&-DtK2)u0?`3|A@nEAm0jWNKWj+WqI!gk=KuKJ+< z+r|<(D`p+Dl@P*TZmR>Aa{a^FdC$}2(lDY?+4#NLUNc+h>u{U3m3cuYL(e^EOI=ft zKU?2Z{v2rxtp_&D-W5Jxf%Qb`C}M9iu_Lwo8p`G9BR$r(Q#dMn&tunqpALWiIedo!y}rh)Ym2E?Q8Cx$7(TPl zwUCdmiE6$W&|}f&TTvmq;wY)IxV>7wytWijoV96@zg{~bT+qb{obe_5CdqnT#GS&& zk{~8T8Cs5?^qP$D#c`Y>)BsjxW;u22qZ&&LEinThbUJ-YeZ!9&FJn6Y+BRk|&g>fE z%||`B73Q05}w)pf$xL1Z}o(YUh6#>NsV zI$5`3aeF9A-X3KE>9{a)@I_6UBrZGjV3aPt7|0+=O#z7VP7JNU_DplzQ7kT{+i%t$ z7h?c*_CWig$@Y5tTecP!f`I4Tt98S_HbD1Yvoh8aahYW~N$V>2Iho+uz2>Fuc(O+d z0cLW-WlQG!L8z54C}I%f2^{Q<-@Nyczb}|OU`tSFI0@Ba(8BaH|HCU=M60%hxvOVF zP1w_fF&3oX@;o+}zo}k5iGbE6iM0GJHa*cRRxAG3n=jL+Ih0Zch$c=Zj7zZ7u{Lu0 z8CltTjvA_Apq!yt3#f z@tA0QT;A9fwaCOyrH_gmf8(Uj1B%BAG7z7jd9l?8$Ro~e8qf~ zluB34I>SWYELL)NSWzOI=K3G$tz(ML#~!*M^1JKh1-!|74Ceitc_hYaZwj@ ziiBsV$@!U{z*ne3o?F>hc$naYErG;0)tclyKO(DdUIwY|EKU|mi};&LeM$}O z+ut_)`OKWN3f|87|Xi@jO2*R)#*Iv<~ z#aU5Jd{D?rk>?{r1i0t16(;w@$k}z;va0Mwg;E!guQD|F0o9=Yt{MSfp#9XZz=QmP zfCPr97#ncNxO4zCuKXVXvuOz639e!6W0!r6-G_ba(0`L5Fc}c#d(5(RoEuv;Gyg`yzA5289I0Nn-QocRDhrd^`=X{N3Xv zXaIhlfC?FUg~Jpsaj4HY>Un7iy2w1M_ENeYe+abY3purEvc7lV3*EwcNyMo+gV1T* z{QS&EOfObj;so~9l{#*jNge^<^h?e~Q1F977Kh$iceE0Nq}zJ@gXr@fD!rj)&v{#~ z)ZiB)(^U@Nk?7DWX-+Vdkz2&I1K9$VM;)a%c zP$J&B&%skE(M!Zt<*w(*NaP;W2L?`@r-Q=Ii*1L3NpW`0o&_7Sr>Ad7=2vjxNWTEL z?WcQYPEKUMxv#>|W3JoCLyX$N+5D;M3wu4#x?xYyX%!%?XQeENAV+RQ`E2jG&f#|b zlfQNJzCG>!2U4G~!FvMUKj=v%qTlI1g%B%h+Iva3C-isZ-r^&MS*rhs%r29$7Sb#K z`+q3hT9(Wo=ssvlG+AX3Wt`y7Bu2w5JEMneQ|L&v`!%X%5wtM@V@mK`NL6Id+}zro zE4bhGL_(Ks2jRgqB#yWbkz@&|xmDVdq4FX+38f0P_6?9)gHBr-Y-AA5eo$4 zE^E$#sJyo(QB$9pz=3Kb%uC5M5fs}N;MBS-KQv4#Ejb*(m-Q44XL>YocNChDS~Zo1 zV2LNA;{c!QbTC@>Gt_sTn)MEA4KwRaHqLWD=I|pZPIyR1?{YL8!o{1#V|xI8j5rJ+AMf%(`3`W5^E9-w2-SYP7CSzd9K?%hn~sFEutlompRX zWOe<2fvX5e=tycFeV7u@Q)qQp$h6q77m4ko@vx{^z*L?*(!7foLwc_XGp6oEd@XhL zCy}_NiU8}iYp6PFz<40m7T1=TT6v2jAcnK;CmLdcjU=@RB{tN#`9uFk?A;r>o zDRkP1OX;u~S+tESwwAnbR?KRD2Jswr#m+}fP0(Y%sYkgt5Zg0h8Tm(EhWA|~^26bA zU$5Fr4Id(PF+bw$pnmLBxw?|es?(|_Qtlk-R3>Xktk(_XP2!W za@R=AxzPpJ6Z~jNmC>{nnluVq{Eg~Fi5Y~SnYR5`YxSX_&(`N~TyHpMHk47B006J;9fZ4IrxFP(>l$Jv9x?@#F%1+BzF!Us1Fn)Dtk4|)OksYf&8^1 zAP^@p3`c-_MrtIz3P}_@N9^kw#)h&0iA}2-kYF(C^Ifc^GC{DB zm5Z=PvpB~wAZuq_wicnBOwof@v%Z%hzRT>6bF_s(ykb$WSHi=+Tlg!RU8}ReGMna8 zDyZV3HRIJlG(f72!e$~-@-U_W5jBEDfLfv@wSV$oxb(=8qw*O|;9?d8Z0}1UMg!?11o#QTFBEPgIN5_qmO2_fP z;^DKEzIok4V*FcGu@GIXeQ=cFOVyl>*}l}I$88}kOJLWf1ot&d(uVt0?`AxaalhWE4Cy~9trKz}jdVhSW&ib#8IL(0bMaFtKCZ79Y8ZdZ145LEl@eh@0kU+m4)oTsj1rQ!T?vQfR7D;4GR z$%Rn7h$w!{Wf#pW&9Ux-$eQcu#lif-(+Y@sU1Vp%>LH|bq!R#1TY7Omso>pbF<>)> zZd9<-V7&K%y?J+?p`B=74=?>P3fu-r7(6; zvB}~Y%Bdp)MphR4NBy(OsyyQcy`X;boI7TJ582-qeM3J9BKWsA>#&+0^0be7zVU-| z5zcB7YBBW?(-NA}LJ_-ezvi0)Lw#qLhy%Xl3h@mSv?p$w>rVX0g3`g|;sx6Zjo;t3 zYX7m8*hyK^+XbZ)1&*($l8P+R2z}cBU@b=lZC~0RjY zAD%Pdf@TK&traB?(8utN(pe)K^|c2ut?XT#!|RD&)P{R|D~uBLmC z1|kMyI7aCvt)TH0G=SFsN={~o35 z6A>N$;~Oz|w%>=;(#V#=KADr@5AP8kHsI4O|2YDnZPp#6nvb^iQYMdTv#ufDs1sw` z^27z8O$#*_7;HPvpNrtdzTlMaHMhx?=$hDygjI%U&=~Se3Z*s+s8vn!GuA1T6nZ@^iAf;_kID(VLYln1+Vk_8w;~=s) zggpS#v=DBEUi->kV~Kj5vt$v=oOU(=3o&f$t>kNPpd zbcTW_5g^bsOZF6zFG0Jh3vZ;to1u|fG|()}Tna5`D+s58r3?1}>SWLB>gzWBo%~xz z0(lt+^t+TgN|TiK83XFNI^t(oJTVTg9F=Z%5k{H_g{*W_LLEuJE#7!-%YI05G9XG( zwq57*nfuV7ma)rE6Tb>3KOQj2Ho4ucvCHnSHKYc`3=pZZ>NLe$=u}9hGYZEyAgr+~ z{}dd7lCG^hyDX453Yko}2Il(n<46Lm$ITKyjoEVgXS7qU7(AsyxO{-bg4z+~k?GTk zrPEaZ8|L$T2TxWh9)VqNSe(N5U;88shlBh`FlwT>5cs`Q;o@!@uoQHpm|0^IxDo!q zh&hzn&gx4$H@a(avn^!+DWwN90{3Sa+CYLrcPyO%FAV3xX8L5_)`M8|2hTCF#T)3~ zy4tQd1PtVUI?fA#|Fap>7YKsmQ-&Bdt~~>DKTBy0ZAy1P+>W_j$Uf!{UP&uzr4P^0P+DwKLve`rTM+z-OKA`C6Is9N?#Ma?aofFaHO<(wd*SYi#tTHkQ zc#@%Ce^Yv;8%U>b6;PEd`EHiX&N-gw>B0hcXD@1oxIR^I`MFnkj8_GG7}Xn&cULxnrkvjg z@yp1IbELKV%Z-^+!zy#hpt{I^!Pk%af@&)?@&F;pD7LEWs}r2A0H?+=W4}U}W=%XM+>zY z{|7_ChffBG6b!u3h*d_scTTmE4+dZ?M?^ej(aklx|6BU|c2e*xXGTfJl{)24s@7me zn_-5MwakE8pAw9>;WJt{;2<>T zfcI^t8)5l@;qbzA#(@&yXCe=FNjSJ-akCj8@;g@o{mG>1>+9eu<$>zBdlJTK-xANb zU1eRSwDGZ5ejqChoV8TVrKK)WJ6l=L(UlYpr3)lNV=udg5xjrB#mHVN1R*{`>Sdj_ zD{`&%xi$V05PKR;#yd5z<@zN0S*BB$NPjikDGvIB4Z@+I-MN@LmoU7ttzU(C0zy$; zTwwT|=Qf+5GqyMS)pbn}iBd6m*L+>{vz<%>FLi50BDv6h)m=#6r2jd+LN$n%d>O*< z4kL9Rl7UmPwTJf-vUpmyOA0La@N?mcop%)=59)c{6QEcC`=G{%#6j3k!9mN(!7C0y zOXBf4OTtS+;Xg-tE2pIeRnyBmLTb}ogh*% z*BT!a!8X~c;+RQov$@1jOoylUYf-T3J1aMOcDmK`i!kB_@=w@m6f^9Ur^nKPv}!>pmO0mU*aNHy72 zSKUjp!>C4izB4^9imE?*V2wN~$sTbk{s!^~S1&>}g7K2*bo7AxdEBg-Zv*c9P^t!n zLMULf{=b4WEIhrl9;PPVCh0j$B}BbXwqhOcNAEw1J%k&MM^LhQhN;!0gGtS(${le$ ze0^Rrxy3k?@ksh)n@E-MKC}5$R{1&WuKGXqu6Pv~c~7NA^yW9Q5ima106zt$flT74 z?v}4`QT$?0-G`#0krENXIq=T-jHY-MB?$tXcC0vGG>D#4p%ja3Hu3U0KDN?CK>Xqa z8@y?LLD`=pjf#fYzu;^Glo|&SBH8dL=_0)w07XfShA8YabsLa?rcSq`I(zMxoZE<3 z{gVYV5iDr1RyHr~v~=eIJ>_(z+-MHIv`x zUOUpn%cn>f`?(QZC4;V(^X_W#fQtVHVU$m;`#2(po!56Vn$}W?5G%pY^w5w#tWCMq zrGnB%fT#34_978W$s!Ko7j44;T;OvU;oEDc&>99^zDiA5pcQhifI|HS1WYmv??+m{ zM84hE(~PSop^OxXg%v|_xNhA~d6Gf=ZwkC-aq)PO8C14*1W-pK@ItThN7zNRD(r+& z?Mw!6QhmCieK_{3Q3zvrR>v2z z;ST@#WZ47L`yh`#N352=HDYWfSyx0s)I=D@?ydAP1nmZlcWo{}a+3fX0N}u{^a5@N z<-%c51*=OCm$P5(m2sL~tm-=gK)-H=Z2gotoe57L?7>bp8ZP!mTt#kl74)!cg@`hi zwc9)R(>Yk;5}8J?I;V~;EB*z+D8ui@jtqIt)r}Z3@FyWr9euB}nZKy?%(-s=;2oRD zOx?bYnbt}0=8PFAd4qu!iw#i4*;C*Tis5K_nC43B%Z4H^99eo#c4QR=dn@%WJ#H~G z#LXAoT9hSp9wc!h2KzQ9Qu9+w1j;VIG$V>oE9{^+uBJQhBAmK%xQd+kuxwktgK5b? zxa&90ip755lz}9(8t%ywk&0fnoo`w9jhb7Z7!Pf(L6PW_z!Q;f0f;MSktBQV$ETNI z^BOsgm7RDn4@2$b!>P_Brz6hXf0nyGIfAW*7#Q-@jG#xI`wwX9j*OB5F%B(L%AkB2}l z5m*}S2F))xO1r>qW2RETo0?;Jj2*u@<9>OFC{8n0!DecgI_Ym*Q#Bc++i1p`if&MqEwnWm$z!6sLwCZ>T_bauqPhe!_NzD*027GqPd83 z7<_BU;^u_G;JbA@)OLYCmN@Z8m5TV&KXG?vDI<^D2OgRfea_y242(}m>2UBz;KDz% z%+;r|irp+&O&f#p;>*zTn3I$px8O~!X`ZwlJpm70hT94d&)P~7&-EG5KYJ1ccR4>e zpz7Bk;p~t$E>l~Q$f^0fg05Z;Qjvhsx!Iv2rKrP-wNq;J39H;Z9zT~2&t(oZFfF;B zGgk#QE@)?nI>*KH3TIp|CUAE^wzmM1)Vf5#n@+{Fd-amYuH<^+aI?5qoj0;ttQEBk znVfxo(Sp|rc)#ZF0=iaXVl&M{Jb4lgO`_f3nx3UePw|NVN5gLD{#N%QU-_q z^Vw!RlHL_zM>=$6=$4sQuqCA-%R$|iw?&jqOw*ob$8#O8D^0Cbo;>$)+sBwz_ynz* zn(0zH;4nAlriw+~Rj(BlFA=Tln(iNSqTsL{=TXlT<+Ag#UF|xJm03BEbXjv>)L(=j zG3%J7E&qca$n2WkR9eyt2g(>6S+QwP>x<@}0tH3dSEk4BV;OMU1_=;OJMJt#@l)YO zkC%n*SUFOu z$!9uJb=1TMJ8_*u@?Raie*LChg65`UHMr@b>@^yWOB7oxGYYF@?6X{E&<+}fc6R)F zN{CUt4(&~R3xYPtHL+0xfnh3_S=tM3Ov%6RD@&#kem(JtLgyi!<#5iIs6LY4@e{) zqnEHJ?8#mhVI35hMtyZ)N6KV(hNycIOqs?Y=9Na~(H;R&hNPBkQ7WpfR)gohRU)y4 z$BEDOvsTc@Ve4>AlCgB3`->%wRysYL*aOfU%FC7c3FLJ@w@g~dT}I@iiKfI0+LC}} z%HYSEkk_)`heX8F4KurDt}x?u8T})_|yK>l(@baO7#@nP~R&`P&yU)Mdp0Im66Lp7d{VR_%Rh zw1j1snZ1 zBI-aTZt!~$ojxf#-{gID6k5dE;hOThAjK#DZu8k?6(dm&q0Igt=oe9mcc-YekI zVH4bq#fPP_D?S*60YL#$IZUZqf#yC*D``}leVDq28%fd>2$BqXh?l-~vxX}@EcN%O zuc^yIo#NC5{rBr_>oC??O_Ck{-4zr}nR}Q)hM0B}K~F7yx#hySnKZv!JRBYhVF;PE*rXT4LOS@>X?G9eSoxJ9;S@ODv1zDDQ!b)w}>B z)!T?Lb%>0*f|w4xiWNTO;^vnyB%F|a_a~Z};B2dO@~!j_uH*Z3v$pnVUUz6O;*ZDt zN0rl#pz({oVmczAYmYAxXn=HaItt58)r1a zVX594JiF_ZYVp3BL<7E4Y?wzQWVJ`2#j+mtK)T2x=AV6)_Kn*)JShR1w3(O~GK>ud z24n(avpgPWjNNP6?$~f+<=AU;#sX>?Q0Cq)2b~$BmCrV3^4QLg5d~O5v*AQ{*9;{E zdLym^SGn!h7e65V{Gvq^*-SUr7ag&CUpX*_ns(mhpShHpoP=MkHOk;*(_54)3Eh5 z8$&_*p`w|bX9EMR+)(y{nQ5{6riqewe-zav#&#+m08T)$zn=7QOL2N@T`ANtAO|!! zSg^V&I6>?%_reoB5S(=;QSoq?nzTXT<%B*z$G=!Y5udCod)##jSg3sCv6vGg#_K^j z*tFeBNP%gvk2*0^nl)5CvXz8RF2#)-A$vbwdWL&vI4m|hd%VYi4&EdwtF3ScO~|I3 zDmRoernGLSRcTSB_aZ*$Nh7Qn)uC(!&Xj@UV;5wqLNio7B|GS^(6_hR~w zdxJu`deuFCn=5P)a_v*K!a_K^BPHS+Klp$6V^j=T1CZc*n0|38hy&JveGdZoL_1E0 z>gHM0%2bg+)4%&wr<|)Y_>omao_-N;lK~Tmp>IHelyXn~hdccUX!~_4T(?q`RP)|c z0sY`wizA?s(qA&9dw`d6vahz`zuq;Sv)-v|qD+I?}xmOO$YxL}Hun35DPs)KQ~spm>68&6YK$#}gWJ zDxXwPY%f)DC+Xm^IMcb-0;gY6#RmCm{bM z+IE1)CclbH@&)@v`a7XD0xZq66o*KY41&jxZ(*Q4ER2>3;*O!(#btk8Y8HWqE;i!= zuy-&EC6ivlZ`|T7BClhx_+1S8bPSAxk^-}zz4S`sz5R(gy{Hs(t+#J3v>`F7Li2D~ zhY+5e(Zg*z*kHa2oS_iuHi#%T-M=kgFPHH`k}Fo2pG!HY9u7GRPj>9I(-hpmXHsNjuqQd(3$vSC<636r|lG9uURa?kf=X-kz1LmtDz_zl-67ui)QIEDwwZMsXPdIqVG zxk%%Ba%Uq%G+_0RN2)gwHXr&eAcQ*{gP@$gG-{1Xt}>g!U<=3sr&Zs9?Mi51@zcspyen>A~U%H5M zW|0}9)DBT9ykgc=S7-YDJb|Ih`{PCYa@Mc#{?>?_iR#+o$@9OzY~{|3B6kwdNRgp8 z#`>|x6aSYo!Q}@jf>IVYx5z4YYPuA$Rts<21JEBH+U+C4`H{8_rF1q+zmn60+2sf7 zo`WTI%aGruplSwh$bs4m3|H6%V9US(wr&qh{zz#o{hfadA@pWyh`kX%1PLWvB;-h0 z)N>wGl)$IrOoQzI@3u3>Nm!1xD86z7sbA1`%U1h||L$($e}zW8-q3hc7jhhcs+vt$ z%Bj)4?N6tjxnQ`N9xS%MrEp)HA|PAJc9TMoRV3{>S*4pbc9>gLA<403O`O-zmx@3fq6b=X)-QzsF8=KW;?* zdRm!&!Cl8)9RrToX+TA5@osBB2LUprKRkA)jv*fFrB+?zNYAF2SR*-4>{jwTYTTzz z+?AU{|BPw>o*e%G+H67V)@S`?lR=qmFJA7A@GiAB_b=Ljmshoe$XvL&DF}-tyIjEn zZA-fIz@k^x=g<@WJ!BuU{C53gYU76>=t5+-~DMalpZ`UffisuO_b)O~(95I}k+8H%PsXt=n$Zkw>Sh>Xc zEpUDfy7AaCH4+A&g)+QdV5-;;N6k!je~oF`UZ)o`*?r?=ZY@*j{1QF0O&H0#a*-1= z{f4$2s}|lDwEy)^kpk60@H5dp&Ju30-{AzT#vnuRrj z%oC55JuQ9KGlqexB#PYCETt}L_YA}IYC%Nca~$^lmVPX3^WdYT^jq>9Y}}KO8Q0TO zVv%sXNKwv?DP%mD!PT>;v2I(SzsCOnl3Rq+7c&V2HIWuQua~C=$hDaZNdyBQwh{OF zPI0W9QFUOqj;1*KMi6+p^HQ-wF^({$NyLh5<*L-{r^re2gfNl^h-%%?Dqo@L>kbY7 zC$uB+RV`J+^!BQ@_6`KHQQ76@6xlJuK4M9)0p=gr9)+e=Q%5Qg3aJ;z3ux%#!ITU7A87m5g^fR;pAf!F<~ zxKVLi;OqL@tZ_|sAgm%@VnowC=4+8t_#0S+{CTDt$#oi{bq#@G~hMMQGI<> zoO2K@7c6_22j2Pq+n)^3P0G|_@?^vd4TERe5 zX)s+tov!$91~m)*4oC{{!{35;TZ+p#8t_mZ(8b?1S7dM6?js4tTIHiO%DUQkuEzy= ziXqwSDq7O)hpF|DCKo+&2C9Q~8tv$+#T-9Z73hXThQM(eB3vXPo}K-6OE5?CM+s@V zzCn-%LTY6S-fAt;3q0BFUWJlZ8QJA0JG^1~OeqqG0J`qt-_nAK_M`?o5#BTBi`q>u_fjHtcf$fs5>K0o z{AF!~+xY;huV_0@USQK*JmRzL>f91?MC_Vjp!V@5HyzKAtP2Ve&S?1i%FdN~3^VGE zQbilEN5xrqQx!?=v>d#wuyE8r6eaxU?JFM22o_d@^Z2Ypqu;caz(UCZ?S zMUu`e`^8G^$+FXi!Er3Xv>fROBlRR!Ov7zqn|nG=oqT66In+1$exWQchP1)HPA^vz z1MZ&{5&0%jDT=H|FF^mH*M5EuMm`-|DRS8cR*DsY46!V0rLW4v7$6{0!S%`q_xAB~ zG>Zy67#^4{(9Lj!5+s5^`(?!bqRNsfx9ddgrTU+-pRc!=JM)=t**u8pQPPh|HSMop zyl$n3qrK7!k;glbkb_+<|Y*b#^kpUp5(Shpg`#XPt+f?j;37Kq2= zM{=qcBowvuz&vNCpyS$c6%9fug6){$Rvp5umXPmGk6xt@Z85>%0SrSqPeJt9Tr5>zi7Ae!J%=}0{C)W2{$Kk zpUhr*7EpwrsobjjP8<9sOZ>FItjr==U+lzV3(-?G-TFT0?4|G`VtR2)C{7}qw?uH( zG0q^uWzfV21k&Jl`7B5ZC7AEtKT3c}cEi&bjIR)o$MHojS8;qxNUd#2|V zRZc|ag_|o`5jMUNt9#MFDw5GT&nNNX`^vdS+}rtWJZI)#-f>~4AW{|%>CO1tP%oKw z#`IOkW0gC#@j;zn$9=DSy+?I|L=6z5x?@PxnnwUy@5+VI0v@i@&gHI zSbnHC1UYW~XK?iDIcd`{0ym|eId_#{6cYFHchon!PA14&L_lXgLp<|CYpHL>qF=kq zLh`C3d05S_WlzEQD|sVBxY?pEOi6(%F;=znrK+Hmd#Qyg5E+0!6mzHD?d--oL@L5x zF3C#vE@zO7jwzE~M{N(6@c-Ee`XgVV_FD5bk z9K;7%C%b1{9)5Wpm!~h*zt>*)-R5$;J5gPYDY>#-Cu=E208L`p5|!0Zu3AE0Hu@c< zwr7nZy(BcwP~3JCi_trOb`XG036x6aHx(YCVE%uzOjq_DVuKf4K^3c1O$Kr z?+nAzvyUhXdZu`GKVc;1qqbcRNXF_=Hu$%u@d|^O=NSBrN_dxE9UT zlUgPjmTg=Out4)7NIq1N9$ED8?{?qixAJ>nFa&@K@wOx|!k9HAJgC3cc%7dX$%){J zKylhJPe&E9muPN<#Moh)39%AduL{A*lg76dhUNzKaUyn0m8*H};CwCc?LD~he{8R( zatmyvAow?CbuekcCEe#3;$aHSJH2vI8BN$GZilF%1Bz@-wdiK2PyUV@m?;|6^-8M% zZN)6s55%s%x?&&)5Srs3ge*Q=hkm-=qNzYZrWA3l%K~dA+m|*DpOcm2o@hEum!r=Y zAGj&>qEXRM*PWhX7HQn&U-FGXb*yW4xtgP_LTofN{Snj@==ix^wtUF0jrq5H&H1Kw z-b@;GfwyBvw6{VH@!$BUy2r`-gx!sXb2)dJuJ0!mtHvToNPXTH9BisS-tTaEv-(Wn z39rjlI!|9aJ zXuJ`p=#Ho9{kJ##!ZyGRs)YPbfL@Vc_1(0iu`}rZiUkehtz~P4n30{acfI-c4iO(V z8=@cDv*JS2{8nu3U*!TX=4WAy1T{(-4C!;&1p)H0-gQf~MHC;-2^%a2stSWl*rJJv zpZa8=N#eeY@D?QL&R2^3!-9{CUTYd`tn|;pd??9H!|yuMJfF*NQHt3K2u$+`Z&J5# z8mP`)ZyJqNQ=ytAz=GlSP(b=xWI<}N?Zdow{cZQ@I<&@cFoJPZmi_9ZFb-zUjV<-9&=mxEU z7?B(tSnDQT=tk17GtFKk3)NxQcJp!!W4_+8WPyoHQ-($PD{lL2KlaPwjURJMxFwXV zS4;Z_CC9kwe%KP)hc3^Fnnt$JuB+1TqzHPfd~pR?5a>BQN$xi`TL}m`gBh=G38DZh z!{1gIqNkiDyb~V{@(f(017!+l!=nH>73x=rI85efAtK3L2SetMf%Xr=3sB66zsOM% zM%PMv3Fy$HhQ<+Yd>3F15aiU+5pYj+kA1thKT%Hrs+sJYTDKM5h}z9&f!aAnKn@EE zJEU8PMu0m3f$uw28ggR0pVee9pLuOcW>PDqWGpor9%9eMRY_>nnZ~9P_2d)_aqnML z#(GYio-`50tQO}-%LMeQC$cTmIERF>QJf;zM?laS*a}-g_yKJb(HRV`3hy1k0J`~a z*R4FM7AeV^sI3LmtaI^B4zI-pJV5A~M7-x*X$LcdhxU*(KSwNKbWc*=UkN65q|X~x z7gRrU70ttmIbZKII-(+`4g53A($e4Tmbizg^Zfz&_#7lbcOX5%$JQ_S3Va(7nTa(~ zV&7mlSP^kkmm%wmh0AI!C?pZfZqFOOF}K2Xg_LA-^L7jD0h?6V4xe0&`!oh==@i-r z13~%X6GvI#Q$|Xlxv0G4TJ%mCyNMZ`X>|l0#gUC^U%}*(F(C2ZH>UZtT@RW!QsW2~ z!m$t-qjgWV+`uVw6k&YxIE z&6w_miIjn%X zey2e?Qk?)jR9J>1)lud^h;rfRY%!CB?B`yJYPxr}d6~P4ZxEl1k`_sy#2pR0A1w441 zEjU4;_Co?23iP@NL~_6y?S?uLZ5 z0qjx~&kUIgNfZE4Kw;IbC4umiv+7cqSkoJ+0N#iI;VDRzxC{&>Z>VHU$#n<_<^&?H=-y?Bo<_^wa$SZWZ~< zJ)eU`njfL}+}pJC^-QAD!-91CxG=xO&(gHtpZ)7EM15T5HY z7fRTp2u%9v^2HIOQ4rWVjay#era5^Wrz3vHoN?&EKQiofgG-@scmiDm<-xx0QLXuM zK%IIGCk^2DUwZc{zE7-HcPpW3nwGfUovO&j?lxBQJIlCRk+73_{J(;3zP*&z3_{9f z-*JcODQ%|i7}~@v+*O)nEGfj;f=tfuAkzVTRO^s#ZC$M*oERlX#mE7K27uqKiB+8o z+sOS@;5fJH`_Do{_!?;nll3x!phe$M%IHr1sO%K6q-)H9FVNjZxLD7$MB46c@tf{` zXcl#CwikQ&8&4<{%Q*U&%C#TQ5AiSfux4F+hHp~y!1y_M+^W}Ks zr6~y;2E);w>i6B0$Iag;4W^K|+$@+uYIp2-VqJ0iW?oc%!2(<6?mP8;%$s1P*FEs2 z(c0NKf!0fd9(W7mTNY33I~jxJg$??6dEDpBw6c&tpq=KoxV(eKzGSB_jU{GFD{zV| zYZvql$&nt}YSD>Espc9f-h6;XvL&=Mj!86%?EH^cYhl_6af0|aB$?qLPilY^@50_& zWk%hJQhQrn*f-79e^frDv-2b04v+^7D8&VjphU=_d%A3`BQA^FYY}|&w4TFD(v|Q# z(SVAa@53@63IXRSQsFC2uRUVI#G_01rPdlrBF5v#gabr=kN`0>g&#~9mM(5h8$vcKW^9aI!RDZSy9?ct zOC9;!X2ECRi}X7YL+B~etKeK2)UW#oYSm9N5p zS0cqYY3a1p>sRFZsMvTRZb8|5*ttwK6gn0-eaP!u#gOT75Q7wXgxdfXcvPhu zNA+1!iw-%yGOmZH?-txd>`N_&!`@jpg+C-hb4dO$wM)CY;3ch!Hsor!r-d!9IfcPD zs$fzD1-$6E;KGjljP2YYiqxk#kGKgBdb*j%fgo@!c)G7z|u^Xvh`Uko^f@ z__Ns5s6Y$m6{}2h$aFIlM62T82pg(X8P0((M{*-01M+9X)@%~dC0xT4lYVrq&KXa% zPhv4i`Ngx!U6D$>`_qW#xSZBPKE#ojflf_#@o#ilmifLy>WMYdX_MxWXSrrGE55Sobo3)ByFhEi+hh z7C!EtI8&q<-b2MkrUx^e=9}_4z4?yR6}`izDT!=cP>3UBeoJJ3@M&|Jjp+8V5HIfu zy1jVMXewf}pMYVy%U$cZzj8;8>+ySou%@}q}gOpCqmht4S6hCmWkaWQf z!}_Wznzf>Xl?u&DkF>C?!GOk{2jFFf&;5X_36NtLfPVYLktUP3n$s$`3Zs;iscNm; zE5$+k;#1{ihX%buPY1SGiaKKM3dsfhDPv^PV;=nJHp{wO6En~P#YH>Ym}1E^0q3S? z|8o)WU{+ZEn>s7C70~siLQ{nwf??)xcSB}QX|7>qZfJy(kuq8(1MMgjAQ|G3L-BYVe^fQ6XTH? zIM{A;-V1vXxKqaUN6#*s8fOyB+xi@|aEH6+B*mN_ZLgPy*qe*?P#cul5tf_hbo!KK zEZ7f&KRA@g*`u(_YU7V=j{Hc|D}d^2LU@rtbsMt~yH+aaPe6~aLf&nPke(8Or2&TF z78AY0YWb)owsg+jc7p;BTrSnl5KsQyBmRo=H-cJ{O>N=A0{=mXwm$o%%XTo>R+<gQ*w_L)kr^r}4A9nFTQd%ME_se!~D?1f(W=Y#iL)M?=`%e}tMyL-IIPkDS9FL-x zK{78~5K98(KOR!J>uuT1x$l$A?x`(um|k-aIZ6X3$}Qm`3oTkJAl0vp$@(&J61l^g zfP7ur{G*CCJpf5P*Q&{``_I$ens9lbE-74mw#f4G>HA*6fu6{y< zbu}$~JtV`$KoC@5H&Ucz2hQP`{)MgNvDiPpTj)se{6PLU-1fT`;&OEG%G=5eKz0+b z=3bG(=`7;v5m`oyt|~tNF1fL^h*5x)VzSulF)E;4JZQ_;!d>6<|l1WqC}a3)aSCG8t)S{(`a(f=RdU5y6W8ygKozRF8J!0FO7t|M|< zD~1ek6nALBAU2TI5g1P`x?Hya8byS5Xqc+UqM7Os8PE*1r2q;IVZimCk7j53*|k>E7TvTz9=j zIw#A5j$bU5XvHo+LxU;ZUD1@b^M@kcOVqMXBPYz3_G3twN}e10Af@O}Pivpk3@V_i zZigT$*oZOnARI4Sv4cv6VhPqG@^V$ENB5*nzurmUabeuxxU~df+*-Q&14 zr+vPwUX}g5iKJyTe?_1L@$sTI(D&f={{zuSQbN!6h;5*M`xnJotU>m6v(bYC;Qf&K ze&vfHkaU6>{OY_(S|GI7(Nc2(81hylAua7u0IU}IY1Fl|pO=7-`~B@{O&olU9NW;na!bb=l4|pLeMSv5bVrqb$?9P@1I6YXwa2$>34!JJ0{tlj;4Jmtnha|+1vgTZ7{ZgVu+QwhIt=t zgSsOU9l4pTb{PZ;wiOo{Fm{4CxQIYhi9>qn5Kss24WyCbFV$I+q_#gO>sO4&A)_uI zmT=?^)e=E+37O^qL9XWzJS7vLR^N`r}GW~@7xU^xhmY}khM1FNc!G$ z`GCr}_bIg@pyz-PQ8BBk4Zi@GW)f~HI<5Dnk`LN%;vjaaC|dee5mUvwx^RgD-M{F7 zY~s&lD~35I_76F}_pxWt#4gNZAaoz|-`gG&d0+<$PaRBUT4FK_9fKikmcd(`ZNMe2 zoa^5S?!2szi=Xn>ROZhQgnT>!u}hx$`i}+|cbdwaXQKiWYjc^%TEFOi#9yjg2^RWz zA>J!kZye0eLQaI~wLsKE-kVwHYw>hWNGBP5y(~9H4}n$jMlG4xt|Hhoe8wHZv-g11o+5eubYD198x>OvF?XFYd%kfzU408Y!($q=u4`ldxSUex%H;U<;r z0Na32Jj5GwbTq|~)f0>*?$>+lO^sP*7E2sdc1x5#J6rZuAqzU28Put%iks6vGGttqvS<8lsS7uBv& zxb6%)TiR%AaIhjV@iM~IpfzApzRUQKJu83yy!*GqA-R_3V&#jQ>62|%Mx{RNc>1^R zb<4zn#ygh@9W>v~t5=ERUX8yR@S32OkX}zbJ%ED#*@6|Q7u)|uZVJHoG0>HdwesAL zKXYk)LkL7X3dv-!4M}THuUxH44Xwp_M&HnW@QIA?4|Gi~NDjo>)J%O!!d;x~%uRzz zyFYStDbxjJL~I}Ayz4d4$)7BeW_mxG)EJ1U=5nGXB(ZJ^uw}#;=2iu&K7VdB)uN&T zlzNgE@U#&+NmJtRG2SQI9Y%YNKP zR0j&J1kay7y57Lioicv&Vp!)eecJNED)uX=)te6cox5XWOf7F_r&6VhS1#ia&P4$- zTT5yQ80ngVstuq1y=95A3b8IfOR@6kcH-8sDe5Mkl3&OCPzFn*3Xjab&Njw5(QEW1 zb$gJZtUd&0M6&@m)s7i3KUi2yqr#=Oq)vxm>kff6QlvZ!h3XXq=K-$$!4*%{NV>Fa zgu1p*p^smq$@_pSyo&AXAZhEOcu(H-xe=vGT9P%#dsg2ypXD+jz=;GODV^tkiyEhn zX==AUWUtnON8WB3Y2@U6WJ<|kTxZT7Ud4&^@^F2z4_FPaJ7)qsDVUcOFfEW<8|E(k z*+}w?ib**rXJJ4$=24B+nDYEKN|!?-ry75bxY~1}vo5J^&ct<5UkmeKH!J1bMl;*$ zST994ASx354T=oQ9-8CkpzNL9nLLx?qPPzc1a~8o>^Te%?XaoS+a3(#CJbju!`G-d zTGPrsNS=T`e`M279tY~+(txrW9^3M&tQi~0IY^r)E-CMQ1N81n5--G45A354PI((- zKef}DTQCqG?YG!4RB|=!5i;c(1{+{4fgk8fEoF?ixL5FlLKbbXzdF5tbmQsw8wW?$ z=&N21I)yEqYNq!T4tHq9znFG;J!9SxWK|-WHWn`zF&X$#!4cZHjyf4}OGxKb zOUC1__p>ap2MDi1TL@2eMpzl-UcngS(sG8~S0qeCF}_Xr4HYK;4lIRo=sLB`h3GZJ zNHY0d_xTq4g^dlyeS;SakTUIcg54pn6y@I(xJ!kzw@Lf6pgDZU z1wBGhDxwM0CIC82$nB+)7=#+j>VYegnGg_UnQ?_kjGCj_3FaXZL)X$H5oN|ekA;cqk2hEal53mfsRV5nP>5cK4x=A&GmzqMc&Q(CAG-X^kT?(l2w+S+7$-n9pqDul0qQ0R zwjj#QI3{?XP@^-IObe2wIlBH_2;gOsR<Kz6|Fiz?tP=P;K!m)}>e zI{f9+Xa*z=^L#u=n-9e+vS|5ZW|rjG27_6FKc;)RcAKg%BY1YR7^G&1coitl_7je| ztX1xp0Fk?^+~GZ5|DyzX28V$;xfu;;5aEUlPYxhT7okvUzw571)Mdr9oz`yo@g-`w zSwraC@&S`&jv#Ydm3E~=0|<7g%pbAxYqn?<@1mI6(RUP{E^DKb?OBFgL4CBgz~uU*3k*>U<>2`1A4E^q zC)TcLSoHLER5D$x0YNh%kGnACYTM9+!g=k|dVjOk8m?`$&AYhkB74o(SbmF*7Fc zO}RymKwiw|=<%uNS??g8ERv9odJ*zX;!3ip25AyjhzKXO015K(xRjgKL$r_sQ5*3>tP|9ft#+Rn@NXdRe=9~$Qd60m zz0&@q$pTU4b#ShKZ`;`6r;M@)w=#8wAt#m6Tm*|G-y&w6I{YHAlFhR}v?Ul{HK$lK`Op%8_+U;YI6w7E~PuVx+&1I-EvR?;EazxQ?Orrx%CpNSR&DBNqaqnnEL z@BgQ7#7Q9Hl_&>_Ngg3y;Xt_@?%Q7OjwyW8eOfj<|>Vq)XddVJM+0G${hr84P1{HrKLKknZZVsEwCfDhWoC_XM+z zd1PvpXk6`7OcleAdf+7Irp<=fYIS%a{1LBY$%)VC@ji#7s&j6rrm{I_FsVR%K3w7P zj}nos-jndk^+BQm2)t#~kB|XW!(b~wrF)qeFt&@cCqQZo)oJ|Cl#Qzx%!HmT1o)W8 zcNoCU_YZ_Wh<$W}!_~!HRT<-E%TXl9ivt)qnCLWMSgKmU5`s~J!^v(axl#u3}oWCZ6k~!R1x$^4;P+_@=%}h7A;+tJU z*K8Zd24R7I*)yr4rVww0^pea)O)T4bN!53u#I6V3&k8eBoIq&?wS<)QQiXRCh<8s1 z-~@n7My7KGDoF-f?y=VXWM83*eTHbT08x-y&I>n%Y2Z3?&)1Y%Bt`&~YGXAWtG6(_ z0(Y3i2XPms`iU|Tdw#w~%2x1-3Ezy0oh*w&6+~XbPDjn-s|^?~aXtEz?4*FGjB+^# z!jaTx)K!QWIbOtXONW61m05;%qy?$$zkRuD{U{ibv>a`B1Rtkgy{a|~7H2F&nKdLo zZP0ml-B`9wg@VvutEq`#1mwJUuYO)1pE)qB;a&(7A1#s}Z7 zVDmob8>Fl84u4#yiimw)wR*#Z{b4C)iw? z)w*NzkJrK^;6>Om8J6g74Vs;0-Ral@H}SMb3QOQ`fnO>B!8mLX0;mX+N>6;z_wmd`YsM)L$nal6#7ti<>RAqF`L!}=dToLtR7M? zlqdm!jBa$!KuLZaW5a<6q29yq+qz?=GuB|~-QkM>7cC+lJ*|_IdbKvt$oqu&bI9D< z>Kqv}a;BFXSEzI`Mj5aU12T>ny*4V#gU@REgaWNvMN<(%8e~%`6O|Wn4yR(aK>tWa z;(iHj-W6!+?5-R!U$jnRvKtCDUI)$EVl+W7a=R*casly3T5c9nt>VR!)9Jj{Bmi$l zRy@(%0&uVZVT+@n*uxDHi*(?Q@h*3ndK~(2j zmJs1I1Zu3wp3`;Oep@NCq!))IOz*}BWGG{rzPIp|iFiG{mFF7>sB@f$mIUgY;CnM(J` z+R8`+wee7QEn*nds6FVy8SRIvXB&sQ8=nSt1iV7cE|ONG`-IIEJ(4qUJ0cPI>_ zvaBMm2-jewi)qInZo75) z+J&&X_%1rQ&Q8IH)|(}zv+s{;{m=KmiFm}2l(31wtC-=-LLDTJX=tw~J)1uNep*h@ z!^y3|IuyQz@8HTo`iu;$t@8AA(Dx4|`u+M8JM*>Q+{7<$3F0;rSgH+O-S*;eKz@?h zWm7hT7fSRJ7DJFZ-V3Wqo0?e&+M9VEFWEW2+{bNh2Rv*LQ&%Dd*z1Mv^aJthpf~N3 z0^fRJwquv@Hp1IoqF^2VtCy(oyP_W7{RspYH+B%TxnCKVigSm|#M^8nt^LwjpdI?DP zX5$&+dpn&O;@`e4t*RYz<@5#MK*3zQsvW3F=WvV(%_AJwHm)9XC!2`A3seL7jHo=a z)xcb$kyo=prg+Qvl0cx+=;WC%YNsERV2s<%>Cd3^vxY@y)LP@Q>B;Wxd_iybHKdu%_fXHdi3x8a z)OM%EmTZNU(WoFgj&Ab%L~`G5)7N*KgIO;}6xrL;=`S6iV!KO2xk@ps2}2@&cx3os z*+#gQH6j5>lEu(i!N5#sm_;8sMJ3wq-W`J{HObih)*(qzuvc_B3PtFq5=Rhl{|xdx&ySov#GO(9`{Q7 z=bIj&cP@;=)^vReC?}LpD}-B>POKEes>V1PUVCk5hsu+F^0BXktE*2DmJ%Xe!U;@w zvpDax5bCQN*W-y*uaxYv?9KT?ml?eQs?~!U$b>f-mG-U0GuT*9@}9Gd&)x#Ycg{LZ z=b^E2r8P&lPtQN(@PePT2D@YVoIXd`pN0~;E219TJ<$}3hM0g1$(z`bNT)flK=ia! zkQDDOmG4->RPT$StL3q4xe#ytVlcGK@`=i=G4#xy>x;P#Lhx!h&c$$$^Cj(OF&LsT z|I&RSAJ6;vL9oZmvG?L=afJz>9N3&CG+Wz~ktNDCVP|rSNV`gxaW|KZYRG6$?K%nf z^k6NBG%MIIMsyR)AVANX7SoXq9_8TaL3!dDCKs*>>_5^td!4%+3?0-niXcU|m4-wr z@?8n2Q<;l{fy|8TiI3HSPfy`=#EVK`UsnRB2Q9P9)bLc5HQH2+vK+-g z$zlU^M5&wSTfg7hwTt`p!IdiI526dUWC{yiP3@u6aN$GBA7Pt0b@RUh5xg{9*3FfA z=ffC|Qq6{8LE!ehXh4fGUPJW5$WRp5<&AegRwM#=^A}F}`eH7+o)=?SD)q4@DurjJ zXCsMhMn120_r5e5_3!?#4HmC(SIP%5;sg|; z$B9G13Zj`&l}BXe>-TIaBdcgIw}*ltNGdyWI2`Y^-AK%t(Jl(`@lwGom^`?!?$1&M zIzYbi!?(_EY@x1;AO%1R-4_G;_{@UzR}syDM-gRtTnAFuFh#>(Nql_J&wlLyR6wi0C<2V1Q#{K()VxM&fgJJIm!RGxMM~f}7xDBjT%DsL zyBIj;GAnAOX*`wSQEyLL`|u{s646%TnFi{Yq7z+3v#mB2ezr?Gterj)J8Vfss>;V- z=pninalfznKAF=qWGn0u`{O4|3iYb|z6!gKLCpq05D@xlA&g2!J(eA zvwR0eUP`ez|Fc@xh1B!!ow#mdg`1ROBsmWMQJa2nQAcM57;pl#V}Xbw?o$=q`-f)ayPOW3J&5i=(y@T*xcll27+25K;!#uElhvWHHIDG zYVtCd|KG5!njWXI#)O<6o?QgKm~nf5lNrK6|C3xX)Vg=<1S+m?ApJsPW0XPcKvG zLy%gij51vPbe6p!e$6`he>7FM9y*J*e`wh(VOTCfp+D6Yk#Hv`3!(V)^dwV99k^M5 zr^XOUVlTikO-Z6;(}HZL|5(DPTT*+u90yj0@_2~~ry=}@^vylA+|BVSN8GJ4Ak;c8 z)%%%XoGSUgXi7-eP}n^`<+j5p?I$>kb{W3fI-_ZAZpQJ-4ynJ#@sVP9%S|PvrY+;i0_yzSj0T9kH^`Zl*oZRBxt%={1 z7tt;P%em=F_Ytps3Nn7b9ilR#tgJRKYb(k9!boxV{f+aMKRYnt+XA(%jlLt)@ENF! z{QoQ-i3iG%vJRr%pTlCpuV-j0*qvtK3ghh5m>p6G638MDY%EdLbvw8UJ(6VverMJ@ z(0l3cl6MmdMg8KTET@AT)wTVbbY)X2MRHm*_3r@7Y+$EwN4aZ&%?ym>>$$%!JCteg zoeuG(nPwN!Oz;SAq>&DpO;o6M>D z5U4NPV9r3L2{3w}Co!w_CQWwm7d=o$z)EjjQC*me)=Pp9BVr(lThbqs-=0QGPJ(=R z{LTytJSu}Xpv@TOhUV1`&ZPAq?Uu(jG1;CqjV{Jcn%1_OKW>#%am7|H3!Qn}!J^du z&W4=n%VWS`9R=mV*t|Ol+S~O5SN13wMh@yA4S2bq+5yXwRWmnn1XvyJ;i?_i8@ z1=S}OeV+%*BhNRI!EU;*iQuH%0T(9h!df?ORq$lAX6GV1x#KT0V2maCAJ&2idGaOl zuf$F92Y&?PD7RQYXu?2>*Aj?EYg?&|0(q|w6{l|RMdqC56%2cVwN^QzmN2)_?;$*ZmGqM&Ey*7a3z0`xp_uKtxcblOl=Rw)XJPA4IFq*B(G3K2S~9H%hZamnH+kyQ z*Aw~i+F+m`S+Nl9hgPsYAj&fY{K)mf<4 zw){P;{V<+HHxAzXoaGM#E`hNHR>+!55TiC~u*P&|T@C~0m!rbRi&zhP!#2)4CF(3x zAQ+^GL0Cnn3;^E{7Y)& zp_(h1GspVBnrDQ^*3bk;?_A4GE-M~X=f%pM4x05rLl&La7#MuGF1SlEEbpgpB`VQr z8x!jMHL(lW*1i zKtg7`7VI7X@G$nJ$7;Teo>9;G?20v&+R9Z@D{cKeY61BFGO`f;L)P)N7}AmC7VRlb zP0U>yV=&}(iZH2=kJgy9Z>|9=Idyc^arP?`^M^$8jAa!9=P$AdgcK(yB3I@%Nz{-o z^lwd12Mx;BuUu+fgblb{DSe-;Lp_a2bCV!qVEmh>%Z0j)+&{Nc#xq@&tsJwRWu(@;HdcKjSrHrCToCDjYdfQv*KX!Ubqq^a!%W83#j9Mwml zl^dIHt=RHmlDRv_-WOu+EV;xHFlbQuF^8Y_(sG#GrMsveOCN{Ln3cVPX;~)#^2TiF zp^U^L%knNE;7&<6-+?Fbws(uw2^Av>D;eipICa&;0)7S0d@@Y`>?G`-6%*EzQGpPM ztqtVKx|yq2rLZE^_kBdDjqlMPs?(SvShS_= zxF}P2X*=%z5@Yv|ySUiUHO(g-GS(KV8SNozp|)a5rc6fPC>09K2^Z^xr3ms{w@WBQ zr8wFhMk|KHH>}Z~a*@Gs88MPX5uND5TJ4bk4lVDn{H8O-^1YKE7cKZ1x^ffrdsTMX zNJv4!ULUv%(~m;HEN-Dq-e>5O2lN}_S~ar_E$f#Thh)sApO2lkSoi0;ZnE^F*d?!h z(+{oc>#n0aC|DsZSZTofV2+KXq9^u?LHkZ!Av{ O}d3<@(hNU#Ng?GmXt!F?zdZ z#0!TLRVuP;-g&E$q)&wxVsPuK7zNip${kj zMqd*ZuMK2j zekvCS6i|v&!9vTRkX21@w%1LohdeeX`|yJZI7ezy+POxJX2EJMiyj{4!-_gqbMRWU1QCn8qTUo;qZI|-nt zpn6#3We;P2$%Yp89mVhKB^b4Hr&3KAE%PSN8I7}g>YSFII_OP0I-QCa=EvX?}Kr*Mj= zLW#fPj@3bv7{PB)LTf`)@Nt_Y9v$|5zq8CAQ-1}&rGaC0-q%7q1=b-d(`dJ_>$y-&pMl4lYx6o!r0AtdFg2dI#S6|P|`zku{3 zhr`*9(motcAepgkRLpX-5rUs_XUOzZcJ;qV(<0is9*iNFNV)yPJ8Sk3EDxZ=HdnYpcBjZD+rISVELoDNd>mmiB4ygZSL z!per&Hv;W}h6fS|9b_Kfdq%fTU%(L<#_Ep(HXQtKSc=-y(tAqI$n4Caz?-o+t0dDp ztpGeGRd2HZ*zO4~W|px{e4|652FXw5=_p&@>)eWqHi$#Eg^tuoJa=ImTOLfZWZ0fD zb?&IwTi)6dR(~F9Xvfr!`jIMmlp=v8xd`c=zxKagOo+0cWBo29q;37?pLTpk`h$Ki zVD%zbKCsHpjew6C-mu_0oJ-|gPO;H67wk=Je=G@l-qVy>kZCSDV`8}3`q$gA z4?@t(n*vZpq9oaITEA9?(ihCB-Qq^nZp5)c*G(2MxK-xVoT{MD{gMW5@E9A(5~i*|+WX`5 zcfF`(HYIH1xCy0A#L;Qz!)4YM%QX6L8zL&Sy-mBy-R$vWh5M$qxM_Niks&e1N_1@X z_4=2q2%I4n!Pb}z;8M3^`ic4qtB(Y-Z3lDTX-rHar--PY+;)KFKqf7I(YoBRBg!!i z+W%U6RTfi*;ETEVyfQG^MP+9}ky9)Y0NQw3s2eF;<-y&PF9*A1U2V;fj~XftT@uSU z=D-jnnf%G@09rH5#sihy@rKu|<;36Sjp^xeoNjan2cFc|HxLb)=Px|ib|ZKo9A9cs zkis{{v zR)l$_Q!~EI!~b)I}DEmt({c`}QXyRE0 z{A+U*^~3;~u~g8ZDZ1kBD&yW)Oy-HY-6TPWWd@BDI9APz#ElY_)h+<%t4N2S7(-*p;IxYdzv=*`^`Y^Kwn+ffQBo{hT3-_;-C%z}0j6fH| z0!CO2g6D+q^Vf6BPjFIDcDk^Q++Yp25x+*)XCn6M=^`ahFmtg1K&bh-1xFAg#rfXt zmQhi@L{1~$w|ofsM*fAA4HGe(b$LMY9^0)1t~6i;Xv1}%8_KFl)zFK?r&aXjD15Ei z9uxW9GD#IBrw3ey(-~G8-Srt{nN9?n71f#i_2=`Pv{O)(MrrI~vHlMi1UPFF3Ic9h z;eC{PA{X#o)W3zrd@+W)6b6kA@}PiRuxfuS3t0;R8%e+edBtLk7l8AoSG;6q+izN& zTAvo$xI6Vv$v~Sfs83Bn6VtJn*JREeosLn}q#R_zv9lCADQxL&;y=I#E|fH**(_zD zj^8%3Zvq?_dHZc$3Hb-97N$xIppAb}QHaPp28SQgRy!}|7|fnMFv>!NigGhpH?4uP z(bSw7SsYU*a&(XWqo&SbTK(pzs7-4G{G(9?gIAa*cMRjpait$OqBqRiwK7QAt=B0t zz?-9}J_anw0Jip-2@VPgpalm6QoxSglE5;FTCPv^gn~Nq$b^5|&Io*^^CCGIX>cn* zDH#aOMWl_Rqy*l2xohYf1J|Y4h1UNS3D2?j>$kzdF-n|l;24sO`(>=z%9ApCu%fg% z;T{g~{8pBIqzi*%UocmT^D+my?Z&e3_%Ne0*~z|8wH$wp%S%{CELfuiN4pr@i5cPV z6ImO4_hUh{gr~50WNq^R3}LWRtEN2NlccGMCWMH&LSk@&S?^x^B|WG96;9FVgW^vDhamhS zGx_}MSk$j8M9@kZb+SCbim=Quu{NPI(pVu557fE-oZwXM$j#ixPQQ(>4>)LJg3?Uyr zRqu+~MhSGy%AG{MT{;)A$!(`bugIt)L_pJCDRiGJ*>phPFFAIoVq1uYQyx5yg)u3V zE(8sy+fKonYK#ulFT2mfz_jlX@cUbPb;)m(L(X)pBYvL0d3N;E&6nIxJFi5yJ1$Uu zmV$*JUv7szv`Wt&Nib%riO7`4P%4*9C2GRvoX6UEAsS)miNv^z^-qHql!!NJG<-7r zA%9@E>k#L}T;+ONcc@k$1TI$GjjUt(f8S^0d>7AcrOpc9`t%qZ5Td(?u*TF+q|m?2 z>}=7`SuVE6Rd5q(Dil1kw{BE-Wi$V?Cu-p76gzfp_&j#8Cw4|5dITi>I|L*wwAU{} ztZf?0&!z`6N@B8L%W%dn^v1;tmQfI6F((-~QY$8+x|Zv2Yo3M4*3Mdn7B5!te9!Xb z67KnQZdvJNYfIg}2w#x757=5XTN9w39AC)u%9@&1xM zY_(Lxo(DDKjPFA#6c^}i%CsEm2wr(E=Ii>7^k))Y=12S|JWTbcX!XNlw*|1HP;&Hu zVnlrw7OR$muq4{!N+J0tYMaAA64jw3p4UWQ)}Uitpx_djHOqZSLDYPHd_(tVPRhL?YtjX68WINy>b0~B%>6c8MtrKzZp`DqU!p9c{r4S zlu>N>-9UT(y^+`{qHF`)x14|t2h!2foWh6r-FIh+HC#J`%$WCp>G~q4e;dzK!E^q$AaBlzE4D_bJbZ+fdl1Y@Uo)lU zr&9_qCq>to+Z6a8uRZBDTlJEX7ll{CqsvokVJ6L)?O z4N=eUT@Ps!4G6U^5`D#B6^MRWqm6Aq*B4h zbcV*L*}RR!<;uU1S)XHuJBe!|x-3vsVytogV_4D~KRnm*>}EBKuA;yojXg7amugKM z64qCF#eq_Qj1nZer`7<2=?rQ~l#|K1yR9MxQf!Idm}q;4+6#&-L)HI6Hf`sO@G6|ZQ=K9JlP zrfdNX_Azx<`=8HQ8?`Vj`c0nm>3Tul2Oklek(#rFmd8PCn^vVtw*~2|%Ii%hf^GLI zP}PaFl#wjt<6Pp-F8AF;v8dy0!oYcK0i$h|P@ijAl^nR`7PLtr<_8V7h8yi4|6Js% ztt^9En6%S@qdpPFWN{{}nNJ;O3EhTd!&deapLr86%F2h^MxhH?UcL?-%27aLA&c0p zBA*XaA^WNVll?s0H?R0R>ZqaJAlShbk?-G5K~GRZ#sx}zlu>Zg>?yHQWSt2`u8RGtUuY=K1DP@Ok;6oTfNmIx_#3da?mItvWv9CDkly;ebo z8kvH*wC*D|Tgvjx3amJ+LqL(@(AV0Lz!tDXZ*q>(PHHtnxSUom{Fuj$o)?a6L}~yr z*pu0k7xgiuJxu(c&7k*B&|Cic-?P3C?Q{u-w~SQ`NkTZ#0g_oYW^fT{tTJRwM@N1P zOixI?{YZ;6TD0))K`_bSyeviamO67N7h+c|pA^ZH|K40w3%d-&wBabiv-8EB9twl$ zrvz6+dK}VDMP94X-R#e7n9UDe*nIy+w-4R8aSCk5dILj?z7a$z=J(^v`Omx)J?3Yt zdH&oMAz&|g(?GMues(FB3=I3_52ur}1DXPY3CgadkcoS7YxSR7F67U>QpqlHCTv># zPH>T02^Qe5n$r^3tJQwavWD%*z<^=nB&c24H&%gml1Zrvi3_~|a+`nN1StXgw;`b$ z>)0^m6zExRAdqp*;6S#SboqmHjD)(0tG;(3^`)>BWwN~Cyls8HGN)2CnZ#mWi9*iF zGkBl(HVg|yGP+@A)RB>IQzcNbWDiEkKd`)Y7Y+z&jM!`E1s+e;?JdbW7JM}4=%sU< zp4g4Eg_4f@)|-U&244T8Nc*-&Y(w2bQXst2RGlw;;Y+Ap$_zW8%Q+rd8nVGfbif+s<$?PU9Np;_Mq zrzYI9ejj1L#>f`?;G{^@AzxuPULvCE_l47`){{psflc(j&>#T&7Rm<|xK zKPUF3&CgW-T!(vLrmfZev4l|2_(MAa&dESak6Ul+jL^kk;}OX7?uhg3u3^5M>9{cD zy=V3lpeH*UZ|zWU2>#wABW9rY>_b{N<2cPUZG5k})Ei6@@j#Jwm*B+=c3r!x={|m<5pr~DFTY6 z45N``?=wR>i9ND16J6>?>6+C^EU!qt?UBwCf{E1x0&y~3)ys@?Jj+0Ep_XHLC)+k% z{$*Z{#n5bKL9)LvC?WoLyYI)-IkvW+X-DHbPI3pyglIH%d4Z{)QlQ(a9^nWS{2lQ| z{}r_W6lJbB1AFt#I{x#U?q7eA6`zZp-ULB$DstoP=Nyb$Jn zn%l%e-eLkJ4ln}~vMGZP#VZ%k;{1D?5$wuEDug*ito&w@xbFH+iX$=tj+ISbUa$aO!E0y6^57R`ez zZ4aPK6)C7$i}TwWbI>MQrXlOGAiIfVV+^{x^i(8rYkvkTk#1~;C_^hXODsQ;k!+Ui z>1TDWlQZ$=c=D_*ivu?5#QXr1Z32|55LY&*q9d1>+Hvy`7nDg$gVJFy+=zEiZR^*X=5ILv3%bsSMNR4B1}N^C!l zt+n-T*=pWG9lY)z6_d`#=V@MikFv}Sw{OP8kfXkS@bBtPs;CAZ3|pe6TyJKkM@LE# zuJUnAxkdTwlH*-|o(kYA3}%n&Z^eEBh3iHD{zBG68qMWwtG*8d$hwQc^3r_1Z`eK| z%B{?XD{x^4v`8tHYHTy>s_fSc3LeQeGEeH?n{rovMpJM--}0-l@oA;z@!i*r+8A>! ztKGF8XxzPaZIoevr{$Rd`}8^+cV0*no{-tPV1b7GW9|wSfJ){A3+s(mmLWXC$o#~o z*b}XDT|mfqq6#-z4+$M@=S~ab)eXsRl{^MgrQiEd9E#jZBJ4$W%ZJ<>Ee_?gTxlYV z4@V&_G+icUvJ0?b2oZu+-HA}jLUJOK{+bZ~i1lWph^2ZroD733$`i+xY)>=^t9*!_ z3#aHQF)5!E6a>R~SFkg^(<}^mIYDFyD*Do~SN=NdF1FRNX|i$I#cMAMMoXF1xi_Gj$bj`%2#=N7DTR+U@MH%kgPa&BzutXw-L1%fNdueQK<7M zV-OPmc+FCvmJ zl@>d#J0K7gZM#v~iBCeb48RKdL>3juGiptC_x*hTO2J5-CxRhM)L3XZ&P0gR*F;9& zle#Y~n!S7nwV;Yw6OQ(bHJNHS$Z4LzhXPXOraO@Dd0Wf^5}jdsm5e_-JEM}ERi@$8 zT_~v&qH#aM>`i>oVSiaDb*)Ow8+hj`>N9vmRU5GTR3w zL;Tqk<|?vBI%o)afhXUE|>|5O0SQv(Y6+ zAl}i}T(+LX$iKP?gi(Q*sI+JM`2{@tB|k2=4-%|>4A|Ok(V1%c$VK=$m;~VjwlNAOJVwjVqXB&Wuj@*Yo26+wz?I4?Gp>4gEd#}{=-^)kJijveY z<+`Hxs>!*fvEAudU8+!+E#FZIzaTh3^U*#uzmrELDuOpZvPnuZN=NbYSG%v|p2q015c!oDO5hu2s(H(?m>=;1*jj z_`Zce)<=%3xK@1EmAqLiO2LBV=m1{th4ST@_+6=6GUBLFifFw-`NnF47_HFv(jV0^ zjV4e%Q=Bg$K2HAedYZBfl6bpS?+=+D;Yy&gN-I`yP*+~jR!S`283}Yz>o}+|6^QDv z!PB*(1M7nw!0e@?5Id}9-oX7}cDxGV99Pm4^1*{Y!~6s@eGXA{ob0f$MS$=US`t2_thf~aNEQ3nO*IgIR4%GVfCk-O+Fm&>)vw6thz~jkQ{Z|@{lV66*yU2~Wf22u!Nqj$Z zsbZ9#A!wxa9OcocjDG5v-#s5)({++*#DamsoxXGzp-w!zTQU~6?HsHOI>3N%K?`fn ze2VQ)Z}>zu;z5-ui|tqqdSiCe6g7vImJMNL4JKp7A;0YD1qOjzsrlrg z?DdrptEmQkK@7?eDFFcA9HiA@;11xDtS*=d@vtX2!Kg?%Lq{>8-(0D+?`^)&9=B8O zN~se_ad!c8l%3jKq2Ipfw2do~iuGmRv8Jt|{oO>5`{F=Bc$zcj%zkb&y3Y&ylvpb0 z_?SbSD0(4UjJkPMn?7$*RDqB2*i83$#}oQUVIELxOTzWV;BTg`Wuft1#PO`pp>k2C zoE}FtG?Ac^>$T886u=<=A@baQNXz?;*s3Sl;@%=ZY#i1D?{qYoQeI{x40M{m6Ivn3 z-4$G|zTW%fsDX*GE?&#Lf2?LB`RJ;U4&aD|yPtD#vhO+oEoigjo&WW9wg5=c6@ud` zH0|4EgMh*DaRUk^S3zHeiOHyWaVJb>*<@dm(;31xdTpl=QYSqyG6-W$$6`>zB5j`b zzj*X*2`VaUo);NPCT~1gmE_f>CNEQJp22qa{j-b=F#R=a^tMgtRFo}uUWw<&m#RVNP>**)HOj+2{PUdk_D?Sm%iUPsJ%K=Pk;2Fe6 z(m|N1fCTa_?n6JwTolH8TbbvixD+M&zyH*Lq$Xb0d zp!HN=ED2i&C%>8eQZ#-xl&~9pn6KBA8odW~R!HL=whhjk#O!r{i9yvQp+PqcUYjFl zF+7rpEi|^}9Z3AwzAdjNXw_0O6!DHZw-cp%2?yg=_V9SQnY^`)$8s5w&Bt4 zYuARrB{9UUWgJoml7f)ncwoTZCC1mm-zjy0n>ni6ZRVx=fnW(G5q;F7C1vGIti~1e z$N8P%dSRoW)@ev$n#?Fw-ofog)K6O93Wr8MAuF)hnWh=##^XGYtW}DAH_SA<;fM0x z#DC)Tn7hViv$_9gF(a^N8wNj;OkxP_}m%B%BUhaNhWc@@D zKfmv^;O+b0HXQXNV;9ZYjYc~r?8Wxm z?!k$;s3JoE0EdWbk?pJeL1{LO7&AHnv0rJ_1-5Shm|e`>6&)A_2a($R3eyrII}FYo ziVn1>L4hE5k1`g}Ja67|CQ=)%WYid%#pJ@GZ3&YG&bA%vKd#=+q;8T~L>4yTo2#g; znydTD*!=8Arh5K6G#FIx(oCT}RGkKMK?Wywh+7#fE}-84{x0ZwM~j#SRi{Whxdyc5 zw70qn1|#_gCEx=P@mOvKe}eO_7ZE5_Koek}1m)xKdG1tV zjkGKrs@M@Zdw!4Ab>5@Qq-OX7-*->f1*7;l6Z#e74wZdZ4?mqdAfCTc&v?Ip9z9+H zFj(#s|0KdJh1TvjYI@B%BtQ>ANrx+>L0Uq! zC%cMekrADGOCzT&KhniY$06V+bJR>i^=~A%met*&%1zy0FPA%h^SA`}foKVF-REB$ z)#+jE>=Jd`d|H5}^u(eq^+6%wqtyO5pGocOXgX2~8E;Vzz+(sv(?11KrMIudVDrT0 zUpwBOgTW``k1p-paswuecSmo++A?$Hgeu<9Ac)!9PsVmxkA5ownLq(Z2X7V2qkjHV^w>wv*x5Hq zu4jaA2^ruSCe`ak2t1mcEPI~B`KR{U!Lj6e(oE}N9??ueZ^Sg+$ke#9!#XKy&Y^jo zp~?@D$D_i1H*U}0GTUO6+tKjWNe>O+RG6A`QJiRAy8zl_$ zvf=)WHCWG;M}BrA`!V)&rx^$2h(%vFRq8mz1YPb@#bLW@sO~M5*tL&#b0B8|tUck= zLQ|)F_Ui#Zopi0R5Am$b@~#V&G$`lHP^(|~VGztl*lxNn2BH-=Rn`SqKie)evO$w7 zB_|4H9Yj}qFnRXQMYjybNoo9e|E8NCZ)o$Nt}3&1*4&uXcf{w=9^hiC)lq9V?sfYF z?_YerVC|Mnl?D2+3_yk?O(7OS)6ms6!xNQXSv2Y>Z~O)~#;Yv^?~ERyRs*{U4BCgS zfE(T+OU)JTHu=o&5N^diYrh^kR7?no^g{~T%#@CAd12`^*yQcz5;?e| zpvY^|+3BuA`);tJ9@lD~A6RKiz)wFMH=K(zM}5M;0@IyR9dCL6ZMQoWGHqI}*%6;J z5X4ZHs|pyv2X{XHBi*9|PG1qmGqqXat)Ue@TI4AIHzEi4_2t17P&o9Mwi7QQ56EbA za~HZ3I6XSOm&H(7j41n5P#q{t-*wM>3++q=KLBf09z75ya$-Ff;!{%0B+vcXW=FRa@IWK_Dl287pV>7>SyC zbJ+rNOA$qxGdJ`lbFERne1W<8!8r3p#T<6XD*qaR)PQP0Bpw}$#zbc#`@B_S;{y4v z+4^Gb>vc(P@lePE#0`nUr_x(Fq3{-+^$~5TG-uL$mwIkCaJa?w&p-iz(h0Rzx`^QC z$?x@#Au(KcsNDlMBWmGJZ0<~K9+Ss({;KFCiJ@2R97qdBJwQZd9L z=S%@W@kR{upLjC1Wwc@UwPFxh!YE%LSM1#Emi*wQm&8Br;*6dS@4tXxS*#wcRctmk zdm1@#-T51;wm_v;PQ=o_5c=UX4HeOPR?|YS2{o(9>sPqo{~Z&=9apM_x9nK3Dt;a; z06MK3kP%ZW(V~~lTXu4zMSBG5Rj__2Vj$}Rm~y*+*Y$xe`lsTwM52&+-eE|I{kn`B zU~!_uhPy6IkUT1lSt!(-6IkJE(iLmsV3=HWq(p+9n9&4nMCOTu-`2rv1gpeZicHlA zK&C$i&*@TTs9&<-a!u=a?AreUGZj#kbo<2~{4g=m1d*wPyZm*U9ErlIuvG2eu%%u? z)yBQd<=C&@4Sf&uWI}~rV^^}%K|gu7ZHIbVgXb%d+Ea$ijo;18O`_%s?zD)3lF&3M zyW#Y5pfWp*1wMHG<=)y@N==}wTg@yXj?3Qb*ye6VMc|t3I(VWdUpn9A5SUucf73#C z8RHkGTh9peh}peDWph8moTO~p5x%gd(EZbu0Fa|Ac08A^}r_|dprw4(zfJ3 z^jefuT-5MWJ3}OZv1&(~7e)t61I5ev)I{{`z%%}5%!!E@mYZ=L)W)-XWL}2<=J?DK z%13rNFOn95zZ=X!*d0kxB1TkC1?u|yVeBe0m|L!y$AoS$X*h82($e=Vmk>DAuA>E! za_0TnV+2n0Z^(8=1eO^OsDPVmyjkw^=#6dVe1gGMHVe#6CC-ZZqR?_10>6W$3kL2m zQ^lA_qw~Me0GgD~kY1^<@38xnayyKjvXxg9V|NARJhHZOI;9tO`fps!`qF%676ofh zq4P*e*?HZ?Pku?cBRj$L<)R=(Wuy^-GnZlyebFN_2d_Idi?H#qYLL5e4Bd7cU-33% z*5YUthT7IAX_uN8Vf1t?yt^hi-mBpIx&5SmepoR%GNGXn%y&6q`V0MC-cljSFn$IU zG3x8`jIt|vVCtWtjEan2!+_M_n9ft0sPG7~gP#P^7N|?Q$i{vPpRlv`y@Ko%eu$P7 z#F%e)3(k9sEU!!e(>I4l6?RL0TcqHctd(Z+%#Z z9AV-ep4en5KtT|xh=lPc_9d}(Ix0GG5nb$D zyq9iBSjB{8+vst)Q<-L4VG08*DxK+_@nHuF-!yrub%)%2CT@kDjsBOzl}}4ivmKKh zTd1+WR>SHk75JeDndV(Sf6Pn798NXBpPW2SWI(@a_nNeNGbqzjy*r6}d1b0~+MrN@ z##6F}Zhs=y288613qh?`ure9WPu5A)3ZzMh0JPhM^E|xP$xZ}_E#4!DWWVPCh(l1q zal?vq(}3t2gWb|f5}{ux{ZWAT)9_U%;tQ#P){_hJVo_;3aMV-mI zI7$PpLXsBpon=`)a5K zz?wd2uf;4FjLm~nxnTnNV2d+;nVWV+_Ym=Fsrs)+K|z1EGQ+FTf{R!yg}cQ&PAaZ) z=;b@d;@}S5q0WL&J~&PK;m)q(b9tw~FOmZk@xfLhAB-X8+MRTGfk>(NQ{h}-*hb+t zZ7k!gt@7(IqT(I>C?mFLp)dG#<2;y)92*l|)fu@Xrkd&ZUf8r6I}bU^U)k*&3gp?% zbqnol+6A{V{u+L^@}~I3}=y1n$1#?(Wh^ z#jBvoBK|{$Q$vvYIqW`}{u#o#)IhaK)&aK~Nee@#*}hR|lKB0uSzm_~olXh&_A6Lj z_!a+n)K&t)Aa*PHOdPMq5e_`z50}IN&-1MvL=(e}sE%P;zZ_yaMV zRaS0T+RLZF)J<4R&^T6yx6@$r(jtlj(deFKxbDzsXG1d2lP>Z|ZI2VJY!Z374?+S7 zi>2I{TA+%5C#`$~`AUF7!-&2)Ipm6PI;{<*|CyvlLeL}(XFX-mdrPIX%Y4pQ05GRZ zJf>>9iRv=d-L@vK=(0`(M|k5^B?X8JHX-(UG4-~Rn`CZbL(3T zY*-eh5Z*l{YNj03M|k0(dIR^o0! zt$Mnv`bS!D)MFm!V{$_twT8h5dU3UXe|$gj95L zSQ7Z?Ok^|&vZn-a9+W(8X|!BSf9?dU3z3MC>y)T&3Eu&BiA^JByfdu^8<`{W*=uD_ zdtem#N&Oouh{;&SsU_2{qM58wJ)iSN$coLnl96+WvwxiOeRyxW1r*?1AxpDvko;}- z1@)_p{*bJ9C)JDDNWL`t*7R@qckwPCZ6Uvap5vPiUPS3+wo4ar zv?h|Mx7u~VaQlcq*!YR6O?l8Rd<~bKqm*;7dkWD?xz^vr6r~)tQ0Z(QXx~%{qaY}g zi&~V@YqP_&?#IhTu(itrYwicg2X8xLo~Wfw;?%H@2g2g6>P*yhzvG%*IiGu``Y?Bd z(|>AeB{)R+r$P8NpO6HQU_2+AEks466^=k>MGGDs$8@dR;601n{{+ReT~niPF0oCc zr$$9l=S>);0Cp@a6n|Hro8|jT|QiqWPk@mbVCBf7&AU z-+Rq_WAzvr#N`D*-xZ$y|$)vhIt8Z$GE}<0eXG*43NPokET*KbvJ@7!; z$7V0N!AhtHVhr-2GoODaG5510JS4a*QI{oq-{#CjNn2=k>}c|91T z5=Z>-2w^l>X;{bpo{G`CDI$4wG5B|{b_J(hpqPm$=STq%V&&m5?uX9z%)gMe)s&D_ zlF6!9LYVq|kCnMVBaFopR9GlvHxdh?0tVq)%=mKSM7%z}T*SgcnORM?pMn7-guHbY z7@$1WW#QHXm7$+*KZ<=ga|mNwY#mHzDmH2tqCe%~$h_QgG zfR@DUO~u^bA6=y=QqQGJW&k*c;a5VJ$jd-Ir0EnL;m%sOidLTdih#!IxzvpGXhPcs zx%z8O*4XmcixPAKX6Lrn5{ALU*#9JhLTX%qgH(>{J=rU(dVxe5>(WQ+rTF^7<=dnm zC2aKn{9wY7K23<4EVzO#7GF%R>R!(JXC%*9cva~u$-~v;Ow@m^$APY*83O9$r3>lr z3=o4qDsfHzMWth%KCYy#IkBZRwf;03eheU_P{ zC=H)o&&IBLZh&0myG>y|PKFtPfE>f0E-V5AbZH@YJ3Zts0|@dQ^JPLk2;7CH}O$(Zw3yLrwK-6H6ysa4lDUe%cLNFg9|9YjxFdhVShPXBI{qa0EF7dt(@94 ziUp@5vyc$WYWu}$_1frtw$8TRSxdM&JXha}ym?1jHSg@>gC2+G*R4}XPjT(DI9L3& z{&^5rr{ulWS8t08S)Ykq^V|NhqD(XM((7DdV&aQT|yLpCxBNP;>*MC=&w% dmjQ)f)Bpp6;SdJNIjM<7CHc9DMcG^p%m98*ah?DG diff --git a/bbfd/docs/css/assets/fonts/Madera-Regular.svg b/bbfd/docs/css/assets/fonts/Madera-Regular.svg deleted file mode 100644 index b4ed242c..00000000 --- a/bbfd/docs/css/assets/fonts/Madera-Regular.svg +++ /dev/null @@ -1,5284 +0,0 @@ - - - - -Created by FontForge 20201107 at Thu Jan 11 12:26:25 2018 - By Unknown -Copyright (c) 2018 Monotype Imaging Inc. All rights reserved - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bbfd/docs/css/assets/fonts/Madera-Regular.ttf b/bbfd/docs/css/assets/fonts/Madera-Regular.ttf deleted file mode 100644 index c0808e8e095e1afb8be5e66c135e1884fdf684b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101784 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 diff --git a/bbfd/docs/css/assets/fonts/Madera-Regular.woff b/bbfd/docs/css/assets/fonts/Madera-Regular.woff deleted file mode 100644 index 4b828b478f867c60261395ed6dedc7baf0420223..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49024 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 diff --git a/bbfd/docs/css/assets/fonts/Madera-Regular.woff2 b/bbfd/docs/css/assets/fonts/Madera-Regular.woff2 deleted file mode 100644 index a2b257cfe3da8471dc254f99a47cfa68b033da5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31156 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 z 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